CONFIG.A86
上传用户:xiaogehua
上传日期:2007-01-08
资源大小:1183k
文件大小:42k
源码类别:

操作系统开发

开发平台:

Asm

  1. ;    File              : $CONFIG.A86$
  2. ;
  3. ;    Description       :
  4. ;
  5. ;    Original Author   : DIGITAL RESEARCH
  6. ;
  7. ;    Last Edited By    : $CALDERA$
  8. ;
  9. ;-----------------------------------------------------------------------;
  10. ;    Copyright Work of Caldera, Inc. All Rights Reserved.
  11. ;      
  12. ;    THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
  13. ;    PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
  14. ;    ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
  15. ;    WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
  16. ;    THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
  17. ;    HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
  18. ;    AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
  19. ;    AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
  20. ;    COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
  21. ;    CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
  22. ;    TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
  23. ;    CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
  24. ;    AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
  25. ;    CIVIL LIABILITY.
  26. ;-----------------------------------------------------------------------;
  27. ;
  28. ;    *** Current Edit History ***
  29. ;    *** End of Current Edit History ***
  30. ;
  31. ;    $Log$
  32. ;
  33. ;    CONFIG.A86 1.35 93/12/01 18:30:29
  34. ;    nls_temp_area grows to 258 bytes
  35. ;    CONFIG.A86 1.34 93/11/28 15:30:27
  36. ;    Support HIBUFFERS in UMB's
  37. ;    CONFIG.A86 1.32 93/11/22 15:02:14
  38. ;    Bus Master checks do Int 21/0D before/after to discard any buffers
  39. ;    CONFIG.A86 1.30 93/11/18 18:02:26 
  40. ;    Add primitive multi-master checking
  41. ;    CONFIG.A86 1.27 93/11/04 16:34:24
  42. ;    Extra callout to STACKER to determine if a drive is valid
  43. ;    CONFIG.A86 1.26 93/11/03 17:00:19
  44. ;    Stop dblspace phantom drives from appearing (FATsize=0)
  45. ;    CONFIG.A86 1.25 93/09/14 20:12:24
  46. ;    Initialise LFLG_PHYSICAL better - allow for zero FAT's meaning phantom drive
  47. ;    CONFIG.A86 1.24 93/09/02 22:34:50
  48. ;    Add header to system allocations
  49. ;    CONFIG.A86 1.23 93/08/06 20:55:23
  50. ;    re-arrange device init order for SCREATE.SYS on a VDISK.SYS
  51. ;    CONFIG.A86 1.22 93/08/02 14:45:55
  52. ;    hide preload drives from func_device
  53. ;    CONFIG.A86 1.20 93/07/28 19:19:08
  54. ;    call to SetupHMA before AllocHMA in setup_buffers allows buffers to go high
  55. ;    on novell memory managers
  56. ;    ENDLOG
  57. include config.equ
  58. include i:msdos.equ
  59. include i:char.def
  60. include i:reqhdr.equ
  61. include i:driver.equ
  62. include i:fdos.equ
  63. include i:f52data.def ; Function 52 DOS Data Area
  64. include i:doshndl.def ; DOS Handle Structure Definition
  65. include i:country.def
  66. TRUE     equ 0FFFFh       ; value of TRUE
  67. FALSE     equ 0       ; value of FALSE
  68. CGROUP group INITCODE, INITDATA
  69. INITCODE CSEG PARA 'INITCODE'
  70. extrn AllocHMA:near
  71. extrn SetupHMA:near
  72. extrn alloc_instseg:near ; Allocate "Segment" Instance Memory
  73. extrn alloc_hiseg:near ; Allocate "Segment" High Memory
  74. extrn alloc_seg:near ; Allocate "Segment" Memory
  75. extrn config_process:near
  76. extrn InitStacks:near
  77. extrn HookInt2F:near
  78. extrn UnhookInt2F:near
  79. extrn Verify386:near
  80. Public config_init
  81. config_init: ; Initialize the CONFIG data
  82. ret
  83. Public country_init
  84. country_init:
  85. ;------------
  86. push ds
  87. push es
  88. push di
  89. push si
  90. ; Obtain the address of the DBCS table in the BDOS.
  91. mov ax, 06507h ; Extended Country Info: get DBCS ptr
  92. mov bx, 0FFFFh ; codepage number: -1 for global cp
  93. mov cx, 00005h ; size of info. buffer
  94. mov dx, 0FFFFh ; country code: -1 for current country
  95. mov di, offset dbcs_buf
  96. push ds
  97. pop es ; es:di -> 5 byte buffer
  98. int DOS_INT ; returns with buffer filled in
  99. ; Get the current country information.
  100. mov dx, offset ctry_info ; ds:dx -> buffer to be filled in
  101. mov ax, 03800h ; get current country info
  102. int DOS_INT
  103. jnc ctry_info_done ; no carry = no error
  104. ; Failed to get country info. Place dummy uppercase routine in table.
  105. mov si, offset ctry_info
  106. mov CI_CASEOFF[si], offset myretf
  107. mov CI_CASESEG[si], cs
  108. mov bx, country_code
  109. ctry_info_done:
  110. mov country_code, bx
  111. pop si
  112. pop di
  113. pop es
  114. pop ds
  115. ret
  116. myretf: retf
  117. ;
  118. ; CONFIG is called after the BIOS INIT code has been relocated to high
  119. ; memory, the BIOS and BDOS have been initialised. 
  120. ;
  121. Public config ; Process CONFIG.SYS, loading and
  122. config: ; initialising device drivers
  123. call country_init ; initialise DBCS tbl and country info
  124. mov ax,max_secsize ; get maximum sector size in BIOS
  125. les bx,func52_ptr
  126. cmp ax,es:F52_SECSIZE[bx] ; larger than default?
  127.  jbe cfg_skip ; skip if not
  128. mov es:F52_SECSIZE[bx],ax ; else update sector size
  129. cfg_skip:
  130. call cpu_init ; initialise CPU type
  131. push ds ! pop es
  132. call config_process ; Process CONFIG.SYS
  133. cmp num_files,MIN_NUM_FILES ; Ensure the Minimum number of File
  134. jae cfg_ex10 ; have been allocated.
  135. mov num_files,MIN_NUM_FILES
  136. cfg_ex10:
  137. xor ax,ax
  138. mov al,init_buf ; now ensure we have allocated
  139. mov num_buf,ax ; the correct number of buffers
  140. call SetupDeblocking ; do our thing with deblocking
  141. call config_finish ; clean up configuration
  142. call setup_fopen ; allocate disk hashing
  143. call setup_history
  144. ret
  145. cpu_init:
  146. ; If we are on a 386 or above set CPU flag
  147. call Verify386 ; make sure it's a 386
  148.  jc cpu_init10 ; skip setting falg if not
  149. les bx,func52_ptr
  150. mov es:F52_CPU_TYPE[bx],1 ; we have a 386 !
  151. cpu_init10:
  152. stc ; it's not a 386
  153. ret
  154. SetupDeblocking:
  155. ;---------------
  156. ; Some types of hard disk controller give us problems with disk access of
  157. ; mapped memory (eg. upper memory, LIM pages).
  158. ; We can force single sector deblocking in the disk driver to avoid these
  159. ; problems. On DRDOS 5/6 our default was single sector I/O above A000, but
  160. ; this gives performance problems when devices/tsr's are loaded into upper
  161. ; memory (eg. STACKER, SERVER). To avoid this we use the following strategy.
  162. ;
  163. ; Default for CONFIG is A000, and may be updated at any time by a DEBLOCK=
  164. ; statement. If this happens the user setting has priority.
  165. ;
  166. ; At the end of CONFIG, assume no user supplied setting, we do some simple
  167. ; tests for multi-master controllers. If these fail we leave the settings
  168. ; at A000. If they succeed we go ahead and change the default setting to
  169. ; deblock at FFFF. The test is to read the 1st sector into low memory, and
  170. ; again into upper memory. If we read the same thing then assume all is well.
  171. ; If we can't do this leave the deblocking set at A000.
  172. ;
  173. ; NB. We will still have problems from LIM, and from DMA crossing page
  174. ; boundaries on some memory managers (eg. DRDOS 5.0)
  175. ;
  176. les bx,func52_ptr
  177. lea bx,F52_DEVROOT[bx] ; ES:BX -> NUL device link
  178. cmp DeblockSetByUser,FALSE
  179.  je SetupDeblocking20 ; the user is king
  180. SetupDeblocking10:
  181. push cs ! pop es ; ES -> local data again
  182. ret
  183. SetupDeblocking20: ; get next device driver
  184. les bx,es:[bx] ; we want resident disk device
  185. cmp bx,0FFFFh ; end of the chain ?
  186.  je SetupDeblocking10
  187. test es:word ptr 4[bx],8000h
  188.  jnz SetupDeblocking20 ; we assume one disk device at 70:xxxx
  189. mov ax,es
  190. cmp ax,cs:bios_seg ; scan for resident disk in IO.SYS
  191.  jne SetupDeblocking20
  192. cmp es:word ptr 18[bx],0EDCh
  193.  jne SetupDeblocking20 ; is it our disk driver ?
  194. lea ax,22[bx] ; deblocking variable is here
  195. mov deblockOffset,ax ; remember that for fixups
  196. mov deblockSeg,es
  197. mov ax,es:DH_STRATEGY[bx] ; Set up the STRATEGY Entry Point
  198. mov strategy_off,ax
  199. mov strategy_seg,es
  200. mov ax,es:DH_INTERRUPT[bx] ; Set up the INTERRUPT Entry Point
  201. mov interrupt_off,ax
  202. mov interrupt_seg,es
  203. mov al,es:DH_NAME[bx] ; get # supported units
  204. cbw
  205. mov numUnits,ax ; remember for later
  206. mov ax,(MS_M_STRATEGY*256)+1; set allocation strategy
  207. mov bl,42h ;  to last fit, upper only
  208. int DOS_INT
  209. mov bx,512/16 ; we need a 512 byte buffer
  210. mov ah, MS_M_ALLOC ; try to allocate on in upper memory
  211. int DOS_INT
  212.  jc SetupDeblocking50
  213. mov UpperMemoryBuffer,ax ; use this for deblocking checks
  214. mov cx,numUnits ; CX = # of drives supported
  215. mov dx,'C'-'A' ; start with drive C:
  216. sub cx,dx ; CX = # of potential hard disks
  217.  jbe SetupDeblocking40 ; skip tests if none
  218. SetupDeblocking30: ; DX = next drive, CX = drive count
  219. push cx ! push dx
  220. call BusMasterCheck ; check if drive DL bus master disk
  221. pop dx ! pop cx
  222.  jc SetupDeblocking40 ; is so leave deblocking alone
  223. inc dx ; else move to next drive
  224. loop SetupDeblocking30 ; repeat for all drives
  225. les bx,deblockPointer
  226. mov es:word ptr [bx],0FFFFh ; safe to disable deblocking
  227. SetupDeblocking40:
  228. mov es,UpperMemoryBuffer
  229. mov ah,MS_M_FREE
  230. int DOS_INT ; free the upper memory buffer
  231. SetupDeblocking50:
  232. mov ax,(MS_M_STRATEGY*256)+1; set allocation strategy
  233. mov bl,0 ;  to first fit
  234. int DOS_INT
  235. push cs ! pop es ; ES -> local data again
  236. ret
  237. BusMasterCheck: ; determine if we have an old troublesome controller
  238. ;--------------
  239. ; On Entry:
  240. ; DL = drive to check (zero based)
  241. ; On Exit:
  242. ; CY set if troublesome drive
  243. ;
  244. call BusMasterRemovable ; is it a removable device ?
  245.  jnc BMCheck10 ; yes, skip the checks
  246. mov ax,mem_current ; read into low memory
  247. call BusMasterRead ; read one sector from disk
  248.  jc BMCheck10 ; give up if we couldn't read
  249. mov es,mem_current ; ensure at least the 1st word will
  250. mov ax,es:.0 ;  differ if the read doesn't happen
  251. not ax
  252. mov es,UpperMemoryBuffer
  253. mov es:.0,ax
  254. mov ax,UpperMemoryBuffer ; read into upper memory
  255. call BusMasterRead ; read one sector from disk
  256.  jc BMCheck10 ; give up if we couldn't read
  257. xor si,si
  258. xor di,di
  259. mov cx,512/2
  260. mov es,mem_current
  261. mov ds,UpperMemoryBuffer
  262. repe cmpsw ; does the sector match ?
  263. push cs ! pop ds
  264.  je BMCheck10 ; yes, everything is fine
  265. stc ; no, better leave DEBLOCK at A000
  266. BMCheck10:
  267. ret
  268. BusMasterRemovable:
  269. ;------------------
  270. ; On Entry:
  271. ; DL = drive
  272. ; On Exit:
  273. ; CY set if not a removable drive
  274. ; DL preserved
  275. ;
  276. push cs ! pop es
  277. mov bx,offset removableMediaRequest
  278. mov es:RH_UNIT[bx],dl
  279. callf cs:strategy
  280. callf cs:interrupt
  281. test es:RH_STATUS[bx],RHS_BUSY
  282.  jz BusMasterRemovable10
  283. stc ; busy bit set, it's a hard disk
  284. BusMasterRemovable10:
  285. ret
  286. BusMasterRead: ; Read first sector from drive BL
  287. ;-------------
  288. ; On Entry:
  289. ; AX = segment of buffer
  290. ; DL = 02 for C:, 03 for D:, etc.
  291. ; Exit:
  292. ; CY clear if deblocking not required
  293. ; DL preserved
  294. ;
  295. les bx,deblockPointer
  296. mov es:word ptr [bx],0FFFFh ; no deblocking during the test
  297. push cs ! pop es
  298. mov bx,offset readRequest
  299. mov es:RH_UNIT[bx],dl
  300. mov es:RH4_BUFOFF[bx],0
  301. mov es:RH4_BUFSEG[bx],ax
  302. mov es:RH4_COUNT[bx],1
  303. callf cs:strategy
  304. callf cs:interrupt
  305. test es:RH_STATUS[bx],RHS_ERROR
  306.  jz BusMasterRead10
  307. stc ; error bit set, say we had a problem
  308. BusMasterRead10:
  309. les bx,deblockPointer
  310. mov es:word ptr [bx],0A000h ; enable deblocking again
  311. ret
  312. Public setup_stacks
  313. setup_stacks:
  314. mov cx,num_stacks ; we want this many stacks
  315.  jcxz setup_stacks10 ; skip if we don't want any
  316. mov dx,stack_size ; they should be this big
  317. call InitStacks ; initialise the stacks
  318. setup_stacks10:
  319. ret
  320. setup_history:
  321. test history_flg,RLF_ENHANCED
  322.  jz setup_hist10 ; if history not enabled just exit
  323. push es
  324. les bx,drdos_ptr ; Get the internal data area
  325. mov si,es:DRDOS_HIST1CTL[bx]; Get the address of History Control
  326. mov ax,history_size ; Get Offset buffer for History data
  327. call setup_hist20 ; Allocate Buffer 1
  328. mov si,es:DRDOS_HIST2CTL[bx]; Get the address of History Control 2
  329. mov ax,history_size ; Get Offset buffer for History data
  330. call setup_hist20 ; Allocate Buffer 2
  331. mov al,history_flg ; copy history state
  332. mov es:DRDOS_HISTFLG[bx],al ;  into DRDOS data area
  333. pop es
  334. setup_hist10:
  335. ret
  336. setup_hist20:
  337. and ax,not 15 ; round to a complete paragraph
  338. add ax,16 ; always be a para bigger
  339. mov es:word ptr 02[si],ax ; Buffer Tail Address
  340. mov cl,4
  341. push ax ; save buffers size in bytes
  342. shr ax,cl ; convert to para's
  343. mov dl,'H' ; History buffer
  344. call alloc_instseg ; Allocate Buffer
  345. mov es:word ptr 00[si],ax ; Buffer Start Address
  346. pop cx ; recover buffer size in bytes
  347. push es
  348. mov es,ax ; point ES at buffer seg
  349. xor di,di ; ES:DI -> buffer
  350. xor ax,ax ; zero it
  351. rep stosb ; before use
  352. pop es
  353. ret
  354. Public device_init, resident_device_init
  355. ; DEVICE_INIT will initialise the device with the Device Header at
  356. ; ES:BX
  357. ;
  358. ; Entry:
  359. ; ES:DI Address of First Device Header
  360. ; DS:SI Command Line Parameters
  361. ;
  362. ; Exit:
  363. ; AX Top bit set on error, error code in AL
  364. ;
  365. device_init:
  366. ;-----------
  367. push es ! push di
  368. call build_cmd_tail ; point DS:SI to dos style cmd line
  369. pop di ! pop es
  370. call HookInt2F ; hook the Int 2F vector
  371. call resident_device_init
  372. call UnhookInt2F ; get off the Int 2F vector
  373. test ax,ax ; set the flags
  374. ret
  375. resident_device_init:
  376. ;--------------------
  377. mov rel_unit,0 ; set rel unit to zero for block devices
  378. mov dev_count,0
  379. mov bx,offset request_hdr ; ds:bx -> command block
  380. if TRUE
  381. mov ax,mem_max ; AX:0 -> top of available memory
  382. mov ds:RH0_RESIDENT,0 ; pass to the device driver
  383. mov ds:RH0_RESIDENT+2,ax ;  in the RESIDENT field
  384. else
  385. mov ds:RH0_RESIDENT,di ; Force the default RESIDENT field
  386. mov ds:RH0_RESIDENT+2,es ;  to be the error condition
  387. endif
  388. dev_i10:
  389. push si
  390. push es ! push di
  391. call save_vecs ; save interrupt vectors
  392. mov bx,offset request_hdr ; ds:bx -> command block
  393. call dev_init ; initialise the device driver
  394. test es:DH_ATTRIB[di],DA_CHARDEV
  395.  jnz dev_i18 ; skip if a character device
  396. cmp ds:RH0_NUNITS,0 ; no drives installed for disk device?
  397.  je dev_i_err ; failed if no drives found
  398. dev_i18:
  399. mov ax,ds:RH0_RESIDENT ; Calculate the address of
  400. mov cl,4 ; last paragraph used by the
  401. shr ax,cl ; device driver. If this is the
  402. add ax,ds:RH0_RESIDENT+2 ; device driver CS then error
  403. test ds:RH0_RESIDENT,15 ; allow for partial para ?
  404.  jz dev_i19
  405. inc ax ; round it up
  406. dev_i19:
  407. cmp ax,strategy_seg
  408.  jbe dev_i_err
  409. cmp ax,mem_max ; Check for Memory Overflow
  410.  jb dev_i30 ; if it does then we can't install
  411. call restore_vecs ; so replace interrupt vectors
  412. dev_i_err: ; device initialization failed!
  413. les di,cs:func52_ptr ; ES:DI -> internal data
  414. mov ax,es
  415. or ax,di ; DOS data area present yet?
  416. pop di ! pop es ; recover the device header
  417. les di,es:DH_NEXT[di] ; try next device driver
  418.  jz dev_i60 ; if it's resident initialisation
  419. mov di,0FFFFh ;  else stop now
  420. jmps dev_i60
  421. ; The device driver initialised OK so now build/update internal
  422. ; tables based on the device driver type.
  423. ;
  424. ; AX = next available paragraph
  425. ; DS:BX = request header
  426. ; ES:DI = device driver header
  427. ;
  428. dev_i30: ; DEV_INIT OK so update the Top of
  429. mov mem_current,ax ; memory field
  430. test es:DH_ATTRIB[di],DA_CHARDEV
  431.  jz dev_i40
  432. call char_device ; Handle Initialization of all
  433. jmps dev_i50 ; character devices
  434. dev_i40:
  435. call block_device ; Handle Initialization of all
  436. ; jmps dev_i50 ; Block Devices
  437. dev_i50:
  438. pop di ! pop es ; Retrieve the current device header
  439. push es:DH_NEXTSEG[di] ; save next entry on the list
  440. push es:DH_NEXTOFF[di] ; while we deal with existing one
  441. mov es:DH_NEXTOFF[di],0FFFFh; terminate the list
  442. call device_insert ;  and insert into the list
  443. pop di
  444. pop es ; go round till the end
  445. dev_i60:
  446. pop si ; recover cmdline for next device
  447. cmp di,0FFFFh ; was that the last device to
  448.  jne dev_i10 ;  initialise, no do next
  449. mov bx,offset request_hdr ; ds:bx -> command block
  450. mov ax,ds:RH_STATUS ; return Status Register
  451. and ax,80FFh ; is there an error ?
  452.  js dev_i70
  453. xor ax,ax ; no, return success
  454. dev_i70:
  455. ret
  456. public init_static_request
  457. init_static_request:
  458. ; Set up request header for INIT command.
  459. sub ax,ax ; get a convenient zero
  460. mov ds:RH_LEN,RH0_LEN ; Init Request Length
  461. mov ds:RH_UNIT,al ; relative drive always 0
  462. mov ds:RH_CMD,CMD_INIT ; Init Command 
  463. mov ds:RH_STATUS,ax ; Zero Status Register
  464. mov ds:RH0_BPBOFF,si ; Save the command line offset and
  465. mov ds:RH0_BPBSEG,ds ; Segment in the BPB Pointer
  466. mov al,next_drv ; the first drive for this device
  467. sub al,preload_drv ; (not including preloaded devices)
  468. mov ds:RH0_DRIVE,al   ; will be allocated as NEXT_DRV
  469. ;;; mov es:DH_NEXTSEG[di],0 ; force seg to zero (386max 4.05)
  470. ret
  471. dev_init:
  472. ;--------
  473. ; On Entry:
  474. ; ES:DI -> device driver header
  475. ; DS:BX -> req header
  476. ; DS:SI -> command line
  477. ; On Exit:
  478. ; ES:DI/DS:BX <preserved>
  479. ;
  480. mov ax,es:DH_STRATEGY[di] ; Set up the STRATEGY Entry Point
  481. mov strategy_off,ax
  482. mov strategy_seg,es
  483. mov ax,es:DH_INTERRUPT[di] ; Set up the INTERRUPT Entry Point
  484. mov interrupt_off,ax
  485. mov interrupt_seg,es
  486. call init_static_request
  487. push ds ! push es ; Save Segment registers
  488. push bx ! push si ! push di ; and pointers (not all preserve them)
  489. push ds ! pop es ; ES -> Points at the Data Segment
  490. mov ds,strategy_seg ; DS == Device Drive Segment
  491.   mov si,di ; DS:SI -> device driver header
  492.   callf cs:strategy ; Call Device Strategy Routine
  493. callf cs:interrupt ; Call Device Interrupt Routine
  494. pop di ! pop si ! pop bx ; recover the pointers
  495. pop es ! pop ds ; Restore Segment Registers
  496. mov es:DH_NEXTSEG[di],es ; ignore segment - it MUST be same one
  497. ret
  498. ;
  499. ; Character Device Driver Initialised OK so now build/update internal
  500. ; tables based on the device driver type.
  501. ;
  502. ; DS:BX Request Header
  503. ; ES:DI Device Driver Header
  504. ;
  505. char_device:
  506. test es:DH_ATTRIB[di],DA_ISCIN
  507.  jz char_d10 ; is this the standard console device?
  508. mov condev_off,di ; save console device driver address
  509. mov condev_seg,es
  510. ret
  511. char_d10:
  512. test es:DH_ATTRIB[di],DA_ISCLK
  513.  jz char_d20 ; is this the standard clock device?
  514. mov clkdev_off,di ; save clock device driver address
  515. mov clkdev_seg,es
  516. char_d20:
  517. ret
  518. ; Block  device  driver  initialised  OK.  Save  the values
  519. ; returned from the INIT call so we can later build all the
  520. ; required internal tables.
  521. ;
  522. ; entry: DS:BX -> request header
  523. ; ES:DI -> device driver header
  524. ;
  525. public block_device
  526. block_device:
  527. mov al,BLKDEV_LENGTH ; bytes per block device table entry
  528. mul byte ptr num_blkdev ;   * # of block devices installed
  529. add ax,offset blkdev_table ; AX -> block dev init result table
  530. xchg ax,si ; pointer to next block device struct
  531. mov devoff,di
  532. mov devseg,es ; point to device driver header
  533. mov 0[si],di
  534. mov 2[si],es ; save device driver address for later
  535. mov ax,ds:RH0_BPBOFF
  536. mov 4[si],ax ; save BPB table address (offset)
  537. mov ax,ds:RH0_BPBSEG
  538. mov 6[si],ax ; save BPB table address (segment)
  539. mov cl,ds:RH0_NUNITS
  540. mov 8[si],cl ; get # of units supported by driver
  541. mov es:DH_NAME[di],cl ; set # of units in device name
  542. inc num_blkdev ; we've installed another block device
  543. add next_drv,cl ; update drive base for next driver
  544. add dev_count,cl ; number of new units
  545. mov ax,boot_device ; now for Andy's bit about boot device
  546. or ax,boot_device+2 ; have we already got a boot device?
  547.  jnz not_boot_dev
  548. mov ch,init_drv
  549. sub ch,next_drv ; is sub unit in this driver
  550.  ja not_boot_dev ; no, skip it
  551. add ch,cl ; work out which sub unit it is
  552. mov boot_drv,ch ; and remember it
  553. mov boot_device,di
  554. mov boot_device+2,es
  555. not_boot_dev:
  556. push si ! push es ! push di
  557. mov cl,8[si]
  558. mov ch,0 ; CX = # of drives found in driver
  559. les si,4[si] ; ES:SI -> BPB array in BIOS
  560. mov bpbseg,es ; remember the segment
  561. blkdev_loop:
  562. lods es:ax ; AX = offset of next BPB
  563. push es ! push si ! push cx
  564. mov bpboff,ax ; remember the offset
  565. xchg ax,di ; ES:DI -> next BPB
  566. mov ax,es:[di] ; AX = sector size for BPB
  567. cmp ax,max_secsize ; new maximum for sector size
  568.  jbe blkdev_next1 ; skip if sector size not grown
  569. mov max_secsize,ax ; else set new maximum
  570. blkdev_next1:
  571. mov dl,es:2[di] ; get sectors per cluster
  572. mov dh,0 ; make this a word
  573. mul dx ; AX = bytes per cluster
  574. cmp ax,max_clsize ; more than previous maximum
  575.  jbe blkdev_next2 ; skip if no new high score
  576. mov max_clsize,ax ; else record max. sector size
  577. blkdev_next2:
  578. les bx,func52_ptr ; ES:BX -> internal data
  579. mov ax,es
  580. or ax,bx ; DOS data area present yet?
  581.  jz blkdev_next3 ; skip if BDOS not present yet
  582. call setup_drives ; update drives in BDOS data
  583. mov es,mem_current ; MUST create a DDSC just after driver
  584. add mem_current,(DDSC_LEN+15)/16
  585. xor bp,bp ; ES:BP points to the DDSC
  586. call setup_ddsc ; add new DDSC_ to chain
  587. call setup_ldt ; initialise LDT for that drive
  588. blkdev_next3:
  589. pop cx ! pop si ! pop es
  590. loop blkdev_loop ; repeat for all BPBs in driver
  591. pop di ! pop es ! pop si
  592. ret
  593. resident_ddscs:
  594. ;--------------
  595. ; Allocate DDSC's for the resident device drivers - we can only do this
  596. ; after the DOS data area is established.
  597. ;
  598. sub bx,bx ; start with 1st block device
  599. mov cx,num_blkdev ; get # of block devices
  600.  jcxz res_ddsc40 ; skip if no block devices
  601. res_ddsc10:
  602. push bx ! push cx
  603. mov ax,BLKDEV_LENGTH
  604. mul bx
  605. add ax,offset blkdev_table
  606. xchg ax,si ; SI -> block device table
  607. sub cx,cx
  608. mov cl,8[si] ; CX = # of units on device
  609. sub bx,bx ; BX = relative unit # * 2
  610. mov rel_unit,bx ; start with relative unit # 0
  611. res_ddsc20: ; CX = remaining units
  612. push bx ! push cx ! push si ; BX = offset, SI -> drive structure
  613. lodsw
  614. mov devoff,ax ; save device header offset
  615. lodsw
  616. mov devseg,ax ; save device header segment 
  617. les si,[si] ; get offset of BPB array
  618. mov ax,es:[bx+si] ; get offset for our BPB
  619. mov bpboff,ax
  620. mov bpbseg,es ; save pointer to BPB
  621. les bp,res_ddsc_ptr ; point to position for DDSC_
  622. add ds:word ptr res_ddsc_ptr,DDSC_LEN
  623. call setup_ddsc ; setup one unit
  624. pop si ! pop cx ! pop bx
  625. inc bx ! inc bx ; increment (unit index*2)
  626. loop res_ddsc20 ; repeat for next unit, same driver
  627. pop cx ! pop bx
  628. inc bx
  629. loop res_ddsc10 ; repeat for next driver
  630. res_ddsc40: ; all block devices done
  631. ret
  632. setup_ddsc:
  633. ;----------
  634. ; On Entry:
  635. ; ES:BP -> DDSC_ to initialise and link into chain
  636. ; bpbptr -> BPB to initialise from
  637. ; devseg:devoff -> device driver header
  638. ; abs_unit, rel_unit reflect drive
  639. ; On Exit:
  640. ; None
  641. ;
  642. push ds
  643. lds si,bpbptr ; DS:SI points to the BPB
  644. mov ah,53h ; build DDSC from BPB call
  645. int DOS_INT ;  initialises the structure
  646. pop ds
  647. mov ax,devoff
  648. mov es:DDSC_DEVOFF[bp],ax
  649. mov ax,devseg
  650. mov es:DDSC_DEVSEG[bp],ax
  651. mov ax,abs_unit
  652. inc abs_unit
  653. mov es:DDSC_UNIT[bp],al ; set absolute unit (global)
  654. mov ax,rel_unit
  655. inc rel_unit
  656. mov es:DDSC_RUNIT[bp],al ; set relative unit (driver relative)
  657. mov ax,-1 ; set link to FFFFh:FFFFh
  658. mov es:word ptr DDSC_LINK[bp],ax
  659. mov es:word ptr DDSC_LINK+2[bp],ax
  660. mov es:DDSC_FIRST[bp],al ; set drive never accessed flag
  661. mov ax,es ; now link into device chain
  662. ;
  663. les bx,func52_ptr ; ES:BX -> secret 52h data
  664. lea bx,F52_DDSCPTR-(offset .DDSC_LINK)[bx]
  665. setup_ddsc10:
  666. cmp es:word ptr DDSC_LINK[bx],0FFFFh
  667.  je setup_ddsc20 ; is there another one ?
  668. les bx,es:DDSC_LINK[bx] ; onto next DDSC_
  669. jmps setup_ddsc10
  670. setup_ddsc20: ; link new DDSC to end of chain
  671. mov es:word ptr DDSC_LINK[bx],bp
  672. mov es:word ptr DDSC_LINK+2[bx],ax
  673. ret ; now RAF will be happy
  674. Public setup_ldt
  675. setup_ldt:
  676. push ds
  677. push es
  678. les bx,func52_ptr ; get internal data in ES:BX
  679. mov al,LDT_LEN ; we need this many bytes per drive
  680. mul es:F52_LASTDRV[bx] ; *lastdrive
  681. xchg ax,cx ; CX = size to initialise
  682. mov al,es:F52_LASTDRV[bx] ; lastdrive
  683. push ax ; save for later
  684. les di,es:F52_PATHPTR[bx] ; now initialise the CSD's
  685. xor al,al ; to zero
  686. rep stosb ; zero them
  687. pop ax ; recover lastdrive
  688. xor bx,bx ; start with zero offset
  689. xor cx,cx ; start with drive A
  690. xchg al,cl ; AH = physical limit, CX logical limit
  691. ldt_init:
  692. push ax
  693. push cx
  694. push ax
  695. lea di,LDT_NAME[bx]
  696. add al,'A' ; make drive ASCII
  697. stosb
  698. mov ax,':' ; point at the root
  699. stosw
  700. mov ax,0FFFFh
  701. lea di,LDT_BLK[bx] ; set to FFFF to force LDT_ rebuild
  702. stosw ! stosw ! stosw ;  next two words are FFFF too
  703. ; lea di,LDT_ROOTLEN[bx]
  704. mov ax,2
  705. stosw ; set the length field
  706. pop ax
  707. lds si,cs:func52_ptr ; get internal data in DS:SI
  708. sub si,offset .DDSC_LINK
  709. ldt_init20:
  710. lds si,ds:DDSC_LINK[si] ; point to next PDT
  711. cmp si,-1 ; skip if there isn't one
  712.  je ldt_init40
  713. cmp al,ds:DDSC_UNIT[si] ; is this the DDSC for the drive
  714.  jne ldt_init20 ; if not try another
  715. mov es:word ptr LDT_PDT[bx],si
  716. mov es:word ptr LDT_PDT+2[bx],ds
  717. cmp ds:DDSC_NFATS[si],0 ; no FATS, then it's a reserved drive
  718.  je ldt_init40
  719. push es
  720. push bx
  721. push ax ; save drive we are processing
  722. mov ax,4A11h
  723. xor bx,bx
  724. int 2Fh ; do an STACKER installation check
  725. pop dx ; DL = drive we are processing
  726. test ax,ax
  727. mov ax,LFLG_PHYSICAL ; assume a physical drive
  728.  jnz ldt_init30 ; no STACKER, it's physical
  729. sub cl,'A' ; zero base STACKER drive returned
  730. cmp cl,dl ; should we check this drive ?
  731.  ja ldt_init30 ; below 1st drive, it's physical
  732. push ax
  733. push dx
  734. mov ax,4A11h
  735. mov bx,1 ; ask STACKER for host drive
  736. int 2Fh
  737. pop dx
  738. pop ax
  739. cmp bl,dl ; is this the host drive ?
  740.  jne ldt_init30
  741. xor ax,ax ; drive is invalid
  742. ldt_init30:
  743. pop bx
  744. pop es
  745. mov es:LDT_FLAGS[bx],ax
  746. ldt_init40:
  747. add bx,LDT_LEN ; move onto next LDT_
  748. pop cx
  749. pop ax
  750. inc ax ; and next drive
  751. loop ldt_init ; done to lastdrive ? no, do another
  752. pop es
  753. pop ds
  754. ret
  755. Public device_insert
  756. device_insert:
  757. ;-------------
  758. ; insert device drivers at ES:DI into global chain
  759. ; if we are initialising the resident device drivers then we don't have
  760. ;  a global chain, so insert them on a local chain and try again later
  761. push ds
  762. lds bx,func52_ptr ; Internal Data Pointer
  763. lea si,F52_DEVROOT[bx] ; DS:SI -> NUL device
  764. mov ax,ds ; if BDOS data area isn't present
  765. or ax,bx ;  we are initialising resident
  766.  jnz dev_ins_next ;  devices
  767. push cs ! pop ds
  768. mov si,offset resdev_chain ; it's resident devices
  769. dev_ins_next:
  770. cmp di,-1 ; end of device chain reached?
  771.  je devins_done ; yes, all devices inserted
  772. mov ax,0[si]
  773. mov dx,2[si] ; DX:AX = original chain 
  774. mov 0[si],di
  775. mov 2[si],es ; link our device at head of chain
  776. xchg ax,es:0[di] ; link old global chain to device
  777. xchg dx,es:2[di] ;  & get next device in local chain
  778. mov di,ax ; point to next device in chain
  779. mov es,dx
  780. jmps dev_ins_next ; repeat until chain empty
  781. devins_done:
  782. pop ds
  783. ret
  784. public config_finish
  785. config_finish: ; finish off configuration
  786. ;-------------
  787. cmp resdev_off,-1 ; are resident devices already
  788.  je cfg_fin10 ;  installed
  789. les di,resdev_chain ; insert all the resident device
  790. call device_insert ;  drivers into DOS chain
  791. call resident_ddscs ; build DDSC's for resident devices
  792. mov resdev_off,-1 ; only do this once...
  793. cfg_fin10:
  794. les bx,func52_ptr ; ES:BX -> base of DOS variables
  795. call setup_drives ; Update No of Physical Drives in case
  796. ; this is the first pass
  797. call setup_ldt ; setup the ldt's
  798. les bx,func52_ptr
  799. lea di,F52_CLKDEV[bx] ; ES:DI -> clock ptr, console ptr
  800. mov si,offset clkdev_off ; DS:SI -> local pointer values
  801. movsw ; set offset of clock device driver
  802. movsw ; set segment of clock device driver
  803. movsw ; set offset of console device driver
  804. movsw ; set segment of console device driver
  805. call setup_doshndl ; Allocate DOS compatible Handles
  806. ; NB must immediately follow devices !
  807. call setup_buffers ; allocate the requested #
  808. ret
  809. setup_buffers:
  810. ;-------------
  811. ; entry: num_buf = minimum # of buffers required
  812. ;           0 - use temporary high buffers
  813. ;
  814. les bx,func52_ptr ; ES:BX -> internal data structure
  815. mov ax,num_buf ; fill in info in DOS for diagnostic
  816. mov es:F52_NUM_BUF[bx],ax ;  programs
  817. mov al,num_read_ahead_buf
  818. mov es:F52_READ_AHEAD[bx],ax
  819. mov ax,es:F52_SECSIZE[bx] ; get DOS data sector size
  820. cmp ax,max_secsize ; has it been poked to a bigger value ?
  821.  ja setup_b10 ; if so we must discard anyway
  822. mov ax,max_secsize ; get max. sector size found
  823. setup_b10:
  824. mov es:F52_SECSIZE[bx],ax ; update max. sector size in PCMODE
  825. mov max_secsize,ax ; update max. sector size locally
  826. add ax,offset .BCB_DATA ; add in the header size
  827. mov es,init_dseg ; ES:DI -> init buffers
  828. mov di,offset INIT_BUFFERS
  829. mov cx,NUM_BUFFS ; CX buffs, DX in size, at ES:DI
  830. mov dx,SIZEOF_BUFFS ; size of init buffers
  831. cmp num_buf,0 ; (zero at init time)
  832.  je setup_b70 ; go ahead and initialise
  833. push ax ; save size of buffer
  834. mul num_buf ; AX = total bytes required
  835. test dx,dx ; > 64 K ?
  836.  jz setup_b30
  837. mov ax,0FFFFh ; do the maximum
  838. setup_b30:
  839. pop bx ; BX = size of a buffer
  840. mov cx,ax ; CX bytes required
  841. xor dx,dx
  842. div bx ; AX = # buffers
  843. push ax ; save # buffers
  844. push bx ; save size of a buffer
  845. push cx ; save bytes wanted
  846. test buffersIn,BUFFERS_IN_HMA
  847. stc ; do we want buffers at FFFF ?
  848.  jz setup_b40
  849. call SetupHMA ; make sure HMA chain is established
  850. pop cx ! push cx ; CX = bytes wanted
  851. mov dx,0FFFFh ; anywhere is OK
  852. call AllocHMA ; ES:DI -> allocated data
  853. setup_b40:
  854. pop ax ; AX = bytes wanted
  855. pop dx ; DX = size of a buffer
  856. pop cx ; CX = number of buffer
  857.  jnc setup_b70 ; if CY clear ES:DI -> our space
  858. shr ax,1 ! shr ax,1
  859. shr ax,1 ! shr ax,1
  860. inc ax ; convert from bytes to para's
  861. push dx
  862. mov dl,'B' ; allocate as a Buffer
  863. test buffersIn,BUFFERS_IN_UMB
  864.  jz setup_b50 ; allocation from UMB's OK ?
  865. call alloc_hiseg ; yes, try and allocate memory there
  866.  jnc setup_b60
  867. setup_b50:
  868. call alloc_seg ; allocate memory in bottom 640 K
  869. setup_b60:
  870. pop dx
  871. mov es,ax ; ES = segment
  872. xor di,di ; ES:DI -> start of buffer
  873. setup_b70:
  874. ; Buffer space for CX buffers, of size DX, allocated at ES:DI
  875. mov si,di ; remember where 1st buffer is
  876. setup_b80:
  877. push cx
  878. mov bx,di ; BX = current buffer
  879. mov cx,dx
  880. xor ax,ax
  881. rep stosb ; zero the buffer, ES:DI -> next buffer
  882. mov es:BCB_DRV[bx],0FFh ; invalidate buffer
  883. mov es:BCB_NEXT[bx],di ; point to where "next" will be
  884. mov ax,bx
  885. sub ax,dx ; work out what our previous was
  886. mov es:BCB_PREV[bx],ax ;  and point to it
  887. pop cx
  888. loop setup_b80 ; do them all
  889. mov es:BCB_NEXT[bx],si ; the last's "next" is our first buffer
  890. mov es:BCB_PREV[si],bx ; the first's "previous" is our last
  891. mov ax,es ; AX:SI -> 1st buffer
  892. les bx,func52_ptr ; ES:BX -> internal data structure
  893. mov es:F52_BCBOFF[bx],si
  894. mov es:F52_BCBSEG[bx],ax ; fixup buffer pointers
  895. mov es:word ptr F52_BUF_INFO[bx],si
  896. mov es:word ptr F52_BUF_INFO+2[bx],ax
  897. inc ax ; seg FFFF ?
  898.  jnz setup_b90 ; skip if not
  899. mov es:F52_HMAFLAG[bx],1 ; buffers are in HMA
  900. mov ax,es:F52_SECSIZE[bx]
  901. add ax,15
  902. mov cl,4
  903. shr ax,cl ; convert to para size
  904. mov dl,'B' ; allocate as a Buffer
  905. call alloc_seg ; allocate a deblocking buffer
  906. mov es:F52_DEBLOCK[bx],ax
  907. les bx,drdos_ptr ; ES:BX -> data area
  908. mov es:DRDOS_DEBLOCK[bx],ax ;  of deblocking buffer
  909. setup_b90:
  910. ret
  911. setup_doshndl:
  912. push es
  913. les bx,func52_ptr ; Internal Data Pointer
  914. lea bx,F52_FILEPTR[bx] ; Start of Handle List
  915. mov cx,num_files ; Number of DOS Handles
  916. add cx,num_fcbs ; + some for FCB's
  917. cmp cx,255
  918.  jbe setup_dh10
  919. mov cx,255 ; maximum IFN is 255
  920. setup_dh10:
  921. cmp es:DCNTRL_DSOFF[bx],0FFFFh ; Last entry ?
  922.  je setup_dh20 ; no, loop round again
  923. les bx,es:DCNTRL_DSADD[bx] ; Get the Next Entry
  924. sub cx,es:DCNTRL_COUNT[bx] ; Update the count
  925.  jc setup_dh30 ; going negative isn't allowed
  926. jmps setup_dh10
  927. setup_dh20:
  928. jcxz setup_dh30 ; any left to allocate ?
  929. mov ax,DHNDL_LEN ; How many bytes do we need
  930. mul cx ; for the structure
  931. mov dx,ax ; including the control
  932. add ax,DCNTRL_LEN+15 ; Ensure the new structure is
  933. shr ax,1 ! shr ax,1 ; a paragraph value
  934. shr ax,1 ! shr ax,1 ; allocate some memory
  935. mov dl,'F' ; allocate for Files
  936.     call    alloc_seg           
  937. mov es:DCNTRL_DSOFF[bx],0 ; link the new seg
  938. mov es:DCNTRL_DSSEG[bx],ax ; to the end of the list
  939. ; We can now initialise the new structure
  940. les bx,es:DCNTRL_DSADD[bx] ; Get the New Entry
  941. mov es:DCNTRL_DSOFF[bx],0FFFFh ; terminate the list
  942. mov es:DCNTRL_DSSEG[bx],0FFFFh ; with -1,-1
  943.   mov es:DCNTRL_COUNT[bx],cx ; Number of elements
  944. ; Now zero the tables
  945. mov ax,DHNDL_LEN ; How many bytes do we have
  946.   mul cx ; with this number of elements
  947. mov cx,ax ; in the structure
  948. lea di,DCNTRL_LEN[bx] ; Zero the contents of the
  949. sub al,al ; structure
  950. rep stosb
  951.  
  952. setup_dh30:
  953. pop es
  954. ret
  955. setup_drives:
  956. mov al,next_drv ; AL = # of drives supported
  957. push es ! push bx
  958. les bx,func52_ptr ; ES:BX -> base of DOS variables
  959. mov es:F52_PHYDRV[bx],al ; set # of Physical drives installed
  960. mov es:F52_LASTDRV[bx],al ; set # of Logical drives installed
  961. pop bx ! pop es
  962. ret
  963. setup_fopen: ; allocate file hashing information
  964. ;-----------
  965. les bx,drdos_ptr
  966. mov ax,num_fopen ; get # of hashed directory entries
  967. cmp ax,-1 ; has it been set yet ?
  968.  jne setup_fopen10 ; yes, then leave it alone
  969. mov ax,DEF_NUM_FOPEN
  970. cmp es:DRDOS_HIMEM_ROOT[bx],0; do we have a high memory chain ?
  971.  jne setup_fopen10 ; high memory means no TPA hit
  972. xor ax,ax ; keep things small otherwise
  973. setup_fopen10:
  974. xor dx,dx ; AX/DX = 32 bit # of entries
  975. mov si,max_clsize ; max. cluster size
  976. mov cl,5 ; 32 byte per directory entry
  977. shr si,cl ; SI = directory entries per cluster
  978. add ax,si ; round up count to multiple of cluster
  979. dec ax
  980. div si ; AX = # of hashed blocks
  981. mov cx,ax
  982.  jcxz setup_fopen90 ; skip if hashing disabled
  983. mov es:DRDOS_HASHMAX[bx],si ; maximum # dir entries allowed
  984. shl si,1 ; SI = bytes required for data
  985. lea si,HCB_DATA[si] ;  + control information
  986. mul si ; AX bytes of data required
  987. test dx,dx
  988.  jnz setup_fopen90 ; overflow (shouldn't happen)
  989. ; Allocate CX HCB_'s of size SI bytes, AX bytes in total
  990. mov bx,es:DRDOS_HIMEM_ROOT[bx]; do we have a high memory chain ?
  991. test bx,bx ;  zero indicates we don't
  992.  jz setup_fopen30
  993. mov dx,0FFFFh ; use the magic FFFF segment
  994. mov es,dx
  995. cmp ax,es:2[bx] ; is there enough room ?
  996.  ja setup_fopen30 ; no, forget try conventinal memory
  997. sub es:2[bx],ax ; else allocate the memory
  998. mov di,es:2[bx] ; get base+length
  999. add di,bx ;  = our allocation
  1000. mov ax,es:2[bx] ; if the section left is under
  1001. cmp ax,2*WORD ;  2 words discard it
  1002.  jae setup_fopen20 ;  as we may overwrite size/link
  1003. mov ax,es:[bx] ; get next entry
  1004. les bx,drdos_ptr ;  and make it the new himem root
  1005. mov es:DRDOS_HIMEM_ROOT[bx],ax
  1006. setup_fopen20:
  1007. xchg ax,dx ; AX = FFFF
  1008. jmps setup_fopen40 ; AX:DI -> data block allocated
  1009. setup_fopen30:
  1010. shr ax,1 ; convert size to para's
  1011. shr ax,1
  1012. shr ax,1
  1013. shr ax,1
  1014. inc ax ; allow for rounding
  1015.     mov dl,'E'          
  1016. call alloc_hiseg ; allocate it para aligned
  1017. dec ax ; zero offset terminates the chain
  1018. mov di,10h ;  so start with a non-zero offset
  1019. ; jmps setup_fopen40 ; AX:DI -> data block allocated
  1020. setup_fopen40:
  1021. ; setup CX HCB_'s of size SI at AX:DI
  1022. les bx,drdos_ptr
  1023. mov es:DRDOS_HASHOFF[bx],di
  1024. mov es:DRDOS_HASHSEG[bx],ax
  1025. mov es,ax
  1026. setup_fopen50:
  1027. mov es:HCB_DRV[di],-1 ; discard the HCB initially
  1028. mov bx,di ; remember where it is
  1029. add di,si ; onto next HCB_
  1030. mov es:HCB_LINK[bx],di ; link it to previous HCB_
  1031. loop setup_fopen50 ; allocate all hash control blocks
  1032. mov es:HCB_LINK[bx],0 ; zero terminate the list
  1033. setup_fopen90: ; all HCBs done, return
  1034. push cs
  1035. pop es ; back to 8080 model
  1036. ret
  1037. Public whitespace
  1038. whitespace:
  1039. lodsb ; Skip any White Space in the 
  1040. cmp al,' ' ! jz whitespace ; CR/LF terminated string
  1041. cmp al,TAB ! jz whitespace
  1042. dec si
  1043. ret
  1044. Public build_cmd_tail
  1045. build_cmd_tail:
  1046. push ds ! pop es
  1047. mov cx,length cfg_buffer - 3 ; (leave room for 3 extra chars)
  1048. mov di,offset cfg_buffer
  1049. build_cl1:
  1050. lodsb ; Copy the device name
  1051. cmp al,' ' ; until a Control char (end of line)
  1052.  jbe build_cl2 ; or a Space (end of name)
  1053. cmp al,'/' ; Also stop scanning when a switch 
  1054.  je build_cl2 ; character is detected
  1055. stosb
  1056. loop build_cl1
  1057. mov al,CR ; indicate we can go no more....
  1058. build_cl2:
  1059. cmp al,CR ; it it really the end ?
  1060. mov al,' ' ; now insert a space character
  1061. stosb
  1062.  je build_cl_exit ; CR meant it's time to go
  1063. dec si ; rewind the source one character
  1064. build_cl3:
  1065. lodsb ; Copy the tail
  1066. cmp al,CR ; until we find a CR
  1067.  je build_cl4 ; at the end of the line
  1068. stosb
  1069. loop build_cl3
  1070. mov al,CR ; no more room, so terminate
  1071. build_cl4:
  1072. stosb
  1073. build_cl_exit:
  1074. mov al,LF ; now insert the terminating linefeed
  1075. stosb ; at the end of the buffer
  1076. mov si,offset cfg_buffer
  1077. ret
  1078. save_vecs:
  1079. ; save interrupt vectors so we can restore if device init fails
  1080. push ds ! push es
  1081. push si ! push di ! push cx
  1082. mov cx,(length vec_save_buf)*2 ; CX = words to save
  1083. xor si,si
  1084. mov ds,si ; DS:SI -> vectors to save
  1085. push cs ! pop es
  1086. mov di,offset vec_save_buf ; ES:DI -> save area
  1087. rep movsw ; save them
  1088. pop cx ! pop di ! pop si
  1089. pop es ! pop ds
  1090. ret
  1091. restore_vecs:
  1092. ; replace interrupt vectors after a dd_init fails
  1093. push ds ! push es
  1094. push si ! push di ! push cx
  1095. mov cx,length vec_save_buf ; CX = vectors to restore
  1096. push cs ! pop ds
  1097. mov si,offset vec_save_buf ; DS:SI -> save area
  1098. xor di,di
  1099. mov es,di ; ES:DI -> vectors to restore
  1100. rest_vec1:
  1101. mov ax,es:2[di] ; get updated vector
  1102. cmp ax,mem_current ; below attempted driver?
  1103.  jb rest_vec2 ; yes, don't zap it
  1104. cmp ax,mem_max ; above attempted driver?
  1105.  jae rest_vec2 ; yes, don't zap it
  1106. movsw ! movsw ; else restore vector
  1107. jmps rest_vec3 ;   overwritten by driver
  1108. rest_vec2:
  1109. add si,dword ; skip vector in source
  1110. add di,dword ;   and in destination
  1111. rest_vec3:
  1112. loop rest_vec1 ; next vector
  1113. pop cx ! pop di ! pop si
  1114. pop es ! pop ds
  1115. ret
  1116. INITDATA DSEG 'INITDATA'
  1117. extrn shell:byte ; Default Command Processor
  1118. extrn shell_cline:byte ; Default Command Line
  1119. extrn num_files:word ; default # of file handles
  1120. extrn num_fcbs:word ; default # of fcb file handles
  1121. extrn num_fopen:word ; default value for fast open
  1122. extrn country_code:word ; Requested Country Code (Default US)
  1123. extrn num_stacks:word ; # hardware stacks wanted
  1124. extrn stack_size:word ; size of a hardware stack
  1125. extrn mem_current:word ; Current Load Address
  1126. extrn mem_max:word ; Top of Available Memory
  1127. extrn init_dseg:word ; Current init Data Segment
  1128. extrn dos_dseg:word
  1129. extrn bios_seg:word
  1130. extrn func52_ptr:dword
  1131. extrn drdos_ptr:dword
  1132. extrn res_ddsc_ptr:dword
  1133. include initmsgs.def ; Include TFT Header File
  1134. extrn preload_drv:byte
  1135. extrn init_drv:byte ; the initial boot drive
  1136. Public dev_load_seg, dev_reloc_seg, dev_epb, dev_name, dev_count
  1137. Public rel_unit, dev_epb
  1138. Public strategy_off, strategy_seg, interrupt_off, interrupt_seg, request_hdr
  1139. Public next_drv, strategy_seg, strategy, interrupt
  1140. Public strategy_seg, condev_off, condev_seg, clkdev_off, clkdev_seg
  1141. Public num_blkdev, blkdev_table, next_drv, max_secsize
  1142. Public max_clsize, init_buf, num_read_ahead_buf
  1143. Public buffersIn, history_flg, history_size
  1144. Public dbcs_tbl, ctry_info, boot_device, boot_drv, resdev_chain
  1145. history_flg db 0 ; Disable history buffers to save RAM
  1146. history_size dw 256 ; When enabled 2*history size are used for bufs
  1147. cfg_buffer rb CFG_BUF_LEN ; extra termination for buggy Windows
  1148. db CR,LF,0 ; device driver - give it CR/LF to hit
  1149. init_buf db MIN_NUM_BUFFS ; default # of buffers
  1150. num_read_ahead_buf db DEF_READ_AHEAD ; default # of read-ahead
  1151. buffersIn db 0 ; default is low
  1152. dev_count db 0 ; count of new drives (used by preload)
  1153. next_drv db 0 ; Next Drive to Allocate
  1154. num_blkdev dw 0 ; # of block devices installed
  1155. boot_device dw 0,0 ; ptr to boot device
  1156. boot_drv db 0 ; and the sub unit number
  1157. max_secsize dw 0 ; max. sector size encountered
  1158. max_clsize dw 0 ; max. cluster size encountered
  1159. ; Do not change the order of the next four words:
  1160. clkdev_off rw 1 ; clock device driver
  1161. clkdev_seg rw 1
  1162. condev_off rw 1 ; console device driver
  1163. condev_seg rw 1
  1164. bpbptr rd 0 ; temporary BPB pointer
  1165. bpboff rw 1
  1166. bpbseg rw 1
  1167. devptr rd 0 ; temporary device header pointer
  1168. devoff rw 1
  1169. devseg rw 1
  1170. resdev_chain rd 0 ; head of chain for resident device
  1171. resdev_off dw -1 ; drivers
  1172. resdev_seg dw -1
  1173. abs_unit dw 0 ; absolute unit #
  1174. rel_unit dw 0 ; relative unit #
  1175. blkdev_table rb BLKDEV_LENGTH*26 ; save block device driver addr. here
  1176. ;
  1177. ; Variable for the FUNC_DEVICE and DEV_INIT sub routines
  1178. ;
  1179. strategy rd 0 ; Device Strategy Entry Point
  1180. strategy_off rw 1 ; Offset 
  1181. strategy_seg rw 1 ; Segment Address
  1182. interrupt rd 0 ; Device Entry Point
  1183. interrupt_off rw 1 ; Offset
  1184. interrupt_seg rw 1 ; Segment Address
  1185. dev_root rd 0 ; Pointer to Root of Device List
  1186. dev_offset rw 1 ; Offset of First Device
  1187. dev_segment rw 1 ; Segment of First Device
  1188. request_hdr rb RH_SIZE ; DOS Request Header
  1189. dev_name rb MAX_FILELEN
  1190. dev_epb rw 0
  1191. dev_load_seg rw 1 ; Load Segment for Device Driver
  1192. dev_reloc_seg rw 1 ; Relocation Factor to be Applied
  1193. ;
  1194. ; A number of routines share this common buffer as they are never required
  1195. ; at the same time. The current clients are -
  1196. ;
  1197. ; BDOSLDR.A86: a sector buffer for boot load of IBMDOS
  1198. ; CONFIG.A86: vector save buffer (during devicehigh)
  1199. ; NLSFUNC.A86: scratch area for country info
  1200. Public sector_buffer
  1201. sector_buffer rb 0
  1202. ; rb 512 ; we need to read a single sector
  1203. Public nls_temp_area
  1204. nls_temp_area rb 0 ; NLS buffer can be shared with
  1205. ; rb 258 ;  vec_save_buf as they are never
  1206. ;  used together
  1207. vec_save_buf rd 256 ; reserve space to save int vectors
  1208. dbcs_buf rb 1 ; BDOS puts a 7 here
  1209. dbcs_tbl rd 1 ; pointer to DBCS table in BDOS
  1210. ctry_info rb CI_LENGTH ; country information 
  1211. num_buf dw 0 ; # of buffers allocated
  1212. ; The following are used for detecting old bus master controllers:
  1213. removableMediaRequest db 13 ; length of request
  1214. db 0 ; unit
  1215. db 15 ; removable media check command
  1216. dw 0 ; status
  1217. rb 8 ; reserved bytes
  1218. readRequest db 30 ; length of request
  1219. db 0 ; unit
  1220. db 4 ; read command
  1221. dw 0 ; status
  1222. rb 8 ; reserved bytes
  1223. db 0F8h ; media ID
  1224. dw 0,0 ; buffer address
  1225. dw 1 ; read one sector
  1226. dw 0FFFFh ; use big sector read
  1227. dw 0,0 ; Volume ID
  1228. dw 1,0 ; starting sector zero
  1229. UpperMemoryBuffer dw 0
  1230. numUnits dw 0
  1231. deblockPointer rd 0
  1232. deblockOffset dw 0
  1233. deblockSeg dw 0
  1234. Public DeblockSetByUser
  1235. DeblockSetByUser db FALSE
  1236. end