ogilvie@klipper.cs.vu.nl (Ogilvie) (09/17/88)
Here follows some code to deal with the AT-setup, but first the theory: Setup information is kept in the Motorola MC146818 CMOS RTC RAM, which is a battery-powered chip with a real-time clock (so the PC knows time and date at startup) and 64 bytes of RAM (also battery powered so the information is secured over power-downs). I have a quiestion too: Does anyone knows if the number of hard disk definitions in the BIOS is recorded somewhere? Here follows what I kow about the SETUP. I/O addresses: to chip: 70h from chip: 71h Internal RAM usage: address meaning ----------- ------------------ 0 seconds (real time) 1 seconds (alarm) 2 minutes (real time) 3 minutes (alarm) 4 hours (real time) 5 hours (alarm) 6 day of the week 7 day-number 8 month-number 9 year 10 status reg. A 11 status reg. B 12 status reg. C 13 status reg. D 14 chip diagnostics status 15 shutdown reason 16 diskette types for A and B (see below) 17 reserved 18 hard disk types C and D (see below 19 reserved 20 equipment byte 21 low byte amount of standard memory 22 high byte amount of standard memory 23 low byte expansion memory 24 high byte " " 25 hard disk type C if byte 18, bits 7-4 == 15 26 hard disk type D if byte 18, bits 3-0 == 15 -45 reserved 46-47 RTC checksum 48 as byte 16, actual 49 as byte 18, actual 50 eon 51 flags 52-63 reserved Diskette types (byte 16) ------------------------ bits 7-4: A-drive 0: not present 1: 320/360Kb 2: 1.2Mb bits 3-0: B-drive (same) Hard disk types (byte 18) ------------------------- bits 7-4: first hard disk 0: not installed 1-14: index into BIOS table with definitions (see below) 15: installed, see byte 25 for actual type bits 3-0: second hard disk (same) Now follows some code. The first is in assembler. The routines can read any byte from the RTC-RAM. The second copies the ROM-BIOS stored HD definitons to user memory. Next follows a C-program that displays the definitons found in the BIOS. -------------------------------------- cut ---------------------------- ; Assembler to be linked with MS-C (4.0) PUBLIC _getrtc, _gettab rtc_port0 equ 70h rtc_port1 equ 71h CMOSDIAG equ 10h _TEXT SEGMENT PUBLIC BYTE 'CODE' ; start the code segment ASSUME CS:_TEXT,DS:nothing _getrtc PROC NEAR ; ; ret= getrtc (regnum) ; push bp mov bp,sp mov ax,CMOSDIAG out rtc_port0,al jmp $+2 ; delay a little for chip jmp $+2 ; before reading it's answer in al,rtc_port1 ; Get the answer test al,0C0h ; battery and checksum ok? jz ok mov ax, -1 jmp eind ; (dutch for end, but end is reserved) ok:mov al,[bp+4] out rtc_port0,al jmp $+2 jmp $+2 in al, rtc_port1 xor ah,ah eind:pop bp ret _getrtc ENDP _gettab PROC NEAR ; get the disk definition tabel in the BIOS ; ; gettab (table, curr_ptr) ; ; The disk table in the BIOS is copied into a user-structure (see below). ; In order to know where it starts, the caller got the current definition ; which is just an index into this table, and transformed this into a ; negative offset to be used by this routine. The current pointer of ; the interrupt 41h vector points to this definition in the ROM-BIOS. ; push bp mov bp,sp push ds push ds mov di,[bp+4] ; destination mov cx,[bp+6] ; length shr cx,1 ; move words xor ax,ax mov es,ax mov ax,es:[104h+2] ; FDBtab segment at int 41h location mov ds,ax ; source segment at int 41h location mov ax,es:[104h] ; FDBtab offset + index sub ax,[bp+8] ; base of table mov si,ax ; source offset pop es ; es=ds (destination segment) cld rep movsw ; copy it. pop ds pop bp ret _gettab ENDP ENDS end -------------------------------- cut ---------------------- /* File to read out the disk types defined in your BIOS and display * them on the screen. Uses the previous assembler */ #include <stdio.h> int i, disktype; typedef unsigned int word; typedef unsigned char byte; struct FDBTAB { /* fixed disk base table */ word ncyls; byte nheads; word dummy1; word wr_pre; byte eccburst; byte control; byte dummy2; byte dummy3; byte dummy4; word landing; byte sects; byte reserved; } FDBtab [60]; char header[]="\ nr. cyls. heads wr-pre ecc control landing sects\n\ --- ----- ----- ------ --- ------- ------- -----\n"; main(argc,argv) int argc; char *argv[]; { if (argc>1) if (stricmp(argv[1],"-i")==0) ignore= 1; /* don't stop after null definiton */ if ((disktype=getrtc(0x12)) == -1) { puts ("RTC-diagnose bad or not an AT"); exit(1); } disktype = (disktype & 0xF0) >> 4; if (disktype==15) disktype= getrtc(0x19); printf ("current type HD1: %d\n\n",disktype); gettab (FDBtab, 60*sizeof(struct FDBTAB), (disktype-1)*sizeof(struct FDBTAB)); i=0; printf (header); while (FDBtab[i].ncyls || FDBtab[i+1].ncyls || ignore) { printf ("%2d%8u%7d%8d%5d%9x%9d%7d\n",i+1, FDBtab[i].ncyls, FDBtab[i].nheads, FDBtab[i].wr_pre, FDBtab[i].eccburst, FDBtab[i].control, FDBtab[i].landing, FDBtab[i].sects ); i++; } } ------------------------ cut ------------------ Kind regards, Paul Ogilvie