 lib environment
 lib bfhdr
 lib dtab
 lib macdefs
 data
 sttl OMTI 5" Winchester Drivers
 pag
 name omtidrvr
 global omtiint,omtidvn,omticlose,omtiopen,omtisto

PRT_DCT set 1 Print DCT when initializing
PRT_ERR set 1 Print I/O Errors
PRT_REQ set 1 Print I/O Requests
PRT_SWP set 0 Print Swap transactions

*
* OMTI 5" Winchester drivers
*

*
* driver equates and addresses
*
OMTITDR equ $00 Test Drive Ready
OMTIREC equ $01 Recalibrate (reseek to 0)
OMTIRSS equ $03 Request Sense Status
OMTIFDR equ $04 Format Drive
OMTIFTR equ $06 Format Track
OMTIRDS equ $08 Read Sector
OMTIWRS equ $0A Write Sector
OMTIIDC equ $C2 Initialize Drive Characteristics
OMTI_FD equ 17 Format Drive (special count)
OMTI_FT equ 17*2 Format Track
*
winesw fdb 0 OMTI Error Status Word
winsbf rzb 4 OMTI Sense Status Buffer
winirs fcb 0 OMTI Controller RESET
winopt fcb 0,0 winchester open table
windtyp fdb win_DC0,win_DC1 drive characteristics tables
win_DC0 rzb 11 Drive Characteristics tables
win_DC1 rzb 11
win_DCn fcb $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
winotyp fdb win_DCn previous drive type
windrv fdb $FFFF current drive select for OMTI
wintmp fcb 0 space to "read" device size
winsdn fdb 0 saved device #
BDtable fdb 0 Block Device Table address
winswpt fdb 0 swap table pointer
*
*  OMTI Command Block (DCB)
*
OMTIcmd fcb 0 OMTI 20C Command
OMTIlun fcb 0 Drive Select
OMTIadr fcb 0,0 Sector Address
OMTIcnt fcb 0 Sector Count
OMTIctl fcb 0 Control Flags (constant)
*
* Device parameters control block
*
DP_TABLE  equ *
DP_width  fcb 0 Step Pulse Width
DP_period fcb 0 Time between pulses
DP_mode   fcb 0 Stepping mode (0->buffered)
DP_heads  fcb 0 Number of heads (-1)
DP_cyls   fdb 0 Number of cylinders (-1)
DP_wsi    fcb 0 Write Precomp cylinder
DP_type   fcb 0 Drive type
DP_sectrk fcb 0 Sectors/Track
          fcb 0 ** Filler **
*
* Seek table - Used to translate Xebec seeks to OMTI
*
seek_tbl equ *
 fcb $09,$3C 0
 fcb $09,$3C 1
 fcb $09,$3C 2
 fcb $09,$3C 3
 fcb $02,$04 4
 fcb $02,$00 5
 fcb $02,$00 6
 fcb $02,$00 7

*
* disk controller definitions
*
OMTIBSY equ %00001000
OMTIREQ equ %00000001 Controller Request Data
*
* open the winchester disk drive - insure the device is online, etc.
*
omtiopen
 std winsdn save device #
 lbsr omtidvn drive select
 tst winopt,x already open?
 beq omtiop1 no - go do open
 inc winopt,x yes - bump open count
 lbra omtirts all done
omtiop1 inc winopt,x set open status
 lda #8 set up default device characteristics = ST-506
 ldb winsdn+1
 subb #OMTIminor
 lbsr cpy_DCT
 pshs x save device offset
 ldx #1 read SIR
 ldy #0
 ldd winsdn restore device #
 lda #OMTImajor make sure block read
 jsr rdbuf
 lda bfflag,y get flags
 bita #BFERR error?
 bne omtiop8 yes - return error
 pshs y save buffer pointer
 ldx 0,s get buffer header
 ldy #wintmp no - read drive type
 ldu #sdenf from "density" byte in SIR
 ldd #1
 jsr cpybts
 lda wintmp check for DCT index/data in SIR
 cmpa #$FF
 bne 10f
 ldx 0,s it is - read actual table from SIR
 ldd winsdn compute table address
 subb #OMTIminor
 aslb
 ldy #windtyp
 ldy b,y
 ldu #swinc
 ldd #11
 jsr cpybts
 bra 20f
10 lda wintmp pick up size field
 cmpa #MAXDCT legal DCT index?
 bls 15f yes - jump (OK)
 lda #8 no - assume ST-506
15 ldb winsdn+1 compute table address
 subb #OMTIminor
 jsr cpy_DCT copy device table
20 puls y restore buffer pointer
 jsr freebf free buffer
 puls x
 ldx #$FFFF force controller to be reconfigured
 stx windrv
 rts device opened OK
omtiop8 jsr freebf release buffer
 puls x restore device index
omtiop9 lda #EIO indicate device offline
 sta uerror stuff into user error flag
 clr winopt,x clear open status
omtirts rts return
*
* Copy a device characteristics table from
* the "Winchesters" table to the internal
* drive type table
*    A - Drive type index
*    B - Relative device number (minor)
*
cpy_DCT pshs d,x,y,u
 aslb
 ldy #windtyp
 ldy b,y
 ldu winotyp reset "old" known configuration
 ldx #MW_DCT compute device characteristics table
 leax a,x
 asla A*8
 asla
 asla
 leax a,x offset*9
 ldb #9
17 lda ,x+ copy table
 sta ,y+
 clr ,u+
 decb
 bne 17b
 clr ,y+ ** filler **
 clr ,y+
 ldx #$FFFF force controller to be reconfigured
 stx windrv
 puls d,x,y,u,pc return
*
*  Set up controller
*
omtiidc pshs d,x,y save registers
 cmpx windrv same drive as last operation?
 lbeq omtiid9 yes - exit
 tfr x,d -- compute table index
 leay d,x 2*X
 ldy windtyp,y
 pshs y save it
 ldx winotyp compare with last table sent
 ldb #11
10 lda ,x+
 cmpa ,y+
 bne 15f jump if not the same
 decb
 bne 10b continue
 puls y clean up stack
 lbra omtiid9 exit - no need to reconfigure
15 ldy 0,s no match - copy table
 ldx winotyp
 ldb #11
17 lda ,y+
 sta ,x+
 decb
 bne 17b
*-- Reformat info for OMTI Assign Disk Parameters command
 puls y restore table address
 ldd ,y++ get # cylinders
 subd #1
 std DP_cyls
 lda ,y+ get # heads
 deca
 sta DP_heads
 ldd ,y++ Reduced write
 ldd ,y++ Write precomp
 anda #$03
 stb DP_wsi
 sta DP_type
 tst ,y+ skip burst length
 lda ,y+ get seek rate
 anda #$07
 lsla
 ldx #seek_tbl
 leax a,x
 lda ,x+
 sta DP_width
 lda ,x+
 sta DP_period
 lda ,y+ get imbedded servo indicator
 beq 18f
 lda #%00110000
 ora DP_type
 sta DP_type
18
 if PRT_DCT
 bsr prt_dct
 endif
 lda #OMTIIDC Initialize Drive Characteristics
 sta OMTIcmd
 lda #1 no DMA/IRQ
 lbsr omticn send command
omtiid2 lbsr omtiwt wait for READY
 bitb #$14 wait for REQ=1, I/O=0, C/D=0
 bne omtiid2
 lda #10
 ldx #DP_TABLE
omtiid3 lbsr omtiwt wait for READY
 ldb ,x+
 stb OMTI_DAT
 deca done?
 bne omtiid3
 lbsr omtist wait for end of command and check status
 beq omtiid9
 pshs d,x
 ldx #00f
 jsr Pdata
 lda winsbf get error code
 jsr Phex
 bra 99f
00 fcc $d,'OMTI Error on IDC: ',0
99 puls d,x
omtiid9
 ldx 2,s restore drive index
 stx windrv no - remember drive #
 puls d,x,y,pc
 if PRT_DCT
*
prt_dct pshs d,x,y,u
 ldx #00f
 jsr Pdata
 lda 2+1,s
 jsr Phex
 ldx #01f
 jsr Pdata
 ldb #10
 ldy #DP_TABLE
0 lda ,y+
 jsr Phex
 jsr Pspace
 decb
 bne 0b
 puls d,x,y,u,pc
00 fcc $d,'OMTI DCT - Unit: ',0
01 fcc ', Table: ',0
 endif
*
* omti close
*
omticlose
 bsr omtidvn set up drive
 dec winopt,x clear open status
 bpl omticl0
 clr winopt,x
omticl0
 rts return
*
* omtidvn - select OMTI drive
*   (B) - minor device #
*   return with (X) - device index
*
omtidvn
 cmpb #OMTIminor+1 check device number
 lbhi omtier0 go set error
 subb #OMTIminor compute relative drive #
 clra set up device index
 tfr d,x
 rts
*
* omtidvnx - select OMTI drive & set up LUN in command
*   (B) - minor device #
*   return with (X) - device index
*
omtidvnx bsr omtidvn set up registers
 tstb
 beq omtidv0
 ldb #$20 select drive #1
omtidv0 stb OMTIlun set command byte
 rts
*
* omticn - set up OMTI command and send to OMTI 20C
*    A - DMA/IRQ select mask
*
omticn pshs d
 tst winirs Has interface been RESET?
 bne omticn0 yes - don't do it again
 lda #$80 no - send RESET code
 sta OMTI_CSR
 clr OMTI_CSR
 inc winirs
omticn0
 lda 0,s restore DMA/IRQ mask
 bita #$60 test DMA/IRQ bits
 beq omticn1
 ldb OMTIlun
 orb bfblch,y set up block #
 stb OMTIlun
 ldd bfblck,y
 std OMTIadr
 lda bfxadr,y get memory address
 sta OMTI_ADR
 ldd bfadr,y
 std OMTI_ADR+1
 bra omticn2
omticn1 ldd #0 clean up DCB
 std OMTIadr
 sta OMTIcnt
omticn2 lda 0,s restore DMA/IRQ mask
 sta OMTI_CSR set up DMA/IRQ selection
 ldb #2 block count (interleave factor)
 lda OMTIcmd test for Format Command
 cmpa #OMTIFDR
 beq omticn3
 cmpa #OMTIFTR Format Track
 beq omticn3
 ldb #1 set block count
omticn3 stb OMTIcnt
 ldx #OMTIcmd set up to send command
 lda #6 send 6 bytes
omticn4 lbsr omtiwt wait for READY
 ldb ,x+ get next byte
 stb OMTI_DAT send to controller
 deca done?
 bne omticn4
 puls d,pc
*
* omtist - wait for operation complete & get status
*
omtist
 lda OMTI_CSR wait for command completion
 bpl omtist
omtist0
 lbsr omtiwt get command status
 lda OMTI_DAT
 pshs a
 lbsr omtiwt
 ldb OMTI_DAT
 puls a
 bita #2 error bit set?
 beq omtist9 no - exit
 std winesw save error status word
 lda #OMTIRSS Request Sense Status
 sta OMTIcmd
 lda #1 no DMA/IRQ
 lbsr omticn send command
 ldx #winsbf Sense Buffer
 lda #4
omtist1 bsr omtiwt wait for READY
 ldb OMTI_DAT get data
 stb ,x+
 deca done?
 bne omtist1
 lbsr omtiwt get command status
 lda OMTI_DAT
 lbsr omtiwt
 ldb OMTI_DAT
 if PRT_ERR
 bsr rpt_err
 endif
 lda winsbf check for soft errors
 anda #$7F
 cmpa #$18 ECC Correctable error code
omtist9 rts return
 if PRT_ERR
*
rpt_err pshs d,x,y,u
 ldx #00f
 jsr Pdata
 ldx #winsbf
 ldb #4
0 lda ,x+
 jsr Phex
 jsr Pspace
 decb
 bne 0b
 puls d,x,y,u,pc
00 fcc $d,'OMTI Error: ',0
 endif
*
*  Wait for OMTI to request data
*
omtiwt ldb OMTI_CSR test READY
 bitb #1
 beq omtiwt wait until READY
 rts

 if PRT_REQ
prt_bh pshs d,x,y,u
 ldx #00f
 jsr Pdata
 ldd bfdvn,y
 bsr phex2
 ldx #01f
 jsr Pdata
 lda bfflag,y
 jsr Phex
 ldx #02f
 jsr Pdata
 lda bfblch,y
 jsr Phex
 ldd bfblck,y
 bsr phex2
 puls d,x,y,u,pc
*
phex2 pshs d
 jsr Phex
 lda 1,s
 jsr Phex
 puls d,pc
*
00 fcc $d,'OMTI I/O, Device = ',0
01 fcc ', Flags = ',0
02 fcc ', Block = ',0
 endif
*
* fire up OMTI operation to initiate transfer
*
omtisto stx BDtable
 if PRT_REQ
 bsr prt_bh print buffer header
 endif
 ldb bfdvn+1,y get drive #
 lbsr omtidvnx select drive
 lbsr omtiidc set up device characteristics if needed
 lda bfblch,y check block number range
 cmpa #$0f
 lbhi omtier if too big - error
*
* decide whether we are doing a read or write (or swap)
*
 ldd bfxfc,y get transfer count
 cmpd #16 special value for swap?
 ble omtiswp
 ldb bfflag,y get buffer flags
 bitb #BFRWF are we reading?
 beq omtiwrt go do write
 lda #OMTIRDS set Read Sector Command
 bra omtirw go perform I/O
*
* set up for write command
*
omtiwrt bitb #BFSPC special i/o
 beq omtiwr9 jump if write
 ldd bfxfc,y get transfer count
 cmpd #512 is it regular block transfer?
 beq omtiwr9 yes - normal write
 cmpd #OMTI_FD special count for Format Disk command
 beq omtiwr1
 cmpd #OMTI_FT special count for Format Track command
 lbne omtier bad I/O
 lda #OMTIFTR set Format Track command
 bra omtirw go do operation
omtiwr1 lda #OMTIFDR Format Drive command
 bra omtirw
omtiwr9 lda #OMTIWRS set Write Sector
omtirw sta OMTIcmd set up command
 lda #$41 set up IRQ
 ldb OMTIcmd DMA required?
 cmpb #OMTIFTR
 beq omtirw0
 cmpb #OMTIFDR
 beq omtirw0
 ora #$20 set for DMA transfer
omtirw0 lbsr omticn send command
 inc windt+dtbusy mark device busy
 rts
*
* take care of OMTI swap request
*
omtiswp
 lda #4 set SWAP activity code
 sta windt+dtbusy
 ldd bfadr,y get swap table pointer
 std winswpt
 lda bfflag,y check direction
 bita #BFRWF Read/Write?
 beq omtisw0 jump for Write
 lda #OMTIRDS set Read Sector opcode
 bra omtisw1
omtisw0 lda #OMTIWRS Write Sector opcode
omtisw1 sta OMTIcmd set up command
 ldb OMTIlun set up block #
 orb bfblch,y
 stb OMTIlun
 ldd bfblck,y
 std OMTIadr
 lda #8 do 4K at a time
 sta OMTIcnt
 bra omtisc2 go do operation
*
* omtisc - Continue SWAP request
*
omtisc0 ldd OMTIadr update block address
 addd #8
 std OMTIadr
 bcc omtisc1
 inc OMTIlun
omtisc1 lda [winswpt] end of list?
 cmpa DSKTRM
 lbeq omtiin4 go to next request
*
*  set up and send SWAP command
*
omtisc2
 ldx winswpt pick up SWAP table pointer
 lda ,x+ get descriptor for next segment
 stx winswpt save new pointer
 cmpa DSKTRM end of list?
 lbeq omtiin4 yes - end of operation
 pshs a compute physical address
 lsra
 lsra
 lsra
 lsra
 sta OMTI_ADR Set up DMA address
 puls a
 eora DATsense
 asla
 asla
 asla
 asla
 clrb
 std OMTI_ADR+1
 lda #$61 set up for DMA/IRQ
 sta OMTI_CSR
 if PRT_SWP
 bsr prt_cx
 endif
 ldx #OMTIcmd send SWAP command
 lda #6
omtisw2 lbsr omtiwt wait for OMTI READY
 ldb ,x+ get next byte
 stb OMTI_DAT send to OMTI
 deca done?
 bne omtisw2
 rts all done
 if PRT_SWP
*
prt_cx pshs d,x,y,u
 ldx #00f
 jsr Pdata
 ldx winswpt
 lda ,-x
 jsr Phex
 ldx #OMTIcmd
 ldb #6
0 lda ,x+
 jsr Phex
 jsr Pspace
 decb
 bne 0b
 puls d,x,y,u,pc
00 fcc $d,'OMTI SWAP - Page: ',0
01 fcc ', Command: ',0
 endif
*
*  Interrupt handler for OMTI 20C Controller
*
*
omtiint
 ldb OMTI_CSR get status
 lbsr omtist0 get status
 bne omtier jump if error
 ldy windt+dtqfl get first transaction
 beq 99f jump if no transaction
 lda bfdvn+1,y check for OMTI transaction
 cmpa #OMTIminor
 blo 99f
 cmpa #OMTIminor+3
 bhi 99f
 lda windt+dtbusy check for SWAP in progress
 beq 99f exit if no operation actually in progress
 cmpa #4
 lbeq omtisc0 continue SWAP
omtiin4 ldy windt+dtqfl get transaction
 beq 99f jump if no transaction
 clr windt+dtbusy set not busy
 ldx BDtable restore Block Device Table address
 jmp BDioend end of operation
*
99 rts *** Spontaneous interrupt ***

*
* error routine - give up forever
*
omtier0 leas 2,s clean up stack
omtier ldy windt+dtqfl get transaction
 beq 10f jump if none present
 lda bfflag,y get buffer flag
 ora #BFERR indicate failure
 sta bfflag,y stuff back in el flago
10 clr windt+dtbusy clear status
 bra omtiin4
