home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / connect / tcpip / crynwr / exp16116 / exp16.asm < prev    next >
Assembly Source File  |  1994-05-20  |  64KB  |  2,958 lines

  1. version        equ    6
  2. DEBUG        equ    0
  3. ;History:1985,1
  4.  
  5. ;  Copyright 1991, 1992, 1993 Russell Nelson
  6.  
  7. ;   This program is free software; you can redistribute it and/or modify
  8. ;   it under the terms of the GNU General Public License as published by
  9. ;   the Free Software Foundation, version 1.
  10. ;
  11. ;   This program is distributed in the hope that it will be useful,
  12. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ;   GNU General Public License for more details.
  15. ;
  16. ;   You should have received a copy of the GNU General Public License
  17. ;   along with this program; if not, write to the Free Software
  18. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20.     include    defs.asm
  21.  
  22. code    segment    word public
  23.     assume    cs:code, ds:code
  24.  
  25. ;
  26. ;    Waits for SCB command unit to become idle
  27. ;
  28. ;    MUST NOT TRASH CX OR THE ISSUE_COMMAND PROCEDURE WILL FAIL
  29. ;cmd_clear exits with cy if the command didn't become idle in one millisecond.
  30.  
  31. cmd_clear    macro
  32.     local    exit
  33.  
  34.     lea    dx, [bp].@SCB_CMD        ;BP -> I/O Base
  35.  
  36.     in    ax, dx                ;Read SCB command
  37.     or    ax, ax                ;Wait for command accepted
  38.     jz    exit
  39.  
  40.     call    cmd_wait
  41. exit:
  42.     endm
  43.  
  44. ;
  45. ; Drives channel attention to the 586.  We don't care whats in AX, the write
  46. ; will cause the ASIC to drive CA to the 586.
  47. ;
  48.     issue_ca    MACRO
  49.     lea    dx, [bp].@CA_Ctrl
  50.     out    dx, al
  51.     endm
  52.  
  53.  
  54. ;
  55. ;
  56. ;  Enable and disable exp16s interrupts.
  57. ;
  58. enable_board_ints    macro
  59.     lea    dx, [bp].@Sel_IRQ
  60.     mov    al, encoded_int_no
  61.     or    al, 08h
  62.     out    dx, al
  63.     endm
  64.  
  65. disable_board_ints    macro
  66.     lea    dx, [bp].@Sel_IRQ
  67.     mov    al, encoded_int_no
  68.     out    dx, al
  69.     endm
  70.  
  71.  
  72. RxBufferSize    equ    1518+14+18    ;Max Rx packet+MAC header+
  73.                         ; 18 (alignment)
  74. TxBufferSize    equ    1518+14+20    ;Max Tx packet+MAC header+
  75.                         ; 20 (alignment)
  76.  
  77.     include    exp16.inc
  78.  
  79. _64K_not_32K    db    0    ;<>0 if we have 64K of memory.
  80. _16_not_8_bit_slot    db    0    ;<>0 if we're in a 16-bit slot.
  81.  
  82. ;possible values for connection_type:
  83. CONN_BNC    equ    0
  84. CONN_AUI    equ    1
  85. CONN_TPE    equ    2
  86. CONN_AUTO    equ    3
  87. connection_type    db    ?
  88.  
  89. ;Memory Sizes
  90. mem_size_address    equ    00H
  91. _32K        equ    00000h
  92. _64K        equ    00001h
  93.  
  94. CONNECTION_ADDRESS    equ    00H
  95. CONNECTION_FIELD    equ    0001000000000000B
  96.  
  97. AUTO_CON_ADDRESS    EQU    01H
  98. AUTO_CON_MASK    EQU    10000000B
  99.  
  100. TPE_address    equ    05H
  101. TPE_type_field    equ    0000000000000001B
  102.  
  103. int_num_address    equ    00H
  104. int_num_field    equ    1110000000000000B
  105. int_field_shift    equ    13
  106.  
  107. EE_ETHERNET_ADD_LOW    equ    2
  108. EE_ETHERNET_ADD_MID    equ    3
  109. EE_ETHERNET_ADD_HIGH    equ    4
  110. EE_INT        equ    0
  111. EE_SHIFT    equ    13
  112.  
  113. ;    Slot Width
  114. slot_width_mask    equ    04h
  115. _16_bit_slot    equ    0000h
  116. _8_bit_slot    equ    0001h
  117.  
  118. _16_bit_override_bit    equ    08h
  119.  
  120.  
  121. ;
  122. ;    EXP16 base port structure
  123. ;
  124. @EXP16BasePorts    struc
  125. @Data_Reg    dw    ?        ;Data Transfer Register.
  126. @Write_Ptr    dw    ?        ;Write Address Pointer.
  127. @Read_Ptr    dw    ?        ;Read Address Pointer.
  128. @CA_Ctrl    db    ?        ;Channel Attention Control.
  129. @Sel_IRQ    db    ?        ;IRQ Select.
  130. @SMB_Ptr    dw    ?        ;Shadow Memory Bank Pointer.
  131.     db    ?
  132. @MEM_Ctrl    db    ?
  133. @MEM_Page_Ctrl    db    ?
  134. @Config        db    ?
  135. @EEPROM_Ctrl    db    ?
  136. @ID_Port    db    ?
  137. @EXP16BasePorts    ends
  138.  
  139. ECR1        equ    300eh
  140.  
  141. @ISR_Ports    struc
  142.     db    0C008h dup(?)
  143. @SCB_STAT    dw    ?
  144. @SCB_CMD    dw    ?
  145. @SCB_CBL    dw    ?
  146. @SCB_RFA    dw    ?
  147. ;        @SCB_CRCERRS    dw      ?
  148. ;        @SCB_ALNERRS    dw      ?
  149. ;        @SCB_RSCERRS    dw      ?
  150. ;        @SCB_OVRNERRS   dw      ?
  151. @ISR_Ports    ends
  152.  
  153.  
  154.     @memory_page_struc    STRUC
  155.     DB    4000H DUP (?)
  156.     @mem_loc_0    DW    ?
  157.     @mem_loc_2    DW    ?
  158.     @mem_loc_4    DW    ?
  159.     @mem_loc_6    DW    ?
  160.     @mem_loc_8    DW    ?
  161.     @mem_loc_10    DW    ?
  162.     @mem_loc_12    DW    ?
  163.     @mem_loc_14    DW    ?
  164.     DB    4000H - 16 DUP (?)
  165.     @mem_loc_16    DW    ?
  166.     @mem_loc_18    DW    ?
  167.     @mem_loc_20    DW    ?
  168.     @mem_loc_22    DW    ?
  169.     @mem_loc_24    DW    ?
  170.     @mem_loc_26    DW    ?
  171.     @mem_loc_28    DW    ?
  172.     @mem_loc_30    DW    ?
  173.     @memory_page_struc    ENDS
  174.  
  175. ;
  176. ;
  177. ;    TData Segment
  178. ;
  179. ;    This segment template represents the 64-KB segment that the 82586
  180. ;    can address.  Shared memory can be either 32K or 64K for the EXP16.
  181. ;    All structures must be quad-word aligned.
  182. ;
  183. ;    Offset    Type of Block    Block Size    Cnt
  184. ;    ------    -------------    ----------    ---
  185. ;    0000h    ISCP        8        1
  186. ;    0008h    SCB        16        1
  187. ;    0020h    CommandBlock    104        1
  188. ;    00E0h    SendBlock(s)    1568        variable
  189. ;    ????h    ReceiveBlock(s)    1568        variable
  190. ;    FFF6h    SCP        10        1
  191. ;
  192.  
  193. TData_64    segment at 0
  194.  
  195.     ISCP    ISysConfigPtr  <>
  196.     SCB    SystemControlBlock <>
  197.  
  198.     ORG    20H
  199.  
  200.     CB    CommandBlock    <>
  201.  
  202.     Send_Blocks    DB    SIZE SendBlock * Number_of_Tx_Buffers dup (?)
  203.     Receive_Blocks    LABEL    WORD
  204.  
  205.  
  206.     ORG    (0FFFFh - SIZE SCPS + 1) AND 0FFE0H
  207.     SCP    LABEL    BYTE
  208.  
  209.     ORG    0FFFFh - SIZE SCPS + 1
  210.     THeapTop    LABEL    BYTE            ;Top of available memory
  211.  
  212. end_of_send_blocks    =    20h + SIZE CommandBlock + (Number_of_Tx_Buffers * SIZE SendBlock)
  213. num_rx_buf_32k    =    (07FFFh - SIZE SCPS + 1 - end_of_send_blocks) / (SIZE ReceiveBlock)
  214. num_rx_buf_64k    =    (0FFFFh - SIZE SCPS + 1 - end_of_send_blocks) / (SIZE ReceiveBlock)
  215.  
  216.     TData_64    ENDS
  217.  
  218.  
  219.     public    int_no
  220. int_no        db    3,0,0,0        ;must be four bytes long for get_number.
  221. io_addr        dw    -1,-1        ; I/O address for card
  222. encoded_int_no    db    ?        ;encoded for exp16.
  223.  
  224.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  225. driver_class    db    BLUEBOOK, IEEE8023, 0        ;from the packet spec
  226. driver_type    db    91        ;from the packet spec
  227. driver_name    db    'EtherExpress16',0    ;name of the driver.
  228. driver_function    db    2 + 16 + 8    ;8 = error in DH, 16 = has TDR function.
  229. parameter_list    label    byte
  230.     db    1    ;major rev of packet driver
  231.     db    9    ;minor rev of packet driver
  232.     db    14    ;length of parameter list
  233.     db    EADDR_LEN    ;length of MAC-layer address
  234.     dw    GIANT    ;MTU, including MAC headers
  235.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  236.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  237.     dw    0    ;(# of successive xmits) - 1
  238. int_num        dw    0    ;Interrupt # to hook for post-EOI
  239.             ;processing, 0 == none,
  240. save_err    db    0        ;error bits on promiscuous recieve
  241. pro0        db    0
  242. pro1        db    0
  243.  
  244.     BART_Board_ID    EQU    0BABAH
  245.     BUD_board_ID    EQU    0BABBH
  246.     mca_hp_board_ID    EQU    0BABCH
  247.  
  248. board_id    dw    ?
  249.  
  250.     public    rcv_modes
  251. rcv_modes    dw    7        ;number of receive modes in our table.
  252.     dw    0            ;There is no mode zero
  253.     dw    0
  254.     dw    rcv_mode_2
  255.     dw    rcv_mode_3
  256.     dw    rcv_mode_4    ;haven't set up perfect filtering yet.
  257.     dw    0
  258.     dw    rcv_mode_6
  259.  
  260. ;
  261. ;    82586 Configuration Parameters
  262. ;
  263.     config_params    LABEL    WORD
  264.     num_config_params    LABEL    BYTE    ;12 BYTEs
  265.     DB    0CH
  266.  
  267.     fifo_limit    LABEL    BYTE
  268.     DB    14
  269.  
  270.     srdy    LABEL    BYTE    ;srdy = 1
  271.     save_bad_frame    LABEL    BYTE    ;do not save bad frame
  272.     DB    40H
  273.  
  274.     address_length    LABEL    BYTE    ;6 BYTEs
  275.     auto_insert_address    LABEL    BYTE    ;auto insert off (1)
  276.     preamble_length    LABEL    BYTE    ;2 BYTEs
  277.     internal_loopback    LABEL    BYTE    ;0 = OFF  1 = ON
  278.     external_loopback    LABEL    BYTE    ;0 = OFF  1 = ON
  279.     DB    2EH    ;26h in IPXWS
  280.  
  281.     linear_priority    LABEL    BYTE    ;default is 0
  282.     accel_contention_resolution    LABEL    BYTE    ;default is 0
  283.     exp_backoff_method    LABEL    BYTE    ;0 = 802.3  1 = Alternate
  284.     DB    00H
  285.  
  286.     interframe_spacing    LABEL    BYTE    ;default is 60H (96 bits)
  287.     DB    60H
  288.  
  289.     slot_time_low    LABEL    BYTE    ;0
  290.     DB    00H
  291.  
  292.     slot_time_high    LABEL    BYTE    ;2
  293.     retry_num    LABEL    BYTE    ;15
  294.     DB    0F2H
  295.  
  296.     promiscuous_mode    LABEL    BYTE    ;0 = OFF  1 = ON
  297.     broadcast_disable    LABEL    BYTE    ;0 = OFF  1 = ON
  298.     encode_decode    LABEL    BYTE    ;0 = NRZ  1 = MANCHESTER
  299.     transmit_on_no_carrier    LABEL    BYTE    ;0 = STOP 1 = CONTINUE
  300.     no_crc_insertion    LABEL    BYTE    ;0 = OFF  1 = ON
  301.     crc_type    LABEL    BYTE    ;0 = 32 bit autodin II
  302.                         ;1 = 16 bit CCITT
  303.     bit_stuffing    LABEL    BYTE    ;0 = 802.3  1 = HDLC
  304.     padding    LABEL    BYTE    ;0 = OFF  1 = ON
  305.     DB    00H
  306.  
  307.     carrier_sense_filter    LABEL    BYTE    ;0 = OFF  1 = 0N
  308.     carrier_sense_source    LABEL    BYTE    ;0 = external  1 = internal
  309.     collision_detect_filter    LABEL    BYTE    ;default = 0
  310.     collision_detect_source    LABEL    BYTE    ;0 = external  1 = internal
  311.     DB    00H
  312.  
  313.     min_frame_length    LABEL    BYTE    ;60 BYTEs
  314.     DB    60
  315.     DB    00H    ;undefined
  316.  
  317.  
  318. RxBufferCount    dw    ?
  319. TxBufferCount    dw    ?
  320.  
  321.     Receive_Head    DW    ?
  322.     Receive_Tail    DW    ?
  323.  
  324. HEADER_LEN    equ    EADDR_LEN + EADDR_LEN + MAX_P_LEN
  325.     even
  326. our_type    db    HEADER_LEN dup(?)
  327.  
  328.     extrn    is_186: byte        ;=0 if 808[68], =1 if 80[123]86.
  329.     extrn    sys_features: byte
  330.  
  331.     include    io16.asm
  332.  
  333.     public    bad_command_intercept
  334. bad_command_intercept:
  335. ;called with ah=command, unknown to the skeleton.
  336. ;exit with nc if okay, cy, dh=error if not.
  337.     cmp    ah,26
  338.     jne    bad_command_intercept_1
  339.     jmp    do_tdr
  340. bad_command_intercept_1:
  341.     mov    dh,BAD_COMMAND
  342.     stc
  343.     ret
  344.  
  345.     public    as_send_pkt
  346. ; The Asynchronous Transmit Packet routine.
  347. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  348. ;   interrupts possibly enabled.
  349. ; Exit with nc if ok, or else cy if error, dh set to error number.
  350. ;   es:di and interrupt enable flag preserved on exit.
  351. as_send_pkt:
  352.     ret
  353.  
  354.     public    drop_pkt
  355. ; Drop a packet from the queue.
  356. ; Enter with es:di -> iocb.
  357. drop_pkt:
  358.     assume    ds:nothing
  359.     ret
  360.  
  361.     public    xmit
  362. ; Process a transmit interrupt with the least possible latency to achieve
  363. ;   back-to-back packet transmissions.
  364. ; May only use ax and dx.
  365. xmit:
  366.     assume    ds:nothing
  367.     ret
  368.  
  369.  
  370.     public    send_pkt
  371. send_pkt:
  372. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  373. ;  (only if the high-performance bit is set in driver_function)
  374. ;enter with ds:si -> packet, cx = packet length.
  375. ;if we're a high-performance driver, es:di -> upcall.
  376. ;exit with nc if ok, or else cy if error, dh set to error number.
  377.     assume    ds:nothing
  378.     cmp    pro1,1
  379.     je    no_size_check1
  380.  
  381.     cmp    cx,GIANT        ; Is this packet too large?
  382.     jna    no_size_check1
  383.     jmp    send_pkt_toobig
  384.  
  385. no_size_check1:
  386.  
  387.     push    bp
  388.     mov    bp,io_addr
  389.  
  390.     disable_board_ints
  391.     cmd_clear    ; wait for command processor to clear
  392.  
  393.     cmp    pro1,1            ; on pro drive do not ajust size
  394.     je    oklen
  395.  
  396.     cmp    cx,RUNT        ; minimum length for Ether
  397.     jae    oklen
  398.     mov    cx,RUNT        ; make sure size at least RUNT
  399. oklen:
  400. ;
  401. ; Set SMB pointer to the transmit buffer.
  402. ;
  403.     lea    dx,[BP].@SMB_Ptr
  404.     mov    ax,offset send_blocks
  405.     out    dx,ax
  406. ;
  407. ; Write evenized, padded packet length (>= RUNT bytes) to 586 TBD byte
  408. ; count field.  OR on the End of Frame bit.
  409. ;
  410.     lea    dx,[BP].@TBD_ByteCount
  411.     mov    ax,cx
  412.     or    ah,byte_BIT_EOF
  413.     out    dx,ax
  414. ;
  415. ; Set the TxCB command field for transmit.  Also set the EL bit (End of List).
  416. ;
  417.     lea    dx, [BP].@TxCB_Command
  418.     mov    ax, BIT_EL+GA_Transmit
  419.     out    dx, ax
  420. ;
  421. ; Set write pointer to the data buffer for current send block.  Also
  422. ; set DX to the data register.
  423. ;
  424.     lea    dx, [BP].@Write_Ptr
  425.     mov    ax, offset send_blocks
  426.     add    ax, offset TB_Data
  427.     out    dx, ax
  428.     mov    dx, bp            ;@Data_Reg
  429.  
  430.     inc    cx        ;round size up to next even number.
  431.     and    cx,not 1
  432.     call    repoutsw
  433.  
  434. send_continue:
  435. ;
  436. ; Set the SCBs command block pointer to this send packet.
  437. ;
  438.     lea    dx, [BP].@SCB_CBL
  439.     mov    ax, offset send_blocks
  440.     out    dx, ax
  441.  
  442. ;
  443. ; Set the SCB command to start the command unit.
  444. ;
  445.     lea    dx, [BP].@SCB_CMD
  446.     mov    ax, CUC_START
  447.     out    dx, ax
  448.     issue_ca
  449.  
  450.     cmd_clear    ; wait for frame transmit to start
  451.     lea    dx,[BP].@SMB_Ptr
  452.     mov    ax,offset send_blocks
  453.     out    dx,ax
  454.  
  455.     lea    dx,[BP].@TxCB_status
  456. transmiting:
  457.     in    ax,dx
  458.  
  459.     test    ax,BIT_C        ; check status of transmit
  460.     jz    transmiting
  461.  
  462.     test    ax,BIT_OK        ; how was the x-mit
  463.     jnz    tx_ok
  464.  
  465.     enable_board_ints
  466.     pop    bp
  467.     mov    dh,CANT_SEND
  468.     jmp    tx_bad
  469.  
  470. tx_ok:
  471.     enable_board_ints
  472.  
  473.     pop    bp
  474.  
  475.     clc
  476.     ret
  477.  
  478. send_pkt_toobig:
  479.     mov    dh,NO_SPACE
  480. tx_bad:
  481.     stc
  482.     ret
  483.  
  484.  
  485. ;    ReadTickCounter
  486. ;
  487. ;    Read the 16 bit timer tick count register (system board timer 0).
  488. ;    The count register decrements by 2 (even numbers) every 838ns.
  489. ;
  490. ;    Assumes:    Interrupts disabled
  491. ;
  492. ;    Returns:    AX with the current count
  493. ;            Interrupts disabled
  494.  
  495. ReadTickCounter:
  496.  
  497.     push    dx
  498.  
  499.     mov    dx, 43h                ;Command 8254 timer to latch
  500.     xor    al, al                ; T0's current count
  501.     out    dx, al
  502.  
  503.     mov    dx, 40h                ;read the latched count
  504.     in    al, dx                ; LSB first
  505.     mov    ah, al
  506.     in    al, dx                ; MSB next
  507.     xchg    al, ah                ;put count in proper order
  508.  
  509.     pop    dx
  510.     ret
  511.  
  512.  
  513.     public    set_address
  514. set_address:
  515. ;enter with ds:si -> Ethernet address, CX = length of address.
  516. ;exit with nc if okay, or cy, dh=error if any errors.
  517.     assume    ds:code
  518.     push    bp
  519.     push    si
  520. ;
  521. ; Set up individual address command block.
  522. ;
  523.     mov    bp,ds:io_addr
  524.     cmd_clear
  525.     mov    bx, BIT_EL+GA_IA_Setup
  526.     call    setup_command_block
  527.     pop    si
  528.  
  529. ;
  530. ; Copy individual address command parameters to individual address
  531. ; command block.
  532. ;
  533.     mov    cx, EADDR_LEN/2
  534. move_node_address:
  535.     lodsw
  536.     out    dx, ax
  537.     loop    move_node_address
  538.  
  539. ;
  540. ; Signal 586 to execute individual address command.
  541. ;
  542.     mov    ax, CUC_Start
  543.     mov    bx, BIT_CNA
  544.     call    issue_command
  545.  
  546.     lea    dx, [bp].@SMB_Ptr        ;Move IO frame to the command
  547.     mov    ax, offset cb            ; command block.
  548.     out    dx, ax
  549.  
  550.     lea    dx,[BP].@CB_Status
  551. working1:
  552.     in    ax,dx
  553.  
  554.     test    ax,BIT_C        ; check status of set_ia
  555.     jz    working1
  556.  
  557.     test    ax,BIT_OK
  558.     jnz    set_ok
  559.     stc
  560.     jmp    set_address_done
  561.  
  562. set_ok:
  563.     mov    cx,5000h        ; on 486's if we do not delay this command does not work
  564. set1:
  565.     mov    bx,cx
  566.     mov    ax,[bx]
  567.     loop    set1            ; just for delay
  568.  
  569.     mov    cx,EADDR_LEN        ;return their address length.
  570.     clc
  571. set_address_done:
  572.     pop    bp
  573.     ret
  574.  
  575.  
  576. rcv_mode_2:
  577.     and    promiscuous_mode,not 3
  578.     or    promiscuous_mode,2    ;disable broadcasts.
  579.     mov    min_frame_length,60
  580.     and    save_bad_frame,not 80h
  581.     mov    pro0,0
  582. ;;;    mov     pro1,0            ;not present in NSA version
  583.     jmp    short configure_command
  584. rcv_mode_4:
  585. rcv_mode_3:
  586.     and    promiscuous_mode,not 3    ;clear promiscuous mode.
  587.     mov    min_frame_length,60
  588.     and    save_bad_frame,not 80h
  589.     mov    pro0,0
  590. ;;;    mov     pro1,0            ;not present in NSA version
  591.     jmp    short configure_command
  592. rcv_mode_6:
  593.     and    promiscuous_mode,not 3
  594.     or    promiscuous_mode,1    ;set promiscuous mode.
  595.     mov    min_frame_length,60    ;allow runt. but let it come in as a bad frame
  596.     or    save_bad_frame,80h    ; yes we want bad frames here
  597.     mov    pro0,1
  598.     mov    pro1,1
  599. ;
  600. configure_command:
  601.     mov    bp,io_addr
  602. ;
  603. ; Set up configure command block.
  604. ;
  605.     mov    bx, bit_el + GA_Configure    ;Set command block for a
  606.     call    setup_command_block        ; configure command. BIT_EL
  607.                         ; means last command.
  608. ;
  609. ; Copy configure command parameters to configure command block.
  610. ;
  611.     mov    si,offset config_params        ;Set DS:SI to parameters and
  612.     mov    cx, 6                ; copy them to the command
  613.  
  614. move_config_params:
  615.  
  616.     lodsw
  617.     out    dx, ax
  618.     loop    move_config_params
  619. ;
  620. ; Signal 586 to execute configure command.
  621. ;
  622.     mov    ax, CUC_Start
  623.     mov    bx, BIT_CNA
  624.     call    issue_command
  625.     ret
  626.  
  627.  
  628. ;*****************************************************************
  629. ; TDR cable tester
  630. ; enter with es:di pointing to time int
  631. ;*****************************************************************
  632.  
  633.     public    do_tdr
  634. do_tdr:
  635.     push    bp
  636.     push    es
  637.     push    di
  638.     mov    bp,io_addr
  639. ;
  640. ; Set up configure command block.
  641. ;
  642.     mov    bx, bit_el + GA_TDR    ;Set command block for a
  643.     call    setup_command_block        ; TDR command. BIT_EL
  644.                         ; means last command.
  645. ; Signal 586 to execute configure command.
  646. ;
  647.     mov    ax, CUC_Start
  648.     mov    bx, BIT_CNA
  649.     call    issue_command
  650.  
  651.     lea    dx, [bp].@SMB_Ptr        ;Move IO frame to the command
  652.     mov    ax, offset cb            ; command block.
  653.     out    dx, ax
  654.  
  655.     lea    dx,[BP].@CB_Status
  656. working:
  657.     in    ax,dx
  658.  
  659.     test    ax,BIT_C        ; check status of transmit
  660.     jz    working
  661.  
  662.     lea    dx,[bp].@CB_Parm0
  663.     in    ax,dx
  664.  
  665.     pop    di
  666.     pop    es
  667.     pop    bp
  668.  
  669.     test    ax,LNK_OK
  670.     jz    tdr_bad_cable
  671.     clc
  672.     ret
  673.  
  674. tdr_bad_cable:
  675.  
  676.     push    ax
  677.     and    ax,TDR_TIME
  678.     stosw    ; store time
  679.     pop    ax
  680.  
  681.     mov    cl,12
  682.     shr    ax,cl
  683.     and    ax,7
  684.     mov    dh,al
  685.  
  686.     stc
  687.     ret
  688.  
  689.  
  690. ;
  691. ;    BX = 586 command word
  692. ;
  693. setup_command_block:
  694.  
  695. ;
  696. ; Setup command block's command, status, and link fields.
  697. ;
  698.     lea    dx, [bp].@SMB_Ptr        ;Move IO frame to the command
  699.     mov    ax, offset cb            ; command block.
  700.     out    dx, ax
  701.  
  702.     lea    dx, [bp].@CB_link        ;Set command block's link to
  703.     out    dx, ax                ; itself.
  704.  
  705.     lea    dx, [bp].@SCB_CBL        ;Point SCB command list
  706.     out    dx, ax                ; pointer to command block.
  707.  
  708.     lea    dx, [bp].@CB_command        ;Set command block's command
  709.     mov    ax, bx                ; word to value passed in
  710.     out    dx, ax                ; BX.
  711.  
  712. ;
  713. ; Return with the write pointer set to the command block parameter
  714. ; offset.
  715. ;
  716.     lea    dx, [bp].@Write_Ptr        ;Set write pointer to command
  717.     lea    ax, CB.CB_Param0        ; parameter field.
  718.     out    dx, ax
  719.  
  720.     mov    dx, bp            ;@Data_Reg
  721.     ret
  722.  
  723.  
  724. ;
  725. ; Wait for 586 command register to be clear (  1 millisecond max)
  726. ; Issue command
  727. ; Wait for command to complete              (500 milliseconds max)
  728. ; Acknowledge command complete
  729. ;
  730. ;
  731. issue_command:
  732.  
  733. ;
  734. ; Make sure 586 command in SCB is clear.
  735. ;
  736.     mov    cx, ax
  737.     cmd_clear
  738.     jc    issue_command_error_exit
  739.     mov    ax, cx
  740. ;
  741. ; Put command code in AX into SCB command register and signal the
  742. ; 586 to look at it.  The cmd_clear macro leaves DX pointing to
  743. ; the SCB command register.
  744. ;
  745.     out    dx, ax
  746.     issue_ca
  747.  
  748. wait_for_commad_status_outer_loop:
  749. ;
  750. ; Wait here for 586 to complete the command.  586 should never take
  751. ; more than 500 Milliseconds to complete a command.
  752. ;
  753.     call    readtickcounter
  754.     mov    cx, ax
  755.     lea    dx, [bp].@SCB_STAT
  756.  
  757. wait_for_commad_status:
  758.  
  759.     in    ax, dx
  760.     cmp    ax, bx
  761.     je    acknowledge_command_complete
  762.  
  763.     call    readtickcounter
  764.     neg    ax
  765.     add    ax, cx
  766.     cmp    ax, ten_mils
  767.     jb    wait_for_commad_status
  768.  
  769. _586_command_error:
  770. ;
  771. ; Signal error by pointing AX to error message, and setting
  772. ; condition codes.
  773. ;
  774.     mov    dx,offset _586_not_responding_msg
  775.     mov    ah,9
  776.     int    21h
  777.     stc
  778.     ret
  779. issue_command_error_exit:
  780.     stc
  781.     ret
  782.  
  783. acknowledge_command_complete:
  784. ;
  785. ; Tell the 586 that we know its done by copying the status back to
  786. ; the command register's acknowledge fields.  BX has status.
  787. ;
  788.     lea    dx, [bp].@SCB_CMD
  789.     out    dx, ax
  790.     issue_ca
  791. ;
  792. ; Signal no error.
  793. ;
  794.     xor    ax, ax
  795.     ret
  796.  
  797.  
  798.     public    set_multicast_list
  799. set_multicast_list:
  800. ;enter with ds:si ->list of multicast addresses, ax = number of addresses,
  801. ;  cx = number of bytes.
  802. ;return nc if we set all of them, or cy,dh=error hf we didn't.
  803.     mov    dh,NO_MULTICAST
  804.     stc
  805.     ret
  806.  
  807.  
  808.     public    terminate
  809. terminate:
  810.     push    bp
  811.     mov    bp,io_addr
  812.  
  813.     cmd_clear    ; wait until last command is done processing
  814.  
  815.     disable_board_ints    ; shut off board ints
  816.  
  817.     lea    dx,[bp].@SCB_CMD
  818.     mov    ax, RUC_SUSPEND        ; suspend recieve unit
  819.     out    dx, ax
  820.     issue_ca
  821.  
  822.     pop    bp            ; now ok to un-hook interrupts and release
  823.     ret    ; driver
  824.  
  825.     public    reset_interface
  826. reset_interface:
  827. ;reset the interface.
  828.     assume    ds:code
  829.     ret
  830.  
  831.  
  832. ;called when we want to determine what to do with a received packet.
  833. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  834.     extrn    recv_find: near
  835.  
  836. ;called after we have copied the packet into the buffer.
  837. ;enter with ds:si ->the packet, cx = length of the packet.
  838.     extrn    recv_copy: near
  839.  
  840. ;call this routine to schedule a subroutine that gets run after the
  841. ;recv_isr.  This is done by stuffing routine's address in place
  842. ;of the recv_isr iret's address.  This routine should push the flags when it
  843. ;is entered, and should jump to recv_exiting_exit to leave.
  844. ;enter with ax = address of routine to run.
  845.     extrn    schedule_exiting: near
  846.  
  847. ;recv_exiting jumps here to exit, after pushing the flags.
  848.     extrn    recv_exiting_exit: near
  849.  
  850.     extrn    count_in_err: near
  851.     extrn    count_out_err: near
  852. ;    extrn    resource_err_in:word
  853.  
  854.     public    recv
  855. recv:
  856. ;called from the recv isr.  All registers have been saved, and ds=cs.
  857. ;Upon exit, the interrupt will be acknowledged.
  858.     assume    ds:code
  859. ;
  860. ; Set BP to the base IO address of exp16.  Also disable exp16s ability
  861. ; to generate interrupts.
  862. ;
  863.     mov    bp,io_addr
  864.     disable_board_ints
  865. ;
  866. ; Make sure that command unit is clear before reading the status.
  867. ;
  868.     cmd_clear
  869. ;
  870. ; Get the SCB status to see why exp16 interrupted us.  Also need to
  871. ; copy the status back to the command word to acknowledge the 586
  872. ; interrupt.  Issue channel attention to get the 586 to realize the
  873. ; interrupt aknowledge.
  874. ;
  875. ;    lea    dx, [bp].@SCB_RSCERRS
  876. ;    in    ax,dx
  877. ;    mov    word ptr resource_err_in,ax
  878. ;    lea    dx, [bp].@SCB_OVRNERRS
  879. ;    in    ax,dx
  880. ;    add    word ptr resource_err_in,ax
  881.  
  882.     lea    dx, [bp].@SCB_STAT
  883.     in    ax, dx
  884.     and    ax, ACK_INT_MASK
  885.  
  886.     lea    dx, [bp].@SCB_CMD
  887.     out    dx, ax
  888.     issue_ca    ; AX is not changed.
  889. ;
  890. ; Check for frame receive status.  Jump if no frames received,
  891. ; otherwise processes the receive.
  892. ;
  893.     test    AX, BIT_FR OR BIT_RNR
  894.     jz    ExitDriverISR
  895.     call    ProcessRx
  896. ExitDriverISR:
  897. ;
  898. ; Here if there was a bad receive status.  Make sure the receive unit
  899. ; of the 586 is running.  Read in the SCB status and jump if we need
  900. ; to restart the receive unit.  We choose to have the jump to restart
  901. ; the RU since most of the time we will not need to do this.  This
  902. ; saves cycle times when exiting without a restart.
  903. ;
  904.     lea    dx, [bp].@SCB_STAT
  905.     in    ax, dx
  906.     test    ax, READY
  907.     jz    restart_RU
  908.  
  909. drvisr_continue:
  910.     enable_board_ints
  911.     ret
  912.  
  913.  
  914. restart_RU:
  915. ;
  916. ; Need to restart the receive unit of the 586.  Set the SCB pointer to
  917. ; the receive frame area.
  918. ;
  919.     lea    dx, [bp].@SCB_RFA
  920.     mov    ax, Receive_Head
  921.     out    dx, ax
  922. ;
  923. ; Make sure 586 is in a state to accept a command.
  924. ;
  925.     cmd_clear
  926. ;
  927. ; Put the receive unit start command into the SCB command word and
  928. ; issue the channel attention.
  929. ;
  930. ; NOTE: cmd_clear macro leaves DX pointing to the SCB command word.
  931. ;
  932. ;    lea    dx, [bp].@SCB_CMD
  933.     mov    ax, RUC_START
  934.     out    dx, ax
  935.     issue_ca
  936.     jmp    drvisr_continue
  937.  
  938.  
  939. ProcessRx:
  940.  
  941. ;
  942. ; Prime the pump that services receives by setting AX to the receive
  943. ; head.  There could be over 30 packets received.
  944. ;
  945.     mov    ax,Receive_Head
  946.  
  947. CheckNextReceiveStatus:
  948.  
  949. ;
  950. ; Save receive head pointer in BX.  BX should not be altered during
  951. ; this loop.
  952. ;
  953.     mov    bx, ax
  954. ;
  955. ; Set SMB pointer to the top of the receive frame.
  956. ;
  957.     lea    dx, [bp].@SMB_Ptr
  958.     out    dx, ax
  959. ;
  960. ; Get the status for this receive frame.  Check to make sure that
  961. ; it completed with no errors.  If not, then jump to check the
  962. ; 586 receive unit.
  963. ;
  964.     lea    dx, [bp].@FD_Status
  965.     in    ax, dx
  966.  
  967.     mov    save_err,1        ; be sure we done accdently report an error
  968.  
  969.     test    ax, BIT_C        ; command compleat
  970.     jz    PRx_no
  971.     test    ax,BIT_OK        ; good frame
  972.     jnz    ProcessRx_1
  973.  
  974.     call    count_in_err
  975.     mov    save_err,0
  976.     cmp    pro0,1
  977.     je    PRx_bad            ; if not in pro-mode lose bad frames and inc error
  978. ;    call    count_in_err
  979.     jmp    recv_isr_9
  980. PRx_no:
  981.     ret
  982.  
  983. PRx_bad:
  984.     mov    dh,0            ;build save_err.
  985.     test    ax,BIT_S7
  986.     jz    PR_no_frag
  987.     or    dh,2
  988. PR_no_frag:
  989.     test    ax,BIT_S11
  990.     jz    PR_no_crc
  991.     or    dh,4
  992. PR_no_crc:
  993.     test    ax,BIT_S10
  994.     jz    PR_no_align
  995.     or    dh,8
  996. PR_no_align:
  997.     test    ax,BIT_S8
  998.     jz    PR_no_dma
  999.     or    dh,16
  1000. PR_no_dma:
  1001.     test    ax,BIT_S9
  1002.     jz    PR_no_ru
  1003.     or    dh,32
  1004. PR_no_ru:
  1005.     mov    save_err,dh
  1006.  
  1007. ProcessRx_1:
  1008. ;
  1009. ; Set the read pointer to access the LengthTypeField.
  1010. ;
  1011. ; NOTE: BX was set to receive head at the beginning of this
  1012. ;       procedure.
  1013. ;
  1014.     lea    dx, [bp].@Read_Ptr
  1015.     lea    ax, [BX].IPX_DestAddr_HIGH
  1016.     out    dx, ax
  1017.     mov    dx, bp            ;@Data_Reg
  1018.  
  1019.     mov    ax,cs
  1020.     mov    es,ax
  1021.     mov    di,offset our_type
  1022.     mov    cx,HEADER_LEN
  1023.     call    repinsw
  1024.  
  1025. ;
  1026. ; Get the packet size from the 586 data structure.
  1027. ;
  1028.     lea    dx, [bp].@RBD_ByteCount
  1029.     in    ax, dx
  1030.     and    ah, 3fh
  1031.     mov    cx, ax
  1032.  
  1033.     mov    di,offset our_type+EADDR_LEN+EADDR_LEN
  1034.  
  1035.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  1036.     mov    ax, es:[di]
  1037.     xchg    ah, al
  1038.     cmp    ax, 1518
  1039.     ja    BlueBookPacket
  1040.     inc    di            ;set di to 802.2 header
  1041.     inc    di
  1042.     mov    dl, IEEE8023
  1043. BlueBookPacket:
  1044.     push    bx
  1045.     push    cx            ; for some reison recv_find trashes cx
  1046.     mov    dh,save_err
  1047.     call    recv_find
  1048.     mov    bp,cs:io_addr        ; just in case
  1049.     pop    cx
  1050.     pop    bx
  1051.  
  1052.     mov    ax,es            ;is this pointer null?
  1053.     or    ax,di
  1054.     je    recv_isr_9        ;yes - just free the frame.
  1055.     push    es            ;remember where the buffer pointer is.
  1056.     push    di
  1057.     push    cx
  1058.   if 0
  1059. ;
  1060. ; Copy the packet's header into their buffer.
  1061. ;
  1062.     push    cx
  1063.     mov    si,offset our_type
  1064.     mov    cx,HEADER_LEN/2
  1065.     rep    movsw
  1066.     pop    cx
  1067.     sub    cx,HEADER_LEN
  1068.   endif
  1069. ;
  1070. ; Set the read pointer to access the packet.
  1071. ;
  1072. ; NOTE: BX was set to receive head at the beginning of this
  1073. ;       procedure.
  1074. ;
  1075.     lea    dx, [bp].@Read_Ptr
  1076.   if 0
  1077.     lea    ax, [BX].IPX_DestAddr_HIGH + HEADER_LEN
  1078.   else
  1079.     lea    ax, [BX].IPX_DestAddr_HIGH
  1080.   endif
  1081.     out    dx, ax
  1082.     mov    dx, bp            ;@Data_Reg
  1083. ;
  1084. ; Now read the packet into es:di
  1085. ;
  1086.     call    repinsw
  1087.  
  1088.     pop    cx
  1089.     pop    si
  1090.     pop    ds
  1091.     assume    ds:nothing
  1092.     call    recv_copy        ;tell them that we copied it.
  1093.     mov    ax,cs            ;restore our ds.
  1094.     mov    ds,ax
  1095.     assume    ds:code
  1096.  
  1097. recv_isr_9:
  1098. ;
  1099. ; Restore SMB pointer to the top of the receive frame.
  1100. ;
  1101.     mov    bp,io_addr        ; just in case
  1102.     mov    ax,bx
  1103.     lea    dx, [bp].@SMB_Ptr
  1104.     out    dx, ax
  1105.  
  1106. ;
  1107. ; Clear the current receive frames status.
  1108. ;
  1109.     lea    dx, [bp].@FD_Status
  1110.     xor    ax, ax
  1111.     out    dx, ax
  1112. ;
  1113. ; Set the end of list bit for the current receive frame.
  1114. ;
  1115.     lea    dx, [bp].@FD_command
  1116.     mov    ax, BIT_EL
  1117.     out    dx, ax
  1118. ;
  1119. ; Read in the pointer to the next receive frame.
  1120. ;
  1121.     lea    dx, [bp].@FD_Link
  1122.     in    ax, dx
  1123. ;
  1124. ; Update our local pointer to the receive resources:
  1125. ;
  1126. ; Receive_tail <-- Receive head
  1127. ; Receive_head <-- next receive frame.
  1128. ;
  1129.     mov    BX, Receive_Head
  1130.     mov    Receive_Tail, BX
  1131.     mov    Receive_Head, AX
  1132.     mov    cx, ax
  1133. ;
  1134. ; Clear previous receive frame descriptors end of list bit to free up
  1135. ; a receive resource.  We do this by moving the write pointer to the
  1136. ; the command word in the previous receive frame and then writing a
  1137. ; zero to it.
  1138. ;
  1139.     lea    dx, [bp].@Write_Ptr
  1140.     lea    ax, [bx].FD_command
  1141.     out    dx, ax
  1142.  
  1143.     mov    dx, bp            ;@Data_Reg
  1144.     xor    ax, ax
  1145.     out    dx, ax
  1146. ;
  1147. ; Check for another receive frame.
  1148. ;
  1149.     mov    ax, cx
  1150.     jmp    CheckNextReceiveStatus
  1151.  
  1152.  
  1153.  
  1154. ; This procedure is called from the cmd_clear macro after the macro determines
  1155. ; that we must wait for a command to clear.
  1156. ;
  1157. ;     MUST NOT TRASH BX or CX OR THE ISSUE_COMMAND PROCEDURE WILL FAIL.
  1158. ;
  1159. cmd_wait:
  1160. ;enter with dx -> SCB_CMD
  1161. ;exit with nc if it cleared in one millisecond, cy if not.
  1162.  
  1163.     push    bx
  1164.     call    readtickcounter            ;Reference clock.  die after
  1165.     mov    bx, ax                ; 1 ms.
  1166.  
  1167. wait_cmd_clear:
  1168.  
  1169.     in    ax, dx                ;Read SCB command
  1170.     or    ax, ax                ;Wait for command accepted
  1171.     jz    exit
  1172.  
  1173.     call    readtickcounter
  1174.     neg    ax
  1175.     add    ax, bx
  1176.  
  1177.     cmp    ax, one_mil
  1178.     jb    wait_cmd_clear
  1179.  
  1180.     stc
  1181. exit:
  1182.     pop    bx
  1183.     ret
  1184.  
  1185.  
  1186.     public    timer_isr
  1187. timer_isr:
  1188. ;if the first instruction is an iret, then the timer is not hooked
  1189.     iret
  1190.  
  1191. ;any code after this will not be kept after initialization. Buffers
  1192. ;used by the program, if any, are allocated from the memory between
  1193. ;end_resident and end_free_mem.
  1194.     public    end_resident,end_free_mem
  1195. end_resident    label    byte
  1196. end_free_mem    label    byte
  1197.  
  1198.  
  1199.     public    usage_msg
  1200. usage_msg    db    "usage: exp16 [options] <packet_int_no> <io_addr>",CR,LF,'$'
  1201.  
  1202.     public    copyright_msg
  1203. copyright_msg    db    "Packet driver for the Intel EtherExpress 16, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
  1204.     db    "Copyright 1991 Intel Corp",CR,LF
  1205.     db    "Portions Copyright 1993 Crynwr Software",CR,LF,'$'
  1206.  
  1207. int_no_name    db    "Interrupt number ",'$'
  1208. io_addr_name    db    "I/O port ",'$'
  1209.  
  1210.     extrn    set_recv_isr: near
  1211.  
  1212. ;enter with si -> argument string, di -> dword to store.
  1213. ;if there is no number, don't change the number.
  1214.     extrn    get_number: near
  1215.  
  1216. ;enter with dx -> argument string, di -> dword to print.
  1217.     extrn    print_number: near
  1218.  
  1219.  
  1220. ;-> the assigned Ethernet address of the card.
  1221.     extrn    rom_address: byte
  1222.  
  1223. chan_sel    db    0    ;Channel select for SYS_MCA machines
  1224.  
  1225.     public    etopen
  1226. etopen:
  1227. ;initialize the driver.
  1228.     assume    ds:code
  1229. ;
  1230. ; Get board information (Node address, etc.).  Returns with BP
  1231. ; set to the board IO base address (if not errors).
  1232. ;
  1233.     call    get_system_info
  1234.     jc    driver_init_error_exit
  1235.  
  1236.     disable_board_ints
  1237. ;
  1238. ; If they're in an 8-bit slot, make sure that they aren't using the slave PIC.
  1239. ;
  1240.     cmp    _16_not_8_bit_slot,0    ;are they using a 16-bit slot?
  1241.     jne    check_config_exit    ;yes -- cool.
  1242.  
  1243.     mov    dx,offset irq_config_error
  1244.     cmp    int_no, 9        ;no - don't let them use the upper IRQs.
  1245.     jb    check_config_exit
  1246. driver_init_error_exit:
  1247.     stc
  1248.     ret
  1249. check_config_exit:
  1250.  
  1251. ;
  1252. ; Initialize the 586 and the 586 data structures.
  1253. ;
  1254.     call    init_586
  1255.     jc    driver_init_error_exit
  1256.  
  1257. ; test iochrdy
  1258.     test    sys_features,SYS_MCA
  1259.     jnz    skip_iochrdy_test
  1260.     call    iochrdy_test
  1261. skip_iochrdy_test:
  1262.  
  1263.     cmp    connection_type,CONN_AUTO
  1264.     jne    no_auto_con
  1265.     call    auto_connector
  1266.     jnc    did_auto_con
  1267.     mov    dx,offset no_wire_msg
  1268.     mov    ah,9
  1269.     int    21h
  1270.     jmp    short    did_auto_con
  1271. no_auto_con:
  1272.     call    write_connector_setting_to_hardware
  1273. did_auto_con:
  1274.  
  1275. ;
  1276. ; Set up Interrupt line, start the receive unit, and Enable exp16s interrupt.
  1277. ;
  1278.     call    set_recv_isr
  1279.     call    ru_start
  1280.     enable_board_ints    ;;; only one left in broken version.
  1281.  
  1282.     mov    al, int_no        ; Get board's interrupt vector
  1283.     add    al, 8
  1284.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  1285.     jb    set_int_num        ; No.
  1286.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  1287. set_int_num:
  1288.     xor    ah, ah            ; Clear high byte
  1289.     mov    int_num, ax        ; Set parameter_list int num.
  1290.  
  1291.     clc
  1292.     ret
  1293.  
  1294. write_connector_setting_to_hardware:
  1295.     assume    ds:code
  1296.     test    sys_features,SYS_MCA
  1297.     je    isa_connector_bart
  1298.  
  1299.     mov    bl,80h
  1300.     cmp    connection_type,CONN_TPE    ;did they ask for TPE?
  1301.     je    mca_tpe_connector
  1302.     mov    bl,0
  1303. mca_tpe_connector:
  1304.  
  1305.     call    enable_slot
  1306.     mov    dx,102h            ;stuff the AUI/Other bit in.
  1307.     in    al,dx
  1308.     and    al,not 04h
  1309.     cmp    connection_type,CONN_AUI
  1310.     je    mca_tpe_connector_1
  1311.     or    al,04h
  1312. mca_tpe_connector_1:
  1313.     out    dx,al
  1314.  
  1315.     mov    dx,103h            ;stuff the BNC/TPE bit in.
  1316.     in    al,dx
  1317.     and    al,not 80h
  1318.     cmp    connection_type,CONN_BNC
  1319.     je    mca_tpe_connector_2
  1320.     or    al,80h            ;<>0 means TPE
  1321. mca_tpe_connector_2:
  1322.     out    dx,al
  1323.     call    disable_slot
  1324.  
  1325.     jmp    no_connector_bart
  1326. isa_connector_bart:
  1327.     cmp    board_id,BART_Board_ID    ;a real BART?
  1328.     je    no_connector_bart    ;yes, it doesn't *have* an ECR1.
  1329.     mov    bp,io_addr
  1330.     lea    dx,ECR1[bp]
  1331.     in    al,dx
  1332.     and    al,not 82h        ;turn off Other/not_AUI (read as
  1333.                     ;   MCA/ISA), and TPE/not_BNC
  1334.     cmp    connection_type,CONN_AUI
  1335.     je    set_connector_bart
  1336.     or    al,80h            ;set Other/not_AUI
  1337.     cmp    connection_type,CONN_BNC
  1338.     je    set_connector_bart
  1339.     or    al,02h            ;set TPE/not_BNC
  1340. set_connector_bart:
  1341.     out    dx,al
  1342. no_connector_bart:
  1343.  
  1344.     mov    cx,10            ;10*10 milliseconds = 100 millis
  1345.     cmp    connection_type,CONN_AUI
  1346.     jne    set_connector_delay
  1347.     mov    cx,50            ;50*10 milliseconds = 500 millis
  1348. set_connector_delay:
  1349. ; Our delay procedure can not accept a value over 27 milliseconds,
  1350. ; so we use a loop to delay the 100 milliseconds.
  1351. set_connector_delay_1:
  1352.     push    cx
  1353.     mov    di, ten_mils
  1354.     call    eeprom_delay
  1355.     pop    cx
  1356.     loop    set_connector_delay_1
  1357.     ret
  1358.  
  1359.  
  1360. ; int number to IRQ translate table.
  1361. IRQ_xlat_table    LABEL    BYTE
  1362.     db     12, 2, 3, 4, 5, 10, 11, 15
  1363.  
  1364. io_addresses    label word
  1365.     dw    300h,310h,320h,330h,340h,350h,360h,370h
  1366.     dw    200h,210h,220h,230h,240h,250h,260h,270h
  1367.     dw    0
  1368.  
  1369. enable_slot:
  1370.     mov    al,chan_sel
  1371.     out    96h, al            ; select channel
  1372.     mov    al, 0ffh
  1373.     out    94h, al            ; protect system board
  1374.     ret
  1375.  
  1376. disable_slot:
  1377.     xor    al,al            ;disable pos
  1378.     out    96h,al
  1379.     ret
  1380.  
  1381.     public    parse_args
  1382. parse_args:
  1383. ;exit with nc if all went well, cy otherwise.
  1384.     test    sys_features,SYS_MCA
  1385.     jne    parse_args_mc
  1386.     jmp    parse_args_1
  1387.  
  1388. parse_args_mc:
  1389. ;The following code to read the POS registers is courtesy of Racal-Interlan.
  1390.  
  1391. ; channel selector resides at io 96h
  1392. ; POS register base is at io 100h
  1393. ; EXP16/MC ID is 0628bh
  1394.  
  1395. ; search thro' the slots for a EXP16/MC card
  1396.     mov    cx, 8            ; for all channels(slots)
  1397.  
  1398. ; channel select value for slots 0,1,2.. is 8,9,A etc
  1399. ; start with slot 0, and then 7,6,5,4,3,2,1
  1400. get_05:
  1401.     mov    ax, cx            ; channel number
  1402.     or    ax, 08h            ; reg. select value
  1403.     mov    chan_sel,al        ; save each one, the LAST will right
  1404.  
  1405. ; read adapter id
  1406.     call    enable_slot
  1407.     mov    dx, 101h
  1408.     in    al, dx            ; adapter id - ms byte
  1409.     mov    ah, al
  1410.     dec    dx
  1411.     in    al, dx            ; adapter id - ls byte
  1412.  
  1413. ; Check if EXP16/MC
  1414.     cmp    ax, 0628bh
  1415.     je    get_10
  1416.     loop    get_05
  1417.  
  1418.     call    disable_slot
  1419.  
  1420.     mov    dx,offset Board_Not_Installed
  1421.     stc
  1422.     ret
  1423.  
  1424. get_10:
  1425. ; found our Adapter
  1426.     call    write_pos_to_eeprom
  1427.  
  1428.     clc
  1429.     ret
  1430.  
  1431. parse_args_1:
  1432.     mov    di,offset io_addr
  1433.     call    get_number
  1434.     clc
  1435.     ret
  1436.  
  1437.     include    exp16mca.asm
  1438.  
  1439. ;-----------------------------------------------------------------------------
  1440. ; It is safe to assume that the command unit is up and running ready
  1441. ; for the first send.  And that there are at least two send buffers 
  1442. ; available.
  1443. ;
  1444. ; This procedure works by sending a 64 byte packet to itself.  We do not turn
  1445. ; on loopback, so we do not expect to see a receive.  Instead, we
  1446. ; expect to see that the send completed OK.  If the send does not complete OK, 
  1447. ; then this routine switches to other connectors and the test is repeated. 
  1448. ;-----------------------------------------------------------------------------
  1449. auto_connector:
  1450.  
  1451. ; Let's start doing the test send with AUI option first.  If we tried BNC
  1452. ; first, and they were using AUI, it would seem like the BNC worked.  So
  1453. ; we switch to AUI, which turns off the BNC power supply.
  1454.     MOV    connection_type, CONN_AUI
  1455.     CALL    write_connector_setting_to_hardware
  1456.  
  1457. ; Test connection to see if it works.  Jump if it does.
  1458.     call    test_send
  1459.     clc
  1460.     je    auto_connector_exit
  1461.  
  1462. ; Toggle AUI/Other setting and try to send a packet.  Jump if send 
  1463. ; works.  Now try sending on BNC.
  1464.     MOV    connection_type, CONN_BNC
  1465.     CALL    write_connector_setting_to_hardware
  1466.     call    test_send
  1467.     clc
  1468.     je    auto_connector_exit
  1469.  
  1470. ; Here if we just tried a send the BNC.  If this is 
  1471. ; a three connector card, then we toggle the BNC/TPE setting.
  1472. ; Jump if connection is found.
  1473.     MOV    connection_type, CONN_TPE
  1474.     CALL    write_connector_setting_to_hardware
  1475.     call    test_send
  1476.     clc
  1477.     je    auto_connector_exit
  1478.     stc
  1479. auto_connector_exit:
  1480.     ret
  1481.  
  1482.  
  1483. test_packet    label    byte
  1484.     db    EADDR_LEN dup(?)
  1485.     db    EADDR_LEN dup(?)
  1486.     db    00h,2eh            ;A 46 in network order
  1487.     db    0,0            ;DSAP=0 & SSAP=0 fields
  1488.     db    0f3h,0            ;Control (Test Req + P bit set)
  1489.  
  1490. ; This procedure sends a packet on the wire and wait for the send to
  1491. ; complete.  It the checks to see if the send completed OK and returns
  1492. ; the results.
  1493. test_send:
  1494.  
  1495.     mov    si,offset rom_address    ;set the destination address.
  1496.     movseg    es,cs
  1497.     mov    di,offset test_packet
  1498.     repmov    EADDR_LEN
  1499.     mov    si,offset rom_address    ;set the source address.
  1500.     repmov    EADDR_LEN
  1501.  
  1502.     mov    cx,60
  1503.     mov    si,offset test_packet
  1504.     call    send_pkt
  1505.  
  1506.     call    ReadTickCounter
  1507.     mov    cx, ax
  1508.  
  1509.     mov    bp,io_addr
  1510.     lea    dx, [bp].@TxCB_Status
  1511. send_test_wait:
  1512.     in    ax,dx
  1513.     test    ax,8000h        ;did it finish?
  1514.     jne    send_test_done
  1515.  
  1516. ; See if we have been here for a millisecond.  Jump if not.
  1517.     call    ReadTickCounter
  1518.     neg    ax
  1519.     add    ax, cx
  1520.     cmp    ax, one_mil
  1521.     jb    send_test_wait
  1522.  
  1523.     in    ax,dx            ;get the transmit status back again.
  1524.  
  1525. send_test_done:
  1526.  
  1527.     mov    cx, ax            ; Save status in CX.
  1528.  
  1529.     xor    ax, ax            ; Clear the transmit command block status.
  1530.     out    dx, ax
  1531.  
  1532. ; Send is complete.  Get the status and compare to OK send and return.
  1533. ; Save flags for return.
  1534.  
  1535.     and    cx, 0f000h
  1536.     cmp    cx, 0a000h
  1537.     ret
  1538.  
  1539. no_wire_msg        db    "***Unable to detect a cable on any connector***",CR,LF,'$'
  1540. bnc_connector_msg    db    "Using the BNC connector",CR,LF,'$'
  1541. aui_connector_msg    db    "Using the AUI connector",CR,LF,'$'
  1542. tpe_connector_msg    db    "Using the twisted-pair connector",CR,LF,'$'
  1543.  
  1544. _8_bit_slot_msg    db    "The board is in an 8-bit slot",CR,LF,'$'
  1545. _16_bit_slot_msg    db    "The board is in a 16-bit slot",CR,LF,'$'
  1546.  
  1547. badset_msg    db    "Set Address Command Failed",CR,LF,'$'
  1548.  
  1549.  
  1550.     public    print_parameters
  1551. print_parameters:
  1552.     mov    di,offset int_no
  1553.     mov    dx,offset int_no_name
  1554.     call    print_number
  1555.     mov    io_addr.segm,0
  1556.     mov    di,offset io_addr
  1557.     mov    dx,offset io_addr_name
  1558.     call    print_number
  1559.  
  1560.     mov    dx,offset bnc_connector_msg    ;print the connection type.
  1561.     cmp    connection_type,CONN_BNC
  1562.     je    print_parameters_1
  1563.     mov    dx,offset aui_connector_msg
  1564.     cmp    connection_type,CONN_AUI
  1565.     je    print_parameters_1
  1566.     mov    dx,offset tpe_connector_msg
  1567. print_parameters_1:
  1568.     mov    ah,9
  1569.     int    21h
  1570.  
  1571.     mov    dx,offset _16_bit_slot_msg    ;print the slot size.
  1572.     cmp    _16_not_8_bit_slot,0
  1573.     jne    print_parameters_2
  1574.     mov    dx,offset _8_bit_slot_msg
  1575. print_parameters_2:
  1576.     mov    ah,9
  1577.     int    21h
  1578.  
  1579.     ret
  1580.  
  1581.  
  1582. init_586:
  1583. ;enter with bp=io_addr, 586 reset.
  1584.  
  1585. ;
  1586. ; Set the number of transmit and receive buffers according to the
  1587. ; amount of RAM on the adapter.
  1588. ;
  1589.     MOV    AX, Number_of_Tx_Buffers
  1590.     MOV    BX, num_rx_buf_32k
  1591.  
  1592.     cmp    _64K_not_32K,0
  1593.     je    save_number_of_buffers
  1594.  
  1595.     MOV    BX, num_rx_buf_64k
  1596.  
  1597. save_number_of_buffers:
  1598.  
  1599.     MOV    TxBufferCount, AX
  1600.     MOV    RxBufferCount, BX
  1601. ;
  1602. ; initialize SCP.  Move IO frame to top of SCP.
  1603. ;
  1604.     LEA    DX, [bp].@SMB_Ptr
  1605.     MOV    AX, OFFSET scp
  1606.     OUT    DX, AX
  1607. ;
  1608. ; Write initial SCP values:
  1609. ;    bus width    0 = 16 bit   1 = 8 bit.
  1610. ;    ISCP address    always found at address 000000.
  1611. ;
  1612.     LEA    DX, [BP].@SCP_SystemBus
  1613.     MOV    AL, bus_width
  1614.     OUT    DX, AX
  1615.  
  1616.     LEA    DX, [BP].@SCP_ISCP_Ptr_low
  1617.     XOR    AX, AX
  1618.     OUT    DX, AX
  1619.     LEA    DX, [BP].@SCP_ISCP_Ptr_high
  1620.     OUT    DX, AX
  1621.  
  1622. ;
  1623. ; Initialize ISCP.  Move IO frame to top of ISCP.  NOTE: AX falls
  1624. ; through as zero.
  1625. ;
  1626.     LEA    DX, [bp].@SMB_Ptr
  1627.     OUT    DX, AX
  1628. ;
  1629. ; Write initial ISCP values:
  1630. ;    ISCP BUSY    1 = Indicates 586 is in initialization
  1631. ;            process.  586 sets this byte to 0 when
  1632. ;            initialization is complete.
  1633. ;
  1634. ;    SCB address     Always 000008
  1635. ;
  1636.     LEA    DX, [BP].@iscp_busy
  1637.     MOV    AX, initialize_586
  1638.     OUT    DX, AX
  1639.  
  1640.     LEA    DX, [BP].@ISCP_SCB_Ptr_low
  1641.     XOR    AX, AX
  1642.     OUT    DX, AX
  1643.     LEA    DX, [BP].@ISCP_SCB_Ptr_high
  1644.     OUT    DX, AX
  1645.     LEA    DX, [BP].@iscp_scb_offset
  1646.     MOV    AX, OFFSET scb
  1647.     OUT    DX, AX
  1648.  
  1649. ;
  1650. ; Initialize SCB.  Move Write Ptr to top of SCB.  NOTE: AX falls
  1651. ; through as offset to SCB.
  1652. ;
  1653.     XOR    AX, AX
  1654.     LEA    DX, [BP].@SCB_Status
  1655.     OUT    DX, AX
  1656.     LEA    DX, [BP].@SCB_Command
  1657.     OUT    DX, AX
  1658.     LEA    DX, [BP].@SCB_CommandList
  1659.     OUT    DX, AX
  1660.     LEA    DX, [BP].@SCB_RecBlockList
  1661.     OUT    DX, AX
  1662.     LEA    DX, [BP].@SCB_CRC_Errors
  1663.     OUT    DX, AX
  1664.     LEA    DX, [BP].@SCB_ALN_Errors
  1665.     OUT    DX, AX
  1666.     LEA    DX, [BP].@SCB_RSC_Errors
  1667.     OUT    DX, AX
  1668.     LEA    DX, [BP].@SCB_OVR_Errors
  1669.     OUT    DX, AX
  1670.  
  1671. ;
  1672. ; Initialize Receive Block(s).  First set head pointer and link from
  1673. ; SCB to first frame descriptor.  NOTE: IO frame points to ISCB.
  1674. ; The SCB link field can be addresses becasue the SCB is physically
  1675. ; contiguous to the ISCB.
  1676. ;
  1677.     mov    ax,offset Receive_Blocks
  1678.     lea    dx, [bp].@SCB_RecBlockList    ;IO address of SCB RF link
  1679.     out    dx, ax
  1680.  
  1681. ;
  1682. ; Initialize the frame descriptor structures.  Move the Write ptr
  1683. ; the top of the current frame descriptor.  AX falls through with the
  1684. ; offset to the first frame descriptor.  DI is used to keep track of
  1685. ; the address of the current frame descriptor.  The frame descriptor,
  1686. ; receive buffer descriptor, and receive buffer are all contiguous in
  1687. ; memory, and make up the frame descriptor structure.
  1688. ;
  1689.     MOV    DI, AX                ;DI is current frame descriptor
  1690.     MOV    RECEIVE_HEAD, DI
  1691.     MOV    CX, RxBufferCount        ;CX is number of frame
  1692.                         ; descriptors to initialize.
  1693. init_receive_frames:
  1694.  
  1695.     LEA    DX, [bp].@SMB_Ptr
  1696.     MOV    AX, DI                ; descriptor.
  1697.     OUT    DX, AX
  1698.  
  1699. ;
  1700. ; Init Frame Descriptor (FD).
  1701. ;
  1702.     XOR    AX, AX                ;Init frame descriptor status
  1703.     LEA    DX, [BP+4000H]
  1704.     OUT    DX, AX                ; and command to zero.
  1705.     LEA    DX, [BP+4002H]
  1706.     OUT    DX, AX
  1707.  
  1708.     MOV    AX, RECEIVE_HEAD        ;Init frame descriptors link
  1709.     CMP    CX, 1                ; to next frame descriptor.
  1710.     JE    next_receive_link        ; If this is the last receive
  1711.                         ; block, then set its link to
  1712.     LEA    AX, [DI+SIZE ReceiveBlock]    ; the first receive block.
  1713.  
  1714. next_receive_link:
  1715.  
  1716.     LEA    DX, [BP+4004H]
  1717.     OUT    DX, AX
  1718.  
  1719.     LEA    AX, [DI+OFFSET RBD_ByteCount] ;Init frame descriptors
  1720.     LEA    DX, [BP+4006H]
  1721.     OUT    DX, AX            ; link to its receive buffer descriptor.
  1722. ;
  1723. ; Init Receive Buffer Descriptor (RBD).
  1724. ;
  1725.     LEA    DX, [BP+4008H]
  1726.     OUT    DX, AX            ;Init the RBD Actual count to zero.
  1727.  
  1728.     MOV    AX, -1            ;Init the RBD link to next RBD
  1729.     LEA    DX, [BP+400AH]
  1730.     OUT    DX, AX            ; to minus 1 (unused link).
  1731.  
  1732.     LEA    AX, [DI+RB_Data]    ;Init the RDB link to the data
  1733.     LEA    DX, [BP+400CH]
  1734.     OUT    DX, AX            ; buffer.
  1735.     XOR    AX, AX
  1736.     LEA    DX, [BP+400EH]
  1737.     OUT    DX, AX
  1738.  
  1739.     MOV    AX, RxBufferSize OR BIT_EL    ;Init the RBD count and status
  1740.     LEA    DX, [BP+8000H]
  1741.     OUT    DX, AX
  1742.  
  1743.     MOV    RECEIVE_TAIL, DI    ;Set receive tail pointer.
  1744.     ADD    DI, SIZE ReceiveBlock    ;Point DI to next frame
  1745.     LOOP    init_receive_frames    ; descriptor.
  1746. ;
  1747. ; Initialize the send block structures.  Move the Write pointer the
  1748. ; top of the current send block.  AX falls through with address of
  1749. ; first send block.  DI is used to keep track of the address of the
  1750. ; current send block.  The Transmit command block, transmit buffer
  1751. ; descriptor, and transmit buffer are all contiguous in memory, and
  1752. ; make up the send block structure.
  1753. ;
  1754.     MOV    DI, OFFSET send_blocks
  1755.     MOV    CX, TxBufferCount
  1756.  
  1757.     LEA    DX, [BP].@SMB_Ptr
  1758.     XOR    AX, AX
  1759.     OUT    DX, AX
  1760.  
  1761.     MOV    AX, DI
  1762.     LEA    DX, [BP].@SCB_CommandList
  1763.     OUT    DX, AX
  1764.  
  1765. init_send_blocks:
  1766.  
  1767.     LEA    DX, [BP].@SMB_Ptr        ;Set write pointer to send
  1768.     MOV    AX, DI                ; block.
  1769.     OUT    DX, AX
  1770. ;
  1771. ; Init Transmit Control Block (TCB).
  1772. ;
  1773.     XOR    AX, AX            ;Init transmit control block
  1774.     LEA    DX, [BP+4000H]
  1775.     OUT    DX, AX            ; status to zero.
  1776.  
  1777.     LEA    DX, [BP+4002H]
  1778.     OUT    DX, AX            ;Init transmit control block
  1779.                     ; command to anything.  The
  1780.     MOV    AX, offset send_blocks    ; Init transmit control block
  1781.     CMP    CX, 1            ; link to next send block.
  1782.     JE    next_send_link        ; If this is the last send
  1783.                     ; block, then point it to
  1784.     LEA    AX, [DI+SIZE SendBlock]    ; the first block.
  1785.  
  1786. next_send_link:
  1787.  
  1788.     LEA    DX, [BP+4004H]
  1789.     OUT    DX, AX
  1790.  
  1791.     LEA    AX, [DI+OFFSET TBD_ByteCount]    ;Init transmit control block
  1792.     LEA    DX, [BP+4006H]
  1793.     OUT    DX, AX                ; link to Transmit Buffer
  1794.                         ; descriptor.
  1795. ;
  1796. ; Init Transmit Buffer Descriptor (TBD).
  1797. ;
  1798.     LEA    DX, [BP+4008H]
  1799.     OUT    DX, AX            ;Init Transmit Buffer Descriptor
  1800.                     ;  byte count to anything
  1801.     MOV    AX, -1            ;Init Transmit Buffer Descriptor
  1802.     LEA    DX, [BP+400AH]
  1803.     OUT    DX, AX            ;  link to next TBD.
  1804.  
  1805.     LEA    AX, [DI+OFFSET TB_Data]    ;Init Transmit Buffer Descriptor
  1806.     LEA    DX, [BP+400CH]
  1807.     OUT    DX, AX            ; link to transmit
  1808.     XOR    AX, AX            ; buffer.  Low part of pointer
  1809.     LEA    DX, [BP+400EH]
  1810.     OUT    DX, AX            ; is done first.
  1811.  
  1812.     ADD    DI, SIZE SendBlock        ;Point DI to next send block
  1813.     LOOP    init_send_blocks        ; and loop to initialize it.
  1814.  
  1815. ;
  1816. ; Enable loopback to insure nothing acidently hits the cable while
  1817. ; the 586 gets initialized.
  1818. ;
  1819.     LEA    DX, [BP].@Config
  1820.     IN    AX, DX
  1821.     OR    AL, loopback_enable
  1822.     OUT    DX, AL
  1823. ;
  1824. ; Free the 586 from reset.
  1825. ;
  1826.     CALL    free_586_reset
  1827. ;
  1828. ; Initialize and configure the 586.  Carry flag set means error and
  1829. ; dx will point to error message.
  1830. ;
  1831.     CALL    init_cmd
  1832.     mov    dx,offset bad_init_msg
  1833.     jc    init_exp16_ram_exit
  1834.  
  1835.     CALL    configure_command
  1836.     mov    dx,offset bad_config_msg
  1837.     jc    init_exp16_ram_exit
  1838.  
  1839.     CALL    diagnose_command
  1840.     jc    init_exp16_ram_exit
  1841.  
  1842.     movseg    es,cs
  1843.     mov    si,offset rom_address
  1844.     mov    cx,EADDR_LEN
  1845.     call    set_address
  1846.     jnc    sa_ok
  1847.  
  1848.     mov    dx,offset badset_msg
  1849.     mov    ah,9
  1850.     int    21h
  1851. sa_ok:
  1852. ;
  1853. ; Disable loopback.
  1854. ;
  1855.     LEA    DX, [BP].@Config
  1856.     IN    AX, DX
  1857.     AND    AL, NOT loopback_enable
  1858.     OUT    DX, AL
  1859.  
  1860.     clc
  1861.     ret
  1862.  
  1863. init_exp16_ram_exit:
  1864.     stc
  1865.     RET
  1866.  
  1867.  
  1868. ; This procedure must wait until the ASIC finishes reset.  This will take
  1869. ; around 240 uSec.  This loop will time out after 500 uSec.
  1870. ;
  1871.     five_hundred_micros    EQU    1194
  1872. ;
  1873. reset_board:
  1874. ;enter with bp=io_addr
  1875.  
  1876.     LEA    DX, [BP].@EEPROM_Ctrl
  1877.     MOV    AL, ASIC_Reset
  1878.     OUT    DX, AL
  1879.  
  1880.     XOR    AL, AL
  1881.     OUT    DX, AL
  1882.  
  1883. ;
  1884. ; Get current tick count.  This loop will wait for 500 uSec to pass
  1885. ; before failing.
  1886. ;
  1887.     CALL    ReadTickCounter
  1888.     MOV    BX, AX
  1889.  
  1890. reset_delay:
  1891.  
  1892.     PUSH    BX
  1893.     LEA    DX, [BP].@ID_Port    ; Set DX to the auto-id port.
  1894.     CALL    check_for_exp16_hardware
  1895.     POP    BX
  1896.  
  1897.     CMP    AX, BART_Board_ID
  1898.     JE    reset_board_exit
  1899.  
  1900.     CALL    ReadTickCounter
  1901.     NEG    AX
  1902.     ADD    AX, BX
  1903.     CMP    AX, five_hundred_micros
  1904.     JB    reset_delay
  1905.  
  1906.     mov    dx, offset reset_error
  1907.     stc
  1908.     RET
  1909.  
  1910. reset_board_exit:
  1911.  
  1912.     MOV    BX, AX
  1913.     clc
  1914.     RET
  1915.  
  1916.  
  1917. reset_586:
  1918. ;enter with bp = io_addr
  1919.     lea    dx, [bp].@EEPROM_Ctrl
  1920.     mov    al, _586_Reset
  1921.     out    dx, al
  1922.     ret
  1923.  
  1924.  
  1925. free_586_reset:
  1926. ;enter with bp = io_addr
  1927.     lea    dx, [bp].@EEPROM_Ctrl
  1928.     xor    al, al
  1929.     out    dx, al
  1930.     ret
  1931.  
  1932. check_for_exp16_hardware:
  1933. ;enter with dx = ID port (or maybe shadow ID port).
  1934. ;
  1935. ; BX will have board ID when the loop is done.  CX is the loop count.
  1936. ;
  1937.     XOR    BX, BX
  1938.     MOV    CX, 4
  1939.  
  1940. get_board_id_loop:
  1941. ;
  1942. ; Init registers for loop.  CX needs to be used in the loop, and AH
  1943. ; could be set from the last loop.
  1944. ;
  1945.     PUSH    CX
  1946.     XOR    AH, AH
  1947. ;
  1948. ; Read ID port.  See description above.
  1949. ;
  1950.     IN    AL, DX
  1951. ;
  1952. ; Make nibble ID a shift count in CL.
  1953. ;
  1954.     MOV    CL, AL
  1955.     AND    CL, 00000011B
  1956.     SHL    CL, 1
  1957.     SHL    CL, 1
  1958. ;
  1959. ; Move ID nibble to low order bits of AX, then shift then into place.  Put
  1960. ; the board ID nibble into BX.  After four passes, BX will have board ID.
  1961. ;
  1962.     SHR    AL, 1
  1963.     SHR    AL, 1
  1964.     SHR    AL, 1
  1965.     SHR    AL, 1
  1966.     SHL    AX, CL
  1967.     OR    BX, AX
  1968. ;
  1969. ; Recover loop count, and loop.
  1970. ;
  1971.     POP    CX
  1972.     LOOP    get_board_id_loop
  1973. ;
  1974. ; Return board ID in AX.
  1975. ;
  1976.     MOV    AX, BX
  1977.     RET
  1978.  
  1979.  
  1980. ;
  1981. ; Command #1:  Initialize
  1982. ;
  1983. init_cmd:
  1984.     XOR    AX, AX                ; Init command
  1985.     MOV    BX, BIT_CX + BIT_CNA        ; status
  1986.     CALL    issue_command
  1987.     RET
  1988.  
  1989. diagnose_command:
  1990. ;return nc if no problem, else cy,dx->error message.
  1991. ;
  1992. ; Set up individual address command block.
  1993. ;
  1994.     MOV    BX, BIT_EL+GA_diagnose
  1995.     CALL    setup_command_block
  1996. ;
  1997. ; Execute the diagnose command.
  1998. ;
  1999.     MOV    AX, CUC_Start
  2000.     MOV    BX, BIT_CNA
  2001.     CALL    issue_command
  2002. ;
  2003. ; Check diagnostics results.
  2004. ;
  2005.     LEA    DX, [BP].@SMB_Ptr        ;Move IO frame to the command
  2006.     MOV    AX, OFFSET cb            ; command block.
  2007.     OUT    DX, AX
  2008.  
  2009.     LEA    DX, [BP].@mem_loc_0        ;Read in the diagnose status
  2010.     IN    AX, DX                ; word.
  2011. ;
  2012. ; Assume 586 failed the test.  Set AX to an error message and exit
  2013. ; with the zero bit cleared.
  2014. ;
  2015.     test    ax, 0800H            ;Test failure bit.  If set,
  2016.     jnz    diagnose_error            ; then error exit.
  2017.     clc
  2018.     ret
  2019. diagnose_error:
  2020.     mov    dx,offset _586_diagnostic_failure
  2021.     stc
  2022.     ret
  2023.  
  2024.  
  2025. ;
  2026. ; Command #4:  RU_START
  2027. ;
  2028. ru_start:
  2029. ;
  2030. ; Set SCBs pointer to receive blocks at head of list.
  2031. ;
  2032.     lea    dx, [bp].@SCB_RFA        ;Set pointer to receive blocks
  2033.     mov    ax, receive_head        ; to the head of the receive
  2034.     out    dx, ax                ; block list.
  2035. ;
  2036. ; Signal 586 to start the receive unit.  cmd_clear leaves DX pointing
  2037. ; to SCB command register.
  2038. ;
  2039.     cmd_clear
  2040.     mov    ax, ruc_start
  2041.     out    dx, ax
  2042.     issue_CA
  2043.     ret
  2044.  
  2045.  
  2046. find_a_board:
  2047.     mov    bx,offset io_addresses
  2048. no_exp16_here:
  2049.     mov    bp,[bx]
  2050.     cmp    bp,0
  2051.     je    no_exp16s
  2052.     inc    bx
  2053.     inc    bx
  2054.     push    bx
  2055.     call    reset_board
  2056.     pop    bx
  2057.     jc    no_exp16_here
  2058.  
  2059.     clc
  2060.     ret
  2061.  
  2062. no_exp16s:
  2063.     stc
  2064.     ret
  2065.  
  2066. get_system_info:
  2067. ;exit with zr if okay, or nz, dx -> error message if not okay.
  2068.     cmp    io_addr,-1
  2069.     jne    addr_override
  2070.     call    find_a_board
  2071.     jnc    board_id_ok
  2072.     jmp    bad_or_no_board
  2073.  
  2074. addr_override:
  2075.  
  2076.     MOV    bp, io_addr
  2077.  
  2078. ;
  2079. ; Next, get the exp16 board ID.  If the ID is not what we expect, then
  2080. ; exit with error code in AX.
  2081. ;
  2082.     call    reset_board
  2083.     jnc    board_id_ok
  2084. ;
  2085. ; Could search for exp16 board, but we error exit instead.
  2086. ;
  2087. bad_or_no_board:
  2088.  
  2089.     mov    dx, offset board_not_installed
  2090.     stc
  2091.     JMP    SHORT get_system_info_exit
  2092.  
  2093. board_id_ok:
  2094.     mov    io_addr,bp
  2095.  
  2096.     LEA    DX, [BP].@ID_Port    ; Set DX to the auto-id port.
  2097.     or    DX,3000h        ;use the shadow port
  2098.     CALL    check_for_exp16_hardware
  2099.     mov    board_id,ax
  2100.  
  2101. ;
  2102. ; Since the software will be reading the EEPROM during the
  2103. ; initialization, the 586 needs to be inactive.  This is because the
  2104. ; control lines to the EEPROM are shared between the 586 and this
  2105. ; software.  To keep from getting fouled up, the 586 reset line is
  2106. ; asserted here (now that we have a base IO address, and we know that
  2107. ; the hardware is present).  The 586 is not released from reset until
  2108. ; after its data structures are intialized.
  2109. ;
  2110.     CALL    reset_586
  2111. ;
  2112. ; Validate the EEPROM by doing a checksum.
  2113. ;
  2114.     mov    cx, 40h
  2115.     CALL    check_eeprom
  2116.     JC    get_system_info_exit
  2117. ;
  2118. ; Get the amount of memory on the adapter.
  2119. ;
  2120.     CALL    test_buffer_memory
  2121.     JC    get_system_info_exit
  2122.  
  2123. ;
  2124. ; Get the connection type.  If carry clear, then AL has connection
  2125. ; type.  Otherwise AX has error code.
  2126. ;
  2127.     CALL    get_connection_type
  2128.     JC    get_system_info_exit
  2129.     MOV    connection_type, AL
  2130. ;
  2131. ; Read the Ethernet address out of the EEPROM.
  2132. ;
  2133.     MOV    AX, EE_ETHERNET_ADD_HIGH
  2134.     CALL    read_eeprom
  2135.     xchg    ah,al
  2136.     MOV    word ptr rom_address[0], AX
  2137.  
  2138.     MOV    AX, EE_ETHERNET_ADD_MID
  2139.     CALL    read_eeprom
  2140.     xchg    ah,al
  2141.     MOV    word ptr rom_address[2], AX
  2142.  
  2143.     MOV    AX, EE_ETHERNET_ADD_LOW
  2144.     CALL    read_eeprom
  2145.     xchg    ah,al
  2146.     MOV    word ptr rom_address[4], AX
  2147.  
  2148.     mov    ax,EE_INT
  2149.     call    read_eeprom
  2150.     mov    cl,EE_SHIFT
  2151.     shr    ax,cl
  2152.     mov    encoded_int_no,al
  2153.     mov    bx,offset irq_xlat_table
  2154.     xlat
  2155.     mov    int_no,al
  2156.  
  2157. ;
  2158. ; Get the Slot width.  If carry clear, then AL has the slot width.
  2159. ; Otherwise AX has error code.
  2160. ;
  2161.     LEA    DX, [BP].@Config
  2162.     IN    AL, DX
  2163. ;
  2164. ; Slot width is found in the adapters configuration register.
  2165. ;
  2166.     and    al, slot_width_mask
  2167.     mov    _16_not_8_bit_slot, al
  2168.  
  2169.     clc
  2170.     ret
  2171.  
  2172. get_system_info_exit:
  2173. ;we only ever get here with cy set.
  2174.     RET
  2175.  
  2176. ;
  2177. ;
  2178. ; Return connection type in AL with carry clear.
  2179. ;
  2180. ;
  2181. get_connection_type:
  2182.  
  2183.     cmp    board_id,BART_Board_ID    ;a real BART?
  2184.     je    get_auto_cnt_exit    ;yes, it doesn't *have* an ECR1.
  2185.  
  2186.     MOV    AX, AUTO_CON_ADDRESS    ;get the auto-connection bit.
  2187.     CALL    read_eeprom
  2188.     TEST    AX, AUTO_CON_MASK    ;set?
  2189.     Je    get_auto_cnt_exit    ;no, okay.
  2190.     mov    bl,CONN_AUTO        ;yes, we should autosense the connector.
  2191.     jmp    short get_connection_type_ret
  2192. get_auto_cnt_exit:
  2193.  
  2194. ;
  2195. ; Read the connection address from the EEPROM.
  2196. ;
  2197.     MOV    AX, connection_address
  2198.     CALL    read_eeprom        ;Read_eeprom does not trash DI
  2199.  
  2200. ;
  2201. ; Assume AUI type connection.  Check connection fields to see if this
  2202. ; is a BNC connection.  Jump if it is BNC.
  2203. ;
  2204.     MOV    BL, CONN_AUI
  2205.     TEST    AX, CONNECTION_FIELD
  2206.     JZ    get_connection_type_ret
  2207.  
  2208. ;
  2209. ; Here if NOT BNC.  Must read another EEPROM word to tell if AUI or
  2210. ; TPE.  Assume AUI and then check for TPE.
  2211. ;
  2212.     MOV    AX, tpe_address
  2213.     CALL    read_eeprom        ;Read_eeprom does not trash DI
  2214.  
  2215. ;
  2216. ; Check for AUI connection.
  2217. ;
  2218.     mov    bl,CONN_BNC
  2219.     TEST    AX, TPE_type_field
  2220.     JZ    get_connection_type_ret
  2221.  
  2222. ;
  2223. ; Here if TPE type connection.
  2224. ;
  2225.     MOV    BL, CONN_TPE
  2226.  
  2227. get_connection_type_ret:
  2228.  
  2229.     MOV    AL, BL
  2230.  
  2231.     CLC
  2232.     RET
  2233.  
  2234.  
  2235. ;
  2236. ;
  2237. ; Do a checksum on the EEPROM.
  2238. ;
  2239. ; The checksum is the same as the board ID.
  2240. ;
  2241. check_eeprom:
  2242. ;enter with bp=io_addr, cx = count of bytes to sum starting at 0.
  2243. ;exit with nc if okay, cy, dx -> error message if not.
  2244.  
  2245.     xor    bx, bx
  2246.  
  2247. checksum_loop:
  2248.  
  2249.     mov    ax, cx
  2250.     dec    ax
  2251.     call    read_eeprom
  2252.  
  2253.     add    bx, ax
  2254.     loop    checksum_loop
  2255.  
  2256.     cmp    bx, BART_Board_ID
  2257.     jne    checksum_error
  2258.  
  2259.     clc
  2260.     ret
  2261.  
  2262. checksum_error:
  2263.     mov    dx,offset eeprom_checksum_error
  2264.     stc
  2265.     ret
  2266.  
  2267.  
  2268. test_buffer_memory:
  2269. ;enter with bp=io_addr
  2270. ;exit with nc and al=_64k_not_32k if no error, or cy and di -> address in error.
  2271.  
  2272. ; Set up SI with the maximum number of words to test.  If there is an
  2273. ; error testing the high 32K of memory, then we will restart the
  2274. ; test at 32K.  When the tests pass, the memory size is passed back
  2275. ; in AX.
  2276. ;
  2277.     mov    si, 64 * (1024/2)
  2278. ;
  2279. ; Warm up the buffer memory with 16 word writes.
  2280. ;
  2281.     mov    cx, 16
  2282.     call    write_zeros
  2283.  
  2284.     cmp    cs:is_186,0
  2285.     jne    start_memory_tests
  2286.  
  2287. restart_memory_tests:
  2288. ;
  2289. ; Here if error testing memory and SI is set to 64K buffer size.
  2290. ; We restart the tests for 32K buffer only.  If an error occurs
  2291. ; with SI set to 32K, then a memory error is reported.
  2292. ;
  2293.     mov    si, 32 * (1024/2)
  2294.  
  2295. start_memory_tests:
  2296. ;
  2297. ; Zero RAM.  Set write pointer to the base address and then fill the
  2298. ; bufffer memory with zeros.
  2299. ;
  2300.     mov    cx, si
  2301.     call    write_zeros
  2302.  
  2303.     call    word_memory_test_pattern
  2304.     jc    buffer_mem_error_exit
  2305.  
  2306.     cmp    cs:is_186,0
  2307.     je    _8088_quick_exit
  2308.  
  2309.     mov    cx, si
  2310.     call    write_zeros
  2311.  
  2312.     call    byte_memory_test_pattern
  2313.     jc    buffer_mem_error_exit
  2314.  
  2315. _8088_quick_exit:
  2316. ;
  2317. ; Zero RAM.  Set write pointer to the base address and then fill the
  2318. ; bufffer memory with zeros.
  2319. ;
  2320.     mov    cx, si
  2321.     call    write_zeros
  2322.  
  2323. ;
  2324. ; Set _64K_not_32K to the size of the memory that passed diagnostics.
  2325. ;
  2326.     cmp    si, 32 * (1024/2)    ;did we quit at 32K
  2327.     je    buffer_mem_exit        ;yes, we only have 32K.
  2328.  
  2329.     mov    _64K_not_32K,1        ;no, we must have 64K.
  2330.  
  2331. buffer_mem_exit:
  2332.     clc
  2333.     ret
  2334.  
  2335. buffer_mem_error_exit:
  2336. ;
  2337. ; If error occured, and SI is not set for 32K, then retry tests with
  2338. ; SI set for 32K.  If the error occurs and the size is 32K, then the
  2339. ; Exp16 board memory is bad.
  2340. ;
  2341.     CMP    SI, 32 * (1024/2)
  2342.     JNE    restart_memory_tests
  2343.  
  2344.     MOV    DX, OFFSET buffer_memory_error
  2345.     STC    ;Set carry to indicate error.
  2346.     RET
  2347.  
  2348.  
  2349. write_zeros:
  2350. ;enter with bp=io_addr, cx=number of zero words to write.
  2351. ;
  2352. ; Move write pointer to the beginning of the buffer memory.
  2353. ;
  2354.     LEA    DX, [BP].@Write_Ptr
  2355.     XOR    AX, AX
  2356.     OUT    DX, AX
  2357. ;
  2358. ; Set DX to the data register and write out zeros CX times.
  2359. ;
  2360.     mov    dx, bp            ;@Data_Reg
  2361. warm_up:
  2362.     out    dx, ax
  2363.     loop    warm_up
  2364.     ret
  2365.  
  2366.  
  2367. word_memory_test_pattern:
  2368. ;enter with si = number of words to test.
  2369.  
  2370. ;
  2371. ; Set CX to number of words to test.  Set BX to beginning og pattern.
  2372. ;
  2373.     MOV    CX, SI
  2374.     MOV    BX, 1
  2375.  
  2376. ;
  2377. ; Set DI to beginning of the buffer.
  2378. ;
  2379.     XOR    DI, DI
  2380.  
  2381. word_inc_pattern:
  2382.  
  2383.     CALL    loop_set_up
  2384.     IN    AX, DX
  2385.     OR    AX, AX
  2386.     JNE    word_memory_test_pattern_error
  2387.  
  2388. ;
  2389. ; Write Test Pattern.
  2390. ;
  2391.     MOV    AX, BX
  2392.     OUT    DX, AX
  2393.  
  2394. ;
  2395. ; Increment BX to next test pattern value.
  2396. ;
  2397.     ADD    BX, 3
  2398.  
  2399. ;
  2400. ; Increment DI to next test memory location.
  2401. ;
  2402.     ADD    DI, 2
  2403.     LOOP    word_inc_pattern
  2404.  
  2405. ;
  2406. ; Set Read pointer to beginning of buffer.
  2407. ;
  2408.     LEA    DX, [BP].@read_ptr
  2409.     XOR    AX, AX
  2410.     OUT    DX, AX
  2411.     MOV    DX, BP            ;@Data_Reg
  2412.  
  2413. ;
  2414. ; Set CX to number of words to test.  Set BX to beginning og pattern.
  2415. ;
  2416.     MOV    CX, SI
  2417.     MOV    BX, 1
  2418.  
  2419. word_check_pattern:
  2420.  
  2421.     IN    AX, DX
  2422.     CMP    AX, BX
  2423.     JNE    word_memory_test_pattern_error
  2424.  
  2425. ;
  2426. ; Increment BX to next test pattern value.
  2427. ;
  2428.     ADD    BX, 3
  2429.  
  2430.     LOOP    word_check_pattern
  2431.  
  2432.     CLC
  2433.     RET
  2434.  
  2435. word_memory_test_pattern_error:
  2436.  
  2437.     STC
  2438.     RET
  2439.  
  2440.  
  2441. byte_memory_test_pattern:
  2442. ;enter with si = number of bytes to test.
  2443.  
  2444. ;
  2445. ; Set CX to number of bytes to test.  Set BX to beginning of pattern.
  2446. ;
  2447.     MOV    CX, SI
  2448.     SHL    CX, 1
  2449.     MOV    BL, 1
  2450.  
  2451. ;
  2452. ; Set DI to beginning of the buffer.
  2453. ;
  2454.     XOR    DI, DI
  2455.  
  2456. byte_inc_pattern:
  2457.  
  2458.     CALL    loop_set_up
  2459.     IN    AL, DX
  2460.     OR    AL, AL
  2461.     JNE    byte_memory_test_pattern_error
  2462.  
  2463. ;
  2464. ; Write Test Pattern.
  2465. ;
  2466.     MOV    AL, BL
  2467.     OUT    DX, AL
  2468.  
  2469. ;
  2470. ; Increment BX to next test pattern value.
  2471. ;
  2472.     ADD    BL, 3
  2473.  
  2474. ;
  2475. ; Increment DI to next test memory location.
  2476. ;
  2477.     INC    DI
  2478.  
  2479.     LOOP    byte_inc_pattern
  2480.  
  2481. ;
  2482. ; Set Read pointer to beginning of buffer.
  2483. ;
  2484.     LEA    DX, [BP].@read_ptr
  2485.     XOR    AX, AX
  2486.     OUT    DX, AX
  2487.     MOV    DX, BP            ;@Data_Reg
  2488.  
  2489. ;
  2490. ; Set CX to number of bytes to test.  Set BX to beginning of pattern.
  2491. ;
  2492.     MOV    CX, SI
  2493.     SHL    CX, 1
  2494.     MOV    BL, 1
  2495.  
  2496. byte_check_pattern:
  2497.  
  2498.     IN    AL, DX
  2499.     CMP    AL, BL
  2500.     JNE    byte_memory_test_pattern_error
  2501.  
  2502. ;
  2503. ; Increment BX to next test pattern value.
  2504. ;
  2505.     add    bl, 3
  2506.  
  2507.     loop    byte_check_pattern
  2508.  
  2509.     clc
  2510.     ret
  2511.  
  2512. byte_memory_test_pattern_error:
  2513.  
  2514.     stc
  2515.     ret
  2516.  
  2517. loop_set_up:
  2518. ;enter with bp=io_addr, di=buffer address.
  2519. ;exit with ax=value at di, dx=I/O address to access buffer memory at DI
  2520.  
  2521.     PUSH    DI
  2522.  
  2523.     MOV    AX, DI            ;SMB_Ptr must be on 16 byte
  2524.     AND    AX, 0FFE0H
  2525.     AND    DI, 0001FH
  2526.  
  2527.     LEA    DX, [BP].@SMB_Ptr        ;Set IO page frame to the
  2528.     OUT    DX, AX
  2529.  
  2530.  
  2531.     TEST    DI, 0010H
  2532.     JZ    loop_set_up_1
  2533.  
  2534.     ADD    DI, @MEM_LOC_0
  2535.  
  2536. loop_set_up_1:
  2537.     AND    DI, 0FFEFH
  2538.     LEA    DX, [BP+DI].@MEM_LOC_0        ;Set DX for IO from buffer and
  2539.  
  2540.     POP    DI
  2541.  
  2542.     RET
  2543.  
  2544.  
  2545. read_eeprom:
  2546. ;enter with bp=io_addr, ax = EEPROM location.
  2547. ;exit with ax = EEPROM contents.
  2548. ;preserves di.
  2549.     push    di
  2550.     push    bx
  2551.     push    cx
  2552.  
  2553. ;  Point to EEPROM control port.
  2554.  
  2555.     lea    dx, [bp].@eeprom_ctrl
  2556.     mov    bx, ax
  2557.  
  2558. ; Select the EEPROM.  Mask off the ASIC and 586 reset bits and set
  2559. ; the ee_cs bit in the EEPROM control register.
  2560.  
  2561.     in    al, dx
  2562.     and    al, 10110010b
  2563.     or    al, ee_cs
  2564.     out    dx, al
  2565.  
  2566. ; Write out read opcode and EEPROM location.
  2567.  
  2568.     mov    ax, eeprom_read_opcode        ;Set AX to READ opcode and
  2569.     mov    cx, 3                ;Send it to the EEPROM circuit
  2570.     call    shift_bits_out
  2571.  
  2572.     mov    ax, bx                ;Tell EEPROM which register is
  2573.     mov    cx, 6                ; to be read.  6 bit address.
  2574.     call    shift_bits_out
  2575.  
  2576.     call    shift_bits_in            ;AX gets EEPROM register
  2577.  
  2578.     call    eeprom_clean_up            ;Leave EEPROM in known state.
  2579.  
  2580.     pop    cx
  2581.     pop    bx
  2582.     pop    di
  2583.     ret
  2584.  
  2585.  
  2586. ;-----------------------------------------------------------------------------
  2587. ;  Writes the specified value to the specified EEPROM register at the 
  2588. ;  specified base I/O address.
  2589. ;
  2590. ;  Entry  - BP  Base IO.
  2591. ;           AX  EEPROM location to write.
  2592. ;        BX  Value to write
  2593. ;
  2594. ;  Return - AX = 0 if no error
  2595. ;        AX = Pointer to Error message
  2596. ;
  2597. ;-----------------------------------------------------------------------------
  2598. write_eeprom:
  2599. ;enter with bp=io_addr, ax = EEPROM location, bx = new contents.
  2600. ;exit with ax = 0 if no error, ax -> error if error.
  2601. ;preserves di.
  2602.  
  2603.     push    bx
  2604.     mov    bx, ax
  2605.  
  2606.     lea    dx, [bp].@EEPROM_Ctrl    ;Point to EEPROM port.
  2607.  
  2608.     in    al, dx                  ;Select EEPROM
  2609.     and    al, 10110000b
  2610.     or    al, ee_cs
  2611.     out    dx, al
  2612.  
  2613. ; Send Erase/write enable opcode to the EEPROM.
  2614.     mov    ax, EEPROM_EWEN_opcode    ;Send erase/write enable
  2615.     mov    cx, 5            ; command to the EEPROM.
  2616.     call    shift_bits_out
  2617.  
  2618.     mov    cx, 4            ;Send 4 don't cares as
  2619.     call    shift_bits_out        ; required by the eeprom
  2620.  
  2621.     call    stand_by
  2622.  
  2623. ; Send the erase opcode to the EEPROM and wait for the command to 
  2624. ; complete.
  2625.     mov    ax, EEPROM_erase_opcode    ;Send Erase command to the
  2626.     mov    cx, 3            ; EEPROM.
  2627.     call    shift_bits_out
  2628.  
  2629.     mov    ax, bx            ;Send EEPROM location the the
  2630.     mov    cx, 6            ; EEPROM.  6 bit address.
  2631.     call    shift_bits_out
  2632.  
  2633.     call    wait_eeprom_cmd_done    ;wait for end-of-operation
  2634.     jc    write_fault_pop        ; go if error
  2635.  
  2636.     call    stand_by
  2637.  
  2638. ; Send the write opcode, location to write, and data to write to the
  2639. ; EEPROM.  Wait for the write to complete.
  2640.     mov    ax, EEPROM_write_opcode    ;Send write command to the 
  2641.     mov    cx, 3            ; EEPROM.
  2642.     call    shift_bits_out
  2643.  
  2644.     mov    ax, bx            ;Send the EEPROM location to
  2645.     mov    cx, 6            ; the EEPROM.  5 bit address.
  2646.     call    shift_bits_out
  2647.  
  2648.     pop    ax            ;Send data to write to the 
  2649.     mov    cx, 16            ; EEPROM.  16 bits.
  2650.     call    shift_bits_out
  2651.  
  2652.     call    wait_eeprom_cmd_done    ;Await end-of-command
  2653.     jc    write_fault        ;go if error
  2654.  
  2655.     call    stand_by
  2656.  
  2657. ; Send the erase write disable command to the EEPROM.
  2658.     mov    ax, EEPROM_EWDS_opcode        ;Disable the Erase/write
  2659.     mov    cx, 5                ; command previously sent to
  2660.     call    shift_bits_out            ; EEPROM.
  2661.  
  2662.     mov    cx, 4                      ;Send 4 don't cares as
  2663.     call    shift_bits_out            ; required by the eeprom
  2664.  
  2665.     call    eeprom_clean_up
  2666.  
  2667.     clc
  2668.     ret
  2669.  
  2670. write_fault_pop:
  2671.     add    sp, 2                ;Get rid of data on stack
  2672. write_fault:
  2673. ;;;    lea    ax, eeprom_write_error
  2674.     stc
  2675.     ret
  2676.  
  2677.  
  2678. shift_bits_out:
  2679. ;enter with ax=data to be shifted, cx=# of bits to be shifted.
  2680.  
  2681.     push    bx
  2682.  
  2683. ; Data bits are right justified in the AX register.  Move the data
  2684. ; into BX and left justify it.  This will cause addresses to to
  2685. ; be sent to the EEPROM high order bit first.
  2686.  
  2687.     mov    bx, ax
  2688.     mov    ch, 16
  2689.     sub    ch, cl
  2690.     xchg    cl, ch
  2691.     shl    bx, cl
  2692.     xchg    cl, ch
  2693.     xor    ch, ch
  2694.  
  2695. ; Get the EEPROM control register into AL.  Mask of the ASIC asn 586
  2696. ; reset bits.
  2697.  
  2698.     in    al, dx
  2699.     and    al, 10111111b
  2700.  
  2701. ; Set or clear DI bit in EEPROM control register based on value of
  2702. ; data in BX.
  2703.  
  2704. out_shift_loop:
  2705.     and    al, not ee_di            ;Assume data bit will be zero
  2706.  
  2707.     rcl    bx, 1                ;Is the data bit a one?
  2708.     jnc    out_with_it            ;No
  2709.     or    al, ee_di            ;Yes
  2710. out_with_it:
  2711.     out    dx, al                ;Output a 0 or 1 on data pin
  2712.  
  2713. ; Set up time for data is .4 Microseconds.  So to be safe (incase of
  2714. ; this software is run on a cray), call delay.
  2715.     mov    di, 1
  2716.     call    eeprom_delay
  2717.  
  2718.     call    raise_eeprom_clock    ; Clock the data into the EEPROM.
  2719.     call    lower_eeprom_clock
  2720.     loop    out_shift_loop        ;Send next bit
  2721.  
  2722.     and    al, not ee_di        ;Force data bit to zero
  2723.     out    dx, al            ;Output a 0 on data pin
  2724.  
  2725.     pop    bx
  2726.  
  2727.     ret
  2728.  
  2729. shift_bits_in:
  2730. ;exit with ax = register contents.
  2731.     push    bx
  2732.     push    cx
  2733.  
  2734. ; BX will receive the 16 bits read from the EEPROM.  Data is valid in
  2735. ; data out bit (DO) when clock is high.  There for, this procedure
  2736. ; raises clock and waits a minimum amount of time.  DO is read, and
  2737. ; clock is lowered.
  2738.  
  2739.     in    al, dx                ;Init AL to eeprom control
  2740.     and    al, 10111111b            ; register.
  2741.  
  2742.     xor    bx, bx                ;Init holding register
  2743.     mov    cx, 16                ;We'll shift in 16 bits
  2744.  
  2745. in_shift_loop:
  2746.     shl    bx, 1            ;Adjust holding register for
  2747.                     ; next bit
  2748.     call    raise_eeprom_clock
  2749.  
  2750.     in    al, dx
  2751.     and    al, 10111111b
  2752.  
  2753.     test    al, ee_do        ;Was the data bit a one?
  2754.     jz    in_eeprom_delay        ;No
  2755.  
  2756.     or    bx, 1            ;Yes, reflect data bit state
  2757.                     ; in holding register.
  2758.  
  2759. in_eeprom_delay:
  2760.     call    lower_eeprom_clock
  2761.     loop    in_shift_loop        ;CONTINUE
  2762.  
  2763.     mov    ax, bx            ;AX = data
  2764.  
  2765.     pop    cx
  2766.     pop    bx
  2767.     ret
  2768.  
  2769. raise_eeprom_clock:
  2770.     or    al, ee_sk        ;Clock the bit out by raising
  2771.     jmp    short eeprom_clock_common
  2772. lower_eeprom_clock:
  2773.     and    al, not ee_sk            ;Lower ee_sk
  2774. eeprom_clock_common:
  2775.     out    dx, al
  2776.     mov    di, ee_tick
  2777.     call    eeprom_delay            ;Waste time
  2778.     ret
  2779.  
  2780.  
  2781. wait_eeprom_cmd_done:
  2782. ;Wait for ee_do to go high, indicating end-of-write or end-of-erase
  2783. ;operation.  Wait at most 20 ms (EEPROM needs at most 10).
  2784. ;exit with nc if no error.
  2785.  
  2786.     push    bx
  2787.     push    cx
  2788.  
  2789.     call    stand_by
  2790.  
  2791.     call    readtickcounter
  2792.     mov    di, ax
  2793.  
  2794. ee_do_wait_loop:
  2795.  
  2796.     call    readtickcounter
  2797.     neg    ax
  2798.     add    ax, di
  2799.  
  2800.     cmp    ax, 28640        ;12 Millisecond wait
  2801.     jb    ee_do_wait_loop
  2802.  
  2803.     in    al, dx            ;Get EEPROM control register
  2804.  
  2805.     test    al, EE_DO        ;ee_do high?
  2806.     jnz    ee_do_found
  2807.  
  2808.     stc
  2809.     jmp    short wait_eeprom_cmd_done_exit
  2810.  
  2811. ee_do_found:
  2812.  
  2813.     clc                ;"clean" status (no timeout)
  2814.  
  2815. wait_eeprom_cmd_done_exit:
  2816.  
  2817.     pop    cx
  2818.     pop    bx
  2819.     ret
  2820.  
  2821.  
  2822. stand_by:
  2823. ; lower chip select for 1 microsecond.
  2824.     in    al, dx                  ;de-select EEPROM
  2825.     and    al, (10111110b) and (not ee_cs)
  2826.     out    dx, al
  2827.  
  2828.     mov    di, 2
  2829.     call    eeprom_delay
  2830.  
  2831.     or    al, ee_cs
  2832.     out    dx, al
  2833.  
  2834.     ret
  2835.  
  2836. ; Lower EEPROM chip select and DI.
  2837. ; Clock EEPROM twice and leave clock low.
  2838.  
  2839. eeprom_clean_up:
  2840.  
  2841.     push    ax
  2842.  
  2843.     in    al, dx
  2844.     and    al, 10111111b
  2845.     and    al, not (ee_cs or ee_di)
  2846.     out    dx, al
  2847.  
  2848.     call    raise_eeprom_clock
  2849.     call    lower_eeprom_clock
  2850.  
  2851.     pop    ax
  2852.     ret
  2853.  
  2854. ; DI has number of 838 Nanoseconds clock counts
  2855. eeprom_delay:
  2856.  
  2857.     push    ax
  2858.     push    bx
  2859.     push    dx
  2860.  
  2861.     call    readtickcounter
  2862.     mov    bx, ax
  2863.  
  2864. eeprom_delay_loop:
  2865.  
  2866.     call    readtickcounter
  2867.     neg    ax
  2868.     add    ax, bx
  2869.     cmp    ax, di
  2870.     jb    eeprom_delay_loop
  2871.  
  2872.     pop    dx
  2873.     pop    bx
  2874.     pop    ax
  2875.     ret
  2876.  
  2877. iochrdy_test:
  2878. ; First test to see if the driver is supposed to run this test.
  2879.     MOV    AX, lock_bit_address
  2880.     CALL    read_eeprom
  2881.  
  2882.     TEST    AX, lock_bit_mask
  2883.     JNZ    iochrdy_test_exit
  2884. ; Get the configuration register.
  2885.  
  2886.     LEA    DX, [BP].@config
  2887.     IN    AL, DX
  2888.  
  2889. ; Set the iochrdy test bit with and set iochrdy to late.
  2890.     OR    AL, iochrdy_test_mask+iochrdy_late
  2891.     CLI
  2892.     OUT    DX, AL
  2893.  
  2894. ; Test IOCHRDY with IO.
  2895.     LEA    DX, [BP].@mem_loc_0
  2896.     IN    AX, DX
  2897.  
  2898. ; Read in the results of the test.  Save results in BL.
  2899.     LEA    DX, [BP].@config
  2900.     IN    AL, DX
  2901.     MOV    BL, AL
  2902.  
  2903. ; Turn iochrdy test off.
  2904.     AND    AL, NOT iochrdy_test_mask
  2905.     OUT    DX, AL
  2906.     STI
  2907.  
  2908. ; Test results.  Exit if IOCHRDY_LATE bit is set correctly.
  2909.     TEST    BL, iochrdy_test_result
  2910.     JZ    iochrdy_test_exit
  2911.  
  2912. ; Here if test failed.  Clear the 16 bit override bit (force 8 bit
  2913. ; transfers) and print a warning message.
  2914.     AND    AL, NOT _16_bit_override_bit
  2915.     OUT    DX, AL
  2916.  
  2917.     mov    dx, offset iochrdy_problem
  2918.     mov    ah,9
  2919.     int    21h
  2920.  
  2921.  
  2922. iochrdy_test_exit:
  2923.  
  2924.     RET
  2925.  
  2926.  
  2927.  
  2928. iochrdy_problem    db    "IOCHRDY Problem.  EtherExpress forced into 8 Bit Mode.",CR,LF,'$'
  2929. buffer_memory_error    db    "Memory error on the EtherExpress board",CR,LF,'$'
  2930.  
  2931. reset_error    db    "ASIC reset failure on EtherExpress board",CR,LF,'$'
  2932.  
  2933. _586_diagnostic_failure    db    "82586 diagnostic failure on the "
  2934.     db    "EtherExpress board",CR,LF,'$'
  2935.  
  2936. _586_not_responding_msg    db    "82586 did not respond to command "
  2937.     db    "on the EtherExpress board",CR,LF,'$'
  2938.  
  2939. command_unit_not_idle    db    "82586 command unit is not "
  2940.     db    "responding on the EtherExpress board",CR,LF,'$'
  2941.  
  2942. invalid_int_number    db    "EtherExpress board IRQ/Interrupt number "
  2943.     db    "not specified correctly",CR,LF,'$'
  2944.  
  2945. eeprom_checksum_error    db    "EEPROM failed checksum",CR,LF,'$'
  2946.  
  2947. Board_Not_Installed    db    "EtherExpress Board not found",CR,LF,'$'
  2948.  
  2949. irq_config_error    db    "IRQ selection is for 16 bit slot only.",CR,LF,'$'
  2950.  
  2951. bad_config_msg    db    "Could not configure the 82586",CR,LF,'$'
  2952.  
  2953. bad_init_msg    db    "Could not initialize the 82586",CR,LF,'$'
  2954.  
  2955. code    ends
  2956.  
  2957.     end
  2958.