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

  1. version        equ    5
  2. DEBUG        equ    0
  3. ;History:31,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    26
  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.     stc
  776. issue_command_error_exit:
  777.     ret
  778.  
  779. acknowledge_command_complete:
  780. ;
  781. ; Tell the 586 that we know its done by copying the status back to
  782. ; the command register's acknowledge fields.  BX has status.
  783. ;
  784.     lea    dx, [bp].@SCB_CMD
  785.     out    dx, ax
  786.     issue_ca
  787. ;
  788. ; Signal no error.
  789. ;
  790.     xor    ax, ax
  791.     ret
  792.  
  793.  
  794.     public    set_multicast_list
  795. set_multicast_list:
  796. ;enter with ds:si ->list of multicast addresses, ax = number of addresses,
  797. ;  cx = number of bytes.
  798. ;return nc if we set all of them, or cy,dh=error hf we didn't.
  799.     mov    dh,NO_MULTICAST
  800.     stc
  801.     ret
  802.  
  803.  
  804.     public    terminate
  805. terminate:
  806.     push    bp
  807.     mov    bp,io_addr
  808.  
  809.     cmd_clear    ; wait until last command is done processing
  810.  
  811.     disable_board_ints    ; shut off board ints
  812.  
  813.     lea    dx,[bp].@SCB_CMD
  814.     mov    ax, RUC_SUSPEND        ; suspend recieve unit
  815.     out    dx, ax
  816.     issue_ca
  817.  
  818.     pop    bp            ; now ok to un-hook interrupts and release
  819.     ret    ; driver
  820.  
  821.     public    reset_interface
  822. reset_interface:
  823. ;reset the interface.
  824.     assume    ds:code
  825.     ret
  826.  
  827.  
  828. ;called when we want to determine what to do with a received packet.
  829. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  830.     extrn    recv_find: near
  831.  
  832. ;called after we have copied the packet into the buffer.
  833. ;enter with ds:si ->the packet, cx = length of the packet.
  834.     extrn    recv_copy: near
  835.  
  836. ;call this routine to schedule a subroutine that gets run after the
  837. ;recv_isr.  This is done by stuffing routine's address in place
  838. ;of the recv_isr iret's address.  This routine should push the flags when it
  839. ;is entered, and should jump to recv_exiting_exit to leave.
  840. ;enter with ax = address of routine to run.
  841.     extrn    schedule_exiting: near
  842.  
  843. ;recv_exiting jumps here to exit, after pushing the flags.
  844.     extrn    recv_exiting_exit: near
  845.  
  846.     extrn    count_in_err: near
  847.     extrn    count_out_err: near
  848. ;    extrn    resource_err_in:word
  849.  
  850.     public    recv
  851. recv:
  852. ;called from the recv isr.  All registers have been saved, and ds=cs.
  853. ;Upon exit, the interrupt will be acknowledged.
  854.     assume    ds:code
  855. ;
  856. ; Set BP to the base IO address of exp16.  Also disable exp16s ability
  857. ; to generate interrupts.
  858. ;
  859.     mov    bp,io_addr
  860.     disable_board_ints
  861. ;
  862. ; Make sure that command unit is clear before reading the status.
  863. ;
  864.     cmd_clear
  865. ;
  866. ; Get the SCB status to see why exp16 interrupted us.  Also need to
  867. ; copy the status back to the command word to acknowledge the 586
  868. ; interrupt.  Issue channel attention to get the 586 to realize the
  869. ; interrupt aknowledge.
  870. ;
  871. ;    lea    dx, [bp].@SCB_RSCERRS
  872. ;    in    ax,dx
  873. ;    mov    word ptr resource_err_in,ax
  874. ;    lea    dx, [bp].@SCB_OVRNERRS
  875. ;    in    ax,dx
  876. ;    add    word ptr resource_err_in,ax
  877.  
  878.     lea    dx, [bp].@SCB_STAT
  879.     in    ax, dx
  880.     and    ax, ACK_INT_MASK
  881.  
  882.     lea    dx, [bp].@SCB_CMD
  883.     out    dx, ax
  884.     issue_ca    ; AX is not changed.
  885. ;
  886. ; Check for frame receive status.  Jump if no frames received,
  887. ; otherwise processes the receive.
  888. ;
  889.     test    AX, BIT_FR OR BIT_RNR
  890.     jz    ExitDriverISR
  891.     call    ProcessRx
  892. ExitDriverISR:
  893. ;
  894. ; Here if there was a bad receive status.  Make sure the receive unit
  895. ; of the 586 is running.  Read in the SCB status and jump if we need
  896. ; to restart the receive unit.  We choose to have the jump to restart
  897. ; the RU since most of the time we will not need to do this.  This
  898. ; saves cycle times when exiting without a restart.
  899. ;
  900.     lea    dx, [bp].@SCB_STAT
  901.     in    ax, dx
  902.     test    ax, READY
  903.     jz    restart_RU
  904.  
  905. drvisr_continue:
  906.     enable_board_ints
  907.     ret
  908.  
  909.  
  910. restart_RU:
  911. ;
  912. ; Need to restart the receive unit of the 586.  Set the SCB pointer to
  913. ; the receive frame area.
  914. ;
  915.     lea    dx, [bp].@SCB_RFA
  916.     mov    ax, Receive_Head
  917.     out    dx, ax
  918. ;
  919. ; Make sure 586 is in a state to accept a command.
  920. ;
  921.     cmd_clear
  922. ;
  923. ; Put the receive unit start command into the SCB command word and
  924. ; issue the channel attention.
  925. ;
  926. ; NOTE: cmd_clear macro leaves DX pointing to the SCB command word.
  927. ;
  928. ;    lea    dx, [bp].@SCB_CMD
  929.     mov    ax, RUC_START
  930.     out    dx, ax
  931.     issue_ca
  932.     jmp    drvisr_continue
  933.  
  934.  
  935. ProcessRx:
  936.  
  937. ;
  938. ; Prime the pump that services receives by setting AX to the receive
  939. ; head.  There could be over 30 packets received.
  940. ;
  941.     mov    ax,Receive_Head
  942.  
  943. CheckNextReceiveStatus:
  944.  
  945. ;
  946. ; Save receive head pointer in BX.  BX should not be altered during
  947. ; this loop.
  948. ;
  949.     mov    bx, ax
  950. ;
  951. ; Set SMB pointer to the top of the receive frame.
  952. ;
  953.     lea    dx, [bp].@SMB_Ptr
  954.     out    dx, ax
  955. ;
  956. ; Get the status for this receive frame.  Check to make sure that
  957. ; it completed with no errors.  If not, then jump to check the
  958. ; 586 receive unit.
  959. ;
  960.     lea    dx, [bp].@FD_Status
  961.     in    ax, dx
  962.  
  963.     mov    save_err,1        ; be sure we done accdently report an error
  964.  
  965.     test    ax, BIT_C        ; command compleat
  966.     jz    PRx_no
  967.     test    ax,BIT_OK        ; good frame
  968.     jnz    ProcessRx_1
  969.  
  970.     call    count_in_err
  971.     mov    save_err,0
  972.     cmp    pro0,1
  973.     je    PRx_bad            ; if not in pro-mode lose bad frames and inc error
  974. ;    call    count_in_err
  975.     jmp    recv_isr_9
  976. PRx_no:
  977.     ret
  978.  
  979. PRx_bad:
  980.     mov    dh,0            ;build save_err.
  981.     test    ax,BIT_S7
  982.     jz    PR_no_frag
  983.     or    dh,2
  984. PR_no_frag:
  985.     test    ax,BIT_S11
  986.     jz    PR_no_crc
  987.     or    dh,4
  988. PR_no_crc:
  989.     test    ax,BIT_S10
  990.     jz    PR_no_align
  991.     or    dh,8
  992. PR_no_align:
  993.     test    ax,BIT_S8
  994.     jz    PR_no_dma
  995.     or    dh,16
  996. PR_no_dma:
  997.     test    ax,BIT_S9
  998.     jz    PR_no_ru
  999.     or    dh,32
  1000. PR_no_ru:
  1001.     mov    save_err,dh
  1002.  
  1003. ProcessRx_1:
  1004. ;
  1005. ; Set the read pointer to access the LengthTypeField.
  1006. ;
  1007. ; NOTE: BX was set to receive head at the beginning of this
  1008. ;       procedure.
  1009. ;
  1010.     lea    dx, [bp].@Read_Ptr
  1011.     lea    ax, [BX].IPX_DestAddr_HIGH
  1012.     out    dx, ax
  1013.     mov    dx, bp            ;@Data_Reg
  1014.  
  1015.     mov    ax,cs
  1016.     mov    es,ax
  1017.     mov    di,offset our_type
  1018.     mov    cx,HEADER_LEN
  1019.     call    repinsw
  1020.  
  1021. ;
  1022. ; Get the packet size from the 586 data structure.
  1023. ;
  1024.     lea    dx, [bp].@RBD_ByteCount
  1025.     in    ax, dx
  1026.     and    ah, 3fh
  1027.     mov    cx, ax
  1028.  
  1029.     mov    di,offset our_type+EADDR_LEN+EADDR_LEN
  1030.  
  1031.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  1032.     mov    ax, es:[di]
  1033.     xchg    ah, al
  1034.     cmp    ax, 1518
  1035.     ja    BlueBookPacket
  1036.     inc    di            ;set di to 802.2 header
  1037.     inc    di
  1038.     mov    dl, IEEE8023
  1039. BlueBookPacket:
  1040.     push    bx
  1041.     push    cx            ; for some reison recv_find trashes cx
  1042.     mov    dh,save_err
  1043.     call    recv_find
  1044.     mov    bp,cs:io_addr        ; just in case
  1045.     pop    cx
  1046.     pop    bx
  1047.  
  1048.     mov    ax,es            ;is this pointer null?
  1049.     or    ax,di
  1050.     je    recv_isr_9        ;yes - just free the frame.
  1051.     push    es            ;remember where the buffer pointer is.
  1052.     push    di
  1053.     push    cx
  1054.   if 0
  1055. ;
  1056. ; Copy the packet's header into their buffer.
  1057. ;
  1058.     push    cx
  1059.     mov    si,offset our_type
  1060.     mov    cx,HEADER_LEN/2
  1061.     rep    movsw
  1062.     pop    cx
  1063.     sub    cx,HEADER_LEN
  1064.   endif
  1065. ;
  1066. ; Set the read pointer to access the packet.
  1067. ;
  1068. ; NOTE: BX was set to receive head at the beginning of this
  1069. ;       procedure.
  1070. ;
  1071.     lea    dx, [bp].@Read_Ptr
  1072.   if 0
  1073.     lea    ax, [BX].IPX_DestAddr_HIGH + HEADER_LEN
  1074.   else
  1075.     lea    ax, [BX].IPX_DestAddr_HIGH
  1076.   endif
  1077.     out    dx, ax
  1078.     mov    dx, bp            ;@Data_Reg
  1079. ;
  1080. ; Now read the packet into es:di
  1081. ;
  1082.     call    repinsw
  1083.  
  1084.     pop    cx
  1085.     pop    si
  1086.     pop    ds
  1087.     assume    ds:nothing
  1088.     call    recv_copy        ;tell them that we copied it.
  1089.     mov    ax,cs            ;restore our ds.
  1090.     mov    ds,ax
  1091.     assume    ds:code
  1092.  
  1093. recv_isr_9:
  1094. ;
  1095. ; Restore SMB pointer to the top of the receive frame.
  1096. ;
  1097.     mov    bp,io_addr        ; just in case
  1098.     mov    ax,bx
  1099.     lea    dx, [bp].@SMB_Ptr
  1100.     out    dx, ax
  1101.  
  1102. ;
  1103. ; Clear the current receive frames status.
  1104. ;
  1105.     lea    dx, [bp].@FD_Status
  1106.     xor    ax, ax
  1107.     out    dx, ax
  1108. ;
  1109. ; Set the end of list bit for the current receive frame.
  1110. ;
  1111.     lea    dx, [bp].@FD_command
  1112.     mov    ax, BIT_EL
  1113.     out    dx, ax
  1114. ;
  1115. ; Read in the pointer to the next receive frame.
  1116. ;
  1117.     lea    dx, [bp].@FD_Link
  1118.     in    ax, dx
  1119. ;
  1120. ; Update our local pointer to the receive resources:
  1121. ;
  1122. ; Receive_tail <-- Receive head
  1123. ; Receive_head <-- next receive frame.
  1124. ;
  1125.     mov    BX, Receive_Head
  1126.     mov    Receive_Tail, BX
  1127.     mov    Receive_Head, AX
  1128.     mov    cx, ax
  1129. ;
  1130. ; Clear previous receive frame descriptors end of list bit to free up
  1131. ; a receive resource.  We do this by moving the write pointer to the
  1132. ; the command word in the previous receive frame and then writing a
  1133. ; zero to it.
  1134. ;
  1135.     lea    dx, [bp].@Write_Ptr
  1136.     lea    ax, [bx].FD_command
  1137.     out    dx, ax
  1138.  
  1139.     mov    dx, bp            ;@Data_Reg
  1140.     xor    ax, ax
  1141.     out    dx, ax
  1142. ;
  1143. ; Check for another receive frame.
  1144. ;
  1145.     mov    ax, cx
  1146.     jmp    CheckNextReceiveStatus
  1147.  
  1148.  
  1149.  
  1150. ; This procedure is called from the cmd_clear macro after the macro determines
  1151. ; that we must wait for a command to clear.
  1152. ;
  1153. ;     MUST NOT TRASH CX OR THE ISSUE_COMMAND PROCEDURE WILL FAIL.
  1154. ;
  1155. cmd_wait:
  1156. ;enter with dx -> SCB_CMD
  1157. ;exit with nc if it cleared in one millisecond, cy if not.
  1158.  
  1159.     call    readtickcounter            ;Reference clock.  die after
  1160.     mov    bx, ax                ; 1 ms.
  1161.  
  1162. wait_cmd_clear:
  1163.  
  1164.     in    ax, dx                ;Read SCB command
  1165.     or    ax, ax                ;Wait for command accepted
  1166.     jz    exit
  1167.  
  1168.     call    readtickcounter
  1169.     neg    ax
  1170.     add    ax, bx
  1171.  
  1172.     cmp    ax, one_mil
  1173.     jb    wait_cmd_clear
  1174.  
  1175.     stc
  1176. exit:
  1177.     ret
  1178.  
  1179.  
  1180.     public    timer_isr
  1181. timer_isr:
  1182. ;if the first instruction is an iret, then the timer is not hooked
  1183.     iret
  1184.  
  1185. ;any code after this will not be kept after initialization. Buffers
  1186. ;used by the program, if any, are allocated from the memory between
  1187. ;end_resident and end_free_mem.
  1188.     public    end_resident,end_free_mem
  1189. end_resident    label    byte
  1190. end_free_mem    label    byte
  1191.  
  1192.  
  1193.     public    usage_msg
  1194. usage_msg    db    "usage: exp16 [options] <packet_int_no> <io_addr>",CR,LF,'$'
  1195.  
  1196.     public    copyright_msg
  1197. copyright_msg    db    "Packet driver for the Intel EtherExpress 16, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
  1198.     db    "Copyright 1991 Intel Corp",CR,LF
  1199.     db    "Portions Copyright 1993 Crynwr Software",CR,LF,'$'
  1200.  
  1201. int_no_name    db    "Interrupt number ",'$'
  1202. io_addr_name    db    "I/O port ",'$'
  1203.  
  1204.     extrn    set_recv_isr: near
  1205.  
  1206. ;enter with si -> argument string, di -> dword to store.
  1207. ;if there is no number, don't change the number.
  1208.     extrn    get_number: near
  1209.  
  1210. ;enter with dx -> argument string, di -> dword to print.
  1211.     extrn    print_number: near
  1212.  
  1213.  
  1214. ;-> the assigned Ethernet address of the card.
  1215.     extrn    rom_address: byte
  1216.  
  1217. chan_sel    db    0    ;Channel select for SYS_MCA machines
  1218.  
  1219.     public    etopen
  1220. etopen:
  1221. ;initialize the driver.
  1222.     assume    ds:code
  1223. ;
  1224. ; Get board information (Node address, etc.).  Returns with BP
  1225. ; set to the board IO base address (if not errors).
  1226. ;
  1227.     call    get_system_info
  1228.     jc    driver_init_error_exit
  1229.  
  1230.     disable_board_ints
  1231. ;
  1232. ; If they're in an 8-bit slot, make sure that they aren't using the slave PIC.
  1233. ;
  1234.     cmp    _16_not_8_bit_slot,0    ;are they using a 16-bit slot?
  1235.     jne    check_config_exit    ;yes -- cool.
  1236.  
  1237.     mov    dx,offset irq_config_error
  1238.     cmp    int_no, 9        ;no - don't let them use the upper IRQs.
  1239.     jb    check_config_exit
  1240. driver_init_error_exit:
  1241.     stc
  1242.     ret
  1243. check_config_exit:
  1244.  
  1245. ;
  1246. ; Initialize the 586 and the 586 data structures.
  1247. ;
  1248.     call    init_586
  1249.     jc    driver_init_error_exit
  1250.  
  1251. ; test iochrdy
  1252.     test    sys_features,SYS_MCA
  1253.     jnz    skip_iochrdy_test
  1254.     call    iochrdy_test
  1255. skip_iochrdy_test:
  1256.  
  1257.     cmp    connection_type,CONN_AUTO
  1258.     jne    no_auto_con
  1259.     call    auto_connector
  1260.     jnc    did_auto_con
  1261.     mov    dx,offset no_wire_msg
  1262.     mov    ah,9
  1263.     int    21h
  1264.     jmp    short    did_auto_con
  1265. no_auto_con:
  1266.     call    write_connector_setting_to_hardware
  1267. did_auto_con:
  1268.  
  1269. ;
  1270. ; Set up Interrupt line, start the receive unit, and Enable exp16s interrupt.
  1271. ;
  1272.     call    set_recv_isr
  1273.     call    ru_start
  1274.     enable_board_ints    ;;; only one left in broken version.
  1275.  
  1276.     mov    al, int_no        ; Get board's interrupt vector
  1277.     add    al, 8
  1278.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  1279.     jb    set_int_num        ; No.
  1280.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  1281. set_int_num:
  1282.     xor    ah, ah            ; Clear high byte
  1283.     mov    int_num, ax        ; Set parameter_list int num.
  1284.  
  1285.     clc
  1286.     ret
  1287.  
  1288. write_connector_setting_to_hardware:
  1289.     assume    ds:code
  1290.     test    sys_features,SYS_MCA
  1291.     je    isa_connector_bart
  1292.  
  1293.     mov    bl,80h
  1294.     cmp    connection_type,CONN_TPE    ;did they ask for TPE?
  1295.     je    mca_tpe_connector
  1296.     mov    bl,0
  1297. mca_tpe_connector:
  1298.  
  1299.     call    enable_slot
  1300.     mov    dx,102h            ;stuff the AUI/Other bit in.
  1301.     in    al,dx
  1302.     and    al,not 04h
  1303.     cmp    connection_type,CONN_AUI
  1304.     je    mca_tpe_connector_1
  1305.     or    al,04h
  1306. mca_tpe_connector_1:
  1307.     out    dx,al
  1308.  
  1309.     mov    dx,103h            ;stuff the BNC/TPE bit in.
  1310.     in    al,dx
  1311.     and    al,not 80h
  1312.     cmp    connection_type,CONN_BNC
  1313.     je    mca_tpe_connector_2
  1314.     or    al,80h            ;<>0 means TPE
  1315. mca_tpe_connector_2:
  1316.     out    dx,al
  1317.     call    disable_slot
  1318.  
  1319.     jmp    no_connector_bart
  1320. isa_connector_bart:
  1321.     cmp    board_id,BART_Board_ID    ;a real BART?
  1322.     je    no_connector_bart    ;yes, it doesn't *have* an ECR1.
  1323.     mov    bp,io_addr
  1324.     lea    dx,ECR1[bp]
  1325.     in    al,dx
  1326.     and    al,not 82h        ;turn off Other/not_AUI (read as
  1327.                     ;   MCA/ISA), and TPE/not_BNC
  1328.     cmp    connection_type,CONN_AUI
  1329.     je    set_connector_bart
  1330.     or    al,80h            ;set Other/not_AUI
  1331.     cmp    connection_type,CONN_BNC
  1332.     je    set_connector_bart
  1333.     or    al,02h            ;set TPE/not_BNC
  1334. set_connector_bart:
  1335.     out    dx,al
  1336. no_connector_bart:
  1337.  
  1338.     mov    cx,10            ;10*10 milliseconds = 100 millis
  1339.     cmp    connection_type,CONN_AUI
  1340.     jne    set_connector_delay
  1341.     mov    cx,50            ;50*10 milliseconds = 500 millis
  1342. set_connector_delay:
  1343. ; Our delay procedure can not accept a value over 27 milliseconds,
  1344. ; so we use a loop to delay the 100 milliseconds.
  1345. set_connector_delay_1:
  1346.     push    cx
  1347.     mov    di, ten_mils
  1348.     call    eeprom_delay
  1349.     pop    cx
  1350.     loop    set_connector_delay_1
  1351.     ret
  1352.  
  1353.  
  1354. ; int number to IRQ translate table.
  1355. IRQ_xlat_table    LABEL    BYTE
  1356.     db     12, 2, 3, 4, 5, 10, 11, 15
  1357.  
  1358. io_addresses    label word
  1359.     dw    300h,310h,320h,330h,340h,350h,360h,370h
  1360.     dw    200h,210h,220h,230h,240h,250h,260h,270h
  1361.     dw    0
  1362.  
  1363. enable_slot:
  1364.     mov    al,chan_sel
  1365.     out    96h, al            ; select channel
  1366.     mov    al, 0ffh
  1367.     out    94h, al            ; protect system board
  1368.     ret
  1369.  
  1370. disable_slot:
  1371.     xor    al,al            ;disable pos
  1372.     out    96h,al
  1373.     ret
  1374.  
  1375.     public    parse_args
  1376. parse_args:
  1377. ;exit with nc if all went well, cy otherwise.
  1378.     test    sys_features,SYS_MCA
  1379.     jne    parse_args_mc
  1380.     jmp    parse_args_1
  1381.  
  1382. parse_args_mc:
  1383. ;The following code to read the POS registers is courtesy of Racal-Interlan.
  1384.  
  1385. ; channel selector resides at io 96h
  1386. ; POS register base is at io 100h
  1387. ; EXP16/MC ID is 0628bh
  1388.  
  1389. ; search thro' the slots for a EXP16/MC card
  1390.     mov    cx, 8            ; for all channels(slots)
  1391.  
  1392. ; channel select value for slots 0,1,2.. is 8,9,A etc
  1393. ; start with slot 0, and then 7,6,5,4,3,2,1
  1394. get_05:
  1395.     mov    ax, cx            ; channel number
  1396.     or    ax, 08h            ; reg. select value
  1397.     mov    chan_sel,al        ; save each one, the LAST will right
  1398.  
  1399. ; read adapter id
  1400.     call    enable_slot
  1401.     mov    dx, 101h
  1402.     in    al, dx            ; adapter id - ms byte
  1403.     mov    ah, al
  1404.     dec    dx
  1405.     in    al, dx            ; adapter id - ls byte
  1406.  
  1407. ; Check if EXP16/MC
  1408.     cmp    ax, 0628bh
  1409.     je    get_10
  1410.     loop    get_05
  1411.  
  1412.     call    disable_slot
  1413.  
  1414.     mov    dx,offset Board_Not_Installed
  1415.     stc
  1416.     ret
  1417.  
  1418. get_10:
  1419. ; found our Adapter
  1420.     call    write_pos_to_eeprom
  1421.  
  1422.     clc
  1423.     ret
  1424.  
  1425. parse_args_1:
  1426.     mov    di,offset io_addr
  1427.     call    get_number
  1428.     clc
  1429.     ret
  1430.  
  1431.     include    exp16mca.asm
  1432.  
  1433. ;-----------------------------------------------------------------------------
  1434. ; It is safe to assume that the command unit is up and running ready
  1435. ; for the first send.  And that there are at least two send buffers 
  1436. ; available.
  1437. ;
  1438. ; This procedure works by sending a 64 byte packet to itself.  We do not turn
  1439. ; on loopback, so we do not expect to see a receive.  Instead, we
  1440. ; expect to see that the send completed OK.  If the send does not complete OK, 
  1441. ; then this routine switches to other connectors and the test is repeated. 
  1442. ;-----------------------------------------------------------------------------
  1443. auto_connector:
  1444.  
  1445. ; Let's start doing the test send with AUI option first.  If we tried BNC
  1446. ; first, and they were using AUI, it would seem like the BNC worked.  So
  1447. ; we switch to AUI, which turns off the BNC power supply.
  1448.     MOV    connection_type, CONN_AUI
  1449.     CALL    write_connector_setting_to_hardware
  1450.  
  1451. ; Test connection to see if it works.  Jump if it does.
  1452.     call    test_send
  1453.     clc
  1454.     je    auto_connector_exit
  1455.  
  1456. ; Toggle AUI/Other setting and try to send a packet.  Jump if send 
  1457. ; works.  Now try sending on BNC.
  1458.     MOV    connection_type, CONN_BNC
  1459.     CALL    write_connector_setting_to_hardware
  1460.     call    test_send
  1461.     clc
  1462.     je    auto_connector_exit
  1463.  
  1464. ; Here if we just tried a send the BNC.  If this is 
  1465. ; a three connector card, then we toggle the BNC/TPE setting.
  1466. ; Jump if connection is found.
  1467.     MOV    connection_type, CONN_TPE
  1468.     CALL    write_connector_setting_to_hardware
  1469.     call    test_send
  1470.     clc
  1471.     je    auto_connector_exit
  1472.     stc
  1473. auto_connector_exit:
  1474.     ret
  1475.  
  1476.  
  1477. test_packet    label    byte
  1478.     db    EADDR_LEN dup(?)
  1479.     db    EADDR_LEN dup(?)
  1480.     db    00h,2eh            ;A 46 in network order
  1481.     db    0,0            ;DSAP=0 & SSAP=0 fields
  1482.     db    0f3h,0            ;Control (Test Req + P bit set)
  1483.  
  1484. ; This procedure sends a packet on the wire and wait for the send to
  1485. ; complete.  It the checks to see if the send completed OK and returns
  1486. ; the results.
  1487. test_send:
  1488.  
  1489.     mov    si,offset rom_address    ;set the destination address.
  1490.     movseg    es,cs
  1491.     mov    di,offset test_packet
  1492.     repmov    EADDR_LEN
  1493.     mov    si,offset rom_address    ;set the source address.
  1494.     repmov    EADDR_LEN
  1495.  
  1496.     mov    cx,60
  1497.     mov    si,offset test_packet
  1498.     call    send_pkt
  1499.  
  1500.     call    ReadTickCounter
  1501.     mov    cx, ax
  1502.  
  1503.     mov    bp,io_addr
  1504.     lea    dx, [bp].@TxCB_Status
  1505. send_test_wait:
  1506.     in    ax,dx
  1507.     test    ax,8000h        ;did it finish?
  1508.     jne    send_test_done
  1509.  
  1510. ; See if we have been here for a millisecond.  Jump if not.
  1511.     call    ReadTickCounter
  1512.     neg    ax
  1513.     add    ax, cx
  1514.     cmp    ax, one_mil
  1515.     jb    send_test_wait
  1516.  
  1517.     in    ax,dx            ;get the transmit status back again.
  1518.  
  1519. send_test_done:
  1520.  
  1521.     mov    cx, ax            ; Save status in CX.
  1522.  
  1523.     xor    ax, ax            ; Clear the transmit command block status.
  1524.     out    dx, ax
  1525.  
  1526. ; Send is complete.  Get the status and compare to OK send and return.
  1527. ; Save flags for return.
  1528.  
  1529.     and    cx, 0f000h
  1530.     cmp    cx, 0a000h
  1531.     ret
  1532.  
  1533. no_wire_msg        db    "***Unable to detect a cable on any connector***",CR,LF,'$'
  1534. bnc_connector_msg    db    "Using the BNC connector",CR,LF,'$'
  1535. aui_connector_msg    db    "Using the AUI connector",CR,LF,'$'
  1536. tpe_connector_msg    db    "Using the twisted-pair connector",CR,LF,'$'
  1537.  
  1538. _8_bit_slot_msg    db    "The board is in an 8-bit slot",CR,LF,'$'
  1539. _16_bit_slot_msg    db    "The board is in a 16-bit slot",CR,LF,'$'
  1540.  
  1541. badset_msg    db    "Set Address Command Failed",CR,LF,'$'
  1542.  
  1543.  
  1544.     public    print_parameters
  1545. print_parameters:
  1546.     mov    di,offset int_no
  1547.     mov    dx,offset int_no_name
  1548.     call    print_number
  1549.     mov    io_addr.segm,0
  1550.     mov    di,offset io_addr
  1551.     mov    dx,offset io_addr_name
  1552.     call    print_number
  1553.  
  1554.     mov    dx,offset bnc_connector_msg    ;print the connection type.
  1555.     cmp    connection_type,CONN_BNC
  1556.     je    print_parameters_1
  1557.     mov    dx,offset aui_connector_msg
  1558.     cmp    connection_type,CONN_AUI
  1559.     je    print_parameters_1
  1560.     mov    dx,offset tpe_connector_msg
  1561. print_parameters_1:
  1562.     mov    ah,9
  1563.     int    21h
  1564.  
  1565.     mov    dx,offset _16_bit_slot_msg    ;print the slot size.
  1566.     cmp    _16_not_8_bit_slot,0
  1567.     jne    print_parameters_2
  1568.     mov    dx,offset _8_bit_slot_msg
  1569. print_parameters_2:
  1570.     mov    ah,9
  1571.     int    21h
  1572.  
  1573.     ret
  1574.  
  1575.  
  1576. init_586:
  1577. ;enter with bp=io_addr, 586 reset.
  1578.  
  1579. ;
  1580. ; Set the number of transmit and receive buffers according to the
  1581. ; amount of RAM on the adapter.
  1582. ;
  1583.     MOV    AX, Number_of_Tx_Buffers
  1584.     MOV    BX, num_rx_buf_32k
  1585.  
  1586.     cmp    _64K_not_32K,0
  1587.     je    save_number_of_buffers
  1588.  
  1589.     MOV    BX, num_rx_buf_64k
  1590.  
  1591. save_number_of_buffers:
  1592.  
  1593.     MOV    TxBufferCount, AX
  1594.     MOV    RxBufferCount, BX
  1595. ;
  1596. ; initialize SCP.  Move IO frame to top of SCP.
  1597. ;
  1598.     LEA    DX, [bp].@SMB_Ptr
  1599.     MOV    AX, OFFSET scp
  1600.     OUT    DX, AX
  1601. ;
  1602. ; Write initial SCP values:
  1603. ;    bus width    0 = 16 bit   1 = 8 bit.
  1604. ;    ISCP address    always found at address 000000.
  1605. ;
  1606.     LEA    DX, [BP].@SCP_SystemBus
  1607.     MOV    AL, bus_width
  1608.     OUT    DX, AX
  1609.  
  1610.     LEA    DX, [BP].@SCP_ISCP_Ptr_low
  1611.     XOR    AX, AX
  1612.     OUT    DX, AX
  1613.     LEA    DX, [BP].@SCP_ISCP_Ptr_high
  1614.     OUT    DX, AX
  1615.  
  1616. ;
  1617. ; Initialize ISCP.  Move IO frame to top of ISCP.  NOTE: AX falls
  1618. ; through as zero.
  1619. ;
  1620.     LEA    DX, [bp].@SMB_Ptr
  1621.     OUT    DX, AX
  1622. ;
  1623. ; Write initial ISCP values:
  1624. ;    ISCP BUSY    1 = Indicates 586 is in initialization
  1625. ;            process.  586 sets this byte to 0 when
  1626. ;            initialization is complete.
  1627. ;
  1628. ;    SCB address     Always 000008
  1629. ;
  1630.     LEA    DX, [BP].@iscp_busy
  1631.     MOV    AX, initialize_586
  1632.     OUT    DX, AX
  1633.  
  1634.     LEA    DX, [BP].@ISCP_SCB_Ptr_low
  1635.     XOR    AX, AX
  1636.     OUT    DX, AX
  1637.     LEA    DX, [BP].@ISCP_SCB_Ptr_high
  1638.     OUT    DX, AX
  1639.     LEA    DX, [BP].@iscp_scb_offset
  1640.     MOV    AX, OFFSET scb
  1641.     OUT    DX, AX
  1642.  
  1643. ;
  1644. ; Initialize SCB.  Move Write Ptr to top of SCB.  NOTE: AX falls
  1645. ; through as offset to SCB.
  1646. ;
  1647.     XOR    AX, AX
  1648.     LEA    DX, [BP].@SCB_Status
  1649.     OUT    DX, AX
  1650.     LEA    DX, [BP].@SCB_Command
  1651.     OUT    DX, AX
  1652.     LEA    DX, [BP].@SCB_CommandList
  1653.     OUT    DX, AX
  1654.     LEA    DX, [BP].@SCB_RecBlockList
  1655.     OUT    DX, AX
  1656.     LEA    DX, [BP].@SCB_CRC_Errors
  1657.     OUT    DX, AX
  1658.     LEA    DX, [BP].@SCB_ALN_Errors
  1659.     OUT    DX, AX
  1660.     LEA    DX, [BP].@SCB_RSC_Errors
  1661.     OUT    DX, AX
  1662.     LEA    DX, [BP].@SCB_OVR_Errors
  1663.     OUT    DX, AX
  1664.  
  1665. ;
  1666. ; Initialize Receive Block(s).  First set head pointer and link from
  1667. ; SCB to first frame descriptor.  NOTE: IO frame points to ISCB.
  1668. ; The SCB link field can be addresses becasue the SCB is physically
  1669. ; contiguous to the ISCB.
  1670. ;
  1671.     mov    ax,offset Receive_Blocks
  1672.     lea    dx, [bp].@SCB_RecBlockList    ;IO address of SCB RF link
  1673.     out    dx, ax
  1674.  
  1675. ;
  1676. ; Initialize the frame descriptor structures.  Move the Write ptr
  1677. ; the top of the current frame descriptor.  AX falls through with the
  1678. ; offset to the first frame descriptor.  DI is used to keep track of
  1679. ; the address of the current frame descriptor.  The frame descriptor,
  1680. ; receive buffer descriptor, and receive buffer are all contiguous in
  1681. ; memory, and make up the frame descriptor structure.
  1682. ;
  1683.     MOV    DI, AX                ;DI is current frame descriptor
  1684.     MOV    RECEIVE_HEAD, DI
  1685.     MOV    CX, RxBufferCount        ;CX is number of frame
  1686.                         ; descriptors to initialize.
  1687. init_receive_frames:
  1688.  
  1689.     LEA    DX, [bp].@SMB_Ptr
  1690.     MOV    AX, DI                ; descriptor.
  1691.     OUT    DX, AX
  1692.  
  1693. ;
  1694. ; Init Frame Descriptor (FD).
  1695. ;
  1696.     XOR    AX, AX                ;Init frame descriptor status
  1697.     LEA    DX, [BP+4000H]
  1698.     OUT    DX, AX                ; and command to zero.
  1699.     LEA    DX, [BP+4002H]
  1700.     OUT    DX, AX
  1701.  
  1702.     MOV    AX, RECEIVE_HEAD        ;Init frame descriptors link
  1703.     CMP    CX, 1                ; to next frame descriptor.
  1704.     JE    next_receive_link        ; If this is the last receive
  1705.                         ; block, then set its link to
  1706.     LEA    AX, [DI+SIZE ReceiveBlock]    ; the first receive block.
  1707.  
  1708. next_receive_link:
  1709.  
  1710.     LEA    DX, [BP+4004H]
  1711.     OUT    DX, AX
  1712.  
  1713.     LEA    AX, [DI+OFFSET RBD_ByteCount] ;Init frame descriptors
  1714.     LEA    DX, [BP+4006H]
  1715.     OUT    DX, AX            ; link to its receive buffer descriptor.
  1716. ;
  1717. ; Init Receive Buffer Descriptor (RBD).
  1718. ;
  1719.     LEA    DX, [BP+4008H]
  1720.     OUT    DX, AX            ;Init the RBD Actual count to zero.
  1721.  
  1722.     MOV    AX, -1            ;Init the RBD link to next RBD
  1723.     LEA    DX, [BP+400AH]
  1724.     OUT    DX, AX            ; to minus 1 (unused link).
  1725.  
  1726.     LEA    AX, [DI+RB_Data]    ;Init the RDB link to the data
  1727.     LEA    DX, [BP+400CH]
  1728.     OUT    DX, AX            ; buffer.
  1729.     XOR    AX, AX
  1730.     LEA    DX, [BP+400EH]
  1731.     OUT    DX, AX
  1732.  
  1733.     MOV    AX, RxBufferSize OR BIT_EL    ;Init the RBD count and status
  1734.     LEA    DX, [BP+8000H]
  1735.     OUT    DX, AX
  1736.  
  1737.     MOV    RECEIVE_TAIL, DI    ;Set receive tail pointer.
  1738.     ADD    DI, SIZE ReceiveBlock    ;Point DI to next frame
  1739.     LOOP    init_receive_frames    ; descriptor.
  1740. ;
  1741. ; Initialize the send block structures.  Move the Write pointer the
  1742. ; top of the current send block.  AX falls through with address of
  1743. ; first send block.  DI is used to keep track of the address of the
  1744. ; current send block.  The Transmit command block, transmit buffer
  1745. ; descriptor, and transmit buffer are all contiguous in memory, and
  1746. ; make up the send block structure.
  1747. ;
  1748.     MOV    DI, OFFSET send_blocks
  1749.     MOV    CX, TxBufferCount
  1750.  
  1751.     LEA    DX, [BP].@SMB_Ptr
  1752.     XOR    AX, AX
  1753.     OUT    DX, AX
  1754.  
  1755.     MOV    AX, DI
  1756.     LEA    DX, [BP].@SCB_CommandList
  1757.     OUT    DX, AX
  1758.  
  1759. init_send_blocks:
  1760.  
  1761.     LEA    DX, [BP].@SMB_Ptr        ;Set write pointer to send
  1762.     MOV    AX, DI                ; block.
  1763.     OUT    DX, AX
  1764. ;
  1765. ; Init Transmit Control Block (TCB).
  1766. ;
  1767.     XOR    AX, AX            ;Init transmit control block
  1768.     LEA    DX, [BP+4000H]
  1769.     OUT    DX, AX            ; status to zero.
  1770.  
  1771.     LEA    DX, [BP+4002H]
  1772.     OUT    DX, AX            ;Init transmit control block
  1773.                     ; command to anything.  The
  1774.     MOV    AX, offset send_blocks    ; Init transmit control block
  1775.     CMP    CX, 1            ; link to next send block.
  1776.     JE    next_send_link        ; If this is the last send
  1777.                     ; block, then point it to
  1778.     LEA    AX, [DI+SIZE SendBlock]    ; the first block.
  1779.  
  1780. next_send_link:
  1781.  
  1782.     LEA    DX, [BP+4004H]
  1783.     OUT    DX, AX
  1784.  
  1785.     LEA    AX, [DI+OFFSET TBD_ByteCount]    ;Init transmit control block
  1786.     LEA    DX, [BP+4006H]
  1787.     OUT    DX, AX                ; link to Transmit Buffer
  1788.                         ; descriptor.
  1789. ;
  1790. ; Init Transmit Buffer Descriptor (TBD).
  1791. ;
  1792.     LEA    DX, [BP+4008H]
  1793.     OUT    DX, AX            ;Init Transmit Buffer Descriptor
  1794.                     ;  byte count to anything
  1795.     MOV    AX, -1            ;Init Transmit Buffer Descriptor
  1796.     LEA    DX, [BP+400AH]
  1797.     OUT    DX, AX            ;  link to next TBD.
  1798.  
  1799.     LEA    AX, [DI+OFFSET TB_Data]    ;Init Transmit Buffer Descriptor
  1800.     LEA    DX, [BP+400CH]
  1801.     OUT    DX, AX            ; link to transmit
  1802.     XOR    AX, AX            ; buffer.  Low part of pointer
  1803.     LEA    DX, [BP+400EH]
  1804.     OUT    DX, AX            ; is done first.
  1805.  
  1806.     ADD    DI, SIZE SendBlock        ;Point DI to next send block
  1807.     LOOP    init_send_blocks        ; and loop to initialize it.
  1808.  
  1809. ;
  1810. ; Enable loopback to insure nothing acidently hits the cable while
  1811. ; the 586 gets initialized.
  1812. ;
  1813.     LEA    DX, [BP].@Config
  1814.     IN    AX, DX
  1815.     OR    AL, loopback_enable
  1816.     OUT    DX, AL
  1817. ;
  1818. ; Free the 586 from reset.
  1819. ;
  1820.     CALL    free_586_reset
  1821. ;
  1822. ; Initialize and configure the 586.  Carry flag set means error and
  1823. ; dx will point to error message.
  1824. ;
  1825.     CALL    init_cmd
  1826.     mov    dx,offset bad_init_msg
  1827.     jc    init_exp16_ram_exit
  1828.  
  1829.     CALL    configure_command
  1830.     mov    dx,offset bad_config_msg
  1831.     jc    init_exp16_ram_exit
  1832.  
  1833.     CALL    diagnose_command
  1834.     jc    init_exp16_ram_exit
  1835.  
  1836.     movseg    es,cs
  1837.     mov    si,offset rom_address
  1838.     mov    cx,EADDR_LEN
  1839.     call    set_address
  1840.     jnc    sa_ok
  1841.  
  1842.     mov    dx,offset badset_msg
  1843.     mov    ah,9
  1844.     int    21h
  1845. sa_ok:
  1846. ;
  1847. ; Disable loopback.
  1848. ;
  1849.     LEA    DX, [BP].@Config
  1850.     IN    AX, DX
  1851.     AND    AL, NOT loopback_enable
  1852.     OUT    DX, AL
  1853.  
  1854.     clc
  1855.     ret
  1856.  
  1857. init_exp16_ram_exit:
  1858.     stc
  1859.     RET
  1860.  
  1861.  
  1862. ; This procedure must wait until the ASIC finishes reset.  This will take
  1863. ; around 240 uSec.  This loop will time out after 500 uSec.
  1864. ;
  1865.     five_hundred_micros    EQU    1194
  1866. ;
  1867. reset_board:
  1868. ;enter with bp=io_addr
  1869.  
  1870.     LEA    DX, [BP].@EEPROM_Ctrl
  1871.     MOV    AL, ASIC_Reset
  1872.     OUT    DX, AL
  1873.  
  1874.     XOR    AL, AL
  1875.     OUT    DX, AL
  1876.  
  1877. ;
  1878. ; Get current tick count.  This loop will wait for 500 uSec to pass
  1879. ; before failing.
  1880. ;
  1881.     CALL    ReadTickCounter
  1882.     MOV    BX, AX
  1883.  
  1884. reset_delay:
  1885.  
  1886.     PUSH    BX
  1887.     LEA    DX, [BP].@ID_Port    ; Set DX to the auto-id port.
  1888.     CALL    check_for_exp16_hardware
  1889.     POP    BX
  1890.  
  1891.     CMP    AX, BART_Board_ID
  1892.     JE    reset_board_exit
  1893.  
  1894.     CALL    ReadTickCounter
  1895.     NEG    AX
  1896.     ADD    AX, BX
  1897.     CMP    AX, five_hundred_micros
  1898.     JB    reset_delay
  1899.  
  1900.     mov    dx, offset reset_error
  1901.     stc
  1902.     RET
  1903.  
  1904. reset_board_exit:
  1905.  
  1906.     MOV    BX, AX
  1907.     clc
  1908.     RET
  1909.  
  1910.  
  1911. reset_586:
  1912. ;enter with bp = io_addr
  1913.     lea    dx, [bp].@EEPROM_Ctrl
  1914.     mov    al, _586_Reset
  1915.     out    dx, al
  1916.     ret
  1917.  
  1918.  
  1919. free_586_reset:
  1920. ;enter with bp = io_addr
  1921.     lea    dx, [bp].@EEPROM_Ctrl
  1922.     xor    al, al
  1923.     out    dx, al
  1924.     ret
  1925.  
  1926. check_for_exp16_hardware:
  1927. ;enter with dx = ID port (or maybe shadow ID port).
  1928. ;
  1929. ; BX will have board ID when the loop is done.  CX is the loop count.
  1930. ;
  1931.     XOR    BX, BX
  1932.     MOV    CX, 4
  1933.  
  1934. get_board_id_loop:
  1935. ;
  1936. ; Init registers for loop.  CX needs to be used in the loop, and AH
  1937. ; could be set from the last loop.
  1938. ;
  1939.     PUSH    CX
  1940.     XOR    AH, AH
  1941. ;
  1942. ; Read ID port.  See description above.
  1943. ;
  1944.     IN    AL, DX
  1945. ;
  1946. ; Make nibble ID a shift count in CL.
  1947. ;
  1948.     MOV    CL, AL
  1949.     AND    CL, 00000011B
  1950.     SHL    CL, 1
  1951.     SHL    CL, 1
  1952. ;
  1953. ; Move ID nibble to low order bits of AX, then shift then into place.  Put
  1954. ; the board ID nibble into BX.  After four passes, BX will have board ID.
  1955. ;
  1956.     SHR    AL, 1
  1957.     SHR    AL, 1
  1958.     SHR    AL, 1
  1959.     SHR    AL, 1
  1960.     SHL    AX, CL
  1961.     OR    BX, AX
  1962. ;
  1963. ; Recover loop count, and loop.
  1964. ;
  1965.     POP    CX
  1966.     LOOP    get_board_id_loop
  1967. ;
  1968. ; Return board ID in AX.
  1969. ;
  1970.     MOV    AX, BX
  1971.     RET
  1972.  
  1973.  
  1974. ;
  1975. ; Command #1:  Initialize
  1976. ;
  1977. init_cmd:
  1978.     XOR    AX, AX                ; Init command
  1979.     MOV    BX, BIT_CX + BIT_CNA        ; status
  1980.     CALL    issue_command
  1981.     RET
  1982.  
  1983. diagnose_command:
  1984. ;return nc if no problem, else cy,dx->error message.
  1985. ;
  1986. ; Set up individual address command block.
  1987. ;
  1988.     MOV    BX, BIT_EL+GA_diagnose
  1989.     CALL    setup_command_block
  1990. ;
  1991. ; Execute the diagnose command.
  1992. ;
  1993.     MOV    AX, CUC_Start
  1994.     MOV    BX, BIT_CNA
  1995.     CALL    issue_command
  1996. ;
  1997. ; Check diagnostics results.
  1998. ;
  1999.     LEA    DX, [BP].@SMB_Ptr        ;Move IO frame to the command
  2000.     MOV    AX, OFFSET cb            ; command block.
  2001.     OUT    DX, AX
  2002.  
  2003.     LEA    DX, [BP].@mem_loc_0        ;Read in the diagnose status
  2004.     IN    AX, DX                ; word.
  2005. ;
  2006. ; Assume 586 failed the test.  Set AX to an error message and exit
  2007. ; with the zero bit cleared.
  2008. ;
  2009.     test    ax, 0800H            ;Test failure bit.  If set,
  2010.     jnz    diagnose_error            ; then error exit.
  2011.     clc
  2012.     ret
  2013. diagnose_error:
  2014.     mov    dx,offset _586_diagnostic_failure
  2015.     stc
  2016.     ret
  2017.  
  2018.  
  2019. ;
  2020. ; Command #4:  RU_START
  2021. ;
  2022. ru_start:
  2023. ;
  2024. ; Set SCBs pointer to receive blocks at head of list.
  2025. ;
  2026.     lea    dx, [bp].@SCB_RFA        ;Set pointer to receive blocks
  2027.     mov    ax, receive_head        ; to the head of the receive
  2028.     out    dx, ax                ; block list.
  2029. ;
  2030. ; Signal 586 to start the receive unit.  cmd_clear leaves DX pointing
  2031. ; to SCB command register.
  2032. ;
  2033.     cmd_clear
  2034.     mov    ax, ruc_start
  2035.     out    dx, ax
  2036.     issue_CA
  2037.     ret
  2038.  
  2039.  
  2040. find_a_board:
  2041.     mov    bx,offset io_addresses
  2042. no_exp16_here:
  2043.     mov    bp,[bx]
  2044.     cmp    bp,0
  2045.     je    no_exp16s
  2046.     inc    bx
  2047.     inc    bx
  2048.     push    bx
  2049.     call    reset_board
  2050.     pop    bx
  2051.     jc    no_exp16_here
  2052.  
  2053.     clc
  2054.     ret
  2055.  
  2056. no_exp16s:
  2057.     stc
  2058.     ret
  2059.  
  2060. get_system_info:
  2061. ;exit with zr if okay, or nz, dx -> error message if not okay.
  2062.     cmp    io_addr,-1
  2063.     jne    addr_override
  2064.     call    find_a_board
  2065.     jnc    board_id_ok
  2066.     jmp    bad_or_no_board
  2067.  
  2068. addr_override:
  2069.  
  2070.     MOV    bp, io_addr
  2071.  
  2072. ;
  2073. ; Next, get the exp16 board ID.  If the ID is not what we expect, then
  2074. ; exit with error code in AX.
  2075. ;
  2076.     call    reset_board
  2077.     jnc    board_id_ok
  2078. ;
  2079. ; Could search for exp16 board, but we error exit instead.
  2080. ;
  2081. bad_or_no_board:
  2082.  
  2083.     mov    dx, offset board_not_installed
  2084.     stc
  2085.     JMP    SHORT get_system_info_exit
  2086.  
  2087. board_id_ok:
  2088.     mov    io_addr,bp
  2089.  
  2090.     LEA    DX, [BP].@ID_Port    ; Set DX to the auto-id port.
  2091.     or    DX,3000h        ;use the shadow port
  2092.     CALL    check_for_exp16_hardware
  2093.     mov    board_id,ax
  2094.  
  2095. ;
  2096. ; Since the software will be reading the EEPROM during the
  2097. ; initialization, the 586 needs to be inactive.  This is because the
  2098. ; control lines to the EEPROM are shared between the 586 and this
  2099. ; software.  To keep from getting fouled up, the 586 reset line is
  2100. ; asserted here (now that we have a base IO address, and we know that
  2101. ; the hardware is present).  The 586 is not released from reset until
  2102. ; after its data structures are intialized.
  2103. ;
  2104.     CALL    reset_586
  2105. ;
  2106. ; Validate the EEPROM by doing a checksum.
  2107. ;
  2108.     mov    cx, 40h
  2109.     CALL    check_eeprom
  2110.     JC    get_system_info_exit
  2111. ;
  2112. ; Get the amount of memory on the adapter.
  2113. ;
  2114.     CALL    test_buffer_memory
  2115.     JC    get_system_info_exit
  2116.  
  2117. ;
  2118. ; Get the connection type.  If carry clear, then AL has connection
  2119. ; type.  Otherwise AX has error code.
  2120. ;
  2121.     CALL    get_connection_type
  2122.     JC    get_system_info_exit
  2123.     MOV    connection_type, AL
  2124. ;
  2125. ; Read the Ethernet address out of the EEPROM.
  2126. ;
  2127.     MOV    AX, EE_ETHERNET_ADD_HIGH
  2128.     CALL    read_eeprom
  2129.     xchg    ah,al
  2130.     MOV    word ptr rom_address[0], AX
  2131.  
  2132.     MOV    AX, EE_ETHERNET_ADD_MID
  2133.     CALL    read_eeprom
  2134.     xchg    ah,al
  2135.     MOV    word ptr rom_address[2], AX
  2136.  
  2137.     MOV    AX, EE_ETHERNET_ADD_LOW
  2138.     CALL    read_eeprom
  2139.     xchg    ah,al
  2140.     MOV    word ptr rom_address[4], AX
  2141.  
  2142.     mov    ax,EE_INT
  2143.     call    read_eeprom
  2144.     mov    cl,EE_SHIFT
  2145.     shr    ax,cl
  2146.     mov    encoded_int_no,al
  2147.     mov    bx,offset irq_xlat_table
  2148.     xlat
  2149.     mov    int_no,al
  2150.  
  2151. ;
  2152. ; Get the Slot width.  If carry clear, then AL has the slot width.
  2153. ; Otherwise AX has error code.
  2154. ;
  2155.     LEA    DX, [BP].@Config
  2156.     IN    AL, DX
  2157. ;
  2158. ; Slot width is found in the adapters configuration register.
  2159. ;
  2160.     and    al, slot_width_mask
  2161.     mov    _16_not_8_bit_slot, al
  2162.  
  2163.     clc
  2164.     ret
  2165.  
  2166. get_system_info_exit:
  2167. ;we only ever get here with cy set.
  2168.     RET
  2169.  
  2170. ;
  2171. ;
  2172. ; Return connection type in AL with carry clear.
  2173. ;
  2174. ;
  2175. get_connection_type:
  2176.  
  2177.     cmp    board_id,BART_Board_ID    ;a real BART?
  2178.     je    get_auto_cnt_exit    ;yes, it doesn't *have* an ECR1.
  2179.  
  2180.     MOV    AX, AUTO_CON_ADDRESS    ;get the auto-connection bit.
  2181.     CALL    read_eeprom
  2182.     TEST    AX, AUTO_CON_MASK    ;set?
  2183.     Je    get_auto_cnt_exit    ;no, okay.
  2184.     mov    bl,CONN_AUTO        ;yes, we should autosense the connector.
  2185.     jmp    short get_connection_type_ret
  2186. get_auto_cnt_exit:
  2187.  
  2188. ;
  2189. ; Read the connection address from the EEPROM.
  2190. ;
  2191.     MOV    AX, connection_address
  2192.     CALL    read_eeprom        ;Read_eeprom does not trash DI
  2193.  
  2194. ;
  2195. ; Assume AUI type connection.  Check connection fields to see if this
  2196. ; is a BNC connection.  Jump if it is BNC.
  2197. ;
  2198.     MOV    BL, CONN_AUI
  2199.     TEST    AX, CONNECTION_FIELD
  2200.     JZ    get_connection_type_ret
  2201.  
  2202. ;
  2203. ; Here if NOT BNC.  Must read another EEPROM word to tell if AUI or
  2204. ; TPE.  Assume AUI and then check for TPE.
  2205. ;
  2206.     MOV    AX, tpe_address
  2207.     CALL    read_eeprom        ;Read_eeprom does not trash DI
  2208.  
  2209. ;
  2210. ; Check for AUI connection.
  2211. ;
  2212.     mov    bl,CONN_BNC
  2213.     TEST    AX, TPE_type_field
  2214.     JZ    get_connection_type_ret
  2215.  
  2216. ;
  2217. ; Here if TPE type connection.
  2218. ;
  2219.     MOV    BL, CONN_TPE
  2220.  
  2221. get_connection_type_ret:
  2222.  
  2223.     MOV    AL, BL
  2224.  
  2225.     CLC
  2226.     RET
  2227.  
  2228.  
  2229. ;
  2230. ;
  2231. ; Do a checksum on the EEPROM.
  2232. ;
  2233. ; The checksum is the same as the board ID.
  2234. ;
  2235. check_eeprom:
  2236. ;enter with bp=io_addr, cx = count of bytes to sum starting at 0.
  2237. ;exit with nc if okay, cy, dx -> error message if not.
  2238.  
  2239.     xor    bx, bx
  2240.  
  2241. checksum_loop:
  2242.  
  2243.     mov    ax, cx
  2244.     dec    ax
  2245.     call    read_eeprom
  2246.  
  2247.     add    bx, ax
  2248.     loop    checksum_loop
  2249.  
  2250.     cmp    bx, BART_Board_ID
  2251.     jne    checksum_error
  2252.  
  2253.     clc
  2254.     ret
  2255.  
  2256. checksum_error:
  2257.     mov    dx,offset eeprom_checksum_error
  2258.     stc
  2259.     ret
  2260.  
  2261.  
  2262. test_buffer_memory:
  2263. ;enter with bp=io_addr
  2264. ;exit with nc and al=_64k_not_32k if no error, or cy and di -> address in error.
  2265.  
  2266. ; Set up SI with the maximum number of words to test.  If there is an
  2267. ; error testing the high 32K of memory, then we will restart the
  2268. ; test at 32K.  When the tests pass, the memory size is passed back
  2269. ; in AX.
  2270. ;
  2271.     mov    si, 64 * (1024/2)
  2272. ;
  2273. ; Warm up the buffer memory with 16 word writes.
  2274. ;
  2275.     mov    cx, 16
  2276.     call    write_zeros
  2277.  
  2278.     cmp    cs:is_186,0
  2279.     jne    start_memory_tests
  2280.  
  2281. restart_memory_tests:
  2282. ;
  2283. ; Here if error testing memory and SI is set to 64K buffer size.
  2284. ; We restart the tests for 32K buffer only.  If an error occurs
  2285. ; with SI set to 32K, then a memory error is reported.
  2286. ;
  2287.     mov    si, 32 * (1024/2)
  2288.  
  2289. start_memory_tests:
  2290. ;
  2291. ; Zero RAM.  Set write pointer to the base address and then fill the
  2292. ; bufffer memory with zeros.
  2293. ;
  2294.     mov    cx, si
  2295.     call    write_zeros
  2296.  
  2297.     call    word_memory_test_pattern
  2298.     jc    buffer_mem_error_exit
  2299.  
  2300.     cmp    cs:is_186,0
  2301.     je    _8088_quick_exit
  2302.  
  2303.     mov    cx, si
  2304.     call    write_zeros
  2305.  
  2306.     call    byte_memory_test_pattern
  2307.     jc    buffer_mem_error_exit
  2308.  
  2309. _8088_quick_exit:
  2310. ;
  2311. ; Zero RAM.  Set write pointer to the base address and then fill the
  2312. ; bufffer memory with zeros.
  2313. ;
  2314.     mov    cx, si
  2315.     call    write_zeros
  2316.  
  2317. ;
  2318. ; Set _64K_not_32K to the size of the memory that passed diagnostics.
  2319. ;
  2320.     cmp    si, 32 * (1024/2)    ;did we quit at 32K
  2321.     je    buffer_mem_exit        ;yes, we only have 32K.
  2322.  
  2323.     mov    _64K_not_32K,1        ;no, we must have 64K.
  2324.  
  2325. buffer_mem_exit:
  2326.     clc
  2327.     ret
  2328.  
  2329. buffer_mem_error_exit:
  2330. ;
  2331. ; If error occured, and SI is not set for 32K, then retry tests with
  2332. ; SI set for 32K.  If the error occurs and the size is 32K, then the
  2333. ; Exp16 board memory is bad.
  2334. ;
  2335.     CMP    SI, 32 * (1024/2)
  2336.     JNE    restart_memory_tests
  2337.  
  2338.     MOV    DX, OFFSET buffer_memory_error
  2339.     STC    ;Set carry to indicate error.
  2340.     RET
  2341.  
  2342.  
  2343. write_zeros:
  2344. ;enter with bp=io_addr, cx=number of zero words to write.
  2345. ;
  2346. ; Move write pointer to the beginning of the buffer memory.
  2347. ;
  2348.     LEA    DX, [BP].@Write_Ptr
  2349.     XOR    AX, AX
  2350.     OUT    DX, AX
  2351. ;
  2352. ; Set DX to the data register and write out zeros CX times.
  2353. ;
  2354.     mov    dx, bp            ;@Data_Reg
  2355. warm_up:
  2356.     out    dx, ax
  2357.     loop    warm_up
  2358.     ret
  2359.  
  2360.  
  2361. word_memory_test_pattern:
  2362. ;enter with si = number of words to test.
  2363.  
  2364. ;
  2365. ; Set CX to number of words to test.  Set BX to beginning og pattern.
  2366. ;
  2367.     MOV    CX, SI
  2368.     MOV    BX, 1
  2369.  
  2370. ;
  2371. ; Set DI to beginning of the buffer.
  2372. ;
  2373.     XOR    DI, DI
  2374.  
  2375. word_inc_pattern:
  2376.  
  2377.     CALL    loop_set_up
  2378.     IN    AX, DX
  2379.     OR    AX, AX
  2380.     JNE    word_memory_test_pattern_error
  2381.  
  2382. ;
  2383. ; Write Test Pattern.
  2384. ;
  2385.     MOV    AX, BX
  2386.     OUT    DX, AX
  2387.  
  2388. ;
  2389. ; Increment BX to next test pattern value.
  2390. ;
  2391.     ADD    BX, 3
  2392.  
  2393. ;
  2394. ; Increment DI to next test memory location.
  2395. ;
  2396.     ADD    DI, 2
  2397.     LOOP    word_inc_pattern
  2398.  
  2399. ;
  2400. ; Set Read pointer to beginning of buffer.
  2401. ;
  2402.     LEA    DX, [BP].@read_ptr
  2403.     XOR    AX, AX
  2404.     OUT    DX, AX
  2405.     MOV    DX, BP            ;@Data_Reg
  2406.  
  2407. ;
  2408. ; Set CX to number of words to test.  Set BX to beginning og pattern.
  2409. ;
  2410.     MOV    CX, SI
  2411.     MOV    BX, 1
  2412.  
  2413. word_check_pattern:
  2414.  
  2415.     IN    AX, DX
  2416.     CMP    AX, BX
  2417.     JNE    word_memory_test_pattern_error
  2418.  
  2419. ;
  2420. ; Increment BX to next test pattern value.
  2421. ;
  2422.     ADD    BX, 3
  2423.  
  2424.     LOOP    word_check_pattern
  2425.  
  2426.     CLC
  2427.     RET
  2428.  
  2429. word_memory_test_pattern_error:
  2430.  
  2431.     STC
  2432.     RET
  2433.  
  2434.  
  2435. byte_memory_test_pattern:
  2436. ;enter with si = number of bytes to test.
  2437.  
  2438. ;
  2439. ; Set CX to number of bytes to test.  Set BX to beginning of pattern.
  2440. ;
  2441.     MOV    CX, SI
  2442.     SHL    CX, 1
  2443.     MOV    BL, 1
  2444.  
  2445. ;
  2446. ; Set DI to beginning of the buffer.
  2447. ;
  2448.     XOR    DI, DI
  2449.  
  2450. byte_inc_pattern:
  2451.  
  2452.     CALL    loop_set_up
  2453.     IN    AL, DX
  2454.     OR    AL, AL
  2455.     JNE    byte_memory_test_pattern_error
  2456.  
  2457. ;
  2458. ; Write Test Pattern.
  2459. ;
  2460.     MOV    AL, BL
  2461.     OUT    DX, AL
  2462.  
  2463. ;
  2464. ; Increment BX to next test pattern value.
  2465. ;
  2466.     ADD    BL, 3
  2467.  
  2468. ;
  2469. ; Increment DI to next test memory location.
  2470. ;
  2471.     INC    DI
  2472.  
  2473.     LOOP    byte_inc_pattern
  2474.  
  2475. ;
  2476. ; Set Read pointer to beginning of buffer.
  2477. ;
  2478.     LEA    DX, [BP].@read_ptr
  2479.     XOR    AX, AX
  2480.     OUT    DX, AX
  2481.     MOV    DX, BP            ;@Data_Reg
  2482.  
  2483. ;
  2484. ; Set CX to number of bytes to test.  Set BX to beginning of pattern.
  2485. ;
  2486.     MOV    CX, SI
  2487.     SHL    CX, 1
  2488.     MOV    BL, 1
  2489.  
  2490. byte_check_pattern:
  2491.  
  2492.     IN    AL, DX
  2493.     CMP    AL, BL
  2494.     JNE    byte_memory_test_pattern_error
  2495.  
  2496. ;
  2497. ; Increment BX to next test pattern value.
  2498. ;
  2499.     add    bl, 3
  2500.  
  2501.     loop    byte_check_pattern
  2502.  
  2503.     clc
  2504.     ret
  2505.  
  2506. byte_memory_test_pattern_error:
  2507.  
  2508.     stc
  2509.     ret
  2510.  
  2511. loop_set_up:
  2512. ;enter with bp=io_addr, di=buffer address.
  2513. ;exit with ax=value at di, dx=I/O address to access buffer memory at DI
  2514.  
  2515.     PUSH    DI
  2516.  
  2517.     MOV    AX, DI            ;SMB_Ptr must be on 16 byte
  2518.     AND    AX, 0FFE0H
  2519.     AND    DI, 0001FH
  2520.  
  2521.     LEA    DX, [BP].@SMB_Ptr        ;Set IO page frame to the
  2522.     OUT    DX, AX
  2523.  
  2524.  
  2525.     TEST    DI, 0010H
  2526.     JZ    loop_set_up_1
  2527.  
  2528.     ADD    DI, @MEM_LOC_0
  2529.  
  2530. loop_set_up_1:
  2531.     AND    DI, 0FFEFH
  2532.     LEA    DX, [BP+DI].@MEM_LOC_0        ;Set DX for IO from buffer and
  2533.  
  2534.     POP    DI
  2535.  
  2536.     RET
  2537.  
  2538.  
  2539. read_eeprom:
  2540. ;enter with bp=io_addr, ax = EEPROM location.
  2541. ;exit with ax = EEPROM contents.
  2542. ;preserves di.
  2543.     push    di
  2544.     push    bx
  2545.     push    cx
  2546.  
  2547. ;  Point to EEPROM control port.
  2548.  
  2549.     lea    dx, [bp].@eeprom_ctrl
  2550.     mov    bx, ax
  2551.  
  2552. ; Select the EEPROM.  Mask off the ASIC and 586 reset bits and set
  2553. ; the ee_cs bit in the EEPROM control register.
  2554.  
  2555.     in    al, dx
  2556.     and    al, 10110010b
  2557.     or    al, ee_cs
  2558.     out    dx, al
  2559.  
  2560. ; Write out read opcode and EEPROM location.
  2561.  
  2562.     mov    ax, eeprom_read_opcode        ;Set AX to READ opcode and
  2563.     mov    cx, 3                ;Send it to the EEPROM circuit
  2564.     call    shift_bits_out
  2565.  
  2566.     mov    ax, bx                ;Tell EEPROM which register is
  2567.     mov    cx, 6                ; to be read.  6 bit address.
  2568.     call    shift_bits_out
  2569.  
  2570.     call    shift_bits_in            ;AX gets EEPROM register
  2571.  
  2572.     call    eeprom_clean_up            ;Leave EEPROM in known state.
  2573.  
  2574.     pop    cx
  2575.     pop    bx
  2576.     pop    di
  2577.     ret
  2578.  
  2579.  
  2580. ;-----------------------------------------------------------------------------
  2581. ;  Writes the specified value to the specified EEPROM register at the 
  2582. ;  specified base I/O address.
  2583. ;
  2584. ;  Entry  - BP  Base IO.
  2585. ;           AX  EEPROM location to write.
  2586. ;        BX  Value to write
  2587. ;
  2588. ;  Return - AX = 0 if no error
  2589. ;        AX = Pointer to Error message
  2590. ;
  2591. ;-----------------------------------------------------------------------------
  2592. write_eeprom:
  2593. ;enter with bp=io_addr, ax = EEPROM location, bx = new contents.
  2594. ;exit with ax = 0 if no error, ax -> error if error.
  2595. ;preserves di.
  2596.  
  2597.     push    bx
  2598.     mov    bx, ax
  2599.  
  2600.     lea    dx, [bp].@EEPROM_Ctrl    ;Point to EEPROM port.
  2601.  
  2602.     in    al, dx                  ;Select EEPROM
  2603.     and    al, 10110000b
  2604.     or    al, ee_cs
  2605.     out    dx, al
  2606.  
  2607. ; Send Erase/write enable opcode to the EEPROM.
  2608.     mov    ax, EEPROM_EWEN_opcode    ;Send erase/write enable
  2609.     mov    cx, 5            ; command to the EEPROM.
  2610.     call    shift_bits_out
  2611.  
  2612.     mov    cx, 4            ;Send 4 don't cares as
  2613.     call    shift_bits_out        ; required by the eeprom
  2614.  
  2615.     call    stand_by
  2616.  
  2617. ; Send the erase opcode to the EEPROM and wait for the command to 
  2618. ; complete.
  2619.     mov    ax, EEPROM_erase_opcode    ;Send Erase command to the
  2620.     mov    cx, 3            ; EEPROM.
  2621.     call    shift_bits_out
  2622.  
  2623.     mov    ax, bx            ;Send EEPROM location the the
  2624.     mov    cx, 6            ; EEPROM.  6 bit address.
  2625.     call    shift_bits_out
  2626.  
  2627.     call    wait_eeprom_cmd_done    ;wait for end-of-operation
  2628.     jc    write_fault_pop        ; go if error
  2629.  
  2630.     call    stand_by
  2631.  
  2632. ; Send the write opcode, location to write, and data to write to the
  2633. ; EEPROM.  Wait for the write to complete.
  2634.     mov    ax, EEPROM_write_opcode    ;Send write command to the 
  2635.     mov    cx, 3            ; EEPROM.
  2636.     call    shift_bits_out
  2637.  
  2638.     mov    ax, bx            ;Send the EEPROM location to
  2639.     mov    cx, 6            ; the EEPROM.  5 bit address.
  2640.     call    shift_bits_out
  2641.  
  2642.     pop    ax            ;Send data to write to the 
  2643.     mov    cx, 16            ; EEPROM.  16 bits.
  2644.     call    shift_bits_out
  2645.  
  2646.     call    wait_eeprom_cmd_done    ;Await end-of-command
  2647.     jc    write_fault        ;go if error
  2648.  
  2649.     call    stand_by
  2650.  
  2651. ; Send the erase write disable command to the EEPROM.
  2652.     mov    ax, EEPROM_EWDS_opcode        ;Disable the Erase/write
  2653.     mov    cx, 5                ; command previously sent to
  2654.     call    shift_bits_out            ; EEPROM.
  2655.  
  2656.     mov    cx, 4                      ;Send 4 don't cares as
  2657.     call    shift_bits_out            ; required by the eeprom
  2658.  
  2659.     call    eeprom_clean_up
  2660.  
  2661.     clc
  2662.     ret
  2663.  
  2664. write_fault_pop:
  2665.     add    sp, 2                ;Get rid of data on stack
  2666. write_fault:
  2667. ;;;    lea    ax, eeprom_write_error
  2668.     stc
  2669.     ret
  2670.  
  2671.  
  2672. shift_bits_out:
  2673. ;enter with ax=data to be shifted, cx=# of bits to be shifted.
  2674.  
  2675.     push    bx
  2676.  
  2677. ; Data bits are right justified in the AX register.  Move the data
  2678. ; into BX and left justify it.  This will cause addresses to to
  2679. ; be sent to the EEPROM high order bit first.
  2680.  
  2681.     mov    bx, ax
  2682.     mov    ch, 16
  2683.     sub    ch, cl
  2684.     xchg    cl, ch
  2685.     shl    bx, cl
  2686.     xchg    cl, ch
  2687.     xor    ch, ch
  2688.  
  2689. ; Get the EEPROM control register into AL.  Mask of the ASIC asn 586
  2690. ; reset bits.
  2691.  
  2692.     in    al, dx
  2693.     and    al, 10111111b
  2694.  
  2695. ; Set or clear DI bit in EEPROM control register based on value of
  2696. ; data in BX.
  2697.  
  2698. out_shift_loop:
  2699.     and    al, not ee_di            ;Assume data bit will be zero
  2700.  
  2701.     rcl    bx, 1                ;Is the data bit a one?
  2702.     jnc    out_with_it            ;No
  2703.     or    al, ee_di            ;Yes
  2704. out_with_it:
  2705.     out    dx, al                ;Output a 0 or 1 on data pin
  2706.  
  2707. ; Set up time for data is .4 Microseconds.  So to be safe (incase of
  2708. ; this software is run on a cray), call delay.
  2709.     mov    di, 1
  2710.     call    eeprom_delay
  2711.  
  2712.     call    raise_eeprom_clock    ; Clock the data into the EEPROM.
  2713.     call    lower_eeprom_clock
  2714.     loop    out_shift_loop        ;Send next bit
  2715.  
  2716.     and    al, not ee_di        ;Force data bit to zero
  2717.     out    dx, al            ;Output a 0 on data pin
  2718.  
  2719.     pop    bx
  2720.  
  2721.     ret
  2722.  
  2723. shift_bits_in:
  2724. ;exit with ax = register contents.
  2725.     push    bx
  2726.     push    cx
  2727.  
  2728. ; BX will receive the 16 bits read from the EEPROM.  Data is valid in
  2729. ; data out bit (DO) when clock is high.  There for, this procedure
  2730. ; raises clock and waits a minimum amount of time.  DO is read, and
  2731. ; clock is lowered.
  2732.  
  2733.     in    al, dx                ;Init AL to eeprom control
  2734.     and    al, 10111111b            ; register.
  2735.  
  2736.     xor    bx, bx                ;Init holding register
  2737.     mov    cx, 16                ;We'll shift in 16 bits
  2738.  
  2739. in_shift_loop:
  2740.     shl    bx, 1            ;Adjust holding register for
  2741.                     ; next bit
  2742.     call    raise_eeprom_clock
  2743.  
  2744.     in    al, dx
  2745.     and    al, 10111111b
  2746.  
  2747.     test    al, ee_do        ;Was the data bit a one?
  2748.     jz    in_eeprom_delay        ;No
  2749.  
  2750.     or    bx, 1            ;Yes, reflect data bit state
  2751.                     ; in holding register.
  2752.  
  2753. in_eeprom_delay:
  2754.     call    lower_eeprom_clock
  2755.     loop    in_shift_loop        ;CONTINUE
  2756.  
  2757.     mov    ax, bx            ;AX = data
  2758.  
  2759.     pop    cx
  2760.     pop    bx
  2761.     ret
  2762.  
  2763. raise_eeprom_clock:
  2764.     or    al, ee_sk        ;Clock the bit out by raising
  2765.     jmp    short eeprom_clock_common
  2766. lower_eeprom_clock:
  2767.     and    al, not ee_sk            ;Lower ee_sk
  2768. eeprom_clock_common:
  2769.     out    dx, al
  2770.     mov    di, ee_tick
  2771.     call    eeprom_delay            ;Waste time
  2772.     ret
  2773.  
  2774.  
  2775. wait_eeprom_cmd_done:
  2776. ;Wait for ee_do to go high, indicating end-of-write or end-of-erase
  2777. ;operation.  Wait at most 20 ms (EEPROM needs at most 10).
  2778. ;exit with nc if no error.
  2779.  
  2780.     push    bx
  2781.     push    cx
  2782.  
  2783.     call    stand_by
  2784.  
  2785.     call    readtickcounter
  2786.     mov    di, ax
  2787.  
  2788. ee_do_wait_loop:
  2789.  
  2790.     call    readtickcounter
  2791.     neg    ax
  2792.     add    ax, di
  2793.  
  2794.     cmp    ax, 28640        ;12 Millisecond wait
  2795.     jb    ee_do_wait_loop
  2796.  
  2797.     in    al, dx            ;Get EEPROM control register
  2798.  
  2799.     test    al, EE_DO        ;ee_do high?
  2800.     jnz    ee_do_found
  2801.  
  2802.     stc
  2803.     jmp    short wait_eeprom_cmd_done_exit
  2804.  
  2805. ee_do_found:
  2806.  
  2807.     clc                ;"clean" status (no timeout)
  2808.  
  2809. wait_eeprom_cmd_done_exit:
  2810.  
  2811.     pop    cx
  2812.     pop    bx
  2813.     ret
  2814.  
  2815.  
  2816. stand_by:
  2817. ; lower chip select for 1 microsecond.
  2818.     in    al, dx                  ;de-select EEPROM
  2819.     and    al, (10111110b) and (not ee_cs)
  2820.     out    dx, al
  2821.  
  2822.     mov    di, 2
  2823.     call    eeprom_delay
  2824.  
  2825.     or    al, ee_cs
  2826.     out    dx, al
  2827.  
  2828.     ret
  2829.  
  2830. ; Lower EEPROM chip select and DI.
  2831. ; Clock EEPROM twice and leave clock low.
  2832.  
  2833. eeprom_clean_up:
  2834.  
  2835.     push    ax
  2836.  
  2837.     in    al, dx
  2838.     and    al, 10111111b
  2839.     and    al, not (ee_cs or ee_di)
  2840.     out    dx, al
  2841.  
  2842.     call    raise_eeprom_clock
  2843.     call    lower_eeprom_clock
  2844.  
  2845.     pop    ax
  2846.     ret
  2847.  
  2848. ; DI has number of 838 Nanoseconds clock counts
  2849. eeprom_delay:
  2850.  
  2851.     push    ax
  2852.     push    bx
  2853.     push    dx
  2854.  
  2855.     call    readtickcounter
  2856.     mov    bx, ax
  2857.  
  2858. eeprom_delay_loop:
  2859.  
  2860.     call    readtickcounter
  2861.     neg    ax
  2862.     add    ax, bx
  2863.     cmp    ax, di
  2864.     jb    eeprom_delay_loop
  2865.  
  2866.     pop    dx
  2867.     pop    bx
  2868.     pop    ax
  2869.     ret
  2870.  
  2871. iochrdy_test:
  2872. ; First test to see if the driver is supposed to run this test.
  2873.     MOV    AX, lock_bit_address
  2874.     CALL    read_eeprom
  2875.  
  2876.     TEST    AX, lock_bit_mask
  2877.     JNZ    iochrdy_test_exit
  2878. ; Get the configuration register.
  2879.  
  2880.     LEA    DX, [BP].@config
  2881.     IN    AL, DX
  2882.  
  2883. ; Set the iochrdy test bit with and set iochrdy to late.
  2884.     OR    AL, iochrdy_test_mask+iochrdy_late
  2885.     CLI
  2886.     OUT    DX, AL
  2887.  
  2888. ; Test IOCHRDY with IO.
  2889.     LEA    DX, [BP].@mem_loc_0
  2890.     IN    AX, DX
  2891.  
  2892. ; Read in the results of the test.  Save results in BL.
  2893.     LEA    DX, [BP].@config
  2894.     IN    AL, DX
  2895.     MOV    BL, AL
  2896.  
  2897. ; Turn iochrdy test off.
  2898.     AND    AL, NOT iochrdy_test_mask
  2899.     OUT    DX, AL
  2900.     STI
  2901.  
  2902. ; Test results.  Exit if IOCHRDY_LATE bit is set correctly.
  2903.     TEST    BL, iochrdy_test_result
  2904.     JZ    iochrdy_test_exit
  2905.  
  2906. ; Here if test failed.  Clear the 16 bit override bit (force 8 bit
  2907. ; transfers) and print a warning message.
  2908.     AND    AL, NOT _16_bit_override_bit
  2909.     OUT    DX, AL
  2910.  
  2911.     mov    dx, offset iochrdy_problem
  2912.     mov    ah,9
  2913.     int    21h
  2914.  
  2915.  
  2916. iochrdy_test_exit:
  2917.  
  2918.     RET
  2919.  
  2920.  
  2921.  
  2922. iochrdy_problem    db    "IOCHRDY Problem.  EtherExpress forced into 8 Bit Mode.",CR,LF,'$'
  2923. buffer_memory_error    db    "Memory error on the EtherExpress board",CR,LF,'$'
  2924.  
  2925. reset_error    db    "ASIC reset failure on EtherExpress board",CR,LF,'$'
  2926.  
  2927. _586_diagnostic_failure    db    "82586 diagnostic failure on the "
  2928.     db    "EtherExpress board",CR,LF,'$'
  2929.  
  2930. _586_not_responding_msg    db    "82586 did not respond to command "
  2931.     db    "on the EtherExpress board",CR,LF,'$'
  2932.  
  2933. command_unit_not_idle    db    "82586 command unit is not "
  2934.     db    "responding on the EtherExpress board",CR,LF,'$'
  2935.  
  2936. invalid_int_number    db    "EtherExpress board IRQ/Interrupt number "
  2937.     db    "not specified correctly",CR,LF,'$'
  2938.  
  2939. eeprom_checksum_error    db    "EEPROM failed checksum",CR,LF,'$'
  2940.  
  2941. Board_Not_Installed    db    "EtherExpress Board not found",CR,LF,'$'
  2942.  
  2943. irq_config_error    db    "IRQ selection is for 16 bit slot only.",CR,LF,'$'
  2944.  
  2945. bad_config_msg    db    "Could not configure the 82586",CR,LF,'$'
  2946.  
  2947. bad_init_msg    db    "Could not initialize the 82586",CR,LF,'$'
  2948.  
  2949. code    ends
  2950.  
  2951.     end
  2952.