Contributor: JOHN HOWARD (* > Is there someone who can tell me how I can CREATED my own .SYS files ? Try "Advanced MSDOS Programming", by Ray Duncan (Microsoft Press) for details about device driver writing. A device driver is a binary image whose origin is at zero. The first two words in the header are always $FFFF. Device attribute varies per device! { start of device driver header } ORG 0 dd -1 { Next device : longint = -1; } dw $8800 { Device attribute word, "generic" driver for DOS 3 or later } dw strategy { Strategy routine offset (request header pointer entry) } dw intrupt { Interrupt routine offset (request entry point) } db 'EXAMPLE ' { Eight character device name } { Global variables } request_ptr LABEL dword request_off DW ? request_seg DW ? { end of device driver header } { "dos_func_table" is used by "intrupt" to call the routine that handles the requested function. Example table with four command entries: } max_cmd EQU 4 dos_func_table: DW dosfunc0, nopcmd, nopcmd, badcmd { Typical table has 24 entries including nopcmd's and badcmd's. dosfunc0 initializes device driver interrupts and buffers, then gives ending address of the device driver (header + body) to DOS. MediaCheck ; not used for character devices -- return done BuildBPB ; not used for character devices -- return done IOCTLRead ; disabled in table word Read ; implemented for character device NdRead ; implemented " " " InpStatus ; implemented " " " InpFlush ; implemented " " " Write ; implemented " " " WriteVerify ; implemented " " " OutStatus ; implemented " " " OutFlush ; not used in this example -- always success IOCTLWrite ; disabled in table word DevOpen ; disabled in table word DevClose ; disabled in table word RemMedia ; disabled in table word OutBusy ; disabled in table word GenIOCTL ; disabled in table word GetLogDev ; not used for character devices -- return done SetLogDev ; not used for character devices -- return done } { "Strategy" routine called by DOS with a request. This implementation just saves the request. } strategy proc far MOV CS:request_off, BX MOV CS:request_seq, ES RET strategy endp { "Intrupt" routine handles request queued by "strategy". Calls one of the subroutines in the function table depending upon the request number. Each subroutine returns with exit status in AX. Partial example: } intrupt proc far STI PUSHA { Preserve all registers except stack } PUSH DS PUSH ES { Read requested function information into registers } LDS BX, CS:request_ptr XOR AH, AH MOV AL, DS:[BX+02h] { AL = function code } CMP AL, max_cmd { Check range for expected table entry } JA unknown_command XCHG BX, AX SHL BX, 1 { Calculate index to function table of words } MOV AX, CS MOV DS, AX CALL word ptr dos_func_table[BX] done: LDS BX, CS:request_ptr { Report status } OR AX, 100h { Always set done bit before exit } MOV [BX+03], AX POP ES POP DS POPA { Restore all registers } RET { Return to DOS } unknown_command: CALL badcmd { Your error routine for invalid codes } JMP done intrupt endp { Invalid function request by DOS } badcmd proc near MOV AX, 813h { Return "Error: invalid command" } RET badcmd endp { Unimplemented function request by DOS will return 0=SUCCESS } nopcmd proc near XOR AX, AX { No error, not busy } RET nopcmd endp dosfunc0 proc near .. endp *)