[comp.os.minix] Minix works on 80386 with fix

jaime@killer (James da Silva @ The Unix Connection BBS, Dallas, Texas) (06/28/87)

After more than a couple nights of poking around and endless 
iterations of re-compiling the kernel, I have gotten Minix to 
boot on a 16Mhz Intel-Motherboard 80386 AT.

The basic incompatibility arises in the vid_copy function, used 
to copy text into screen memory.  AST uses the 'lock' prefix to 
indicate to the PC-Simulator that video memory has changed.  The 
specific instruction used is 'lock nop'. 

The designers of the 80386 decided to restrict the use of the 
lock prefix to certain instructions that read a value from 
memory, modify it in some way, then store it back in the same 
memory location. In particular, the lock prefix is permitted only 
with the following instructions and addressing modes: 

        BT, BTS, BTR, BTC                 mem, reg/immediate
        ADD, OR, ADC, SBB, AND, SUB, XOR  mem, reg/immediate
        XCHG                              reg, mem
        XCHG                              mem, reg
        NOT, NEG, INC, DEC                mem

The 'lock nop' instruction was causing an undefined opcode trap 
to occur.  Not Pretty.  And not easy to find.  With the lock nop 
instruction commented out,  Minix came up without a hitch. 

If you want to maintain compatibility with the PC Simulator (as I 
expect AST will with any release), vid_copy must be modified to 
lock one of the instructions mentioned above.  I added a dummy 
byte in the data segment named 'vidlck', then incremented it with 
the lock prefix.  This works on my 386, and it should work under 
the PC Simulator, too. 

For the compatibility records, my machine is an Intel iSBC 386AT 
motherboard.  I think this is the same motherboard used in the 
Wyse 386 and others.  My guess is that, with this fix installed, 
Minix should boot on any AT-compatible 80386 box, including the 
Compaq 386.

I'd love to hear from any other people running (or trying to run) 
Minix on a 386.  Protected mode Minix, anyone?

Here's the modified vid_copy function:

|*===========================================================================*
|*                              vid_copy                                     *
|*===========================================================================*
| This routine takes a string of (character, attribute) pairs and writes them
| onto the screen.  For a color display, the writing only takes places during
| the vertical retrace interval, to avoid displaying garbage on the screen.
| The call is:
|     vid_copy(buffer, videobase, offset, words)
| where
|     'buffer'    is a pointer to the (character, attribute) pairs
|     'videobase' is 0xB800 for color and 0xB000 for monochrome displays
|     'offset'    tells where within video ram to copy the data
|     'words'     tells how many words to copy
| if buffer is zero, the fill char (BLANK) is used
|
|  June 28, 1987 - modified by James da Silva to work on 80386 machines and
|                  still remain compatible with AST's PC-Simulator.

BLANK = 0x0700                  | controls color of cursor on blank screen

        .data
vidlck: .byte   0               | a dummy data byte used in lock
        .text

_vid_copy:
        push bp                 | we need bp to access the parameters
        mov bp,sp               | set bp to sp for indexing
        push si                 | save the registers
        push di                 | save di
        push bx                 | save bx
        push cx                 | save cx
        push dx                 | save dx
        push es                 | save es
vid.0:  mov si,4(bp)            | si = pointer to data to be copied
        mov di,8(bp)            | di = offset within video ram
        and di,_vid_mask        | only 4K or 16K counts
        mov cx,10(bp)           | cx = word count for copy loop
        mov dx,#0x3DA           | prepare to see if color display is retracing

        mov bx,di               | see if copy will run off end of video ram
        add bx,cx               | compute where copy ends
        add bx,cx               | bx = last character copied + 1
        sub bx,_vid_mask        | bx = # characters beyond end of video ram
        sub bx,#1               | note: dec bx doesn't set flags properly
        jle vid.1               | jump if no overrun
        sar bx,#1               | bx = # words that don't fit in video ram
        sub cx,bx               | reduce count by overrun
        mov tmp,cx              | save actual count used for later

vid.1:  test _color,*1          | skip vertical retrace test if display is mono
        jz vid.4                | if monochrome then go to vid.2

|vid.2: in                      | with a color display, you can only copy to
|       test al,*010            | the video ram during vertical retrace, so
|       jnz vid.2               | wait for start of retrace period.  Bit 3 of
vid.3:  in                      | 0x3DA is set during retrace.  First wait
        testb al,*010           | until it is off (no retrace), then wait
        jz vid.3                | until it comes on (start of retrace)

vid.4:  pushf                   | copying may now start; save flags
        cli                     | interrupts just get in the way: disable them
        mov es,6(bp)            | load es now: int routines may ruin it

        cmp si,#0               | si = 0 means blank the screen
        je vid.7                | jump for blanking
        lock                    | this is a trick for the IBM PC simulator only
        incb vidlck             | 'lock' indicates a video ram access
        rep                     | this is the copy loop
        movw                    | ditto

vid.5:  popf                    | restore flags
        cmp bx,#0               | if bx < 0, then no overrun and we are done
        jle vid.6               | jump if everything fit
        mov 10(bp),bx           | set up residual count
        mov 8(bp),#0            | start copying at base of video ram
        cmp 4(bp),#0            | NIL_PTR means store blanks
        je vid.0                | go do it
        mov si,tmp              | si = count of words copied
        add si,si               | si = count of bytes copied
        add 4(bp),si            | increment buffer pointer
        jmp vid.0               | go copy some more

vid.6:  pop es                  | restore registers
        pop dx                  | restore dx
        pop cx                  | restore cx
        pop bx                  | restore bx
        pop di                  | restore di
        pop si                  | restore si
        pop bp                  | restore bp
        ret                     | return to caller

vid.7:  mov ax,#BLANK           | ax = blanking character
        rep                     | copy loop
        stow                    | blank screen
        jmp vid.5               | done


----------------------------------------------------------------
James da Silva                          14102 Bramble Ct. #203
Path: ..!ihnp4!killer!jaime             Laurel, Maryland  20807