home *** CD-ROM | disk | FTP | other *** search
/ C/C++ User's Journal & Wi…eveloper's Journal Tools / C-C__Users_Journal_and_Windows_Developers_Journal_Tools_1997.iso / gsidemo / tail.asm < prev    next >
Encoding:
Assembly Source File  |  1994-09-29  |  17.0 KB  |  680 lines

  1. ;   PC/FTP Packet Driver source, conforming to version 1.05 of the spec
  2. ;   Updated to version 1.08 Feb. 17, 1989.
  3. ;   Copyright 1988-1993 Russell Nelson
  4.  
  5. ;   This program is free software; you can redistribute it and/or modify
  6. ;   it under the terms of the GNU General Public License as published by
  7. ;   the Free Software Foundation, version 1.
  8. ;
  9. ;   This program is distributed in the hope that it will be useful,
  10. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. ;   GNU General Public License for more details.
  13. ;
  14. ;   You should have received a copy of the GNU General Public License
  15. ;   along with this program; if not, write to the Free Software
  16. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18.     include    defs.asm
  19.  
  20. code    segment word public
  21.     assume    cs:code, ds:code
  22.  
  23.     public    is_eisa
  24. is_eisa    db    0            ;=0 if ISA, =1 if EISA
  25.     extrn    sys_features: byte    ;bitmask of system features.
  26.     extrn    is_186: byte        ;=0 if 808[68], =1 if 80[1234]86.
  27.     extrn    is_286: byte        ;=0 if 80[1]8[68], =1 if 80[234]86.
  28.     extrn    is_386: byte        ;=0 if 80[12]8[68], =1 if 80[34]86.
  29.     extrn    int_no: byte        ;the board's interrupt level.
  30.     extrn    hw_int_no: byte        ;the 8259 interrupt level.
  31.     extrn    driver_class: byte    ;the class of this driver, per the spec.
  32.     extrn    rcv_modes: word        ;count of modes followed by mode handles.
  33.  
  34. ;-> last byte of static memory used by driver-dependent code.
  35.     extrn    end_resident: byte
  36.     extrn    end_free_mem: byte
  37.  
  38. ;-> the fixed address of the card.
  39.     extrn    rom_address: byte
  40.  
  41. ;-> the current address of the card.
  42.     extrn    my_address: byte
  43.  
  44.     extrn    phd_dioa: byte
  45.     extrn    phd_environ: word
  46.     extrn    flagbyte: byte
  47.  
  48.     include    printnum.asm
  49.     include    decout.asm
  50.     include    digout.asm
  51.     include    crlf.asm
  52.     include    chrout.asm
  53.  
  54. free_mem    dw    end_resident    ;allocate memory from here.
  55. ;also see memory_to_keep.
  56.  
  57.     public    malloc
  58. malloc:
  59. ;enter with dx = amount of memory desired.
  60. ;exit with nc, dx -> that memory, or cy if there isn't enough memory.
  61.     add    dx,free_mem        ;make a pointer after that much memory.
  62.     cmp    dx,offset end_free_mem    ;is it still in the free area?
  63.     ja    malloc_1        ;no, we're in trouble.
  64.     xchg    dx,free_mem        ;get the pointer back, store ptr->end.
  65.     clc
  66.     ret
  67. malloc_1:
  68.     stc
  69.     ret
  70.  
  71.  
  72. end_tail_1    label    byte        ; end of the delayed init driver
  73.  
  74. ;usage_msg is of the form "usage: driver [options] <packet_int_no> <args>"
  75.     extrn    usage_msg: byte
  76.  
  77. options_i_msg    label    byte
  78. db"   -i -- Force driver to report itself as IEEE 802.3 instead of Ethernet II.",CR,LF
  79. options_msg    label    byte
  80. db"   -d -- Delayed initialization.  Used for diskless booting",CR,LF
  81. db"   -n -- NetWare conversion.  Converts 802.3 packets into 8137 packets",CR,LF
  82. db"   -w -- Windows hack, obsoleted by winpkt",CR,LF
  83. db"   -p -- Promiscuous mode disable",CR,LF
  84. db"   -u -- Uninstall",CR,LF
  85. db '$'
  86.  
  87. ;copyright_msg is of the form:
  88. ;"Packet driver for the foobar",CR,LF
  89. ;"Portions Copyright 19xx, J. Random Hacker".
  90.     extrn    copyright_msg: byte
  91.  
  92. copyleft_msg    label    byte
  93.  db "Packet driver skeleton copyright 1988-93, Crynwr Software.",CR,LF
  94.  db "This program is freely copyable; source must be available; NO WARRANTY.",CR,LF
  95.  db "See the file COPYING.DOC for details; send FAX to +1-315-268-9201 for a copy.",CR,LF
  96.  db CR,LF,'$'
  97.  
  98. no_resident_msg    label    byte
  99.  db CR,LF,"*** Packet driver failed to initialize the board ***",CR,LF,'$'
  100.  
  101. ;parse_args should parse the arguments.
  102. ;called with ds:si -> immediately after the entry_point.
  103.     extrn    parse_args: near
  104.  
  105. ;print_parameters should print the arguments.
  106.     extrn    print_parameters: near
  107.  
  108.     extrn    our_isr: near, their_isr: dword
  109.     extrn    entry_point: byte
  110.  
  111. eisa_signature    db    "EISA"
  112.  
  113. system_msg    db    "System: ",'$'
  114. i386_msg    db    "[345]86 processor",'$'
  115. i286_msg    db    "286 processor",'$'
  116. i186_msg    db    "186 processor",'$'
  117. i8088_msg    db    "8088/8086 processor",'$'
  118. mca_msg        db    ", Microchannel bus",'$'
  119. eisa_msg    db    ", EISA bus",'$'
  120. isa_msg        db    ", ISA bus",'$'
  121. two_8259_msg    db    ", Two 8259s",'$'
  122. entry_point_name    db    "Packet driver software interrupt is ",'$'
  123. eaddr_msg    db    "My Ethernet address is ",'$'
  124. aaddr_msg    db    "My ARCnet address is ",'$'
  125.  
  126. already_msg    db    CR,LF,"Error: there is already a packet driver (you may uninstall it using -u) at ",'$'
  127. no_pkint_msg    db    CR,LF,"Error: there is no packet driver at ",'$'
  128. no_pkt_msg    db    CR,LF,"Error: no packet driver found between 0x60 and 0x80",CR,LF,'$'
  129. two_pkts_msg    db    CR,LF,"Error: there are two packets drivers (specify the desired one after -u).",CR,LF,'$'
  130. int_msg        db    CR,LF
  131.         db    "Error: <hardware_irq> should be between 0 and "
  132. int_msg_num    label    word
  133.         db    "15 inclusive", '$'
  134. xt_hd_warn_msg    db    CR,LF,"Warning: the hard disk on an XT usually uses IRQ 5.  Use a different interrupt",CR,LF,'$'
  135. no_ieee_msg    db    CR,LF,"Error: this driver doesn't implement both IEEE 802.3 and Ethernet II",CR,LF,'$'
  136. terminated_msg    db    "Uninstall completed",'$'
  137.  
  138. handle        dw    ?
  139.  
  140. entry_point_fnd    db    0
  141. bogus_type    db    0,0        ;totally bogus type code.
  142. our_recv:
  143.     xor    di,di
  144.     mov    es,di
  145.     retf
  146.  
  147.     public    etopen_diagn
  148. etopen_diagn    db    0        ; errorlevel from etopen if set
  149.  
  150. ;etopen should initialize the device.  If it needs to give an error, it
  151. ;can issue the error message and quit to dos.
  152.     extrn    etopen: near
  153.  
  154. memory_to_keep    dw    end_resident    ;keep at least this much memory.
  155. ;also see free_mem.
  156.  
  157. already_error:
  158.     mov    dx,offset already_msg
  159. already_error_1:
  160.     mov    di,offset entry_point
  161.     call    print_number
  162.     mov    ax,4c05h        ; give errorlevel 5
  163.     int    21h
  164.  
  165. usage_error:
  166.     mov    dx,offset usage_msg
  167.     mov    ah,9
  168.     int    21h
  169.     mov    dx,offset options_msg
  170.     cmp    word ptr driver_class,BLUEBOOK + IEEE8023*256    ;both present?
  171.     jne    error
  172.     mov    dx,offset options_i_msg
  173.     public    error
  174. error:
  175.     mov    ah,9
  176.     int    21h
  177.     mov    ax,4c0ah        ; give errorlevel 10
  178.     int    21h
  179.  
  180. ;;;    include    timeout.asm
  181.  
  182.     public    start_1
  183. start_1:
  184.     cld
  185.  
  186. ;** First, print a few welcoming messages.
  187.  
  188.     mov    dx,offset copyright_msg
  189.     mov    ah,9
  190.     int    21h
  191.  
  192.     mov    dx,offset copyleft_msg
  193.     mov    ah,9
  194.     int    21h
  195.  
  196.     mov    dx,offset branding_msg
  197.     mov    ah,9
  198.     int    21h
  199.  
  200. ;** Identify the bus type (EISA, 8-bit ISA, 16-bit ISA, MCA)
  201.  
  202.     mov    dx,0f000h        ;ROM segment
  203.     mov    es,dx
  204.     mov    di,0ffd9h
  205.     mov    si,offset eisa_signature
  206.     mov    cx,2
  207.     repe    cmpsw
  208.     jne    not_eisa
  209.     inc    is_eisa
  210. not_eisa:
  211.  
  212. ;
  213. ; Get the feature byte (if reliable) so we can know if it is a microchannel
  214. ; computer and how many interrupts there are.
  215. ;
  216.     mov    ah,0c0h
  217.     int    15h            ; es:bx <- sys features block
  218.     jc    look_in_ROM        ; error, must use rom.
  219.     or    ah,ah
  220.     jnz    look_in_ROM
  221.     mov    dx,es:[bx]        ; # of feature bytes
  222.     cmp    dx,4            ; do we have the feature byte we want?
  223.     jae    got_features        ;yes.
  224. look_in_ROM:
  225.     cmp    byte ptr es:[0fffeh],0fch;is this an AT?
  226.     jne    identified        ;no.
  227.     or    sys_features,TWO_8259    ; ATs have 2nd 8259
  228.     jmp    short identified    ; assume no microchannel
  229. got_features:
  230.     mov    ah,es:[bx+2]        ; model byte
  231.     cmp    ah,0fch
  232.     je    at_ps2
  233.     ja    identified        ; FD, FE and FF are not ATs
  234.     cmp    ah,0f8h
  235.     je    at_ps2
  236.     ja    identified        ; F9, FA and FB are not ATs
  237.     cmp    ah,09ah
  238.     jbe    identified        ; old non-AT Compacs go here
  239. at_ps2:                    ; 9B - F8 and FC are assumed to
  240.     mov    ah,es:[bx+5]        ;   have reliable feature byte
  241.     mov    sys_features,ah
  242. identified:
  243.  
  244. ;** Identify which processor we're running on.
  245.  
  246. ;Determine the processor type.  The 8088 and 8086 will actually shift ax
  247. ;over by 33 bits, while the 80[123]86 use a shift count mod 32.
  248.     mov    cl,33
  249.     mov    ax,0ffffh
  250.     shl    ax,cl            ;186 or better?
  251.     jz    processor_identified    ;no.
  252.     mov    is_186,1
  253.  
  254.     push    sp
  255.     pop    ax
  256.     cmp    ax,sp            ;286 or better?
  257.     jne    processor_identified    ;no.
  258.     mov    is_286,1
  259.  
  260.     pushf
  261.     pop    ax
  262.     or    ax,7000h        ;the 386 lets us set these bits
  263.     push    ax
  264.     popf                ;this should be a real popf.
  265.     pushf
  266.     pop    ax
  267.     test    ax,7000h        ;did the bits get set?
  268.     je    processor_identified
  269.     mov    is_386,1
  270.  
  271. processor_identified:
  272.  
  273. ;** Parse the command line.
  274.  
  275.     mov    si,offset phd_dioa+1
  276.     call    skip_blanks        ;end of line?
  277.     cmp    al,CR
  278.     je    usage_error_j_1
  279.  
  280. chk_options:
  281.  
  282. ;** Look for -<single-letter> options.
  283.  
  284.     call    skip_blanks
  285.     cmp    al,'-'            ; any options?
  286.     jne    no_more_opt
  287.     inc    si            ; skip past option char
  288.     lodsb                ; read next char
  289.     or    al,20h            ; convert to lower case
  290.     cmp    al,'d'
  291.     jne    not_d_opt
  292.     or    flagbyte,D_OPTION
  293.     jmp    chk_options
  294. not_d_opt:
  295.     cmp    al,'n'
  296.     jne    not_n_opt
  297.     or    flagbyte,N_OPTION
  298.     jmp    chk_options
  299. not_n_opt:
  300.     cmp    al,'w'
  301.     jne    not_w_opt
  302.     or    flagbyte,W_OPTION
  303.     jmp    chk_options
  304. not_w_opt:
  305.     cmp    al,'p'
  306.     jne    not_p_opt
  307.     cmp    rcv_modes,6        ;do they even *have* a promiscuous mode?
  308.     jbe    chk_options        ;no.
  309.     mov    rcv_modes+2[6*2],0    ;yes, nuke it.
  310.     jmp    chk_options
  311. not_p_opt:
  312.     cmp    al,'u'
  313.     jne    not_u_opt
  314.     or    flagbyte,U_OPTION
  315.     jmp    chk_options
  316. not_u_opt:
  317.     cmp    al,'i'
  318.     jne    not_i_opt
  319.     cmp    word ptr driver_class,BLUEBOOK + IEEE8023*256    ;both present?
  320.     mov    dx,offset no_ieee_msg
  321.     jne    usage_error_j_1        ;no - give error
  322.     mov    word ptr driver_class,IEEE8023 + BLUEBOOK*256    ;yes, swap them.
  323.     jmp    chk_options
  324. not_i_opt:
  325. usage_error_j_1:
  326.     jmp    usage_error
  327. no_more_opt:
  328.  
  329. ;** get the packet driver interrupt number.
  330.  
  331.     mov    di,offset entry_point    ;parse the packet interrupt number
  332.     call    get_number        ;  for them.
  333.  
  334. ;** see if they wanted to terminate the existing driver.
  335.  
  336.     test    flagbyte,U_OPTION    ;should we terminate the driver?
  337.     jne    terminate
  338.     jmp    not_terminate
  339. terminate:
  340.  
  341.     cmp    entry_point,0        ;did they ask for the default?
  342.     jne    terminate_int_ok    ;no, run with it.
  343.  
  344. ;**Look for the existing packet driver interrupt
  345.  
  346.     mov    entry_point,60h
  347. terminate_check_int:
  348.     call    verify_packet_int
  349.     jc    terminate_check_int_1
  350.     jne    terminate_check_int_1
  351.     cmp    entry_point_fnd,0    ;did we already find one?
  352.     jne    terminate_check_int_2    ;yes, it's ambiguous - give error.
  353.     mov    al,entry_point        ;no, remember it.
  354.     mov    entry_point_fnd,al
  355. terminate_check_int_1:
  356.     inc    entry_point        ;go look at the next one
  357.     cmp    entry_point,80h
  358.     jbe    terminate_check_int    ;keep going to the end.
  359.  
  360.     mov    al,entry_point_fnd    ;restore the last one found.
  361.     mov    entry_point,al
  362.     cmp    entry_point_fnd,0    ;did we find one?
  363.     jne    terminate_int_ok    ;yes.
  364.     mov    dx,offset no_pkt_msg    ;no packet drivers installed!
  365.     jmp    error
  366. terminate_check_int_2:
  367.     mov    dx,offset two_pkts_msg    ;two packet drivers - which one??
  368.     jmp    error
  369.  
  370. terminate_int_ok:
  371.     call    verify_packet_int    ;is the one they specified acceptable?
  372.     jnc    terminate_1        ;no, it's not in range.
  373.     jmp    error
  374. terminate_1:
  375.     je    terminate_2        ;go if we found a signature.
  376.     mov    dx,offset no_pkint_msg    ;no packet driver there.
  377.     jmp    already_error_1
  378. terminate_2:
  379.  
  380.     mov    their_isr.offs,bx
  381.     mov    their_isr.segm,es
  382.  
  383.     mov    ax,1ffh            ;driver_info
  384.     pushf
  385.     cli
  386.     call    their_isr
  387.     call    fatal_error
  388.     movseg    ds,cs
  389.  
  390.     mov    ah,2            ;access_type
  391.     mov    al,ch            ;their class from driver_info().
  392.     mov    bx,dx            ;their type from driver_info().
  393.     mov    dl,cl            ;their number from driver_info().
  394.     mov    cx,2            ;use type length 2.
  395.     mov    si,offset bogus_type
  396.     movseg    es,cs
  397.     mov    di,offset our_recv
  398.     pushf
  399.     cli
  400.     call    their_isr
  401.     call    fatal_error
  402.     mov    handle,ax
  403.  
  404.     mov    ah,5            ;terminate the driver.
  405.     mov    bx,handle
  406.     pushf
  407.     cli
  408.     call    their_isr
  409.     jnc    now_close
  410.     call    print_error
  411.  
  412.     mov    ah,3            ;release_type
  413.     mov    bx,handle
  414.     pushf
  415.     cli
  416.     call    their_isr
  417.     int    20h
  418. now_close:
  419.     mov    dx,offset terminated_msg
  420.     mov    ah,9
  421.     int    21h
  422.     int    20h
  423.  
  424. usage_error_j_2:
  425.     jmp    usage_error
  426. not_terminate:
  427.  
  428. ;** ask the driver to parse any remaining parameters.
  429.  
  430.     call    parse_args
  431.     jc    usage_error_j_2
  432.  
  433.     call    skip_blanks        ;end of line?
  434.     cmp    al,CR
  435.     jne    usage_error_j_2
  436.  
  437.     call    verify_packet_int
  438.     jnc    packet_int_ok
  439.     jmp    error
  440. packet_int_ok:
  441.     jne    packet_int_unused
  442.     jmp    already_error        ;give an error if there's one there.
  443. packet_int_unused:
  444.  
  445. ;** Verify that the hardware interrupt number they gave is valid.
  446.  
  447.     cmp    int_no,15        ;can't possibly be > 15.
  448.     ja    int_bad
  449.     test    sys_features,TWO_8259    ; 2nd 8259 ?
  450.     jnz    int_ok            ;yes, no need to check for <= 7.
  451.     mov    int_msg_num,'7'+' '*256    ;correct the error message, just in case.
  452.     cmp    int_no,7        ;make sure that the packet interrupt
  453.     jbe    int_ok_7        ;  number is in range.
  454. int_bad:
  455.     mov    dx,offset int_msg
  456.     jmp    error
  457. int_ok_7:
  458.  
  459. ;** IRQ 5 on an XT is not available -- it's used by the hard disk.
  460.     cmp    int_no,5        ;Are they trying to use irq 5 on an XT?
  461.     jne    int_ok            ;no.
  462.  
  463.     push    ds
  464.     mov    ax,40h
  465.     mov    ds,ax
  466.     mov    al,ds:[75h]        ;get the number of hard disks.
  467.     pop    ds
  468.  
  469.     or    al,al            ;do they have one?
  470.     je    int_ok            ;unbelievably, no.
  471.     mov    dx,offset xt_hd_warn_msg
  472.     mov    ah,9
  473.     int    21h
  474. int_ok:
  475.  
  476. ;
  477. ; Map IRQ 2 to IRQ 9 if needed.
  478. ;
  479.     test    sys_features,TWO_8259    ; 2nd 8259 ?
  480.     je    no_mapping_needed    ;no, no mapping needed
  481.     cmp    int_no,2        ;map IRQ 2 to IRQ 9.
  482.     jne    no_mapping_needed
  483.     mov    int_no,9
  484. no_mapping_needed:
  485.  
  486. ; If they chose the -d option, don't call etopen when we are loaded,
  487. ; but when we are called for the first time
  488. ;
  489. ; Save part of the tail, needed by delayed etopen
  490.     test    flagbyte,D_OPTION
  491.     jz    open_now
  492.     mov    memory_to_keep,offset end_tail_1    ; save first part of tail
  493.     jmp    delayed_open_1
  494. open_now:
  495.     call    etopen            ;init the driver.  If any errors,
  496.                     ;this routine returns cy.
  497.     jnc    yes_resident
  498.     jmp    no_resident
  499.  
  500. yes_resident:
  501.  
  502. ;** etopen has set rom_address to their hardware address.  Set our copy of
  503. ;** the current address.
  504.  
  505.     mov    si,offset rom_address    ;copy their original address to
  506.     movseg    es,ds
  507.     mov    di,offset my_address    ;  their current address.
  508.     mov    cx,MAX_ADDR_LEN/2
  509.     rep    movsw
  510.  
  511. ;** tell them what kind of system they have.
  512.     mov    dx,offset system_msg
  513.     mov    ah,9
  514.     int    21h
  515.  
  516.     mov    dx,offset i386_msg
  517.     cmp    is_386,0
  518.     jne    have_processor
  519.     mov    dx,offset i286_msg
  520.     cmp    is_286,0
  521.     jne    have_processor
  522.     mov    dx,offset i186_msg
  523.     cmp    is_186,0
  524.     jne    have_processor
  525.     mov    dx,offset i8088_msg
  526. have_processor:
  527.     mov    ah,9
  528.     int    21h
  529.  
  530.     mov    dx,offset mca_msg
  531.     test    sys_features,SYS_MCA
  532.     jne    have_bus
  533.     mov    dx,offset eisa_msg
  534.     cmp    is_eisa,0
  535.     jne    have_bus
  536.     mov    dx,offset isa_msg
  537. have_bus:
  538.     mov    ah,9
  539.     int    21h
  540.  
  541.     test    sys_features,TWO_8259
  542.     je    only_one_8259
  543.     mov    dx,offset two_8259_msg
  544.     mov    ah,9
  545.     int    21h
  546. only_one_8259:
  547.  
  548.     call    crlf
  549.  
  550.     mov    di,offset entry_point
  551.     mov    dx,offset entry_point_name
  552.     call    print_number
  553.  
  554.     call    print_parameters    ;echo our parameters.
  555.     or    flagbyte,CALLED_ETOPEN
  556.  
  557.     cmp    driver_class,BLUEBOOK    ;Blue Book Ethernet?
  558.     je    print_eaddr        ;yes.
  559.     cmp    driver_class,IEEE8023    ;IEEE 802.3 Ethernet?
  560.     jne    print_addr_2        ;no, don't print what we don't have.
  561.  
  562. print_eaddr:
  563.     mov    dx,offset eaddr_msg
  564.     mov    ah,9
  565.     int    21h
  566.  
  567.     mov    si,offset rom_address
  568.     call    print_ether_addr
  569.  
  570.     call    crlf
  571.  
  572. print_addr_2:
  573.  
  574.     cmp    driver_class,8        ;ARCnet?
  575.     jne    print_addr_3        ;no, don't print what we don't have.
  576.  
  577.     mov    dx,offset aaddr_msg
  578.     mov    ah,9
  579.     int    21h
  580.  
  581.     mov    al,rom_address
  582.     mov    cl,' '            ;Don't eliminate leading zeroes.
  583.     call    byteout
  584.  
  585.     call    crlf
  586.  
  587. print_addr_3:
  588. delayed_open_1:
  589.  
  590. ;** Take care of installing ourselves in memory.
  591.  
  592.     mov    ah,35h            ;remember their packet interrupt.
  593.     mov    al,entry_point
  594.     int    21h
  595.     mov    their_isr.offs,bx
  596.     mov    their_isr.segm,es
  597.  
  598.     mov    ah,25h            ;install our packet interrupt
  599.     mov    dx,offset our_isr
  600.     int    21h
  601.  
  602.     mov    ah,49h            ;free our environment, because
  603.     mov    es,phd_environ        ;  we won't need it.
  604.     int    21h
  605.  
  606.     mov    bx,1            ;get the stdout handle.
  607.     mov    ah,3eh            ;close it in case they redirected it.
  608.     int    21h
  609.  
  610.     test    flagbyte,D_OPTION
  611.     jne    f_release_type_1    ;no.
  612.     cmp    rcv_modes+2[3*2],0    ;does mode 3 exist?
  613.     je    f_release_type_1    ;no.
  614.     call    rcv_modes+2[3*2]    ;  call it.
  615. f_release_type_1:
  616.  
  617.     mov    dx,memory_to_keep    ;keep the greater of this and
  618.     cmp    dx,free_mem        ;  free_mem.
  619.     jae    go_resident
  620.     mov    dx,free_mem
  621. go_resident:
  622.     add    dx,0fh            ;round up to next highest paragraph.
  623.     mov    cl,4
  624.     shr    dx,cl
  625.     mov    ah,31h            ;terminate, stay resident.
  626.     mov    al,etopen_diagn        ; errorlevel (0 - 9, just diagnostics)
  627.     int    21h
  628.  
  629. no_resident:
  630.     mov    ah,9            ;print their error message.
  631.     int    21h
  632.  
  633.     mov    dx,offset no_resident_msg
  634.     mov    ah,9
  635.     int    21h
  636.  
  637.     mov    ax,4c00h + 32        ; give errorlevel 32
  638.     cmp    al,etopen_diagn
  639.     ja    no_et_diagn        ; etopen gave specific reason?
  640.     mov    al,etopen_diagn        ; yes, use that for error level
  641. no_et_diagn:
  642.     int    21h
  643.  
  644. ;             Suggested errorlevels:
  645. ;
  646. ; _____________________  0 = normal
  647. ;              1 = unsuitable memory address given; corrected
  648. ; In most cases every-     2 = unsuitable IRQ level given; corrected
  649. ; thing should work as     3 = unsuitable DMA channel given; corrected
  650. ; expected for lev 1-5     4 = unsuitable IO addr given; corrected (only 1 card)
  651. ; _____________________     5 = packet driver for this int # already loaded
  652. ; External errors, when    20 = general cable failure (but pkt driver is loaded)
  653. ; corrected normal    21 = network cable is open             -"-
  654. ; operation starts    22 = network cable is shorted          -"-
  655. ; _____________________ 23 = 
  656. ; Packet driver not    30 = usage message
  657. ; loaded. A new load    31 = arguments out of range
  658. ; attempt must be done    32 = unspecified device initialization error
  659. ;            33 = 
  660. ;            34 = suggested memory already occupied
  661. ;            35 = suggested IRQ already occupied
  662. ;            36 = suggested DMA channel already occupied
  663. ;            37 = could not find the network card at this IO address
  664.  
  665.  
  666.     include    verifypi.asm
  667.     include    getnum.asm
  668.     include    getdig.asm
  669.     include    skipblk.asm
  670.     include    printea.asm
  671.     include    pkterr.asm
  672.     include    getenv.asm
  673.  
  674.     public    branding_msg
  675. branding_msg    db    '$'
  676.  
  677. code    ends
  678.  
  679.     end
  680.