home *** CD-ROM | disk | FTP | other *** search
/ Chip 2000 May / Chip_2000-05_cd2.bin / dosutils / partprog / pdisk.arc / PDISK.ASM < prev    next >
Assembly Source File  |  1989-01-12  |  11KB  |  439 lines

  1.     TITLE    DISK -- A Multiple Disk Driver
  2.     SUBTTL    Header and global definitions
  3.     PAGE    64D,132D    ; make line length 132
  4. ;    .286
  5.     .radix    16
  6.     OK186    EQU    (@Cpu and 02)
  7.  
  8. ;DISK_NO    EQU    1    ; should get this from makefile
  9. RQ        STRUC    ; Standard Request Header
  10. RQ_LEN        DB    ?     ; number of bytes passed  -- first field
  11. RQ_UCD        DB    ?     ; unit code
  12. RQ_CCD        DB    ?     ; command code
  13. RQ_STAT        DW    ?     ; status (return code)
  14. RQ_RES        DB    8 DUP(?) ; reserved area
  15. RQ        ENDS
  16. ; Status field bit equates
  17. STAT_ERR    EQU    8000    ; There was an error.  See low byte.
  18. STAT_BUSY    EQU    200    ; Busy.  Used in build BPB call.
  19. STAT_DONE    EQU    100    ; Operation complete.
  20. ; low byte error return codes.
  21. STAT_GEN_FAIL    EQU    0E    ; general failure
  22. STAT_READ_FAULT    EQU    0BH    ; read fault
  23. STAT_WRITE_FAULT EQU    0A    ; write fault
  24. STAT_NOT_FOUND    EQU    8    ; sector not found
  25. STAT_UNK_CMD    EQU    3    ; unknown command
  26. STAT_UNK_UNIT    EQU    1    ; unknown unit
  27. ;
  28. CSEG         SEGMENT
  29. ; start driver.  first section is data
  30. ; (though it is in the code segment)
  31.         ASSUME    CS:CSEG,DS:NOTHING,ES:NOTHING
  32. ;  special device header
  33. ; This MUST be at ORG 0 (i.e. the first code).
  34. START        EQU    $
  35. NEXT_DEV    DD    -1        ; ptr to next device
  36. ATTRIBUTE    DW    4800        ; block device, supports 3.x, ioctl
  37. STRATEGY    DW    DEV_STRAT    ; ptr to device strategy
  38. INTERRUPT    DW    DEV_INT        ; ptr to dev interrupt handler
  39. DEV_COUNT    DB    0        ; number of units
  40. DEV_NAME    DB    'SEGdsk','0'+DISK_NO    ; 7 bytes of filler
  41. DRVTBL  LABEL   WORD
  42.     DW    INIT
  43.     DW    MEDIA_CHK
  44. ; according to DOS tech manual, BUILD_BPB should never get called, as long as
  45. ; MEDIA_CHK always returns "media unchanged" [sic].  However, this is not true.
  46. ; DOS's "reserved" functions 1F and 32 call it, anyway.
  47.     DW    BUILD_BPB
  48.     DW    EXIT        ; would be IOCTL_IN
  49.     DW    DOTRANS
  50.     DW    CMDERR
  51.     DW    CMDERR
  52.     DW    CMDERR
  53.     DW    DOTRANS
  54.     DW    DOTRANS
  55.     DW    CMDERR
  56.     DW    CMDERR
  57.     DW    IOCTL_OUT
  58.     DW    EXIT
  59.     DW    EXIT
  60.     DW    REMOVE
  61.     DW    CMDERR
  62. PTRSAV    DD    ?    ; for DEVSTRAT
  63.     SUBTTL    Small Routines (interrupt, entry, exit, error, media check)
  64.     PAGE
  65. STRATP    PROC    FAR    ; device strategy
  66. DEV_STRAT:
  67.     MOV    WORD PTR CS:[PTRSAV],BX
  68.     MOV    WORD PTR CS:[PTRSAV+2],ES
  69.     RET
  70. STRATP    ENDP
  71.  
  72. DEV_INT:        ; device interrupt handler
  73. IF    OK186
  74.     PUSHA
  75. ELSE
  76.     PUSH    AX
  77.     PUSH    BX
  78.     PUSH    CX
  79.     PUSH    DX
  80.     PUSH    SI
  81.     PUSH    DI
  82.     PUSH    BP
  83. ENDIF
  84.     PUSH    DS
  85.     PUSH    ES
  86.     ASSUME  DS:CSEG
  87.     MOV    AX,CS        ; get normal data addressability (DS=CS)
  88.     MOV    DS,AX
  89.     LES    BP,[PTRSAV]
  90.     MOV    AL,ES:[BP].RQ_CCD        ; Command code
  91.     CMP    AL,10
  92.     JA    CMDERR            ; Bad command
  93.     CBW                ; = xor ah,ah
  94.     SHL    AX,1            ; 2 times command = word table index
  95.     MOV    SI,AX
  96.     JMP    WORD PTR [SI].DRVTBL        ; Index into table
  97. ;
  98. STD_BPB        STRUC        ; a bios parameter block
  99. B_PER_S        DW    ?
  100. SEC_PER_AU    DB    ?
  101. RES_SECTS    DW    ?
  102. NFATS        DB    ?
  103. NDIRENTS    DW    ?
  104. NSECTS        DW    ?
  105. MEDIA_DES    DB    ?
  106. NFATSECTS    DW    ?    ; last word of standard portion
  107. STD_BPB        ENDS
  108.  
  109. STD_BPB_LEN    EQU    TYPE STD_BPB
  110.  
  111. BPB        STRUC
  112.         DB    STD_BPB_LEN DUP (?)
  113. RELSEC        DD    ?    ; add-on: see part_rec.rel_sect
  114. PARTNO        DB    ?    ; save partition number of this drive
  115. BPB        ENDS
  116. ;
  117. BPB_NDX        DW    OFFSET BPB_SPACE
  118.         DW    (OFFSET BPB_SPACE)+(TYPE BPB)
  119.         DW    (OFFSET BPB_SPACE)+2*(TYPE BPB)
  120.         DW    (OFFSET BPB_SPACE)+3*(TYPE BPB)
  121. ;
  122. BBPBDATA    STRUC    ; build bpb data struct
  123. BP_RQ        DB    (TYPE RQ) DUP(?) ; standard part
  124. BP_MDES        DB    ?        ; media descriptor (input)
  125. BP_TRANS    DD    DWORD PTR ?    ; transfer address
  126. BP_RET1        DW    ?
  127. BP_RET2        DW    ?
  128. BBPBDATA    ENDS
  129. ;
  130. BUILD_BPB:
  131.     MOV    AL,ES:[BP].RQ_UCD
  132.     CBW
  133.     MOV    SI,AX
  134.     SHL    SI,1
  135.     MOV    SI,[SI].BPB_NDX
  136.     MOV    ES:[BP].BP_RET1,SI
  137.     MOV    ES:[BP].BP_RET2,CS
  138.     JMP    SHORT EXIT
  139. ;
  140. MCDATA        STRUC    ; media check data struct
  141. MC_RQ        DB    (TYPE RQ) DUP(?) ; standard part
  142. MC_MDES        DB    ?        ; media descriptor (input)
  143. MC_RET        DB    ?        ; returned byte: 1 if media unchanged
  144. MCDATA        ENDS
  145. ;
  146. MEDIA_CHK:    ; Winchesters never change
  147.     MOV    ES:[BP].MC_RET,1
  148.     JMP    SHORT EXIT
  149. REMOVE:
  150.     MOV    AX,STAT_DONE+STAT_BUSY    ; "busy" bit = non-removable medium
  151.     JMP    SHORT ERR1
  152. CMDERR:
  153.     MOV    AX,STAT_ERR+STAT_UNK_CMD+STAT_DONE    ; unknown command error
  154.     JMP    SHORT ERR1
  155.  
  156. IOCTL_OUT:            ; only valid return is a copy of the extended BPB
  157.     MOV    AL,ES:[BP].RQ_UCD
  158.     CBW                ; promote AL to AX with sign extension
  159.     SHL    AX,1            ; make device number into table offset
  160.     MOV    SI,AX
  161.     MOV    AX,ES
  162.     LES    DI,DWORD PTR ES:[BP].RW_TRANS
  163.     MOV    SI,[SI].BPB_NDX        ; now SI points to the correct BPB
  164.     MOV    CX,TYPE BPB        ; get length of data to transfer
  165.     REP    MOVSB
  166.     MOV    ES,AX
  167.     MOV    ES:[BP].RW_COUNT,TYPE BPB ; set length of data transferred
  168.     JMP    SHORT EXIT
  169.  
  170. EXITP   PROC    FAR        ; EXIT - All routines return through this path
  171. EXIT:   MOV    AX,STAT_DONE        ; "done" (no error)
  172. ERR1:   MOV    ES:[BP].RQ_STAT,AX    ; mark operation complete
  173.     POP    ES
  174.     POP    DS
  175. IF    OK186
  176.     POPA
  177. ELSE
  178.     POP    BP
  179.     POP    DI
  180.     POP    SI
  181.     POP    DX
  182.     POP    CX
  183.     POP    BX
  184.     POP    AX
  185. ENDIF
  186.     RET        ; restore regs and return
  187. EXITP   ENDP
  188.     SUBTTL    Read and Write sectors
  189.     PAGE
  190.  
  191. RWDATA        STRUC
  192. RW_RQ        DB    (TYPE RQ) DUP(?) ; standard part
  193. RW_MEDIA    DB    ?          ; media descriptor
  194. RW_TRANS    DD    DWORD PTR ?      ; transfer address
  195. RW_COUNT    DW    ?          ; # of sectors to transfer
  196. RW_START    DW    ?          ; first block to transfer
  197. RWDATA        ENDS
  198. ;
  199. ; local variables:
  200. DISK_ADDR    EQU    7F+DISK_NO    ; 0x80 = disk #1, 0x81 = disk 2.
  201. NSECS        DB    ?    ; number of sectors per track
  202. SHPROD        DW    ?    ; NHEADS*NSECS
  203. ;
  204. DOTRANS:
  205.     MOV    AL,ES:[BP].RQ_UCD
  206.     CBW                ; promote AL to AX with sign extension
  207.     MOV    SI,AX
  208.     INC    AX            ; (adjust for 1-based)
  209.     CMP    AL,[DEV_COUNT]
  210.     JLE    OK_COUNT
  211.     MOV    AX,STAT_ERR+STAT_DONE+STAT_UNK_UNIT
  212.     JMP    SHORT ERR1
  213. OK_COUNT:
  214.     SHL    SI,1            ; make device number into table offset
  215.     MOV    SI,[SI].BPB_NDX        ; now SI points to the correct BPB
  216.     MOV    BX,ES:[BP].RW_START    ; starting sector of request
  217.     MOV    DI,BX            ; start_sec+sec_trans>num_secs =>error
  218.     MOV    AX,ES:[BP].RW_COUNT
  219.     ADD    BX,AX
  220.     CMP    BX,[SI].NSECTS
  221.     JBE    OK_COUNT2
  222.     MOV    AX,STAT_ERR+STAT_DONE+STAT_NOT_FOUND
  223.     JMP    SHORT ERR1
  224. OK_COUNT2:
  225.     MOV    BX,AX            ; save
  226.     MOV    AX,WORD PTR [SI].RELSEC
  227.     MOV    DX,WORD PTR [SI+2].RELSEC
  228.     ADD    AX,DI        ; add starting relative sector word to request
  229.     ADC    DX,0        ; add carry, if any, to high word
  230.     DIV    [SHPROD] ; AX=DX:AX div CX (CX=nsects*nheads), DX=DX:AX mod CX
  231. IF    OK186
  232.     SHL    AH,6
  233. ELSE
  234.     MOV    CL,6    ; Need to put into screwy BIOS format
  235.     SHL    AH,CL
  236. ENDIF
  237.     XCHG    AL,AH
  238.     MOV    CX,AX
  239.     MOV    AX,DX    ; now get head and sector number
  240.     DIV    [NSECS]    ; now AH=sector number, AL=head number
  241.     MOV    DH,AL
  242.     OR    CL,AH
  243.     INC    CX    ; sector number is 1 based, not 0 based (from MOD)
  244.     MOV    DL,DISK_ADDR    ; drive code
  245.     MOV    AX,BX        ; get original RW_COUNT back
  246.     CMP    AX,80
  247.     JLE    BIOS_OK1
  248. BIOS_BAD1:
  249.     MOV    AX,STAT_ERR+STAT_DONE+STAT_GEN_FAIL
  250.     JMP    SHORT ERR1
  251. BIOS_OK1:
  252.     MOV    BX,WORD PTR ES:[BP].RW_TRANS
  253.     PUSH    CX
  254.     PUSH    DX
  255.     MOV    DI,AX
  256. IF    OK186
  257.     SHL    AX,9
  258. ELSE
  259.     MOV    CL,9
  260.     SHL    AX,CL
  261. ENDIF
  262.     MOV    DX,AX
  263.     ADD    AX,BX
  264.     JNC    BIOS_OK2
  265.     SUB    DX,AX
  266.     MOV    AX,DX
  267. IF    OK186
  268.     SHR    AX,9
  269. ELSE
  270.     SHR    AX,CL
  271. ENDIF
  272.     MOV    ES:[BP].RW_COUNT,AX
  273.     JMP    SHORT SKIP_OK2    ; skip restore of original AX
  274. BIOS_OK2:
  275.     MOV    AX,DI    ; original sector count was good
  276. SKIP_OK2:
  277.     ; following depends on fact that BIOS read fcn is 2, write is 3
  278.     MOV    AH,2    ; AL has number of sectors; AH gets op code
  279.     CMP    ES:[BP].RQ_CCD,4    ; 4=read
  280.     JE    DO_OP
  281.     INC    AH
  282. DO_OP:
  283.     POP    DX
  284.     POP    CX
  285.     PUSH    ES
  286.     MOV    ES,WORD PTR ES:[BP+2].RW_TRANS
  287.     INT    13
  288.     POP    ES
  289.     JNC    OK_TRANS    ; Carry bit unaffected by POP
  290.     CMP    AH,11        ; CRC error -- ignore
  291.     JNE    BIOS_BAD1
  292. OK_TRANS:
  293.     JMP    EXIT
  294. ;
  295. ; the BPB table should be the LAST thing declared before initialization code,
  296. ; as we throw away whatever we don't need of it.
  297. BPB_SPACE    BPB    4 DUP(<>) ; space for whatever BPB's we need
  298. ;
  299.     SUBTTL    Initialization code
  300.     PAGE
  301. ; Equates
  302. CR        EQU    0DH
  303. LF        EQU    0AH
  304. BOOT_BPB    EQU    0BH    ; offset of main BPB in boot sector
  305. BOOT_PARTTAB    EQU    1BE    ; offset of partition table in boot sector
  306. SIGNATURE    EQU    06
  307. ; Local Structs
  308. PART_REC    STRUC
  309. BOOT_IND    DB    ?
  310. S_HEAD        DB    ?
  311. S_SEC_CYL    DW    ?
  312. SYS_IND        DB    ?
  313. E_HEAD        DB    ?
  314. E_SEC_CYL    DW    ?
  315. REL_SECT    DD    ?
  316. NUM_SECT    DD    ?
  317. PART_REC    ENDS
  318. ;
  319. INITDATA    STRUC
  320. INI_RQ        DB    (TYPE RQ) DUP(?) ; standard part
  321. INI_NUNITS    DB    ?          ; number of units in driver
  322. INI_END_OFF    DW    ?          ; ending address offset
  323. INI_END_SEG    DW    ?          ; ending address segment
  324. INI_BPB_OFF    DW    ?          ; BPB array offset
  325. INI_BPB_SEG    DW    ?          ; BPB array segment
  326. INI_BLOCKDEV    DB    ?
  327. INITDATA    ENDS
  328. ; Data
  329. PREFIX    DB    "Pdisk",'0'+DISK_NO,": $"
  330. COPYRIGHT    DB    "(c) 1986, 1988 S. E. Garfinkle.  All Rights Reserved.$"
  331. NO_VOLS        DB    "No volumes found.$"
  332. NO_DRIVE    DB    "No valid drive connected.$"
  333. DRV_INST    DB    "0 Drive(s) installed.$"
  334. BOOT_SEC    DB    200 DUP(?)
  335. SEC_BUF_2    DB    200 DUP(?)
  336. ; Initialization code
  337. INIT:    
  338.     PUSH    ES    ; save ES until end of initialization
  339.     MOV    AX,DS    ; ES=DS
  340.     MOV    ES,AX
  341.     MOV    DX,OFFSET COPYRIGHT
  342.     CALL    PR_MSG
  343.     MOV    AH,8    ; set up for "determine drive characteristics" call
  344.     MOV    DL,DISK_ADDR
  345.     INT    13
  346.     CMP    DL,DISK_NO
  347.     JAE    GOT_DISKS
  348.     MOV    DX,OFFSET NO_DRIVE
  349.     CALL    PR_MSG
  350.     XOR    DX,DX
  351.     JMP    END_INIT
  352. GOT_DISKS:
  353.     AND    CL,3F    ; max # of sectors.  rest of CL is cylinder high bits
  354.     MOV    [NSECS],CL
  355.     MOV    AL,DH    ; max # of heads.
  356.     INC    AL    ; was zero-based.
  357.     MUL    CL
  358.     MOV    [SHPROD],AX    ; saves a lot of time later
  359.     MOV    AX,201    ; need to read master boot record: AH=read, AL=1 sector
  360.     MOV    BX,OFFSET BOOT_SEC
  361.     MOV    CX,1    ; cylinder 1, sector 0
  362.     MOV    DX,DISK_ADDR    ; head 0, current disk
  363.     INT    13
  364.     CLD
  365.     MOV    SI,OFFSET BOOT_SEC+BOOT_PARTTAB
  366. ; DI does double duty here:  it serves as the ptr to the BPBs being filled and
  367. ; also as the pointer to the end of retainable code.
  368.     MOV    DI,OFFSET BPB_SPACE
  369.     MOV    BX,OFFSET SEC_BUF_2
  370.     MOV    CX,4        ; max number of partitions
  371.     MOV    DX,((DISK_NO - 1) SHL 0C) ; volume count=0 (DL), partno=DISK_NO << 4    
  372. LOOP1A:
  373.     CMP    [SI].SYS_IND,SIGNATURE
  374.     JNE    E_LOOP1A
  375.     PUSH    CX
  376.     PUSH    DX
  377.     PUSH    SI
  378.     MOV    CX,[SI].S_SEC_CYL
  379.     MOV    DH,[SI].S_HEAD
  380.     MOV    DL,DISK_ADDR
  381.     MOV    AX,201
  382.     INT    13
  383.     MOV    SI,OFFSET SEC_BUF_2+BOOT_BPB
  384.     MOV    CX,STD_BPB_LEN
  385.     REP    MOVSB
  386.     POP    SI                ; SI once again points to PARTTAB
  387.     MOV    AX,WORD PTR [SI].REL_SECT
  388.     STOSW
  389.     MOV    AX,WORD PTR [SI+2].REL_SECT
  390.     STOSW
  391.     POP    DX
  392.     MOV    AL,DH                ; low 4 bits are partition number
  393.     STOSB
  394.     POP    CX
  395.     INC    DL
  396. E_LOOP1A:
  397.     INC    DH
  398.     ADD    SI,TYPE PART_REC
  399.     LOOP    LOOP1A
  400.     MOV    AX,STAT_DONE
  401.     OR    DL,DL
  402.     JNZ    END_INIT
  403. NONE:
  404.     MOV    DX,OFFSET NO_VOLS
  405.     CALL    PR_MSG
  406.     MOV    AX,STAT_DONE+STAT_ERR+STAT_GEN_FAIL
  407.     XOR    DL,DL
  408.     XOR    DI,DI
  409. END_INIT:
  410.     POP    ES        ; restore addressability to DOS request header
  411.     MOV    [DEV_COUNT],DL    ; "not necessary," according to manual
  412.     MOV    ES:[BP].INI_NUNITS,DL
  413.     MOV    ES:[BP].INI_END_OFF,DI
  414.     MOV    ES:[BP].INI_BPB_OFF,OFFSET BPB_NDX
  415.     MOV    ES:[BP].INI_END_SEG,CS
  416.     MOV    ES:[BP].INI_BPB_SEG,CS
  417.     MOV    DI,OFFSET DRV_INST
  418.     ADD    BYTE PTR [DI],DL
  419.     MOV    DX,DI
  420.     CALL    PR_MSG
  421.     JMP    ERR1
  422.  
  423. CRLF    DB    CR,LF,"$"
  424.  
  425. PR_MSG    PROC    NEAR
  426.     MOV    AH,9
  427.     PUSH    DX
  428.     MOV    DX,OFFSET PREFIX
  429.     INT    21
  430.     POP    DX
  431.     INT    21
  432.     MOV    DX,OFFSET CRLF
  433.     INT    21
  434.     RET
  435. PR_MSG    ENDP
  436.  
  437. CSEG    ENDS
  438.     END
  439.