	NOLIST
;	This file is part of picide, ATA(PI) interface to PIC18 family MCUs.
;	Copyright (C) 2004-5 Toby Thain, toby@telegraphics.com.au

;	This program is free software; you can redistribute it and/or modify
;	it under the terms of the GNU General Public License as published by  
;	the Free Software Foundation; either version 2 of the License, or
;	(at your option) any later version.

;	This program is distributed in the hope that it will be useful,
;	but WITHOUT ANY WARRANTY; without even the implied warranty of
;	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;	GNU General Public License for more details.

;	You should have received a copy of the GNU General Public License  
;	along with this program; if not, write to the Free Software
;	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
	LIST

	TITLE picide
	SUBTITLE "Console monitor"

;; Version history
;; 16-Oct-2004: 0.1 - started by Toby
;; 23-Feb-2005: 1.0 - public release under GPL

; contents of this module:
	global monitor	; enter monitor loop (prompt, get command, execute)
	global dumpid

#include "defs.inc"
#include "idecmd.inc"

	extern init_rs232,putch,getch
	extern puthex,hexdigit,udiv32_16,divd,divs,dumpsec,putdec16,dec16,putdec

	extern init_ide,ide_identify,ide_lbacmd,ide_rdata,ide_wdata
	extern ide_atapiiddev
	extern idecmd,seccnt,feat,lba0,lba8,lba16,lba24

	extern stop,checkerr,devtype
	extern atapi_checkerr,atapi_readcapacity
	extern tick1khz

;---------------------------------------------------------
; planned monitor functions 
; - enable/disable debugging messages
; - enable/disable command logging
; - drive identify, test, format, copy (?)
; - defect listing?
; - read/write tests ?
; - show/create partition table
; - change partition type
; - upload partition image (Zmodem? Kermit? uucode?)
; - upload partition MBR (bootstrap sector)
; - logical unit <-> partition mapping
; - configure MSCP parameters
; - stats reporting (transfer sizes, rate)

; host diagnostics?
; - memory test/dump
; - bootstrap

#ifdef GPASM
#define UC	; workaround bug (gpasm-0.12.4 beta)
#else
#define UC(c) ((c) & ~32)	; uppercased version of literal ASCII
#endif

;;; DATA

	udata_acs
dbgflag	res 1
logflag	res 1
key	res 1
cnt	res 1
devsel	res 1	; selected device 1/0
devt	res 1	; type of sel device

	code

monitor:
	; select device 0 initially
	movlw IDE_DRVHEAD_LBA|IDE_DEVICE0
	movwf devsel
	movf devtype+0,w
	movwf devt
	
	rcall dohelp	; greet with help message
	; enter main command loop
getcommand:
	_crlf		; put prompt
	_putchar '>'
	rcall getch	; get keystroke
	andlw ~32	; uppercase it
	movwf key
	
	movlw UC('I')
	cpfseq key
	  bra notI
	; got "I": identify device
	rcall doidentify
	bra getcommand
notI:	movlw UC('0')
	cpfseq key
	  bra not0
	; got "0": select device 0
	movf devtype+0,w
	movwf devt
	movlw IDE_DRVHEAD_LBA|IDE_DEVICE0
	movwf devsel
	bra seldone
not0:	movlw UC('1')
	cpfseq key
	  bra not1
	; got "1": select device 1
	movf devtype+1,w
	movwf devt
	movlw IDE_DRVHEAD_LBA|IDE_DEVICE1
	movwf devsel
seldone:_puts "Select device \0"
	movf key,w
	rcall hexdigit
	_crlf
	bra getcommand
not1:	movlw UC('?')
	cpfseq key
	  bra getcommand	; didn't recognise it; get another one
	; got "?": show help
	rcall dohelp
	bra getcommand

dohelp:	_puts "Commands: I)dentify 0)1)Select device ?)Help\r\n\0"
	return

doidentify:
	movf devsel,w
	movwf lba24

	movf devt,w
	xorlw DEV_ATA
	bz isata
	xorlw DEV_ATAPI ^ DEV_ATA
	bz isatapi
	; unknown device type??
	_puts "No device\r\n\0"
	return
isata:	_puts "Identify (ATA):\r\n\0"
	call ide_identify
	movlw 1
	movwf seccnt
	movlw 0	; = 256 words
	call ide_rdata
	call checkerr
	btfss STATUS,Z
	goto iddone
; ATA specific stuff
	rcall printsectors
	bra id2
isatapi:
	_puts "\nATAPI Read Capacity...\r\n\0"
	call atapi_readcapacity
	call atapi_checkerr
	_puts "Identify (ATAPI):\r\n\0"
	call ide_atapiiddev
	movlw 1
	movwf seccnt
	movlw 0	; = 256 words
	call ide_rdata
	call checkerr
	bnz iddone
; ATAPI specific stuff
	BANKSEL secbuf
	_puts "Device type: \0"
	movlw 0x1f
	andwf secbuf+0*2+1,f,1
	movf secbuf+0*2+1,w
	call putdec
	movlw 5
	cpfseq secbuf+0*2+1,1
	bra id2
	_puts " (CD-ROM)\0"
	bra id2
;devtypes: dw "Direct Access\000Seq Access\000Printer\000Proc\000Write-Once\000CD-ROM\000Scanner\000Optical Memory\000Medium Changer\000Comms\000ACS IT8\000Array Ctlr\000Enclosure Serv\000Reduced Blk Cmd\000Optical Card R/W\000"
;devtunk:_puts "??\r\n\0"

id2:	
; generic stuff
	_crlf
	BANKSEL secbuf

dumpid:
	movlw 9
	call dumpsec
	; print model number
	_puts "Model: \0"
	clrf 47*2+1,1
	_putstrswapd (secbuf+27*2)	; note: from data memory, with byte pairs swapped
	_crlf

	retlw NO_ERR
iddone:
	return

  IF 0
	_puts "S/N: \0"
	clrf 20*2+1,1
	_putstrswapd (secbuf+10*2)	; note: from data memory, with byte pairs swapped
	_crlf
	_puts "Firmware rev: \0"
	clrf 27*2+1,1
	_putstrswapd (secbuf+23*2)	; note: from data memory, with byte pairs swapped
	_crlf
	
	movlw b'1111'
	andwf 82*2,1
	bz nocmdsets
	_puts "Command sets:\r\n\0"
	rrcf 82*2,f,1
	bnc notpm
	_puts "  Power management\r\n\0"
notpm:	rrcf 82*2,f,1
	bnc notrem
	_puts "  Removable\r\n\0"
notrem:	rrcf 82*2,f,1
	bnc notsec
	_puts "  Security\r\n\0"
notsec:	rrcf 82*2,f,1
	bnc nocmdsets
	_puts "  SMART\r\n\0"

  ENDIF

printsectors:
	BANKSEL secbuf
	_puts "Sectors: \0"
	movf 58*2+1,w,1
	call puthex
	movf 58*2,w,1
	call puthex
	movf 57*2+1,w,1
	call puthex
	movf 57*2,w,1
	call puthex
	_putchar '='

	; check if should be printing GB
	; sectors >> 11 = MB
	; so, if: sectors >> 11 >= 1<<16
	; = if:  sectors >> 24 (msbyte) >= 1<<3
	movlw 8
	cpfslt 58*2+1,1
	bra printgb

	; msbyte of sector count < 8,
	; so disk is < 65536MB
printmb:
	; following doesn't work if disk is >65535 MB !!
	; divide sector count to get MB (already div 256)
	movf 58*2,w,1
	movwf dec16+1
	movf 57*2+1,w,1
	movwf dec16

	addlw 0 ; clear carry
	rrcf 58*2+1,1
	rrcf dec16+1
	rrcf dec16
	addlw 0 ; clear carry
	rrcf 58*2+1,1
	rrcf dec16+1
	rrcf dec16
	addlw 0 ; clear carry
	rrcf 58*2+1,1
	rrcf dec16+1
	rrcf dec16
	call putdec16
	_putchar 'M'
	bra printtail
printgb:
	; sectors >> 21 = GB
	; by taking top two bytes of sector count,
	; we have already shifted sixteen places right
	movf 58*2+1,w,1
	movwf dec16+1
	movf 58*2,w,1
	movwf dec16

	; so shift another 5
	movlw 5
	movwf cnt
shft:	addlw 0 ; clear carry
	rrcf dec16+1
	rrcf dec16
	decfsz cnt
	bra shft
	call putdec16
	_putchar 'G'	
printtail:
	_putchar 'B'
	_crlf

	; output C,H,S default translation for ATA units
	_puts "Default trans: c=\0"
	movf 1*2+1,w,1	; word 1: # of cyls in default translation mode
	movwf dec16+1
	movf 1*2,w,1
	movwf dec16
	call putdec16
	_putchar ' '
	_putchar 'h'
	_putchar '='
	movf 3*2+1,w,1	; word 3: # of logical heads per logical cyl
	movwf dec16+1
	movf 3*2,w,1
	movwf dec16
	call putdec16
	_putchar ' '
	_putchar 's'
	_putchar '='
	movf 6*2+1,w,1	; word 6: # of logical sectors per logical track
	movwf dec16+1
	movf 6*2,w,1
	movwf dec16
	call putdec16
	_crlf
	return

;---------------------------------------------------------
	end
