Path: utzoo!attcan!uunet!steinmetz!ge-dab!peora!rtmvax!johnc From: johnc@rtmvax.UUCP (John Connin) Newsgroups: comp.os.minix Subject: Equip Survey Keywords: Minix, PS-2, Hardware Message-ID: <2880@rtmvax.UUCP> Date: 25 Jan 89 18:24:55 GMT Organization: Robert Talley (PRIVATE), Orlando, FL Lines: 208 In message <1944@ast.cs.vu.nl> Andy Tanenbaum writes: [ stuff deleted ] > Hardware types, get out your thinking caps. > > Another point, I am still trying to figure out exactly how to tell if > a machine is (1) PS/2 and (2) Microchannel. Several people have pointed > out that INT 15 is supposed to tell you, but I can't find that in my > (PC) BIOS manual. Maybe it is something new. Could some kind soul please [ stuff deleted ] First, as a policy, I believe that Minix should NOT rely on BIOS services. Yes, I know it makes life easier, but my feeling is that doing so detracts from the beauty of Minix. As to AST's question, though not comprehensive, perhaps the follow code fragments will help. One determines the processor type by executing selected instructions. The other determines the machine type by testing the 'model byte' located at 0xFFFF:000E. Perhaps someone more knowledgeable than myself can contribute a comprehensive model byte list. An additional piece of information (clone type) can be had by checking the BIOS 'id_string' at 0xF000:0xFFEA (eg. "IBM", "COMPAQ", "OLIVETTI",..). As an addition thought, I believe it would be prudent to collect all low level "survey code" into one code module. As envisioned, this code would be called by kernel/main and would place results in a "system data" structure which is accessable to all other OS modules. To illustrate the point, consider the following code fragement and system data structure which is evolving in my own version of Minix: survey_enviroment() { /* find out our equipment configuration */ equip_check(); /* get the io port address */ serial_ports(); printer_ports(); /* get the memory parameters */ mem_parms(); /* get the hard disk parameters */ hdisk_parms(); } /* Global System Data */ struct sysdat { ... int cur_proc; int prev_proc; long realtime; /* -- memory section -- */ uint base_mem; /* amount of base memory (kb) */ uint extended_mem; /* amount of extended memory (kb) */ phys_clicks minix_base; /* where minix starts in memory */ vir_clicks minix_size; /* length of memory image exclusive */ /* of RAM disk */ phys_clicks init_text_org; vir_clicks init_text_size; phys_clicks init_data_org; vir_clicks init_data_size; /* -- general equipment section -- */ int nr_fdisks; int nr_hdisks; int nr_serial; int nr_parallel; int nr_mono; int nr_color; int nr_ndp; /* numeric processor */ int serial_ports[ MAX_PORTS]; /* port addresses */ int parallel_ports[ MAX_PORTS]; /* -- video section -- */ int vio_boot_mode; /* 00 = EGA, 01 = CGA-40 */ /* 10 = CGA-80, 11 = MDA-80 */ int vio_cur_mode; int vio_segment; int vio_sync; int ega_config; int ega_memsize; int ega_switch; int ega_feature; uint herc_retrace; /* hercules retrace timing */ /* -- hard disk parameters -- */ struct hd_parm hdisk_tbl[ MAX_HDISK]; ... }; After 'sysdat' is initialized, each module is initialized in turn and the address of 'sysdat' is passed as an argument ( even to those modules which occupy a different address space, eg. mm and fs). _mmgr_init: mov word ptr DGROUP:_sysdata, bx ; store address of struct sys_dat mov word ptr DGROUP:_sysdata+2,dx ; call _mm_init retf mm_init() { /* create the memory manager process */ if ((mm_procnr = create((struct pdesc far *) &mm_pdesc)) == -1) { kprintf(fpString("Can't create process: memory manager\n")); } else { if (ready(mm_procnr) != OK) return( -1 ); } return( OK ); } mm_server() { int error; init_mm(); /* initialize memory manager tables */ /* This is MM's main loop - get work and do it, forever.. */ while (TRUE) { /* Wait for message. */ get_work(); /* wait for an MM system call */ ..... } } Well I have stray too far from the intended focus of this message, so I will stop at this point. ---------------------------------------------------------------- processor_type: push sp ; ax != sp if (8086/88/186/V20/30/...) pop ax ; ax == sp if (80286 or 80386) cmp ax,sp ; je not_86 ; mov ax, 1 ; is 86/88/186 ret ; not_86: ; have 286 or 386 pushf ; determine which via IOPL flags pop ax ; or ah,30h ; set IOPL == 3 push ax ; popf ; pushf ; 386 if (ax == 3xxx) else pop ax ; 286 if (ax == 0xxx ) and ah,30h ; cmp ah,30h ; je is_386 ; ; mov ax, 2 ; is 286 ret ; ; is_386: ; mov ax, 3 ; is 386 ret machine_type: mov ax,0FFFFh ; address top of ROM mov es,ax mov al,es:.0Eh ; get IBM model byte cmp al,0FCh ; AT or PS/2 50/60 jne ckf_30 ; mov ax, 1 ; is AT or PS/2 50 or 60 chf_30: cmp al,0FAh ; jne ckf_80 ; mov ax, 2 ; is PS/2 model 30 ret ckf_80: cmp al,0F8h ; jne no_mt ; mov ax, 2 ; is PS/2 model 80 ret ; no_mt: ; mov ax, 0 ; none of the above ret ; John L. Connin (peora!rtmvax!johnc)