[comp.os.minix] Equip Survey

johnc@rtmvax.UUCP (John Connin) (01/26/89)

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)

chasm@killer.DALLAS.TX.US (Charles Marslett) (01/30/89)

In article <2880@rtmvax.UUCP>, johnc@rtmvax.UUCP (John Connin) writes:
> 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.
The beauty of MINIX is not in running directly over the hardware (that is
the beauty of SCO Xenix, Microport Unix, Interactive Unix, etc.) -- MINIX is
small enough to be understandable and still not a career, MINIX is large
enough to be useful, and MINIX runs on the computer I own.  To keep the
other two characteristics, MINIX will need to take full advantage of any
help the BIOS provides if it is to run on a reasonable number of (non-IBM)
computers and especially if it is to avoid being rewritten every time a new
computer box is released.  The BIOS was written to provide a cushion against
the future changes of the hardware, and if it is not performing that function
perfectly, think how hard it would be to do anything without it.  MINIX
probably has 10K of vendor specific code in it now (for PS/2s, ATs, XTs, etc.)
and if it had to boot without the BIOS we would have 10 to 50 incompatible
binarys instead of 3 (or 2?, STs, ATs and XTs).

> 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.

The model byte is almost useless as a processor type detector, since the
various clone BIOS writers have to stuff a value that works best with the
available (MSDOS) software -- V20/V30 based systems often call themselves
ATs (without extended memory), PS/2 boxes have a whole new set of ID bytes,
since they are all the same, but different, and most clone AT and 386 boxes
use either Compaq's code or the IBM AT codes . . .  I have found that the
model byte is most useful to tell if there are 1 or 2 interrupt controllers
(since lots of MSDOS software uses it for this purpose), but it tells you
very little else unless you are willing to limit your universe to the high
priced boxes.

> An additional piece of information (clone type) can be had by checking
> the BIOS 'id_string' at 0xF000:0xFFEA (eg. "IBM", "COMPAQ", "OLIVETTI",..).

Again, only if you are willing to ignore "cheap" clones.  For example, most
Phoenix BIOSes have no useful string there at all.

> 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.

I agree on this point, the code will have to be modified (even using all the
help we can get from any source whatsoever) fairly often, and it will be the
most likely candidate for any failure to boot on a new computer.  Localizing
it makes the task of maintaining it all that much easier.

> John L. Connin  (peora!rtmvax!johnc)

===========================================================================
Charles Marslett
STB Systems, Inc.  <== Apply all standard disclaimers
Wordmark Systems   <== No disclaimers required -- that's just me
chasm@killer.dallas.tx.us