loaddrv.asm
上传用户:xiaoan1112
上传日期:2013-04-11
资源大小:19621k
文件大小:15k
源码类别:

操作系统开发

开发平台:

Visual C++

  1. ;*
  2. ;* CW : Character Windows
  3. ;*
  4. ;* loaddrv.asm : installable driver loader routines
  5. include kernel.inc
  6. include kmem.inc
  7. include indrv.inc
  8. include inscr.inc
  9. include inkbd.inc
  10. include insyd.inc
  11. include _loaddrv.inc
  12. ;*****************************************************************************
  13. ;* App call backs for memory management
  14. ;; REVIEW: hard coded driver allocation!
  15. externFP <LpwAllocDriverMem,FreeDriverMem>
  16. IFDEF DOS5
  17. externFP <DosOpen, DosClose>
  18. externFP <DosChgFilePtr, DosRead>
  19. externFP <DosCreateCSAlias>
  20. ENDIF
  21. sBegin DATA
  22.     assumes CS,DGROUP
  23.     assumes DS,DGROUP
  24. ifndef DOS5
  25. externW chDrivePhantom ; set to "b:" on one floppy systems.
  26. endif ; !DOS5
  27. externW <inkj> ; keyboard
  28. externW <insj> ; screen (character)
  29. externW <inyj> ; system
  30. ifdef DUAL
  31. ifndef DOS5
  32. LDRVDATA = 1
  33. endif
  34. else ;!DUAL
  35. LDRVDATA = 1
  36. endif ;!DUAL
  37. ifdef LDRVDATA
  38. labelW <PUBLIC, rgindvCw> ;* INDV structures for csd, kbd
  39. labelW <PUBLIC, indvKbd> ;* Keyboard
  40. DB indtKeyboard,0
  41. DW dataOffset inkj
  42. DW cpfnKbdMin
  43. DW cpfnKbdMin
  44. DW 0
  45. DW 0
  46. labelW <PUBLIC, indvCsd> ;* Character Screen
  47. DB indtCharacterScreen,0
  48. DW dataOffset insj
  49. DW cpfnCsdMin
  50. DW cpfnCsdMin
  51. DW 0
  52. DW 0
  53. labelW <PUBLIC, indvSyd> ;* System Services
  54. DB indtSystem,0
  55. DW dataOffset inyj
  56. DW cpfnSydMin
  57. DW cpfnSydMin
  58. DW 0
  59. DW 0
  60. PUBLIC cindvCw
  61. cindvCw EQU ($-rgindvCw)/cbIndvMin
  62. else ;!LDRVDATA
  63. externW rgindvCw
  64. endif ;!LDRVDATA
  65. IFDEF DOS5
  66. externB inosDrv ;* INOS info (from loaddrv.asm)
  67. ENDIF ;DOS5
  68. sEnd DATA
  69. ifndef LDRVDATA
  70. externA cindvCw
  71. endif ;!LDRVDATA
  72. ;*****************************************************************************
  73. sBegin KERNEL
  74.     assumes CS,KERNEL
  75.     assumes DS,DGROUP
  76.     assumes SS,DGROUP
  77. ;********** RerrLoadDrvFd **********
  78. ;* entry: hFile => valid file handle
  79. ;* rgindv => cindv INDV records
  80. ;* * Loads drivers from given file
  81. ;* exit: 0 ok, otherwise error code: rerrBadRead,
  82. ;*   rerrBadFormat,
  83. ;*   rerrNoMemory,
  84. ;*   rerrBadFile,
  85. ;*   rerrBadMemReq,
  86. ;*   rerrBadVersion
  87. ;*
  88. ;* On error, no service is partially installed.  However, only some
  89. ;* services may have been installed.
  90. ;*
  91. ;* nop if cindv == 0 
  92. rldf_badopen:
  93. mov ax,rerrBadFile ; restrict error returned
  94. rldf_Abort1:
  95. jmp rldf_Abort
  96. ;----------------------------------------
  97. cProc RerrLoadDrvFd, <PUBLIC,FAR>,<DI,SI>
  98.     parmW hFile
  99.     parmW rgindv
  100.     parmW cindv
  101. IFDEF DOS5
  102.     localW action
  103.     localW HI_tmp
  104.     localW LO_tmp
  105. ENDIF ;DOS5
  106.     localW HI_lfaMT
  107.     localW LO_lfaMT
  108.     localW HI_lpwCSeg
  109.     localW LO_lpwCSeg
  110.     localW HI_lfaReadMT
  111.     localW LO_lfaReadMT
  112.     localW pindv
  113.     localW cb ; count of bytes in rgbBuff
  114.     localV rgbBuff,cbBuff ; buffer for master table entries
  115. cBegin RerrLoadDrvFd
  116. ;* set indv's to not loaded
  117. xor ax,ax
  118. mov cx,cindv
  119. jcxz rldf_Abort1 ; no service will be loaded
  120. mov di,rgindv
  121. @@: jcxz @F
  122. mov [di].psLoadedIndv,ax
  123. mov [di].cpfnLoadedIndv,ax
  124. add di,cbIndvMin
  125. loop @B
  126. @@:
  127. IFNDEF DOS5
  128. ;* seek to EOF magic tag
  129. mov bx,hFile
  130. mov ax,-cbIndhMin
  131. cwd
  132. mov cx,dx
  133. mov dx,ax
  134. mov ax,4202h ; offset is from EOF
  135. int 21h
  136. jc rldf_AbFileshort2
  137. ;* compute absolute offset to EOF
  138. add ax,cbIndhMin
  139. adc dx,0
  140. mov LO_lfaReadMT,ax
  141. mov HI_lfaReadMT,dx
  142. ELSE
  143. ;* seek to EOF magic tag
  144. mov ax,-cbIndhMin
  145. cwd
  146. lea bx,LO_lfaReadMT ; HI_ is in appropriate position
  147. cCall DosChgFilePtr,<hFile,dx,ax,2,ss,bx>
  148. or ax,ax
  149. jnz rldf_AbFileshort2
  150. ;* compute absolute offset to EOF
  151. mov ax,cbIndhMin
  152. add LO_lfaReadMT,ax
  153. adc HI_lfaReadMT,0
  154. ENDIF ;DOS5
  155. ;* read magic tag and dlfaTable
  156. lea dx,rgbBuff
  157. IFNDEF DOS5
  158. mov ah,3fh
  159. AssertEQ bx,hFile
  160. mov cx,cbIndhMin
  161. int 21h
  162. jc rldf_AbFileshort2
  163. ELSE
  164. lea ax,cb
  165. cCall DosRead,<hFile,ss,dx,cbIndhMin,ss,ax>
  166. or ax,ax
  167. jnz rldf_AbFileshort2
  168. mov ax,cb
  169. ENDIF ;DOS5
  170. cmp ax,cbIndhMin ; check read
  171. mov ax,rerrBadRead
  172. jne rldf_AbFileshort1
  173. mov ax,rerrBadFormat
  174. mov cx,rgbBuff+LO_rgchMagicIndh
  175. ; check magic word ("DRV0")
  176. cmp cx,'RD'
  177. jne rldf_AbFileshort1 ; invalid format
  178. mov cx,rgbBuff+HI_rgchMagicIndh
  179. cmp cx,'0V'
  180. je @F
  181. rldf_AbFileshort2:
  182. mov ax,rerrBadRead
  183. rldf_AbFileshort1:
  184. jmp rldf_AbFile ; invalid format
  185. @@:
  186. ;* compute offset of master table
  187. mov dx,LO_lfaReadMT
  188. mov cx,HI_lfaReadMT
  189. sub dx,rgbBuff+LO_dlfaTableIndh
  190. sbb cx,rgbBuff+HI_dlfaTableIndh
  191. ;* save lfa of master table
  192. mov LO_lfaMT,dx
  193. mov HI_lfaMT,cx
  194. ;* prep for master table read
  195. mov LO_lfaReadMT,dx
  196. mov HI_lfaReadMT,cx
  197. mov cx,cbBuff
  198. ;*
  199. ;* Read from lfaReadMT into rgbBuff
  200. ;* cx bytes to read
  201. ;*
  202. ;* cb bytes read
  203. ;* lfaReadMT
  204. ;* adjusted to next byte to be read
  205. ;* di points to first INDS (smart about table header)
  206. rldf_ReadMT:
  207. ;* seek to lfaReadMT
  208. IFNDEF DOS5
  209. push cx
  210. mov ax,4200h
  211. mov bx,hFile
  212. mov dx,LO_lfaReadMT
  213. mov cx,HI_lfaReadMT
  214. int 21h
  215. pop cx
  216. jc rldf_AbFileshort2
  217. ELSE
  218. lea ax,LO_tmp ; dummy
  219. cCall DosChgFilePtr,<hFile,HI_lfaReadMT,LO_lfaReadMT,0,ss,ax>
  220. or ax,ax
  221. jnz rldf_AbFileshort2
  222. ENDIF ;DOS5
  223. ;* read master table entries
  224. lea dx,rgbBuff
  225. IFNDEF DOS5
  226. mov ah,3fh
  227. AssertEQ bx,hFile
  228. int 21h
  229. jc rldf_AbFileshort2
  230. mov cb,ax ; save bytes read
  231. ELSE
  232. lea ax,cb
  233. cCall DosRead,<hFile,ss,dx,cx,ss,ax>
  234. or ax,ax
  235. jnz rldf_AbFileshort2
  236. mov ax,cb
  237. ENDIF ;DOS5
  238. or ax,ax
  239. mov ax,rerrBadRead
  240. jnz @F
  241. jmp rldf_AbFile ; check for read beyond EOF
  242. @@:
  243. ;* cx:dx == lfaRead
  244. mov dx,LO_lfaReadMT
  245. mov cx,HI_lfaReadMT
  246. lea di,rgbBuff ; di points to inds struct
  247. ;* if we just read from lfaMT, check magic, load number of
  248. ;* services, and increase di after INDT
  249. cmp dx,LO_lfaMT
  250. jne not_first_mt_read
  251. cmp cx,HI_lfaMT
  252. jne not_first_mt_read
  253. ;* check magic word
  254. mov ax,rerrBadFormat
  255. mov bx,rgbBuff+LO_rgchMagicIndt
  256. ; check magic word ("DRV0")
  257. cmp bx,'RD'
  258. jne rldf_AbFileshort1 ; invalid format
  259. mov bx,rgbBuff+HI_rgchMagicIndt
  260. cmp bx,'0V'
  261. je @F
  262. jmp rldf_AbFile ; invalid format
  263. @@:
  264. ;* si == number of services
  265. mov si,rgbBuff+cindsIndt ; si services in file
  266. ;* di => INDS
  267. lea di,rgbBuff+rgindsIndt
  268. not_first_mt_read:
  269. ;* adjust lfaReadMT
  270. add dx,cb
  271. adc cx,0
  272. mov LO_lfaReadMT,dx
  273. mov HI_lfaReadMT,cx
  274. ;*
  275. ;* Load next service
  276. ;* si number of services left to load
  277. ;* di current inds structure
  278. ;*
  279. rldf_Load:
  280. ;* are we done?
  281. xor ax,ax
  282. dec si
  283. jge @F
  284. jmp rldf_done ; load completed
  285. @@:
  286. ;* have we run out of services in this block?
  287. lea ax,rgbBuff
  288. add ax,cb
  289. cmp ax,di
  290. ja @F
  291. ;* read next block of INDS structures
  292. inc si ;* retry this service
  293. mov cx,cbBlock
  294. jmp rldf_ReadMT
  295. @@:
  296. ;* should we load this service?
  297. push di
  298. ;* * first see if operating system is supported
  299. IFDEF DOS5
  300. test [di].floadInds,floadProtMode
  301. ELSE
  302. test [di].floadInds,floadRealMode
  303. ENDIF ;!DOS5
  304. jz rldf_indtNotfound
  305. mov ah,[di].indtInds
  306. ;* search rgindv
  307. mov di,rgindv
  308. mov cx,cindv
  309. rldf_nextindv:
  310. cmp ah,[di].indtIndv
  311. jne @F
  312. ; found indv
  313. mov pindv,di
  314. clc ; flag load
  315. jmp short rldf_endIndtLookup
  316. @@:
  317. add di,cbIndvMin
  318. loop rldf_nextindv
  319. rldf_indtNotfound:
  320. stc ; no service info, flag no load
  321. rldf_endIndtLookup:
  322. pop di
  323. jnc @F
  324. jmp rldf_loadnext ; unknown service
  325. @@:
  326. ;*
  327. ;* Load service segment
  328. ;*
  329. ;* allocate code area
  330. mov ax,[di].cbCodeInds
  331. inc ax ; round up
  332. AssertNE ax,0
  333. shr ax,1 ; convert cb -> cw
  334. test [di].floadInds,floadFixed
  335. IFNDEF LATER
  336. AssertNZ ; only know about fixed segments
  337. mov bx,fmemFixed
  338. ENDIF
  339. cCall <LpwAllocDriverMem>,<ax,bx>
  340. mov cx,ax
  341. or cx,dx
  342. jnz @F
  343. mov ax,rerrNoMemory
  344. jmp rldf_AbFile
  345. @@:
  346. IFDEF DEBUG ; valid pointers are either ds:offset
  347. ;  or other:0000
  348. mov bx,ds
  349. cmp bx,dx
  350. je @F
  351. AssertEQ ax,0
  352. @@:
  353. ENDIF ;DEBUG
  354. ;* save pointer to code area
  355. mov LO_lpwCSeg,ax
  356. mov HI_lpwCSeg,dx
  357. ;* seek to service segment
  358. mov dx,LO_lfaMT
  359. mov cx,HI_lfaMT
  360. sub dx,[di].LO_dlfaCodeInds ; calculate lfaCode
  361. sbb cx,[di].HI_dlfaCodeInds
  362. IFNDEF DOS5
  363. mov ax,4200h
  364. mov bx,hFile
  365. int 21h
  366. jc rldf_AbCodeshort2
  367. ELSE
  368. lea ax,LO_tmp ; dummy
  369. cCall DosChgFilePtr,<hFile,cx,dx,0,ss,ax>
  370. or ax,ax
  371. jnz rldf_AbCodeshort2
  372. ENDIF ;DOS5
  373. ;* read in code segment
  374. IFNDEF DOS5
  375. push ds
  376. mov ah,3fh
  377. mov bx,hFile
  378. mov cx,[di].cbCodeInds
  379. mov dx,HI_lpwCSeg
  380. mov ds,dx
  381. mov dx,LO_lpwCSeg
  382. int 21h
  383. pop ds
  384. jc rldf_AbCodeshort2
  385. ELSE
  386. lea ax,cb
  387. cCall DosRead,<hFile,HI_lpwCSeg,LO_lpwCSeg,[di].cbCodeInds,ss,ax>
  388. or ax,ax
  389. jnz rldf_AbCodeshort2
  390. mov ax,cb
  391. ENDIF ;DOS5
  392. cmp ax,[di].cbCodeInds ; check for read error
  393. jne rldf_AbCodeshort2
  394. ;* if load type is non-standard, this service is completed
  395. test [di].floadInds,floadStandard
  396. jnz @F
  397. jmp rldf_loadnext ; non-standard driver
  398. @@:
  399. ;* allocate data area
  400. mov bx,HI_lpwCSeg ; es:bx points to service header
  401. mov es,bx
  402. mov bx,LO_lpwCSeg
  403. mov ax,es:[bx].cbDataInsh
  404. inc ax
  405. shr ax,1 ; convert cb -> cw
  406. cmp ax,0
  407. jne @F
  408. xor ax,ax ; no data to allocate
  409. mov dx,ax
  410. jmp short rldf_load11 ; continue with link
  411. @@:
  412. push ax ; save word count for later
  413. mov cx,fmemFixed
  414. test es:[bx].fNearDataInsh,0ffffh
  415. jz @F
  416. mov cx,fmemNear
  417. cmp ax,cbNearMemServiceMax / 2
  418. jbe @F
  419. mov ax,rerrBadMemReq ; asking for too much near mem!
  420. jmp rldf_AbCode
  421. @@:
  422. cCall <LpwAllocDriverMem>,<ax,cx>
  423. ;* put word count in cx
  424. pop cx
  425. or ax,ax ; 0? failure
  426. jnz @F
  427. or dx,dx
  428. jnz @F
  429. mov ax,rerrNoMemory
  430. rldf_AbCodeshort1:
  431. jmp rldf_AbCode
  432. rldf_AbCodeshort2:
  433. mov ax,rerrBadRead
  434. jmp rldf_AbCode
  435. @@:
  436. rldf_load11:
  437. IFDEF DEBUG ; valid pointers are either ds:offset
  438. ;  or other:0000
  439. mov bx,ds
  440. cmp bx,dx
  441. je @F
  442. AssertEQ ax,0
  443. @@:
  444. ENDIF ;DEBUG
  445. ;* patch code segment with pointer to data segment and pinos
  446. mov es,HI_lpwCSeg ; es => code segment
  447. xor bx,bx
  448. mov es:[bx].LO_lpwDataInsh,ax
  449. mov es:[bx].HI_lpwDataInsh,dx
  450. ;* * set "pinos"
  451. IFNDEF DOS5
  452. mov es:[bx].pinosInsh,0
  453. ELSE
  454. mov es:[bx].pinosInsh,dataOffset inosDrv
  455. ENDIF
  456. IFDEF DOS5
  457. ;* create CS alias
  458. lea ax,HI_lpwCSeg
  459. mov bx,HI_lpwCSeg
  460. cCall DosCreateCSAlias,<bx,ss,ax>
  461. or ax,ax
  462. jz @F
  463. mov HI_lpwCSeg,bx ; restore selector on failure
  464. jmp rldf_AbCode
  465. @@:
  466. ;* restore registers used (es,ax,bx,cx,dx are important)
  467. ;* cx,dx not changed
  468. mov es,HI_lpwCSeg
  469. xor bx,bx
  470. mov ax,es:[bx].LO_lpwDataInsh
  471. ENDIF ;DOS5
  472. ;* clear data segment to zeros (assume word count in cx)
  473. ;* es:0 => code segment INSH
  474. ;* dx:ax => data segment
  475. ;* cx  data size (words)
  476. push es
  477. push di
  478. mov di,ax
  479. mov es,dx
  480. xor ax,ax
  481. rep stosw
  482. pop di
  483. pop es
  484. ;* get function count and rgpfn
  485. mov dx,es:[bx].cpfnInsh ; function count
  486. add bx,cbInshMin ; rgpfn
  487. ;* At this point we have:
  488. ;* es:bx => HI_lpwCSeg:rgpfn
  489. ;* dx    == cpfn
  490. ;* ds:di => inds
  491. ;* pindv OR psld => link info
  492. ;* link service to app
  493. push di
  494. push ds
  495. ;* check version
  496. ; check version
  497. ; link
  498. ; set return values of indv struct
  499. mov di,pindv
  500. cmp dx,ss:[di].cpfnNeedMinIndv
  501. jae @F ;* we have at least enough
  502. rldf_linkBadver:
  503. mov ax,rerrBadVersion
  504. stc
  505. jmp short rldf_linkdone
  506. @@:
  507. mov cx,ss:[di].cpfnNeedMacIndv ;* the max # we want
  508. cmp dx,cx
  509. jae @F ;* just copy the ones we want
  510. mov cx,dx ;* copy what we have < NeedMac
  511. @@:
  512. mov di,ss:[di].rglpfnIndv
  513. ;* link to app
  514. mov dx,ds ; segment switch for rep stosw
  515. mov ax,es
  516. mov ds,ax
  517. mov es,dx
  518. ; ds => HI_lpwCSeg
  519. ; es => DGROUP
  520. push cx ; save cfpn for later
  521. push cx
  522. push di
  523. shl cx,1
  524. mov ax,ds
  525. rep stosw ; fill app jump table with segment value
  526. pop di
  527. pop cx
  528. @@: ; fill in offsets
  529. mov ax,[bx]
  530. mov es:[di],ax
  531. inc bx
  532. inc bx
  533. add di,4
  534. loop @B
  535. pop cx ; restore cpfn
  536. ;* set return values in indv
  537. mov bx,pindv
  538. mov ss:[bx].cpfnLoadedIndv,cx
  539. mov cx,HI_lpwCSeg
  540. mov ss:[bx].psLoadedIndv,cx
  541. clc ; linkage completed
  542. rldf_linkdone:
  543. pop ds
  544. pop di
  545. jc rldf_AbData
  546. rldf_loadnext:
  547. add di,cbIndsMin
  548. jmp rldf_Load
  549. rldf_AbData:
  550. ;* Code and data segments allocated but couldn't link to app.
  551. ;* Free data then go on to free code and close hFile.
  552. push ax ; return code in ax
  553. mov ax,HI_lpwCSeg
  554. mov es,ax
  555. mov ax,es:LO_lpwDataInsh
  556. mov dx,es:HI_lpwDataInsh
  557. cCall <far ptr FreeDriverMem>,<dx,ax>
  558. pop ax
  559. rldf_AbCode:
  560. ;* Something went wrong before completing code segment that
  561. ;* was allocated - free it and close hFile.
  562. push ax ; return code in ax
  563. mov ax,LO_lpwCSeg
  564. mov dx,HI_lpwCSeg
  565. cCall <far ptr FreeDriverMem>,<dx,ax>
  566. pop ax
  567. rldf_done:
  568. rldf_AbFile:
  569. rldf_Abort:
  570. cEnd RerrLoadDrvFd
  571. ;********** RerrLoadDrv **********
  572. ;* entry: szFile => full path
  573. ;* rgindv => cindv INDV records
  574. ;* * Loads drivers from given file
  575. ;* exit: see RerrLoadDrvFd
  576. rlds_badopen:
  577. mov ax,rerrBadFile ; restrict error returned
  578. jmp short rlds_end
  579. ;----------------------------------------
  580. cProc RerrLoadDrv, <PUBLIC,FAR>,<DI,SI>
  581.     parmW szFile
  582.     parmW rgindv
  583.     parmW cindv
  584.     localW hFile
  585. cBegin RerrLoadDrv
  586. ;* open file
  587. IFDEF DOS5
  588. lea ax,hFile
  589. lea bx,action
  590. cCall DosOpen,<ss,szFile,ss,ax,ss,bx,0,0,0,01h,openRO,0,0>
  591. or ax,ax
  592. jnz rlds_badopen
  593. ELSE ; !DOS5
  594. mov dx,szFile
  595. mov bx,dx
  596. mov ax,[bx] ; Get first two letters
  597. or al,20h ; If the file is "B:xxx" on a single
  598. cmp ax,chDrivePhantom ;   floppy system, then no can do.
  599. je rlds_badopen
  600. mov ax,3d00h
  601. int 21h
  602. mov hFile,ax
  603. jc rlds_badopen
  604. ENDIF ; !DOS5
  605. cCall RerrLoadDrvFd,<hFile, rgindv, cindv>
  606. push ax ; return code in ax
  607. IFNDEF DOS5
  608. mov ah,3eh ; close file
  609. mov bx,hFile
  610. int 21h
  611. ELSE
  612. cCall DosClose,<hFile>
  613. ENDIF ;DOS5
  614. pop ax ; ignore return code from close
  615. rlds_end:
  616. cEnd RerrLoadDrv
  617. ;********** RerrLoadCwDrvFd **********
  618. ;* entry: hFile => valid file handle
  619. ;* * Loads kbd and csd drivers from given file
  620. ;* exit: same as RerrLoadDrvFd
  621. cProc RerrLoadCwDrvFd, <PUBLIC,FAR>
  622.     parmW hFile
  623. cBegin RerrLoadCwDrvFd
  624. mov ax,dataOffset rgindvCw
  625. mov cx,cindvCw
  626. cCall RerrLoadDrvFd,<hFile, ax, cx>
  627. cEnd RerrLoadCwDrvFd
  628. ;********** RerrLoadCwDrv **********
  629. ;* entry: szFile => full file name of driver
  630. ;* * Loads kbd and csd drivers from given file
  631. ;* exit: same as RerrLoadDrv
  632. cProc RerrLoadCwDrv, <PUBLIC,FAR>
  633.     parmW szFile
  634. cBegin RerrLoadCwDrv
  635. mov ax,dataOffset rgindvCw
  636. mov cx,cindvCw
  637. cCall RerrLoadDrv,<szFile, ax, cx>
  638. cEnd RerrLoadCwDrv
  639. sEnd KERNEL
  640. ;*****************************************************************************
  641. END