Mercurial > hg > Members > kono > nitros9-code
changeset 2590:17d43fd29ee2
Integration of SuperDriver
author | boisy |
---|---|
date | Thu, 22 Dec 2011 18:23:47 +0000 |
parents | e134044fd755 |
children | f026e5eecfb0 |
files | defs/ide.d defs/rbsuper.d defs/scsi.d level1/cmds/scsiquery.asm level1/coco/modules/makefile level1/modules/boot_ide.asm level1/modules/boot_scsi.asm level1/modules/llide.asm level1/modules/llscsi.asm level1/modules/rbdesc.asm level1/modules/rbsuper.asm level1/modules/superdesc.asm level2/coco3/modules/makefile |
diffstat | 13 files changed, 4331 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/defs/ide.d Thu Dec 22 18:23:47 2011 +0000 @@ -0,0 +1,55 @@ +******************************************************************** +* ide.d - IDE definitions +* +* $Id$ +* +* (C) 2004 Boisy G. Pitre - Licensed to Cloud-9 +* +* Edt/Rev YYYY/MM/DD Modified by +* Comment +* ------------------------------------------------------------------ +* 2005/12/11 Boisy G. Pitre +* Moved IDE base addresses and I/O offsets to here. + +* +* ATAPI Commands +* +A$READ2 EQU $A8 +A$WRITE2 EQU $AA +A$READ EQU $28 +A$WRITE EQU $2A +A$STOP EQU $1B + +* +* ATA Commands +* +S$READ EQU $20 +S$WRITE EQU $30 + +* +* IDE Registers +* +DataReg EQU 0 Data (1st 8 bits, non-latched) +ErrorReg EQU 1 Error # when read +Features EQU 1 Features when write +SectCnt EQU 2 Sector count +SectNum EQU 3 Sector # +CylLow EQU 4 Low byte of cylinder +CylHigh EQU 5 High byte of cylinder +DevHead EQU 6 Device/Head +Status EQU 7 Status when read +Command EQU 7 Command when write +Latch EQU 8 Latch (2nd 8 bits of 16 bit word) + +BusyBit EQU %10000000 BUSY=1 +DrdyBit EQU %01000000 drive ready=1 +DscBit EQU %00010000 seek finished=1 +DrqBit EQU %00001000 data requested=1 +ErrBit EQU %00000001 error_reg has it +RdyTrk EQU %01010000 ready & over track +RdyDrq EQU %01011000 ready w/ data + +**** IDE Interface Definitions + IFNE IDE +SDAddr SET $FF50 + ENDC
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/defs/rbsuper.d Thu Dec 22 18:23:47 2011 +0000 @@ -0,0 +1,79 @@ +******************************************************************** +* rbsuper.d - rbsuper definitions +* +* $Id$ +* +* (C) 2004 Boisy G. Pitre - Licensed to Cloud-9 +* +* These definitions make up the static storage environment for the +* rbsuper driver. Low level drivers share these variables with +* rbsuper, and also have an area reserved exclusively for their use. +* +* Edt/Rev YYYY/MM/DD Modified by +* Comment +* ------------------------------------------------------------------ +* 2004/04/10 Boisy G. Pitre +* Created. +* +* 2005/11/27 Boisy G. Pitre +* Moved SCSI base addresses and I/O offsets to here. +* +* 2005/12/13 Boisy G. Pitre +* Employed a "trick" whereby driver's U is pointed UOFFSET bytes +* into the static storage for faster, smaller code generation. +* +* 2005/12/13 Boisy G. Pitre +* Rearranged order of driver statics for smaller code size + +* Interface Address +SDAddr SET $FF00 +SDMPI SET $FF + +* +* IT.DNS Definitions for all Low Level Drivers +* +DNS.HDB EQU %00001000 + +* +* IT.DNS Definitions for Low Level SCSI Driver +* +DNS.TURBO EQU %00010000 + +maxcache SET 2048 +DrvCount EQU 8 +llreserve EQU 64 + +UOFFSET EQU DRVBEG+(DRVMEM*DrvCount) + + ORG 0 +V.LLSema RMB 1 low-level semaphore variable +V.LastDrv RMB 1 last drive to access cache +V.PhysSect RMB 3 physical (HW) sector +V.LogSect RMB 3 logical (256 byte) sector +V.SectSize RMB 1 sector size +V.SectCnt RMB 1 number of hw sectors to read from interface +V.Log2Phys RMB 1 number of logical (256) byte sectors to 1 physical sector +V.CchAddr RMB 2 address of cache in system memory +V.CchSize RMB 2 size of cache in bytes +V.CchPSpot RMB 2 pointer to target physical sector in cache +V.CchLSpot RMB 2 pointer to target logical sector in cache +V.CchDirty RMB 1 cache dirty flag (0 = cache is stable, !0 = cache is dirty) +V.CchBase RMB 3 logical sector at start of cache +V.HDBDrive RMB 1 IT.STP (used as HDB-DOS drive number if HDB-DOS partition) +V.HDBPart RMB 1 HDB-DOS partition flag (0 = not HDB-DOS partition, !0 = is) +V.SSCache RMB DrvCount sector size cache table for each drive +V.LLAddr RMB 2 low level module address +V.LLInit RMB 2 low level init entry point +V.LLRead RMB 2 low level read entry point +V.LLWrite RMB 2 low level write entry point +V.LLGtSt RMB 2 low level getstat entry point +V.LLStSt RMB 2 low level setstat entry point +V.LLTerm RMB 2 low level term entry point +* Low Level Driver Memory starts here +V.LLMem EQU . start of low level driver memory + RMB llreserve reserved area... low level driver uses this as it wants +V.LLMemSz EQU .-V.LLMem +* Note: we trick rbsuper to so that it thinks its static storage starts at +* zero when it really starts beyond DRVBEG+(DRVMEM*DrvCount). + RMB UOFFSET +V.RBSuper EQU . end of RBSuper's (and ll driver's) memory requirements
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/defs/scsi.d Thu Dec 22 18:23:47 2011 +0000 @@ -0,0 +1,99 @@ +******************************************************************** +* scsi.d - SCSI definitions +* +* $Id$ +* +* (C) 2004 Boisy G. Pitre - Licensed to Cloud-9 +* +* Edt/Rev YYYY/MM/DD Modified by +* Comment +* ------------------------------------------------------------------ +* 2005/12/11 Boisy G. Pitre +* Moved SCSI base addresses and I/O offsets to here. + + +* +* SCSI Packet Command Bytes +* +S$REZERO EQU $01 +S$REQSEN EQU $03 +S$FORMAT EQU $04 +S$READ EQU $08 +S$WRITE EQU $0A +S$SEEK EQU $0B +S$MODSEL EQU $15 +S$UNIT EQU $1B +S$RCAP EQU $25 +S$READEX EQU $28 +S$WRITEX EQU $2A + +* +* SCSI Status Codes +* +X$ERROR EQU $02 +X$BUSY EQU $08 + +**** Cloud-9 TC^3 Controller Definitions + IFNE TC3+SB +SCSIDATA EQU 0 +SCSISTAT EQU 1 +SCSISEL EQU 1 +SCSIRST EQU 1 INVALID, but not used + +REQ EQU $01 +BUSY EQU $02 +MSG EQU $04 +CMD EQU $08 +INOUT EQU $10 + + IFNE SB +SDAddr SET $FF1E + ELSE +SDAddr SET $FF74 + ENDC + + ENDC + +**** Ken-Ton/LR-Tech Controller Definitions + IFNE KTLR +SCSIDATA EQU 0 +SCSISTAT EQU 1 +SCSISEL EQU 2 +SCSIRST EQU 3 + +REQ EQU $01 +BUSY EQU $02 +MSG EQU $04 +CMD EQU $08 +INOUT EQU $10 +ACK EQU $20 +SEL EQU $40 +RST EQU $80 + +SDAddr SET $FF74 + ENDC + +**** Disto 4-N-1/HD-II Controller Definitions + IFNE D4N1+HDII +SDMPI SET $02 + +* Disto SCSI Controller Definitions +SCSIDATA EQU 0 +SCSISTAT EQU -2 +SCSISEL EQU -1 +SCSIRST EQU -2 + +SEL EQU $00 +BUSY EQU $01 +ACK EQU $02 +MSG EQU $04 +INOUT EQU $20 +CMD EQU $40 +REQ EQU $80 + + IFNE D4N1 +SDAddr SET $FF5B + ELSE +SDAddr SET $FF53 + ENDC + ENDC
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/level1/cmds/scsiquery.asm Thu Dec 22 18:23:47 2011 +0000 @@ -0,0 +1,269 @@ +******************************************************************** +* scsiquery - Get info on SCSI device through SS.DCmd call +* +* $Id$ +* +* Edt/Rev YYYY/MM/DD Modified by +* Comment +* ------------------------------------------------------------------ +* 1 2008/01/21 Boisy G. Pitre +* Created while on the FPSO Kikeh in the South China Sea. + + nam scsiquery + ttl Get info on SCSI device through the SS.DCmd call + + ifp1 + use defsfile + use scfdefs + endc + +tylg set Prgrm+Objct +atrv set ReEnt+rev +rev set $00 +edition set 1 + + mod eom,name,tylg,atrv,start,size + + org 0 +code rmb 1 +lsn rmb 3 +left rmb 2 +path rmb 1 +numbuf rmb 16 +txbuff rmb 2048 to accomodate CD-ROM sector sizes + rmb 200 +size equ . + +StartM fcc /SCSI Inquiry Utility/ +cr fcb C$CR +VID fcc /Vendor ID : / +VIDL equ *-VID +PID fcc /Product ID : / +PIDL equ *-PID +RLV fcc /Revision : / +RLVL equ *-RLV +LBA fcc /Blocks : / +LBAL equ *-LBA +BSZ fcc /Block Size : / +BSZL equ *-BSZ + +InquiryUnit fcb $12,$00,$00,$00,96,$00 +ReadCapacity fcb $25,$00,$00,$00,$00,$00,$00,$00,$00,$00 + +name fcs /scsiquery/ + fcb edition + +start + leay txbuff,u + ldd #$2060 +l@ sta ,y+ + decb + bne l@ + leay txbuff,u + +l@ lda ,x+ + cmpa #C$CR + beq ok@ + cmpa #C$SPAC + beq ok@ + sta ,y+ + bra l@ +ok@ ldd #'@*256+C$CR + std ,y + leax txbuff,u + + lda #READ. + os9 I$Open + lbcs exit + sta path,u + + leax StartM,pcr + lda #1 + ldy #100 + os9 I$WritLn + +* Do INQUIRY + leax txbuff,u + leay InquiryUnit,pcr + lda path,u + ldb #SS.DCmd + os9 I$SetStt + lbcs exit + +* Show Vendor ID + leax VID,pcr + ldy #VIDL + lda #1 + os9 I$WritLn + + leax txbuff+8,u + ldy #15-8+1 + lda #1 + os9 I$Write + leax cr,pcr + ldy #1 + os9 I$WritLn + +* Show Product ID + leax PID,pcr + ldy #PIDL + lda #1 + os9 I$WritLn + + leax txbuff+16,u + ldy #31-16+1 + lda #1 + os9 I$Write + leax cr,pcr + ldy #1 + os9 I$WritLn + +* Show Revision Level + leax RLV,pcr + ldy #RLVL + lda #1 + os9 I$WritLn + + leax txbuff+32,u + ldy #35-32+1 + lda #1 + os9 I$Write + leax cr,pcr + ldy #1 + os9 I$WritLn + +* Do READ CAPACITY + leax txbuff,u + leay ReadCapacity,pcr + lda path,u + ldb #SS.DCmd + os9 I$SetStt + bcs exit + +* Show Number of Blocks + leax LBA,pcr + ldy #LBAL + lda #1 + os9 I$WritLn + + leax txbuff,u + leay numbuf,u + bsr itoa + lda #1 + os9 I$Write + + leax cr,pcr + ldy #1 + os9 I$WritLn + +* Show Block Size + leax BSZ,pcr + ldy #BSZL + lda #1 + os9 I$WritLn + + leax txbuff+4,u + leay numbuf,u + bsr itoa + lda #1 + os9 I$Write + + leax cr,pcr + ldy #1 + os9 I$WritLn + +exitok clrb +exit os9 F$Exit + +* Entry: +* X = address of 32 bit value +* Y = address of buffer to hold number +* Exit: +* X = address of buffer holding number +* Y = length of number string in bytes +itoa pshs u,y + tfr y,u + ldb #10 max number of numbers (10^9) + pshs b save count on stack + leay Base,pcr point to base of numbers +s@ lda #$30 put #'0 + sta ,u at U +s1@ bsr Sub32 ,X=,X-,Y + inc ,u + bcc s1@ if X>0, continue + bsr Add32 add back in + dec ,u+ + dec ,s decrement counter + beq done@ + lda ,s + cmpa #$09 + beq comma@ + cmpa #$06 + beq comma@ + cmpa #$03 + bne s2@ +comma@ ldb #', + stb ,u+ +s2@ leay 4,y point to next + bra s@ +done@ leas 1,s +* 1,234,567,890 + ldb #14 length of string with commas + 1 + ldx ,s++ get pointer to buffer +a@ decb + beq ex@ + lda ,x+ get byte + cmpa #'0 + beq a@ + cmpa #', + beq a@ + clra + tfr d,y transfer count into Y +v@ leax -1,x + puls u,pc +ex@ ldy #0001 + bra v@ + +* Entry: +* X = address of 32 bit minuend +* Y = address of 32 bit subtrahend +* Exit: +* X = address of 32 bit difference +Sub32 ldd 2,x + subd 2,y + std 2,x + ldd ,x + sbcb 1,y + sbca ,y + std ,x + rts + + +* Entry: +* X = address of 32 bit number +* Y = address of 32 bit number +* Exit: +* X = address of 32 bit sum +Add32 ldd 2,x + addd 2,y + std 2,x + ldd ,x + adcb 1,y + adca ,y + std ,x + rts + +Base fcb $3B,$9A,$CA,$00 1,000,000,000 + fcb $05,$F5,$E1,$00 100,000,000 + fcb $00,$98,$96,$80 10,000,000 + fcb $00,$0f,$42,$40 1,000,000 + fcb $00,$01,$86,$a0 100,000 + fcb $00,$00,$27,$10 10,000 + fcb $00,$00,$03,$e8 1,000 + fcb $00,$00,$00,$64 100 + fcb $00,$00,$00,$0a 10 + fcb $00,$00,$00,$01 1 + + emod +eom equ * + end
--- a/level1/coco/modules/makefile Tue Oct 04 15:11:45 2011 +0000 +++ b/level1/coco/modules/makefile Thu Dec 22 18:23:47 2011 +0000 @@ -15,12 +15,15 @@ CLOCKSOFT = -aRTCSoft=1 CLOCKMESSEMU = -aRTCMessEmu=1 CLOCKJVEMU = -aRTCJVEmu=1 +TC3FLAGS = $(AFLAGS) -aTC3=1 $(FLAGS) +IDEFLAGS = $(AFLAGS) -aIDE=1 $(FLAGS) DEPENDS = ./makefile TPB = $(3RDPARTY)/booters BOOTERS = boot_1773_6ms boot_1773_30ms \ - boot_burke boot_rampak boot_wd1002 boot_dw3 boot_dw3_coco1 + boot_burke boot_rampak boot_wd1002 boot_dw3 boot_dw3_coco1 \ + boot_tc3 boot_ide BOOTTRACK = rel $(BOOTERS) KERNEL = krn krnp2 wbug SYSMODS = ioman init sysgo_dd sysgo_h0 @@ -35,7 +38,11 @@ ddd0_35s.dd d0_35s.dd d1_35s.dd d2_35s.dd d3_35s.dd \ ddd0_40d.dd d0_40d.dd d1_40d.dd d2_40d.dd \ ddd0_80d.dd d0_80d.dd d1_80d.dd d2_80d.dd \ - ddx0.dd x0.dd x1.dd x2.dd x3.dd + ddx0.dd x0.dd x1.dd x2.dd x3.dd \ + rbsuper.dr lltc3.dr llide.dr \ + ddi0_ide.dd i0_ide.dd i1_ide.dd ih_ide.dd \ + dds0_tc3.dd s0_tc3.dd s1_tc3.dd s2_tc3.dd s3_tc3.dd s4_tc3.dd \ + s5_tc3.dd s6_tc3.dd sh_tc3.dd SCF = scf.mn \ sc6551.dr vrn.dr scbbp.dr scbbt.dr scdwp.dr sspak.dr vtio.dr \ @@ -58,7 +65,19 @@ all: $(ALLOBJS) +# Kernel +krn krnp2: + $(CD) kernel; make $@ + $(CP) kernel/$@ . + # Special cases +# TC^3 SCSI Booter +boot_tc3: boot_scsi.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) + +# SuperIDE/Glenside IDE Booter +boot_ide: boot_ide.asm + $(AS) $(ASOUT)$@ $< $(IDEFLAGS) # DriveWire 3 boot_dw3_coco1: boot_dw3.asm @@ -67,11 +86,6 @@ dw3_coco1.sb: dw3.asm $(AS) $< $(ASOUT)$@ $(AFLAGS) -aBAUD38400=1 -# Kernel -krn krnp2: - $(CD) kernel; make $@ - $(CP) kernel/$@ . - boot_1773_6ms: boot_1773.asm $(AS) $< $(ASOUT)$@ $(AFLAGS) -aDNum=0 -aSTEP=0 @@ -84,18 +98,13 @@ rb1773_scii_ff58.dr: rb1773.asm $(AS) $< $(ASOUT)$@ $(AFLAGS) -aSCII=1 -aSCIIALT=1 -# Clocks -clock_60hz: clock.asm - $(AS) $(AFLAGS) $(ASOUT)$@ $< -aPwrLnFrq=60 +# TC^3 SCSI Driver +lltc3.dr: llscsi.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) -clock_50hz: clock.asm - $(AS) $(AFLAGS) $(ASOUT)$@ $< -aPwrLnFrq=50 - -clock2_bnb: clock2_ds1315.asm - $(AS) $(AFLAGS) $(ASOUT)$@ $< -aBNB=1 - -clock2_cloud9: clock2_ds1315.asm - $(AS) $(AFLAGS) $(ASOUT)$@ $< -aCLOUD9=1 +# IDE Driver +llide.dr: llide.asm + $(AS) $(ASOUT)$@ $< $(IDEFLAGS) # Floppy descriptors SSDD35 = -aCyls=35 -aSides=1 -aSectTrk=18 -aSectTrk0=18 \ @@ -209,6 +218,47 @@ x3.dd: dwdesc.asm $(AS) $< $(ASOUT)$@ $(AFLAGS) -aDNum=3 +# TC^3 SCSI Descriptors +dds0_tc3.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) $(ID0) -aDD=1 + +s0_tc3.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) $(ID0) $(SCSI_HD) + +s1_tc3.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) $(ID1) $(SCSI_HD) + +s2_tc3.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) $(ID2) $(SCSI_HD) + +s3_tc3.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) $(ID3) $(SCSI_HD) + +s4_tc3.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) $(ID4) $(SCSI_HD) + +s5_tc3.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) $(ID5) $(SCSI_HD) + +s6_tc3.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) $(ID6) $(SCSI_HD) + +sh_tc3.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) $(HDBDOS) + +# IDE Descriptors +ddi0_ide.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(IDEFLAGS) $(MASTER) -aDD=1 + +i0_ide.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(IDEFLAGS) $(MASTER) + +i1_ide.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(IDEFLAGS) $(SLAVE) + +ih_ide.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(IDEFLAGS) $(HDBDOS) + # RFM descriptors ddy0.dd: rfmdesc.asm $(AS) $< $(ASOUT)$@ $(AFLAGS) -aDD=1 -aDNum=0 @@ -234,6 +284,19 @@ sysgo_h0: sysgo.asm $(AS) $(AFLAGS) $(ASOUT)$@ $< +# Clocks +clock_60hz: clock.asm + $(AS) $(AFLAGS) $(ASOUT)$@ $< -aPwrLnFrq=60 + +clock_50hz: clock.asm + $(AS) $(AFLAGS) $(ASOUT)$@ $< -aPwrLnFrq=50 + +clock2_bnb: clock2_ds1315.asm + $(AS) $(AFLAGS) $(ASOUT)$@ $< -aBNB=1 + +clock2_cloud9: clock2_ds1315.asm + $(AS) $(AFLAGS) $(ASOUT)$@ $< -aCLOUD9=1 + clean: $(CD) kernel; make $@ $(RM) $(ALLOBJS)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/level1/modules/boot_ide.asm Thu Dec 22 18:23:47 2011 +0000 @@ -0,0 +1,248 @@ +******************************************************************** +* Boot - IDE Boot Module +* +* $Id$ +* +* Edt/Rev YYYY/MM/DD Modified by +* Comment +* ------------------------------------------------------------------ +* ? 1994/06/25 Alan DeKok +* Diassembled. +* +* 6 1999/08/17 Paul T. Barton +* Redone for IDE. +* +* 7 2002/06/27 Boisy G. Pitre +* Added use of LSN bits 23-16. +* +* 7r1 2004/05/12 Boisy G. Pitre +* Optimized, made toG wait on !BUSY and DRDY, added slowdown POKE +* for Fujitsu 128MB CF (may be temporary) +* +* 8 2004/07/29 Boisy G. Pitre +* Now detects CHS/LBA mode to work with ALL IDE drives. +* +* 9 2005/10/13 Boisy G. Pitre +* Support for fragmented bootfiles added. + + NAM Boot + TTL IDE Boot Module + + IFP1 + USE defsfile + USE ide.d + ENDC + +tylg SET Systm+Objct +atrv SET ReEnt+rev +rev SET $00 +edition SET 9 + +* Disassembled 94/06/25 11:37:47 by Alan DeKok +* ReDone by Paul T. Barton 99/08/17, for IDE + + MOD eom,name,tylg,atrv,start,size + +* on-stack static storage + ORG 0 +cyls RMB 2 +sides RMB 1 +sects RMB 2 +mode RMB 1 +seglist RMB 2 pointer to segment list +blockloc RMB 2 pointer to memory requested +blockimg RMB 2 duplicate of the above +bootloc RMB 3 sector pointer; not byte pointer +bootsize RMB 2 size in bytes +LSN0Ptr RMB 2 LSN0 pointer (used by boot_common.asm) +size EQU . + +name FCS /Boot/ + FCB edition + +* Common booter-required defines +LSN24BIT EQU 1 +FLOPPY EQU 0 + + USE boot_common.asm + +* HWInit - Initialize the device +* Entry: Y = hardware address +* Exit: Carry Clear = OK, Set = Error +* B = error (Carry Set) +HWInit ldb Address+2,pcr + bne slave@ + lda #%10100000 + FCB $8C +slave@ lda #%10110000 + sta mode,u + stb DevHead,y select device +a@ tst Status,y wait for BSY to clear + bmi a@ + lda #$EC + sta Command,y +b@ tst Status,y + bmi b@ +* Harvest C/H/S values. + ldb DataReg,y ignore bytes 0-1 + ldb DataReg,y bytes 2-3 = no. of cylinders + lda Latch,y + std cyls,u save cylinders in our private static area + ldb DataReg,y ignore bytes 4-5 + ldb DataReg,y bytes 6-7 = no. of heads + stb sides,u save sides on stack (B) + ldb DataReg,y ignore bytes 8-9 + ldb DataReg,y ignore bytes 10-11 + ldb DataReg,y bytes 12-13 = no. of sectors/track + lda Latch,y + std sects,u save sectors/track on stack (Y) +* Throw away the next 42 (48-7) words + ldb #43 +l@ tst DataReg,y + lda Latch,y + decb + bne l@ +* A holds byte with LBA bit + anda #%00000010 LBA drive? + beq nope@ + ldb mode,u + orb #%01000000 + stb mode,u +nope@ ldb #256-50 +o@ tst DataReg,y + decb + bne o@ +HWTerm clrb + rts + +* HWRead - Read a 256 byte sector from the device +* Entry: Y = hardware address +* B = bits 23-16 of LSN +* X = bits 15-0 of LSN +* blockloc,u = ptr to 256 byte sector +* Exit: X = ptr to data (i.e. ptr in blockloc,u) +HWRead + pshs x,b +b@ tst Status,y + bmi b@ if =1 then loop + lda mode,u + sta DevHead,y 0L0d/0hhh device=CHS +r@ ldb Status,y is IDE ready for commands? + andb #BusyBit+DrdyBit ready ? + cmpb #DrdyBit + bne r@ loop until Drdy=1 and Busy=0 + ldb #$01 only one at a time + stb SectCnt,y only one at a time + anda #%01000000 + beq chs@ branch if mode + lda ,s get bits 23-16 + sta CylHigh,y + ldd 1,s get bits 15-0 + stb SectNum,y + sta CylLow,y + bra DoCmd +chs@ +* Compute proper C:H:S value + lda sides,u get device's head + ldb sects+1,u and sector + mul multiply H*S +* Note, there is a chance here that if the product is zero, we could loop forever +* beq ZeroProd + pshs d save product of H*S + ldd 1+2,s get bits 15-0 of LSN + ldx #-1 start Y at -1 + inc 0+2,s increment physical sector +* Here we are doing physLSN/(H*S) to get cylinder for physLSN +a@ leax 1,x increment count to compensate + subd ,s subtract (H*S) from physLSN + bhs a@ if D>=0 then continue + dec 0+2,s decrement phys sector bits 23-16 + bne a@ if not zero, continue divide + addd ,s++ add in (H*S) to make non-negative + pshs d X now holds cylinder, save D on stack + tfr x,d + exg a,b swap + std CylLow,y store computed cylinder in HW + puls d restore saved cylinder +* Now we will compute the sector/head value + ldx #-1 +c@ leax 1,x + subb sects+1,u + sbca #0 + bcc c@ + addb sects+1,u + incb add 1 to B, which is sector + stb SectNum,y store computed sector in HW + tfr x,d + orb DevHead,y OR in with value written earlier + stb DevHead,y +DoCmd lda #S$READ read one sector + sta Command,y finish process + +Blk2 lda Status,y is IDE ready to send? + anda #DrqBit DRQ, data request + beq Blk2 loop while DRQ =0 + + ldx blockloc,u + clr ,s +BlkLp + lda DataReg,y A <- IDE + ldb Latch,y + std ,x++ into RAM + inc ,s + bpl BlkLp go get the rest +b@ lda DataReg,y read remaining 256 bytes + dec ,s + bne b@ + + leax -256,x + stx 1,s + lda Status,y check for error-bit + clrb + puls b,x,pc + + + +* ------------------------------------------ + +*Init +* pshs d,y +* ldy <Address,pcr +* bsr ChkBusy could be spinning up... +* lda #Diagnos hits all drives +* sta Command,y ./ +* bsr ChkBusy wait 'til both done +* clrb no errors +* puls d,y,pc + +* Entry: A = number to show +* Destroys D +*Num +* tfr a,b +* lsra +* lsra +* lsra +* lsra +* bsr x@ +* andb #$0F +* tfr b,a +*x@ +* adda #'0 +* cmpa #'9 +* ble s@ +* adda #$7 +*s@ jsr <D.BtBug +* rts + + IFGT Level-1 +Pad FILL $39,$1D0-3-2-1-* + ENDC + +Address FDB SDAddr +WhchDriv FCB 0 Drive to use (0 = master, 1 = slave) + + + EMOD +eom EQU * + END +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/level1/modules/boot_scsi.asm Thu Dec 22 18:23:47 2011 +0000 @@ -0,0 +1,284 @@ +******************************************************************** +* Boot - SCSI Boot Module +* +* $Id$ +* +* This module allows booting from a hard drive that uses HDB-DOS +* and is controlled by a TC^3, Ken-Ton or Disto SCSI controller. +* +* It was later modified to handle hard drives with sector sizes +* larger than 256 bytes, and works on both 256 byte and larger drives, +* so it should totally replace the old SCSI boot module. +* +* Instructions followed by +++ in the comment field were added for this fix. +* +* Edt/Rev YYYY/MM/DD Modified by +* Comment +* ------------------------------------------------------------------ +* 1 ????/??/?? Roger Krupski +* Original Roger Krupski distribution version +* +* 1r1 1996/??/?? Boisy G. Pitre +* Added code to allow booting from any sector size hard drive +* +* 1r2 2002/05/01 Boisy G. Pitre +* Merged Ken-Ton and TC^3 module source +* +* 1r3 2002/07/22 Boisy G. Pitre +* Outputs '.' for each sector read when booting under NitrOS-9 +* +* 2 2004/07/30 Boisy G. Pitre +* SCSI ID 0-7 now modifiable at end of module as well as base address +* +* 3 2005/10/09 Boisy G. Pitre +* Fixed stupid mistake where SCSIDATA was set to base address. Now +* baseaddr is the base address set at the end of the module and SCSIDATA +* is 0 for the data offset. +* Also SCSI-3 compatible SCSI IDs (with hi-bit set) are now sent to bus which +* causes the booter to work with IBM-DPES31080 and other newer hard drives. +* Fragmented bootfiles are now supported. +* +* 4 2008/02/17 Boisy G. Pitre +* Message phase code was broken, now fixed and the booter now works. + + NAM Boot + TTL SCSI Boot Module + + IFP1 + USE defsfile + USE rbsuper.d + USE scsi.d + ENDC + +tylg SET Systm+Objct +atrv SET ReEnt+rev +rev SET 0 +edition SET 4 + + MOD eom,name,tylg,atrv,start,size + +SCSIEX EQU 1 + +* Data equates; subroutines must keep data in stack + IFNE SCSIEX +v$cmd RMB 1 +v$extra RMB 1 +v$addr0 RMB 1 +v$addr1 RMB 1 +v$addr2 RMB 1 +v$addr3 RMB 1 +v$resv RMB 1 +v$blks0 RMB 1 +v$blks1 RMB 1 +v$ctrl RMB 1 + ELSE +v$cmd RMB 1 +v$addr0 RMB 1 +v$addr1 RMB 2 +v$blks RMB 1 +v$opts RMB 1 + ENDC +seglist RMB 2 pointer to segment list +blockloc RMB 2 pointer to memory requested +blockimg RMB 2 duplicate of the above +bootloc RMB 3 sector pointer; not byte pointer +bootsize RMB 2 size in bytes +LSN0Ptr RMB 2 LSN0 pointer (used by boot_common.asm) +size EQU . + +name FCS /Boot/ + FCB edition + +* Common booter-required defines +LSN24BIT EQU 1 +FLOPPY EQU 0 + + + USE boot_common.asm + +************************************************************ +************************************************************ +* Hardware-Specific Booter Area * +************************************************************ +************************************************************ + +* HWInit - Initialize the device +* Entry: Y = hardware address +* Exit: Carry Clear = OK, Set = Error +* B = error (Carry Set) +HWInit + clr >$FF40 stop the disk motors + IFNE D4N1+HDII + leax CntlSlot,pcr + lda ,x + sta MPI.Slct + ENDC + ldd #S$SEEK*256 + ldx #0 + bsr setup + IFEQ SCSIEX + clr v$blks,u + ENDC + bra command + +* Sets up the SCSI packet to send +* Destroys B +setup sta v$cmd,u + IFNE SCSIEX + clr v$extra,u + clr v$addr0,u + stb v$addr1,u + stx v$addr2,u + clr v$resv,u + clr v$blks0,u + ldb #1 + stb v$blks1,u + clr v$ctrl,u + ELSE + stb v$addr0,u + stx v$addr1,u + ldb #1 + stb v$blks,u + clr v$opts,u + ENDC + rts + +scsival FCB $80+1,$80+2,$80+4,$80+8,$80+16,$80+32,$80+64,$80 + +* SCSI Wake-Up Routine +* Destroys: X +wakeup ldx #0 load X with 0 (counter) +* Step 1: Wait for BUSY+SEL to be clear +wake lda SCSISTAT,y obtain SCSI status byte + bita #BUSY BUSY clear? + beq wake1 branch if so + leax -1,x else count down + bne wake and try again if not timed out + bra wake4 else branch to timeout +* Step 2: Put our SCSI ID on the bus +wake1 bsr wake3 small delay + lda WhichDrv,pcr get SCSI ID + leax <scsival,pcr point to SCSI value table + lda a,x get appropriate bitmask + sta SCSIDATA,y put on SCSI bus + bsr wake3 small delay + sta SCSISEL,y and select + ldx #0 load X with 0 (counter) +wake2 lda SCSISTAT,y obtain SCSI status byte + bita #BUSY BUSY set? + bne wake3 if so, exit without error + leax -1,x else count down + bne wake2 and try again if not timed out +wake4 comb set carry + ldb #E$NotRdy and load error +wake3 rts then return + + +* HWRead - Read a 256 byte sector from the device +* Entry: Y = hardware address +* B = bits 23-16 of LSN +* X = bits 15-0 of LSN +* blockloc,u = ptr to 256 byte sector +* Exit: X = ptr to data (i.e. ptr in blockloc,u) +HWRead lda #S$READEX + bsr setup +* SCSI Send Command Routine +command bsr wakeup tell SCSI we want the bus + bcs wake3 return immediately if error + leax v$cmd,u + bsr SCSISend + bcs command + bsr Wait4REQ + bita #CMD + bne getsta + ldx blockloc,u + bsr read +getsta bsr Wait4REQ + lda SCSIDATA,y + anda #%00001111 + pshs a + bsr Wait4REQ + clra + sta SCSIDATA,y + puls a + bita #X$BUSY + bne command + bita #X$ERROR + beq HWTerm +reterr comb + ldb #E$Unit + rts + +* HWTerm - Terminate the device +* Entry: Y = hardware address +* Exit: Carry Clear = OK, Set = Error +* B = error (Carry Set) +HWTerm clrb + rts + +SCSISend bsr Wait4REQ + bita #CMD + beq HWTerm + bita #INOUT + bne ckmsg + lda ,x+ + sta SCSIDATA,y + bra SCSISend +ckmsg bita #MSG MESSAGE IN (target->initiator) + beq HWTerm + lda SCSIDATA,y extended message? + deca +* +* MESSAGE IN phase code +* + bne SCSISend + ldb SCSIDATA,y get extended message length +l@ tst SCSIDATA,y read extended message + decb + bne l@ + bra reterr return with carry set + +Wait4REQ +loop@ lda SCSISTAT,y + bita #REQ + beq loop@ + rts + +* Patch to allow booting from sector sizes > 256 bytes - BGP 08/16/97 +* We ignore any bytes beyond byte 256, but continue to read them from +* the SCSIDATA until the CMD bit is set. +read +* next 2 lines added + clrb +++ use B as counter +read2 + bsr Wait4REQ + bita #CMD + bne HWTerm + lda SCSIDATA,y + sta ,x+ +* next line commented out and next 8 lines added +* bra read + incb +++ + bne read2 +++ + leax -256,x +read3 + bsr Wait4REQ +++ + bita #CMD +++ + bne HWTerm +++ + lda SCSIDATA,y +++ + bra read3 +++ + + + IFGT Level-1 +* Fillers to get to $1D0 +Pad FILL $39,$1D0-3-1-2-1-* + ENDC + +* The default SCSI ID is here +CntlSlot FCB SDMPI +Address FDB SDAddr +WhichDrv FCB 0 + + EMOD +eom EQU * + END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/level1/modules/llide.asm Thu Dec 22 18:23:47 2011 +0000 @@ -0,0 +1,1098 @@ +******************************************************************* +* llide - Low-level IDE driver +* +* $Id$ +* +* This low level driver works with both ATA and ATAPI devices. +* +* The type of device (ATA or ATAPI) is automatically detected +* by the 'IOSetup' routine. Additionally, an ATA device is +* further detected as either an LBA or CHS device. +* +* Since only two physical drives are allowed (master/slave), +* there is a two entry "per drive static storage" that indicates +* if a drive has been initialized, its type (ATAPI or ATA, LBA or +* CHS), and if ATA, its geometry. +* +* Edt/Rev YYYY/MM/DD Modified by +* Comment +* ------------------------------------------------------------------ +* 1 2004/04/08 Boisy G. Pitre +* Created. +* +* 2 2005/07/23 Christopher R. Hawks +* Fixes for persnickity ATAPI CDROMs. +* +* 3 2005/08/21 Christopher R. Hawks +* More fixes. +* +* 4 2005/12/13 Boisy G. Pitre +* Moved SS.VarSect code into RBSuper for performance + + NAM llide + TTL Low-level IDE driver + + IFP1 + USE defsfile + USE rbsuper.d + USE ide.d + ENDC + +tylg SET Sbrtn+Objct +atrv SET ReEnt+rev +rev SET 4 + + +RW12 SET 0 Use READ12/WRITE12 ATAPI commands (1 = yes) +WAITTIME SET 10 BUSY wait time (in approximate seconds) + +* +* Status Register Flip/Mask Values +* +NBUSYDRDY EQU (BusyBit|DrdyBit)*256+(DrdyBit) +NBUSY EQU (BusyBit)*256+$00 +NBUSYDRQ EQU (BusyBit|DrqBit)*256+(DrqBit) +NBUSYNDRQ EQU (BusyBit|DrqBit)*256+$00 + + MOD eom,name,tylg,atrv,start,0 + + IFNE RW12 +READCODE EQU A$READ2 +WRITCODE EQU A$WRITE2 + ELSE +READCODE EQU A$READ +WRITCODE EQU A$WRITE + ENDC + +NumRetries EQU 8 + +* Low-level driver static memory area + ORG V.LLMem +* Master static storage +V.Master RMB 1 status byte (ATAPI or ATA (CHS or LBA)) + RMB 2 Cylinders (CHS) or Bits 31-16 of LBA + RMB 1 Sides (CHS) or Bits 15-8 of LBA + RMB 2 Sectors (CHS) or Bits 7-0 of LBA +* Slave drive static storage +V.Slave RMB 1 + RMB 2 + RMB 1 + RMB 2 +* ATAPI Command Packet +V.ATAPICmd RMB 18 +V.SnsData EQU V.ATAPICmd Sense Data is shared with ATAPI command block +* The following values are for device 0 and 1 respectively: +* Bit 0 = device inited (0 = false, 1 = true) +* Bit 1 = device type (0 = ATA, 1 = ATAPI) +* Bit 2 = device mode (0 = CHS, 1 = LBA) +V.CurStat RMB 1 +V.Retries RMB 1 +V.WhichDv RMB 1 contains devhead selection (made by IOSetup) +V.PhySct RMB 3 local copy of physical sector passed (V.PhySct) +V.SctCnt RMB 1 local copy of physical sector passed (V.SectCnt) +V.Sectors RMB 1 number of sectors (harvested directly from drive query) +V.CurDTbl RMB 2 +V.ATAVct RMB 2 + + +name FCS /llide/ + +start bra ll_init + nop + lbra ll_read + lbra ll_write + lbra ll_getstat + lbra ll_setstat + +* ll_init - Low level init routine +* +* Entry: +* Y = address of device descriptor +* U = address of low level device memory area +* +* Exit: +* CC = carry set on error +* B = error code +* +* Note: This routine is called ONCE: for the first device +* IT IS NOT CALLED PER DEVICE! +* +ll_init +* clrb +* rts + + +* ll_term - Low level term routine +* +* Entry: +* Y = address of device descriptor +* U = address of device memory area +* +* Exit: +* CC = carry set on error +* B = error code +* +* Note: This routine is called ONCE: for the last device +* IT IS NOT CALLED PER DEVICE! +* +ll_term + clrb + rts + + +* Entry: Y = address of per-drive static storage +ATADSize + pshs y,x,b make room for space on stack (and save id byte) +* Determine if we are dealing with LBA or CHS + bitb #$04 LBA? + bne lba@ +* Here we pull CHS values +chs@ + ldd 1,y get cylinders + std 1,s + lda 3,y get sides + sta ,s save sides on stack (B) + ldd 4,y get sectors + std 3,s save sectors/track on stack (Y) + bra m@ +* Here we pull LBA values at words 60-61 +lba@ + clr ,s clear flag indicating LBA mdoe (B) + ldd 3,y get bits 15-0 + std 3,s save bits 15-0 on stack (Y) + ldd 1,y get bits 31-16 + std 1,s save bits 31-16 (X) +m@ lda #$02 512 bytes/sector +ex@ puls b,x,y,pc + + +* SSDSize - Get a disk medium's size +* +* GetStat Call SS.DSize: +* +* Entry: B = SS.DSize +* Exit: Carry = 1; error with code in B +* Carry = 0: +* IF B = 0 +* A = Sector Size (1 = 256, 2 = 512, 4 = 1024, 8 = 2048) +* X = Number of Sectors (bits 31-16) +* Y = Number of Sectors (Bits 15-0) +* IF B != 0 +* A = Sector Size (1 = 256, 2 = 512, 4 = 1024, 8 = 2048) +* X = Number of Logical Cylinders +* B = Number of Logical Sides +* Y = Number of Logical Sectors/Track +* +SSDSize pshs u,y + bsr DSize + bcs ex@ + ldu ,s get path desc in U + ldu PD.RGS,u + std R$D,u + stx R$X,u + sty R$Y,u + clrb +ex@ puls y,u,pc + +DSize lbsr IOSetup + bcs ex@ +* Determine if this device is ATAPI or ATA + bitb #$02 ATAPI? + lbeq ATADSize no, it's ATA +* Note - for ATAPI version of SS.DSize, we use the obsolete +* READ CAPACITY call because it works on CD-ROMs, as opposed to +* READ FORMAT CAPACITIES. +ATAPIDSize + lbsr ATAPIPreSend prepare packet +* Populate packet buffer with STOP code and Eject +* ldd #$230C ATAPI READ FORMAT CAPACITIES Code + lda #$25 ATAPI READ CAPACITY Code + sta V.ATAPICmd,u write it +* stb V.ATAPICmd+8,u and allocation length +* Send to data port + bsr ATAPISend send command + bcs ex@ +* Read 8 bytes of format capacity data +* ldb #6 + ldb #4 + pshs b + leay V.SnsData,u +read@ lda DataReg,x + ldb Latch,x + std ,y++ + dec ,s + bne read@ + puls b + ldx V.SnsData+0,u + ldy V.SnsData+2,u + leay 1,y + bcc b@ + leax 1,x +b@ lda V.SnsData+6,u + clrb +ex@ rts + +* ldy PD.RGS,y +* ldd V.SnsData+0,u get bits 31-16 +* std R$X,y +* ldd V.SnsData+2,u get bits 15-0 +* addd #$0001 add 1 +* std R$Y,y +* bcc b@ +* ldd R$X,y +* addd #$0001 +* std R$X,y +*b@ lda V.SnsData+6,u get bits 15-8 of block size +* sta R$A,y +* clr R$B,y signal that this is LBA mode +* clrb +*ex@ rts + + +* ll_getstat - Low level GetStat routine +* +* Entry: +* Y = address of path descriptor +* U = address of device memory area +* +* Exit: +* CC = carry set on error +* B = error code +* +ll_getstat + ldx PD.RGS,y + lda R$B,x + cmpa #SS.DSize + beq SSDSize + ldb #E$UnkSvc + coma +ex1 rts + + +* StopUnit - Park a drive +* +* ATA Devices: This is a No-Op. +* ATAPI Devices: A STOP UNIT command is issued to the device. +* (ejects media on ATAPI removable devices) +StopUnit lbsr IOSetup + bcs ex1 +* Determine if this device is ATAPI or ATA + bitb #$02 ATAPI? + beq ex1 no, ignore... + lbsr ATAPIPreSend prepare packet +* Populate packet buffer with STOP code and Eject +ok@ ldd #A$STOP*256+$02 ATAPI STOP Code and Eject byte + sta V.ATAPICmd,u write it and RSV to zero + stb V.ATAPICmd+4,u +* Send to data port + bra ATAPISend send command + + +* ll_setstat - Low level SetStat routine +* +* Entry: +* Y = address of path descriptor +* U = address of device memory area +* +* Exit: +* CC = carry set on error +* B = error code +* +ll_setstat + ldx PD.RGS,y + lda R$B,x + cmpa #SS.SQD + beq StopUnit + IFNE 0 + cmpa #SS.DCmd + bne n@ + pshs x save pointer to caller registers + bsr DCmd call DCmd + puls x get pointer to caller registers + sta R$A,x save status byte in A + ENDC +n@ clrb +ssex rts + + + IFNE 0 +BadType comb + ldb #E$BTyp + rts + +* Entry: +* X = caller regs +* Y = path descriptor +* +* R$B = SS.DCmd +* R$X = Transfer buffer +* R$Y = ATAPI command packet +DCmd + pshs y + os9 F$ID get the user ID of the calling process + cmpy #$0000 is it 0 (superuser)? + puls y + bne noperms no, don't allow the call + lbsr IOSetup +** SS.DCmd only works with ATAPI devices. + bitb #$02 ATAPI? + beq BadType branch if not + ldy R$X,x get caller's transfer buffer + sty V.UTxBuf,u save off in mem for later + ldx R$Y,x get ptr to caller's command buffer + IFGT Level-1 + ldy D.Proc get current process ptr + lda P$Task,y get task # for current process + ldb D.SysTsk get system task # + ldy #ATAPIPkLn max size of ATAPI command + pshs u save on stack + leau V.ATAPICmd,u point to ATAPI command buffer in our statics + os9 F$Move copy from caller to temporary task + puls u + bcs ex error copying, exit + ELSE + ldb #ATAPIPkLn + leay V.ATAPICmd,u +cl@ lda ,x+ + sta ,y+ + decb + bne cl@ + ENDC + ldy V.PORT-UOFFSET,u get hw address (because we overwrite Y earlier) +* inc V.OS9Err,u we want real errors returned + inc V.CchDirty,u and make cache dirty +* leax retry@,pcr +* stx V.RetryVct,u +retry@ lbsr ATAPISend + bcs ex + IFGT Level-1 + ldx D.Proc get current process ptr + ldb P$Task,x get task # for current process + ENDC + ldx V.UTxBuf,u + +msgloop@ lbsr Wait4REQ wait for REQ to be asserted + bita #CMD command phase? + lbne PostXfr yes, return +io@ bita #INOUT data coming in or going out? + bne in@ branch if coming in... + IFGT Level-1 + os9 F$LDABX + leax 1,x + ELSE + lda ,x+ + ENDC + sta SCSIDATA,y + bra msgloop@ +in@ lda SCSIDATA,y + IFGT Level-1 + os9 F$STABX + leax 1,x + ELSE + sta ,x+ + ENDC + bra msgloop@ + ENDC + +* ATAPISend - Sends the command packet to the device +* +* Entry: X = HW address +* V.WhichDv = DevHead device selection value +* Exit: Carry = 1; error code in B +* Carry = 0; command successfully sent +ATAPISend +* First, select the device and wait for /BUSY + lda V.WhichDv,u + sta DevHead,x select device +* ATAPI says we wait for !BUSY + ldd #NBUSYDRDY wait for NBUSY and DEVREADY too - CRH + lbsr StatusWait wait for proper condition + bcs timeout branch if error + lda #NumRetries get retry count + sta V.Retries,u and save +retry@ + clr Features,x clear feature byte + clr SectCnt,x clear TAG field + ldd #$FFFF maximum read in PIO mode + std CylLow,x + lda #$A0 ATAPI PACKET CODE + sta Command,x write it to device +* Check for error + ldd #NBUSYDRQ /BUSY and DRQ + lbsr StatusWait wait for proper condition + bcs ex@ branch if error +* Send to data port + lda #6 packet size / 2 + pshs a,y + leay V.ATAPICmd,u +l@ ldd ,y++ + stb Latch,x + sta DataReg,x + dec ,s + bne l@ + puls a,y +* Added by CRH - Some drives require that we wait for much more than +* 400ns. Hence this code forces a slow-down and checks the status +* to see if things are ok. + clrb +slow@ decb CRH wait for much more than 400ns + bne slow@ + lda Status,x CRH Sometimes error on first try + lsra + bcc ok@ + dec V.Retries,u + bne retry@ +* As per ATA/ATAPI-6 spec (T13/1410D Revision 3A), page 161, we wait for /BUSY +* and DRQ after sending a command +* That IS NOT the case when sending START/STOP unit commands, so we don't check +* for DRQ. +ok@ ldd #NBUSY /BUSY + lbsr StatusWait wait for proper condition + bcs ex@ branch if error + lda #A$STOP CRH see above + cmpa V.ATAPICmd,u + beq nodata@ + ldd #NBUSYDRQ /BUSY and DRQ + lbsr StatusWait wait for proper condition + bcs ex@ branch if error +nodata@ lsra shift in CHECK CONDITION bit + bcc ex@ branch if ok +* Note: if the device returns error, DRQ won't be set... +err@ lbsr HandleSenseKey go check sense key + bcs ex@ +ret@ dec V.Retries,u else retry until terminal + bne retry@ continue retrying +timeout comb set carry + ldb #E$DevBsy+4 SHOULD BE AN E$TimeOut ERROR! +ex@ rts + +* Prepare the ATAPI Packet +ATAPIPreSend + pshs x +* Clear 12 byte packet. + leax V.ATAPICmd,u + ldb #12 +c@ clr ,x+ + decb + bne c@ +ex@ puls x,pc + + +** ATAPI REQUEST SENSE Command +** Should only be called for ATAPI devices +*ReqSense +* bsr ATAPIPreSend prepare packet +** Populate packet buffer with REQUEST SENSE +* ldd #$0312 ATAPI REQUEST SENSE Code and allocation length byte +* sta V.ATAPICmd,u +* stb V.ATAPICmd+4,u +** Send to data port +* lbsr ATAPISend send command +* lda Status,x get status code +* lsra shift in CHECK CONDITION bit +* bcs ex@ branch if ok +** Read 18 bytes of sense data +* ldb #$12 +* pshs y,b +* leay V.SnsData,u +*read@ lda DataReg,x +* ldb Latch,x +* std ,y++ +* dec ,s +* bne read@ +* puls b,y,pc +*ex@ rts + + +* IOSetup - Sets up the device for I/O +* +* The device is selected (master or slave), then the device is +* checked for previous initialization. +* +* If the device has not been initialized, it is queried for its +* mode (ATAPI/ATA, LBA or CHS) and size. That information is +* saved in the driver's static storage for later use by other +* routines. +* +* Entry: Y = path descriptor pointer +* U = static memory pointer +* Exit: B = status byte for device +* X = HW address +* Y = pointer to current device table +IOSetup ldx V.PORT-UOFFSET,u get hw address + lda PD.DNS,y get device ID bit + lsra shift device ID into carry + bcs slave@ + lda #%10100000 master byte + leay V.Master,u + bra t@ +slave@ lda #%10110000 slave byte + leay V.Slave,u else point to slave status byte +t@ sty V.CurDTbl,u + sta V.WhichDv,u save for later +* Select the device -- on power-up, the status register is usually 0 + sta DevHead,x select device +* According to page 320 of the ATA/ATAPI-6 document, we must wait for BOTH +* BUSY and DRQ to be clear before proceeding. (HI2: Device_Select State) + ldd #NBUSYNDRQ /BUSY and /DRQ + lbsr StatusWait wait for proper condition + lbcs ex@ branch if error +* Determine if this device has already been initialized + tst ,y test device's stat byte + lbne initdone if not zero, init already done +* Here we must initialize the device by IDENTIFYING it. +* First, try sending the ATA IDENTIFY DRIVE code + lda #$EC ATA identify command + sta Command,x write it + ldd #NBUSY /BUSY + lbsr StatusWait wait for proper condition + lbcs ex@ branch if error +* Check if there's an error + lsra shift error bit into carry + bcc ATAIdent if no error, then probably ATA +* If here, we got an error sending $EC, so try ATAPI's $A1 + lda #$A1 + sta Command,x + clrb +slow@ decb CRH wait for much more than 400ns + bne slow@ + ldd #NBUSY + lbsr StatusWait wait for proper condition + bcs ex@ branch if error + lsra shift error bit into carry + bcs timeout if not error, we're ok + ldd #NBUSYDRQ + lbsr StatusWait wait for proper condition + lbcs ex@ branch if error +* Here, we have identified an ATAPI device. +ATAPIIdent + ldb #$03 ATAPI + stb ,y +* We flush the ATAPI data but don't reference it +dread@ ldb DataReg,x CRH flush ALL bytes +* ldb Latch,x but save time by not reading latch + lda Status,x + anda #8 + bne dread@ + bra initdone +* ATAIdent - process an ATA device +* This routine is called by IOSetup when it deduces that the device +* being queried is an ATA device. This device is called ONCE -- the +* first time the device is accessed. +* This routine will set up our per-drive static storage to indicate that +* it is an ATA device. It will also determine if it is an LBA or CHS mode +* device, and save the appropriate CHS or LBA sector values. +ATAIdent + ldd #NBUSYDRDY /BUSY and DRDY + lbsr StatusWait wait for proper condition + bcs ex@ branch if error +* Harvest C/H/S and LBA sector values. + ldb DataReg,x ignore bytes 0-1 + ldb DataReg,x bytes 2-3 = no. of cylinders + lda Latch,x + std 1,y save cylinders in our private static area + ldb DataReg,x ignore bytes 4-5 + ldb DataReg,x bytes 6-7 = no. of heads + lda Latch,x + stb 3,y save sides on stack (B) + ldb DataReg,x ignore bytes 8-9 + ldb DataReg,x ignore bytes 10-11 + ldb DataReg,x bytes 12-13 = no. of sectors/track + lda Latch,x + std 4,y save sectors/track on stack (Y) +* Throw away the next 42 (7-48) words + ldb #43 +l@ tst DataReg,x + lda Latch,x + decb + bne l@ +* A holds byte with LBA bit + incb B was 0, now 1 + anda #%00000010 LBA allowed on this drive? + beq nope@ + orb #$04 set LBA mode + stb ,y save updated status byte +* Since we're LBA mode, get the number of LBA sectors in words 60-61 + ldb #10 skip to the LBA sectors (words 60-61) +more@ tst DataReg,x simply read the data register like this... + decb + bne more@ + ldb DataReg,x get word 60 + lda Latch,x + std 3,y + ldb DataReg,x and 61 + lda Latch,x + std 1,y + lda #256-61 how many words we have left + bra left@ go on. +nope@ stb ,y save updated status byte +* Read remaining 256-50 words + lda #256-50 +left@ ldb DataReg,x + deca + bne left@ +initdone ldb ,y get status byte of drive + clra clear carry +ex@ rts + + +* ATAPI Write Routine -- Independent of ATA Read +ATAPIWrite + lbsr ATAPIPreSend prepare packet +* Populate packet buffer with WRITE code and sector information +again@ ldb V.PhySct,u get bits 23-16 of sector + stb V.ATAPICmd+3,u + ldd V.PhySct+1,u get bits 15-0 of sector + std V.ATAPICmd+4,u + ldd #WRITCODE*256+$01 ATAPI WRITE Code and transfer length + sta V.ATAPICmd,u write it + IFNE RW12 + stb V.ATAPICmd+9,u write to byte 9 + ELSE + stb V.ATAPICmd+8,u write to byte 8 + ENDC +* Send to data port + lbsr ATAPISend send command + bcs ex@ +* Shift data from device +o@ pshs d + lda V.Log2Phys,u + sta 1,s set up our logical sector counter +inc@ clr ,s set up our byte counter +wr@ ldd ,y++ + stb Latch,x + sta DataReg,x + inc ,s + bpl wr@ + dec 1,s + bne inc@ + puls d +* Increment physical sector + inc V.PhySct+2,u + bcc go@ + inc V.PhySct+1,u + bcc go@ + inc V.PhySct,u +go@ dec V.SctCnt,u decrement # of hw sectors to read + bne again@ if not zero, do it again + ldd #NBUSY /BUSY + lbsr StatusWait wait for proper condition + bcs ex@ branch if error + lsra error bit set? + bcc ex@ yep... + bsr HandleSenseKey +ex@ puls x,pc + + + +* ATAPI Read Routine -- Independent of ATA Read +ATAPIRead + ldy V.CchPSpot,u get pointer to spot in cache to put sector + lbsr ATAPIPreSend do command packet setup stuff +* Populate packet buffer with READ code and sector information +again@ ldb V.PhySct,u get,u bits 23-16 of sector + stb V.ATAPICmd+3,u + ldd V.PhySct+1,u get bits 15-0 of sector + std V.ATAPICmd+4,u + ldd #READCODE*256+$01 ATAPI Read Code and transfer length + sta V.ATAPICmd,u write it and RSV to zero + IFNE RW12 + stb V.ATAPICmd+9,u write to byte 9 + ELSE + stb V.ATAPICmd+8,u write to byte 8 + ENDC +* Send to data port + lbsr ATAPISend send command + bcs ex@ +* Shift data from device +o@ pshs d + lda V.Log2Phys,u + sta 1,s set up our logical sector counter +inc@ clr ,s set up our byte counter +read@ lda DataReg,x + ldb Latch,x + std ,y++ + inc ,s + bpl read@ + dec 1,s + bne inc@ + puls d +* Increment physical sector + inc V.PhySct+2,u + bcc go@ + inc V.PhySct+1,u + bcc go@ + inc V.PhySct,u +go@ dec V.SctCnt,u decrement # of hw sectors to read + bne again@ if not zero, do it again + ldd #NBUSY /BUSY + lbsr StatusWait wait for proper condition + bcs ex@ branch if error + lsra error bit set? + bcc ex@ nope... + bsr HandleSenseKey +ex@ puls x,pc + + +* Handle ATAPI Sense Key +* If the resulting error in the look-up table is zero, +* we return with carry clear +* Returns: B = 0 (carry clear, no error) +* B != 1 (carry set, error) +HandleSenseKey + pshs x,a + ldb ErrorReg,x get error register value + lsrb shift sense key into place + lsrb + lsrb + lsrb + leax SenseMap,pcr point to Sense Key Map + clra clear carry + ldb b,x get appropriate error + beq ok@ if error is zero, return ok + coma set carry +ok@ puls a,x,pc + +* ll_read - Low level read routine +* +* Entry: +* Registers: +* Y = address of path descriptor +* U = address of device memory area +* Static Variables of interest: +* V.PhySct = starting physical sector to read from +* V.SectCnt = number of physical sectors to read +* V.SectSize = physical sector size (0=256,1=512,2=1024,3=2048) +* V.CchPSpot = address where physical sector(s) will go +* +* Exit: +* All registers may be modified +* Static variables may NOT be modified +ll_read + pshs x make some space on the stack + lbsr IOSetup initialize the device + lbcs ex@ +* Copy V.PhySct and V.SectCnt to our local copy +* since we cannot modify them. + lda V.PhysSect,u + ldy V.PhysSect+1,u + sta V.PhySct,u + sty V.PhySct+1,u + lda V.SectCnt,u + sta V.SctCnt,u + bitb #$02 ATAPI device? + lbne ATAPIRead yes, go do it +* ATA Read Routine +ATARead +* stb V.CurStat,u save status of current drive + bitb #$04 LBA drive? + bne lba@ branch if so + leay DoCHS,pcr else point Y to CHS routine + bra skip@ +lba@ leay DoLBA,pcr +skip@ sty V.ATAVct,u save pointer + ldy V.CchPSpot,u get pointer to spot in cache to put sector +loop@ + ldd #NBUSY /BUSY + bsr StatusWait wait for proper condition + bcs ex@ branch if error + jsr [V.ATAVct,u] do proper ATA preparation + bcs ex@ branch if error +cont@ lda #$01 + sta SectCnt,x store it + lda #S$READ + sta Command,x + ldd #NBUSY /BUSY + bsr StatusWait wait for proper condition + bcs ex@ branch if error + lsra error bit set? + bcc w@ branch if not + lbsr ATAError + bra ex@ +w@ ldd #NBUSYDRQ /BUSY and DRQ + bsr StatusWait wait for proper condition + bcs ex@ branch if error + lda V.Log2Phys,u + sta 1,s set up our logical sector counter +inc@ clr ,s set up our byte counter +read@ lda DataReg,x + ldb Latch,x + std ,y++ + inc ,s + bpl read@ + dec 1,s + bne inc@ +* Increment physical sector + inc V.PhySct+2,u + bcc go@ + inc V.PhySct+1,u + bcc go@ + inc V.PhySct,u +go@ dec V.SctCnt,u decrement # of hw sectors to read + bne loop@ if not zero, do it again + clrb +ex@ puls x,pc + + +* +* Convert LSN to LBA values +* +* Entry: V.PhySct = bits 23-0 of LSN +* X = ptr to hardware +* +* Exit: CHS values placed directly in HW +* +DoLBA lda V.WhichDv,u get devhead value populated by IOSetup (CHS mode) + ora #%01000000 OR in LBA bit + sta DevHead,x + ldd #NBUSYNDRQ /BUSY and /DRQ + bsr StatusWait + bcs ex@ + ldb V.PhySct,u get bits 23-16 of sector + stb CylHigh,x store it + ldd V.PhySct+1,u get bits 15-0 of sector + stb SectNum,x store it + sta CylLow,x +ex@ rts + + +* Wait for a set of conditions in the status register to be TRUE +* This yields a delay of about 4 seconds. +* +* Entry: X = HW address +* A = flip (if bit set, that bit is tested) +* B = mask (result must match this byte) +* Exit: A = status +StatusWait + pshs y,b,a + IFEQ Level-1 + ldb #WAITTIME/2 + ldy #$0000 + ELSE + ldb #WAITTIME + ldy #$0000 + ENDC +l@ lda Status,x + anda ,s apply flip + cmpa 1,s compare to mask + bne dec@ branch if not equal (not what we want) + clrb clear carry + bra ok@ +dec@ leay -1,y count down + bne l@ + decb decrement bits 23-16 + bpl l@ if >=0, keep going +err@ comb set carry + ldb #E$DevBsy +ok@ leas 2,s + lda Status,x get status again + puls y,pc + +* Wait for 1 tick (1/60 second) +*Delay1Tk +* pshs x +* IFGT Level-1 +* ldx D.Proc get proc descriptor +* cmpx D.SysPrc system? +* beq hw@ yep, system cannot sleep +* ENDC +* ldx D.AProcQ get active proc queue +* beq hw@ if empty, do hard wait +* ldx #1 +* os9 F$Sleep give up worst case: 1 tick (1/60 second) +* puls x,pc return to caller +** In case we can't sleep... do a hard 1/60 second delay +*hw@ +* IFEQ Level-1 +* ldx #$E52E/2 (5) (4) +* ELSE +* ldx #$E52E (5) (4) +* ENDC +*w@ leax -1,x (4+) (4+) +* bne w@ (3) (3) +* puls x,pc return to caller +* + + +* ll_write - Low level write routine +* +* Entry: +* Registers: +* Y = address of path descriptor +* U = address of device memory area +* Static Variables of interest: +* V.PhySct = starting physical sector to write to +* V.SectCnt = number of physical sectors to write +* V.SectSize = physical sector size (0=256,1=512,2=1024,3=2048) +* V.CchPSpot = address of data to write to device +* +* Exit: +* All registers may be modified +* Static variables may NOT be modified +ll_write + pshs x make some space on the stack + lbsr IOSetup initialize the device + lbcs ex@ +* Copy V.PhySct to our local copy + lda V.PhysSect,u + ldy V.PhysSect+1,u + sta V.PhySct,u + sty V.PhySct+1,u + lda V.SectCnt,u + sta V.SctCnt,u +* + ldy V.CchPSpot,u get pointer to spot in cache where physical sector is + bitb #$02 ATAPI device? + lbne ATAPIWrite yes, go do it +* ATA Write Routine +ATAWrite stb V.CurStat,u save status of current drive +loop@ + ldd #NBUSY /BUSY + bsr StatusWait wait for proper condition + bcs ex@ branch if ok +* Check for LBA mode + ldb V.CurStat,u get status of current drive + bitb #$04 LBA bit set? + bne lba@ branch if so +* Here, we use CHS + bsr DoCHS + bcs ex@ + bra cont@ +lba@ lbsr DoLBA +cont@ lda #$01 + sta SectCnt,x store it + lda #S$WRITE + sta Command,x + ldd #NBUSY /BUSY + bsr StatusWait wait for proper condition + bcs ex@ branch if ok + lsra error bit set? + bcc g@ branch if not + lbsr ATAError + bra ex@ +g@ ldd #NBUSYDRQ /BUSY and DRQ + lbsr StatusWait wait for proper condition + bcs ex@ branch if ok +again@ lda V.Log2Phys,u + sta 1,s set up our sector counter +inc@ clr ,s set up our byte counter +wr@ ldd ,y++ + stb Latch,x + sta DataReg,x + inc ,s + bpl wr@ + dec 1,s + bne inc@ +* Increment physical sector + inc V.PhySct+2,u + bcc go@ + inc V.PhySct+1,u + bcc go@ + inc V.PhySct,u +go@ + dec V.SctCnt,u decrement # of hw sectors to read + bne loop@ if not zero, do it again + clrb +ex@ puls x,pc + +* +* Convert LSN to C/H/S values and write to IDE hardware +* +* Entry: V.PhySct = bits 23-0 of LSN +* X = ptr to hardware +* +* Exit: CHS values placed directly in HW +* +DoCHS +* Select device + lda V.WhichDv,u get devhead value made by IOSetup (already CHS) + sta DevHead,x + ldd #NBUSYNDRQ /BUSY and /DRQ + lbsr StatusWait wait for proper condition + bcc start@ branch if ok + rts +* Start computation +start@ pshs y save original Y + ldy V.CurDTbl,u + lda 3,y get device's head + ldb 5,y and sector + stb V.Sectors,u + mul multiply H*S + beq ZeroProd if zero, error out + pshs d save product of H*S + ldd V.PhySct+1,u get bits 15-0 of LSN + ldy #-1 start Y at -1 + inc V.PhySct,u increment physical sector +* Here we are doing physLSN/(H*S) to get cylinder for physLSN +a@ leay 1,y increment count to compensate + subd ,s subtract (H*S) from physLSN + bhs a@ if D>=0 then continue + dec V.PhySct,u decrement phys sector bits 23-16 + bne a@ if not zero, continue divide + addd ,s++ add in (H*S) to make non-negative + pshs d D now holds cylinder, save on stack + tfr y,d Y now holds cylinder value + exg a,b swap + std CylLow,x store computed cylinder in HW + puls d restore saved cylinder +* Now we will compute the sector/head value + ldy #-1 +b@ leay 1,y + subb V.Sectors,u + sbca #0 + bcc b@ + addb V.Sectors,u + incb add 1 to B, which is sector + stb SectNum,x store computed sector in HW + tfr y,d + orb DevHead,x OR in with value written earlier + stb DevHead,x + clrb + puls y,pc +ZeroProd ldb #E$Sect + coma + puls y,pc + +* ATAError - Checks the ATA error register and maps +* to a NitrOS-9 error message. +* +* Called if the error bit in the status register is set. +ATAError + lda ErrorReg,x + ldb #7 +l@ lsra + bcs LookUp + decb + bne l@ +LookUp leax Errs,pcr +x@ ldb b,x + coma + rts + +* This is the ATAPI Sense Key -> NitrOS-9 Error Table +* The Sense Key Table is on page 50 of the ATAPI Removable +* Rewritable Specification, Revision 1.3 Proposed. +* If an error number is zero, then no error is returned. +SenseMap FCB 0 sense key 0 (NO SENSE) + FCB 0 sense key 1 (RECOVERED ERROR) + FCB E$NotRdy sense key 2 (NOT READY) + FCB E$Sect sense key 3 (MEDIUM ERROR) + FCB E$Unit sense key 4 (HARDWARE ERROR) + FCB E$IllArg sense key 5 (ILLEGAL REQUEST) + FCB 0 sense key 6 (UNIT ATTENTION) + FCB E$WP sense key 7 (DATA PROTECT) + FCB 0 sense key 8 (BLANK CHECK) + FCB 0 sense key 9 (VENDOR SPECIFIC) + FCB 0 sense key A (RESERVED) + FCB 1 sense key B (ABORTED COMMAND) + FCB 0 sense key C (RESERVED) + FCB 0 sense key D (VOLUME OVERFLOW) + FCB 0 sense key E (MISCOMPARE) + FCB 0 sense key F (RESERVED) + +* ERROR REG Bit 0 1 2 3 4 5 6 7 +Errs FCB E$Unit,E$CRC,E$UnkSvc,E$Sect,E$UnkSvc,E$DIDC,E$Seek,E$Sect + + EMOD +eom EQU * + END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/level1/modules/llscsi.asm Thu Dec 22 18:23:47 2011 +0000 @@ -0,0 +1,970 @@ +******************************************************************** +* llscsi - Low-level SCSI driver +* +* $Id$ +* +* Drives tested with this driver: +* ------------------------------- +* Conner DCP30200 Hard Drive - Sends out a SDTR message immediately, +* which confused the driver. The driver now handles the receipt +* of SCSI messages from the target. +* +* IBM DPES-31080 Hard Drive - Works, but seizes the bus if a +* device ID is referenced on the bus that doesn't exist. +* +* Sony CDU415 2X CD-ROM - Works fine. +* +* Toshiba XM-4101BME 12X CD-ROM - Works fine. +* +* NOTE: A full dsave from the Sony to the IBM was done on 300+ MB +* of data (RTSI RBF CD-ROM) on June 7, 2004 with no problems. +* +* +* Edt/Rev YYYY/MM/DD Modified by +* Comment +* ------------------------------------------------------------------ +* 2004/04/?? Boisy G. Pitre +* Created. +* +* 2004/??/?? Boisy G. Pitre +* RELEASED WITH SUPERDRIVERS 1.0 +* +* 2005/12/02 Boisy G. Pitre +* Now detects MESSAGE IN phase and reads in message codes (ignoring +* the data). The Conner DCP30200 Hard Drive sends out a SDTR message +* immediately, which confused the driver. The driver now handles the +* receipt of messages from the target. +* +* 2005/12/11 Boisy G. Pitre +* Added SS.SQD and SS.DCmd support. +* +* 2005/12/13 Boisy G. Pitre +* Moved SS.VarSect code into RBSuper for performance. +* +* 2006/03/22 Boisy G. Pitre +* Moved SS.VarSect code into RBSuper for performance. +* +* 2008/01/21 Boisy G. Pitre +* Fixed issue in DCmd where Y was not being saved when os9 F$ID was being called. + + NAM llscsi + TTL Low-level SCSI driver + + IFP1 + USE defsfile + USE rbsuper.d + USE scsi.d + ENDC + +tylg SET Sbrtn+Objct +atrv SET ReEnt+rev +rev SET 0 + + +* +* SCSI Delay Constants +* + IFGT Level-1 +BUSYDELAY EQU $FFFF + ELSE +BUSYDELAY EQU $FFFF/2 + ENDC +NUMTRIES EQU 8 + + MOD eom,name,tylg,atrv,start,0 + + ORG V.LLMem +* Low-level driver static memory area +* SCSI Command Packet +* SCSI packet length is 14 bytes +V.SCSICMD RMB 1 +V.SCSILUN RMB 1 +V.SCSIPrm0 RMB 1 +V.SCSIPrm1 RMB 1 +V.SCSIPrm2 RMB 1 +V.SCSIPrm3 RMB 1 +V.SCSIPrm4 RMB 1 +V.SCSIPrm5 RMB 1 +V.SCSIPrm6 RMB 1 +V.SCSIPrm7 RMB 1 + RMB 4 +SCSIPkLn EQU .-V.SCSICMD +V.Retries RMB 1 SCSI command retry counter +V.OS9Err RMB 1 (0 = return OS-9 error code, 1 = return SCSI error code) +V.Turbo RMB 1 turbo flag (0 = regular read, 1 = turbo read) +V.TfrBuf RMB 2 transfer buffer pointer +V.RetryVct RMB 2 retry vector +V.ReadVct RMB 2 normal/turbo read vectoor +V.WriteVct RMB 2 normal/turbo write vector +V.DnsByte RMB 1 copy of PD.DNS from last accessed drive + IFNE D4N1+HDII +V.MPISlot RMB 1 MPI slot +V.MPISave RMB 1 contents of original MPI slot + ENDC +* The Request Sense Packet and Read Capacity return data share the same space +ReqSnPkt EQU . +V.TxBuf EQU . used by DSize +V.R$Err RMB 2 SCSI error code return value +V.UTxBuf EQU . +V.R$Err2 RMB 10 +V.R$AdSns RMB 1 +ReqPkL EQU .-ReqSnPkt length of packet + RMB 3 makes V.TxBuf 16 bytes + +name FCC /ll/ + IFNE TC3 + FCS /tc3/ + ELSE + IFNE KTLR + FCS /ktlr/ + ELSE + IFNE D4N1+HDII + FCS /disto/ + ENDC + ENDC + ENDC + +start bra ll_init + nop + lbra ll_read + lbra ll_write + bra ll_getstat + nop + lbra ll_setstat +* lbra ll_term + +* ll_term +* +* Entry: +* Y = address of device descriptor +* U = address of device memory area +* +* Exit: +* CC = carry set on error +* B = error code +* +ll_term + clrb + rts + +* ll_init +* +* Entry: +* Y = address of device descriptor +* U = address of device memory area +* +* Exit: +* CC = carry set on error +* B = error code +* +ll_init + IFNE D4N1+HDII +* Disto 4-N-1 and HD-II: Get MPI slot select value from descriptor +* and save it in our static storage. + lda IT.MPI,y + anda #$0F preserve *SCS bits only + sta V.MPISlot,u + ENDC + clrb + rts + + +* ll_getstat +* +* Entry: +* Y = address of path descriptor +* U = address of device memory area +* +* Exit: +* CC = carry set on error +* B = error code +* +ll_getstat + ldx PD.RGS,y + lda R$B,x + cmpa #SS.DSize + beq SSDSize + ldb #E$UnkSvc + coma + rts + + +* SS.DSize - Return size information about a device +* +* Entry: B = SS.DSize +* Exit: Carry = 1; error with code in B +* Carry = 0: +* IF B = 0 +* A = Sector Size (1 = 256, 2 = 512, 4 = 1024, 8 = 2048) +* X = Number of Sectors (bits 31-16) +* Y = Number of Sectors (Bits 15-0) +* IF B != 0 +* A = Sector Size (1 = 256, 2 = 512, 4 = 1024, 8 = 2048) +* X = Number of Logical Cylinders +* B = Number of Logical Sides +* Y = Number of Logical Sectors/Track +* +SSDSize + pshs u,y + bsr DSize + bcs ex@ + ldu ,s get path desc in U + ldu PD.RGS,u + std R$D,u + stx R$X,u + sty R$Y,u + clrb +ex@ puls y,u,pc + +* DSize - Get SCSI disk size +* +* Exit: Carry = 1; error with code in B +* Carry = 0: +* IF B = 0 +* A = Sector Size (1 = 256, 2 = 512, 4 = 1024, 8 = 2048) +* X = Number of Sectors (bits 31-16) +* Y = Number of Sectors (Bits 15-0) +* IF B != 0 +* A = Sector Size (1 = 256, 2 = 512, 4 = 1024, 8 = 2048) +* X = Number of Logical Cylinders +* B = Number of Logical Sides +* Y = Number of Logical Sectors/Track +DSize lbsr SCSIPrep do SCSI prep stuff + lda #S$RCAP + sta V.SCSICMD,u + leax V.TxBuf,u + stx V.TfrBuf,u + IFNE D4N1+HDII + lbsr MPIIn + ENDC + lbsr SCSIXfer + bcs ex@ + ldd V.TxBuf+2,u get bits 15-0 of block count + addd #$0001 add 1 to count + std V.TxBuf+2,u resave + bcc b@ + ldd V.TxBuf,u get bits 31-16 + addd #$0001 add 1 + std V.TxBuf,u resave +b@ lda V.TxBuf+6,u + clrb + ldx V.TxBuf,u + ldy V.TxBuf+2,u +ex@ + IFNE D4N1+HDII + lbra MPIOut + ELSE + rts + ENDC + + +* ll_setstat +* +* Entry: +* Y = address of path descriptor +* U = address of device memory area +* +* Exit: +* CC = carry set on error +* B = error code +* +ll_setstat + ldx PD.RGS,y + lda R$B,x + cmpa #SS.SQD + beq StopUnit + cmpa #SS.DCmd + bne n@ + pshs x save pointer to caller registers + bsr DCmd call DCmd + puls x get pointer to caller registers + sta R$A,x save status byte in A +n@ clrb +ex rts + +* Entry: +* R$B = SS.SQD +StopUnit + lbsr SCSIPrep do SCSI prep stuff + lda #S$UNIT + sta V.SCSICMD,u + clr V.SCSIPrm2,u we want to STOP unit +s@ + IFNE D4N1+HDII + lbsr MPIIn + ENDC + lbra SCSIXfer + +noperms comb + ldb #E$FNA + rts + +* Entry: +* X = caller regs +* Y = path descriptor +* +* R$B = SS.DCmd +* R$X = Transfer buffer +* R$Y = SCSI command packet +DCmd +* Fixed bug where Y was not being saved when doing os9 F$ID + pshs y + os9 F$ID get the user ID of the calling process + cmpy #$0000 is it 0 (superuser)? + puls y + bne noperms no, don't allow the call + lbsr SCSIPrep + ldy R$X,x get caller's transfer buffer + sty V.UTxBuf,u save off in mem for later + ldx R$Y,x get ptr to caller's SCSI command buffer + IFGT Level-1 + ldy D.Proc get current process ptr + lda P$Task,y get task # for current process + ldb D.SysTsk get system task # + ldy #SCSIPkLn max size of SCSI command + pshs u save on stack + leau V.SCSICMD,u point to SCSI command buffer in our statics + os9 F$Move copy from caller to temporary task + puls u + bcs ex error copying, exit + ELSE + ldb #SCSIPkLn + leay V.SCSICMD,u +cl@ lda ,x+ + sta ,y+ + decb + bne cl@ + ENDC + ldy V.PORT-UOFFSET,u get hw address (because we overwrite Y earlier) + IFNE D4N1+HDII + lbsr MPIIn + ENDC + inc V.OS9Err,u we want real SCSI errors returned + inc V.CchDirty,u and make cache dirty + leax retry@,pcr + stx V.RetryVct,u +retry@ lbsr SCSISend + IFNE D4N1+HDII + lbcs MPIOut + ELSE + bcs ex + ENDC + IFGT Level-1 + ldx D.Proc get current process ptr + ldb P$Task,x get task # for current process + ENDC + ldx V.UTxBuf,u + +msgloop@ lbsr Wait4REQ wait for REQ to be asserted + bita #CMD command phase? + lbne PostXfr yes, return +io@ bita #INOUT data coming in or going out? + bne in@ branch if coming in... + IFGT Level-1 + os9 F$LDABX + leax 1,x + ELSE + lda ,x+ + ENDC + sta SCSIDATA,y + bra msgloop@ +in@ lda SCSIDATA,y + IFGT Level-1 + os9 F$STABX + leax 1,x + ELSE + sta ,x+ + ENDC + bra msgloop@ + + +* ll_read +* +* Entry: +* Y = address of path descriptor +* U = address of device memory area +* +* Static memory referenced: +* V.CchPSpot = address of spot in cache where physical sector data will go +* sectsize = sector size (0=256,1=512,2=1024,3=2048) +* V.SectCnt = sectors to read +* V.PhysSect = physical sector to start read from +ll_read + IFNE D4N1+HDII + lbsr MPIIn + ENDC + IFNE SIZEMATTERS + bsr SCSIPrep do SCSI prep stuff + bsr MakeRead make read command packet + ldx V.CchPSpot,u + stx V.TfrBuf,u + lbra SCSIXfer + ELSE + leax SCSIReadRetry,pcr + stx V.RetryVct,u + lbsr SCSIPrep do SCSI prep stuff + lbsr MakeRead make read command packet +SCSIReadRetry + lbsr SCSISend + bcs mpiex + bita #CMD + lbne PostXfr + ldb V.SectCnt,u + pshs b +* Set up appropriate read call (regular or turbo) + tst V.Turbo,u + beq reg@ + leax TurboRead,pcr + bra do@ +reg@ leax RegRead256,pcr +do@ stx V.ReadVct,u + ldx V.CchPSpot,u get pointer to physical sector in cache for data in +again@ + ldb V.Log2Phys,u + pshs b +loop@ + jsr [V.ReadVct,u] + dec ,s + bne loop@ + puls b + dec ,s + bne again@ + puls a + lbra PostXfr +mpiex + IFNE D4N1+HDII + lbra MPIOut + ELSE + rts + ENDC + +TurboRead + IFNE H6309 + +* 6309 Turbo READ + ldw #256 + orcc #IntMasks we have to mask interrupts for Level 1 + tfm y,x+ do the transfer + andcc #^IntMasks we have to unmask interrupts for Level 1 + lbsr DeauxDeaux + rts + + ELSE + +* 6809 Turbo READ + lda #16 + pshs a +l2@ lda SCSIDATA,y + ldb SCSIDATA,y + std ,x + lda SCSIDATA,y + ldb SCSIDATA,y + std $02,x + lda SCSIDATA,y + ldb SCSIDATA,y + std $04,x + lda SCSIDATA,y + ldb SCSIDATA,y + std $06,x + lda SCSIDATA,y + ldb SCSIDATA,y + std $08,x + lda SCSIDATA,y + ldb SCSIDATA,y + std $0A,x + lda SCSIDATA,y + ldb SCSIDATA,y + std $0C,x + lda SCSIDATA,y + ldb SCSIDATA,y + std $0E,x + leax 16,x + dec ,s decrement counter + bne l2@ + puls a,pc + ENDC + +RegRead256 + clrb +* +* "Non-Turbo" Read Data from controller +* +* Passed: B = bytes to read +* X = Address of buffer +* Y = Controller Address +* +RegRead +* We wait for REQ in an infinite, faster loop here + lda SCSISTAT,y get SCSI status byte + bita #REQ REQ? + beq RegRead + lda SCSIDATA,y + sta ,x+ + decb + bne RegRead + rts + + + ENDC + + +* Make Read/Write Packet +* Entry: +* A = SCSI command +* V.PhysSect = 3 byte physical sector to read/write +MakeWrite lda #S$WRITEX + fcb $8C skip next two bytes +MakeRead lda #S$READEX +MakeRW sta V.SCSICMD,u put passed SCSI command + lda V.SectCnt,u 'V.SectCnt' logical blocks +* Make SCSI Read/Write 6 byte CDB here +* sta V.SCSIPrm2,u +* lda V.PhysSect,u +* sta V.SCSILUN,u +* ldd V.PhysSect+1,u +* std V.SCSIPrm0,u +* rts +* Make SCSI Read/Write Extended 10 byte CDB here + sta V.SCSIPrm6,u + lda V.PhysSect,u + sta V.SCSIPrm1,u + ldd V.PhysSect+1,u + std V.SCSIPrm2,u + rts + +* Prep for SCSI transfer +* Preserves all regs +* Entry: Y = path descriptor +* Exit: Y = hardware address +SCSIPrep pshs x,d + leax V.SCSICMD,u + ldb #SCSIPkLn +l@ clr ,x+ + decb + bne l@ + ldb PD.DNS,y and DNS byte + stb V.DnsByte,u save in our statics + andb #DNS.TURBO mask out all but turbo bit + stb V.Turbo,u and save state + lda #NUMTRIES get retry count + sta V.Retries,u and reset retry counter + clr V.OS9Err,u we want real SCSI errors returned + ldy V.PORT-UOFFSET,u get hw address + puls x,d,pc + +* Check Transfer Status +* This routine is passed the address of another routine to call in case +* the device is busy or there is an error returned. +* +* Passed: V.RetryVct,u = address of routine to call if SCSI device is busy +PostXfr lbsr GetStatB get transfer status byte + bita #X$BUSY device BUSY? + bne retry@ attempt a retry if so... +chkerr@ bita #X$ERROR error? + beq ok@ branch if not... +* Error occurred.. retry +retry@ dec V.Retries,u decrement retry count + bne jmp@ try again if not at end + IFNE D4N1+HDII + lbsr SCSIErr + lbra MPIOut + ELSE + lbra SCSIErr + ENDC +jmp@ jmp [V.RetryVct,u] +ok@ clrb + IFNE D4N1+HDII + lbra MPIOut + ELSE + rts + ENDC + + +* ll_write +* +* Entry: +* Y = address of path descriptor +* U = address of device memory area +* +* Static memory referenced: +* V.CchPSpot = address of spot in cache where physical sector data is +* sectsize = sector size (0=256,1=512,2=1024,3=2048) +* V.SectCnt = sectors to read +* V.PhysSect = physical sector to start read from +ll_write + IFNE D4N1+HDII + lbsr MPIIn + ENDC + IFNE SIZEMATTERS + bsr SCSIPrep do SCSI prep stuff + bsr MakeWrite make read command packet + ldx V.CchPSpot,u + stx V.TfrBuf,u + ELSE + leax SCSIWriteRetry,pcr + stx V.RetryVct,u + bsr SCSIPrep do SCSI prep stuff + lbsr MakeWrite +SCSIWriteRetry lbsr SCSISend + lbcs mpiex + bita #CMD + bne PostXfr + ldb V.SectCnt,u + pshs b +* Set up appropriate write call (regular or turbo) + tst V.Turbo,u + beq reg@ + leax TurboWrite,pcr + bra do@ +reg@ leax RegWrite,pcr +do@ stx V.WriteVct,u + ldx V.CchPSpot,u +again@ ldb V.Log2Phys,u + pshs b +loop@ jsr [V.WriteVct,u] + dec ,s + bne loop@ + puls b + dec ,s + bne again@ + puls a + bra PostXfr + +TurboWrite + IFNE H6309 + +* 6309 Turbo WRITE +loop@ orcc #IntMasks we have to mask interrupts for Level 1 + ldw #256 + tfm x+,y + andcc #^IntMasks we have to unmask interrupts for Level 1 + lbsr DeauxDeaux + rts + + ELSE + +* 6809 Turbo WRITE + lda #16 + pshs a +l2@ ldd ,x + sta SCSIDATA,y + stb SCSIDATA,y + ldd $02,x + sta SCSIDATA,y + stb SCSIDATA,y + ldd $04,x + sta SCSIDATA,y + stb SCSIDATA,y + ldd $06,x + sta SCSIDATA,y + stb SCSIDATA,y + ldd $08,x + sta SCSIDATA,y + stb SCSIDATA,y + ldd $0A,x + sta SCSIDATA,y + stb SCSIDATA,y + ldd $0C,x + sta SCSIDATA,y + stb SCSIDATA,y + ldd $0E,x + sta SCSIDATA,y + stb SCSIDATA,y + leax 16,x + dec ,s decrement counter + bne l2@ + puls a,pc + + ENDC + +* +* "Non-Turbo" Write Data to controller +* +* Passed: X = Address of data to write +* Y = Controller Address +* +RegWrite clrb +loop@ lda SCSISTAT,y + bita #REQ + beq loop@ + lda ,x+ + sta SCSIDATA,y + decb + bne loop@ + rts + + ENDC + + IFNE D4N1+HDII +* Disto 4-N-1/HD-II: Map in MPI HERE +MPIIn pshs cc,a + lda MPI.Slct get MPI value + sta V.MPISave,u save off in our statics + anda #$F0 preserve CTS slot bits (%1111000) + ora V.MPISlot,u OR in MPI slot of our HW +MPIWrite sta MPI.Slct write out to MPI + puls a,cc,pc + +MPIOut pshs cc,a + lda V.MPISave,u + bra MPIWrite + ENDC + + +* SCSIXfer +* +* Entry: +* Y = hardware address +* U = address of device memory area +* +* Static memory referenced: +* V.TfrBuf,u = address of transfer/receive buffer +SCSIXfer leax retry@,pcr + stx V.RetryVct,u +retry@ bsr SCSISend + bcs sr@ + ldx V.TfrBuf,u +tfr@ lbsr Wait4REQ wait for REQ to be asserted + bita #CMD + lbne PostXfr COMMAND phase... +* If here, we're in DATA PHASE + bita #INOUT data coming in or going out? + bne in@ branch if coming in... +out@ lda ,x+ + sta SCSIDATA,y + bra tfr@ +in@ lda SCSIDATA,y + sta ,x+ + bra tfr@ +sr@ rts + + +* Give up timeslice several times unless this is the system +DeauxDeaux pshs x + IFGT Level-1 + ldx D.Proc get proc descriptor + cmpx D.SysPrc system? + beq WaitDone yep, system cannot sleep + ENDC +* ldx D.AProcQ get active proc queue +* beq WaitDone if empty, return +* ldx #$0001 +* os9 F$Sleep give up timeslice +* ldx D.AProcQ get active proc queue +* beq WaitDone if empty, return + ldx #$0001 + os9 F$Sleep give up timeslice +WaitDone puls x,pc return to caller + +* Get Status Byte from SCSI controller +* Exit: A = status byte +GetStatB bsr Wait4REQ + lda SCSIDATA,y + pshs a + bsr Wait4REQ + clr SCSIDATA,y + puls pc,a + +* SCSI ID table with hi-bit set for SCSI-3 compliance +IDTBL FCB $80+1,$80+2,$80+4,$80+8,$80+16,$80+32,$80+64,128 + +* +* SCSI Packet Send Routine +* +* Sets LUN for SCSI Packet, then sends command packet to controller +* +* Passed: Y = Device Address +* +* Returns: A = SCSI Status byte +* +* Destroys: X +* +SCSISend ldb V.SCSILUN,u get SCSI LUN + andb #%00011111 mask out LUN + stb V.SCSILUN,u + ldb V.DnsByte,u get DNS byte + andb #%11100000 get SCSI LUN from byte + orb V.SCSILUN,u OR with SCSI LUN byte + stb V.SCSILUN,u save off + ldd #BUSY*256 we want /BUSY + bsr StatusWait + bcs ex4 +* BUSY is clear, put initiator/target IDs on bus + lda V.DnsByte,u get DNS byte + anda #$07 mask out all but SCSI IDs + leax IDTBL,pcr point to device ID table + lda a,x get ID value + sta SCSIDATA,y write out to controller + sta SCSISEL,y here too... + ldd #BUSY*256+BUSY we want BUSY + bsr StatusWait + bcs ex4 +* BUSY is set +* Here we send the packet to the controller. +chkok@ leax V.SCSICMD,u point X to SCSI command packet +tfrloop@ bsr Wait4REQ wait for REQ + bita #CMD SCSI CMD bit set? + beq ex4 branch if not... + bita #INOUT INOUT set? + bne ckmsg@ branch if target->initiator + lda ,x+ get byte from SCSI CMD packet + sta SCSIDATA,y write to controller + bra tfrloop@ +ckmsg@ bita #MSG MESSAGE IN (target->initiator) + beq ex4 +* +* MESSAGE IN phase code +* +MSGIn lda SCSIDATA,y extended message? + deca + bne SCSISend nope, restart target initiation + ldb SCSIDATA,y get extended message length +* Note: We ignore extended messages +l@ tst SCSIDATA,y read extended message data + decb + bne l@ + bra SCSISend message read, restart target initiation +ex4 rts + +* +* Loop until REQ bit is set +* +* Passed: Y = Device Address +* +* Returns: A = SCSI Status byte +* +Wait4REQ +loop@ lda SCSISTAT,y get SCSI status byte + bita #REQ REQ? + beq sleep@ + + rts + +sleep@ lbsr DeauxDeaux + bra loop@ + +* Wait for a set of conditions in the status register to be TRUE +* This yields a delay of about 5 seconds. +* +* Entry: Y = HW address +* A = flip (if bit set, that bit is tested) +* B = mask (result must match this byte) +StatusWait + pshs x,d + IFEQ Level-1 + ldb #$02 + ldx #$0000 + ELSE + ldb #$04 + ldx #$0000 + ENDC +l@ lda SCSISTAT,y + anda ,s apply flip + cmpa 1,s compare to mask + bne dec@ branch if not equal (not what we want) + lda SCSISTAT,y + clrb clear carry + bra ok@ +dec@ leax -1,x count down + bne l@ + decb decrement bits 23-16 + bpl l@ if >=0, keep going + comb set carry + ldb #E$NotRdy +ok@ leas 2,s + puls x,pc + +* +* Send a REQSENSE message to the SCSI controller +* +SndMSG lbsr Wait4REQ wait for REQ to be asserted + bita #CMD command phase? + bne ex4 yes, return + beq INorOUT no, check for in/out + rts +INorOUT bita #INOUT data coming in or going out? + bne ComingIn branch if coming in... + lda ,x+ + sta SCSIDATA,y + bra SndMSG +ComingIn lda SCSIDATA,y + sta ,x+ + bra SndMSG + + +* SCSIErr - Attemps a REQUEST SENSE to find a SCSI error +* +* Entry: +* Y = address of hardware +* U = address of device memory area +* +* Exit: +* CC = carry set +* B = error code +* +SCSIErr lda #S$REQSEN REQUEST SENSE command + sta V.SCSICMD,u + clra + clrb + sta V.SCSILUN,u + std V.SCSIPrm0,u + lda #ReqPkL set allocation length + std V.SCSIPrm2,u + lbsr SCSISend send command + bcs ex4 branch if error + leax V.R$Err,u point to return data buffer + bsr SndMSG get response data + lbsr GetStatB + clra + pshs a + lda V.R$Err,u get error code + anda #$7F wipe out hi bit + cmpa #$70 "current" error? + bne L05A3 branch if not... + lda V.R$Err2,u get more detailed error + anda #%00001111 + sta ,s save off stack + lda V.R$AdSns,u get additional sense code +L05A3 tst V.OS9Err,u send OS-9 error? +L05A7 beq L05AD branch if so... + tfr a,b else put SCSI error in B + clr V.OS9Err,u and clear SCSI error flag + bra ErrErr and return with error +* Walk error table to find OS-9 error +L05AD leax >ErrTbl,pcr + ldb #E$Unit +L05B3 tst ,x + beq ErrErr + cmpa ,x++ + blt L05B3 + ldb -1,x +ErrErr coma + puls pc,a + + + +* Error Table - Maps SCSI errors to OS-9 errors +* This table is contructed so that gaps are actually continuations of +* the previous entry. For example, $14 maps to E$Seek, and so does $15 and +* $16. +ErrTbl FCB $01,E$NotRdy + FCB $02,E$Seek + FCB $03,E$Write + FCB $04,E$NotRdy + FCB $06,E$Seek + FCB $10,E$CRC + FCB $11,E$Read + FCB $14,E$Seek + FCB $17,E$CRC + FCB $19,E$IllArg + FCB $1C,E$Read + FCB $1E,E$CRC + FCB $20,E$IllCmd + FCB $21,E$Sect + FCB $25,E$IllArg + FCB $29,E$NotRdy + FCB $00 + + + EMOD +eom EQU * + END +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/level1/modules/rbdesc.asm Thu Dec 22 18:23:47 2011 +0000 @@ -0,0 +1,71 @@ +******************************************************************** +* rbdesc - Device Descriptor Template +* +* $Id$ +* +* Edt/Rev YYYY/MM/DD Modified by +* Comment +* ------------------------------------------------------------------ + + nam rbdesc + ttl Device Descriptor Template + +* Disassembled 98/08/23 17:09:41 by Disasm v1.6 (C) 1988 by RML + + ifp1 + use defsfile + endc + +tylg set Devic+Objct +atrv set ReEnt+rev +rev set $00 + +DNum set 0 + IFNE D35 +Type set TYP.CCF+TYP.3 + ELSE +Type set TYP.CCF+TYP.5 + ENDC +Density set DNS.MFM +Step set STP.6ms +Cyls set 35 +Sides set 1 +Verify set 1 +SectTrk set 18 +SectTrk0 set 18 +Interlv set 3 +SAS set 8 + + mod eom,name,tylg,atrv,mgrnam,drvnam + + fcb DIR.!SHARE.!PEXEC.!PWRIT.!PREAD.!EXEC.!UPDAT. mode byte + fcb HW.Page extended controller address + fdb $FF40 physical controller address + fcb initsize-*-1 initalization table size + fcb DT.RBF device type:0=scf,1=rbf,2=pipe,3=scf + fcb DNum drive number + fcb Step step rate + fcb Type drive device type + fcb Density media density:0=single,1=double + fdb Cyls number of cylinders (tracks) + fcb Sides number of sides + fcb Verify verify disk writes:0=on + fdb SectTrk # of sectors per track + fdb SectTrk0 # of sectors per track (track 0) + fcb Interlv sector interleave factor + fcb SAS minimum size of sector allocation +initsize equ * + + IFNE DD +name fcs /DD/ + ELSE +name fcs /RTST/ + fcb '0+DNum+$80 + ENDC +mgrnam fcs /RBF/ +drvnam fcs /rbtest/ + + emod +eom equ * + end +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/level1/modules/rbsuper.asm Thu Dec 22 18:23:47 2011 +0000 @@ -0,0 +1,791 @@ +******************************************************************** +* rbsuper - RBF Super Caching Device Driver +* +* $Id$ +* +* (C) 2004 Boisy G. Pitre - Licensed to Cloud-9 +* +* RBSuper is the framework for a new type of RBF device driver -- one +* that fetches native-size, or PHYSICAL sectors. A physical sector is +* a sector that is sized to its device. For example, all IDE drives and +* pretty much all SCSI drives have 512 byte sectors; CD-ROMs have 2048 +* byte sectors. +* +* As a high-level driver, this module is responsible for managing +* the cache, verifying writes, etc. +* +* The actual reading and writing of sectors is performed by the +* low-level driver, which can be designed for any device. +* +* Conditionals: +* H6309 - if set, assembles for 6309 +* USECS - if set, uses critical section code (slows down driver) +* HDBDOS - if set, adds code to handle HDB-DOS partitions +* +* Edt/Rev YYYY/MM/DD Modified by +* Comment +* ------------------------------------------------------------------ +* 2004/04/10 Boisy G. Pitre +* Created due to Mark's constant harping about a NitrOS-9 driver for +* the SuperIDE Interface. Here ya go, Marlette. +* +* 2005/12/12 Boisy G. Pitre +* The SS.VarSect call has been moved from the low level driver to rbsuper +* for efficiency. Also it no longer calls SS.DSize every time it is called. +* Instead, it only calls it the first time, then caches the sector size value +* and returns that value on subsequent calls. +* +* 2005/12/13 Boisy G. Pitre +* Employed a trick to "shift" the idea of where the driver's static +* data starts at the start of each entry point. This saves about 200 +* bytes of memory. +* +* 1 2006/08/20 Boisy G. Pitre +* Fixed bug where linking to a non-existent module in Init would cause a crash +* because IOMan calls the Term routine when Init returns an error. Added a simple +* one line test in Term to see if a value was non-zero which would indicate if Init +* +* 2 2008/02/05 Boisy G. Pitre +* Fixed bug where DNS HDB flag was being pulled from PD.TYP byte instead of PD.DNS. +* +* 3 2011/12/22 Boisy G. Pitre +* Made a "fast path" for 256 byte sector devices to read/write directly into PD.BUF +* instead of using the cache, for performance reasons. +* Conditionalized critical section code since it may not be needed, and affects performance. + + NAM rbsuper + TTL RBF Super Caching Device Driver + + IFP1 + USE defsfile + USE rbsuper.d + ENDC + +tylg SET Drivr+Objct +atrv SET ReEnt+rev +rev SET 0 +edition SET 2 + + MOD eom,name,tylg,atrv,start,V.RBSuper + + FCB DIR.+SHARE.+PEXEC.+PREAD.+PWRIT.+EXEC.+UPDAT. + +name FCS /RBSuper/ + FCB edition + +start lbra Init + bra Read + nop + lbra Write + lbra GetStat + lbra SetStat + +* +* Term +* +* Entry: +* U = address of device memory area +* +* Exit: +* CC = carry set on error +* B = error code +* +Term leau UOFFSET,u +* Free memory allocated for cache + lda V.CchSize,u get cache size into A +* Note, the next line fixes a bug where the system would crash when F$Link in Init failed. +* If it fails, V.CchSize will never get set, and since it is set to 0 initally, we assume +* that init failed if V.CchSize is 0 and thus we simply return. + beq ret@ + tfr u,x move statics ptr into X for safety + ldu V.CchAddr,u and load U with cache address + beq nofree@ + os9 F$SRtMem return cache memory to system +nofree@ tfr x,u and restore statics ptr +* Call low-level driver term + ldx V.LLTerm,u + lbsr LLCall +* Unlink low-level driver + IFGT Level-1 + ldx D.Proc get curr proc ptr + ldd D.SysPrc get system process desc ptr + std D.Proc and make current proc + ENDC + ldu V.LLAddr,u get the address of the low-level module + os9 F$Unlink unlink it + IFGT Level-1 + stx D.Proc restore + ENDC +ret@ rts return + +* +* Read +* +* Entry: +* B = MSB of the disk's LSN +* X = LSB of the disk's LSN +* Y = address of path descriptor +* U = address of device memory area +* +* Exit: +* CC = carry set on error +* B = error code +* +Read leau UOFFSET,u + cmpx #$0000 LSN 0? + bne ReadSect branch if not + tstb LSN 0? + bne ReadSect branch if not + bsr ReadSect else read LSN0 + bcs bye if error, return +* Code to deal with copying LSN0 + leax DRVBEG-UOFFSET,u point X to start of drive table + ldb PD.DRV,y get drive number +lsn@ beq CopyLSN0 branch if zero + leax DRVMEM,x else increase X by drive table size + decb decrement drive number + bra lsn@ branch to loop + +* X = drive table pointer for PD.DRV +* Copy DD.SIZ bytes (LSN0) from buffer to drive table +CopyLSN0 EQU * + ldu PD.BUF,y + IFNE H6309 + ldw #DD.SIZ + tfm u+,x+ + ELSE + ldb #DD.SIZ +CpyLSNLp pulu a one cycle less than lda ,u+ + sta ,x+ + decb + bne CpyLSNLp + ENDC +rret rts + + IFNE HDBDOS +* For HDB-DOS, we must add in drive number +* First, multiply drive number in descriptor by $276 (630 sectors), +* then, add the product to the PSect +ComputeHDB + IFNE H6309 + clra + ldb V.HDBDrive,u + muld #$0276 + addw V.PhysSect+1,u + stw V.PhysSect+1,u + adcb V.PhysSect,u + stb V.PhysSect,u + ELSE + leas -4,s make a stack to store product of $276 * DriveNum + lda V.HDBDrive,u get drive number + ldb #$76 + mul + std 2,s + lda V.HDBDrive,u + ldb #$02 + mul + std ,s + clrb + lda 1,s + addd 2,s + std 2,s + bcc f@ + inc ,s +f@ lda ,s + sta 1,s + ldd 2,s + addd V.PhysSect+1,u + std V.PhysSect+1,u + lda 1,s + adca V.PhysSect,u + sta V.PhysSect,u + leas 4,s + ENDC + ENDC +bye rts + +* 256 byte sector device: setup for low level driver to put 256 byte sector directly into PD.BUF +Read256 + lbsr Log2Phys +* We may not have to do this (and disturb the cache as a result) +* lda PD.DRV,y get current drive number +* sta V.LastDrv,u and make this the current drive + lda #1 + sta V.SectCnt,u + ldx PD.BUF,y put address of PD.BUF directly into cache spot + stx V.CchPSpot,u +* Call low-level driver read + ldx V.LLRead,u + lbra LLCall + +* Read Sector +* +* The sector will be read from either the cache or the controller. +* A cache "hit" is verified by two methods: +* 1. Comparing the drive number of the drive for the current path to +* the drive number of the last path -- if they match, we *MAY* +* have a cache hit. If not, we fill the cache +* 2. If #1 matches, then we know the current drive and the last drive +* are the same. We then check the logical sector to see if it is +* in the cache. +* +* Entry: +* Y = address of path descriptor +* U = address of device memory area +* B = Sector bits 23-16 +* X = Sector bits 15-0 +* +ReadSect bsr PreXfr to pre-transfer stuff + bcs bye branch if error + IFNE HDBDOS + tst V.HDBPart,u HDB-DOS partition? + beq NotHDB +* This is the HDB-DOS partition "read" code path. +* As an HDB-DOS partition, we are interested ONLY in reading the first 256 bytes +* regardless of the size of the cache. + lda V.SectSize,u get sector size (0=256,1=512,2=1024,etc) + leax SCTTBL,pcr + lda a,x + sta V.Log2Phys,u set logical sectors per phys + lda #$01 get sector count + sta V.SectCnt,u and store it + sta V.CchDirty,u the cache will ALWAYS be dirty in HDB-DOS mode + lda V.LogSect,u get logical sector stored earlier + sta V.PhysSect,u save off logical sector as physical one + ldd V.LogSect+1,u get logical sector stored earlier + std V.PhysSect+1,u save off logical sector as physical sector + lbsr AddSectorOffset add in partition offset and HDB-DOS drive + bsr ComputeHDB and compute HDB-DOS offset +* Set up the pointer to the buffer + ldx V.CchAddr,u get address of cache + stx V.CchPSpot,u save in current sector pointer +* Call low-level driver + ldx V.LLRead,u + lbsr LLCall + bcs bye + ldx V.CchAddr,u get cache pointer which holds HDB-DOS sector + bra CopyXToPDBUF + ENDC +NotHDB +* New: Dec 20, 2011 +* Fast path opportunity: if sector size is 256 bytes, call LLRead right into PD.BUF + tst V.SectSize,u (0=256 byte sector device) + beq Read256 + bsr ValidateCache + bcs ex@ +* Copy appropriate 256 byte sector from V.CchAddr to PD.BUF,y + lda V.CchSize,u get hi byte of cache size + deca + anda V.LogSect+2,u + clrb + ldx V.CchAddr,u + leax d,x +CopyXToPDBUF pshs y + ldy PD.BUF,y + IFNE H6309 + ldw #256 + tfm x+,y+ + clrb + puls y,pc + ELSE + clr ,-s +next@ ldd ,x++ + std ,y++ + inc ,s + bpl next@ + clrb + puls a,y,pc + ENDC +ex@ rts + +* ValidateCache +* +* Check if the cache is coherent (i.e. contains requested sector). +* If the cache is NOT coherent, it calls 'FillCache' to fill it. +ValidateCache +* We must determine if the currently requested sector is already in cache. +* First, is this drive the same as the last drive that accessed the cache? +* If not, then we need to fill the cache with sectors from the current drive. + tst V.CchDirty,u has cache been initialized? + bne nomatch branch if not + lda PD.DRV,y get current drive + cmpa V.LastDrv,u save as last drive to access cache? + bne nomatch if not, fill cache +* Same drive as last access... is this sector in cache? + ldb V.LogSect,u save off logical sector + cmpb V.CchBase,u compare bits 23-16 + bne nomatch branch if not the same + lda V.LogSect+1,u save off logical sector + ldb V.CchSize,u get hi byte of cache size + decb decrement (e.g. 8=7,4=3,2=1,1=0) + comb invert (e.g. 7=$F8,3=$FC,1=$FE,0=$FF) + andb V.LogSect+2,u mask out cached sectors + cmpd V.CchBase+1,u same as what's in cache? + beq exok@ YES, WE HAVE A CACHE HIT!!! +nomatch bra FillCache no, we must fil the cache +* +* PreXfr +* +* Called at read/write to gather info from path descriptor and +* device descriptor. +PreXfr stb V.LogSect,u save off logical sector + stx V.LogSect+1,u save off logical sector + lda PD.STP,y get possible HDB-DOS drive number + sta V.HDBDrive,u save off in our statics + lda PD.TYP,y + anda #TYPH.SSM lob off all but sector size bits +* SmartCache - check if our current cache can accommodate this sector size + cmpa V.SectSize,u do we need to expand? + bls no@ branch if not +* Yes, we need to free our current cache mem and alloc more + pshs a,u save regs + ldd V.CchSize,u get current cache size + ldu V.CchAddr,u and cache pointer + beq nofree@ + os9 F$SRtMem return that memory +nofree@ puls a,u restore regs + lbsr ExpandCache go expand cache + bcs ex@ and branch if error + sta V.SectSize,u save new sector size +no@ + lda PD.DNS,y get DNS byte + anda #DNS.HDB isolate HDB-DOS flag + sta V.HDBPart,u and save state +exok@ clrb clear carry + rts return +ex@ clr V.SectSize,u clear sector size to force realloc + orcc #Carry set carry (indicates error) + rts return + +* FillCache +* +* Fill the cache with sectors from the device. +* +* Destroys: A, B, X +FillCache + lda V.LogSect,u get logical sector bits 23-16 + sta V.CchBase,u save as cached base + lda V.LogSect+1,u save off logical sector + ldb V.CchSize,u get hi byte of cache size (1, 2, 4 or 8) + decb decrement (e.g. 8=7,4=3,2=1,1=0) + comb invert (e.g. 7=$F8,3=$FC,1=$FE,0=$FF) + andb V.LogSect+2,u mask out cached sectors + std V.CchBase+1,u save as cached base + lbsr Log2Phys convert logical sectors to physical + lda PD.DRV,y get current drive number + sta V.LastDrv,u and make this the currently cached drive +* Set up the transfer + ldb V.CchSize,u get upper 8 bits of cache size + lda V.SectSize,u get sector size (0=256,1=512,2=1024,etc) + leax SCTTBL,pcr + lda a,x + sta V.Log2Phys,u + lda V.SectSize,u get sector size (0=256,1=512,2=1024,etc) + beq ok@ +lsr@ lsrb divide by 2 + deca decrement + bne lsr@ else divide again +ok@ stb V.SectCnt,u save sector count + decb + comb + andb V.PhysSect+2,u + stb V.PhysSect+2,u +* Set up the pointer to the buffer + ldx V.CchAddr,u get pointer to big buffer + stx V.CchPSpot,u save in current sector pointer +* Call low-level driver read + ldx V.LLRead,u + bsr LLCall + bcs ex@ + clr V.CchDirty,u cache is no longer dirty + clrb + rts +ex@ stb V.CchDirty,u store error code as dirty flag + rts + + +SCTTBL FCB 256/256 + FCB 512/256 + FCB 1024/256 + FCB 2048/256 + +* GetStat/SetStat +* +* Entry: +* R$B = function code +* Y = address of path descriptor +* U = address of device memory area +* +* Exit: +* CC = carry set on error +* B = error code +* +SetStat leau UOFFSET,u + ldx V.LLStSt,u + bra LLCall + +SSVarSect ldb PD.DRV,y get drive number + leax V.SSCache,u point to sector size cache table + abx + lda ,x get sector size + bne go2@ if not zero, use that value + pshs x + ldx PD.RGS,y + pshs x + leas -R$Size,s + sts PD.RGS,y + lda #SS.DSize + sta R$B,s + bsr gs2 make a call to low level driver's SS.DSize +* Be sure that no instructions from here to the bcs modify carry + lda R$A,s + leas R$Size,s + puls x + stx PD.RGS,y + puls x + bcs ex@ + cmpa #8 2048 byte sector? + beq go@ + lsra else shift right + FCB $8C skip next two bytes (cmpx...) +go@ lda #3 + sta ,x save newly acquired value off into cached size table +go2@ pshs a + lda PD.TYP,y + anda #^TYPH.SSM + ora ,s+ +* Boisy's Notes 3/27/06: +* Notice that we save the true sector size of the device in the PD.TYP byte of +* the path descriptor EACH TIME SS.VarSect is called. This is important, +* because it alleviates the user from having to set this value in the device +* descriptor in a situation where the device being accessed has a larger sector +* size than what is in the device descriptor. +* +* Note that the value in the device descriptor IS used to initially determine +* the size of the cache at INIT time since we haven't even talked to the +* controller at that time yet to query it for its size. +* sta PD.TYP,y and in path descriptor + clrb +ex@ rts + + +GetStat leau UOFFSET,u + ldx PD.RGS,y get registers + ldb R$B,x get caller's B + cmpb #SS.VarSect + beq SSVarSect + +gs2 ldx V.LLGtSt,u + +* Entry: Y = path desc ptr +* U = statics ptr +* X = address of routine to call +LLCall + IFEQ USECS-1 + pshs a preserve A for duration of csacq_wait + lda #255 wait the maximum number of counts + bsr csacq_wait acquire the critical section + tsta test A for zero + puls a restore A + beq cserr return if A was zero (semaphore wasn't acquired) + ENDC + pshs u,y save U and Y + jsr ,x call low level routine + puls y,u restore U and Y + + IFEQ USECS-1 +* Critical Section Release - clear the critial section to zero, allowing others to use it +csrel pshs cc preserve CC + clr V.LLSema,u clear critical section + puls cc,pc restore CC and return +cserr comb set the carry + ldb #111 and load B with error indicating a semaphore timeout + ENDC + rts + + IFEQ USECS-1 +* Critical Section Acquire With Wait +* +* Entry: +* A = number of times to check before giving up +* +* Exit: +* A = status (>0 = Critical section acquired, 0 = Critical section not acquired) +* +csacq_wait pshs cc save CC on stack + orcc #IntMasks mask interrupts + tst V.LLSema,u does someone already have the critical section? + bne w@ if so, then branch + inc V.LLSema,u else claim critical section (0->1) +e@ puls cc,pc restore CC and return +w@ deca decrement our timeout counter + beq e@ if zero, we've timed out, return + puls cc give interrupts a chance to breathe + IFGT Level-1 +* Give up timeslice unless this is the system + pshs x + ldx D.Proc get proc descriptor + cmpx D.SysPrc system? + beq wd@ yep, system cannot sleep +* ldx D.AProcQ get active proc queue +* beq wd@ if empty, return + ldx #$0001 + os9 F$Sleep give up timeslice +wd@ puls x return to caller + ENDC + bra csacq_wait and try again + ENDC + + +* Log2Phys - Convert logical sector to physical sector +* +* Stores V.PhysSect,u from V.LogSect,u based on V.SectSize,u +* Also adds IT.SOFF1-IT.SOFF3 to V.PhysSect,u for partitioning. +* Results are placed in V.PhysSect,u +Log2Phys lda V.LogSect,u + sta V.PhysSect,u + ldd V.LogSect+1,u + std V.PhysSect+1,u + lda V.SectSize,u + beq AddSectorOffset +DivBy2 lsr V.PhysSect,u + ror V.PhysSect+1,u + ror V.PhysSect+2,u + deca + bne DivBy2 +* This routine adds the 3 byte sector offset in the +* device descriptor to the physical sector. +AddSectorOffset + ldx PD.DEV,y + ldx V$DESC,x + ldd IT.SOFF2,x + addd V.PhysSect+1,u + std V.PhysSect+1,u + lda IT.SOFF1,x + adca V.PhysSect,u + sta V.PhysSect,u +logex rts + + +* 256 byte sector device: setup for low level driver to put 256 byte sector directly into PD.BUF +Write256 + bsr Log2Phys +* We may not have to do this (and disturb the cache as a result) +* lda PD.DRV,y get current drive number +* sta V.LastDrv,u and make this the current drive + lda #1 + sta V.SectCnt,u + ldx PD.BUF,y put address of PD.BUF directly into cache spot + stx V.CchPSpot,u +* Call low-level driver read + ldx V.LLWrite,u + bra LLCall + +* Write +* +* Entry: +* B = MSB of the disk's LSN +* X = LSB of the disk's LSN +* Y = address of path descriptor +* U = address of device memory area +* +* Exit: +* CC = carry set on error +* B = error code +* +Write leau UOFFSET,u + lbsr PreXfr to pre-transfer stuff + bcs logex branch if error + IFNE HDBDOS + lda V.HDBPart,u HDB-DOS partition? + beq h@ +* HDB-DOS partition code path + sta V.CchDirty,u cache is dirty + lda V.SectSize,u get sector size (0=256,1=512,2=1024,3=2048) + leax SCTTBL,pcr + lda a,x + sta V.Log2Phys,u set logical sectors per phys + lda V.LogSect,u + sta V.PhysSect,u + ldd V.LogSect+1,u + std V.PhysSect+1,u + bsr AddSectorOffset add in partition offset and HDB-DOS drive + lbsr ComputeHDB and compute HDB-DOS offset + ldx PD.BUF,y get path desc buffer + stx V.CchPSpot,u we write directly from PD.BUF + bra writeit + ENDC +* New: Dec 20, 2011 +* Fast path opportunity: if sector size is 256 bytes, call LLRead right into PD.BUF +h@ + tst V.SectSize,u (0=256 byte sector device) + beq Write256 + lbsr ValidateCache + bcs logex +* Copy appropriate 256 byte sector from PD.BUF,y to V.CchAddr,u +* Determine where in the cache we copy this 256 byte sector + bsr Log2Phys compute physical sector from logical sector + lda V.CchSize,u get hi byte of cache size + deca + anda V.LogSect+2,u + clrb + ldx V.CchAddr,u + leax d,x + stx V.CchLSpot,u save for possible verify later + pshs y save path desc for now + ldy PD.BUF,y + IFNE H6309 + ldw #256 + tfm y+,x+ + puls y + ELSE + clr ,-s +loop@ ldd ,y++ + std ,x++ + inc ,s + bpl loop@ + puls a,y + ENDC +* Now that sector is copied, determine where in cache we start + lda V.LogSect+2,u get logical sector bits 7-0 + leax MASKTBL,pcr point to base of cache + ldb V.SectSize,u get sector size in B + anda b,x + pshs a + lda V.CchSize,u get upper 8 bits of cache size + deca + anda ,s+ + clrb + ldx V.CchAddr,u point to base of cache + leax d,x + stx V.CchPSpot,u +* Call low-level driver write routine +writeit lda #$01 + sta V.SectCnt,u + ldx V.LLWrite,u + lbsr LLCall +* If verify flag is on, read back and compare + tst PD.VFY,y verify flag set? + bne ex@ if so, we don't verify -- just exit +* Read back physical sector into cache + tst V.HDBPart,u HDB-DOS partition? + beq o@ +* If in HDB-DOS mode, we simply place the base address of the cache into +* V.CchPSpot... and V.CchLSpot for later verify + ldx V.CchAddr,u + stx V.CchPSpot,u + stx V.CchLSpot,u +o@ lda #$01 + sta V.SectCnt,u + ldx V.LLRead,u + lbsr LLCall +* Now compare PD.BUF to sector in cache just re-read + ldx V.CchLSpot,u get spot in cache where 256 byte sector is. + ldy PD.BUF,y get pointer to buffer + clra +a@ ldb ,x+ get byte in cache + cmpb ,y+ compare against byte in PD.BUF + bne err@ + deca + bne a@ +ex@ clrb + rts +err@ comb + ldb #E$Write + stb V.CchDirty,u make cache dirty due to error + rts + +* +* Init +* +* Entry: +* Y = address of device descriptor +* U = address of device memory area +* +* Exit: +* CC = carry set on error +* B = error code +* +Init pshs y save device descriptor ptr on stack + ldb #DrvCount get maximum drives supported + stb V.NDRV,u save in our device memory + leax DRVBEG,u point X to the drive tables + lda #$FF +* Invalidate V.NDRV drive tables +drvx sta DD.TOT,x + sta DD.TOT+1,x + sta DD.TOT+2,x + leax DRVMEM,x point to next drive table + decb decrement counter + bne drvx if not zero, continue +* Link to low-level driver + ldd IT.LLDRV,y point to name in descriptor + leax d,y point to name in descriptor + pshs u + IFGT Level-1 + ldd D.Proc get curr proc ptr + pshs d save on stack + ldd D.SysPrc get system process desc ptr + std D.Proc and make current proc + ENDC + lda #Sbrtn+Objct + os9 F$Link link to it + IFGT Level-1 + puls x get curr proc ptr + stx D.Proc restore + ENDC + tfr u,x transfer module address to X + puls u restore U + leau UOFFSET,u + bcs ret@ + stx V.LLAddr,u else save module address +* setup entry points to low-level module + leax V.LLInit,u + lda #6 number of entry points +l@ sty ,x++ + leay 3,y + deca + bne l@ +* Call low-level driver init + ldy ,s grab path desc ptr + ldx V.LLInit,u + lbsr LLCall + bcc r@ +ret@ puls y,pc +* Allocate cache memory +r@ lda IT.TYP,y get type byte + anda #TYPH.SSM mask out all but sector size +* Added Dec 20, 2011: save off to V.SectSize (never got initialized until now!) + sta V.SectSize,u clear out V.SectSize + puls y +* Fall through to ExpandCache + +* Entry: A = cache size to expand to (1 = 512, 2 = 1024, 3 = 2048) +* Exit: D is destroyed +* Note: any previously allocated cache memory must have been +* freed before this call! +* +ExpandCache + pshs a,x + leax CCHTBL,pcr + lda a,x get 1, 2, 4 or 8 + sta V.CchDirty,u make cache dirty since we will expand it + clrb + std V.CchSize,u save cache size (256, 512, 1024 or 2048) + tfr u,x + os9 F$SRqMem allocate cache memory + stu V.CchAddr,x save cache ptr + tfr x,u restore mem pointer +ex@ puls a,x,pc + + +CCHTBL FCB 256/256 + FCB 512/256 + FCB 1024/256 + FCB 2048/256 + +MASKTBL FCB $07,$06,$04,$00 + + EMOD +eom EQU * + END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/level1/modules/superdesc.asm Thu Dec 22 18:23:47 2011 +0000 @@ -0,0 +1,206 @@ +******************************************************************** +* SuperDesc - Super Driver Device Descriptor Template +* +* $Id$ +* +* RBSuper Defined Offsets +* +* IT.STP (offset $14) +* Bit Meaning +* --- --------------------------------------------------------------- +* 7-0 HDB-DOS Drive Number (useful only if HDB-DOS bit set in IT.DNS) +* +* IT.TYP (offset $15) +* Bit Meaning +* --- --------------------------------------------------------------- +* 7 Hard Disk: 1 = hard disk +* 6 Fudge LSN0: 0 = OS-9 disk, 1 = non-OS-9 disk +* 5 Undefined +* 4 Drive Size Query (1 = yes, 0 = no) +* 2-3 Undefined +* 0-1 Sector Size (0 = 256, 1 = 512, 2 = 1024, 3 = 2048) +* +* IT.DNS (offset $16) for SCSI Low Level Driver +* Bit Meaning +* --- --------------------------------------------------------------- +* 5-7 SCSI Logical Unit Number of drive (0-7) (ignored if bit 3 is 1) +* 4 Turbo Mode: 1 = use accelerated handshaking, 0 = standard +* 3 HDB-DOS Partition Flag +* 0-2 SCSI ID of the drive or controller (0-7) +* +* IT.DNS (offset $16) for IDE Low Level Driver +* Bit Meaning +* --- --------------------------------------------------------------- +* 4-7 Undefined +* 3 HDB-DOS Partition Flag +* 1-2 Undefined +* 0 IDE ID (0 = master, 1 = slave) +* +* Edt/Rev YYYY/MM/DD Modified by +* Comment +* ------------------------------------------------------------------ +* 0 2004/04/08 Boisy G. Pitre +* Created. +* +* 0 2005/11/27 Boisy G. Pitre +* Added IT.MPI value to descriptor. +* +* 0 2005/12/08 Boisy G. Pitre +* Reserved two bits in IT.TYP for llscsi. + + NAM SuperDesc + TTL Super Driver Device Descriptor Template + +* Super Driver specific fields +ITDRV SET $00 +ITSTP SET $00 +ITTYP SET $81 +ITDNS SET $00 + +ITSOFS1 SET $00 +ITSOFS2 SET $00 +ITSOFS3 SET $00 + +* Geometry for an EZ-135 +Sides SET $40 +Cyls SET $007f +SectTrk SET $0020 +SectTrk0 SET $0020 +Interlv SET $01 +SAS SET $08 + + IFP1 + USE defsfile + USE rbsuper.d + IFNE IDE + USE ide.d + ELSE + USE scsi.d + ENDC + ENDC + +tylg SET Devic+Objct +atrv SET ReEnt+rev +rev SET $09 + + MOD eom,name,tylg,atrv,mgrnam,drvnam + + IFNE CDROM + FCB DIR.+SHARE.+PEXEC.+PREAD.+EXEC.+READ. + ELSE + FCB DIR.+SHARE.+PEXEC.+PREAD.+PWRIT.+EXEC.+UPDAT. + ENDC + FCB HW.PAGE extended controller address + FDB SDAddr physical controller address + FCB initsize-*-1 initilization table size + FCB DT.RBF device type:0=scf,1=rbf,2=pipe,3=scf + FCB ITDRV drive number + FCB ITSTP step rate + FCB ITTYP drive device type + FCB ITDNS media density + FDB Cyls number of cylinders (tracks) + FCB Sides number of sides + FCB $01 verify disk writes:0=on + FDB SectTrk # of sectors per track + FDB SectTrk0 # of sectors per track (track 0) + FCB Interlv sector interleave factor + FCB SAS minimum size of sector allocation + FCB 0 IT.TFM + FDB 0 IT.Exten + FCB 0 IT.STOff +* Super Driver specific additions to the device descriptor go here +* NOTE: These do NOT get copied into the path descriptor; they +* cannot due to the fact that there is simply NO ROOM in +* the path descriptor to do so. The driver must access +* these values directly from the descriptor. + FCB ITSOFS1 (IT.WPC) + FCB ITSOFS2 (IT.OFS) + FCB ITSOFS3 +initsize EQU * + FDB lldrv (IT.RWC) + FCB SDMPI (IT.MPI) + + IFNE NULL +name FCC /NULL/ + FCB ITDRV+$B0 + ELSE + IFNE DD +name FCS /DD/ + ELSE + IFNE DRIVEWIRE +name FCC /X/ + IFNE HB + FCS /H/ + ELSE + FCB ITDRV+$B0 + ENDC + ELSE + IFNE IDE +name FCC /I/ + IFNE HB + FCS /H/ + ELSE + FCB ITDRV+$B0 + ENDC + ELSE + IFNE SD +name FCC /SD/ + IFNE HB + FCS /H/ + ELSE + FCB ITDRV+$B0 + ENDC + ELSE +name FCC /S/ + IFNE HB + FCS /H/ + ELSE + FCB ITDRV+$B0 + ENDC + ENDC + ENDC + ENDC + ENDC + ENDC + +mgrnam FCS /RBF/ +drvnam FCS /rbsuper/ +lldrv EQU * + IFNE NULL + FCS /llnull/ + FCB 0 + ELSE + IFNE DRIVEWIRE + FCS /lldw/ + FCB 0,0,0 + ELSE + IFNE TC3+SB + FCS /lltc3/ + FCB 0,0 + ELSE + IFNE KTLR + FCS /llktlr/ + FCB 0 + ELSE + IFNE HDII+D4N1 + FCS /lldisto/ + ELSE + IFNE IDE + FCS /llide/ + FCB 0,0 + ELSE + IFNE SD + FCS /llsd/ + FCB 0,0,0 + ENDC + ENDC + ENDC + ENDC + ENDC + ENDC + ENDC + + + EMOD +eom EQU * + END
--- a/level2/coco3/modules/makefile Tue Oct 04 15:11:45 2011 +0000 +++ b/level2/coco3/modules/makefile Thu Dec 22 18:23:47 2011 +0000 @@ -15,12 +15,15 @@ CLOCKSOFT = -aRTCSoft=1 CLOCKMESSEMU = -aRTCMessEmu=1 CLOCKJVEMU = -aRTCJVEmu=1 +TC3FLAGS = $(AFLAGS) -aTC3=1 $(FLAGS) +IDEFLAGS = $(AFLAGS) -aIDE=1 $(FLAGS) DEPENDS = ./makefile -TPB = ../../3rdparty/booters +TPB = $(3RDPARTY)/booters BOOTERS = boot_1773_6ms boot_1773_30ms \ - boot_burke boot_rampak boot_wd1002 boot_dw3 boot_dw3_becker + boot_burke boot_rampak boot_wd1002 boot_dw3 boot_dw3_becker \ + boot_tc3 boot_ide BOOTTRACK = rel_32 rel_40 rel_80 rel_32_50hz rel_40_50hz rel_80_50hz $(BOOTERS) krn KERNEL = krnp2 krnp3_perr krnp4_regdump SYSMODS = ioman init sysgo_h0 sysgo_dd @@ -38,8 +41,11 @@ ddd0_35s.dd ddd0_40d.dd ddd0_80d.dd \ rammer.dr r0_8k.dd r0_96k.dd r0_128k.dd r0_192k.dd \ ddr0_8k.dd ddr0_96k.dd ddr0_128k.dd ddr0_192k.dd md.dd \ - ddx0.dd x0.dd x1.dd x2.dd x3.dd - + ddx0.dd x0.dd x1.dd x2.dd x3.dd \ + rbsuper.dr lltc3.dr llide.dr \ + ddi0_ide.dd i0_ide.dd i1_ide.dd ih_ide.dd \ + dds0_tc3.dd s0_tc3.dd s1_tc3.dd s2_tc3.dd s3_tc3.dd s4_tc3.dd \ + s5_tc3.dd s6_tc3.dd sh_tc3.dd SCF = scf.mn \ vtio.dr vrn.dr scbbp.dr scbbt.dr scdwp.dr sspak.dr sc6551.dr \ @@ -86,21 +92,40 @@ $(CP) kernel/$@ . # Special cases +# TC^3 SCSI Booter +boot_tc3: boot_scsi.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) + +# SuperIDE/Glenside IDE Booter +boot_ide: boot_ide.asm + $(AS) $(ASOUT)$@ $< $(IDEFLAGS) + +# DriveWire 3 Becker Booter boot_dw3_becker: boot_dw3.asm $(AS) $< $(ASOUT)$@ $(AFLAGS) -aBECKER=1 +# DriveWire 3 Becker Submodule dw3_becker.sb: dw3.asm $(AS) $< $(ASOUT)$@ $(AFLAGS) -aBECKER=1 +# CoGrf/CoVDG Modules cogrf.io: cowin.asm $(AS) $< $(ASOUT)$@ $(AFLAGS) -aCoGrf=1 +covdg.io: covdg.asm + $(AS) $(AFLAGS) $(ASOUT)$@ $< -aCOCO2=1 + +covdg_small.io: covdg.asm + $(AS) $(AFLAGS) $(ASOUT)$@ $< + +# Disto SC-II Drivers rb1773_scii_ff74.dr: rb1773.asm $(AS) $< $(ASOUT)$@ $(AFLAGS) -aSCII=1 rb1773_scii_ff58.dr: rb1773.asm $(AS) $< $(ASOUT)$@ $(AFLAGS) -aSCII=1 -aSCIIALT=1 +# REL Modules rel_32: rel.asm $(AS) $< $(ASOUT)$@ $(AFLAGS) -aWidth=32 @@ -119,18 +144,28 @@ rel_80_50hz: rel.asm $(AS) $< $(ASOUT)$@ $(AFLAGS) -aWidth=80 -aTkPerSec=50 +# Floppy Booters boot_1773_6ms: boot_1773.asm $(AS) $< $(ASOUT)$@ $(AFLAGS) -aSTEP=0 boot_1773_30ms: boot_1773.asm $(AS) $< $(ASOUT)$@ $(AFLAGS) -aSTEP=3 +# SysGo Modules sysgo_dd: sysgo.asm $(AS) $< $(ASOUT)$@ $(AFLAGS) -aDD=1 sysgo_h0: sysgo.asm $(AS) $< $(ASOUT)$@ $(AFLAGS) +# TC^3 SCSI Driver +lltc3.dr: llscsi.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) + +# IDE Driver +llide.dr: llide.asm + $(AS) $(ASOUT)$@ $< $(IDEFLAGS) + # Floppy descriptors SSDD35 = -aCyls=35 -aSides=1 -aSectTrk=18 -aSectTrk0=18 \ -aInterlv=3 -aSAS=8 -aDensity=1 @@ -268,6 +303,47 @@ x3.dd: dwdesc.asm $(AS) $< $(ASOUT)$@ $(AFLAGS) -aDNum=3 +# TC^3 SCSI Descriptors +dds0_tc3.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) $(ID0) -aDD=1 + +s0_tc3.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) $(ID0) $(SCSI_HD) + +s1_tc3.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) $(ID1) $(SCSI_HD) + +s2_tc3.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) $(ID2) $(SCSI_HD) + +s3_tc3.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) $(ID3) $(SCSI_HD) + +s4_tc3.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) $(ID4) $(SCSI_HD) + +s5_tc3.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) $(ID5) $(SCSI_HD) + +s6_tc3.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) $(ID6) $(SCSI_HD) + +sh_tc3.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(TC3FLAGS) $(HDBDOS) + +# IDE Descriptors +ddi0_ide.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(IDEFLAGS) $(MASTER) -aDD=1 + +i0_ide.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(IDEFLAGS) $(MASTER) + +i1_ide.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(IDEFLAGS) $(SLAVE) + +ih_ide.dd: superdesc.asm + $(AS) $(ASOUT)$@ $< $(IDEFLAGS) $(HDBDOS) + # RFM descriptors ddy0.dd: rfmdesc.asm $(AS) $< $(ASOUT)$@ $(AFLAGS) -aDD=1 -aDNum=0 @@ -284,13 +360,6 @@ y3.dd: rfmdesc.asm $(AS) $< $(ASOUT)$@ $(AFLAGS) -aDNum=3 -# VDGInt Modules -covdg.io: covdg.asm - $(AS) $(AFLAGS) $(ASOUT)$@ $< -aCOCO2=1 - -covdg_small.io: covdg.asm - $(AS) $(AFLAGS) $(ASOUT)$@ $< - # Clocks clock_60hz: clock.asm $(AS) $(AFLAGS) $(ASOUT)$@ $< -aPwrLnFrq=60