* DEVICE SERVICE ROUTINES
*
* This modules takes care of all the high level I/O to
* the SCSI drives (Open, close, read, write, etc)
*

SCSI0  CLR  R6
       JMP  SCSDSR
SCSI1  LI   R6,>0100
       JMP  SCSDSR
SCSI2  LI   R6,>0200
       JMP  SCSDSR
SCSI3  LI   R6,>0300
       JMP  SCSDSR
SCSI4  LI   R6,>0400
       JMP  SCSDSR
SCSI5  LI   R6,>0500
       JMP  SCSDSR
SCSI6  LI   R6,>0600
       JMP  SCSDSR
SCSI7  LI   R6,>0700
       JMP  SCSDSR
DSK1   LI   R6,>0001

SCSDSR
       ANDI R12,>FF00
       AI   R12,24
       LDCR @ZERO,4      Make sure RAM bank 0 is active
       MOV  R1,@SAVR1
       MOV  R11,@SAVR11

       LI   R0,STINIT    Reset the stack pointer for BANKIT
       MOV  R0,@STACK

* Copy the PAB to our buffer and the file name to the
* name compare buffer in RAM bank 2
*
       MOV  @>8356,R4
       S    @>8354,R4
       AI   R4,-10
       MOV  R4,@PABADR
       SWPB R4
       MOVB R4,@VDPWA
       SWPB R4
       MOVB R4,@VDPWA
       LI   R5,10
       LI   R4,PABBUF
SCSD01 MOVB @VDPRD,*R4+
       DEC  R5
       JNE  SCSD01

* Now make sure we're not trying to do I/O to the
* SCSI card.
*
       ANDI R12,>FF00
       AI   R12,8
       CLR  R2
       STCR R2,3         Read SCSI address of the card
       CB   R2,R6        See if it matches
       JNE  DSR3
       BL   @DSRERR
       DATA >0300        Illegal operation

DSR3
*
* Now copy the name of the file to the name compare
* buffer in banks 2 and 4.
* We also check that the name is not longer than 40
* characters, contains only valid characters and
* that there are not more than 10 characters between
* periods.
*
* If we are doing DSK emulation, prefix the filename
* with the appriproate directory
*

       MOVB @PABBUF+9,R1 Set the file name length
       SRL  R1,8

       ANDI R12,>FF00
       AI   R12,24
       LDCR @B02,4       Select RAM bank 2

       LI   R3,NCB       Name Compare Buffer
       LI   R2,40        Maximum name length
       CLR  R7           Number of characters between periods
       JMP  DSR5

DSR4   BL   @DSRERR      Name too long!
       DATA >0700        Bad open attribute?

DSR5

* If we are doing DSKx emulation, prefix the filename
*
       MOV  R6,R8
       ANDI R8,>00FF
       JEQ  DSR5B

       MOV  @DS,*R3+         copy the 'DS'
       MOVB @ASCIIK,*R3+     copy the 'K'
       AI   R8,48
       SWPB R8
       MOVB R8,*R3+
       MOVB @PERIOD,*R3+
       AI   R2,-5            Maximum length is 5 less

DSR5B  C    R1,@>8354
       JEQ  DSR7         Pad everything!
       S    @>8354,R1    Subtract device name length
       DEC  R1           Account for period after device name
       JEQ  DSR7
       C    R1,R2        See if name > 40 characters
       JH   DSR4
       S    R1,R2        Compute number of spaces we will have to pad

       MOVB @>8357,@VDPWA Set VDP read address to
       NOP                file name
       MOVB @>8356,@VDPWA
       NOP
       MOVB @VDPRD,R0    Ignore the period after the device name
       NOP

DSR5A  MOVB @VDPRD,R5
       CB   R5,@SPACE
       JLE  DSR4         Illegal character
       CB   R5,@B126
       JH   DSR4         Illegal character

       MOVB R5,*R3+
       CB   R5,@PERIOD
       JNE  DSR6
       CI   R7,0
       JEQ  DSR4
       CI   R7,10
       JH   DSR4
       SETO R7

DSR6   INC  R7
       DEC  R1
       JNE  DSR5A

* Make sure the last part of the name is not too long
*
       CI   R7,10
       JH   DSR4

* Now pad the rest of the name with spaces
*

       CI   R2,0
       JEQ  DSR8
DSR7   MOVB @SPACE,*R3+
       DEC  R2
       JNE  DSR7

* Now copy it to the name compare buffer in bank 4
*
DSR8   LI   R3,NCB
       LI   R2,40
DSR9   MOV  *R3,R4
       LDCR @B04,4
       MOV  R4,*R3+
       LDCR @B02,4
       DECT R2
       JNE  DSR9

* Check the I/O Opcode and call the appripriate routine
*

* If we are doing DSKx emulation, only let the LOAD I/O
* op code go through.


       LDCR @ZERO,4
       CB   @PABBUF,@B05
       JNE  DSR10

DSRIO5 BL   @XFER
       DATA LOAD
DSR10
       MOV  R6,R0             Check for emulation
       ANDI R0,>00FF
       JNE  DSR19

       MOVB @PABBUF,R1
       SRL  R1,8
       CI   R1,9
       JH   DSR18
       SLA  R1,1
       MOV  @IOJTBL(R1),R1
       B    *R1

IOJTBL DATA DSRIO0
       DATA DSRIO1
       DATA DSRIO2
       DATA DSRIO3
       DATA DSRIO4
       DATA DSRIO5
       DATA DSRIO6
       DATA DSRIO7
       DATA DSR18
       DATA DSRIO9

DSRIO0 BL   @XFER
       DATA OPEN
DSRIO1 BL   @XFER
       DATA CLOSE
DSRIO2 BL   @XFER
       DATA READ
DSRIO3 BL   @XFER
       DATA WRITE
DSRIO4 BL   @XFER
       DATA REWIND
DSRIO6 BL   @XFER
       DATA SAVE
DSRIO7 BL   @XFER
       DATA DELETE
DSRIO9 BL   @XFER
       DATA STATUS
DSR18
       ANDI R12,>FF00
       MOV  @SAVR1,R1
       MOV  @SAVR11,R11
       INCT R11
DSR19  RT

**
*
* Here is where we have to compare label names to
* see which disk we are truely accessing.
*
**

DSR20  ANDI R12,>FF00
       AI   R12,24
       LDCR @ZERO,4

       MOV  R1,@SAVR1
       MOV  R11,@SAVR11

       LI   R0,STINIT    Reset the stack pointer for BANKIT
       MOV  R0,@STACK

* Now we have to check our table of disk labels.  If the VIB
* hasn't been read on a disk yet, the entry will be null.

* Copy the PAB from VDP memory to a buffer in bank 0

       MOV  @>8356,R4        Get pointer to file name
       S    @>8354,R4
       AI   R4,-10
       MOV  R4,@PABADR
       SWPB R4
       MOVB R4,@VDPWA
       SWPB R4
       MOVB R4,@VDPWA
       LI   R5,10
       LI   R4,PABBUF
DSR21  MOVB @VDPRD,*R4+
       DEC  R5
       JNE  DSR21

       DEC  R4
       MOVB *R4,R2           Get file name length
       SRL  R2,8
       S    @>8354,R2
       JEQ  DSR23            No label given - error
       DEC  R2
       JEQ  DSR23

       MOVB @>8357,@VDPWA
       NOP
       MOVB @>8356,@VDPWA
       NOP
       MOVB @VDPRD,R0        Ignore the period

       LDCR @B02,4           Select RAM bank 2
       LI   R3,NCB
DSR22  MOVB @VDPRD,R0
       DEC  R2
       CB   R0,@PERIOD
       JEQ  DSR25
       MOVB R0,*R3+
       CI   R2,0
       JEQ  DSR25
       CI   R3,NCB+10
       JNE  DSR22

* The label given is longer than 10 characters.  No way can it
* match anything.  Give up here.

DSR23  LDCR @ZERO,4
       MOV  @SAVR1,R1
       ANDI R12,>FF00
       RT

DSR24  MOVB @SPACE,*R3+
DSR25  CI   R3,NCB+10
       JNE  DSR24

**
*
* Now that we have the label in our compare buffer, check to
* see if there are any SCSI drives that have a label that
* matches.
*
**

       CLR  R6               Start with SCSI ID=0
       LI   R5,DLTABL
       LDCR @B02,4           Select RAM bank 2

DSR26  C    *R5,@MINUS1
       JEQ  DSR28
       C    *R5,@ZERO
       JNE  DSR31

       LDCR @ZERO,4          We have to read the label
       CLR  R7
       CLR  R8
       BLWP @BANKIT
       DATA SCSIRD
       JEQ  DSR29
DSR27  SETO *R5
DSR28  LDCR @B02,4
       AI   R5,10
       AI   R6,>0100
       CI   R6,>0800
       JNE  DSR26
       JMP  DSR23            No match - error

DSR29  LI   R7,SECBUF        * Now move label to table
       LI   R0,10
DSR30  MOV  *R7+,R8
       LDCR @B02,4
       MOV  R8,*R5+
       LDCR @ZERO,4
       DECT R0
       JNE  DSR30
       LDCR @B02,4
       AI   R5,-10

DSR31  LI   R0,10
       LI   R7,NCB
       MOV  R5,R8
DSR32  C    *R7+,*R8+
       JNE  DSR28
       DECT R0
       JNE  DSR32

* Hooray!  We found a match!  Now copy the real filename to
* the filename compare buffer

       LI   R3,NCB
       CI   R2,0             Check for no name (i.e.
       JEQ  DSR34             directory access)
       CI   R2,40            Check file name length
       JLE  DSR33

       BL   @DSRERR          File name too long!
       DATA >0700

DSR33  MOVB @VDPRD,*R3+
       DEC  R2
       JNE  DSR33

DSR34  CI   R3,NCB+40
       JEQ  DSR35
       MOVB @SPACE,*R3+
       JMP  DSR34

DSR35  B    @DSR8

* Let's display our file name for fun
*
*DSR35  CLR   @VDPWA
*      LI    R1,>4040
*      MOV   R1,@VDPWA
*      LI    R0,40
*      LI    R3,NCB
*SR999 MOVB  *R3+,@VDPWD
*      DEC   R0
*      JNE   DSR999
*SR888 JMP   DSR888

DS     DATA 'DS'
MINUS1 DATA >FFFF
ASCIIK BYTE 'K'
B126   BYTE 126
