 NAM WINCHESTER DISK DRIVER
 OPT PAGE
 PAG
* WINCHESTER DISK DRIVER FOR WD1002-HD0 CONTROLLER
*
* COPYRIGHT 1984 PERIPHERAL TECHNOLOGY
*     ALL RIGHTS RESERVED
*
* LAST CHANGE 5/25/85 for the WD1002 Origional Code

* Rewritten 9/1/21 for IDE register layout + LBA mode
* Changed 9/7/21 to move boot command code here
* Modified 9/11/21 FOR 6800
* LAST CHANGE 08/5/24 - SO I CAN TELL WHICH IS LATEST VERSION

* Modernized for IDE/SD card used with PT-HDO-IDE adapter.
* PT-HDO board converts the pin outs of the WD1002-HDO port to
* IDE Pin outs.

* for purpose of this driver, the IDE device is put in LBA mode.
* This make for faster performance and a simpiler and faster driver.

* Drive arangemnet for this rewrite is for 16MB partitions
* You may format a smaller size, but the driver works in 16MB blocks
*  IDE/SD devices use 512 byte sector size and 16 bit transfer per read.
*  Because devices are cheap and the 6809 and FLEX are 8 bit
*  devices, half of the data is discarded.  Only 8 of the 16 bits
*  is read/written.  The extra complexity of hardware and the extra overhead
*  of software to block and unblock 512 byte sectors in not worth
*  the effort for the hardware changes or the loss in performance
*  to block/unblock 512 byte sectors to 256.

* A $4 32GB SD card would support over 1000 16MB partitions. So there is
* no reason to be concerned about the loss of half of the data capacity.

* Offset is the number of 16MB offsets for the partition being accessed.

* DRIVE DESCCRIPTORS - WINCHESTER

* Don't delete any of the unused space in the descriptor,  the size must
* be the same as the floppy desctiptor, which needs the extra space.

 ORG 0

DISK RMB 1 0=FLOPPY  <>0 - WINCHESTER
DRVNO RMB 1 HARDWARE DRIVE NUMBER - Must be 0 or 1
STEP RMB 1 Not used  was STEP RATE
INIT RMB 1 0=NOT INITIALIZED
SHIFT RMB 1 Not used  was  <9 NUMBER OF SHIFTS >8 DIV
HMASK RMB 1 Not used  was  HEAD MASK
OFFSET RMB 2 Partition OFFSET - number of 16MB offsets
DRVSIZ EQU *

* ADDRESS DEFINITIONS FOR FLEX LOADER

 ORG $A100 Address where SECTOR 1 LOADED
 RMB 5 
LTRKNO RMB 2 CYLINDER to load FLEX from
LSECNO RMB 1 SECTOR TO LOAD FLEX FROM
XFER RMB 2 TRANSFER ADDRESS
LDPTR RMB 2 LOAD POINTR ADDRESS
PNTR RMB 2 BUFFER NEXT READ POINTER
LBUF EQU *
LDATA EQU LBUF+4
DATEND EQU LBUF+256

PDATA1 EQU $E07E SWTBUG PRINT STRING 
SWTBUG EQU $E0E3 RETURN TO SWTBUG
STACK1 EQU $A07F START ADDRESS OF STACK 
DRTMP EQU $BE95

* FLOPPY DRIVER EQUAT

DRVPTR EQU $BE0F DESCRIPTOR POINTER 

* PORT DEFINITION

BASADR EQU $8008

DATA EQU BASADR DATA REGISTER
ERROR EQU BASADR+1 ERROR REGISTER
WPC EQU BASADR+1 WRITE PRECOMP REGISTER
SECNT EQU BASADR+2 SECTOR COUNT
SECNO EQU BASADR+3 SECTOR NUMBER
CYLLO EQU BASADR+4 CYLINDER NUMBER (LSB)
CYLHI EQU BASADR+5 CYLINDER NUMBER (MSB)
SDH EQU BASADR+6 SIZE/DRIVE/HEAD REGISTER
STATUS EQU BASADR+7 STATUS REGISTER
COMREG EQU BASADR+7 COMMAND REGISTER

* COMMAND DEFINITIONS

READCM EQU $20 READ COMMAND
WRTCMD EQU $30 WRITE COMMAND

 PAG

 ORG $E600 

* DISK JUMP TABLE

READ JMP READ1
WRITE JMP WRITE1
VERIFY JMP VER1
RESTOR JMP REST1
DRVSEL JMP DRVSL1
CDRRDY JMP CDRR1
QDRRDY JMP CDRR1
DCOLDS JMP DCOLD
DWARMS JMP RTS
IBOOT  JMP WBOOT Boot from IDE

***********************
* READ SECTOR COMMAND *
***********************
* Entry
* X - Address to place sector - 256 bytes
* A - Sector Number
* B - Track Number
* Exit
* X,A May be destroyed
* B - Error Code
* Z - 1 if no error
* Z - 0 if an error

READ1 EQU *
 JSR TSKSET SET UP TASK REGISTERS
 LDAA #READCM GET READ COMMAND
 STAA COMREG ISSUE COMMAND TO WD1002-HD0
READ2 LDAA STATUS READ STATUS
 ASLA WAIT FOR BUSY TO CLEAR
 BCS READ2

 LDAB #128 LOOP COUNTER
READ3 LDA A DATA GET DATA 
 STA A 0,X STORE IT 
 INX  INCREMENT STORE POINTER
 LDAA DATA GET DATA
 STAA 0,X STORE IT
 INX  INCREMENT STORE POINTER
 DECB  DECREMENT LOOP COUNTER
 BNE READ3 CONTINUE LOOPING UNTIL 256 BYTES XFERED
 LDAA STATUS     GET STATUS 
 BITA #1  ERROR BIT
 BEQ READ4  BRANCH IF NO ERROR
 LDAB #$10 SET ERROR CODE
 SEC
 RTS
READ4 CLRB NO ERROR CODE
 RTS

*****************
* WRITE COMMAND *
*****************
*
* X - Address of 256 bytes to be written
* A - Track Number
* B - Sector Number
* EXIT
* X,A may be destroyed
* B - Error Code - 0=None
* Z - Z=1 if no error
* Z - Z=0 if error

WRITE1 EQU *
 JSR TSKSET SET UP TASK REGISTERS
 LDAA #WRTCMD GET WRITE COMMAND
 STAA COMREG ISSUE TO WD1002-HDO
WRITE6 LDAA STATUS READ STATUS
 ASLA SHIFT BUSY BIT TO CARRY
 BCS WRITE6 LOOP UNTIL NOT BUSY

 LDAB #128 LOOP COUNTER
WRITE2 LDAA 0,X GET DATA TO STORE
 STAA DATA STORE IT 
 INX  INCREMENT NEXT DATA POINTER
 LDAA 0,X GET DATA
 STAA DATA STORE IT
 INX  INCREMENT NEXT DATA POINTER
 DECB  DECREMENT LOOP COUNTER
 BNE WRITE2 CONTINUE LOOPING UNTIL 256 BYTES XFERED
WRITE3 LDAA STATUS     GET STATUS 
 BITA #$80  BUSY?
 BNE WRITE3  BRANCH WHILE BUSY
 BITA #1 ERROR BIT
 BNE WRITE4 BRANCH ERROR
 CLRB  CLEAR ERROR FLAG
 RTS
WRITE4 LDAB ERROR GET ERROR FROM WD1002/IDE
 SEC
 RTS

**********************
* VERIFY DISK DRIVER *
**********************
*
* The sector just written is to be verified.
* This routine only called immediately after a write
* 
* Entry
* No parameters are given
* Exit
* X,A may be destroyed
* B - Error code - 0=none

* While the origonal code worked on the WD1002-HDO controller
* the code does not work with modern IDE controllers.
* If you start a read on a IDE controller you must transfer
* the data from the controller or the command hangs.
* On the WD1002 controller you did not need to transfer the
* data from the buffer and could just abort.

* This routine will need to be rewritten for it to work.

VER1 CLRB --------------------------- EXIT -  ROUTINE NOT VIABLE
 RTS

* LDA #READCM
* STA COMREG
*VER2 LDA STATUS
* BITA #$80
* BNE VER2
* BITA #1
* BNE VER3
* CLRB
* RTS
*VER3 LDB ERROR
* SEC
RTS RTS

***********************
* TASK SET-UP ROUTINE *
***********************


* INPUT D=LOGICAL SECTOR NUMBER
*    A = TRACK  B=SECTOR
* 
*
* Driver currently supports only 256 partitions
*
* OUTPUT IDE registers set
*

TSKSET STAB SECNO Set LSB of LSN
       STAA CYLLO Set MSB of LSN
 STX DRTMP SAVE X
       LDX DRVPTR point to descriptor
       LDAA OFFSET+1,X get parttion number
       STAA CYLHI
       LDAA DRVNO,X Get drive Number
 LDX DRTMP RESTORE X REGISTER
       ASLA Put in corrent bit position
       ASLA
       ASLA
       ASLA
       ORAA #$E0 Drive number + LBA Mode
       STAA SDH Select Drive and LBA
  LDAA #1 SET FOR ONE SECTOR READ/WRITE
  STAA SECNT SET IDE REGISTER
       RTS

 
*******************
* RESTORE COMMAND *
*******************
*
* Drive in the FCB address (3,X contains drive number) DRIVE should be selected
* before the RESTORE is performed.
*
* Entry
* X - FCB address - 3,X contains drive number
* Exit
* X,A - may be destroyed
* B - Error code - 0=no error

* While there is nothing to do for a modern drive, FLEX
* expects DRIVE SELECT to be called by this routine.  It is therefore
* necessary to set the DRVPTR pointer TO POINT AT THE 
* PROPER DISK DESCRIPTOR with this routine.

REST1 LDAA 3,X GET DRIVE NUMBER
 LDAB #DRVSIZ GET DESCRIPTOR SIZE

 LDX #$BE11 BEGINNING ADDRESS OF DRIVE DESCRIPTORS
 TSTA   TEST FOR DIRVE 0
 BEQ REST5 DRIVE 0 - SAVE POINTER - NOTHING TO DO
 PSHB  SAVE DESCRIPTOR SIZE
REST2 INX INCREMENT UNTIL POINTING TO NEXT DESCRIPTOR
 DEC B  "
 BNE REST2 CONTINUE LOOPING UNTIL NEXT POINTER ADDRESS
 PULB  RESTORE SIZE OF DESCRIPTOR
 PSHB  TO PRESERVE STACK POINTER
 DECA  DECREMENT NUMBER OF DRIVE
 BNE REST2 CONTINUE INCREMENTING DESCRIPTOR POINTER UNTIL COMPLETE

REST4 PULB CLEAN UP STACK USAGE
REST5 STX DRVPTR      SAVE DESCRIPTOR POINTER

 CLRB   No error CODE
 RTS  


********************
* DRIVE READY TEST *
********************
*
* Drive number found in the FCB  should be checked for ready
*
* Entry
* X - FCB address - 3,X contains drive number
* Exit
* X,A - may be destroyed
* B - Error code - 0=no error
* -------------------------------------------------------------- THIS ROUTINE SHOULD
*                                                      BE CHANGED TO REPORT NOT READY FOR
*                                               NON EXISTANT DIRVE  
CDRR1 LDAA STATUS
 BITA #$40    Drive ready bit
 BEQ CDRR2    branch for not ready
 CLRB         clear error flag
 RTS
CDRR2 LDAB #$80 set not ready error
 SEC
 RTS

********************
* COLD START - INIT*
********************
*
* Do any driver initialization here when the system is first booted.
*
* Entry
* No parameters are given
* Exit
* A,B,X,Y,U may be destroyed
* No exit code for this routine. Simply issue RTS

DCOLD LDAA STATUS Get status
 BITA #$80 Test Busy bit
 BNE DCOLD loop until ready

* This would be a good place to insert time out code
* and print a message if no drive plugged in

 RTS

************************
* DRIVE SELECT ROUTINE *
************************
*
* Drive specified is selected
*
* Entry
* X - FCB address - (3,X contains drive number)
* Exit
* X,A may be destroyed
* B - $0F error code for non-existant drive
* Z - 1=error  0=no error
* C - 0=error  1=error
*
* For this driver, it means the DRVPTR must be set so
* READ/WRITE works on the correct drive.
*
* The drive is selected during the Task setup routine
* There is nothing to do to the drive here
 
* USE REST1 ROUTINE SINCE IT WOULD BE THE SAME

DRVSL1 BRA REST1

*----------------------------------------------------------
* Boot from IDE
*
* This boot no longer uses a Bootstrap loader in sector 1.
* The only information on sector 1 is the link to the OS (FLEX)

***********************
* 'W' BOOT WINCHESTER *
***********************

WBOOT LDS #STACK1
 LDX #DESCRIP
 STX DRVPTR

 CLRA BOOT TRK0
 LDAB #1 BOOT SECTOR

 LDX #$A100 LOAD ADDRESS
 JSR READ
 TSTB
 BEQ WBOOT3 NO ERROR - CHECK FOR LINK PRESENT
 LDX #MSGWN2
 JSR PDATA1
 JMP SWTBUG

* CHECK TO SEE IF DISK IS LINKED

WBOOT3

* IF TRACK = 0 , THE DRIVE IS NOT LINKED.

 TST LTRKNO TEST TRACK NUMBER 
 BNE LDFLEX LOAD FLEX
 LDX #MSGWN3 NOT LINKED MESSAGE
 JSR PDATA1
 JMP SWTBUG JUMP TO SWTBUG

MSGWN1 FCB $D,$A,$A
 FCC /WAITING FOR DISK TO SPIN UP/
 FCB 4

MSGWN2 FCB $D,$A
 FCC /ERROR READING BOOT SECTOR/
 FCB $D,$A
 FCB 4

MSGWN3 FCB $D,$A
 FCC /NOT LINKED/
 FCB $D,$A
 FCB 4


*---------------------------------------------------------------
* FLEX LOADER
*
* Load FLEX from the LINK in provided in sector 1


DESCRIP EQU *

* DRIVE DESCRIPTOR LOADED HERE

DESWIN FCB 1 WINCHESTER
 FCB 0 HARDWARE DRIVE NUMBER
 FCB 0 
 FCB 0
 FCB 0
 FCB 0 
 FDB 0 TRACK OFFSET

* INITIALIZE TEMP STORAGE

LDFLEX EQU *

 LDX #0
 STX XFER
 STX LDPTR
 STX PNTR
 BRA START1

REDSEC LDA A LTRKNO GET STARTING TRACK
       LDA B LTRKNO+1 GET STARTING SECTOR
RESEC1 LDX #LBUF
 JSR READ
 BCS FAIL0 YES : RESTART
 LDX #LDATA POINT X AT BEGINNING OF DATA
 STX PNTR SAVE POINTER
 RTS
FAIL0 JMP FAIL

*----------------------------------------------------
* GET DATA BYTE AND ADVANCE POINTER
*  ON END OF BUFFER - READ NEXT SECTOR

READAT LDX PNTR GET POINTER
 CPX #DATEND END OF DATA?
 BEQ REDAT1 YES: READ NEXT SECTOR
 LDAA 0,X NO: GET NEXT BYTE
 INX
 STX PNTR SAVE POINTER
 RTS

* READ NEXT SECTOR

REDAT1 LDX #LBUF POINT TO BEGINNING OF BUFFER
 LDA A 0,X GET ADDRESS OF NEXT SECTOR
 LDA B 1,X "
 BSR RESEC1 READ NEXT SECTOR
 BRA READAT CONTINUE WITH GET NEXT DATA BYTE

*--------------------------------------------------------------------
* START OF FLEX LOADER

START1 LDX #DESWIN
 STX DRVPTR
 BSR REDSEC READ FIRST SECTOR
LOAD BSR READAT GET DATA
 CMPA #$02 TEST FOR LOAD RECORD
 BEQ BINREC
 TST LBUF
 BNE LOAD
 TST LBUF+1
 BNE LOAD

* PROCESS TRANSFER RECORD

 CMPA #$16 TEST FOR TRANSFER RECORD
 BNE LOAD NO - CONTINUE PROCESSING FILE
 BSR READAT GET MSB OF XFER ADDRESS
 STA A XFER
 BSR READAT GET LSB OF XFER ADDRESS
 STA A XFER+1
 LDX XFER GET TRANSFER ADDRESS
 JMP 0,X JUMP TO IT

* BINARY FILE LOADER

BINREC BSR READAT GET MSB LOAD ADDRESS
 PSHA 
 BSR READAT GET LSB LOAD ADDRESS
 PULB 
 STAA LDPTR+1
 STAB LDPTR
 BSR READAT GET NUMBER OF BYTES TO LOAD
 TAB B=COUNTER OF BYTES TO LOAD
 BEQ LOAD

BINRC1 PSHB 
 BSR READAT
 PULB 
 LDX LDPTR
 STAA $00,X
 INX 
 STX LDPTR
 DECB DECREMENT COUNTER
 BNE BINRC1
 BRA LOAD


FAIL LDX #FAILMSG
 JSR PDATA1
 JMP $E0E3 RESTART PTMON

FAILMSG FCC /LOAD FAILED/
 FCB 4



 END
