home *** CD-ROM | disk | FTP | other *** search
- include mmclock.mac
- title MM58167A clock/calendar driver -- Copyright 1990 Wales
-
- ; ======================================================================
- ;
- ; MM58167A clock/calendar driver.
- ; (C) Copyright 1990 Richard B. Wales. All Rights Reserved.
- ;
-
- ; ======================================================================
- ;
- ; Format of a DOS I/O request header structure.
-
- Request struc
- db ? ; length of header
- db ? ; unit number
- Command db ? ; command code
- Status dw ? ; return status
- db 8 dup (?) ; reserved
- db ? ; media descriptor
- Address dw ?, ? ; memory address for transfer
- Args dw ?, ? ; command-line argument string
- Request ends
-
- ; ======================================================================
- ;
- ; Bit values for return status word in request header.
-
- IOERR equ 8000h ; error flag
- IOBUSY equ 0200h ; busy
- IODONE equ 0100h ; done
- IOUNK equ 0003h ; unknown command
-
- ; ======================================================================
- ;
- ; Driver header.
-
- org 0 ; drivers start at offset zero
- Header dd -1 ; link to next device
- dw 8008h ; attribute word (clock device)
- dw Strat ; entry point (strategy)
- dw Intr ; entry point (interrupt)
- db 'MM$CLOCK' ; device name
- RHptr dw ?, ? ; pointer to request header
-
- ; ======================================================================
- ;
- ; Dispatch table for driver command codes -- used by interrupt routine
-
- Dispatch:
- dw Init ; 0 = initialize
- dw Done ; 1 = media check
- dw Done ; 2 = build parameter block
- dw NoSuchOp ; 3 = I/O control read
- dw Read ; 4 = read
- dw Busy ; 5 = non-destructive read
- dw Done ; 6 = current input status
- dw Done ; 7 = flush input buffers
- dw Write ; 8 = write
- dw Write ; 9 = write and verify
- dw Done ; 10 = current output status
- dw Done ; 11 = flush output buffers
- dw NoSuchOp ; 12 = I/O control write
- dw Done ; 13 = open
- dw Done ; 14 = close
- dw NoSuchOp ; 15 = removable media check
- dw NoSuchOp ; 16 = output until busy
- MaxCmd equ (($-Dispatch)/2)-1
-
- ; ======================================================================
- ;
- ; I/O port for clock.
-
- ClkPort dw 0
-
- ; ======================================================================
- ;
- ; External routines called directly from the driver.
-
- extrn DriverInit:proc, ClkToBuf:proc, BufToClk:proc
-
- ; ======================================================================
- ;
- ; Strategy routine (saves request header pointer).
-
- Strat proc far
-
- mov cs:[RHptr], bx
- mov cs:[RHptr+2], es
- ret
-
- Strat endp
-
- ; ======================================================================
- ;
- ; Interrupt routine (jumps to service routine through dispatch table).
- ;
- ; The interrupt routine saves all registers on entry (including flags),
- ; and restores them all on exit. Any procedure called from the inter-
- ; rupt routine is presumed to destroy all registers; hence, anything to
- ; be saved in a register across a procedure call must be pushed before
- ; the CALL and popped afterwards. In particular, ES and DI are used by
- ; the "Done" cleanup processing and must be saved prior to any CALL.
-
- Intr proc far
-
- ; Save registers.
- PUSHM ax, bx, cx, dx, bp, ds, es, si, di, flags
-
- ; Make sure string operations work in ascending memory order.
- cld
-
- ; Make data addressable via DS. This is required in order to
- ; get the service routine address via "mod-reg-r/m" addressing,
- ; so we might as well take advantage of it.
- INIT_DS
-
- ; Get the request header (ES:DI).
- les di, dword ptr [RHptr]
-
- ; Get the command code.
- mov al, es:[di.Command]
- cmp al, MaxCmd ; command code too big?
- ja NoSuchOp
-
- ; Get the address of the service routine.
- xor ah, ah
- shl ax, 1
- mov bx, offset Dispatch
- add bx, ax
-
- ; Jump to the service routine.
- ; Note that the service routine must preserve ES and DI --
- ; but all other registers are fair game and cannot be assumed
- ; to contain anything meaningful later on.
- jmp [bx]
- assume ds:nothing ; service routine may zap DS
-
- Success:
- ; Successful completion of the service routine.
- xor ax, ax
- ; (fall through to "Done")
-
- Done:
- ; Store the status code, restore registers, and return.
- or ax, IODONE
- mov es:[di.Status], ax
- POPM flags, di, si, es, ds, bp, dx, cx, bx, ax
- ret
-
- NoSuchOp:
- ; Unimplemented driver command.
- mov ax, IOERR + IOUNK
- jmp short Done
-
- Busy:
- ; Driver is busy. (Response to a non-destructive read request.)
- mov ax, IOERR + IOBUSY
- jmp short Done
-
- Intr endp
-
- ; ======================================================================
- ;
- ; Initialization routine.
-
- Init:
- assume ds:nothing
- lds si, dword ptr es:[di.Args]
- PUSHM es, di
- call DriverInit
- POPM di, es
- mov cs:[ClkPort], dx ; save clock port for Read/Write
- mov es:[di.Address], cx ; first mem loc after driver
- mov es:[di.Address+2], cs
- jmp short Success
-
- ; ======================================================================
- ;
- ; Read routine.
-
- Read:
- assume ds:code
- mov dx, [ClkPort] ; DS still set from "Intr"
- assume ds:nothing
- PUSHM es, di
- les di, dword ptr es:[di.Address]
- call ClkToBuf
- POPM di, es
- jmp short Success
-
- ; ======================================================================
- ;
- ; Write routine.
-
- Write:
- assume ds:code
- mov dx, [ClkPort] ; DS still set from "Intr"
- assume ds:nothing
- PUSHM es, di
- lds si, dword ptr es:[di.Address]
- call BufToClk
- POPM di, es
- jmp short Success
-
- code ends
-
- end