Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1865 lines
59 KiB

  1. PAGE ,132
  2. TITLE DXDISK.ASM -- Dos Extender Low Level Disk Interface
  3. ; Copyright (c) Microsoft Corporation 1988-1991. All Rights Reserved.
  4. ;***********************************************************************
  5. ;
  6. ; DXDISK.ASM -- Dos Extender Low Level Disk Interface
  7. ;
  8. ;-----------------------------------------------------------------------
  9. ;
  10. ; This module provides the 286 DOS extender's low level protected-to-
  11. ; real mode disk interface. It supports a subset of the BIOS Int 13h
  12. ; and DOS Int 25h/26h services.
  13. ;
  14. ;-----------------------------------------------------------------------
  15. ;
  16. ; 05/22/89 jimmat Original version
  17. ; 18-Dec-1992 sudeepb Changed cli/sti to faster FCLI/FSTI
  18. ;
  19. ;***********************************************************************
  20. .286p
  21. ; -------------------------------------------------------
  22. ; INCLUDE FILE DEFINITIONS
  23. ; -------------------------------------------------------
  24. .xlist
  25. .sall
  26. include segdefs.inc
  27. include gendefs.inc
  28. include pmdefs.inc
  29. include interupt.inc
  30. include intmac.inc
  31. .list
  32. ; -------------------------------------------------------
  33. ; GENERAL SYMBOL DEFINITIONS
  34. ; -------------------------------------------------------
  35. ; -------------------------------------------------------
  36. ; EXTERNAL SYMBOL DEFINITIONS
  37. ; -------------------------------------------------------
  38. extrn EnterIntHandler:NEAR
  39. extrn LeaveIntHandler:NEAR
  40. extrn EnterRealMode:NEAR
  41. extrn EnterProtectedMode:NEAR
  42. extrn GetSegmentAddress:NEAR
  43. extrn SetSegmentAddress:NEAR
  44. externFP NSetSegmentDscr
  45. extrn FreeSelector:NEAR
  46. extrn AllocateSelector:NEAR
  47. extrn ParaToLDTSelector:NEAR
  48. ifdef NEC_98 ;
  49. extrn IncInBios:NEAR ;
  50. extrn DecInBios:NEAR ;
  51. endif ;NEC_98 ;
  52. ; -------------------------------------------------------
  53. ; DATA SEGMENT DEFINITIONS
  54. ; -------------------------------------------------------
  55. DXDATA segment
  56. extrn rgbXfrBuf0:BYTE
  57. extrn rgbXfrBuf1:BYTE
  58. ifdef NEC_98
  59. extrn rglpfnRmISR:DWORD
  60. endif
  61. cbSectorSize dw ? ;sector size for target drive
  62. cSectorsTransfered dw ? ;# sectors transfered so far
  63. cSectorsToTransfer dw ? ;# sectors to read/write
  64. cSectorsPerTransfer dw ? ;# sectors to R/W at a time
  65. cSectorsThisTransfer dw ? ;# sectors to R/W this time
  66. lpSectorData dd ? ;far pointer to caller's buffer
  67. ifdef NEC_98 ;
  68. public lpRmISR
  69. endif ;NEC_98 ;
  70. lpRmISR dd ? ;real mode int service rtn to invoke
  71. ifdef NEC_98 ;
  72. sensedata1 dw ? ;sector length
  73. sensedata2 dw ? ;cylinder
  74. sensedata3 dd ? ;head
  75. sensedata4 dd ? ;sector num
  76. extrn fPCH98:BYTE ;for PC_H98
  77. endif ;NEC_98 ;
  78. DXDATA ends
  79. ; -------------------------------------------------------
  80. ; CODE SEGMENT VARIABLES
  81. ; -------------------------------------------------------
  82. DXCODE segment
  83. DXCODE ends
  84. DXPMCODE segment
  85. extrn segDXDataPM:WORD
  86. DXPMCODE ends
  87. ; -------------------------------------------------------
  88. subttl INT 13h Mapping Services
  89. page
  90. ; -------------------------------------------------------
  91. ; INT 13h MAPPING SERVICES
  92. ; -------------------------------------------------------
  93. DXPMCODE segment
  94. assume cs:DXPMCODE
  95. ; -------------------------------------------------------
  96. ; PMIntr13 -- Service routine for the Protect Mode INT 13h
  97. ; interface to the real mode BIOS.
  98. ;
  99. ; Input: Various registers
  100. ; Output: Various registers
  101. ; Errors:
  102. ; Uses: All registers preserved, other than return values
  103. ;
  104. ; Currently, the following Int 13h services are supported:
  105. ;
  106. ; ah= 0 - Reset Disk System (no mapping required)
  107. ; 1 - Get Disk System Status (no mapping required)
  108. ; 2 - Read Sector (mapping required)
  109. ; 3 - Write Sector (mapping required)
  110. ; 4 - Verify Sector (mapping required)
  111. ; 5 - Fromat Track (mapping required)
  112. ; 6 - Format Bad Track (no mapping required)
  113. ; 7 - Format Drive (no mapping required)
  114. ; 8 - Get Drive Parameters (mapping required)
  115. ; 9 - Init Fixed Disk Characteristics (no mapping required)
  116. ; C - Seek (no mapping required)
  117. ; D - Reset Disk System (no mapping required)
  118. ; 10 - Get Drive Status (no mapping required)
  119. ; 11 - Recalibrate Drive (no mapping required)
  120. ; 12 - Controller RAM Diagnostic (no mapping required)
  121. ; 13 - Controller Drive Diagnostic (no mapping required)
  122. ; 14 - Controller Internal Diagnostic (no mapping required)
  123. ; 15 - Get Disk Type (no mapping required)
  124. ; 16 - Get Disk Change Status (no mapping required)
  125. ; 17 - Set Disk Type (no mapping required)
  126. ; 18 - Set Media Type for Format (mapping required)
  127. ; 19 - Park Heads (no mapping required)
  128. ;
  129. ; Functions not listed above will most likely not work properly!
  130. ;
  131. ; NOTE: several functions take 2 bits of the cylinder number in CL
  132. ; if the operation is on a fixed disk. The code currently does
  133. ; not account for these bits, and may not work properly if
  134. ; the request must be split into smaller operations for real/
  135. ; extended memory buffering.
  136. ;
  137. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  138. public PMIntr13
  139. PMIntr13 proc near
  140. ifdef NEC_98 ;
  141. call IncInBios ;
  142. endif ;NEC_98 ;
  143. cld ;cya...
  144. call EnterIntHandler ;build an interrupt stack frame
  145. assume ds:DGROUP,es:DGROUP ; also sets up addressability
  146. FSTI ;allow HW interrupts
  147. call IntEntry13 ;perform translations/buffering
  148. ; Execute the real mode BIOS routine
  149. ifdef NEC_98 ;
  150. push es
  151. assume es:nothing
  152. mov ax,SEL_RMIVT OR STD_RING
  153. mov es,ax
  154. mov ax,word ptr es:[4*1bh] ;move real mode Int 13h
  155. mov word ptr [bp].lParam,ax ; handler address to
  156. mov ax,word ptr es:[4*1bh+2]; lParam on stack frame
  157. mov word ptr [bp].lParam+2,ax
  158. pop es
  159. assume es:DGROUP
  160. mov ah,1bh ;wParam1 = int #, function
  161. else ;NEC_98 ;
  162. push es
  163. assume es:nothing
  164. mov ax,SEL_RMIVT OR STD_RING
  165. mov es,ax
  166. mov ax,word ptr es:[4*13h] ;move real mode Int 13h
  167. mov word ptr [bp].lParam,ax ; handler address to
  168. mov ax,word ptr es:[4*13h+2]; lParam on stack frame
  169. mov word ptr [bp].lParam+2,ax
  170. pop es
  171. assume es:DGROUP
  172. mov ah,13h ;wParam1 = int #, function
  173. endif ;NEC_98 ;
  174. mov al,byte ptr [bp].intUserAX+1
  175. mov [bp].wParam1,ax
  176. ifdef NEC_98 ;
  177. and al,0fh
  178. cmp al,05 ;write data?
  179. jb i13_not_rw
  180. cmp al,06 ;read data?
  181. ja i13_not_rw
  182. else ;NEC_98 ;
  183. cmp al,02 ;call special read/write routine
  184. jb i13_not_rw ; if this is a read/write sectors
  185. cmp al,03 ; request
  186. ja i13_not_rw
  187. endif ;NEC_98 ;
  188. call ReadWriteSectors ;common Int 13h/25h/26h read/write code
  189. jmp short i13_done
  190. i13_not_rw:
  191. SwitchToRealMode ;otherwise, do the service ourself
  192. pop es
  193. pop ds
  194. assume ds:NOTHING,es:NOTHING,ss:DGROUP
  195. popa
  196. sub sp,8 ; make room for stack frame
  197. push bp
  198. mov bp,sp
  199. push es
  200. push ax
  201. xor ax,ax
  202. mov es,ax
  203. mov [bp + 8],cs
  204. mov [bp + 6],word ptr (offset i13_10)
  205. ifdef NEC_98 ;
  206. mov ax,es:[1Bh*4]
  207. mov [bp + 2],ax
  208. mov ax,es:[1Bh*4 + 2]
  209. else ;NEC_98 ;
  210. mov ax,es:[13h*4]
  211. mov [bp + 2],ax
  212. mov ax,es:[13h*4 + 2]
  213. endif ;NEC_98 ;
  214. mov [bp + 4],ax
  215. pop ax
  216. pop es
  217. pop bp
  218. retf
  219. i13_10: pushf
  220. FCLI
  221. pusha
  222. push ds
  223. push es
  224. mov bp,sp ;restore stack frame pointer
  225. SwitchToProtectedMode
  226. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  227. FSTI ;allow HW interrupts
  228. ; Perform fixups on the return register values.
  229. i13_done:
  230. mov ax,[bp].pmUserAX ;get original function code
  231. call IntExit13
  232. FCLI ;LeaveIntHandler requires ints off
  233. call LeaveIntHandler ;restore caller's registers, stack
  234. assume ds:NOTHING,es:NOTHING
  235. ifdef NEC_98 ;
  236. call DecInBios ;
  237. endif ;NEC_98 ;
  238. riret
  239. PMIntr13 endp
  240. ; -------------------------------------------------------
  241. ; IntEntry13 -- This routine performs translations and
  242. ; buffering of Int 13h requests on entry.
  243. ;
  244. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  245. public IntEntry13
  246. IntEntry13 proc near
  247. ifdef NEC_98 ;
  248. and ah,0fh
  249. cmp ah,05 ;Write sectors?
  250. jb @f
  251. cmp ah,06 ;Read sectors?
  252. ja @f
  253. ;----------- 90/08/13 copy segment address from ds -------
  254. push ax
  255. mov ax,segDXDataPM
  256. mov [bp].intUserES,ax ;segment address
  257. pop ax
  258. ;------------------------------------------------------------
  259. mov [bp].intUserBP,offset DGROUP:rgbXfrBuf1 ;use DOSX buffer 90/07/13
  260. ret
  261. @@:
  262. cmp ah,01h ;Verify sectors?
  263. jnz @f
  264. mov [bp].intUserES,0F000h ;older versions of verify need a buff,
  265. mov [bp].intUserBP,0 ; offset adress 90/07/12 change
  266. ret
  267. @@:
  268. cmp ah,0Dh ;Format track?
  269. jnz @f
  270. ;------ 90/11/08 debug -----
  271. push ds
  272. mov si,[bp].pmUserBP ;es:bx -> 512 byte buffer to copy down
  273. mov ds,[bp].pmUserES
  274. mov di,offset DGROUP:rgbXfrBuf1
  275. mov cx,128 ;might be good to check segment limit
  276. cld ; on callers source!
  277. rep movsw
  278. pop ds
  279. push ax
  280. mov ax,segDXDataPM
  281. mov [bp].intUserES,ax ;segment address
  282. pop ax
  283. mov [bp].intUserBP,offset DGROUP:rgbXfrBuf1
  284. push es
  285. pop ds
  286. ret
  287. @@:
  288. ;///// 90/09/04 PC_H98 DISK BIOS command(Read Defect Data) support/////
  289. test fPCH98,0FFh
  290. jz @f
  291. cmp ah,0Ch
  292. jz ReadDD
  293. cmp ah,2Ch
  294. jz ReadDD
  295. jmp @f
  296. ReadDD:
  297. push ax
  298. mov ax,segDXDataPM
  299. mov [bp].intUserES,ax ;segment address
  300. pop ax
  301. mov [bp].intUserBP,offset DGROUP:rgbXfrBuf1 ;use DOSX buffer 90/07/13
  302. ;///// 90/09/04 PC_H98 DISK BIOS command(Read Defect Data) support/////
  303. @@:
  304. ret
  305. else ;NEC_98 ;
  306. cmp ah,02 ;Read sectors?
  307. jb @f
  308. cmp ah,03 ;Write sectors?
  309. ja @f
  310. mov [bp].intUserBX,offset DGROUP:rgbXfrBuf1 ;use DOSX buffer
  311. ret
  312. @@:
  313. cmp ah,04h ;Verify sectors?
  314. jnz @f
  315. mov [bp].intUserES,0F000h ;older versions of verify need a buff,
  316. mov [bp].intUserBX,0 ; we just point them at the BIOS!
  317. ret
  318. @@:
  319. cmp ah,05h ;Format track?
  320. jnz @f
  321. mov si,bx ;es:bx -> 512 byte buffer to copy down
  322. mov di,offset DGROUP:rgbXfrBuf1
  323. mov [bp].intUserBX,di
  324. mov ds,[bp].pmUserES
  325. mov cx,256 ;might be good to check segment limit
  326. cld ; on callers source!
  327. rep movsw
  328. push es
  329. pop ds
  330. ret
  331. @@:
  332. ret
  333. endif ;NEC_98 ;
  334. IntEntry13 endp
  335. ; -------------------------------------------------------
  336. ; IntExit13 -- This routine performs translations and
  337. ; buffering of Int 13h requests on exit.
  338. ;
  339. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  340. public IntExit13
  341. IntExit13 proc near
  342. ifdef NEC_98 ;
  343. ; Functions 06h (Read sectors) and 05h (Write sectors) return a count of
  344. ; sectors transfered in AL. Since we may break the transfer up into a
  345. ; number of transfers, we have to return the total # that we transfered,
  346. ; not the number of the last bios request.
  347. ;----- 90/11/08 debug -----
  348. and ah,0fh
  349. ;----- 90/11/08 debug -----
  350. ;----- 90/07/06 change -----
  351. cmp ah,05h ;Write data
  352. jb @f
  353. cmp ah,06h ;Read data
  354. ja @f
  355. mov al,byte ptr cSectorsTransfered
  356. mov byte ptr [bp].intUserAX,al
  357. @@:
  358. ; Functions 06h (Read sectors), 05h (Write sectors), 01h (Verify sectors),
  359. ; and 0Dh (Format track) need to have the caller's value of bx restored.
  360. ;----- 90/07/06 change -----
  361. cmp ah,01h ;Verify sectors?
  362. je @f
  363. cmp ah,05h ;Write sectors?
  364. je @f
  365. cmp ah,06h ;Read sectors?
  366. je @f
  367. cmp ah,0Dh ;Format track?
  368. jne other
  369. ;offset adress 90/07/12 change
  370. ;----------- 90/08/13 copy segment address from ES -------
  371. mov ax,[bp].pmUserES
  372. mov [bp].intUserES,ax
  373. ;------------------------------------------------------------
  374. @@: mov ax,[bp].pmUserBP ;restore caller's BP value
  375. mov [bp].intUserBP,ax
  376. other:
  377. ret
  378. else ;NEC_98 ;
  379. ; Functions 02h (Read sectors) and 03h (Write sectors) return a count of
  380. ; sectors transfered in AL. Since we may break the transfer up into a
  381. ; number of transfers, we have to return the total # that we transfered,
  382. ; not the number of the last bios request.
  383. cmp ah,02h
  384. jb @f
  385. cmp ah,03h
  386. ja @f
  387. mov al,byte ptr cSectorsTransfered
  388. mov byte ptr [bp].intUserAX,al
  389. @@:
  390. ; Functions 02h (Read sectors), 03h (Write sectors), 04h (Verify sectors),
  391. ; and 05h (Format track) need to have the caller's value of bx restored.
  392. cmp ah,02h ;Read sectors?
  393. jb @f
  394. cmp ah,05 ;Format track?
  395. ja @f
  396. mov ax,[bp].pmUserBX ;restore caller's BX value
  397. mov [bp].intUserBX,ax
  398. ret
  399. @@:
  400. ; Functions 08h (Get Drive Parameters) and 18h (Set Drive Type for Format)
  401. ; return a pointer in ES:DI. Map the segment in ES to a selector
  402. cmp ah,08h ;Get Drive Parameters
  403. jz i13_map_es
  404. cmp ah,18h
  405. jnz @f
  406. i13_map_es:
  407. test byte ptr [bp].intUserFL,1 ;don't bother to map ES if
  408. jnz @f ; function failed (carry set)
  409. i13_do_it:
  410. mov ax,[bp].intUserES ;returns a pointer in ES:DI, get
  411. mov bx,STD_DATA ; a selector for it
  412. call ParaToLDTSelector
  413. mov [bp].pmUserES,ax
  414. ret
  415. @@:
  416. ret
  417. endif ;NEC_98 ;
  418. IntExit13 endp
  419. ; -------------------------------------------------------
  420. subttl INT 25h/26h Absolute Disk Read/Write
  421. page
  422. ; -------------------------------------------------------
  423. ; INT 25h/26h ABSOLUTE DISK READ/WRITE
  424. ; -------------------------------------------------------
  425. ; PMIntr25 -- This routine provides the protected-to-real
  426. ; mode mapping for Int 25h (Absolute Disk Read)
  427. ;
  428. ; In: al - drive # (0 = A, 1 = B, ...)
  429. ; cx - # of sectors to read
  430. ; dx - starting sector #
  431. ; ds:bx - selector:offset of buffer
  432. ;
  433. ; -- or --
  434. ;
  435. ; al - drive #
  436. ; cx - -1
  437. ; ds:bx - pointer to 5 word parameter block
  438. ;
  439. ; Out: if successful, carry clear
  440. ; if unsuccessful, carry set and
  441. ; ax - error code
  442. assume ds:DGROUP,es:DGROUP
  443. public PMIntr25
  444. PMIntr25 proc near
  445. ifdef NEC_98 ;
  446. call IncInBios ;
  447. endif ;NEC_98 ;
  448. cld ;cya...
  449. call EnterIntHandler ;build an interrupt stack frame
  450. assume ds:DGROUP,es:DGROUP ; also sets up addressability
  451. FSTI ;allow HW interrupts
  452. mov ah,25h
  453. call IntEntry2X ;perform translations/buffering
  454. ; Do the read
  455. push es
  456. mov ax,SEL_RMIVT OR STD_RING
  457. mov es,ax
  458. assume es:nothing
  459. mov ax,word ptr es:[4*25h] ;move real mode Int 25h
  460. mov word ptr [bp].lParam,ax ; handler address to
  461. mov ax,word ptr es:[4*25h+2]; lParam on stack frame
  462. mov word ptr [bp].lParam+2,ax
  463. pop es
  464. assume es:DGROUP
  465. mov ah,25h ;wParam1 = int #
  466. mov [bp].wParam1,ax
  467. call ReadWriteSectors ;common Int 13h/25h/26h read/write code
  468. ; Perform fixups on the return register values.
  469. mov ah,25h
  470. call IntExit2X ;perform translations/buffering
  471. FCLI
  472. call LeaveIntHandler ;restore caller's registers, stack
  473. assume ds:NOTHING,es:NOTHING
  474. ; Int 25 & 26 leave the caller's flags on the stack, but we want to return
  475. ; with the flags returned by the real mode ISR (which LeaveIntHandler has
  476. ; incorporated into the caller's flags), so make a copy of the flags and
  477. ; pop them into the flags register before returning.
  478. push ax
  479. push bp
  480. mov bp,sp ;bp -> BP AX IP CS FL
  481. mov ax,[bp+8]
  482. xchg ax,[bp+2] ;bp -> BP FL IP CS FL
  483. pop bp
  484. ifdef NEC_98 ;
  485. call DecInBios ;
  486. endif ;NEC_98 ;
  487. npopf
  488. retf
  489. PMIntr25 endp
  490. ; -------------------------------------------------------
  491. ; PMIntr26 -- This routine provides the protected-to-real
  492. ; mode mapping for Int 26h (Absolute Disk Write)
  493. ;
  494. ; In: al - drive # (0 = A, 1 = B, ...)
  495. ; cx - # of sectors to write
  496. ; dx - starting sector #
  497. ; ds:bx - selector:offset of buffer
  498. ;
  499. ; -- or --
  500. ;
  501. ; al - drive #
  502. ; cx - -1
  503. ; ds:bx - pointer to 5 word parameter block
  504. ;
  505. ; Out: if successful, carry clear
  506. ; if unsuccessful, carry set and
  507. ; ax - error code
  508. assume ds:DGROUP,es:DGROUP
  509. public PMIntr26
  510. PMIntr26 proc near
  511. ifdef NEC_98 ;
  512. call IncInBios ;
  513. endif ;NEC_98 ;
  514. cld ;cya...
  515. call EnterIntHandler ;build an interrupt stack frame
  516. assume ds:DGROUP,es:DGROUP ; also sets up addressability
  517. FSTI ;allow HW interrupts
  518. mov ah,26h
  519. call IntEntry2X ;perform translations/buffering
  520. ; Do the write
  521. push es
  522. mov ax,SEL_RMIVT OR STD_RING
  523. mov es,ax
  524. assume es:nothing
  525. mov ax,word ptr es:[4*26h] ;move real mode Int 25h
  526. mov word ptr [bp].lParam,ax ; handler address to
  527. mov ax,word ptr es:[4*26h+2]; lParam on stack frame
  528. mov word ptr [bp].lParam+2,ax
  529. pop es
  530. assume es:DGROUP
  531. mov ah,26h ;wParam1 = int #
  532. mov [bp].wParam1,ax
  533. call ReadWriteSectors ;common Int 13h/25h/26h read/write code
  534. ; Perform fixups on the return register values.
  535. mov ah,26h
  536. call IntExit2X ;perform translations/buffering
  537. FCLI
  538. call LeaveIntHandler ;restore caller's registers, stack
  539. assume ds:NOTHING,es:NOTHING
  540. ; Int 25 & 26 leave the caller's flags on the stack, but we want to return
  541. ; with the flags returned by the real mode ISR (which LeaveIntHandler has
  542. ; incorporated into the caller's flags), so make a copy of the flags and
  543. ; pop them into the flags register before returning.
  544. push ax
  545. push bp
  546. mov bp,sp ;bp -> BP AX IP CS FL
  547. mov ax,[bp+8]
  548. xchg ax,[bp+2] ;bp -> BP FL IP CS FL
  549. pop bp
  550. ifdef NEC_98 ;
  551. call DecInBios ;
  552. endif ;NEC_98 ;
  553. npopf
  554. retf
  555. PMIntr26 endp
  556. ; -------------------------------------------------------
  557. ; IntEntry2X -- This routine performs translations and
  558. ; buffering of Int 25h and 26h requests on entry.
  559. ;
  560. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  561. public IntEntry2X
  562. IntEntry2X proc near
  563. cmp [bp].intUserCX,-1 ;DOS 4.0 extended read/write?
  564. jnz e2x_dsbx ; no, just go map DS:BX
  565. mov ds,[bp].pmUserDS ; yes, copy down parameter blk
  566. assume ds:NOTHING
  567. mov si,[bp].pmUserBX
  568. mov di,offset rgbXfrBuf0
  569. cld
  570. movsw ;32-bit sector #
  571. movsw
  572. movsw ;# sectors to read/write
  573. mov ax,offset rgbXfrBuf1 ;replace pointer with addr of
  574. stosw ; our own low buffer
  575. mov ax,segDXDataPM ;segment, not selector
  576. stosw
  577. push es
  578. pop ds
  579. assume ds:DGROUP
  580. mov [bp].intUserBX,offset rgbXfrBuf0
  581. ret
  582. e2x_dsbx: ;standard read/write, just redirect DS:BX
  583. mov [bp].intUserBX,offset rgbXfrBuf1
  584. ret
  585. IntEntry2X endp
  586. ; -------------------------------------------------------
  587. ; IntExit2X -- This routine performs translations and
  588. ; buffering of Int 25h and 26h requests on exit.
  589. ;
  590. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  591. public IntExit2X
  592. IntExit2X proc near
  593. mov ax,[bp].pmUserBX ;restore caller's BX
  594. mov [bp].intUserBX,ax
  595. ret
  596. IntExit2X endp
  597. ; -------------------------------------------------------
  598. subttl Disk Utility Routines
  599. page
  600. ; -------------------------------------------------------
  601. ; DISK UTILITY ROUTINES
  602. ; -------------------------------------------------------
  603. ; ReadWriteSectors -- Common code to read/write disk sectors for
  604. ; Int 13h/25h/26h.
  605. ;
  606. ; In: lParam - seg:off of real mode interrupt handler
  607. ; wParam1 - int #, and possible subfunction
  608. ; regs on stack
  609. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  610. public ReadWriteSectors
  611. ReadWriteSectors proc near
  612. ifdef NEC_98 ;
  613. pop [bp].wParam2 ;save return addr higher on stack
  614. ; Setup the global data items for the read/write--pointer to caller's
  615. ; buffer, # sectors to read/write, and sector size.
  616. cmp byte ptr [bp].wParam1+1,1Bh ;Int 1Bh?
  617. jz DISK_BIOS
  618. jmp DOSReadWriteSectors
  619. ;;;;;;;; jmp rws_dos_size
  620. DISK_BIOS:
  621. ;offset adress 90/07/12 change
  622. mov ax,[bp].pmUserBP ;ES:BP points to caller's buf
  623. mov word ptr lpSectorData,ax
  624. mov ax,[bp].pmUserES
  625. mov word ptr [lpSectorData+2],ax
  626. ;US:sector num, but :data length 90/07/13
  627. ;-------------------------- 90/07/23 in ---------------------------
  628. ; to adjust to US, we get a data with sense command on HDD,
  629. ; and set a data with 1MB/640KB on FDD.
  630. ;----------------------------------------------------------------------
  631. mov al,byte ptr [bp].intUserAX ;
  632. ;
  633. push ax
  634. and al,10h ;DA:4th bit on :FDD
  635. pop ax
  636. jnz FDBIOS
  637. mov ah,84h ;SENSE command
  638. push ax
  639. SwitchToRealMode
  640. pop ax
  641. pushf ;have BIOS get the drive data
  642. call rglpfnRmISR[1Bh*4] ;90/07/04
  643. mov sensedata1,bx ;sector length
  644. mov sensedata2,cx ;cylinder
  645. mov byte ptr sensedata3,dh ;DH = head
  646. mov byte ptr sensedata4,dl ;DL = sector num
  647. SwitchToProtectedMode
  648. jmp SECTOR
  649. FDBIOS:
  650. push ax
  651. mov cx,[bp].intUserCX ;sector size shift factor (0,1,2,3)
  652. ;;;;;;;; mov cl,byte ptr [bp].intUserCX ;sector size shift factor (0,1,2,3)
  653. mov ax,128
  654. xchg ch,cl
  655. shl ax,cl ;ax now = sector size
  656. mov cx,ax
  657. mov sensedata1,cx ;sector length
  658. pop ax
  659. cmp al,90h ;1MB floppy disk,1MB/640KBdual modefloppy disk(1MB FD access)
  660. jb fd640k
  661. cmp al,93h
  662. ja fd640k
  663. ;set the max value to the buffer with 1MBFD
  664. mov sensedata2,77 ;cylinder
  665. mov word ptr sensedata3,1 ;head
  666. mov word ptr sensedata4,26 ;sector num
  667. jmp SECTOR
  668. fd640k:
  669. cmp al,70h ;640KB floppy disk
  670. jb @f
  671. cmp al,73h
  672. ja @f
  673. mov sensedata2,79 ;cylinder
  674. mov word ptr sensedata3,1 ;head
  675. mov word ptr sensedata4,16 ;sector num
  676. jmp SECTOR
  677. @@:
  678. cmp al,10h ;1MB/640KB dual modefloppy disk(640KB FD access)
  679. jb @f
  680. cmp al,13h
  681. ja @f
  682. mov sensedata2,79 ;cylinder
  683. mov word ptr sensedata3,1 ;head
  684. mov word ptr sensedata4,16 ;sector num
  685. jmp SECTOR
  686. @@:
  687. cmp al,30h ;1.44MBfloppy disk '93 1/5 By S.Kurokawa
  688. jb fdother
  689. cmp al,33h
  690. ja fdother
  691. mov sensedata2,79 ;cylinder
  692. mov word ptr sensedata3,1 ;head
  693. mov word ptr sensedata4,18 ;sector num
  694. jmp SECTOR
  695. ;------------------------ 90/07/23 ------------------------------
  696. ; for the media except for 1MB FD,640KB FD ::�i10MB FD�j
  697. ; we do not know that we can certainly issue a sense command
  698. ;--------------------------------------------------------------------
  699. fdother:
  700. mov ah,84h ;SENSE command
  701. push ax
  702. SwitchToRealMode
  703. pop ax
  704. pushf ;have BIOS get the drive data
  705. call rglpfnRmISR[1Bh*4] ;90/07/04
  706. mov sensedata1,bx ;sector length
  707. mov sensedata2,cx ;cylinder
  708. mov byte ptr sensedata3,dh ;DH = head
  709. mov byte ptr sensedata4,dl ;DL = sector num
  710. SwitchToProtectedMode
  711. SECTOR:
  712. push dx
  713. xor dx,dx
  714. mov cx,sensedata1 ;sector length
  715. mov ax,[bp].intUserBX ;# sectors caller wants to
  716. div cx
  717. mov cSectorsToTransfer,ax ;bytes�^sector len��sector num
  718. pop dx
  719. ;;;; mov cx,1 ;90/07/13
  720. FSTI ;don't need them disabled
  721. if DEBUG ;------------------------------------------------------------
  722. cmp cx,512
  723. jz @f
  724. Debug_Out "Odd sector size = #CX"
  725. @@:
  726. endif ;DEBUG --------------------------------------------------------
  727. ; CX now has the drive's sector size. Determine how many sectors we can
  728. ; transfer at a time
  729. rws_have_size:
  730. mov cbSectorSize,cx ;save sector size for later
  731. xor dx,dx
  732. mov ax,CB_XFRBUF1 ;buf size / sector size = sectors per
  733. div cx ; transfer
  734. if DEBUG ;------------------------------------------------------------
  735. or ax,ax
  736. jnz @f
  737. Debug_Out "Sectors per transfer = 0!"
  738. @@:
  739. endif ;DEBUG --------------------------------------------------------
  740. mov cSectorsPerTransfer,ax
  741. xor ax,ax
  742. mov cSectorsTransfered,ax ;sectors transfered so far = 0
  743. mov cSectorsThisTransfer,ax ;sectors transfered last time = 0
  744. ; Get/init a selector that we'll use to reference the caller's buffer.
  745. mov ax,word ptr [lpSectorData+2] ;get lma of caller's buffer
  746. call GetSegmentAddress
  747. add dx,word ptr lpSectorData
  748. adc bx,0
  749. call AllocateSelector ;build a sel/dscr pointing
  750. mov cx,0FFFFh
  751. cCall NSetSegmentDscr,<ax,bx,dx,0,cx,STD_DATA>
  752. xor bx,bx
  753. mov word ptr lpSectorData,bx ;use that as the buffer ptr
  754. mov word ptr [lpSectorData+2],ax
  755. ; ======================================================================
  756. ; Main sector read/write loop ------------------------------------------
  757. ; ======================================================================
  758. rws_do_it_loop:
  759. ; Calculate how many sectors to transfer this time around, set starting
  760. ; sector number based on how many transfered last time.
  761. ; int 3 ;------ 90/11/08 debug ------
  762. mov ax,cSectorsToTransfer ;total sector
  763. sub ax,cSectorsTransfered ;total sector - transferred sector = remain
  764. jnz @f
  765. jmp rws_done
  766. @@:
  767. cmp ax,cSectorsPerTransfer ;buffer size / sector len = sectors in buffer
  768. jna @f ;sectors in buffer > remain sectors = remain
  769. mov ax,cSectorsPerTransfer ;sectors in buffer < remain = sectors in buffer
  770. @@:
  771. mov bx,cSectorsThisTransfer ;still # R/W from last loop
  772. push [bp].pmUserAX ;the BIOS does not save
  773. pop [bp].intUserAX ; registers across calls to
  774. push [bp].pmUserCX ; it so if we're doing
  775. pop [bp].intUserCX ; multiple calls to buffer
  776. ; push [bp].pmUserDX ; data, restore the initial
  777. ; pop [bp].intUserDX ; register values
  778. ; Previous two lines include bug. '93 1/15 Debugged by S.Kurokawa.
  779. ;in data transmits with a byte, so mov AX to BX 90/07/18
  780. ;;;; mov byte ptr [bp].intUserAX,al ;# sectors in AL = sectors
  781. push ax ;90/11/08
  782. xor ah,ah ;for calc a data len, ah=0 90/07/25
  783. mov cx,cbSectorSize
  784. mul cx ;sector num * sector len 90/07/25
  785. mov [bp].intUserBX,ax ;# sectors in BX = data len
  786. pop ax ;90/11/08
  787. ;;;; add byte ptr [bp].intUserCX,bl ;update new start sector in CL
  788. add byte ptr [bp].intUserDX,bl ;update new start sector in DL = sector num�@90/07/13
  789. rws_size_start_set:
  790. ; At this point, AX has the number of sectors to transfer. If this is a
  791. ; write, copy a buffer of data from the caller's buffer.
  792. mov cSectorsThisTransfer,ax ;in case it's a read
  793. ;cSectorsThisTransfer = sectors in buffer or remained sectors
  794. ;----------------90/11/08 debug -------------------------------------
  795. push ax
  796. mov ax,[bp].wParam1 ;BIOS write?
  797. and ax,0ff0fh
  798. cmp ax,1B05h ;BIOS write?
  799. pop ax
  800. ;----------------90/11/08 debug -------------------------------------
  801. jnz rws_not_write
  802. ; call DBIOS_DEVICE
  803. rws_buf_write:
  804. mul cbSectorSize ;AX now = # bytes to transfer
  805. mov cx,ax ;can safely assume < 64k
  806. shr cx,1 ;# words to move
  807. ; lds si,lpSectorData
  808. ; assume ds:NOTHING
  809. push ds
  810. mov si,[bp].pmUserBP ;90/11/09
  811. mov ds,[bp].pmUserES ;90/11/09
  812. ; mov di,offset rgbXfrBuf1
  813. mov di,offset DGROUP:rgbXfrBuf1
  814. cld
  815. rep movsw
  816. pop ds
  817. push es
  818. pop ds
  819. assume ds:DGROUP
  820. mov word ptr [bp].pmUserBP,si ;update src ptr for next time
  821. ; mov word ptr lpSectorData,si ;update src ptr for next time
  822. ; call NormalizeBufPtr ; and normalize it
  823. rws_not_write:
  824. ;------------------------------------------------------------
  825. push ax ;90/11/09
  826. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  827. mov ax,segDXDataPM
  828. ; mov ax,[bp].pmUserES ;debug
  829. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  830. mov [bp].intUserES,ax ;segment address
  831. pop ax
  832. mov [bp].intUserBP,offset DGROUP:rgbXfrBuf1
  833. ;------------------------------------------------------------
  834. ; Switch to real mode, do the transfer.
  835. SwitchToRealMode
  836. assume ds:DGROUP,es:DGROUP
  837. push word ptr [bp].lParam
  838. pop word ptr lpRmISR
  839. push word ptr [bp].lParam+2
  840. pop word ptr lpRmISR+2
  841. pop es
  842. pop ds
  843. assume ds:NOTHING,es:NOTHING,ss:DGROUP
  844. popa
  845. call lpRmISR
  846. pushf
  847. FCLI
  848. rws_save_regs:
  849. pusha
  850. push ds
  851. push es
  852. mov bp,sp ;restore stack frame pointer
  853. SwitchToProtectedMode
  854. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  855. FSTI ;allow HW interrupts
  856. ; If the call failed, then cut out now without further processing...
  857. test byte ptr [bp].intUserFL,1 ;CY set?
  858. jnz rws_done
  859. ; If this was a successful read, copy the data back to the caller.
  860. ;----------------90/11/08 debug -------------------------------------
  861. push ax
  862. mov ax,[bp].wParam1 ;BIOS write?
  863. and ax,0ff0fh
  864. cmp ax,1B06h ;BIOS write?
  865. pop ax
  866. ;----------------90/11/08 debug -------------------------------------
  867. jnz rws_not_read
  868. ; call DBIOS_DEVICE
  869. rws_buf_read:
  870. mov ax,cSectorsThisTransfer ;calc size of data to move
  871. mul cbSectorSize
  872. mov cx,ax
  873. shr cx,1 ;in words
  874. ;;;;;;;; les di,lpSectorData ;caller's buffer pointer
  875. ;;;;;;;; assume es:NOTHING
  876. push es
  877. mov di,[bp].pmUserBP
  878. mov es,[bp].pmUserES
  879. mov si,offset DGROUP:rgbXfrBuf1
  880. cld
  881. rep movsw
  882. pop es
  883. push ds
  884. pop es
  885. assume es:DGROUP
  886. mov word ptr [bp].pmUserBP,di ;update dest ptr for next time
  887. ; mov word ptr lpSectorData,di ;update dest ptr for next time
  888. ; call NormalizeBufPtr ; and normailize it
  889. rws_not_read:
  890. mov ax,cSectorsThisTransfer ;count total sectors transfered
  891. add cSectorsTransfered,ax ;add sectors transmitted
  892. ;to previous sectors
  893. ;----------- 90/11/09 copy the segment address -------
  894. push ax
  895. mov ax,[bp].pmUserES ;90/09/19 BX regster restor
  896. mov [bp].intUserES,ax
  897. mov ax,[bp].pmUserBP
  898. mov [bp].intUserBP,ax
  899. pop ax
  900. ;------------------------------------------------------------
  901. jmp rws_do_it_loop ;go do another buffer full
  902. rws_done:
  903. mov ax,word ptr [lpSectorData+2] ;release our temp buffer sel
  904. call FreeSelector
  905. jmp [bp].wParam2
  906. else ;NEC_98 ;
  907. pop [bp].wParam2 ;save return addr higher on stack
  908. ; Setup the global data items for the read/write--pointer to caller's
  909. ; buffer, # sectors to read/write, and sector size.
  910. cmp byte ptr [bp].wParam1+1,13h ;Int 13h?
  911. jnz rws_dos_size
  912. mov ax,[bp].pmUserBX ;ES:BX points to caller's buf
  913. mov word ptr lpSectorData,ax
  914. mov ax,[bp].pmUserES
  915. mov word ptr [lpSectorData+2],ax
  916. mov al,byte ptr [bp].intUserAX ;# sectors caller wants to
  917. xor ah,ah ; read or write
  918. mov cSectorsToTransfer,ax
  919. mov ah,08h ;get drive parameters
  920. mov dx,[bp].intUserDX ; for drive in DL
  921. push ax
  922. SwitchToRealMode
  923. pop ax
  924. pushf ;have BIOS get the drive data
  925. sub sp,8 ; make room for stack frame
  926. push bp
  927. mov bp,sp
  928. push es
  929. push ax
  930. xor ax,ax
  931. mov es,ax
  932. mov [bp + 8],cs
  933. mov [bp + 6],word ptr (offset rws_10)
  934. mov ax,es:[13h*4]
  935. mov [bp + 2],ax
  936. mov ax,es:[13h*4 + 2]
  937. mov [bp + 4],ax
  938. pop ax
  939. pop es
  940. pop bp
  941. retf
  942. rws_10: jnc @f
  943. mov cx,512 ;according to PS/2 tech ref, some
  944. jmp short rws_to_pm ; old bios versions may fail this,
  945. @@: ; just use 512 in that case
  946. mov cl,es:[di+3] ;sector size shift factor (0,1,2,3)
  947. mov ax,128
  948. shl ax,cl ;ax now = sector size
  949. mov cx,ax
  950. rws_to_pm:
  951. SwitchToProtectedMode
  952. FSTI ;don't need them disabled
  953. if DEBUG ;------------------------------------------------------------
  954. cmp cx,512
  955. jz @f
  956. Debug_Out "Odd sector size = #CX"
  957. @@:
  958. endif ;DEBUG --------------------------------------------------------
  959. jmp short rws_have_size
  960. ; Before DOS 4.0, CX was the # sectors to read/write. Starting with 4.0,
  961. ; if CX == -1, DS:BX points to a parameter block which contains the
  962. ; sector size at offset 4.
  963. rws_dos_size:
  964. mov cx,[bp].intUserCX ;caller's cs == -1?
  965. inc cx
  966. jcxz rws_dos_4
  967. dec cx ; no, then cx has sector count
  968. mov ax,[bp].pmUserBX ; and DS:BX points to buffer
  969. mov word ptr lpSectorData,ax
  970. mov ax,[bp].pmUserDS
  971. mov word ptr [lpSectorData+2],ax
  972. jmp short rws_dos_num_secs
  973. rws_dos_4:
  974. mov cx,word ptr rgbXfrBuf0+4 ; yes, get count from low param block
  975. push ds ; and DS:BX points to param block
  976. mov ds,[bp].pmUserDS ; which contains pointer to buffer
  977. assume ds:NOTHING
  978. mov bx,[bp].pmUserBX
  979. mov ax,word ptr ds:[bx+6]
  980. mov word ptr lpSectorData,ax
  981. mov ax,word ptr ds:[bx+8]
  982. mov word ptr [lpSectorData+2],ax
  983. pop ds
  984. assume DS:DGROUP
  985. rws_dos_num_secs:
  986. mov cSectorsToTransfer,cx ;number sectors to read/write
  987. mov cx,512 ;I've been assured by a WINFILE developer
  988. ; that the Int 25/26 sector size will always
  989. ; be 512 bytes.
  990. ; CX now has the drive's sector size. Determine how many sectors we can
  991. ; transfer at a time
  992. rws_have_size:
  993. mov cbSectorSize,cx ;save sector size for later
  994. xor dx,dx
  995. mov ax,CB_XFRBUF1 ;buf size / sector size = sectors per
  996. div cx ; transfer
  997. if DEBUG ;------------------------------------------------------------
  998. or ax,ax
  999. jnz @f
  1000. Debug_Out "Sectors per transfer = 0!"
  1001. @@:
  1002. endif ;DEBUG --------------------------------------------------------
  1003. mov cSectorsPerTransfer,ax
  1004. xor ax,ax
  1005. mov cSectorsTransfered,ax ;sectors transfered so far = 0
  1006. mov cSectorsThisTransfer,ax ;sectors transfered last time = 0
  1007. ; Get/init a selector that we'll use to reference the caller's buffer.
  1008. mov ax,word ptr [lpSectorData+2] ;get lma of caller's buffer
  1009. call GetSegmentAddress
  1010. add dx,word ptr lpSectorData
  1011. adc bx,0
  1012. call AllocateSelector ;build a sel/dscr pointing
  1013. mov cx,0FFFFh
  1014. cCall NSetSegmentDscr,<ax,bx,dx,0,cx,STD_DATA>
  1015. xor bx,bx
  1016. mov word ptr lpSectorData,bx ;use that as the buffer ptr
  1017. mov word ptr [lpSectorData+2],ax
  1018. ; ======================================================================
  1019. ; Main sector read/write loop ------------------------------------------
  1020. ; ======================================================================
  1021. rws_do_it_loop:
  1022. ; Calculate how many sectors to transfer this time around, set starting
  1023. ; sector number based on how many transfered last time.
  1024. mov ax,cSectorsToTransfer
  1025. sub ax,cSectorsTransfered
  1026. jnz @f
  1027. jmp rws_done
  1028. @@:
  1029. cmp ax,cSectorsPerTransfer
  1030. jna @f
  1031. mov ax,cSectorsPerTransfer
  1032. @@:
  1033. mov bx,cSectorsThisTransfer ;STIll # R/W from last loop
  1034. cmp byte ptr [bp].wParam1+1,13h ;BIOS read/write?
  1035. jnz rws_use_dos_size
  1036. push [bp].pmUserAX ;the BIOS does not save
  1037. pop [bp].intUserAX ; registers across calls to
  1038. push [bp].pmUserCX ; it so if we're doing
  1039. pop [bp].intUserCX ; multiple calls to buffer
  1040. push [bp].pmUserDX ; data, restore the initial
  1041. pop [bp].intUserDX ; register values
  1042. mov byte ptr [bp].intUserAX,al ;# sectors in AL
  1043. add byte ptr [bp].intUserCX,bl ;update new start sector in CL
  1044. jmp short rws_size_start_set
  1045. rws_use_dos_size:
  1046. cmp [bp].intUserCX,0FFFFh ;normal or extended DOS?
  1047. jz rws_dos4_size
  1048. mov [bp].intUserCX,ax ; normal, # sectors in CX
  1049. add [bp].intUserDX,bx ; new start sector in DX
  1050. jmp short rws_size_start_set
  1051. rws_dos4_size:
  1052. mov word ptr rgbXfrBuf0+4,ax ; extended, # sectors & 32 bit
  1053. add word ptr rgbXfrBuf0,bx ; start sector in parameter
  1054. adc word ptr rgbXfrBuf0+2,0 ; block
  1055. rws_size_start_set:
  1056. ; At this point, AX has the number of sectors to transfer. If this is a
  1057. ; write, copy a buffer of data from the caller's buffer.
  1058. mov cSectorsThisTransfer,ax ;in case it's a read
  1059. cmp [bp].wParam1,1303h ;BIOS write?
  1060. jz rws_buf_write
  1061. cmp byte ptr [bp].wParam1+1,26h ;DOS write?
  1062. jnz rws_not_write
  1063. rws_buf_write:
  1064. mul cbSectorSize ;AX now = # bytes to transfer
  1065. mov cx,ax ;can safely assume < 64k
  1066. shr cx,1 ;# words to move
  1067. lds si,lpSectorData
  1068. assume ds:NOTHING
  1069. mov di,offset rgbXfrBuf1
  1070. cld
  1071. rep movsw
  1072. push es
  1073. pop ds
  1074. assume ds:DGROUP
  1075. mov word ptr lpSectorData,si ;update src ptr for next time
  1076. call NormalizeBufPtr ; and normalize it
  1077. rws_not_write:
  1078. ; Switch to real mode, do the transfer.
  1079. SwitchToRealMode
  1080. assume ds:DGROUP,es:DGROUP
  1081. push word ptr [bp].lParam
  1082. pop word ptr lpRmISR
  1083. push word ptr [bp].lParam+2
  1084. pop word ptr lpRmISR+2
  1085. cmp byte ptr [bp].wParam1+1,13h
  1086. jnz rws_call_dos
  1087. pop es
  1088. pop ds
  1089. assume ds:NOTHING,es:NOTHING,ss:DGROUP
  1090. popa
  1091. call lpRmISR
  1092. pushf
  1093. FCLI
  1094. jmp short rws_save_regs
  1095. rws_call_dos:
  1096. pop es
  1097. pop ds
  1098. assume ds:NOTHING,es:NOTHING,ss:DGROUP
  1099. popa
  1100. call lpRmISR
  1101. pop word ptr lpRmISR ;int 25/26 leave flags on stack,
  1102. pushf ; pop them to nowhere
  1103. FCLI
  1104. rws_save_regs:
  1105. pusha
  1106. push ds
  1107. push es
  1108. mov bp,sp ;restore stack frame pointer
  1109. SwitchToProtectedMode
  1110. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  1111. FSTI ;allow HW interrupts
  1112. ; If the call failed, then cut out now without further processing...
  1113. test byte ptr [bp].intUserFL,1 ;CY set?
  1114. jnz rws_done
  1115. ; If this was a successful read, copy the data back to the caller.
  1116. cmp [bp].wParam1,1302h ;BIOS read?
  1117. jz rws_buf_read
  1118. cmp byte ptr [bp].wParam1+1,25h ;DOS read?
  1119. jnz rws_not_read
  1120. rws_buf_read:
  1121. mov ax,cSectorsThisTransfer ;calc size of data to move
  1122. mul cbSectorSize
  1123. mov cx,ax
  1124. shr cx,1 ;in words
  1125. les di,lpSectorData ;caller's buffer pointer
  1126. assume es:NOTHING
  1127. mov si,offset rgbXfrBuf1
  1128. cld
  1129. rep movsw
  1130. push ds
  1131. pop es
  1132. assume es:DGROUP
  1133. mov word ptr lpSectorData,di ;update dest ptr for next time
  1134. call NormalizeBufPtr ; and normailize it
  1135. rws_not_read:
  1136. mov ax,cSectorsThisTransfer ;count total sectors transfered
  1137. add cSectorsTransfered,ax
  1138. jmp rws_do_it_loop ;go do another buffer full
  1139. rws_done:
  1140. mov ax,word ptr [lpSectorData+2] ;release our temp buffer sel
  1141. call FreeSelector
  1142. jmp [bp].wParam2
  1143. endif ;NEC_98 ;
  1144. ReadWriteSectors endp
  1145. ifdef NEC_98 ;
  1146. ; -------------------------------------------------------
  1147. subttl Disk Utility Routines
  1148. page
  1149. ; -------------------------------------------------------
  1150. ; DISK UTILITY ROUTINES
  1151. ; -------------------------------------------------------
  1152. ; DOSReadWriteSectors -- Common code to read/write disk sectors for
  1153. ; Int 13h/25h/26h.
  1154. ;
  1155. ; In: lParam - seg:off of real mode interrupt handler
  1156. ; wParam1 - int #, and possible subfunction
  1157. ; regs on stack
  1158. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  1159. public DOSReadWriteSectors
  1160. DOSReadWriteSectors proc near
  1161. ; int 3 ;------ 90/11/08 debug ------
  1162. ; pop [bp].wParam3 ;save return addr higher on stack
  1163. ; Setup the global data items for the read/write--pointer to caller's
  1164. ; buffer, # sectors to read/write, and sector size.
  1165. ; Before DOS 4.0, CX was the # sectors to read/write. Starting with 4.0,
  1166. ; if CX == -1, DS:BX points to a parameter block which contains the
  1167. ; sector size at offset 4.
  1168. rws_dos_size:
  1169. mov cx,[bp].intUserCX ;caller's cs == -1?
  1170. inc cx
  1171. jcxz rws_dos_4
  1172. dec cx ; no, then cx has sector count
  1173. mov ax,[bp].pmUserBX ; and DS:BX points to buffer
  1174. mov word ptr lpSectorData,ax
  1175. mov ax,[bp].pmUserDS
  1176. mov word ptr [lpSectorData+2],ax
  1177. jmp short rws_dos_num_secs
  1178. rws_dos_4:
  1179. mov cx,word ptr rgbXfrBuf0+4 ; yes, get count from low param block
  1180. push ds ; and DS:BX points to param block
  1181. mov ds,[bp].pmUserDS ; which contains pointer to buffer
  1182. assume ds:NOTHING
  1183. mov bx,[bp].pmUserBX
  1184. mov ax,word ptr ds:[bx+6]
  1185. mov word ptr lpSectorData,ax
  1186. mov ax,word ptr ds:[bx+8]
  1187. mov word ptr [lpSectorData+2],ax
  1188. pop ds
  1189. assume DS:DGROUP
  1190. rws_dos_num_secs:
  1191. mov cSectorsToTransfer,cx ;number sectors to read/write
  1192. ;
  1193. ; We will need the sector size if we have to break up the transfer.
  1194. ;
  1195. if 0
  1196. push ds
  1197. push bx
  1198. mov dl,byte ptr [bp].pmUserAX
  1199. inc dl
  1200. mov ah,1ch
  1201. assume DS:NOTHING
  1202. int 21h
  1203. pop bx
  1204. pop ds
  1205. assume DS:DGROUP
  1206. cmp al,0ffh
  1207. jne rws_have_size
  1208. ;
  1209. ; Call to DOS to get drive data failed, probably due to invalid
  1210. ; drive number. Assume 512, let INT 25h/26h return the failure.
  1211. ;
  1212. rws_use_default:
  1213. @@ mov cx,512
  1214. else
  1215. push bx
  1216. mov bl, byte ptr [bp].pmUserAX
  1217. inc bl
  1218. call GetSectorSize
  1219. pop bx
  1220. endif
  1221. ; CX now has the drive's sector size. Determine how many sectors we can
  1222. ; transfer at a time
  1223. DOS_rws_have_size:
  1224. mov cbSectorSize,cx ;save sector size for later
  1225. xor dx,dx
  1226. mov ax,CB_XFRBUF1 ;buf size / sector size = sectors per
  1227. div cx ; transfer
  1228. if DEBUG ;------------------------------------------------------------
  1229. or ax,ax
  1230. jnz @f
  1231. Debug_Out "Sectors per transfer = 0!"
  1232. @@:
  1233. endif ;DEBUG --------------------------------------------------------
  1234. mov cSectorsPerTransfer,ax
  1235. xor ax,ax
  1236. mov cSectorsTransfered,ax ;sectors transfered so far = 0
  1237. mov cSectorsThisTransfer,ax ;sectors transfered last time = 0
  1238. ; Get/init a selector that we'll use to reference the caller's buffer.
  1239. mov ax,word ptr [lpSectorData+2] ;get lma of caller's buffer
  1240. call GetSegmentAddress
  1241. add dx,word ptr lpSectorData
  1242. adc bx,0
  1243. call AllocateSelector ;build a sel/dscr pointing
  1244. mov cx,0FFFFh
  1245. cCall NSetSegmentDscr,<ax,bx,dx,0,cx,STD_DATA>
  1246. xor bx,bx
  1247. mov word ptr lpSectorData,bx ;use that as the buffer ptr
  1248. mov word ptr [lpSectorData+2],ax
  1249. ; ======================================================================
  1250. ; Main sector read/write loop ------------------------------------------
  1251. ; ======================================================================
  1252. DOS_rws_do_it_loop:
  1253. ; Calculate how many sectors to transfer this time around, set starting
  1254. ; sector number based on how many transfered last time.
  1255. ; int 3 ;------ 90/11/08 debug ------
  1256. mov ax,cSectorsToTransfer ;totak sectors
  1257. sub ax,cSectorsTransfered ;total sectors - sectors transmitted = remaine sectors
  1258. jnz @f
  1259. jmp DOS_rws_done
  1260. @@:
  1261. cmp ax,cSectorsPerTransfer ;buffer size / sector len = sectors in buffer
  1262. jna @f ;sectors in buffer > remain = remain
  1263. mov ax,cSectorsPerTransfer ;sectors in buf < remain = sectors in buffer
  1264. @@:
  1265. mov bx,cSectorsThisTransfer ;still # R/W from last loop
  1266. rws_use_dos_size:
  1267. cmp [bp].intUserCX,0FFFFh ;normal or extended DOS?
  1268. jz rws_dos4_size
  1269. mov [bp].intUserCX,ax ; normal, # sectors in CX
  1270. add [bp].intUserDX,bx ; new start sector in DX
  1271. jmp short DOS_rws_size_start_set
  1272. rws_dos4_size:
  1273. mov word ptr rgbXfrBuf0+4,ax ; extended, # sectors & 32 bit
  1274. add word ptr rgbXfrBuf0,bx ; start sector in parameter
  1275. adc word ptr rgbXfrBuf0+2,0 ; block
  1276. DOS_rws_size_start_set:
  1277. ; At this point, AX has the number of sectors to transfer. If this is a
  1278. ; write, copy a buffer of data from the caller's buffer.
  1279. mov cSectorsThisTransfer,ax ;in case it's a read
  1280. ;cSectorsThisTransfer = sectors in buffer or remain sectors
  1281. ;----------------- 90/07/24 -----------------------------------------
  1282. cmp byte ptr [bp].wParam1+1,26h ;DOS write?
  1283. jz DOS_rws_buf_write
  1284. jmp DOS_rws_not_write
  1285. DOS_rws_buf_write:
  1286. mul cbSectorSize ;AX now = # bytes to transfer
  1287. mov cx,ax ;can safely assume < 64k
  1288. shr cx,1 ;# words to move
  1289. lds si,lpSectorData
  1290. assume ds:NOTHING
  1291. mov di,offset rgbXfrBuf1
  1292. cld
  1293. rep movsw
  1294. push es
  1295. pop ds
  1296. assume ds:DGROUP
  1297. mov word ptr lpSectorData,si ;update src ptr for next time
  1298. call NormalizeBufPtr ; and normalize it
  1299. DOS_rws_not_write:
  1300. ; Switch to real mode, do the transfer.
  1301. SwitchToRealMode
  1302. assume ds:DGROUP,es:DGROUP
  1303. push word ptr [bp].lParam
  1304. pop word ptr lpRmISR
  1305. push word ptr [bp].lParam+2
  1306. pop word ptr lpRmISR+2
  1307. rws_call_dos:
  1308. pop es
  1309. pop ds
  1310. assume ds:NOTHING,es:NOTHING,ss:DGROUP
  1311. popa
  1312. pusha ; This trashes all registers
  1313. call lpRmISR
  1314. mov bp,sp
  1315. jnc @F ; If carry, AX = error code
  1316. mov [bp+14],ax
  1317. @@:
  1318. popa
  1319. pop word ptr lpRmISR ; int 25/26 leave flags on stack,
  1320. ; pop them to nowhere
  1321. pushf
  1322. FCLI
  1323. DOS_rws_save_regs:
  1324. ; int 3
  1325. pusha
  1326. push ds
  1327. push es
  1328. mov bp,sp ;restore stack frame pointer
  1329. SwitchToProtectedMode
  1330. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  1331. FSTI ;allow HW interrupts
  1332. ; If the call failed, then cut out now without further processing...
  1333. test byte ptr [bp].intUserFL,1 ;CY set?
  1334. jnz DOS_rws_done
  1335. ; If this was a successful read, copy the data back to the caller.
  1336. ;----------------- 90/07/23 -----------------------------------------
  1337. cmp byte ptr [bp].wParam1+1,25h ;DOS read?
  1338. jz DOS_rws_buf_read
  1339. jmp DOS_rws_not_read
  1340. DOS_rws_buf_read:
  1341. mov ax,cSectorsThisTransfer ;calc size of data to move
  1342. mul cbSectorSize
  1343. mov cx,ax
  1344. shr cx,1 ;in words
  1345. les di,lpSectorData ;caller's buffer pointer
  1346. assume es:NOTHING
  1347. mov si,offset rgbXfrBuf1
  1348. cld
  1349. rep movsw
  1350. push ds
  1351. pop es
  1352. assume es:DGROUP
  1353. mov word ptr lpSectorData,di ;update dest ptr for next time
  1354. call NormalizeBufPtr ; and normailize it
  1355. DOS_rws_not_read:
  1356. mov ax,cSectorsThisTransfer ;count total sectors transfered
  1357. add cSectorsTransfered,ax ;add sectors transmitted
  1358. ;to previous sectors
  1359. jmp DOS_rws_do_it_loop ;go do another buffer full
  1360. DOS_rws_done:
  1361. mov ax,word ptr [lpSectorData+2] ;release our temp buffer sel
  1362. call FreeSelector
  1363. jmp [bp].wParam2
  1364. DOSReadWriteSectors endp
  1365. endif ;NEC_98 ;
  1366. ; -------------------------------------------------------
  1367. ; This routine 'normalizes' the far pointer in lpSectorData such that
  1368. ; the selector/descriptor points to where the selector:offset currently
  1369. ; points
  1370. assume ds:DGROUP,es:NOTHING
  1371. NormalizeBufPtr proc near
  1372. mov ax,word ptr [lpSectorData+2] ;get segment base address
  1373. call GetSegmentAddress
  1374. add dx,word ptr lpSectorData ;add in current offset
  1375. adc bx,0
  1376. call SetSegmentAddress ;make that the new seg base
  1377. xor bx,bx
  1378. mov word ptr lpSectorData,bx ; with a zero offset
  1379. ret
  1380. NormalizeBufPtr endp
  1381. ifdef NEC_98 ;
  1382. public GetSectorSize
  1383. GetSectorSize proc near
  1384. push ax
  1385. push bx
  1386. push dx
  1387. push ds
  1388. sub sp, 40h
  1389. mov dx, sp
  1390. push ss
  1391. pop ds
  1392. mov ax, 440Dh
  1393. mov cx, 0860h
  1394. int 21h
  1395. ifdef NEC_98
  1396. mov cx, 1024 ; if 440D doesn't work, 512 bytes!
  1397. else ;NEC_98
  1398. mov cx, 512 ; if 440D doesn't work, 512 bytes!
  1399. endif ;NEC_98
  1400. jc @F
  1401. mov bx, dx
  1402. mov cx, word ptr ds:[bx+7] ; bytes per sector first field
  1403. @@: add sp, 40h
  1404. pop ds ; in BPB at offset 7.
  1405. pop dx
  1406. pop bx
  1407. pop ax
  1408. ret
  1409. GetSectorSize endp
  1410. ;-------------------------- DBIOS_DEVICE --------------------------------
  1411. ; for difference of cylinders, heads, sectors between all devices
  1412. ; if reached at each max value, we change the cylinders, heads
  1413. ; to have a READ/WRITE process
  1414. ;------------------------------------------------------------------------
  1415. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  1416. public DBIOS_DEVICE
  1417. DBIOS_DEVICE proc near
  1418. mov ax,[bp].intUserDX ;DH = head num�CDL = sector num
  1419. cmp byte ptr sensedata4,al ;maximum sector num ?
  1420. jnz DBIOS_RET ;NO = JMP
  1421. cmp byte ptr sensedata3,ah ;maximum head num ?
  1422. jnz HEADINC ;NO = JMP
  1423. mov [bp].intUserDX,0 ;DH = head num�CDL = sector num 0
  1424. mov ax,[bp].intUserCX ;set the next cylinder
  1425. add al,1 ;
  1426. mov [bp].intUserCX,ax ;
  1427. DBIOS_RET:
  1428. ret ;
  1429. HEADINC:
  1430. add ah,1 ;increase head num
  1431. mov al,0 ;sector num 0
  1432. mov [bp].intUserDX,ax ;set
  1433. ret
  1434. DBIOS_DEVICE endp
  1435. endif ;NEC_98 ;
  1436. DXPMCODE ends
  1437. ;****************************************************************
  1438. end