home *** CD-ROM | disk | FTP | other *** search
- include mmclock.mac
- title MM58167A clock driver init -- Copyright 1990 Wales
-
- ; ======================================================================
- ;
- ; MM58167A clock/calendar driver initialization.
- ; (C) Copyright 1990 Richard B. Wales. All Rights Reserved.
- ;
- ; Global variables:
- ;
- ; None.
- ;
- ; Global routines:
- ;
- ; DriverInit
- ; Initializes the driver.
-
- ; ======================================================================
- ;
- ; Start of the initialization code. Everything from this point onward
- ; can be thrown away once the driver has been initialized.
-
- StartInit equ $
-
- ; ======================================================================
- ;
- ; Various character strings.
-
- CR equ 0Dh
- LF equ 0Ah
- TAB equ 09h
-
- Banner db CR, LF
- db '╔═══════════════════════════════════════════════╗', CR, LF
- db '║ MM58167A Clock Driver -- Version 1.20 (06/90) ║', CR, LF
- db '║ (C) Copyright 1990 Richard B. Wales ║', CR, LF
- db '║ (213)826-0893 Internet: wales@CS.UCLA.EDU ║', CR, LF
- db '$'
-
- ClkFound db '║ Real-time clock found; I/O port '
- ClkAddr db 'XXXXh ║', CR, LF
- db '║ Current date/time: '
- CurDay db 'XX '
- CurMon db 'XXX '
- CurYear db 'XXXX '
- CurHour db 'XX:'
- CurMin db 'XX:'
- CurSec db 'XX.'
- CurHSec db 'XX ║', CR, LF, '$'
- Windup db '╚═══════════════════════════════════════════════╝'
- db CR, LF, CR, LF, '$'
-
- NoClkFound db '║ Clock not found! ** DRIVER NOT INSTALLED ** ║'
- db CR, LF, '$'
-
- ; ======================================================================
- ;
- ; Stuff for identifying the month.
- ; Note that February in this table has 29 days (as for leap year).
- ; Before trying to identify the month, any date in March or later
- ; in a non-leap year is incremented by one; hence, this works.
-
- MonLen dw 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
- MonNam db 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec '
-
- ; ======================================================================
- ;
- ; Buffer for reading the initial clock value.
-
- buffer db 6 dup (?)
-
- ; ======================================================================
- ;
- ; Hex-to-ASCII conversion table.
-
- hex2asc db '0123456789ABCDEF'
-
- ; ======================================================================
- ;
- ; Port list -- used when a port number is specified via an argument.
-
- ThePort dw ?, 0
-
- ; ======================================================================
- ;
- ; Global symbols.
-
- public DriverInit
-
- ; ======================================================================
- ;
- ; External routines called.
-
- extrn LookForClock:proc, ClkToBuf:proc, SetBIOS:proc
-
- ; ======================================================================
- ;
- ; Binary-to-BCD conversion table.
-
- extrn bin2bcd:byte
-
- ; ======================================================================
- ;
- ; DriverInit
- ;
- ; Announces the driver and looks for the clock.
- ;
- ; Arguments:
- ;
- ; DS:SI Text of the DRIVER= line in the CONFIG.SYS file
- ; (starting with the character after the "=").
- ;
- ; Returned values:
- ;
- ; CX Offset (relative to CS) of the first byte that
- ; does not need to be saved in the driver. If the
- ; clock was not found, CX will be zero (which will
- ; cause the driver not to be installed at all).
- ; DX I/O port address of the clock; zero if no clock.
-
- DriverInit proc near
-
- ; BX will contain the port number from the argument (0 if none).
- xor bx, bx
-
- ; Skip over the driver file name
- ; (look for space, slash, tab, or CR after name).
- skip_driver_name:
- lodsb
- cmp al, CR
- je short port_done
- cmp al, ' '
- je short end_of_name
- cmp al, TAB
- je short end_of_name
- cmp al, '/'
- jne short skip_driver_name
- end_of_name:
-
- ; Process a port number argument, if any.
- mov cl, 4 ; for shifting
- ;
- next_port_digit:
- lodsb ; get next (possible) digit
- cmp al, ' '
- je short next_port_digit ; skip spaces
- cmp al, TAB
- je short next_port_digit ; skip tabs
- cmp al, '/'
- je short next_port_digit ; skip slashes
- cmp al, '0'
- jb short port_done
- cmp al, '9'
- ja short not_decimal
- ;
- process_port_digit:
- shl bx, cl
- and al, 0Fh
- add bl, al ; add new digit into total
- jmp short next_port_digit
- ;
- not_decimal:
- cmp al, 'A'
- jb short port_done
- cmp al, 'F'
- ja short not_capital
- ;
- alpha_digit:
- add al, 9 ; shift to range 10-15
- jmp short process_port_digit
- ;
- not_capital:
- cmp al, 'a'
- jb short port_done
- cmp al, 'f'
- ja short port_done
- jmp short alpha_digit
- ;
- port_done:
- ; BX will now contain the port number argument, or zero if none.
- and bx, 0FFF0h ; mask out low-order four bits
-
-
- ; Make data addressable via DS (required for DOS calls and XLAT).
- INIT_DS
-
- ; Print banner.
- PRINT Banner
-
- ; Look for the clock.
- and bx, bx
- jz short use_default_port ; if BX=0, use default port list
- mov ThePort, bx ; otherwise use only BX as port #
- mov bx, offset ThePort
- jmp short got_port
- use_default_port:
- xor bx, bx ; use default port list
- got_port:
- push ds
- call LookForClock ; returns in DX (I/O port)
- pop ds
- and dx, dx
- jnz short clock_found ; DX=0 if no clock found
-
- ; Announce that no clock was found.
- PRINT NoClkFound
- PRINT Windup
- xor dx, dx ; clock port = 0 (no clock)
- xor cx, cx ; can toss the entire driver
- ret
-
- clock_found:
- ; Format the clock's port address for output.
- mov bx, offset hex2asc ; hex->ASCII conversion table
- mov cx, 4 ; for shifting
- SPLIT dh
- xlat
- SWAP
- xlat
- mov word ptr [ClkAddr], ax
- SPLIT dl
- xlat
- SWAP
- xlat
- mov word ptr [ClkAddr+2], ax
- push dx ; save I/O port address
-
- ; Read the clock value. This is done now for two reasons:
- ; first, to set the BIOS time-of-day count; and second, to
- ; announce the current date and time in the driver banner.
- mov ax, ds
- mov es, ax
- mov di, offset buffer
- call ClkToBuf
-
- ; Set the BIOS time-of-day count.
- mov cx, word ptr [buffer+2]
- mov dx, word ptr [buffer+4]
- call SetBIOS
-
- ; Format the current time in the driver banner.
- mov bx, offset bin2bcd ; for XLAT
- mov cx, 4 ; for SPLIT
- mov dx, ('0' shl 8) + '0' ; for ASCII conversion
- ;
- mov al, byte ptr [buffer+3] ; hours
- xlat
- SPLIT al
- add ax, dx
- SWAP
- mov word ptr [CurHour], ax
- ;
- mov al, byte ptr [buffer+2] ; minutes
- xlat
- SPLIT al
- add ax, dx
- SWAP
- mov word ptr [CurMin], ax
- ;
- mov al, byte ptr [buffer+5] ; seconds
- xlat
- SPLIT al
- add ax, dx
- SWAP
- mov word ptr [CurSec], ax
- ;
- mov al, byte ptr [buffer+4] ; 1/100 second
- xlat
- SPLIT al
- add ax, dx
- SWAP
- mov word ptr [CurHSec], ax
-
- ; Format the current date in the driver banner. In order to
- ; do this, it is necessary to convert the "long count" date
- ; from the driver into a year, month, and day.
- mov ax, word ptr [buffer] ; get long count
- mov bx, 1980 ; initial year
- mov cx, 365
- ;
- try_next_year:
- mov dx, cx ; 365 days in a year . . .
- test bl, 3
- jnz short not_leap_year ; but in a leap year,
- inc dx ; it's 366 days instead
- not_leap_year:
- sub ax, dx ; a full year of days left?
- jb found_year
- inc bx ; if so, add one to year,
- jmp short try_next_year ; and try again
- ;
- found_year:
- add ax, dx ; if not, fix day count
- cmp ax, 59 ; if March or later,
- jb short leap_fix_done
- test bl, 3 ; and not a leap year,
- jz short leap_fix_done
- inc ax ; add 1 to AX so we can pretend
- ; later that February always has
- ; 29 days
- leap_fix_done:
- push ax ; save day count for later
- mov ax, bx
- mov bl, 100
- div bl ; split into century and year
- mov di, ax ; save year part for later
- ;
- mov bx, offset bin2bcd ; for XLAT
- mov cx, 4 ; for SPLIT
- mov dx, ('0' shl 8) + '0' ; for ASCII conversion
- ;
- xlat ; century already in AL after DIV
- SPLIT al
- add ax, dx
- SWAP
- mov word ptr [CurYear], ax
- ;
- mov ax, di
- SWAP
- xlat ; low-order two digits of year
- SPLIT al
- add ax, dx
- SWAP
- mov word ptr [CurYear+2], ax
- ;
- pop ax ; back to month and day
- mov si, 0 ; initial month (January)
- ;
- try_next_month:
- sub ax, word ptr [MonLen+si]
- jb short found_month
- inc si
- inc si
- jmp short try_next_month
- ;
- found_month:
- add ax, word ptr [MonLen+si]
- inc ax ; AL is now day number
- ;
- mov bx, offset bin2bcd ; for XLAT
- mov cx, 4 ; for SPLIT
- mov dx, ('0' shl 8) + '0' ; for ASCII conversion
- ;
- xlat
- SPLIT al
- add ax, dx
- SWAP
- mov word ptr [CurDay], ax
- ;
- shl si, 1 ; SI = 4 * (month - 1)
- mov ax, word ptr [MonNam+si]
- mov word ptr [CurMon], ax
- mov ax, word ptr [MonNam+2+si]
- mov word ptr [CurMon+2], ax
-
- ; Announce that the clock was found, and the current time.
- PRINT ClkFound
- PRINT Windup
- pop dx ; restore I/O port address
-
- ; Ready to return.
- mov cx, offset StartInit ; can toss all the init code
- ret
-
- DriverInit endp
-
- code ends
-
- end