[comp.dcom.lans] 3Com Etherlink I & II elink.sys

maurice@xanth.cs.odu.edu (Dale Ross Maurice) (01/08/89)

Due to the number of responses, I've decided to post the source
to ELINK.ASM.   (See the docs below to see what it does.)
I have encountered one know bug that I'm not sure how to fix;
actually I haven't had the time to find out what is causing the
problem.
It seems to work fine with all the software I've tried except
Procomm 2.4.2.  Whenever the following device driver is loaded
and I attempt to run procomm I get a 'Network Retrying' error 
and the machine hangs up.  If someone should find what is causing
this problem PLEASE let me know what is causing it.

If there are any other questions please feel free to mail me.

;-----------------------------------------------------------------;
;  Written by : Dale Ross Maurice                                 ;
;  Date : 01-06-89                                                ;
;                                                                 ;
; maurice@xanth.cs.odu.edu  maurice@cs.odu.edu                    ;
; maurice@xanth.uucp        maurice@gwynedd.uucp                  ;
;                                                                 ;
;  ELINK.ASM - Allows config.sys modification based on hardware   ;
;  configuration at boot time by determining whether an etherlink ;
;  I (3com 3C501) or etherlink II (3com 3C503) card is installed. ;
;  Depending on the card installed it replaces a dummy config.sys ;
;  entry (ELINK.DRIVER12345678) with the required 3com 3+Share    ;
;  driver ( eth.sys for 3C501, eth503.sys for 3C503).             ;
;    TASM elink                                                   ;
;    TLINK elink                                                  ;
;    EXE2BIN elink.exe elink.sys                                  ;
;    modify config.sys to contain:                                ;
;      device=elink.sys                                           ;
;      device=elink.driver12345678                                ;
;      ( The 'elink.driver12345678' is used as a buffer for the   ;
;        replacement driver.  This may need to be made longer     ;
;        depending on what configuration you are using.           ;
;           ie: Ours is   ETH503.SYS /i:2                         ;
;           CONFIG_DUM     DB      "ELINK.DRIVER12345678"         ;
;           CONFIG_DUM_LEN EQU     20                             ;
;        The two above defines can be made larger to meet other   ;
;        needs.                                                   ;
;      )                                                          ;
;                                                                 ;
;  Assembled using Turbo Assembler 1.0 but should work with       ;
;  MASM 2.0 or later. Remember to EXE2BIN                         ;
;  Based on CONFIG.CTL 1.0 (C) 1988 Ziff Communications Co.       ;
;-----------------------------------------------------------------;
_TEXT          SEGMENT PUBLIC 'CODE'
               ASSUME  CS:_TEXT,DS:_TEXT
               ASSUME  ES:_TEXT,SS:_TEXT
               ORG     0H

;************* DEVICE_HEADER *************;
POINTER        DD      -1
ATTRIBUTE      DW      1000000000000000B
DEVICE_STAG    DW      STRATEGY
DEVICE_INT     DW      INTERRUPT
DEVICE_NAME    DB      "CONFIGURE"

;************* REQUEST HEADER ************;
REQUEST_HEADER STRUC

HEADER_LENGTH  DB      ?
UNIT_CODE      DB      ?
COMMAND_CODE   DB      ?
STATUS         DW      ?
RESERVED       DQ      ?

REQUEST_HEADER ENDS

DONE           EQU     0000000100000000B       ;Status codes.
UNKNOWN        EQU     1000000000000011B
;-------------------------;
INIT           STRUC

HEADER         DB      (TYPE REQUEST_HEADER) DUP(?)
UNITS          DB      ?
ENDING_OFFSET  DW      ?
ENDING_SEGMENT DW      ?
ARGUMENTS_OFF  DW      ?
ARGUMENTS_SEG  DW      ?

INIT           ENDS

REQUEST_OFFSET DW      ?
REQUEST_SEG    DW      ?

;-----------------------------------------------------------------------------;
; The only task of the strategy is to save the pointer to the request header. ;
;-----------------------------------------------------------------------------;
STRATEGY       PROC    FAR

               MOV     CS:REQUEST_OFFSET,BX    ;Request header address is
               MOV     CS:REQUEST_SEG,ES       ; passed in ES:BX.
               RET

STRATEGY       ENDP

;------------------------------------------------------------------------;
; The interrupt procedure will be called immediately after the strategy. ;
;------------------------------------------------------------------------;
INTERRUPT      PROC    FAR

               PUSH    AX                      ;Responsible for all registers.
               PUSH    BX
               PUSH    CX
               PUSH    DX
               PUSH    DS
               PUSHF

               MOV     DS,CS:REQUEST_SEG       ;Retrieve request header pointer.
               MOV     BX,CS:REQUEST_OFFSET

               OR      STATUS[BX],DONE         ;Tell DOS we are done.
               CMP     COMMAND_CODE[BX],0      ;Is it INIT command?
               JZ      MAKE_STACK              ;If yes, do our stuff.
               OR      STATUS[BX],UNKNOWN      ;Else, exit with confused
               JMP     SHORT UNKNOWN_EXIT      ; message to DOS.

MAKE_STACK:    MOV     CX,SS                   ;Save DOS stack.
               MOV     DX,SP
               MOV     AX,CS
               CLI
               MOV     SS,AX                   ;Make new stack.
               MOV     SP,0FFFEH
               STI
               PUSH    CX                      ;Save old stack pointers on new.
               PUSH    DX

               PUSH    ES                      ;Save rest of registers.
               PUSH    SI
               PUSH    DI
               PUSH    BP

               CALL    INITIALIZE              ;Go do our stuff.

               POP     BP                      ;Restore registers.
               POP     DI
               POP     SI
               POP     ES

               POP     DX                      ;Restore old DOS stack.
               POP     CX
               CLI
               MOV     SS,CX
               MOV     SP,DX
               STI

UNKNOWN_EXIT:  POPF                            ;Restore rest of registers.
               POP     DS
               POP     DX
               POP     CX
               POP     BX
               POP     AX
               RET                             ;Far return back to DOS.

INTERRUPT      ENDP

CONFIG_CTL_END LABEL   WORD

;************* END OF RESIDENT PORTION *************;


BUFFER_SEGMENT DW      ?                       ;CONFIG.SYS buffer segment
BUFFER_START   DW      ?                       ; and offset.
BUFFER_END     DW      ?

ADDRESS        DB      6 DUP(0)
VALID          DB      02H,60H,8CH

CONFIG_DUM     DB      "ELINK.DRIVER12345678"
CONFIG_DUM_LEN EQU     20

; Drivers must be Null (ascii 0) padded to 20 characters,
; replace all embedded spaces with nulls

ELINKI_DRV     DB      "ETH.SYS",13 DUP(0)
ELINKII_DRV    DB      "ETH503.SYS",0,"/I:2",5 DUP(0) 
BAD_DRV        DB      "ELINK CARD NOT FOUND"  

;------------------------------------------;
; INPUT                                    ;
;   DS:BX points to request header.        ;
;                                          ;
;   All registers destroyed.               ;
;------------------------------------------;
INITIALIZE     PROC    NEAR

               MOV     ENDING_OFFSET[BX],OFFSET CONFIG_CTL_END
               MOV     ENDING_SEGMENT[BX],CS   ;Resident portion setup.

               MOV     AX,ARGUMENTS_SEG[BX]    ;Retrieve CONFIG.SYS buffer
               MOV     ES,AX                   ; pointers from INIT table.
               MOV     BX,ARGUMENTS_OFF[BX]
               PUSH    CS                      ;Point to our data.
               POP     DS
               MOV     BUFFER_SEGMENT,ES       ;And save the segment.
;-----------------------------------------------------------------------;
; Search for dummy ELINK.DRIVER12345678 in config.sys and replace it,   ;
; if found, with the required etherlink driver.                         ;
;-----------------------------------------------------------------------;
NEXT_BYTE:     MOV     SI,OFFSET CONFIG_DUM    ;Pointer to CONFIG_DUM.
               MOV     DI,BX                   ;Pointer to current buffer pos.
               MOV     CX,CONFIG_DUM_LEN       ;Is it CONFIG_DUM?
               CLD
               REPZ    CMPSB
               JZ      FOUND_DUM               ;If yes, found dummy.
               INC     BX                          ;Else, increment buff pos.
               CMP     BX,0FFFFH - CONFIG_DUM_LEN  ;End of segment?
               JNZ     NEXT_BYTE                   ;If no, continue.
               JMP     INIT_END                ;Else, give up search.

FOUND_DUM:     CALL    CHOOSEDRIVER

INIT_END:      RET                             ;Exit.
INITIALIZE     ENDP

CHOOSEDRIVER   PROC    NEAR
               PUSH    BX
               PUSH    ES
               CALL    GETELINKIADDR
               MOV     AX,CS
               MOV     DS,AX
               MOV     ES,AX
               LEA     DI,ADDRESS
               LEA     SI,VALID
               MOV     CX,3H
               CLD
               REPE    CMPSB
               JNZ     SHORT GETELINKII
               POP     ES
               POP     BX
               MOV     DI,BX
               LEA     SI,ELINKI_DRV
               MOV     CX,CONFIG_DUM_LEN
               CLD
               REP     MOVSB

               JMP     SHORT FINISHED

GETELINKII:
               CALL    GETELINKIIADDR

               MOV     AX,CS
               MOV     DS,AX
               MOV     ES,AX
               LEA     DI,ADDRESS
               LEA     SI,VALID
               MOV     CX,3H
               CLD
               REPE    CMPSB
               JNZ     SHORT BADMESSAGE
               POP     ES
               POP     BX
               MOV     DI,BX
               LEA     SI,ELINKII_DRV
               MOV     CX,CONFIG_DUM_LEN
               CLD
               REP     MOVSB
               JMP     SHORT FINISHED
BADMESSAGE:
               POP     ES
               POP     BX
               MOV     DI,BX
               LEA     SI,BAD_DRV
               MOV     CX,CONFIG_DUM_LEN
               CLD
               REP     MOVSB
FINISHED:
               RET
CHOOSEDRIVER   ENDP

;--------------------------------------------------------------------
; GET ELINKI

GETELINKIADDR  PROC    NEAR
               MOV     CX,6
               MOV     SI,0
AGAINI:
               MOV     AX,SI
               MOV     DX,308H
               OUT     DX,AL
               MOV     DX,309H
               MOV     AL,0H
               OUT     DX,AL
               MOV     DX,30CH
               IN      AL,DX    ; THE HEXPAIR
               MOV     ADDRESS[SI],AL
               INC     SI
               LOOP    AGAINI
               RET
GETELINKIADDR  ENDP

;--------------------------------------------------------------------
; GET ELINKII

GETELINKIIADDR PROC    NEAR
               MOV     DX,706H
               MOV     AX,4
               OUT     DX,AX
               MOV     CX,6
               MOV     SI,0
               MOV     DX,300H
AGAINII:
               IN      AL,DX  ; THE HEXPAIR
               MOV     ADDRESS[SI],AL
               INC     SI
               INC     DX
               LOOP    AGAINII
               RET
GETELINKIIADDR ENDP

DATA_STORAGE   EQU     $
_TEXT          ENDS
               END

-- 
;Dale Ross Maurice           |  maurice@xanth.cs.odu.edu  maurice@cs.odu.edu 
;Old Dominion University     |  maurice@xanth.uucp        maurice@gwynedd.uucp