home *** CD-ROM | disk | FTP | other *** search
/ Chip 1994 February / CHIP0294.ISO / digital / magazin / trumpet / pktdrvs / smc_wd.asm < prev    next >
Encoding:
Assembly Source File  |  1993-12-14  |  20.7 KB  |  773 lines

  1. ;History:133,1
  2. version    equ    8
  3.  
  4.     include    defs.asm
  5.  
  6. ;  The following people have contributed to this code: David Horne, Eric
  7. ;  Henderson, Bob Clements, Reinhard Strebler, Jan Engvald LDC, and Paul
  8. ;  Kranenberg.
  9.  
  10. ;  Copyright, 1988-1992, Russell Nelson, Crynwr Software
  11.  
  12. ;   This program is free software; you can redistribute it and/or modify
  13. ;   it under the terms of the GNU General Public License as published by
  14. ;   the Free Software Foundation, version 1.
  15. ;
  16. ;   This program is distributed in the hope that it will be useful,
  17. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. ;   GNU General Public License for more details.
  20. ;
  21. ;   You should have received a copy of the GNU General Public License
  22. ;   along with this program; if not, write to the Free Software
  23. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  
  25. code    segment    byte public
  26.     assume    cs:code, ds:code
  27.  
  28. ; Stuff specific to the Western Digital WD8003E Ethernet controller board
  29. ; C version by Bob Clements, K1BC, May 1988 for the KA9Q TCP/IP package
  30.  
  31. ; The EN registers - First, the board registers
  32.  
  33. EN_CMD        equ    000h    ; Board's command register
  34. EN_REG1        equ    001h    ; 8013 bus size register
  35. EN_REG5        equ    005h    ; New command register (REGISTER 5)
  36. EN_REG6        equ    006h    ; Ultra interrupt control register
  37. EN_SAPROM    equ    008h    ; Window on station addr prom
  38. EN_REGE        equ    00eh    ; Board Id (code) byte
  39.  
  40. EN_OFF        equ    10h
  41.  
  42. ENDCFG_BM8    equ    48h
  43.  
  44.     include movemem.asm
  45.     include    8390.inc
  46.  
  47. ; Board commands in EN_CMD
  48. EN_RESET    equ    080h    ; Reset the board
  49. EN_MEMEN    equ    040h    ; Enable the shared memory
  50. EN_MEM_MASK    equ    03fh    ; B18-B13 of address of the shared memory
  51.  
  52. ; Bits in REG1
  53. ENR1_BUS16BIT    equ    001h    ; Bus is 16 bits
  54.  
  55. ; Commands for REG5 register
  56. ENR5_MEM16EN    equ    080h    ; Enable 16 bit memory access from bus (8013)
  57. ENR5_LAN16EN    equ    040h    ; Enable 16 bit memory access from chip (8013)
  58. ENR5_MEM_MASK    equ    01fh    ; B23-B19 of address of the memory (8013)
  59. ENR5_LA19    equ    001h    ; B19 of address of the memory (8013)
  60. ENR5_EIL    equ    004h    ; Enable 8390 interrupts to bus (microchannel)
  61.  
  62. ; Commands for REG6 register
  63. ENR6_EIL    equ    001h    ; Enable 8390 interrupts to bus (Ultra)
  64.  
  65. ; Bits in the REGE register
  66. ENRE_MICROCHANEL equ    080h    ; Microchannel bus (vs. PC/AT)
  67. ENRE_LARGERAM    equ    040h    ; Large RAM
  68. ENRE_SOFTCONFIG    equ    020h    ; Soft config
  69. ENRE_REVMASK    equ    01eh    ; Revision mask
  70. ENRE_ETHERNET    equ    001h    ; Ethernet (vs. Starlan)
  71.  
  72. ; Shared memory management parameters
  73.  
  74. SM_TSTART_PG    equ    0    ; First page of TX buffer
  75. SM_RSTART_PG    equ    6    ; Starting page of ring
  76. SM_RSTOP_PG    equ    32    ; Last page +1 of ring
  77.  
  78. ; End of WD8003E parameter definitions
  79.  
  80. board_features    db    0    ; Board features
  81. BF_MEM16EN    equ    1    ; 16-bit board, enable 16-bit memory
  82. BF_16K        equ    2    ; Board has 16 KB or shared memory
  83. BF_584        equ    4    ; Board has 584 interface chip
  84. BF_NIC_690    equ    32    ; Board has 690 NIC chip
  85.  
  86. pause_    macro
  87. ;    jmp    $+2
  88. ;
  89. ; The reason for the pause_ macro is to establish a minimum time between
  90. ; accesses to the card hardware. The assumption is that the fetch and execution
  91. ; of the jmp $+2 instruction will provide this time. In a fast cache machine
  92. ; this may be a false assumption. In a fast cache machine, there may be 
  93. ; NO REAL TIME DIFFERENCE between the two I/O instruction streams below:
  94. ;
  95. ;    in    al,dx        in    al,dx
  96. ;    jmp    $+2
  97. ;    in    al,dx        in    al,dx
  98. ;
  99. ; To establish a minimum delay, an I/O instruction must be used. A good rule of
  100. ; thumb is that ISA I/O instructions take ~1.0 microseconds and MCA I/O
  101. ; instructions take ~0.5 microseconds. Reading the NMI Status Register (0x61)
  102. ; is a good way to pause on all machines.
  103. ;
  104. ; The National 8390 Chip (NIC) requires 4 bus clocks between successive
  105. ; chip selects (National DP8390 Data Sheet Addendum, June 1990 -- it took them
  106. ; long enough to figure this out and tell everyone) or the NIC behaves badly.
  107. ; Therefor one I/O instruction should be inserted between each successive
  108. ; NIC I/O instruction that could occur 'back - to - back' on a fast cache
  109. ; machine.
  110. ;   - gft - 910529
  111. ;
  112.     push    ax
  113.     in    al, 61h
  114.     pop    ax
  115. ;
  116. endm
  117.  
  118. reset_8390    macro
  119.     loadport        ; First, pulse the board reset
  120.     setport    EN_CMD
  121.     mov    al,EN_RESET        ;Turn on board reset bit
  122.     out    dx,al
  123.     longpause
  124.     xor    al,al            ;Turn off board reset bit
  125.     out    dx,al
  126.     setport    EN_REG5
  127.     mov    al,ENR5_EIL
  128.     test    sys_features,SYS_MCA
  129.     jz    reset_no_mc
  130.     out    dx,al            ; enable 8390 interrupts to bus
  131. reset_no_mc:
  132.     setport    EN_REG6
  133.     mov    al,ENR6_EIL
  134.     out    dx,al
  135.     endm
  136.  
  137.  
  138. terminate_board    macro
  139.     endm
  140.  
  141. ; The following three values may be overridden from the command line.
  142. ; If they are omitted from the command line, these defaults are used.
  143.  
  144.     public    int_no, io_addr, mem_base
  145. int_no        db    3,0,0,0        ; Interrupt level
  146. io_addr        dw    0280h,0        ; I/O address for card (jumpers)
  147. mem_base    dw    0d000h,0    ; Shared memory addr (software)
  148.  
  149.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  150. driver_class    db    BLUEBOOK, IEEE8023, 0        ;from the packet spec
  151. driver_type    db    14        ;from the packet spec
  152. driver_name    db    'SMC_WD',0    ;name of the driver.
  153. driver_function    db    2
  154. parameter_list    label    byte
  155.     db    1    ;major rev of packet driver
  156.     db    9    ;minor rev of packet driver
  157.     db    14    ;length of parameter list
  158.     db    EADDR_LEN    ;length of MAC-layer address
  159.     dw    GIANT    ;MTU, including MAC headers
  160.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  161.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  162.     dw    0    ;(# of successive xmits) - 1
  163. int_num    dw    0    ;Interrupt # to hook for post-EOI
  164.             ;processing, 0 == none,
  165.  
  166.     extrn    sys_features: byte
  167.  
  168. block_output:
  169. ;enter with cx = byte count, ds:si = buffer location, ax = buffer address
  170.     assume    ds:nothing
  171.     mov    es,mem_base        ; Set up ES:DI at the shared RAM
  172.     mov    di,ax            ; ..
  173. ; Can't use movemem which word aligns to the source, but needs to word
  174. ; align to the destination writing to WD8003ET/A. Fortunately works for
  175. ; all cards.
  176.     inc    cx        ; if odd bytes round up.
  177.     and    cx,not 1
  178.     call    rcopy_subr
  179.  
  180.     clc
  181.     ret            ; End of transmit-start routine
  182.  
  183. block_input:
  184. ;enter with cx = byte count, es:di = buffer location, ax = board address.
  185. ; Old version checked size, memory space, queue length here. Now done
  186. ; in higher level code.
  187. ; Set cx to length of this frame.
  188.     assume    ds:nothing,es:nothing
  189.     push    ds
  190.     mov    ds,mem_base        ; ds:si points at first byte to move
  191.     mov    si,ax
  192.  
  193.     cmp    cx,GIANT
  194.     jbe    rcv_size_ok        ; is the size sane? 
  195.     cmp    ch,cl            ; is it starlan bug (dup of low byte)
  196.     jne    rcv_size_not_ok        ; no.
  197. ;fix the starlan bug
  198.     mov    ch,ds:[si+EN_RBUF_NXT_PG] ; Page after this frame
  199.     cmp    ch,bl
  200.     ja    rcv_frm_no_wrap
  201.     add    ch,byte ptr cs:sm_rstop_ptr        ; Wrap if needed
  202.     dec    ch
  203. rcv_frm_no_wrap:
  204.     sub    ch,bl
  205.     dec    ch
  206.     cmp    cx,GIANT
  207.     jbe    rcv_size_ok        ; is the size sane? 
  208. rcv_size_not_ok:
  209.     mov    cx,GIANT        ; no, restore sanity.
  210. rcv_size_ok:
  211.  
  212.     add    ax,cx            ; Find the end of this frame.
  213.     cmp    ah,byte ptr cs:sm_rstop_ptr ; Over the top of the ring?
  214.     jb    rcopy_one_piece        ; Go move it
  215.  
  216. rcopy_wrap:
  217. ; Copy in two pieces due to buffer wraparound.
  218.     mov    ah,byte ptr cs:sm_rstop_ptr ; Compute length of first part
  219.     xor    al,al
  220.     sub    ax,si            ;  as all of the pages up to wrap point
  221.     sub    cx,ax            ; Move the rest in second part
  222.     push    cx            ; Save count of second part
  223.     mov    cx,ax            ; Count for first move
  224.     call    rcopy_subr
  225.     mov    si,SM_RSTART_PG*256    ; Offset to start of first receive page
  226.     pop    cx            ; Bytes left to move
  227. rcopy_one_piece:
  228.     call    rcopy_subr
  229.     pop    ds
  230.     ret
  231.  
  232.  
  233. rcopy_subr:
  234.     test    board_features,BF_MEM16EN; Is this a WD8013?
  235.     je    sm_wd8003        ; no, no need to enable 16-bit access.
  236.     loadport            ; Base of device
  237.     setport    EN_REG5            ; Enable 16-bit access
  238.     mov    al,ENR5_MEM16EN+ENR5_LAN16EN+ENR5_LA19
  239.     out    dx,al
  240.     call    movemem            ; Copy packet
  241.     mov    al,ENR5_LAN16EN+ENR5_LA19 ; Disable 16-bit access to WD8013
  242.     out    dx,al
  243.     ret
  244. sm_wd8003:
  245.     call    movemem            ; Copy packet
  246.     ret
  247.  
  248.  
  249.     include    8390.asm
  250.  
  251.     public    usage_msg
  252. usage_msg    db    "usage:",CR,LF
  253.         db    "   SMC_WD [options] <packet_int_no> [-o] <hardware_irq> <io_addr> <mem_base>",CR,LF,'$'
  254.  
  255.     public    copyright_msg
  256. copyright_msg   db      "Packet driver for SMC/WD/IBM Ethernet adapters, version "
  257.         db    '0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,".",'0'+dp8390_version,CR,LF
  258.         db    "Portions Copyright 1988, Robert C. Clements, K1BC",CR,LF
  259.         db    "Portions Copyright 1992, 1993, Crynwr Software",CR,LF,'$'
  260.  
  261. not_our_msg    label    byte
  262.     db    "The memory present at this address does not belong to WD/SMC/IBM",CR,LF,'$'
  263. no_board_msg    label    byte
  264.     db    "WD/SMC/IBM apparently not present at this memory address.",CR,LF,'$'
  265. bad_cksum_msg    label    byte
  266.     db    "WD/SMC/IBM not at this I/O address (or address PROM bad).  Re-set parameters",CR,LF
  267.     db    "with EZSETUP, or check jumpers.",CR,LF,'$'
  268. bad_board_msg    label    byte
  269.     db    "Suggested WD/SMC/IBM memory address is invalid.",CR,LF,'$'
  270. occupied_msg    label    byte
  271.     db    "Suggested WD/SMC/IBM memory address already occupied.",CR,LF,'$'
  272. addr_bad_msg    db    "Memory address should be less than 65536.",CR,LF,'$'
  273. using_16bits    db    "Accessing the board using 16 bits of data.",CR,LF,'$'
  274. needs_16k_msg    db    "Please reconfigure the board to use 16K of RAM",CR,LF,'$'
  275. int_no_name    db    "Interrupt number ",'$'
  276. io_addr_name    db    "I/O port ",'$'
  277. mem_base_name    db    "Memory address ",'$'
  278. nic_name    db    "NIC ",'$'
  279.  
  280. occupied_switch    db    0        ;if zero, don't use occupied test.
  281. nic_number    dw    ?
  282.  
  283.     extrn    set_recv_isr: near
  284.     extrn    skip_blanks: near
  285.  
  286. ;enter with si -> argument string, di -> word to store.
  287. ;if there is no number, don't change the number.
  288.     extrn    get_number: near
  289.  
  290. ;enter with dx -> name of word, di -> dword to print.
  291.     extrn    print_number: near
  292.  
  293. ;enter with dx:ax = number to print
  294.     extrn    decout: near
  295.  
  296. ;print a crlf.
  297.     extrn    crlf: near
  298.  
  299.     public    parse_args
  300. parse_args:
  301.     call    skip_blanks
  302.     cmp    al,'-'            ;did they specify a switch?
  303.     jne    not_switch
  304.     cmp    byte ptr [si+1],'o'    ;did they specify '-o'?
  305.     je    got_occupied_switch
  306.     stc                ;no, must be an error.
  307.     ret
  308. got_occupied_switch:
  309.     mov    occupied_switch,1
  310.     add    si,2            ;skip past the switch's characters.
  311.     jmp    parse_args        ;go parse more arguments.
  312. not_switch:
  313.     test    sys_features,SYS_MCA
  314.     jnz    do_mc_defaults
  315.     jmp    just_parse_args
  316. do_mc_defaults:
  317.  
  318. ; channel selector resides at io 96h
  319. ; POS register base is at io 100h
  320. ; WD8003E ID is one of 6FC0h, 6FC1h or 6FC2h
  321. ; SMC ID is one of 61c8h or 61c9h.
  322. ; IBM Ethernet Adapter A is EFE5h
  323.  
  324. ; search thro' the slots for a wd8003e card
  325.     mov    cx, 8            ; for all channels(slots)
  326.  
  327. ; channel select value for slots 0,1,2.. is 8,9,A etc
  328. ; start with slot 0, and then 7,6,5,4,3,2,1
  329. get_05:
  330.     mov    ax, cx            ; channel number
  331.     or    ax, 08h         ; reg. select value
  332.     mov    dx, 96h         ; channel select register
  333.     out    dx, al            ; select channel
  334.  
  335. ; read adapter id
  336.     mov    dx, 101h
  337.     in    al, dx            ; adapter id - ms byte
  338.     mov    ah, al
  339.     dec    dx
  340.     in    al, dx            ; adapter id - ls byte
  341.  
  342. ; Check if wd8003e
  343.     cmp    ax, 06FC0h        ;WD8003E/A or WD8003ET/A
  344.     je    get_10
  345.     cmp    ax, 06FC1h        ;WD8003ST/A (Starlan)
  346.     je    get_10
  347.     cmp    ax, 06FC2h        ;WD8003W/A
  348.     je    get_10
  349. ;SMC's new IDs:
  350.     cmp     ax, 061C8h        ;WD8013EP/A
  351.     je      get_20
  352.     cmp     ax, 061C9h        ;WD8013WP/A
  353.     je      get_20
  354. ; Check if IBM Ethernet Adapter A
  355.     cmp     ax, 0EFE5h        ;long card
  356.     je      get_12
  357.     cmp     ax, 0EFD4h        ;short card, BNC
  358.     je      get_20
  359.     cmp     ax, 0EFD5h        ;short card, RJ_45
  360.     je      get_20
  361.     loop    get_05
  362.  
  363.     mov    dx,offset no_WD8003E_msg
  364.     mov    etopen_diagn,37
  365.     stc
  366.     ret
  367.  
  368. no_WD8003E_msg:
  369.     db    "WD/SMC/IBM board apparently not found.",CR,LF,'$'
  370.  
  371. int_xlate db    03,04,10,15
  372.  
  373. get_20:
  374.     jmp    get_21
  375.  
  376. get_10:
  377. ; found our Adapter
  378.  
  379. ; Get WD8003E I/O Address ( read POS Register 0 )
  380.     mov    dx,102h
  381.     in    al,dx
  382.     and    ax,0F0h
  383.     jmp    short get_17
  384. get_12:
  385. ; Get long Ethernet Adapter/A I/O address
  386.     mov    dx,102h
  387.     in    al,dx
  388.     and    ax,0FEh
  389. get_17:
  390.     mov    cl,4
  391.     shl    ax,cl
  392.     mov    io_addr,ax
  393. ; Get WD8003E shared RAM memory address (read POS Register 1 )
  394.     xor    ax,ax
  395.     mov    dx,103h
  396.     in    al,dx
  397.     and    al,0FCh
  398.     xchg    al,ah
  399.     mov    mem_base,ax
  400. ; Get WD8003E IRQ (read POS Register 3 )
  401.     xor    ax,ax
  402.     mov    dx,105h
  403.     in    al,dx
  404.     and    al,003h
  405.     mov    bx,offset int_xlate
  406.     xlat
  407.     mov    int_no,al
  408.     jmp    short just_parse_args
  409.  
  410. int_xlate_20    db    03,04,10,14
  411.  
  412. get_21:
  413. ; Get short Ethernet Adapter/A I/O Address ( read POS Register 0 )
  414.     mov    dx,102h
  415.     in    al,dx
  416.     and    ax,00F0h
  417.     or    al,08h
  418.     xchg    al,ah
  419.     mov    io_addr,ax
  420. ; Get short Ethernet Adapter/A shared RAM memory address (read POS Register 1 )
  421.     mov    dx,103h
  422.     in    al,dx
  423.     test    al,10000b
  424.     je    get_21_needs_16k
  425.     and    ax,0fh
  426.     shl    al,1
  427.     or    al,0c0h
  428.     xchg    al,ah
  429.     mov    mem_base,ax
  430. ; Get short Ethernet Adapter/A IRQ (read POS Register 3 )
  431.     xor    ax,ax
  432.     mov    dx,105h
  433.     in    al,dx
  434.     shr    al,1
  435.     shr    al,1
  436.     and    al,003h
  437.     mov    bx,offset int_xlate_20
  438.     xlat
  439.     mov    int_no,al
  440.  
  441. just_parse_args:
  442.     mov    di,offset int_no
  443.     call    get_number
  444.     mov    di,offset io_addr
  445.     call    get_number
  446.     mov    di,offset mem_base
  447.     call    get_number
  448.     clc
  449.     ret
  450.  
  451. get_21_needs_16k:
  452.     mov    dx,offset needs_16k_msg
  453.     mov    ah,9
  454.     int    21h
  455.     stc
  456.     ret
  457.  
  458.     extrn    etopen_diagn: byte
  459. addr_not_avail:
  460.     mov    dx,offset occupied_msg
  461.     mov    etopen_diagn,34
  462.     stc
  463.     ret
  464. bad_cksum:
  465.     mov    dx,offset bad_cksum_msg
  466.     mov    etopen_diagn,37
  467.     stc
  468.     ret
  469. bad_memory:
  470.     mov    dx,offset bad_board_msg
  471.     mov    etopen_diagn,37
  472.     stc
  473.     ret
  474. not_our_memory:
  475.     mov    dx,offset not_our_msg
  476.     mov    etopen_diagn,37
  477.     stc
  478.     ret
  479. no_memory:
  480.     mov    dx,offset no_board_msg
  481.     mov    etopen_diagn,37
  482.     stc
  483.     ret
  484.  
  485. ENC_PAGE2    equ    080h        ; select page 2 of chip registers
  486. TCR_TST_690    equ    018h        ; 690 xmit config test value
  487.  
  488. test_tcr:
  489. ;see if TXCR, when modified, also appears on page 2.
  490. ;enter with the bit value to test in cl.
  491.     loadport
  492.     setport    EN_CCMD            ; select page 0.
  493.     pause_
  494.     mov    al, ENC_PAGE0 + ENC_NODMA + ENC_STOP
  495.     out    dx,al
  496.  
  497.     setport    EN0_TXCR        ; write test value to xmit
  498.     pause_
  499.     mov    al,cl            ; config register
  500.     out    dx,al
  501.  
  502.     setport    EN_CCMD            ; select page 2
  503.     pause_
  504.     mov    al, ENC_PAGE2 + ENC_NODMA + ENC_STOP
  505.     out    dx,al
  506.  
  507.     setport    EN0_TXCR        ; read xmit config register
  508.     pause_
  509.     in    al,dx
  510.     and    al,TCR_TST_690
  511.     cmp    al,cl
  512.     ret
  513.  
  514.  
  515. init_card:
  516. ; Now get the board's physical address from on-board PROM into card_hw_addr
  517.     assume ds:code
  518.  
  519.     mov    nic_number, 8390        ; assume 8390
  520.  
  521.   if 0    ;the following screws up on a 486/50, and the 690 support code doesn't
  522.     ;seem to be really necessary anyway.
  523.     mov    cl,0h
  524.     call    test_tcr
  525.     jne    check_690_1
  526.     mov    cl,ENTXCR_ATD
  527.     call    test_tcr
  528.     jne    check_690_1
  529.     mov    cl,ENTXCR_OFST
  530.     call    test_tcr
  531.     jne    check_690_1
  532.     mov    cl,ENTXCR_ATD or ENTXCR_OFST
  533.     call    test_tcr
  534.     je    check_690_2
  535.  
  536. check_690_1:
  537.     or    board_features, BF_NIC_690
  538.     mov    nic_number, 690        ; yes, it's a 690
  539.     mov    rcv_modes+2[4*2],0    ;nuke mode 4 -- the 690 has no hash tbl.
  540.  
  541. check_690_2:
  542.     loadport
  543.     setport    EN_CCMD            ; back to page 0
  544.     mov    al, ENC_PAGE0 + ENC_NODMA + ENC_STOP
  545.     pause_
  546.     out    dx, al
  547.  
  548.     mov    al, ENTXCR_LOOP        ; back to loopback mode
  549.     setport    EN0_TXCR
  550.     pause_
  551.     out    dx, al
  552.   endif
  553.  
  554.     test    sys_features,SYS_MCA
  555.     jz    etopen_no_mc
  556.     or    board_features,BF_16K
  557.     or    endcfg,ENDCFG_WTS
  558.     loadport
  559.     setport    EN_REG5
  560.     mov    al,ENR5_EIL
  561.     out    dx,al        ; enable 8390 interrupts to bus
  562.     jmp    etopen_have_id
  563. etopen_no_mc:            ; Check for WD8013EBT
  564.     loadport        ; WD8013EBT doesn't have register alaasing
  565.     setport    EN_CMD        ; Register 0 may be aliased to Register 8
  566.     mov bx,    dx
  567.     setport    EN_SAPROM
  568.     mov cx,    EN_SAPROM-EN_CMD ; Check 8 bytes
  569. alias_loop:
  570.     in al,    dx        ; Get one register
  571.     mov ah,    al
  572.     xchg bx, dx        ; Switch to other register
  573.     in al,    dx        ; Get other register
  574.     cmp al,    ah        ; Are they the same?
  575.     jne    not_aliased    ; Nope, not aliased
  576.     inc    bx        ; Increment register pair
  577.     inc    dx
  578.     dec    cx        ; Decrement loop counter
  579.     jne    alias_loop    ; Finished?
  580.     jmp    etopen_have_id    ; Aliased; not WD8013EBT
  581. not_aliased:            ; Not aliased; Check for 16-bit board
  582.     loadport
  583.     setport    EN_REG1        ; Bit 0 must be unmodifiable
  584.     in al,    dx        ; Get register 1
  585.     mov bl,    al        ; Store original value
  586.     xor al,    ENR1_BUS16BIT    ; Flip bit 0
  587.     out dx,    al        ; Write it back
  588.     and al,    ENR1_BUS16BIT    ; Throw other bits away
  589.     mov ah,    al        ; Store bit value
  590.     in al,    dx        ; Read register again
  591.     and al,    ENR1_BUS16BIT    ; Throw other bits away
  592.     cmp al,    ah        ; Was it modified?
  593.     jne    board16bit    ; No; board is a WD8013EBT !
  594.     mov al,    bl        ; Get original value
  595.     out dx,    al        ; Write it back
  596.     jmp    etopen_have_id
  597. board16bit:            ; But is it plugged into a 16-bit slot?
  598.     and al,    ENR1_BUS16BIT    ; Throw other bits away
  599.     je    etopen_have_id    ; Nope; silly board installer!
  600.     mov    dx,offset using_16bits
  601.     mov    ah,9
  602.     int    21h
  603.     or    board_features,BF_MEM16EN+BF_16K
  604.     or    endcfg,ENDCFG_WTS
  605.     loadport
  606.     setport    EN_REG5
  607.     mov    al,ENR5_LAN16EN+ENR5_LA19 ; Write LA19 now, but not MEM16EN
  608.     out    dx,al        ; enable 8390 interrupts to bus
  609.  
  610. etopen_have_id:
  611.  
  612.     loadport            ; base of device
  613.     setport    EN_SAPROM        ; Where the address prom is
  614.     cld                ; make sure string mode is right
  615.     movseg    es,cs
  616.     mov di,    offset rom_address
  617.     mov cx,    EADDR_LEN        ; Set count for loop
  618.     xor bx,    bx            ; Clear the addr ROM checksum
  619. ini_addr_loop:
  620.     in    al,dx            ; Get a byte of address
  621.     stosb                ; Feed it to caller
  622.     add    bl,al            ; Compute the checksum
  623.     inc    dx            ; Next byte at next I/O port
  624.     loop    ini_addr_loop        ; Loop over six bytes
  625.  
  626.     in al,    dx            ; Get seventh byte
  627.     add bl,    al            ; Add it in
  628.     inc    dx            ; Step to eighth byte
  629.     in al,    dx            ; Get last byte
  630.     add bl,    al            ; Final checksum
  631.     cmp bl, 0ffh            ; Correct?
  632.     je    good_cksum
  633.     jmp    bad_cksum        ; No, board is not happy
  634. good_cksum:
  635.  
  636.     cmp    mem_base.offs,0        ;low word of segment can't be zero.
  637.     je    mem_base_bad
  638.     cmp    mem_base.segm,0        ;high word of segment must be zero.
  639.     je    mem_base_ok
  640. mem_base_bad:
  641.     mov    dx,offset addr_bad_msg
  642.     stc
  643.     ret
  644. mem_base_ok:
  645.  
  646. ; Check if the shared memory address range is available to us
  647.     mov    bx,mem_base
  648.     cmp    occupied_switch,0    ; did they insist?
  649.     jne    no_lim_chk        ; yes, don't check.
  650.     cmp    bh,080h            ; low limit is 8000
  651.     jae    fr_8000
  652. bad_memory_j_1:
  653.     jmp    bad_memory
  654. fr_8000:
  655.     cmp    bh,0f0h            ; upper limit is F000
  656.     jae    bad_memory_j_1
  657.     test    bx,01ffh        ; must be on a 8 k boundary
  658.     jnz    bad_memory_j_1
  659. no_lim_chk:
  660.     mov    di,8*1024/16        ; 8 kbyte
  661.     mov    sm_rstop_ptr,32
  662.     test    board_features,BF_16K
  663.     jz    just_8k
  664.     test    bx,03ffh        ; must be on a 16K boundary
  665.     jnz    bad_memory_j_1
  666.     mov    di,16*1024/16        ; 16 kbytes
  667.     mov    sm_rstop_ptr,64
  668. just_8k:
  669.     cmp    occupied_switch,0    ; did they insist?
  670.     jne    is_avail        ; yes, don't check.
  671.     call    occupied_chk        ; check if address range is available
  672.     jnc    is_avail
  673.     jmp    addr_not_avail        ; we HAVE to have at least 8/16 kbyte
  674. is_avail:
  675.     test    board_features,BF_16K
  676.     jnz    not_32k
  677.     mov    di,32*1024/16        ; may be there is space for 32 kbyte
  678.     call    occupied_chk
  679.     jc    not_32k            ; no, then don't try it later either
  680.     and    bh,7
  681.     jnz    not_32k            ; must be on a 32k boundary
  682.     mov    sm_rstop_ptr,128    ; yes, there is space for a WD8003EBT
  683. not_32k:
  684.  
  685. ; Turn on the shared memory block
  686.     loadport
  687.     setport    EN_CMD        ; Point at board command register
  688.     mov ax,    mem_base    ; Find where shared memory will be mapped
  689.     mov al,    ah        ; Shift to right location
  690.     shr al,    1        ;  in the map control word
  691.     and al,    EN_MEM_MASK    ; Just these bits
  692.     or al,    EN_MEMEN    ; Command to turn on map
  693.     test    sys_features,SYS_MCA
  694.     jz    AT_card
  695.     mov    al,EN_MEMEN    ; membase handled different for MC card
  696. AT_card:
  697.     out dx,    al        ; Create that memory
  698.  
  699. ; Find how much memory this card has (without destroying other memory)
  700.     mov    si,ax            ; save bord command value
  701.     mov    es,mem_base
  702.     mov    bl,0FFH            ; first try 32 kbyte (WD8003EBT)
  703.     mov    bh,sm_rstop_ptr        ;   or what is available
  704.     dec    bh
  705. memloop:
  706.     dec    bx            ; use even address
  707.     cli                ; disable interrupts
  708.     mov    cx,es:[bx]        ; save old memory contents
  709.     mov    word ptr es:[bx],05A5Ah    ; put testpattern
  710.     loadport
  711.     setport    EN_CCMD            ; drain the board bus for any
  712.     in    al,dx            ;   capacitive memory
  713.     cmp    word ptr es:[bx],05A5Ah    ; any real memory there?
  714.     jne    not_our_mem        ;   no
  715.     setport    EN_CMD            ;   yes
  716.     mov    ax,si
  717.     and    al,not EN_MEMEN
  718.     out    dx,al            ; turn off our memory
  719.     jmp    short $+2
  720.     or    al,EN_MEMEN
  721.     cmp    word ptr es:[bx],05A5Ah    ; was it OUR memory?
  722.     out    dx,al            ; turn on our memory.
  723.     jmp    short $+2
  724.     mov    es:[bx],cx        ; restore the original contents.
  725.     sti
  726.     jne    our_mem            ;   yes, it wasn't there any more
  727. not_our_mem:                ;   no, it was still there
  728.     shr    bx,1            ; test if half as much memory
  729.     cmp    bx,1FFFh        ; down to 8 kbyte
  730.     jae    memloop
  731.     jmp    not_our_memory        ; no memory at address mem_base
  732. our_mem:                ; it IS our memory!
  733.     inc    bh
  734.     mov    sm_rstop_ptr,bh        ; # of 256 byte ring bufs + 1
  735.     mov    ch,bh
  736.     xor    cl,cl
  737.     mov    ax,mem_base
  738.     call    memory_test        ; check all of that memory
  739.     je    mem_ok
  740.     jmp    no_memory
  741. mem_ok:
  742.     clc
  743.     ret
  744.  
  745.     public    print_parameters
  746. print_parameters:
  747.     mov    di,offset int_no
  748.     mov    dx,offset int_no_name
  749.     call    print_number
  750.     mov    di,offset io_addr
  751.     mov    dx,offset io_addr_name
  752.     call    print_number
  753.     mov    di,offset mem_base
  754.     mov    dx,offset mem_base_name
  755.     call    print_number
  756.  
  757.     mov    dx,offset nic_name    ;print the number in decimal.
  758.     mov    ah,9
  759.     int    21h
  760.     mov    ax,nic_number
  761.     xor    dx,dx
  762.     call    decout
  763.     call    crlf
  764.  
  765.     ret
  766.  
  767.     include    memtest.asm
  768.     include    occupied.asm
  769.  
  770. code    ends
  771.  
  772.     end
  773.