        IF      IODRIVERINIT
        PAGE    SSB SEMICONDUCTOR DISK (RAM DISK)
SDRESTORE
        LDB     #SDBASEPAGE            GO GRAB A PAGE
SDRESTORE1
        STB     SDMAPSLOT              MAP IT IN (ASSERT INTS ARE OFF)
        LDA     SDCYLBASE              TEST THE RAM PAGE
        COM     SDCYLBASE
        COMA
        CMPA    SDCYLBASE              SMELL LIKE MEMORY?
        BNE     SDRESTORE2             B/ NO, THIS PAGE IS NOT RAM
        COM     SDCYLBASE
        INCB
        CMPB    #255                   0..254 IS RAM, 255 IS I/O PAGE
        BNE     SDRESTORE1             B/ MORE RAM LEFT
SDRESTORE2
        SUBB    #SDBASEPAGE            COMPUTE NUMBER OF CYLINDERS
        CLR     SD.DCB+DSKINFO:NCYL
        STB     SD.DCB+DSKINFO:NCYL+1
        CLR     SDMAPSLOT              MAKE SDOS WHOLE AGAIN
        RTS
        FIN     IODRIVERINIT
        IF      IODRIVERRAM
        PAGE    SSB SD DRIVER RAM
*       AFTER THE RESET CODE IS EXECUTED, SDNEXTPAGE CONTAINS
*       THE LAST PAGE OF THE RAM
SDNEXTPAGE      FCB     SDBASEPAGE     NEXT PHYSICAL PAGE AVAILABLE FOR SD
        PAGE
SDREADWRITE     RMB     1              READ/WRITE FLAG
*
SD.DCB  FCB     1                      DCB:DONEFLAG
        FDB     0                      DCB:LASTERROR
        FDB     SD.DCB+DSKINFO:SIZE    DCB:NAME
        FDB     NEXTDISKDCB            DCB:NEXTDCB
        FDB     SDDRIVER               DCB:DRIVER
*
        FDB     256                    DSKINFO:NBPS
        FDB     16                     DSKINFO:NSPT
        FDB     1                      DSKINFO:NTPC
        FDB     135                    DSKINFO:NCYL
*
        RMB     1                      DSKINFO:NSPC
        RMB     LCN:SIZE               DSKINFO:MINALLOC
        RMB     LCN:SIZE               DSKINFO:MIDALLOC
        FDB     1                      DSKINFO:MAPALGORITHM
*
        RMB     1                      DSKINFO:LOG2NBPS
        RMB     2                      DSKINFO:NBPSM1
        RMB     LSN:SIZE               DSKINFO:NLSN
        RMB     LCN:SIZE               DSKINFO:NLCN
        RMB     2                      DSKINFO:NBPC
        RMB     LCN:SIZE               DSKINFO:RANDMAP
        RMB     LSN:SIZE               DSKINFO:MAPLSN
*
        RMB     2                      DSKINFO:DIRFCB
        RMB     2                      DSKINFO:MAPFCB
        RMB     2                      DSKINFO:SECTORDB
        RMB     LSN:SIZE               DSKINFO:BADLSN
        FDB     0                      DSKINFO:SEEKERRCNT
        FDB     0                      DSKINFO:SEEKERRSTS
        FDB     0                      DSKINFO:WRITEERRCNT
        FDB     0                      DSKINFO:WRITEERRSTS
        FDB     0                      DSKINFO:READERRCNT
        FDB     0                      DSKINFO:READERRSTS
        FCB     0,0,0                  DSKINFO:OPSCOUNT
        RMB     LSN:SIZE               DSKINFO:ERRLSN
        RMB     1                      DSKINFO:WRITEPROTSTATE
        IF      (*-SD.DCB)#DSKINFO:SIZE
        ?       INCORRECT DCB OFFSETS
        FIN
*
        FCC     /SD:/                  DEVICE NAME
        FCB     0                      END OF DEVICE NAME
NEXTDISKDCB     SET     SD.DCB
NDISKDCBS       SET     NDISKDCBS+1
        FIN     IODRIVERRAM
        IF      IODRIVERBODY
        PAGE    SEMICONDUCTOR DISK (SD) DRIVER
*
*       THE SEMICONDUCTOR DISK (SD) OPERATES IN THE SYSTEM SPACE (0)
*       BY DE-SELECTING THE RAM AT $E000 (SDOS) AND SELECTING
*       THE 4K CHUNK OF SD RAM WE WISH TO READ OR WRITE TO.
*       A WORD HERE ABOUT HOW ALL THE PIECES FIT TOGETHER:
*       8 MAPS ARE CURRENTLY USED OUT OF 16 POSSIBLE.
*       MAP 0 (THE SYSTEM SPACE) IS SETUP UPON HARDWARE RESET
*       AS FOLLOWS:
*
*               ADDRESS         PAGE
*               $0000-0FFF      $0E
*               $1000-1FFF      $0D
*                  .             .
*                  .             .
*                  .             .
*               $D000-DFFF      $01
*               $E000-EFFF      $00
*               $F000-FFFF      $FF (I/O PAGE)
*
*       USER MAPS 1 THROUGH 7 ARE DYNAMICALLY BUILT UPON THE FIRST
*       REFERENCE TO USERCURRENTSIZE FOR THAT MAP (AN MT PRIMITIVE).
*       EACH MAP IS ASSIGNED 15 PAGES OF RAM PLUS THE I/O PAGE. EACH
*       PAGE IS TESTED TO MAKE SURE IT IS RAM. IF IT IS, IT IS PERMANENTLY
*       ASSIGNED TO THE MAP AND NEVER CHANGES DURING SYSTEM EXECUTION.
*       PAGES $0F THROUGH $77 ARE RESERVED FOR USER MAPS 1 THROUGH 7.
*       PAGES $78 THROUGH $FE ARE RESERVED FOR THE SD. UPON EXECUTION
*       OF THE SD RESET CODE, THE LARGEST CONTIGUOUS GROUP OF PAGES
*       BEGINNING WITH PAGE $78 ARE ALLOCATED FOR USE BY THE SD. THE DCB
*       IS MODIFIED TO REFLECT THE CURRENT SIZE. THE SD IS ORGANIZED
*       INTO 256 BYTE SECTORS, 16 SECTORS/TRACK, 1 TRACK/CYL, N CYL,
*       WHERE A CYL IS ONE 4K PAGE OF RAM, AND THERE ARE N OF THESE, ONE
*       FOR EACH RAM PAGE ALLOCATED FOR USE BY THE SD. PRIOR TO AND
*       DURING EXECUTION OF THE SD DRIVER, THE SYSTEM SPACE IS SELECTED
*       (MAP 0). TO ACCESS AN SD 'SECTOR', IT'S PHYSICAL 'CYLINDER' IS
*       DETERMINED, $78 IS ADDED TO GIVE THE CORRESPONDING PHYSICAL PAGE
*       NUMBER AND THE RESULT IS STORED AT LOCATION $FFFE, THEREBY
*       MAPPING THAT 'CYLINDER' INTO SYSTEM SPACE ADDRESS $E000-$EFFF.
*       THIS AREA CORRESPONDS TO A PORTION OF SDOS, WHICH WON'T BE A
*       PROBLEM, BECAUSE THE BUFFER POOL IS NOT LOCATED THERE, AND
*       WE WILL DO THE MAP/TRANSFER/REMAP WITH INTERRUPTS OFF. AFTER
*       THE SD TRANSFER, THE SYSTEM MAP IS REPAIRED BY STORING A 0
*       AT LOCATION $FFFE.
*
SDMAPSLOT       EQU     $FFFE          ADDRESS E000-EFFF IN SYS SPACE
SDCYLBASE       EQU     $E000          THIS IS THE AREA WE ARE MAPPING
SDBASEPAGE      EQU     120            THIS IS THE LOWEST SD PAGE NUMBER
        PAGE
SDDRIVER                               ; Driver entry points
        FDB     SDRESTORE
        FDB     SDREAD
        FDB     SDWRITE
        FDB     SDWAITDONE
        FDB     ILLDEVICEOP            SDSTATUS handled completely by SDOS1.1
        FDB     SDCONTROL
*
*       SDCONTROL -- CONTROL OPERATION ENTRY POINT FOR SECTOR I/O DRIVER
*
SDCONTROL
        CMPA    #CC:DISMOUNTDISK       SINCE SDOS PASSES THIS THRU
        BEQ     SDDISMOUNT             B/ ITS A DISMOUNT!
        JMP     ILLDEVICEOP            NOT A LEGAL CONTROL CALL
*
*       SDREAD/WRITE -- START SINGLE SECTOR TRANSFER
*
SDREAD  LDA     #RDSISTATE:READING
        BRA     SDWRITE1
SDWRITE LDA     #RDSISTATE:WRITING
SDWRITE1        ; Assert SDOS checks DCB:DONEFLAG before calling
        JMP     SDSETUPDRIVE           GO SET UP ALL THE PARAMETERS IN THE DCB
SDWAITDONE
SDSTARTIO
        LDD     DCBPOINTER             NOW NOBODY'S USING DRIVE
        LDX     #SDINTSTART
        JSR     SDOS+SDOS:STARTIO
SDDISMOUNT
SDWAIT2 CLRB                           CLEAR THE CARRY
SDWRITE2
        RTS
        PAGE
*
*       SDSETUPDRIVE -- SETS UP SDDRIVE TABLE FOR INTERRUPT DRIVEN TRANSFER
*
SDSETUPDRIVE 
        LDX     DCBPOINTER             GET DCB POINTER
        LDY     DSKINFO:SECTORDB,X     GET RDSI POINTER
        STA     SDREADWRITE
*       BRA     TEARLSN                FIND OUT WHAT CYL, TRACK AND SECTOR
        PAGE
*
*       Take RDSI:LSN and split it up into RDSI:CYLINDER,
*       RDSI:TRACK, and RDSI:SECTOR
*
SDTEARLSN
        LDX     DCBPOINTER
        LDY     DSKINFO:SECTORDB,X     GET ADDRESS OF RDSI
        CLR     RDSI:SECTOR,Y          CLEAR MSB SECTOR, TRACK, CYLINDER
        CLR     RDSI:TRACK,Y
*       CLR     RDSI:CYLINDER,Y
*
*       ASSERT RDSI:LSN ALREADY CHECKED FOR LEGAL BY SDOS
*       COMPUTE CYLINDER
*
        LDD     RDSI:LSN+1,Y
        LSRD                           CYL NUMBER=LSN/16
        LSRD
        LSRD
        LSRD
        STD     RDSI:CYLINDER,Y
*
*       COMPUTE TRACK
*
        CLR     RDSI:TRACK+1,Y
*
*       COMPUTE SECTOR
*
        LDA     RDSI:LSN+2,Y
        ANDA    #16-1
        STA     RDSI:SECTOR+1,Y
        OKRTS
        PAGE    SSB SEMICONDUCTOR DISK (SD) INTERRUPT LEVEL CODE
*
*       Start I/O for SSB semiconductor disk (SD)
*       ASSERT: INTERRUPTS ARE DISABLED HERE!
*
SDINTSTART
        TFR     D,X                    SETUP DCB POINTER
        LDY     DSKINFO:SECTORDB,X     Get pointer to RDSI
        INC     DSKINFO:OPSCOUNT+2,X   COUNT # OPERATIONS ISSUED TO SD
        BNE     SDCOUNTCOMMAND1
        INC     DSKINFO:OPSCOUNT+1,X
        BNE     SDCOUNTCOMMAND1
        INC     DSKINFO:OPSCOUNT,X
SDCOUNTCOMMAND1
        LDD     #SDCYLBASE             BASE ADDRESS OF CYLINDER
        ADDA    RDSI:SECTOR+1,Y        SECTOR NUMBER DETERMINES OFFSET IN CYL
        TFR     D,U
        LDA     RDSI:CYLINDER+1,Y      GET CYLINDER NUMBER
        ADDA    #SDBASEPAGE            ADD BASE PAGE OFFSET
        STA     SDMAPSLOT              RAM PAGE NOW MAPPED IN (INTS DISABLED)
        LDY     RDSI:SECTORBASE,Y      POINT TO THE SECTOR BUFFER
        LEAY    16,Y                   SETUP FOR FAST BLOCK TRANSFER
        LEAU    16,U
        LDB     #8                     NUMBER OF LOOP ITERATIONS
        LDA     SDREADWRITE            READING OR WRITING?
        CMPA    #RDSISTATE:READING
        BEQ     SDINTREAD
        CMPA    #RDSISTATE:WRITING
        BEQ     SDINTWRITE             B/ IT'S A WRITE COMMAND
        SWI
        PAGE
*
*       ON A WRITE TO DISK, U POINTS TO SECTOR BUFFER,
*       Y POINTS TO THE DISK
*
SDINTWRITE
        EXG     U,Y
*
*       ON A READ FROM DISK, U POINTS TO THE DISK,
*       Y POINTS TO SECTOR BUFFER
*
SDINTREAD
        LDX     -16,U
        STX     -16,Y
        LDX     -14,U
        STX     -14,Y
        LDX     -12,U
        STX     -12,Y
        LDX     -10,U
        STX     -10,Y
        LDX     -8,U
        STX     -8,Y
        LDX     -6,U
        STX     -6,Y
        LDX     -4,U
        STX     -4,Y
        LDX     -2,U
        STX     -2,Y
        LDX     0,U
        STX     0,Y
        LDX     2,U
        STX     2,Y
        LDX     4,U
        STX     4,Y
        LDX     6,U
        STX     6,Y
        LDX     8,U
        STX     8,Y
        LDX     10,U
        STX     10,Y
        LDX     12,U
        STX     12,Y
        LDX     14,U
        STX     14,Y
        LEAY    32,Y
        LEAU    32,U
        DECB
        BNE     SDINTREAD
*
SDDONE  CLR     SDMAPSLOT              MAKE SDOS WHOLE AGAIN
        JMP     SDOS+SDOS:RTI
        FIN     IODRIVERBODY
        END
