home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / RUN96.ZIP / NEW96.ASM < prev    next >
Encoding:
Assembly Source File  |  1987-01-27  |  42.6 KB  |  1,434 lines

  1.  
  2.         page    66,132
  3.         title   '96 TPI DISK DRIVER'
  4. ; as of 7-4-1986
  5.  
  6. ; Much of this code is from the Zenith MS-DOS 2.11
  7. ; BIOS, copyright Zenith Data Systems, 1983-4.
  8. ; It has been extensively hacked on, but seems to work.
  9. ;
  10. ; Features and limitations:
  11. ;
  12. ; 1) Device driver for 96 tpi drive support
  13. ; 2) Sets disk parameter by BPB head, so should read
  14. ;    any 96tpi format with a valid BPB. I have used with
  15. ;    the Tandy format ( as put by FORMAT96 ) and the
  16. ;    DOS 3.2 format for 720k disks.
  17. ; 3) Does not double step for 48 tpi drives
  18. ; 4) Has not been tested with single sided drives
  19. ; 5) DOS considerations limit the reconfigurability to
  20. ;    disks with 512 byte sectors. PCDOS requires a
  21. ;    patch to use large sectors. For smaller sectors,
  22. ;    the routine to read sector 0 would have to include
  23. ;    trying different sector sizes, since the ROM bios
  24. ;    routine used returns error if wrong sector size is
  25. ;    used;
  26. ; 6) A timeout of 6 secs is used to determined if disk has
  27. ;    been changed. Six seconds was the fastest I could change
  28. ;    disk, so it seemed like a safe value.
  29. ; 7) Does not support single density diskettes
  30. ; 8) the assembly code is hardwired for 2 external 96 track
  31. ;    drives and two internal 48 tpi drives. Changes would
  32. ;    require adjusting the offset added to unit number to obtain
  33. ;    physical floppy number, as well as changing the number of
  34. ;    drives returned to DOS  upon initialization.
  35. ;
  36.  
  37. BPBTEST equ  1
  38. DEBUG   equ  0  ; 1 to use debug lines
  39. BEGINBPB equ  11; offset in sector 0 to start of BPB
  40.  
  41. ; INTERRUPT LOCATIONS AND PARAMETERS
  42.  
  43. TIME_OF_DAY_INTR   EQU  1AH
  44. TOD_GET            EQU  0
  45.  
  46. DISK_IO_INTR  EQU  13H
  47. DIO_READ      EQU  2
  48. DIO_WRITE     EQU  3
  49. DIO_VERIFY    EQU  4
  50. DIO_RESET     EQU  0    ; 1 WAS TO REREAD DISK STATUS
  51.  
  52. ; MISC. CONSTANTS
  53.  
  54. SEC_SIZE      EQU  512
  55. NUM_RETRY     EQU  5
  56. TIME_OUT      EQU  80H
  57.  
  58.  
  59. ;
  60.         IF1
  61. %OUT PASS 1 STARTED
  62.         ELSE
  63. %OUT PASS 2 STARTED
  64.         ENDIF
  65.  
  66. D_2SEC  =       1                       ; Assemble with 4 sec timeout for disk media check
  67.  
  68.                                         ; media check.
  69. DSK_MAXVAL =    6*18                    ; 6 sec delay on disk changes
  70. TOD_LIM    =    2*60*18                 ; 2 min between stamp updates
  71. MIN_SEC =       9                       ; Highest sector to update date/time on
  72.  
  73. ; The Static Request header
  74.  
  75. SRH_STRUC STRUC
  76.   SRH_LEN     DB ?; Length of command request structure
  77.   SRH_UNIT    DB ?; Sub unit number
  78.   SRH_CMD     DB ?; Command code(see below)
  79.   SRH_STAT    DW ?; Status code(see below))
  80.   SRH_RES     DB 8 DUP(?); Reserved for two sets of links
  81. SRH_STRUC ENDS
  82.  
  83.  
  84. ; Status codes (in upper half of SRH_STAT)
  85.  
  86. SRHS_ERR    EQU 80H; 1=error; 0=no error
  87. SRHS_RES1   EQU 7CH; reserved
  88. SRHS_BUI    EQU 02H; 1=busy; 0=not busy
  89. SRHS_DON    EQU 01H; 1=done; 0=not done
  90.  
  91. ; Error codes (in lower half of SRH_STAT)
  92.  
  93. SRHS_EWPR   EQU 0    ; Write protect violation
  94. SRHS_EUKU   EQU 1    ; Unknown unit
  95. SRHS_EDNR   EQU 2    ; Drive not ready
  96. SRHS_EUKC   EQU 3    ; Unknown command
  97. SRHS_ECRC   EQU 4    ; CRC error
  98. SRHS_ELEN   EQU 5    ; Bad request structure length
  99. SRHS_ESEEK  EQU 6    ; Seek error
  100. SRHS_EUKM   EQU 7    ; Unknown media
  101. SRHS_ESNF   EQU 8    ; Sector not found
  102. SRHS_ENPP   EQU 9    ; Printer out of paper
  103. SRHS_EWRF   EQU 10   ; Write fault
  104. SRHS_ERDF   EQU 11   ; Read fault
  105. SRHS_EGNF   EQU 12   ; General failure
  106. SRHS_EMAX   EQU 12   ; Max error code
  107.  
  108.  
  109. ; Read/Write Request packet
  110.  
  111. CRW_STRUC STRUC
  112.   CRW_SRH   DB SIZE SRH_STRUC DUP(?) ; A static request header
  113.   CRW_MBYTE DB ?       ; Media descriptor
  114.   CRW_TADDR DD ?       ; Transfer addr
  115.   CRW_CNT   DW ?       ; Byte/sector count
  116.   CRW_START DW ?       ; Starting sector number
  117. CRW_STRUC ENDS
  118.  
  119.  
  120. ; Non-destructive read(no wait) packet
  121.  
  122. CIC_STRUC STRUC
  123.   CIC_SRH    DB SIZE SRH_STRUC DUP(?) ; A static request header
  124.   CIC_CHAR   DB ?                     ; Character from device
  125. CIC_STRUC ENDS
  126.  
  127.  
  128. ; Media check packet
  129.  
  130. CMC_STRUC STRUC
  131.   CMC_SRH   DB SIZE SRH_STRUC DUP(?) ; A static request header
  132.   CMC_MBYTE DB ?                     ; Media descriptor
  133.   CMC_STAT  DB ?                     ; Media status (see below)
  134. CMC_STRUC ENDS
  135.  
  136. CMCS_CHG   EQU -1  ; Media has been changed
  137. CMCS_DKN   EQU  0  ; Don't know if media changed
  138. CMCS_NOC   EQU +1  ; Media not changed
  139.  
  140.  
  141. ; Build BPB packet
  142.  
  143. CBPB_STRUC STRUC
  144.   CBPB_SRH     DB SIZE SRH_STRUC DUP(?) ; A static request header
  145.   CBPB_MBYTE   DB ?                     ; Media descriptor
  146.   CBPB_TADDR   DD ?                     ; Transfer addr
  147.   CBPB_BADDR   DD ?                     ; BPB addr
  148. CBPB_STRUC ENDS
  149.  
  150.  
  151. ; Init packet
  152.  
  153. CIN_STRUC STRUC
  154.   CIN_SRH      DB SIZE SRH_STRUC DUP(?) ; A static request header
  155.   CIN_UNITS    DB ?      ; Number of units
  156.   CIN_KADDR    DD ?      ; Break addr
  157.   CIN_BADDR    DD ?      ; BPB array addr
  158.   CIN_PADDR    DD ?      ; Init parameters
  159. CIN_STRUC ENDS
  160.  
  161.  
  162. ; A BPB (BIOS parameter block)
  163.  
  164. BPB_STRUC STRUC
  165.   BPB_SECSZ   DW ?  ; Sector size
  166.   BPB_SPAU    DB ?  ; Sectors per allocation unit
  167.   BPB_RES     DW ?  ; Reserved sectors
  168.   BPB_NFATS   DB ?  ; Number of FAT's (file alloc tables)
  169.   BPB_DIRENTS DW ?  ; Number of director entries
  170.   BPB_SECS    DW ?  ; Number of sectors
  171.   BPB_MBYTE   DB ?  ; Media byte
  172.   BPB_FATSECS DW ?  ; Number of sectors occupied by a FAT
  173.   BPB_SPT     DW ?  ; Number of sectors per track
  174.   BPB_HEADS   DW ?  ; Number of heads
  175.   BPB_HIDDEN  DW ?  ; Number of hidden sectors
  176.   BPB_UNIT    DB ?  ; Unit number
  177. BPB_STRUC ENDS
  178.  
  179.         org   0 ;
  180. CODE    segment byte ;
  181.         ASSUME CS:CODE  , DS:CODE,ES:CODE,SS:CODE
  182.  
  183. mydisk_start  label   near
  184.         DW      -1      ; next device offset
  185.         DW      -1      ; segment of next driver
  186.         DW       2000H     ; 2000H = 0010 0000 0000 0000B ; attributes for non-ibm
  187.                         ;block device,  ibm type=0
  188.         DW      OFFSET DISK_STRAT
  189.         DW      OFFSET DISK_INT
  190.         db      2,'96TKDRV'
  191.  
  192.  
  193. ;       Subroutine dispatch table for the disk driver
  194.  
  195. DISK_TABLE LABEL near
  196.  
  197.         DW      offset DISK_INIT       ; Init
  198.         DW      offset MEDIA_CHECK     ; Media check
  199.         DW      offset BUILD_BPB       ; Build BPB
  200.         DW      offset UNKNOWN         ; IOCTL INPUT
  201.         DW      offset DISK_READ       ; Disk read
  202.         DW      offset BUSY            ; Non destructive read
  203.         DW      offset NO_OP           ; Status
  204.         DW      offset NO_OP           ; Flush
  205.         DW      offset DISK_WRITE      ; Write
  206.         DW      offset DISK_WRITE_VERIFY ; Write and verify
  207.         DW      offset NO_OP           ; Output status
  208.         DW      offset NO_OP           ; Output flush
  209.         DW      offset UNKNOWN         ; IOCTL OUTPUT
  210.  
  211. ;       Floppy disk BPB's. These are the floppy disk BPB's used
  212. ;       by the disk I/O code.
  213.  
  214. FLOPPY_BPBS     LABEL   word
  215. ; note these are maximal bpb's so DOS can set up its buffers
  216. ; have declared here a longer fat than needed 4 sectors for each
  217. ; because going down to 1k allocation units would need more length
  218. ;
  219. ; DOS 3.1 does not seem to play by the rules. It interprets the
  220. ; BPB by a combination of the startup BPB and the BPB submitted
  221. ; by BUILD_BPB later
  222. ; example, disk BPB said 1 FAT, 112 entry directory
  223. ; DOS gave 2 fats, and 256 entry directory
  224. ; to get DOS to believe the 2 sectors per allocation block
  225. ; for this size disk, had to make it that way in the startup
  226. ; bpb
  227.  
  228.  
  229. BPBDISK0  BPB_STRUC <512,4,1,2,112,1440,0edh,2,9,2,0,0>
  230. BPBDISK1  BPB_STRUC <512,4,1,2,112,1440,0edh,2,9,2,0,0>
  231.  
  232. floppy_start label word ; send these to DOS on startup
  233. ; this is for testing the effects of startup bph versus
  234. ; those read on the trk 0 sector 1
  235. ;
  236.  
  237. BPB0  BPB_STRUC <512,4,1,2,112,1440,0edh,2,9,2,0,0>
  238. BPB1  BPB_STRUC <512,4,1,2,112,1440,0edh,2,9,2,0,0>
  239.  
  240. BPB_VECTOR      LABEL   NEAR
  241.         DW      OFFSET BPB0
  242.         DW      OFFSET BPB1
  243.  
  244. ; maximum format to be reported to DOS
  245.  
  246. BPBDRIVE  db   0                ;stores drive number for new bpb routine
  247.  
  248. newbpbptr dw   offset bpbdisk0  ;
  249.  
  250. IF BPBTEST  ; DEBUG  ; caution these output routines seem to crash system
  251.           ; if used too extensively
  252.  
  253.  
  254. hexdigit  db   '0123456789ABCDEF'
  255.  
  256. ; uses dos calls.. should be ok if not redirected
  257.  
  258. crlf  proc  near
  259.         push    ax
  260.         push    bx
  261.         push    cx
  262.         push    dx
  263.         mov     dl,0dh
  264.         call    stdtout
  265.         mov     dl,0ah
  266.         call    stdtout
  267.         pop     dx
  268.         pop     cx
  269.         pop     bx
  270.         pop     ax
  271.         ret
  272. crlf    endp
  273.  
  274. putnibble proc near
  275. ; take nibble in al, send as hex to screen
  276. ; uses dos call
  277.     and  al,0fh ; make sure it's a nibble
  278.                 ; convert to ascii digit or A..F
  279.     xor  ah,ah
  280.     mov   bx,offset hexdigit
  281.     add   bx,ax  ; point to digit
  282.     mov   dl,cs:[bx]
  283.     call  stdtout
  284.     ret
  285. putnibble endp
  286.  
  287. putbyte proc near
  288. ; print byte in al, high nibble first
  289.         push    ax
  290.         push    bx
  291.         push    dx
  292.         push    cx
  293.         mov     cl,4  ; rotate 4
  294.         push    ax
  295.         ror     al,cl
  296.         call    putnibble
  297.         pop     ax
  298.         call    putnibble
  299.         pop     cx
  300.         pop     dx
  301.         pop     bx
  302.         pop     ax
  303.         ret
  304. putbyte endp
  305.  
  306. putword proc near
  307. ; print in hex the word in ax, in high byte first order
  308.         push    ax
  309.         mov     al,ah
  310.         call    putbyte
  311.         pop     ax
  312.         call    putbyte
  313.         ret
  314. putword endp
  315.  
  316. printword proc near ; print word pointed to by ds:bx
  317.        mov    ax,[bx]
  318.        call   putword
  319.        call   crlf
  320.        inc    bx
  321.        inc    bx
  322.        ret
  323. printword endp
  324.  
  325. printbyte proc near ; print byte pointed to by ds:bx
  326.        mov    ax,[bx]
  327.        call   putbyte
  328.        call   crlf
  329.        inc    bx
  330.        ret
  331. printbyte endp
  332.  
  333. prtbpb0 proc  near     ; kills ax,bx,ds
  334.        mov    ax,cs
  335.        mov    ds,ax
  336.        mov    bx,offset bpbdisk0
  337. prtbpb0 endp
  338.  
  339. printbpb proc near ; print to console the bpb pointed to by ds:bx
  340.        push   ax
  341.        push   bx
  342.        push   cx
  343.        push   dx
  344.        push   ds
  345.        push   es
  346. ;
  347.        call   printword     ;0-1
  348.        call   printbyte     ;2
  349.        call   printword     ;3-4
  350.        call   printbyte     ;5
  351.        call   printword     ;6-7
  352.        call   printword     ;8-9
  353.        call   printbyte     ;10
  354.        call   printword     ;11-12
  355.        call   printword     ;13-14
  356.        call   printword     ;15-16
  357.        call   printword     ;17-18
  358. ;
  359.        pop    es
  360.        pop    ds
  361.        pop    dx
  362.        pop    cx
  363.        pop    bx
  364.        pop    ax
  365. ;
  366.        ret
  367. printbpb endp
  368.  
  369. ENDIF  ; debug
  370.  
  371.  
  372.  
  373. ;       my floppy disk parameter table ,pointed to by
  374. ;       $1Eh during ROM disk routines
  375. ;       might want to use a macro to define this in case
  376. ;       wanted more than one
  377.  
  378. myparameters LABEL near
  379.  
  380.         DB      0EFH   ; mode byte 1  used by SPECIFY command of 765
  381.                        ; top nibble is step rate, second is head unload time
  382. mode2   DB      002H   ; mode byte 2  top 7 bits are head load time,
  383.                        ; last bit is is non-DMA mode flag
  384.         DB      025h   ; 025H   ; delay on motor turnoff in 18.2 clicks/sec
  385.         DB      002H   ; bytes per sector 2 = 512 bytes
  386.         DB      009H   ; sectors per track
  387.         DB      02AH   ; gap length
  388.         DB      0FFH   ; data length 80h for 128, ff otherwise
  389.         DB      050H   ; gap while formating
  390.         DB      0F6H   ; formatting fill byte
  391. HDSET   DB      0DH    ; head settling time
  392.         DB      02H    ; was 4 motor start time in .25 sec increments
  393.  
  394.  
  395. ;       Floppy disk timeout tables.  These are used to store the current
  396. ;       timer values to determine when the drive was last accessed.
  397.  
  398. DSK_TIMOUT      LABEL   BYTE
  399.         DD      0     ; 4 bytes
  400.         DD      0     ; 4 bytes
  401.  
  402.  
  403. ;**************************************
  404. ; Variables used by the disk I/O code *
  405. ;**************************************
  406.  
  407. RETRY_COUNT DB  ?               ; Location to keep retry count
  408. DRIVE       DB  ?               ; Drive number for ROM
  409.  
  410. TIM_PTR    DW  ?                ; Pointer to timeout table of last access
  411.  
  412. NUM_FLOPPY DB   2               ; Number of floppy drives in the system
  413. DOP_TYPE   DB   ?               ; Disk operation type (ROM error code)
  414. DOP_VERIFY DB   ?               ; Verify flag (1 = verify, 0 = no verify)
  415.  
  416.  
  417. SEC_CNT    DW   ?               ; Sector count
  418. OLD_SP1    DW   ?               ; Old stack pointer for error exit
  419. OLD_SP2    DW   ?               ; Old stack pointer for error exit
  420.  
  421. ;       Error codes returned by the ROM
  422.  
  423. T_ERR   DB      80H, 40H, 20H, 10H, 09H, 08H, 04H, 03H, 02H, 01H
  424. L_ERR   =       OFFSET $ - OFFSET T_ERR
  425.  
  426. ;       Error codes to return to MS-DOS (1 to 1 map to the table above)
  427.  
  428.         DB      02H, 06H, 0CH, 04H, 0CH, 04H, 08H, 00H, 0CH, 0CH
  429.  
  430. ; messages, mostly for debugging
  431.  
  432.  
  433.  IF DEBUG
  434. BUILDBPBMSG  DB   0DH,0AH,'Call to Build_BPB in 96TPI.',0dh,0ah, '$'
  435. MEDIAmsg     DB   0DH,0AH,'Call to MEDIA_CHECK in 96TPI.',0dh,0ah, '$'
  436. notchanged   db   0dh,0ah,'Media not changed by timeout.',0dh,0ah,'$'
  437. timeoutmsg   db   0dh,0ah,'In time out routine of media_chk.',0dh,0ah,'$'
  438.  ENDIF; { debug }
  439.  
  440.  
  441. ;       Packet pointer for the DOS packet
  442.  
  443. PACKET  DD      ?
  444. SS_SAVE DW      ?               ; Storage for saving the DOS stack
  445. SP_SAVE DW      ?
  446.  
  447. ;       MYDISK  local stack
  448.  
  449.         DW      128 DUP(?)
  450.  
  451. STACK_TOP LABEL WORD
  452.  
  453. ;       Disk driver initialization - Return the address of a BPB table
  454. ;       number of units
  455. ;
  456. ;       has to return the number of units,
  457. ;       end of code
  458. ;       address of array of pointers to BPB's for the units
  459.  
  460.  
  461.  
  462. ;
  463. STRATEGY PROC FAR
  464.  
  465. ; just store the packet address away
  466.  
  467. DISK_STRAT:
  468.         MOV     WORD PTR CS:PACKET,BX
  469.         MOV     WORD PTR CS:PACKET+2,ES
  470.         RET
  471. STRATEGY ENDP
  472.  
  473.  
  474. ;**     DISK_INT - This routine passes the address of a jump
  475. ;               table to the common interrupt routine
  476. ;
  477.  
  478. DISK_INT proc   FAR
  479.  
  480.         PUSH    AX
  481.         CLI
  482.  
  483. ; turn off interrupts to switch stacks
  484.  
  485.         MOV     CS:SS_SAVE,SS   ; save previous stack
  486.         MOV     CS:SP_SAVE,SP
  487.         MOV     AX,CS
  488.         MOV     SS,AX       ; make local stack
  489.         MOV     SP,OFFSET STACK_TOP
  490.  
  491. ; turn interrupts back on
  492. ; save most registers, except ds:dx
  493.  
  494.         STI
  495.         PUSH    BX
  496.         PUSH    CX
  497.         PUSH    ES
  498.         PUSH    SI
  499.         PUSH    DI
  500.         PUSHF
  501.  
  502. ; ax still has cs
  503.  
  504.         mov     ds,ax     ; get right data segment
  505.         LES     BX,CS:PACKET                       ; ES:BX = request packet
  506.         MOV     SI,offset cs:DISK_TABLE         ; Command table
  507.         MOV     CL,ES:SRH_CMD[BX]               ; CL = requested command
  508.         XOR     CH,CH
  509.         SHL     CX,1                            ; Make into word offset
  510.         ADD     SI,CX                           ; SI = pointer to routine
  511.         JMP     [SI]            ; Go to it
  512.  
  513. ; so when it gets to a command, ES:BX points to paket, ds to data segment
  514.  
  515.  
  516. ;       Now exit from the request
  517. ;       TWO POSSIBLE EXITS.. SUCCESS OR ERROR
  518.  
  519. SUCESS:  ; set ah to show no error
  520.          XOR      ax,ax
  521.          OR       ah,srhs_don     ; ????? is srhs_don = 0
  522.          JMP SHORT TRK96_EXIT
  523.  
  524. ERROR:   ; al will contain an error code, and ah is set to indicate
  525.          ; existence of an error
  526.  
  527.         MOV     AH,SRHS_ERR                 ; Flag error
  528.                                         ; AL has the description of error
  529. TRK96_EXIT:
  530.  
  531.         LES     BX,CS:PACKET  ; ES:BX = packet
  532.         MOV     ES:SRH_STAT[BX],AX              ; Save the status
  533.  
  534. ; do a little cleanup
  535.         call    oldparms          ; restore old pointer to disk parameter block
  536.         mov     cs:HDSET,0dh    ; and make sure our private one is right
  537.         mov     cs:mode2,2  ; head load ; since adjusted on fly for read-write
  538.  
  539. ; now set for return
  540.  
  541.         POPF
  542.         POP     DI
  543.         POP     SI
  544.         POP     ES
  545.         POP     CX
  546.         POP     BX
  547. ; get old stack
  548.         CLI
  549.         MOV     SS,CS:SS_SAVE
  550.         MOV     SP,CS:SP_SAVE
  551.         STI
  552.         POP     AX
  553.         RET    ; far return
  554.  
  555. DISK_INT ENDP
  556.  
  557. ;**     Set the busy status flag to show input queue empty
  558. BUSY    PROC NEAR
  559.         MOV     AH,SRHS_BUI
  560.         JMP     TRK96_EXIT
  561. BUSY    ENDP
  562.  
  563. ;       Unknown command requested
  564.  
  565. UNKNOWN proc near
  566.         MOV     AL,SRHS_EUKC            ; Unknown command code
  567.         JMP     ERROR           ; Flag error
  568. unknown endp
  569.  
  570.  
  571. ;       Correct the transfer count and flag error, used only for
  572. ;        R/W packets with CX=Number of blocks/chars left untransferred
  573.  
  574. ERRORC  PROC NEAR
  575.         LES     BX,CS:PACKET
  576.         SUB     ES:CRW_CNT[BX],CX
  577.         JMP     SHORT NO_OP
  578. ERRORC   ENDP
  579.  
  580. ;       No operation
  581. NO_OP   proc    near
  582.         JMP     TRK96_EXIT
  583. no_op   endp
  584.  
  585.  
  586. ;*      MEDIA_CHECK - return the disk change status
  587. ;               If a floppy
  588. ;                    Check if drive has been accessed within last
  589. ;                    2 secs, if so, return no change, else return
  590. ;                    don't know.
  591. ;
  592. ;       ENTRY:  ES:BX - Pointer to DOS packet
  593. ;               DS = CS
  594. ;
  595. ;       EXIT:   Packet status = Disk change status (-1 disk has changed,
  596. ;                                         0 don't know,
  597. ;                                         1 disk has not changed)
  598. ;
  599. MEDIA_CHECK PROC NEAR
  600.  
  601.         MOV     ES:CMC_STAT[BX],CMCS_DKN        ; Don't know if disk changed
  602.         MOV     AL,ES:SRH_UNIT[BX]              ; get unit number
  603. IF      D_2SEC                          ; Assemble if 2 sec delay chosen
  604. if debug
  605. ;        push    es
  606. ;        push    dx
  607. ;        call    putbyte
  608. ;        mov     dx, offset timeoutmsg
  609. ;        call    prtstring
  610. ;        pop     dx
  611. ;        pop     es
  612. endif;
  613. ;       See when floppy was last accessed
  614.  
  615.         CBW            ; make ax = al
  616.         MOV     CL,2   ; multiply by 4
  617.         SHL     AX,CL               ; Make unit into dword pointer
  618.         MOV     DI,AX               ; store ax in di for indexing later
  619.         MOV     CS:WORD PTR TIM_PTR,AX          ; Store pointer for later use
  620.         MOV     AH,TOD_GET
  621.         ; Get time from system
  622.         push    bx
  623.         INT     TIME_OF_DAY_INTR
  624.         pop     bx
  625.  
  626. if debug
  627.  ;       push    ax
  628.  ;       mov     ax,cx
  629.  ;       call    putword
  630.  ;       mov     ax,dx
  631.  ;       call    putword
  632.  ;       call    crlf
  633.  ;       mov     ax,cs:word ptr dsk_timout[DI+2]
  634.  ;       call    putword
  635.  
  636. ;       mov     ax,cs:word ptr dsk_timout[di]
  637. ;        call    putword
  638. ;        pop     ax
  639.  endif; { debug }
  640. ;
  641.         CMP     AL,0                            ; Same day?
  642.         JNZ     MC0                             ; No
  643.         SUB     DX,CS:WORD PTR DSK_TIMOUT[DI]   ; Get number of elapsed ticks
  644.         SBB     CX,CS:WORD PTR DSK_TIMOUT[DI+2]
  645.         JNZ     MC0                             ; Jump if too many ticks
  646.         CMP     DX,DSK_MAXVAL                   ; More than DSK_MAXVAL ticks?
  647.         JG      MC0  ; Yes
  648.         mov     al,1
  649.         mov     ES:BYTE PTR CMC_STAT[BX],al        ; Flag as not changed
  650.         ; increments from 0 to 1
  651. if debug
  652. ;        push    es
  653. ;        push    dx
  654. ;        mov     dx, offset notchanged
  655. ;        call    prtstring
  656. ;        pop     dx
  657. ;        pop     es
  658. endif; { debug }
  659.  
  660. MC0:
  661.         ENDIF         ; time_out check
  662.         JMP     TIM_RESET                       ; Reset timer and exit
  663.  
  664. MEDIA_CHECK ENDP
  665.  
  666.  
  667.         SUBTTL Build BPB for disk
  668.         PAGE
  669. ;**     BUILD_BPB
  670. ;       Return the address of a BPB that describes
  671. ;       the requested unit.
  672. ;       The new method is to to read the first sector of the
  673. ;       disk into a buffer, and move the bpb part into the bpb
  674. ;       storage spot. This is not completely adaptable, since the
  675. ;       implicit assumption is that sectors are 512 bytes long
  676. ;
  677. ;
  678. ;       ENTRY:  ES:BX - packet
  679. ;               DS - MYDISK segment
  680. ;
  681. ;       EXIT:   Packet has pointer to new BPB
  682. ;
  683.  
  684. oldbx   dw   0
  685. oldes   dw   0
  686.  
  687. BUILD_BPB PROC  NEAR
  688.  
  689. ;       Get BPB for floppy disk
  690. ;
  691. ife  bpbtest    ; quick and dirty bpb
  692.         MOV     AX, OFFSET cs:BPBDISK0
  693.         MOV     WORD PTR ES:CBPB_BADDR[BX],AX   ; Return offset and segment
  694.         MOV     WORD PTR ES:CBPB_BADDR[BX+2],cs
  695.         JMP     SUCESS
  696. endif
  697.  
  698. if bpbtest
  699.          mov     word ptr cs:oldbx,bx
  700.          mov     word ptr cs:oldes,es
  701.          MOV     AL,ES:SRH_UNIT[BX]      ; get unit number
  702.          and     al,1  ; 0 or 1 only possible values
  703.          mov     cs:bpbdrive,al       ; store it
  704.          call    newparms     ; set disk parameters correctly
  705.          call    fetchfirst    ; read first sector of disk
  706.          jc      fetcherror    ; carry set if error
  707.  
  708. getbpbsector:
  709.         mov     al,cs:bpbdrive    ; decide which table to use
  710.         or      al,al
  711.         jz      set0 ;
  712. set1:
  713.         mov     ax, offset bpbdisk1 ;  in case drive 1
  714.         jmp     movebpb
  715. set0:
  716.         MOV     AX,OFFSET BPBDISK0  ;
  717.  
  718. MOVEBPB:
  719.         mov     word ptr cs:newbpbptr,ax ; store the bpb-address again
  720. ; get disk bpb for validity
  721.         mov     ax,word ptr cs:disk_buf[beginbpb] ; get number of bytes
  722.         cmp     ax,0200h   ; minor test for validity of result
  723.         jz      FINISHUP  ; jz takes 8 bit displacement
  724.         jmp     UNKNOWN   ; can't handle this disk
  725.  
  726. FINISHUP:   ; haven't gotten here if unless new bpb is plausible
  727.         MOV     AX,offset disk_buf       ; BX SET FROM FETCHBPB CALL
  728.         add     AX,BEGINbpb  ;11 = offset to beginning of bpb in dos buffer
  729.         mov     si,ax ;  move ds:si to   es:di
  730.         mov     ax,cs
  731.         mov     ds,ax     ; set ds:si = cs:offset disk_buf + 11
  732.         mov     es,ax
  733.         mov     di,word ptr cs:newbpbptr  ;ax
  734.         mov     cx,type BPBDISK0  ; should give right length
  735.         cld              ; clear direction flag for loop
  736. move18:
  737.         MOVSB
  738.         loop   move18
  739.  
  740. ; now set pointers
  741.         mov     ax,word ptr cs:newbpbptr
  742.         mov     bx,word ptr cs:oldbx
  743.         mov     es,word ptr cs:oldes
  744.         MOV     WORD PTR ES:CBPB_BADDR[BX],AX   ; Return offset and segment
  745.         MOV     WORD PTR ES:CBPB_BADDR[BX+2],CS
  746.         JMP     SUCESS
  747. endif; if bpbtest
  748. BUILD_BPB ENDP
  749.  
  750. if bpbtest
  751. fetchfirst proc near
  752. ; set up presently only to control outboard drives 2..3 out of 0..3
  753.         add     al,2   ; outboard drives
  754.         mov     dl,al  ; drive number set up int 13h read call
  755. ; use int 13h to read sector 1 of track 0 side 0
  756. ; need dl=drive, es:bx =dta, ah= diskop, al = sectors to read
  757.         mov     BX,offset disk_buf ; GET THE TRANSFER ADDRESS
  758.         mov     ax,cs
  759.         mov     es,ax
  760.         mov     ah, DIO_READ
  761.         mov     al,1   ; read one sector
  762.         mov     dh,0   ; side 0
  763.         mov     ch,0   ; track 0
  764.         mov     cl,1   ; sector 1 of track 0
  765.         int     DISK_IO_INTR
  766.         ret
  767. fetchfirst endp
  768.  
  769. fetcherror proc near
  770. ; error code in ah if carry flag was set
  771. ; get ready to do error analysis
  772. ; decode error return from ROM routine
  773.         PUSH    CS                      ; Set up addressing
  774.         POP     ES
  775.         MOV     AL,AH                   ; Code in AL for scan
  776.         MOV     CX,L_ERR                ; Length of table
  777.         MOV     DI,OFFSET T_ERR
  778.         CLD
  779.         REPNZ   SCASB
  780.         MOV     AL,[DI+(L_ERR-1)]       ; Get the mapped error code
  781.         jmp     error   ; could not read bpb sector
  782. fetcherror endp
  783.  
  784. endif; if bpbtest
  785.  
  786. prtstring proc near
  787. ; takes string in ds:dx and prints until find '$'
  788.   push   ax
  789.   push   bx
  790.   push   cx
  791.   push   dx
  792. beginhere:
  793.   mov    bx,dx
  794.   mov    al,[bx]
  795.   cmp    al,'$'
  796.   jz     allover
  797.   push   dx
  798.   mov    dl,al
  799.   call   stdtout
  800.   pop    dx
  801.   inc    dx
  802.   jmp    beginhere
  803. allover:
  804.   pop    dx
  805.   pop    cx
  806.   pop    bx
  807.   pop    ax
  808.   ret
  809. prtstring endp
  810.  
  811. stdtout  proc  near
  812. ; takes byte in dl and outputs to the console
  813. ; don't use DOS calls to avoid re-entrant problem
  814. ;
  815.     push   ax
  816.     push   bx
  817.     push   cx
  818.     push   dx
  819.     mov    ah,14
  820.     mov    al,dl
  821.     mov    bh,0
  822.     mov    bl,0  ; should not matter
  823.     int    10h
  824. ;   mov    ah,0   ; send to printer for now
  825. ;   mov    al,dl
  826. ;   mov    dx,0
  827. ;   int    17h
  828.     pop    dx
  829.     pop    cx
  830.     pop    bx
  831.     pop    ax
  832.     ret
  833. stdtout   endp
  834.  
  835.  
  836. oldparmofs  dw    1 dup(?)
  837. oldparmseg  dw    1 dup(?)
  838.  
  839.  
  840.  
  841.  
  842. ;       Set up SI to point to disk BPB table
  843.  
  844. ;**     DISK I/O - This routine will handle all disk I/O calls
  845. ;
  846. ;       ENTRY:  ES:BX - pointer to DOS packet
  847. ;               DS = CS
  848. ;
  849. ;       EXIT:   None
  850. ;
  851.  
  852. DISK_READ PROC NEAR
  853.  
  854.         MOV     DOP_TYPE,DIO_READ       ; Read operation
  855.         mov     cs:HDSET, 0        ;
  856.         mov     cs:mode2,0              ; head load time
  857.         call    newparms
  858.         JMP     SHORT DOP1
  859.  
  860. DISK_READ ENDP
  861.  
  862. DISK_WRITE_VERIFY PROC NEAR
  863.         mov     cs:HDSET,0dh
  864.         mov     cs:mode2,2
  865.         call    newparms
  866.         MOV     DOP_VERIFY,1            ; Write with verify
  867.         JMP     SHORT DOP0
  868. DISK_WRITE_VERIFY ENDP
  869.  
  870. DISK_WRITE PROC NEAR
  871.         mov     cs:HDSET,0dh
  872.         mov     cs:mode2,2
  873.         call    newparms
  874.         MOV     DOP_VERIFY,0            ; Write no verify
  875. DOP0:
  876.         MOV     DOP_TYPE,DIO_WRITE      ; Write operation
  877. DOP1:
  878.         MOV     CX,ES:CRW_CNT[BX]       ; Count of sectors
  879.         CMP     CX,0                    ; If count = 0 then done
  880.         JNZ     DOP2
  881.         JMP     SUCESS
  882.  
  883. ;       Set up SI to point to disk BPB table
  884.  
  885. DOP2:
  886.         MOV     SEC_CNT,CX              ; Save sector count
  887.         MOV     OLD_SP1,SP              ; Save stack for error exit
  888.         MOV     AL,ES:SRH_UNIT[BX]      ; Get unit and save
  889.         and     al,1
  890.         MOV     DRIVE,AL
  891.  
  892.  
  893. ;       Address disk parameter table
  894. ;       how would the media byte know what it was?
  895.  
  896.         MOV     AL,drive     ; Get the drive number
  897.         MOV     AH,TYPE BPB_STRUC
  898.         MUL     AH
  899.         ADD     AX,OFFSET BPBDISK0
  900.         MOV     SI,AX                   ; Get pointer to BPB table
  901.         mov     ax,cs
  902.         mov     ds,ax
  903.         MOV     AL, BYTE PTR BPB_SPT[SI]
  904.  
  905.         ASSUME  DS:code
  906.  
  907. DOP5:
  908.         MOV     CX,SEC_CNT              ; Set up sector count in case of error
  909.  
  910. ;       Check if last requested sector lies on this disk
  911.  
  912.         MOV     DX,ES:CRW_START[BX]
  913.  
  914.         MOV     DI,DX                   ; Start sector
  915.         ADD     DI,CX                   ; # of sectors
  916.  
  917.         JC      DOP7                    ; Bad parms, no such sector
  918.  
  919. DOP6:
  920.         CMP     DI,BPB_SECS[SI] ; compare to last sector on disk
  921.         JBE     DOP8                    ; Request OK
  922.  
  923. DOP7:
  924.         MOV     AL,SRHS_ESNF            ; Sector not found error
  925.         JMP     DISK_ERROR1
  926.  
  927. DOP8:
  928.         ADD     DX,BPB_HIDDEN[SI]       ; Add in hidden sectors
  929.  
  930.  
  931.         ASSUME  DS:code
  932.  
  933.  
  934.  
  935. ;       Calculate track, sector number and head
  936.  
  937. DOP10:
  938.         CALL    DECODE                  ; Set necessary regs for call to DOP18
  939.         MOV     DL,DRIVE                ; Move drive to DL for ROM
  940.  
  941.         add     dl,2                    ; map it to floppies 2,3
  942.                                         ; instead of 0,1
  943.  
  944. ;       Check if transfer lies within this 64K boundry for DMA
  945.  
  946.         LES     BX,ES:CRW_TADDR[BX]     ; Get transfer address
  947. DOP11:
  948.         MOV     AX,ES                   ; Get 16 bits of transfer address
  949.         PUSH    CX
  950.         MOV     CL,4
  951.         SHL     AX,CL
  952.         MOV     CL,9                    ; Prepare for next shift operation
  953.         ADD     AX,BX
  954.         NEG     AX                      ; Find remainder of this 64K
  955.         JNZ     DOP12
  956.         MOV     AH,80H                  ; Special case, full 64K available
  957.         DEC     CL                      ; Correct shift count
  958. DOP12:
  959.         SHR     AX,CL                   ;  this 64K
  960.         POP     CX
  961.         JZ      DOP14                   ; If none left in this 64K, get 1 sector
  962.         CMP     AX,SEC_CNT              ; Can request be honored?
  963.                                         ;  AX <  SEC_CNT Can't service
  964.                                         ;  AX >= SEC_CNT Can service
  965.         JB      DOP13
  966.         MOV     AX,SEC_CNT
  967.  
  968. ;       R/W the requested number of sectors
  969.  
  970. DOP13:
  971.         CALL    DOP18                   ; R/W the sectors
  972.         JC      DISK_ERRORL
  973.         CMP     SEC_CNT,0               ; Update sector count
  974.         JNZ     DOP14                   ; R/W across 64kb boundry
  975.  
  976. DISK_EXIT:
  977.  
  978. TIM_RESET:
  979.         IF      D_2SEC
  980.  
  981.         MOV     DI,CS:WORD PTR TIM_PTR  ;
  982.     ; was set by media_check???     Get offset into timout table
  983.         MOV     CS:WORD PTR TIM_PTR,0FFFH       ; Make pointer invalid
  984.         MOV     AL,NUM_FLOPPY           ; Get total number of floppies
  985.         CBW
  986.         MOV     CL,2                    ; Make an offset
  987.         SHL     AX,CL                   ; multiply by 4
  988.         CMP     DI,AX                   ; Is it a floppy?
  989.         JGE     DISK_EXIT1              ; No
  990.         MOV     AH,TOD_GET              ; Get time from ROM
  991.         INT     TIME_OF_DAY_INTR
  992.         MOV     CS:WORD PTR DSK_TIMOUT[DI],DX   ; Store low word
  993.         MOV     CS:WORD PTR DSK_TIMOUT[DI+2],CX ; Store high word
  994.  
  995. DISK_EXIT1:
  996.         ENDIF
  997.  
  998.  
  999.  
  1000.  
  1001.         JMP     SUCESS          ; All done!
  1002.  
  1003. ;       Need to R/W 1 sector to cross 64Kb boundry
  1004.  
  1005. DOP14:
  1006.         CLD                             ; Clear direction for later use
  1007.         PUSH    ES                      ; Save user buffer area
  1008.         PUSH    BX
  1009.  
  1010.         CMP     DOP_TYPE,DIO_READ
  1011.         JZ      DOP15                   ; Read one sector
  1012.  
  1013. ;       Copy user data to internal buffer and write it
  1014.  
  1015.         PUSH    ES                      ; Set up segments for source and dest.
  1016.         PUSH    CS
  1017.         POP     ES
  1018.         POP     DS
  1019.         PUSH    SI                      ; Save disk table pointer
  1020.         MOV     SI,BX                   ; Set up source offset
  1021.         MOV     DI,OFFSET DISK_BUF      ; Set up dest. offset
  1022.         MOV     BX,DI                   ; Set up X-fer offset for disk write
  1023.  
  1024.         PUSH    CX                      ; Save CX
  1025.         MOV     CX,SEC_SIZE/2           ; Move 1 sector (512b) of data
  1026.         REP     MOVSW
  1027.         POP     CX                      ; Restore CX
  1028.         POP     SI                      ; Restore disk table pointer
  1029.         PUSH    CS                      ; Restore data segment
  1030.         POP     DS
  1031.  
  1032.         CALL    DOP17                   ; Write 1 sector
  1033.         JC      DISK_ERRORL
  1034.         POP     BX                      ; Restore user buffer
  1035.         POP     ES
  1036.         ADD     BH,SEC_SIZE SHR 8
  1037.         JMP     SHORT DOP16
  1038.  
  1039. DISK_ERRORL:
  1040.         JMP     DISK_ERROR
  1041.  
  1042. ;       Read 1 sector, transfer it to the users area and continue
  1043.  
  1044. DOP15:
  1045.         PUSH    CS                      ; Set up MYDISK transfer address
  1046.         POP     ES
  1047.         MOV     BX,OFFSET DISK_BUF
  1048.         CALL    DOP17
  1049.         JC      DISK_ERRORL
  1050.         POP     DI                      ; restore user transfer address
  1051.         POP     ES
  1052.  
  1053.         PUSH    SI                      ; Save disk pointer table
  1054.         MOV     SI,OFFSET DISK_BUF
  1055.         PUSH    CX                      ; Save CX
  1056.         MOV     CX,SEC_SIZE/2           ; Move 1 sector of data to user
  1057.         REP     MOVSW
  1058.         POP     CX                      ; restore CX
  1059.         POP     SI                      ; Restore disk table pointer
  1060.  
  1061.         MOV     BX,DI                   ; Update user address
  1062. DOP16:
  1063.         CMP     SEC_CNT,0               ; All done?
  1064.         JZ      DISK_EXITL
  1065.         JMP     DOP11
  1066. DISK_EXITL:
  1067.         JMP     DISK_EXIT
  1068.  
  1069. ;*      Read/Write sectors
  1070. ;
  1071. ;       Entry:
  1072. ;               AX - count of sectors to R/W (1 if entering at DOP17)
  1073. ;               CH - Track number
  1074. ;               CL - Sector number
  1075. ;               DL - Drive
  1076. ;               DH - Head number
  1077. ;               ES:BX - transfer address
  1078. ;               DS:SI - BPB of disk
  1079. ;               DOP_TYPE - Code to pass the ROM for read or write
  1080. ;
  1081. ;       Exit:
  1082. ;               'C' set, a disk error has occured
  1083. ;               'C' clear, operation sucessful
  1084. ;               AX,
  1085. ;               BX (updated load address),
  1086. ;               CX (updated track and sector),
  1087. ;               DH (updated head number),
  1088. ;               DI.
  1089. ;
  1090. DOP17:
  1091.         MOV     AX,1                    ; R/W 1 Sector
  1092. DOP18:
  1093.         MOV     OLD_SP2,SP              ; Save old stack for quick error exit
  1094.         MOV     RETRY_COUNT,NUM_RETRY
  1095.         PUSH    AX                      ; Save count
  1096.         MOV     AL,BYTE PTR BPB_SPT[SI] ; Get sectors per track
  1097.         PUSH    CX
  1098.         AND     CL,3FH
  1099.         SUB     AL,CL                   ; How many sectors left on this track?
  1100.         POP     CX
  1101.         INC     AL
  1102.         CBW                             ; Clear high byte
  1103.         POP     DI                      ; Restore count
  1104.         CMP     DI,AX                   ; See if request will fit in this track
  1105.         JAE     DOP19                   ; Yes, fulfill request
  1106.         MOV     AX,DI                   ; No, get remainder of this track
  1107.  
  1108. ;       Do the actual disk read/write
  1109.  
  1110. DOP19:
  1111.         PUSH    AX                      ; Save count
  1112.         MOV     AH,DOP_TYPE             ; Pass operation type
  1113.         INT     DISK_IO_INTR            ; Call ROM
  1114.         JC      RETRY                   ; Retry on error
  1115.         POP     AX                      ; Restore count
  1116.  
  1117. ;       Check for verify
  1118.  
  1119.         CMP     WORD PTR DOP_TYPE,1 SHL 8 + DIO_WRITE ; Check for verify-write
  1120.         JNZ     DOP20
  1121.         PUSH    AX
  1122.         MOV     AH,DOP_VERIFY           ; Verify sectors
  1123.         INT     DISK_IO_INTR
  1124.         JC      RETRY
  1125.         POP     AX
  1126.  
  1127. DOP20:
  1128.         SUB     SEC_CNT,AX              ; Update sector count
  1129.  
  1130.         MOV     AH,AL                   ; Copy sector count to AH
  1131.         SHL     AH,1                    ; Turn into 512 byte sectors
  1132.         ADD     BH,AH                   ; Update load address
  1133.         SUB     AH,AH                   ; Fix up sector count
  1134.  
  1135.         SUB     DI,AX                   ; Update count
  1136.  
  1137. ;       Update head, track and sector
  1138.  
  1139. DOP21:
  1140.         PUSH    BX                      ; Free up a register
  1141.         MOV     BH,0  ; cl get Cylinder in BX
  1142.         ;ROL    BH,1
  1143.         ;ROL    BH,1
  1144.         ;AND    BH,0                    ; assume cylinder < 256
  1145.         MOV     BL,CH
  1146.  
  1147.         AND     CL,3FH                  ; Isolate sector bits
  1148.         ADD     CL,AL                   ; Get new sector to start at
  1149.         CMP     CL,BYTE PTR BPB_SPT[SI] ; Check if beyond end of track
  1150.         JBE     DOP22                   ; No, skip
  1151.         MOV     CL,1                    ; Past end, now at sector 1
  1152.         INC     DH
  1153.  
  1154.         CMP     DH,BYTE PTR BPB_HEADS[SI]
  1155.         JB      DOP22
  1156.         SUB     DH,DH                   ; Back to head zero
  1157.         INC     BX                      ; Next track
  1158. DOP22:
  1159. ;
  1160. ;       ROR     BH,1                    ; Set up track and sector registers
  1161. ;       ROR     BH,1
  1162.         OR      CL,BH
  1163.         MOV     CH,BL
  1164.         POP     BX                      ; Restore transfer address
  1165.  
  1166.         CMP     DI,0                    ; Operation done?
  1167.         JNZ     DOP23
  1168.         CLC
  1169.         RET
  1170. DOP23:
  1171.         MOV     AX,DI                   ; Update remaining sector count
  1172.         JMP     DOP18                   ; Continue
  1173.  
  1174. RETRY:
  1175.         PUSH    AX                      ; Save return code
  1176.         MOV     AH,DIO_RESET            ; Reset disk system
  1177.         INT     DISK_IO_INTR
  1178.         POP     AX                      ; Restore return
  1179.         CMP     AH,TIME_OUT             ; Test for disk time out
  1180.         JZ      RETRY1
  1181.         DEC     RETRY_COUNT
  1182.         JZ      RETRY1
  1183.         POP     AX                      ; Restore count and
  1184.         JMP     DOP19                   ;  try again
  1185. RETRY1:
  1186.         MOV     SP,OLD_SP2              ; Restore stack to entry conditions
  1187.         STC                             ; Show error
  1188.         RET
  1189.  
  1190. ;       Retry error has occured. Get the ROM error code and map to
  1191. ;       an MS-DOS error code.
  1192.  
  1193. DISK_ERROR:
  1194.         PUSH    CS                      ; Set up addressing
  1195.         POP     ES
  1196.         MOV     AL,AH                   ; Code in AL for scan
  1197.         MOV     CX,L_ERR                ; Length of table
  1198.         MOV     DI,OFFSET T_ERR
  1199.         CLD
  1200.         REPNZ   SCASB
  1201.         MOV     AL,[DI+(L_ERR-1)]       ; Get the mapped error code
  1202.  
  1203. ;*      Disk error
  1204. ;
  1205. ;       Entry: AL - Error code
  1206. ;              SEC_CNT - Count of sectors not yet done
  1207. ;
  1208. DISK_ERROR1:
  1209.         MOV     CX,SEC_CNT              ; Return the number of sectors left to transfer
  1210.         MOV     SP,OLD_SP1              ; Pop the stack to entry conditions
  1211.         JMP     ERRORC
  1212.  
  1213. DISK_WRITE ENDP
  1214.  
  1215. NEWPARMS proc near   ; can't use dos call to reset pointer
  1216.         ;ret          ; for testing
  1217.         cli
  1218.         push    ax
  1219.         push    bx
  1220.         PUSH    DX
  1221.         PUSH    DS
  1222.         SUB     DX,DX
  1223.         MOV     DS,DX     ; look in segment 0
  1224.  
  1225.  ASSUME DS:NOTHING
  1226.         ; have a pointer to current disk parameter table at 1eh
  1227.         mov     bx,001eh shl 2   ; 1eh double words
  1228.         mov     ax, offset cs:myparameters
  1229.         mov     [bx],ax
  1230.         inc      bx
  1231.         inc      bx
  1232.         mov      ax,cs
  1233.         mov      [bx],ax
  1234.       ;
  1235.         POP     DS
  1236.         POP     DX
  1237.         pop     bx
  1238.         pop     ax
  1239.         sti
  1240.         ret
  1241. NEWPARMS ENDP
  1242.  
  1243.       assume ds:code
  1244.  
  1245. oldparms proc near
  1246.         ;ret  ; for testing
  1247.         cli
  1248.         push   ax
  1249.         push   bx
  1250.         PUSH   DX
  1251.         PUSH   DS
  1252.         xor     ax,ax
  1253.         MOV     DS,ax     ; look in segment 0
  1254.         ASSUME  DS:NOTHING
  1255.         ; have a pointer to current disk parameter table at 1eh
  1256.         mov     bx,001eh shl 2  ; point to current ROM parameters
  1257.         mov     ax,cs:oldparmofs  ; get value there
  1258.         mov     [bx],ax
  1259.         mov     ax,cs:oldparmseg  ; get value there
  1260.         inc     bx
  1261.         inc     bx
  1262.         mov     [bx],ax
  1263.         POP     DS
  1264.         POP     DX
  1265.         pop     bx
  1266.         pop     ax
  1267.         sti
  1268.         ret
  1269. oldparms endp
  1270.  
  1271.  
  1272.       assume ds:code
  1273.  
  1274. ;       DECODE - This routine will take a MS-DOS logical sector number
  1275. ;               and decode it into head sector and cylinder for the
  1276. ;               given disk.
  1277. ;        add adjustment to double step 96 tpi drive if using 48 tpi media
  1278. ;        ; this not working yet
  1279. ;
  1280. ;       ENTRY:  DX - Logical sector number
  1281. ;               DS:SI - Pointer to BPB for this disk
  1282. ;
  1283. ;       EXIT:   CH - Cylinder number
  1284. ;               CL - Sector number
  1285. ;               DH - Head
  1286. ;
  1287. ;       USES:   AX
  1288. ;
  1289. DECODE  PROC    NEAR
  1290.  
  1291.         PUSH    BX
  1292.         MOV     BX,DX
  1293.         SUB     AX,AX
  1294.         XCHG    AX,DX                   ; AX = Start sector
  1295. ; divide dx:ax by sectors per track
  1296. ; get quotient in ax, remainder in dx
  1297.  
  1298.         DIV     WORD PTR BPB_SPT[SI]    ; divide by sectors per track
  1299. ; run sectors 1 .. spt
  1300.         INC     DL                      ; DL = Sector #, AX = track
  1301.         MOV     CL,DL                   ; Move sector into CL for ROM
  1302.         SUB     DX,DX
  1303.  
  1304. ; decide on tracks
  1305. ; track in ax, head in dl
  1306.  
  1307.         DIV     WORD PTR BPB_HEADS[SI]
  1308.         MOV     DH,DL                   ; Put head into DH for ROM
  1309.  
  1310. ; max cylinder is 8 bits = 1024
  1311.  
  1312.         AND     AH,0            ; Ensure no high bits for cyl.
  1313.         OR      CL,AH           ; Set sector and cyl. high bits
  1314.         MOV     CH,AL                   ; Low part of cyl. for ROM
  1315.  
  1316. around: MOV     DL,BL                   ; Restore DL
  1317.         POP     BX
  1318.         RET
  1319.  
  1320. DECODE  ENDP
  1321.  
  1322. DISK_BUF LABEL  BYTE            ; Disk buffer after initialization complete
  1323.          db     512  dup(?)     ; 512  dup(?)
  1324.  
  1325.  
  1326. MYDISK_END LABEL NEAR
  1327.  
  1328. DISK_INIT PROC  NEAR
  1329. ; put at end so can discard after initialization
  1330. ; DISK_INIT fills in ES:BX with address of Request header
  1331. ; returns break address in ds:dx
  1332. ; so don't save old ds:dx on stack
  1333.  
  1334. ; the device driver init is slightly different from the
  1335. ; bios init, in that ds:dx contains information
  1336. ; hence have to
  1337. ; change disk_int
  1338. ; disk_exit
  1339. ; use mdisk as a template for these changes
  1340.  
  1341.  
  1342.         push    ax
  1343.         push    bx
  1344.         push    es
  1345.         mov     ax,cs
  1346.         mov     ds,ax
  1347.         mov     ah,19h  ; get current drive number
  1348.         int     21h
  1349.         mov     dl,al   ; set up call to find out number of drives
  1350.         mov     ah,0eh  ; log current disk again and get number of drives
  1351.         int     21h
  1352.         add     al,'A'  ; make it alpha
  1353.         mov     drive0,al  ; put into signon message
  1354.         inc     al
  1355.         mov     drive1,al
  1356.         mov     dx, offset hereiam
  1357.         call    prtstring
  1358.         pop     es
  1359.         pop     bx
  1360.         pop     ax
  1361.  
  1362.  
  1363. ;have told world what we do
  1364.  
  1365. ; remember standard disk parameters from DOS
  1366.         cli
  1367.         push    ax
  1368.         push    bx
  1369.         push    ds
  1370.         xor     ax,ax
  1371.         mov     ds,ax
  1372.         mov     bx,001eh shl 2   ; 1eh double words
  1373.         mov     ax,[bx] ; get offset
  1374.         mov     cs:oldparmofs,ax
  1375.         inc     bx
  1376.         inc     bx
  1377.         mov     ax,[bx]
  1378.         mov     cs:oldparmseg,ax
  1379.         pop     ds
  1380.         pop     bx
  1381.         pop     ax
  1382.         sti
  1383.  
  1384. ; return number of units
  1385.  
  1386.         mov     al,2     ; NUM_DISKS
  1387.         MOV     ES:[CIN_UNITS + BX],al  ; two units
  1388.  
  1389. ; return end of this driver code
  1390. ; normalize it to largest possible segment
  1391.  
  1392.         mov     ax,cs
  1393.         mov     ds,ax
  1394.         mov     dx, offset mydisk_end + 17; { add a little room }
  1395.         mov     cx,4
  1396.         shr     dx,cl  ; make it a paragraph boundary
  1397.         add     ax,dx  ; ax had cs from before
  1398.         xor     dx,dx  ; round it off
  1399.  
  1400. ; must also return break address in DS:DX, according to manual
  1401.  
  1402.         mov     ds,ax  ; segment
  1403.         MOV     ES:word ptr CIN_KADDR[BX],  DX  ; Break address
  1404.         MOV     ES:word ptr CIN_KADDR[BX+2],AX  ;  dword
  1405.         MOV     ES:word ptr CIN_BADDR[BX],  OFFSET BPB_VECTOR
  1406.         MOV     ES:word ptr CIN_BADDR[BX+2],CS
  1407.  
  1408. ; what about status word, and media byte??
  1409.  
  1410.         JMP     SUCESS
  1411.  
  1412. DISK_INIT ENDP
  1413.  
  1414. HEREIAM DB      0dh,0ah,'96 TPI Driver installed for two external drives, '
  1415. drive0  db      43h,': and '
  1416. drive1  db      44h,':'
  1417. if d_2sec
  1418.         DB      0dh,0ah,'Version 1.3 using media change timeout of 6 seconds.'
  1419. endif;
  1420. if bpbtest
  1421.         db      0dh,0ah,'Reads track 0, side 0, sector 1 BPB'
  1422.         db      ' for disk information.'
  1423. endif;
  1424. if debug
  1425.         db      0dh,0ah,'Debugging test version.'
  1426. endif;
  1427.         db      0dh,0ah,'Copyright by Clarence Wilkerson 6-11-1986.'
  1428.         db      0dh,0ah,'$'
  1429.  
  1430. MYDISK_LENGTH   =       OFFSET MYDISK_END - OFFSET MYDISK_START
  1431.  
  1432. CODE    ENDS
  1433.         END      mydisk_start
  1434.