home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / packetdrivers.tar.gz / pd.tar / src / smc_wd.asm < prev    next >
Assembly Source File  |  1995-06-25  |  20KB  |  766 lines

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