!************************************************************************** !* !* Network driver interface for netboot bootrom !* !* Module: pktinit.S !* Purpose: Load and initialize the packet driver interface !* Entries: drv_load !* !************************************************************************** !* !* Copyright (C) 1998-2003 Gero Kuhlmann !* !* This program is free software; you can redistribute it and/or modify !* it under the terms of the GNU General Public License as published by !* the Free Software Foundation; either version 2 of the License, or !* any later version. !* !* This program is distributed in the hope that it will be useful, !* but WITHOUT ANY WARRANTY; without even the implied warranty of !* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !* GNU General Public License for more details. !* !* You should have received a copy of the GNU General Public License !* along with this program; if not, write to the Free Software !* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. !* !* $Id: pktinit.S,v 1.4 2003/01/25 23:29:42 gkminix Exp $ !* ! !************************************************************************** ! ! Include assembler macros: ! #include #include #include #include "pktpriv.inc" ! !************************************************************************** ! ! Miscelleneous equates: ! MIN_INT equ $20 ! lowest usable packet driver interrupt MAX_INT equ $80 ! highest usable packet driver interrupt DRIVER_OFS equ 3 ! offset of ID string ! !************************************************************************** ! ! BSS segment: ! .bss ! start BSS segment extrn _end_of_bss .comm irqnum,2 ! hardware IRQ number .comm pktvect,4 ! packet driver software int vector ! !************************************************************************** ! ! Data segment: ! .data ! start data segment ! ID string at the beginning of the packet driver code: pktdrv_id: .ascii "PKT DRVR" pktdrv_end_id: ! !************************************************************************** ! ! Start code segment. ! .text public drv_load ! define entry points ! External routines of the DOS simulator extrn initdos extrn cleandos extrn loadprog extrn runprog ! General library external routines extrn prnstr extrn prnbyte extrn intsave extrn intrestore extrn intchanged extrn chkhwint ! !************************************************************************** ! ! Load and initialize the packet driver interface. When an error ! occurred, it will print an error message before returning. ! Input: ES:SI - pointer to network driver source ! DX - first usable paragraph for network driver ! Output: AX - PXE error code ! Registers changed: AX, BX, CX, DX, SI, DI, ES ! drv_load: ! Get space for the interrupt table copy on the stack. We can safely ! assume that we have enough stack space here (required are 1024 bytes) ! because the kernel loader already switched to a new stack which should ! be large enough. When normally entering a routine C style, BP gets ! the old stack pointer. Here it gets the new stack pointer. Therefore ! we cant use the penter macro. push bp sub sp,#IDT_SIZE mov bp,sp ! Save all interrupts and initialize the DOS simulator. push es push si call intsave ! save interrupts call initdos ! initialize the DOS simulator pop si pop es ! Scan through the list of DOS programs and run each in turn. The binary ! patch program should have stored the number of DOS programs at the first ! byte of the network driver source area. ! Note that these DOS simuator routines print a message in case of an ! error, so we dont have to do it ourselves. ! After all programs have been started, restore all interrupt vectors and ! identify those which have been changed by the packet driver. These will ! be set in the local IDT buffer. Then clean all DOS interrupts from this ! buffer, as the DOS simulator should not be needed anymore. seg es mov cx,word ptr [si] ! get number of DOS programs add si,#2 init1: push cx call loadprog ! load program into DOS memory jc init2 call runprog ! and run it init2: pop cx jnc init3 call intrestore ! in case of error restore all jmp initE ! interrupt vectors init3: loop init1 ! scan through all programs call intrestore ! restore all interrupt vectors jnc init7 ! and save new vectors in IDT buffer mov bx,#chgmsg ! print error message jmp initF init7: call cleandos ! cleanup DOS interrupts ! Determine the packet driver interrupt. If one has been found, save ! it for later reference and remove it from the local IDT buffer. This ! way it doesnt get set again. cld mov bx,#MIN_INT * 4 ! start looking at first interrupt init4: mov si,bx les di,[bp + si] ! get interrupt vector add di,#DRIVER_OFS ! compute address of ID string mov si,#pktdrv_id mov cx,#pktdrv_end_id - pktdrv_id repe cmpsb ! compare both strings je init5 ! found it add bx,#4 ! advance to next interrupt vector cmp bx,#MAX_INT * 4 ! at the end of the list? jb init4 mov bx,#intmsg ! print interrupt error message initF: push bx mov bx,#errmsg call prnstr pop bx call prnstr mov bx,#crlf call prnstr initE: mov ax,#PXENV_EXIT_FAILURE jmp init9 init5: mov si,bx #ifdef IS386 xor eax,eax xchg eax,[bp + si] ! get new vector and set it to 0 mov [pktvect],eax ! in interrupt buffer #else xor ax,ax xor dx,dx xchg ax,[bp + si + 0] xchg dx,[bp + si + 2] mov word ptr [pktvect + 0],ax mov word ptr [pktvect + 2],dx #endif #ifdef IS186 shr bx,#2 ! compute interrupt number #else shr bx,#1 shr bx,#1 ! compute interrupt number #endif ! Now try to find the hardware interrupt in the local interrupt buffer. This ! will also clear the interrupt from the IDT buffer. push bx call chkhwint ! find hardware interrupt pop bx or cx,cx jnz init6 mov bx,#hwmsg ! print error message if not IRQ found jmp initF init6: mov [irqnum],cx ! save hardware IRQ number ! Now set all those interrupt vectors which have to remain set while the ! packet driver is loaded. Then tell the user that we found something. push bx call intchanged ! identify permanent interrupts mov bx,#fndmsg call prnstr pop ax call prnbyte ! print packet driver software interrupt mov bx,#irqmsg call prnstr mov ax,[irqnum] call prnbyte ! print hardware IRQ number mov bx,#crlf call prnstr xor ax,ax ! return without error init9: add sp,#IDT_SIZE ! restore stack pop bp ret ! Message to tell user about packet driver interrupt: fndmsg: .byte $0D,$0A .asciz "Found packet driver at int " irqmsg: .asciz ", irq " ! Error messages errmsg: .byte $0D,$0A .asciz "PKTDRV ERROR: " intmsg: .asciz "no driver int" hwmsg: .asciz "no hw int" chgmsg: .asciz "too many changed ints" crlf: .byte $0D,$0A,0 ! !************************************************************************** ! end