home *** CD-ROM | disk | FTP | other *** search
- version equ 3
- DEBUG equ 0
- ;History:1518,1
-
- ; Copyright 1991 Russell Nelson
-
- ; This program is free software; you can redistribute it and/or modify
- ; it under the terms of the GNU General Public License as published by
- ; the Free Software Foundation, version 1.
- ;
- ; This program is distributed in the hope that it will be useful,
- ; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ; GNU General Public License for more details.
- ;
- ; You should have received a copy of the GNU General Public License
- ; along with this program; if not, write to the Free Software
- ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- include defs.asm
-
- code segment word public
- assume cs:code, ds:code
-
- ;
- ; Waits for SCB command unit to become idle
- ;
- ; MUST NOT TRASH CX OR THE ISSUE_COMMAND PROCEDURE WILL FAIL
-
- deb macro xxx
- if DEBUG
- push bx
- push ds
-
- mov bx,0b800h
- mov ds,bx
- mov bx,word ptr xxx
- add bx,40
- shl bx,1
- shl bx,1
- inc byte ptr ds:[bx]
- pop ds
- pop bx
- endif
- endm
-
-
- cmd_clear macro
- local exit
-
- lea dx, [bp].@SCB_CMD ;BP -> I/O Base
-
- in ax, dx ;Read SCB command
- or ax, ax ;Wait for command accepted
- jz exit
-
- call cmd_wait
- exit:
- endm
-
- ;
- ; Drives channel attention to the 586. We don't care whats in AX, the write
- ; will cause the ASIC to drive CA to the 586.
- ;
- issue_ca MACRO
- lea dx, [bp].@CA_Ctrl
- out dx, al
- endm
-
-
- ;
- ;
- ; Enable and disable barts interrupts.
- ;
- enable_board_ints macro
- lea dx, [bp].@Sel_IRQ
- mov al, encoded_int_no
- or al, 08h
- out dx, al
- endm
-
- disable_board_ints macro
- lea dx, [bp].@Sel_IRQ
- mov al, encoded_int_no
- out dx, al
- endm
-
-
- RxBufferSize equ 1518+14+18 ;Max Rx packet+MAC header+
- ; 18 (alignment)
- TxBufferSize equ 1518+14+20 ;Max Tx packet+MAC header+
- ; 20 (alignment)
-
- ; 82586 Structure definitions
-
- SysConfigPtr struc
- SCP_SystemBus dw ?
- dw 2 dup (?)
- SCP_ISCP_Ptr_low dw ?
- SCP_ISCP_Ptr_high dw ?
- SysConfigPtr ends
-
-
- ;----------------------------------------------------------------
- ; Note: The @ addresses are the I/O address offsets from [bp].
- ;----------------------------------------------------------------
-
- ; The SCP is at location XXX6H. Since the
- ; SMB pointers must have the low order 5 bits
- ; zero, we assume that the SMP pointer will
- ; be set to XXE0H
- @SysConfigPtr struc
- db 8000h dup (?)
- dw ?
- dw ?
- dw ?
- @SCP_SystemBus dw ?
- dw 2 dup (?)
- @SCP_ISCP_Ptr_low dw ?
- @SCP_ISCP_Ptr_high dw ?
- @SysConfigPtr ends
-
-
- ISysConfigPtr struc
- ISCP_Busy dw ?
- ISCP_SCB_Offset dw ?
- ISCP_Ptr_low dw ?
- ISCP_Ptr_high dw ?
- ISysConfigPtr ends
-
-
- ; NOTE: Access to the SCB through the shadow
- ; registers is done by setting the SMB_PTR to
- ; the ISCP base address and then using this
- ; structure. This is because the SCB address
- ; does not start on a 32 byte boundary as
- ; as required for the SMB_PTR.
-
- @ISysConfigPtr struc
- db 4000h dup (?)
- @ISCP_Busy dw ?
- @ISCP_SCB_Offset dw ?
- @ISCP_SCB_Ptr_low dw ?
- @ISCP_SCB_Ptr_high dw ?
- @SCB_Status dw ?
- @SCB_Command dw ?
- @SCB_CommandList dw ?
- @SCB_RecBlockList dw ?
- db 4000h - 16 dup (?)
- @SCB_CRC_Errors dw ?
- @SCB_ALN_Errors dw ?
- @SCB_RSC_Errors dw ?
- @SCB_OVR_Errors dw ?
- @ISysConfigPtr ends
-
-
- SystemControlBlock struc
- SCB_Status dw ?
- SCB_Command dw ?
- SCB_CommandList dw ?
- SCB_RecBlockList dw ?
- SCB_CRC_Errors dw ?
- SCB_ALN_Errors dw ?
- SCB_RSC_Errors dw ?
- SCB_OVR_Errors dw ?
- SystemControlBlock ends
-
- ; NOTE: The SCB shadow register structure is
- ; part of the ISysConfigPtr shadow register
- ; structure.
-
- ReceiveBlock struc
- FD_Status dw ?
- FD_Command dw ?
- FD_Link dw ?
- FD_RBD_Offset dw ?
- RBD_ByteCount dw ?
- RBD_Link dw ?
- RBD_RB_Address_low dw ?
- RBD_RB_Address_high dw ?
- RBD_Size dw ?
- RB_Data db RxBufferSize dup (?)
- ReceiveBlock ends
-
- ReceiveBlock_data struc
- IPX_FD_Status dw ?
- IPX_FD_Command dw ?
- IPX_FD_Link dw ?
- IPX_FD_RBD_Offset dw ?
- IPX_RBD_ByteCount dw ?
- IPX_RBD_Link dw ?
- IPX_RBD_RB_Address_low dw ?
- IPX_RBD_RB_Address_high dw ?
- IPX_RBD_Size dw ?
- IPX_DestAddr_HIGH dw ?
- IPX_DestAddr_MID dw ?
- IPX_DestAddr_LOW dw ?
- IPX_SourceAddr_HIGH dw ?
- IPX_SourceAddr_MID dw ?
- IPX_SourceAddr_LOW dw ?
- IPX_LengthTypeField dw ?
- ReceiveBlock_data ends
-
-
- @ReceiveBlock struc
- db 4000h dup (?)
- @FD_Status dw ?
- @FD_Command dw ?
- @FD_Link dw ?
- @FD_RBD_Offset dw ?
- @RBD_ByteCount dw ?
- @RBD_Link dw ?
- @RBD_RB_Address_low dw ?
- @RBD_RB_Address_high dw ?
- db 4000h - 16 dup (?)
- @RBD_Size dw ?
- ; Ethernet Packet Data
- @DestAddr_HIGH dw ?
- @DestAddr_MID dw ?
- @DestAddr_LOW dw ?
- @SourceAddr_HIGH dw ?
- @SourceAddr_MID dw ?
- @SourceAddr_LOW dw ?
- @LengthTypeField dw ?
- @ReceiveBlock ends
-
- SendBlock struc
- TxCB_Status dw ?
- TxCB_Command dw ?
- TxCB_Link dw ?
- TxCB_TBD_Offset dw ?
- TBD_ByteCount dw ?
- TBD_Link dw ?
- TBD_TB_Address_low dw ?
- TBD_TB_Address_high dw ?
- TB_Data db TxBufferSize dup (?)
- SendBlock ends
-
-
- @SendBlock struc
- db 4000h dup (?)
- @TxCB_Status dw ?
- @TxCB_Command dw ?
- @TxCB_Link dw ?
- @TxCB_TBD_Offset dw ?
- @TBD_ByteCount dw ?
- @TBD_Link dw ?
- @TBD_TB_Address_low dw ?
- @TBD_TB_Address_high dw ?
- db 4000h - 16 dup (?)
- @TB_Data db TxBufferSize dup (?)
- @SendBlock ends
-
-
- CommandBlock struc ;Set command block
- CB_Status dw ? ; Size for largest
- CB_Command dw ? ; command. The Dump
- CB_Link dw ? ; command needs a 170
- CB_Param0 dw ? ; byte area. The 14
- db 170+14 dup (?) ; extra bytes are
- CommandBlock ends ; padding to make the
- ; size of this struc
- ; boundary.
- @CommandBlock struc
- db 4000h dup (?) ;Set command block
- @CB_Status dw ? ; Size for largest
- @CB_Command dw ? ; command. The Dump
- @CB_Link dw ? ; command needs a 170
- @CB_Parm0 dw ? ; byte area. The 14
- db 170+14 dup (?) ; extra bytes are
- @CommandBlock ends ; padding to make the
- ; size of this struc
- ; align on a 16 byte
- SCPS equ SysConfigPtr
- ISCPS equ ISysConfigPtr
- SCBS equ SystemControlBlock
-
- ; System ControlBlock.
-
- Bit_CX equ 8000h
- Bit_FR equ 4000h
- Bit_CNA equ 2000h
- Bit_RNR equ 1000h
-
- ; System Control Block's control unit statuses
-
- CUS_Idle equ 0000h
- CUS_Suspended equ 0100h
- CUS_Active equ 0200h
- CUS_Mask equ 0300h
-
- ; System Control Block's receive unit statuses.
- RUS_Idle equ 0000h
- RUS_Suspend equ 0010h
- RUS_No_Resource equ 0020h
- RUS_Ready equ 0040h
-
- ; System Control Block's control unit commands
- CUC_NOP equ 0000h
- CUC_Start equ 0100h
- CUC_Resume equ 0200h
- CUC_Suspend equ 0300h
- CUC_Abort equ 0400h
-
- ; System Control Block's receive unit commands
- RUC_NOP equ 0000h
- RUC_Start equ 0010h
- RUC_Resume equ 0020h
- RUC_Suspend equ 0030h
- RUC_Abort equ 0040h
-
-
- ; General Action Command Block.
-
- GA_NOP equ 0000h
- GA_IA_Setup equ 0001h
- GA_Configure equ 0002h
- GA_MC_Setup equ 0003h
- GA_Transmit equ 0004h
- GA_TDR equ 0005h
- GA_Dump equ 0006h
- GA_Diagnose equ 0007h
-
- lock_bit_address EQU 01H
- lock_bit_mask EQU 0000000000000001B
- iochrdy_mask EQU 00010000B
- iochrdy_test_mask EQU 00100000B
- iochrdy_test_result EQU 01000000B
- iochrdy_early EQU 00000000B
- iochrdy_late EQU 00010000B
-
-
- ; Common Bits.
-
- Bit_C equ 8000h ; Command complete.
- Bit_B equ 4000h ; Busy executing command.
- Bit_OK equ 2000h ; Error free completion.
- Bit_A equ 1000h ; Command aborted.
-
- Bit_EL equ 8000h ; End of list.
- Bit_EOF equ 8000h ; End of frame.
- byte_Bit_EOF equ 80h ; End of frame.
- Bit_S equ 4000h ; Suspend after completion.
- Bit_I equ 2000h ; Interrupt after completion.
-
- Bit_S11 equ 0800h
- Bit_S10 equ 0400h
- Bit_S9 equ 0200h
- Bit_S8 equ 0100h
- Bit_S7 equ 0080h
- Bit_S6 equ 0040h
- Bit_S5 equ 0020h
-
- ACK_INT_Mask equ 0f000h
- MaxCollisions equ 0020h
- Ready equ 0040h
-
- LNK_OK equ 8000h
- XCVR_PRB equ 4000h
- ET_OPN equ 2000h
- ET_SRT equ 1000h
- TDR_TIME equ 07ffh
-
- ;
- ; equates and definitions:
- ;
- EOI equ 020h ;End-of-interrupt command.
- Master_PIC equ 020h ;1st Interrupt-Control port.
- Slave_PIC equ 0A0h ;2nd Interrupt-Control port.
-
- Bart_Board_ID equ 0BABAH
-
- Number_of_Tx_Buffers equ 1
-
- _586_Reset equ 0080H
- ASIC_Reset equ 0040H
-
- bus_width equ 0 ;16 bit, use for initialize
- initialize_586 equ 1
-
- ;
- ; Timer equates
- ;
- one_mil EQU 02387
- ten_mils EQU 23866
-
-
- ;
- ; EEPROM equATES
- ;
- EE_SK equ 00000001B ;EEPROM shift clock (1 = high, 0 = low)
- EE_CS equ 00000010B ;EEPROM chip select (1 = high, 0 = low)
- EE_DI equ 00000100B ;EEPROM data in (set to 1 for writing data to EEPROM)
- EE_DO equ 00001000B ;EEPROM data out
- EE_tick equ 10
-
- EEPROM_read_opcode equ 110B
- EEPROM_write_opcode equ 101B
- EEPROM_erase_opcode equ 111B
- EEPROM_EWEN_opcode equ 10011B ;Erase/write enable
- EEPROM_EWDS_opcode equ 10000B ;Erase/write disable
-
- TIME_OUT_VALUE equ 0FFFFh
-
- loopback_enable equ 00000010B
-
- _64K_not_32K db 0 ;<>0 if we have 64K of memory.
- _16_not_8_bit_slot db 0 ;<>0 if we're in a 16-bit slot.
- connection_type db ?
-
- ;Memory Sizes
- mem_size_address equ 00H
- _32K equ 00000h
- _64K equ 00001h
-
- connection_address equ 00H
- connection_field equ 0001000000000000B
-
- TPE_address equ 05H
- TPE_type_field equ 0000000000000001B
-
- BNC equ 00000h
- AUI equ 00001h
- TPE equ 00002h
-
- int_num_address equ 00H
- int_num_field equ 1110000000000000B
- int_field_shift equ 13
-
- ee_ethernet_add_low equ 2
- ee_ethernet_add_mid equ 3
- ee_ethernet_add_high equ 4
- ee_int equ 0
- ee_shift equ 13
-
- ; CPU types
- _8088_CPU equ 00000h
- Not_8088_CPU equ NOT _8088_CPU
-
- ; Slot Width
- slot_width_mask equ 04h
- _16_bit_slot equ 0000h
- _8_bit_slot equ 0001h
-
- _16_bit_override_bit equ 08h
-
-
- ;
- ; BART base port structure
- ;
- @BARTBasePorts struc
- @Data_Reg dw ? ;Data Transfer Register.
- @Write_Ptr dw ? ;Write Address Pointer.
- @Read_Ptr dw ? ;Read Address Pointer.
- @CA_Ctrl db ? ;Channel Attention Control.
- @Sel_IRQ db ? ;IRQ Select.
- @SMB_Ptr dw ? ;Shadow Memory Bank Pointer.
- db ?
- @MEM_Ctrl db ?
- @MEM_Page_Ctrl db ?
- @Config db ?
- @EEPROM_Ctrl db ?
- @ID_Port db ?
- @BARTBasePorts ends
-
-
- @ISR_Ports struc
- db 0C008h dup(?)
- @SCB_STAT dw ?
- @SCB_CMD dw ?
- @SCB_CBL dw ?
- @SCB_RFA dw ?
- ; @SCB_CRCERRS dw ?
- ; @SCB_ALNERRS dw ?
- ; @SCB_RSCERRS dw ?
- ; @SCB_OVRNERRS dw ?
- @ISR_Ports ends
-
-
- @memory_page_struc STRUC
- DB 4000H DUP (?)
- @mem_loc_0 DW ?
- @mem_loc_2 DW ?
- @mem_loc_4 DW ?
- @mem_loc_6 DW ?
- @mem_loc_8 DW ?
- @mem_loc_10 DW ?
- @mem_loc_12 DW ?
- @mem_loc_14 DW ?
- DB 4000H - 16 DUP (?)
- @mem_loc_16 DW ?
- @mem_loc_18 DW ?
- @mem_loc_20 DW ?
- @mem_loc_22 DW ?
- @mem_loc_24 DW ?
- @mem_loc_26 DW ?
- @mem_loc_28 DW ?
- @mem_loc_30 DW ?
- @memory_page_struc ENDS
-
- ;
- ;
- ; TData Segment
- ;
- ; This segment template represents the 64-KB segment that the 82586
- ; can address. Shared memory can be either 32K or 64K for the BART.
- ; All structures must be quad-word aligned.
- ;
- ; Offset Type of Block Block Size Cnt
- ; ------ ------------- ---------- ---
- ; 0000h ISCP 8 1
- ; 0008h SCB 16 1
- ; 0020h CommandBlock 104 1
- ; 00E0h SendBlock(s) 1568 variable
- ; ????h ReceiveBlock(s) 1568 variable
- ; FFF6h SCP 10 1
- ;
-
- TData_64 segment at 0
-
- ISCP ISysConfigPtr <>
- SCB SystemControlBlock <>
-
- ORG 20H
-
- CB CommandBlock <>
-
- Send_Blocks DB SIZE SendBlock * Number_of_Tx_Buffers dup (?)
- Receive_Blocks LABEL WORD
-
-
- ORG (0FFFFh - SIZE SCPS + 1) AND 0FFE0H
- SCP LABEL BYTE
-
- ORG 0FFFFh - SIZE SCPS + 1
- THeapTop LABEL BYTE ;Top of available memory
-
- end_of_send_blocks = 20h + SIZE CommandBlock + (Number_of_Tx_Buffers * SIZE SendBlock)
- num_rx_buf_32k = (07FFFh - SIZE SCPS + 1 - end_of_send_blocks) / (SIZE ReceiveBlock)
- num_rx_buf_64k = (0FFFFh - SIZE SCPS + 1 - end_of_send_blocks) / (SIZE ReceiveBlock)
-
- TData_64 ENDS
-
-
- public int_no
- int_no db 3,0,0,0 ;must be four bytes long for get_number.
- io_addr dw 0,0 ; I/O address for card
- encoded_int_no db ? ;encoded for bart.
-
- public driver_class, driver_type, driver_name, driver_function, parameter_list
- driver_class db BLUEBOOK, IEEE8023, 0 ;from the packet spec
- driver_type db 255 ;from the packet spec
- driver_name db 'EtherExpress16',0 ;name of the driver.
- driver_function db 26
- parameter_list label byte
- db 1 ;major rev of packet driver
- db 9 ;minor rev of packet driver
- db 14 ;length of parameter list
- db EADDR_LEN ;length of MAC-layer address
- dw GIANT ;MTU, including MAC headers
- dw MAX_MULTICAST * EADDR_LEN ;buffer size of multicast addrs
- dw 0 ;(# of back-to-back MTU rcvs) - 1
- dw 0 ;(# of successive xmits) - 1
- int_num dw 0 ;Interrupt # to hook for post-EOI
- ;processing, 0 == none,
- save_err db 0 ;error bits on promiscuous recieve
- pro db 0
- pro1 db 0
-
- public rcv_modes
- rcv_modes dw 7 ;number of receive modes in our table.
- dw 0 ;There is no mode zero
- dw 0
- dw rcv_mode_2
- dw rcv_mode_3
- dw rcv_mode_4 ;haven't set up perfect filtering yet.
- dw 0
- dw rcv_mode_6
-
- ;
- ; 82586 Configuration Parameters
- ;
- config_params LABEL WORD
- num_config_params LABEL BYTE ;12 BYTEs
- DB 0CH
-
- fifo_limit LABEL BYTE ;Default is 8
- DB 08H
-
- srdy LABEL BYTE ;srdy = 1
- save_bad_frame LABEL BYTE ;do not save bad frame
- DB 40H
-
- address_length LABEL BYTE ;6 BYTEs
- auto_insert_address LABEL BYTE ;auto insert off (1)
- preamble_length LABEL BYTE ;2 BYTEs
- internal_loopback LABEL BYTE ;0 = OFF 1 = ON
- external_loopback LABEL BYTE ;0 = OFF 1 = ON
- DB 2EH
-
- linear_priority LABEL BYTE ;default is 0
- accel_contention_resolution LABEL BYTE ;default is 0
- exp_backoff_method LABEL BYTE ;0 = 802.3 1 = Alternate
- DB 00H
-
- interframe_spacing LABEL BYTE ;default is 60H (96 bits)
- DB 60H
-
- slot_time_low LABEL BYTE ;0
- DB 00H
-
- slot_time_high LABEL BYTE ;2
- retry_num LABEL BYTE ;15
- DB 0F2H
-
- promiscuous_mode LABEL BYTE ;0 = OFF 1 = ON
- broadcast_disable LABEL BYTE ;0 = OFF 1 = ON
- encode_decode LABEL BYTE ;0 = NRZ 1 = MANCHESTER
- transmit_on_no_carrier LABEL BYTE ;0 = STOP 1 = CONTINUE
- no_crc_insertion LABEL BYTE ;0 = OFF 1 = ON
- crc_type LABEL BYTE ;0 = 32 bit autodin II
- ;1 = 16 bit CCITT
- bit_stuffing LABEL BYTE ;0 = 802.3 1 = HDLC
- padding LABEL BYTE ;0 = OFF 1 = ON
- DB 00H
-
- carrier_sense_filter LABEL BYTE ;0 = OFF 1 = 0N
- carrier_sense_source LABEL BYTE ;0 = external 1 = internal
- collision_detect_filter LABEL BYTE ;default = 0
- collision_detect_source LABEL BYTE ;0 = external 1 = internal
- DB 00H
-
- min_frame_length LABEL BYTE ;60 BYTEs
- DB 60
- DB 00H ;undefined
-
-
- RxBufferCount dw ?
- TxBufferCount dw ?
-
- Receive_Head DW ?
- Receive_Tail DW ?
-
- our_type dw 8 dup(?)
-
- is_186 db 0 ;=0 if 808[68], =1 if 80[123]86.
- rom_address db EADDR_LEN dup(?)
-
- include io16.asm
-
- public as_send_pkt
- ; The Asynchronous Transmit Packet routine.
- ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
- ; interrupts possibly enabled.
- ; Exit with nc if ok, or else cy if error, dh set to error number.
- ; es:di and interrupt enable flag preserved on exit.
- as_send_pkt:
- ret
-
- public drop_pkt
- ; Drop a packet from the queue.
- ; Enter with es:di -> iocb.
- drop_pkt:
- assume ds:nothing
- ret
-
- public xmit
- ; Process a transmit interrupt with the least possible latency to achieve
- ; back-to-back packet transmissions.
- ; May only use ax and dx.
- xmit:
- assume ds:nothing
- ret
-
-
- public send_pkt
- send_pkt:
- ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
- ; (only if the high-performance bit is set in driver_function)
- ;enter with ds:si -> packet, cx = packet length.
- ;if we're a high-performance driver, es:di -> upcall.
- ;exit with nc if ok, or else cy if error, dh set to error number.
- assume ds:nothing
- cmp pro1,1
- je no_size_check1
-
- cmp cx,GIANT ; Is this packet too large?
- jna no_size_check1
- jmp send_pkt_toobig
-
- no_size_check1:
-
- push bp
- mov bp,io_addr
-
- disable_board_ints
- cmd_clear ; wait for command processor to clear
-
- cmp pro1,1 ; on pro drive do not ajust size
- je oklen
-
- cmp cx,RUNT ; minimum length for Ether
- jae oklen
- mov cx,RUNT ; make sure size at least RUNT
- oklen:
- inc cx ;round size up to next even number.
- and cx,not 1
- ;
- ; Set SMB pointer to the transmit buffer.
- ;
- lea dx,[BP].@SMB_Ptr
- mov ax,offset send_blocks
- out dx,ax
- ;
- ; Write evenized, padded packet length (>= RUNT bytes) to 586 TBD byte
- ; count field. OR on the End of Frame bit.
- ;
- lea dx,[BP].@TBD_ByteCount
- mov ax,cx
- or ah,byte_BIT_EOF
- out dx,ax
- ;
- ; Set the TxCB command field for transmit. Also set the EL bit (End of List).
- ;
- lea dx, [BP].@TxCB_Command
- mov ax, BIT_EL+GA_Transmit
- out dx, ax
- ;
- ; Set write pointer to the data buffer for current send block. Also
- ; set DX to the data register.
- ;
- lea dx, [BP].@Write_Ptr
- mov ax, offset send_blocks
- add ax, offset TB_Data
- out dx, ax
- mov dx, bp ;@Data_Reg
-
- call repoutsw
- ;.286
- ; rep outsb
-
- send_continue:
- ;
- ; Set the SCBs command block pointer to this send packet.
- ;
- lea dx, [BP].@SCB_CBL
- mov ax, offset send_blocks
- out dx, ax
-
- ;
- ; Set the SCB command to start the command unit.
- ;
- lea dx, [BP].@SCB_CMD
- mov ax, CUC_START
- out dx, ax
- issue_ca
-
- cmd_clear ; wait for frame transmit to start
- lea dx,[BP].@SMB_Ptr
- mov ax,offset send_blocks
- out dx,ax
-
- lea dx,[BP].@TxCB_status
- transmiting:
- in ax,dx
-
- test ax,BIT_C ; check status of transmit
- jz transmiting
-
- test ax,BIT_OK ; how was the x-mit
- jnz tx_ok
-
- enable_board_ints
- pop bp
- mov dh,255
- jmp tx_bad
-
- tx_ok:
- enable_board_ints
-
- pop bp
-
- clc
- ret
-
- send_pkt_toobig:
- mov dh,NO_SPACE
- tx_bad:
- stc
- ret
-
-
- ; ReadTickCounter
- ;
- ; Read the 16 bit timer tick count register (system board timer 0).
- ; The count register decrements by 2 (even numbers) every 838ns.
- ;
- ; Assumes: Interrupts disabled
- ;
- ; Returns: AX with the current count
- ; Interrupts disabled
-
- ReadTickCounter:
-
- push dx
-
- mov dx, 43h ;Command 8254 timer to latch
- xor al, al ; T0's current count
- out dx, al
-
- mov dx, 40h ;read the latched count
- in al, dx ; LSB first
- mov ah, al
- in al, dx ; MSB next
- xchg al, ah ;put count in proper order
-
- pop dx
- ret
-
-
- public get_address
- get_address:
- ;get the address of the interface.
- ;enter with es:di -> place to get the address, cx = size of address buffer.
- ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
- ; Give caller the one currently in the 8390, not necessarily the one in PROM.
- assume ds:code
- cmp cx, EADDR_LEN ; Caller wants a reasonable length?
- jb get_addr_x ; No, fail.
- mov cx, EADDR_LEN ; Move one ethernet address from our copy
- mov si, offset rom_address ; Copy from most recent setting
- rep movsb
- mov cx, EADDR_LEN ; Tell caller how many bytes we fed him
- clc ; Carry off says success
- ret
- get_addr_x:
- stc ; Tell caller our addr is too big for him
- ret
-
-
- public set_address
- set_address:
- ;enter with ds:si -> Ethernet address, CX = length of address.
- ;exit with nc if okay, or cy, dh=error if any errors.
- assume ds:nothing
- cmp cx,EADDR_LEN ;ensure that their address is okay.
- je set_address_4
- mov dh,BAD_ADDRESS
- stc
- jmp short set_address_done
- set_address_4:
- push bp
- push ds
- push si
-
- push cs
- pop ds
- ;
- ; Set up individual address command block.
- ;
- mov bp,ds:io_addr
- cmd_clear
- mov bx, BIT_EL+GA_IA_Setup
- call setup_command_block
-
- pop si
- pop ds
-
- ;
- ; Copy individual address command parameters to individual address
- ; command block.
- ;
- mov cx, EADDR_LEN/2
- move_node_address:
- lodsw
- out dx, ax
- loop move_node_address
-
- ;
- ; Signal 586 to execute individual address command.
- ;
- mov ax, CUC_Start
- mov bx, BIT_CNA
- call issue_command
-
- lea dx, [bp].@SMB_Ptr ;Move IO frame to the command
- mov ax, offset cb ; command block.
- out dx, ax
-
- lea dx,[BP].@CB_Status
- working1:
- in ax,dx
-
- test ax,BIT_C ; check status of set_ia
- jz working1
-
- test ax,BIT_OK
- jnz set_ok
- pop bp
- stc
- jmp set_address_done
-
- set_ok:
- mov cx,5000h ; on 486's if we do not delay this command does not work
- set1:
- mov bx,cx
- mov ax,[bx]
- loop set1 ; just for delay
-
- mov cx,EADDR_LEN ;return their address length.
- clc
- pop bp
- set_address_done:
- push cs
- pop ds
- assume ds:code
- ret
-
-
- rcv_mode_2:
- and promiscuous_mode,not 3
- or promiscuous_mode,2 ;disable broadcasts.
- mov min_frame_length,60
- and save_bad_frame,not 80h
- mov pro,0
- jmp short configure_command
- rcv_mode_4:
- rcv_mode_3:
- and promiscuous_mode,not 3 ;clear promiscuous mode.
- mov min_frame_length,60
- and save_bad_frame,not 80h
- mov pro,0
- jmp short configure_command
- rcv_mode_6:
- and promiscuous_mode,not 3
- or promiscuous_mode,1 ;set promiscuous mode.
- mov min_frame_length,60 ;allow runt. but let it come in as a bad frame
- or save_bad_frame,80h ; yes we want bad frames here
- mov pro,1
- mov pro1,1
- ;
- configure_command:
- mov bp,io_addr
- ;
- ; Set up configure command block.
- ;
- mov bx, bit_el + GA_Configure ;Set command block for a
- call setup_command_block ; configure command. BIT_EL
- ; means last command.
- ;
- ; Copy configure command parameters to configure command block.
- ;
- mov si,offset config_params ;Set DS:SI to parameters and
- mov cx, 6 ; copy them to the command
-
- move_config_params:
-
- lodsw
- out dx, ax
- loop move_config_params
- ;
- ; Signal 586 to execute configure command.
- ;
- mov ax, CUC_Start
- mov bx, BIT_CNA
- call issue_command
- clc
- ret
-
-
- ;*****************************************************************
- ; TDR cable tester
- ; enter with es:di pointing to time int
- ;*****************************************************************
-
- public do_tdr
- do_tdr:
- push bp
- push es
- push di
- mov bp,io_addr
- ;
- ; Set up configure command block.
- ;
- mov bx, bit_el + GA_TDR ;Set command block for a
- call setup_command_block ; TDR command. BIT_EL
- ; means last command.
- ; Signal 586 to execute configure command.
- ;
- mov ax, CUC_Start
- mov bx, BIT_CNA
- call issue_command
-
- lea dx, [bp].@SMB_Ptr ;Move IO frame to the command
- mov ax, offset cb ; command block.
- out dx, ax
-
- lea dx,[BP].@CB_Status
- working:
- in ax,dx
-
- test ax,BIT_C ; check status of transmit
- jz working
-
- lea dx,[bp].@CB_Parm0
- in ax,dx
-
- pop di
- pop es
- pop bp
-
- test ax,LNK_OK
- jz tdr_bad_cable
- clc
- ret
-
- tdr_bad_cable:
-
- push ax
- and ax,TDR_TIME
- stosw ; store time
- pop ax
-
- mov cl,12
- shr ax,cl
- and ax,7
- mov dh,al
-
- stc
- ret
-
-
- ;
- ; BX = 586 command word
- ;
- setup_command_block:
-
- ;
- ; Setup command block's command, status, and link fields.
- ;
- lea dx, [bp].@SMB_Ptr ;Move IO frame to the command
- mov ax, offset cb ; command block.
- out dx, ax
-
- lea dx, [bp].@CB_link ;Set command block's link to
- out dx, ax ; itself.
-
- lea dx, [bp].@SCB_CBL ;Point SCB command list
- out dx, ax ; pointer to command block.
-
- lea dx, [bp].@CB_command ;Set command block's command
- mov ax, bx ; word to value passed in
- out dx, ax ; BX.
-
- ;
- ; Return with the write pointer set to the command block parameter
- ; offset.
- ;
- lea dx, [bp].@Write_Ptr ;Set write pointer to command
- lea ax, CB.CB_Param0 ; parameter field.
- out dx, ax
-
- mov dx, bp ;@Data_Reg
- ret
-
-
- ;
- ; Wait for 586 command register to be clear ( 1 millisecond max)
- ; Issue command
- ; Wait for command to complete (500 milliseconds max)
- ; Acknowledge command complete
- ;
- ;
- issue_command:
-
- ;
- ; Make sure 586 command in SCB is clear.
- ;
- mov cx, ax
- cmd_clear
- jnz issue_command_error_exit
- mov ax, cx
- ;
- ; Put command code in AX into SCB command register and signal the
- ; 586 to look at it. The cmd_clear macro leaves DX pointing to
- ; the SCB command register.
- ;
- out dx, ax
- issue_ca
-
- wait_for_commad_status_outer_loop:
- ;
- ; Wait here for 586 to complete the command. 586 should never take
- ; more than 500 Milliseconds to complete a command.
- ;
- call readtickcounter
- mov cx, ax
- lea dx, [bp].@SCB_STAT
-
- wait_for_commad_status:
-
- in ax, dx
- cmp ax, bx
- je acknowledge_command_complete
-
- call readtickcounter
- neg ax
- add ax, cx
- cmp ax, ten_mils
- jb wait_for_commad_status
-
- _586_command_error:
- ;
- ; Signal error by pointing AX to error message, and setting
- ; condition codes.
- ;
- MOV AX, OFFSET _586_not_responding_msg
- OR AX, AX
-
- issue_command_error_exit:
-
- RET
-
- acknowledge_command_complete:
- ;
- ; Tell the 586 that we know its done by copying the status back to
- ; the command register's acknowledge fields. BX has status.
- ;
- lea dx, [bp].@SCB_CMD
- out dx, ax
- issue_ca
- ;
- ; Signal no error.
- ;
- xor ax, ax
- ret
-
-
- public set_multicast_list
- set_multicast_list:
- ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
- ;return nc if we set all of them, or cy,dh=error if we didn't.
- mov dh,NO_MULTICAST
- stc
- ret
-
-
- public terminate
- terminate:
- push bp
- mov bp,io_addr
-
- cmd_clear ; wait until last command is done processing
-
- disable_board_ints ; shut off board ints
-
- lea dx,[bp].@SCB_CMD
- mov ax, RUC_SUSPEND ; suspend recieve unit
- out dx, ax
- issue_ca
-
- pop bp ; now ok to un-hook interrupts and release
- ret ; driver
-
- public reset_interface
- reset_interface:
- ;reset the interface.
- assume ds:code
- ret
-
-
- ;called when we want to determine what to do with a received packet.
- ;enter with cx = packet length, es:di -> packet type, dl = packet class.
- extrn recv_find: near
-
- ;called after we have copied the packet into the buffer.
- ;enter with ds:si ->the packet, cx = length of the packet.
- extrn recv_copy: near
-
- extrn count_in_err: near
- extrn count_out_err: near
- ; extrn resource_err_in:word
-
- public recv
- recv:
- ;called from the recv isr. All registers have been saved, and ds=cs.
- ;Upon exit, the interrupt will be acknowledged.
- assume ds:code
- ;
- ; Set BP to the base IO address of bart. Also disable barts ability
- ; to generate interrupts.
- ;
- mov bp,io_addr
- disable_board_ints
- ;
- ; Make sure that command unit is clear before reading the status.
- ;
- cmd_clear
- ;
- ; Get the SCB status to see why bart interrupted us. Also need to
- ; copy the status back to the command word to acknowledge the 586
- ; interrupt. Issue channel attention to get the 586 to realize the
- ; interrupt aknowledge.
- ;
- ; lea dx, [bp].@SCB_RSCERRS
- ; in ax,dx
- ; mov word ptr resource_err_in,ax
- ; lea dx, [bp].@SCB_OVRNERRS
- ; in ax,dx
- ; add word ptr resource_err_in,ax
-
- lea dx, [bp].@SCB_STAT
- in ax, dx
- and ax, ACK_INT_MASK
-
- lea dx, [bp].@SCB_CMD
- out dx, ax
- issue_ca ; AX is not changed.
- ;
- ; Check for frame receive status. Jump if no frames received,
- ; otherwise processes the receive.
- ;
- test AX, BIT_FR OR BIT_RNR
- jz ExitDriverISR
- call ProcessRx
- ExitDriverISR:
- ;
- ; Here if there was a bad receive status. Make sure the receive unit
- ; of the 586 is running. Read in the SCB status and jump if we need
- ; to restart the receive unit. We choose to have the jump to restart
- ; the RU since most of the time we will not need to do this. This
- ; saves cycle times when exiting without a restart.
- ;
- lea dx, [bp].@SCB_STAT
- in ax, dx
- test ax, READY
- jz restart_RU
-
- drvisr_continue:
- enable_board_ints
- ret
-
-
- restart_RU:
- deb 160
- ;
- ; Need to restart the receive unit of the 586. Set the SCB pointer to
- ; the receive frame area.
- ;
- lea dx, [bp].@SCB_RFA
- mov ax, Receive_Head
- out dx, ax
- ;
- ; Make sure 586 is in a state to accept a command.
- ;
- cmd_clear
- ;
- ; Put the receive unit start command into the SCB command word and
- ; issue the channel attention.
- ;
- ; NOTE: cmd_clear macro leaves DX pointing to the SCB command word.
- ;
- ; lea dx, [bp].@SCB_CMD
- mov ax, RUC_START
- out dx, ax
- issue_ca
- jmp drvisr_continue
-
-
- ProcessRx:
-
- ;
- ; Prime the pump that services receives by setting AX to the receive
- ; head. There could be over 30 packets received.
- ;
- deb 1
- mov ax,Receive_Head
-
- CheckNextReceiveStatus:
-
- ;
- ; Save receive head pointer in BX. BX should not be altered during
- ; this loop.
- ;
- mov bx, ax
- ;
- ; Set SMB pointer to the top of the receive frame.
- ;
- lea dx, [bp].@SMB_Ptr
- out dx, ax
- ;
- ; Get the status for this receive frame. Check to make sure that
- ; it completed with no errors. If not, then jump to check the
- ; 586 receive unit.
- ;
- lea dx, [bp].@FD_Status
- in ax, dx
-
- mov save_err,1 ; be sure we done accdently report an error
-
- test ax, BIT_C ; command compleat
- jz PRx_no
- test ax,BIT_OK ; good frame
- jnz ProcessRx_1
-
- call count_in_err
- mov save_err,0
- cmp pro,1
- je PRx_bad ; if not in pro-mode lose bad frames and inc error
- ; call count_in_err
- jmp recv_isr_9
- PRx_no:
- ret
-
- PRx_bad:
- mov dh,0
- test ax,BIT_S7
- jz PR_no_frag
- or dh,2
- PR_no_frag:
- test ax,BIT_S11
- jz PR_no_crc
- or dh,4
- PR_no_crc:
- test ax,BIT_S10
- jz PR_no_align
- or dh,8
- PR_no_align:
- test ax,BIT_S8
- jz PR_no_dma
- or dh,16
- PR_no_dma:
- test ax,BIT_S9
- jz PR_no_ru
- or dh,32
- PR_no_ru:
-
- mov save_err,dh
- jmp ProcessRx_1
-
- ProcessRx_1:
- deb 2
- ;
- ; Set the read pointer to access the LengthTypeField.
- ;
- ; NOTE: BX was set to receive head at the beginning of this
- ; procedure.
- ;
- lea dx, [bp].@Read_Ptr
- lea ax, [BX].IPX_LengthTypeField
- out dx, ax
- mov dx, bp ;@Data_Reg
-
- mov ax,cs
- mov es,ax
- mov di,offset our_type
- mov cx,8
- call repinsw
- ;.286
- ; rep insb
-
- ;
- ; Get the packet size from the 586 data structure.
- ;
- lea dx, [bp].@RBD_ByteCount
- in ax, dx
- and ah, 3fh
- mov cx, ax
-
- mov di,offset our_type
-
- mov dl, BLUEBOOK ;assume bluebook Ethernet.
- mov ax, es:[di]
- xchg ah, al
- cmp ax, 1518
- ja BlueBookPacket
- inc di ;set di to 802.2 header
- inc di
- mov dl, IEEE8023
- BlueBookPacket:
- deb 3
- push bx
- push cx ; for some reison recv_find trashes cx
- mov dh,save_err
- call recv_find
- mov bp,cs:io_addr ; just in case
- pop cx
- pop bx
-
- mov ax,es ;is this pointer null?
- or ax,di
- je recv_isr_9 ;yes - just free the frame.
- push es ;remember where the buffer pointer is.
- push di
- push cx
- deb 4
- ;
- ; Set the read pointer to access the packet.
- ;
- ; NOTE: BX was set to receive head at the beginning of this
- ; procedure.
- ;
- lea dx, [bp].@Read_Ptr
- lea ax, [BX].IPX_DestAddr_HIGH
- out dx, ax
- mov dx, bp ;@Data_Reg
- ;
- ; Now read the packet into es:di
- ;
- call repinsw
- ; rep insb
-
- pop cx
- pop si
- pop ds
- assume ds:nothing
- call recv_copy ;tell them that we copied it.
- mov ax,cs ;restore our ds.
- mov ds,ax
- assume ds:code
-
- mov bp,io_addr ; just in case
- deb 5
- recv_isr_9:
-
- ;
- ; Clear the current receive frames status.
- ;
- lea dx, [bp].@FD_Status
- xor ax, ax
- out dx, ax
- ;
- ; Set the end of list bit for the current receive frame.
- ;
- lea dx, [bp].@FD_command
- mov ax, BIT_EL
- out dx, ax
- ;
- ; Read in the pointer to the next receive frame.
- ;
- lea dx, [bp].@FD_Link
- in ax, dx
- ;
- ; Update our local pointer to the receive resources:
- ;
- ; Receive_tail <-- Receive head
- ; Receive_head <-- next receive frame.
- ;
- mov BX, Receive_Head
- mov Receive_Tail, BX
- mov Receive_Head, AX
- mov cx, ax
- ;
- ; Clear previous receive frame descriptors end of list bit to free up
- ; a receive resource. We do this by moving the write pointer to the
- ; the command word in the previous receive frame and then writing a
- ; zero to it.
- ;
- lea dx, [bp].@Write_Ptr
- lea ax, [bx].FD_command
- out dx, ax
-
- mov dx, bp ;@Data_Reg
- xor ax, ax
- out dx, ax
- ;
- ; Check for another receive frame.
- ;
- mov ax, cx
- jmp CheckNextReceiveStatus
-
-
-
- public recv_exiting
- recv_exiting:
- ;called from the recv isr after interrupts have been acknowledged.
- ;Only ds and ax have been saved.
- assume ds:nothing
- ret
-
- ; This procedure is called from the cmd_clear macro after the macro determines
- ; that we must wait for a command to clear.
- ;
- ; MUST NOT TRASH CX OR THE ISSUE_COMMAND PROCEDURE WILL FAIL.
- ;
- cmd_wait:
- ;enter with dx -> SCB_CMD
- ;exit with nc if it cleared in one millisecond, cy if not.
-
- call readtickcounter ;Reference clock. die after
- mov bx, ax ; 1 ms.
-
- wait_cmd_clear:
-
- in ax, dx ;Read SCB command
- or ax, ax ;Wait for command accepted
- jz exit
-
- call readtickcounter
- neg ax
- add ax, bx
-
- cmp ax, one_mil
- jb wait_cmd_clear
-
- stc
- exit:
- ret
-
-
- ;any code after this will not be kept after initialization.
- end_resident label byte
-
-
- public usage_msg
- usage_msg db "usage: exp16 [-n] [-d] [-w] <packet_int_no> [<io_addr>]",CR,LF,'$'
-
- public copyright_msg
- copyright_msg db "Packet driver for the Intel EtherExpress 16, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
- db "Copyright Intel Corp",CR,LF,'$'
- using_186_msg db "Using 80[123]86 I/O instructions.",CR,LF,'$'
-
- int_no_name db "Interrupt number ",'$'
- io_addr_name db "I/O port ",'$'
-
- extrn set_recv_isr: near
-
- ;enter with si -> argument string, di -> dword to store.
- ;if there is no number, don't change the number.
- extrn get_number: near
-
- ;enter with dx -> argument string, di -> dword to print.
- extrn print_number: near
-
-
- public etopen
- etopen:
- ;initialize the driver.
- assume ds:code
- ;Determine the processor type. The 8088 and 8086 will actually shift ax
- ;over by 33 bits, while the 80[123]86 use a shift count mod 32.
- mov cl,33
- mov ax,0ffffh
- shl ax,cl
- jz not_186
- mov is_186,1
- mov dx,offset using_186_msg
- mov ah,9
- int 21h
- not_186:
-
- ;
- ; Get board information (Node address, etc.). Returns with BP
- ; set to the board IO base address (if not errors).
- ;
- call get_system_info
- jnz driver_init_error_exit
-
- disable_board_ints
- ;
- ; If they're in an 8-bit slot, make sure that they aren't using the slave PIC.
- ;
- cmp _16_not_8_bit_slot,0 ;are they using a 16-bit slot?
- jne check_config_exit ;yes -- cool.
-
- mov dx,offset irq_config_error
- cmp int_no, 9 ;no - don't let them use the upper IRQs.
- jae driver_init_error_exit
- check_config_exit:
-
- ;
- ; Initialize the 586 and the 586 data structures.
- ;
- call init_586
- jnz driver_init_error_exit
-
- ; test iochrdy
- call iochrdy_test
- ;
- ; Set up Interrupt line, start the receive unit, and Enable barts interrupt.
- ;
- call set_recv_isr
- call ru_start
- enable_board_ints
-
- mov al, int_no ; Get board's interrupt vector
- add al, 8
- cmp al, 8+8 ; Is it a slave 8259 interrupt?
- jb set_int_num ; No.
- add al, 70h - 8 - 8 ; Map it to the real interrupt.
- set_int_num:
- xor ah, ah ; Clear high byte
- mov int_num, ax ; Set parameter_list int num.
-
- mov dx,offset end_resident
- clc
- ret
-
- driver_init_error_exit:
- stc
- ret
-
-
- ; int number to IRQ translate table.
- IRQ_xlat_table LABEL BYTE
- DB 00H ;IRQ 0 Invalid IRQ
- DB 00H ;IRQ 1 Invalid IRQ
- DB 01H ;IRQ 2 Valid IRQ
- DB 02H ;IRQ 3 Valid IRQ
- DB 03H ;IRQ 4 Valid IRQ
- DB 04H ;IRQ 5 Valid IRQ
- DB 00H ;IRQ 6 Invalid IRQ
- DB 00H ;IRQ 7 Invalid IRQ
- DB 00H ;IRQ 8 Invalid IRQ
- DB 01H ;IRQ 9 Valid IRQ
- DB 05H ;IRQ 10 Valid IRQ
- DB 06H ;IRQ 11 Valid IRQ
- max_IRQ EQU $-IRQ_xlat_table
-
- io_addresses label word
- dw 300h,310h,320h,330h,340h,350h,360h,370h
- dw 200h,210h,220h,230h,240h,250h,260h,270h
- dw 0
-
- public parse_args
- parse_args:
- ; mov di,offset int_no
- ; call get_number
- mov di,offset io_addr
- call get_number
-
- ; mov al,int_no ;ensure that it's in our table.
- ; cmp al,max_IRQ
- ; ja get_encoded_irq_error_exit
- ;
- ; mov bx,offset irq_xlat_table ;encode it into the number bart wants.
- ; xlat
- ;
- ; or al, al ;if zero, bart doesn't want it.
- ; je get_encoded_irq_error_exit
- ; mov encoded_int_no,al
- ;
- clc
- ret
-
- ;get_encoded_irq_error_exit:
- ; stc
- ; ret
-
- bnc_connector_msg db "Configured for the BNC connector",CR,LF,'$'
- aui_connector_msg db "Configured for the AUI connector",CR,LF,'$'
- tpe_connector_msg db "Configured for the twisted-pair connector",CR,LF,'$'
-
- _8_bit_slot_msg db "The board is in an 8-bit slot",CR,LF,'$'
- _16_bit_slot_msg db "The board is in a 16-bit slot",CR,LF,'$'
-
- badset_msg db "Set Address Command Failed",CR,LF,'$'
-
-
- public print_parameters
- print_parameters:
- mov di,offset int_no
- mov dx,offset int_no_name
- call print_number
- mov di,offset io_addr
- mov dx,offset io_addr_name
- call print_number
-
- mov dx,offset bnc_connector_msg ;print the connection type.
- cmp connection_type,BNC
- je print_parameters_1
- mov dx,offset aui_connector_msg
- cmp connection_type,AUI
- je print_parameters_1
- mov dx,offset tpe_connector_msg
- print_parameters_1:
- mov ah,9
- int 21h
-
- mov dx,offset _16_bit_slot_msg ;print the slot size.
- cmp _16_not_8_bit_slot,0
- jne print_parameters_2
- mov dx,offset _8_bit_slot_msg
- print_parameters_2:
- mov ah,9
- int 21h
-
- ret
-
-
- init_586:
- ;enter with bp=io_addr, 586 reset.
-
- ;
- ; Set the number of transmit and receive buffers according to the
- ; amount of RAM on the adapter.
- ;
- MOV AX, Number_of_Tx_Buffers
- MOV BX, num_rx_buf_32k
-
- cmp _64K_not_32K,0
- je save_number_of_buffers
-
- MOV BX, num_rx_buf_64k
-
- save_number_of_buffers:
-
- MOV TxBufferCount, AX
- MOV RxBufferCount, BX
- ;
- ; initialize SCP. Move IO frame to top of SCP.
- ;
- LEA DX, [bp].@SMB_Ptr
- MOV AX, OFFSET scp
- OUT DX, AX
- ;
- ; Write initial SCP values:
- ; bus width 0 = 16 bit 1 = 8 bit.
- ; ISCP address always found at address 000000.
- ;
- LEA DX, [BP].@SCP_SystemBus
- MOV AL, bus_width
- OUT DX, AX
-
- LEA DX, [BP].@SCP_ISCP_Ptr_low
- XOR AX, AX
- OUT DX, AX
- LEA DX, [BP].@SCP_ISCP_Ptr_high
- OUT DX, AX
-
- ;
- ; Initialize ISCP. Move IO frame to top of ISCP. NOTE: AX falls
- ; through as zero.
- ;
- LEA DX, [bp].@SMB_Ptr
- OUT DX, AX
- ;
- ; Write initial ISCP values:
- ; ISCP BUSY 1 = Indicates 586 is in initialization
- ; process. 586 sets this byte to 0 when
- ; initialization is complete.
- ;
- ; SCB address Always 000008
- ;
- LEA DX, [BP].@iscp_busy
- MOV AX, initialize_586
- OUT DX, AX
-
- LEA DX, [BP].@ISCP_SCB_Ptr_low
- XOR AX, AX
- OUT DX, AX
- LEA DX, [BP].@ISCP_SCB_Ptr_high
- OUT DX, AX
- LEA DX, [BP].@iscp_scb_offset
- MOV AX, OFFSET scb
- OUT DX, AX
-
- ;
- ; Initialize SCB. Move Write Ptr to top of SCB. NOTE: AX falls
- ; through as offset to SCB.
- ;
- XOR AX, AX
- LEA DX, [BP].@SCB_Status
- OUT DX, AX
- LEA DX, [BP].@SCB_Command
- OUT DX, AX
- LEA DX, [BP].@SCB_CommandList
- OUT DX, AX
- LEA DX, [BP].@SCB_RecBlockList
- OUT DX, AX
- LEA DX, [BP].@SCB_CRC_Errors
- OUT DX, AX
- LEA DX, [BP].@SCB_ALN_Errors
- OUT DX, AX
- LEA DX, [BP].@SCB_RSC_Errors
- OUT DX, AX
- LEA DX, [BP].@SCB_OVR_Errors
- OUT DX, AX
-
- ;
- ; Initialize Receive Block(s). First set head pointer and link from
- ; SCB to first frame descriptor. NOTE: IO frame points to ISCB.
- ; The SCB link field can be addresses becasue the SCB is physically
- ; contiguous to the ISCB.
- ;
- mov ax,offset Receive_Blocks
- lea dx, [bp].@SCB_RecBlockList ;IO address of SCB RF link
- out dx, ax
-
- ;
- ; Initialize the frame descriptor structures. Move the Write ptr
- ; the top of the current frame descriptor. AX falls through with the
- ; offset to the first frame descriptor. DI is used to keep track of
- ; the address of the current frame descriptor. The frame descriptor,
- ; receive buffer descriptor, and receive buffer are all contiguous in
- ; memory, and make up the frame descriptor structure.
- ;
- MOV DI, AX ;DI is current frame descriptor
- MOV RECEIVE_HEAD, DI
- MOV CX, RxBufferCount ;CX is number of frame
- ; descriptors to initialize.
- init_receive_frames:
-
- LEA DX, [bp].@SMB_Ptr
- MOV AX, DI ; descriptor.
- OUT DX, AX
-
- ;
- ; Init Frame Descriptor (FD).
- ;
- XOR AX, AX ;Init frame descriptor status
- LEA DX, [BP+4000H]
- OUT DX, AX ; and command to zero.
- LEA DX, [BP+4002H]
- OUT DX, AX
-
- MOV AX, RECEIVE_HEAD ;Init frame descriptors link
- CMP CX, 1 ; to next frame descriptor.
- JE next_receive_link ; If this is the last receive
- ; block, then set its link to
- LEA AX, [DI+SIZE ReceiveBlock] ; the first receive block.
-
- next_receive_link:
-
- LEA DX, [BP+4004H]
- OUT DX, AX
-
- LEA AX, [DI+OFFSET RBD_ByteCount] ;Init frame descriptors
- LEA DX, [BP+4006H]
- OUT DX, AX ; link to its receive buffer descriptor.
- ;
- ; Init Receive Buffer Descriptor (RBD).
- ;
- LEA DX, [BP+4008H]
- OUT DX, AX ;Init the RBD Actual count to zero.
-
- MOV AX, -1 ;Init the RBD link to next RBD
- LEA DX, [BP+400AH]
- OUT DX, AX ; to minus 1 (unused link).
-
- LEA AX, [DI+RB_Data] ;Init the RDB link to the data
- LEA DX, [BP+400CH]
- OUT DX, AX ; buffer.
- XOR AX, AX
- LEA DX, [BP+400EH]
- OUT DX, AX
-
- MOV AX, RxBufferSize OR BIT_EL ;Init the RBD count and status
- LEA DX, [BP+8000H]
- OUT DX, AX
-
- MOV RECEIVE_TAIL, DI ;Set receive tail pointer.
- ADD DI, SIZE ReceiveBlock ;Point DI to next frame
- LOOP init_receive_frames ; descriptor.
- ;
- ; Initialize the send block structures. Move the Write pointer the
- ; top of the current send block. AX falls through with address of
- ; first send block. DI is used to keep track of the address of the
- ; current send block. The Transmit command block, transmit buffer
- ; descriptor, and transmit buffer are all contiguous in memory, and
- ; make up the send block structure.
- ;
- MOV DI, OFFSET send_blocks
- MOV CX, TxBufferCount
-
- LEA DX, [BP].@SMB_Ptr
- XOR AX, AX
- OUT DX, AX
-
- MOV AX, DI
- LEA DX, [BP].@SCB_CommandList
- OUT DX, AX
-
- init_send_blocks:
-
- LEA DX, [BP].@SMB_Ptr ;Set write pointer to send
- MOV AX, DI ; block.
- OUT DX, AX
- ;
- ; Init Transmit Control Block (TCB).
- ;
- XOR AX, AX ;Init transmit control block
- LEA DX, [BP+4000H]
- OUT DX, AX ; status to zero.
-
- LEA DX, [BP+4002H]
- OUT DX, AX ;Init transmit control block
- ; command to anything. The
- MOV AX, offset send_blocks ; Init transmit control block
- CMP CX, 1 ; link to next send block.
- JE next_send_link ; If this is the last send
- ; block, then point it to
- LEA AX, [DI+SIZE SendBlock] ; the first block.
-
- next_send_link:
-
- LEA DX, [BP+4004H]
- OUT DX, AX
-
- LEA AX, [DI+OFFSET TBD_ByteCount] ;Init transmit control block
- LEA DX, [BP+4006H]
- OUT DX, AX ; link to Transmit Buffer
- ; descriptor.
- ;
- ; Init Transmit Buffer Descriptor (TBD).
- ;
- LEA DX, [BP+4008H]
- OUT DX, AX ;Init Transmit Buffer Descriptor
- ; byte count to anything
- MOV AX, -1 ;Init Transmit Buffer Descriptor
- LEA DX, [BP+400AH]
- OUT DX, AX ; link to next TBD.
-
- LEA AX, [DI+OFFSET TB_Data] ;Init Transmit Buffer Descriptor
- LEA DX, [BP+400CH]
- OUT DX, AX ; link to transmit
- XOR AX, AX ; buffer. Low part of pointer
- LEA DX, [BP+400EH]
- OUT DX, AX ; is done first.
-
- ADD DI, SIZE SendBlock ;Point DI to next send block
- LOOP init_send_blocks ; and loop to initialize it.
-
- ;
- ; Enable loopback to insure nothing acidently hits the cable while
- ; the 586 gets initialized.
- ;
- LEA DX, [BP].@Config
- IN AX, DX
- OR AL, loopback_enable
- OUT DX, AL
- ;
- ; Free the 586 from reset.
- ;
- CALL free_586_reset
- ;
- ; Initialize and configure the 586. Carry flag set means error and
- ; AX will point to error message.
- ;
- CALL init_cmd
- JNZ init_bart_ram_exit
-
- CALL configure_command
- JNZ init_bart_ram_exit
-
- CALL diagnose_command
- JNZ init_bart_ram_exit
-
- push cs
- pop es
- mov si,offset rom_address
- mov cx,EADDR_LEN
- call set_address
- jnc sa_ok
-
- mov dx,offset badset_msg
- mov ah,0
- int 21h
- sa_ok:
- ;
- ; Disable loopback.
- ;
- LEA DX, [BP].@Config
- IN AX, DX
- AND AL, NOT loopback_enable
- OUT DX, AL
-
- XOR AX, AX
-
- init_bart_ram_exit:
-
- OR AX, AX
- RET
-
-
- ; This procedure must wait until the ASIC finishes reset. This will take
- ; around 240 uSec. This loop will time out after 500 uSec.
- ;
- five_hundred_micros EQU 1194
- ;
- reset_board:
- ;enter with bp=io_addr
-
- LEA DX, [BP].@EEPROM_Ctrl
- MOV AL, ASIC_Reset
- OUT DX, AL
-
- XOR AL, AL
- OUT DX, AL
-
- ;
- ; Get current tick count. This loop will wait for 500 uSec to pass
- ; before failing.
- ;
- CALL ReadTickCounter
- MOV BX, AX
-
- reset_delay:
-
- PUSH BX
- CALL check_for_bart_hardware
- POP BX
-
- CMP AX, bart_board_id
- JE reset_board_exit
-
- CALL ReadTickCounter
- NEG AX
- ADD AX, BX
- CMP AX, five_hundred_micros
- JB reset_delay
-
- MOV AX, OFFSET reset_error
- stc
- RET
-
- reset_board_exit:
-
- MOV BX, AX
- clc
- RET
-
-
- reset_586:
- ;enter with bp = io_addr
- lea dx, [bp].@EEPROM_Ctrl
- mov al, _586_Reset
- out dx, al
- ret
-
-
- free_586_reset:
- ;enter with bp = io_addr
- lea dx, [bp].@EEPROM_Ctrl
- xor al, al
- out dx, al
- ret
-
- check_for_bart_hardware:
- ;
- ; Set DX to the auto-id port.
- ;
- LEA DX, [BP].@ID_Port
- ;
- ; BX will have board ID when the loop is done. CX is the loop count.
- ;
- XOR BX, BX
- MOV CX, 4
-
- get_board_id_loop:
- ;
- ; Init registers for loop. CX needs to be used in the loop, and AH
- ; could be set from the last loop.
- ;
- PUSH CX
- XOR AH, AH
- ;
- ; Read ID port. See description above.
- ;
- IN AL, DX
- ;
- ; Make nibble ID a shift count in CL.
- ;
- MOV CL, AL
- AND CL, 00000011B
- SHL CL, 1
- SHL CL, 1
- ;
- ; Move ID nibble to low order bits of AX, then shift then into place. Put
- ; the board ID nibble into BX. After four passes, BX will have board ID.
- ;
- SHR AL, 1
- SHR AL, 1
- SHR AL, 1
- SHR AL, 1
- SHL AX, CL
- OR BX, AX
- ;
- ; Recover loop count, and loop.
- ;
- POP CX
- LOOP get_board_id_loop
- ;
- ; Return board ID in AX.
- ;
- MOV AX, BX
- RET
-
-
- ;
- ; Command #1: Initialize
- ;
- init_cmd:
- XOR AX, AX ; Init command
- MOV BX, BIT_CX + BIT_CNA ; status
- CALL issue_command
- RET
-
- diagnose_command:
- ;
- ; Set up individual address command block.
- ;
- MOV BX, BIT_EL+GA_diagnose
- CALL setup_command_block
- ;
- ; Execute the diagnose command.
- ;
- MOV AX, CUC_Start
- MOV BX, BIT_CNA
- CALL issue_command
- ;
- ; Check diagnostics results.
- ;
- LEA DX, [BP].@SMB_Ptr ;Move IO frame to the command
- MOV AX, OFFSET cb ; command block.
- OUT DX, AX
-
- LEA DX, [BP].@mem_loc_0 ;Read in the diagnose status
- IN AX, DX ; word.
- ;
- ; Assume 586 failed the test. Set AX to an error message and exit
- ; with the zero bit cleared.
- ;
- MOV BX, AX
- MOV AX, OFFSET _586_diagnostic_failure
-
- TEST BX, 0800H ;Test failure bit. If set,
- JNZ diagnose_exit ; then error exit.
-
- XOR AX, AX ;Set AX and zero bit to
- ; indicate no error.
- diagnose_exit:
-
- RET
-
-
- ;
- ; Command #4: RU_START
- ;
- ru_start:
- ;
- ; Set SCBs pointer to receive blocks at head of list.
- ;
- lea dx, [bp].@SCB_RFA ;Set pointer to receive blocks
- mov ax, receive_head ; to the head of the receive
- out dx, ax ; block list.
- ;
- ; Signal 586 to start the receive unit. cmd_clear leaves DX pointing
- ; to SCB command register.
- ;
- cmd_clear
- mov ax, ruc_start
- out dx, ax
- issue_CA
- ret
-
-
- find_a_board:
- mov bx,offset io_addresses
- no_bart_here:
- mov bp,[bx]
- cmp bp,0
- je no_barts
- inc bx
- inc bx
- push bx
- call reset_board
- pop bx
- jc no_bart_here
-
- clc
- ret
-
- no_barts:
- stc
- ret
-
- get_system_info:
- cmp io_addr,0
- jne addr_override
- call find_a_board
- jnc board_id_ok
- jmp bad_or_no_board
-
- addr_override:
-
- MOV bp, io_addr
-
- ;
- ; Next, get the bart board ID. If the ID is not what we expect, then
- ; exit with error code in AX.
- ;
- call reset_board
- jnc board_id_ok
- ;
- ; Could search for bart board, but we error exit instead.
- ;
- bad_or_no_board:
-
- MOV AX, OFFSET board_not_installed
- JMP SHORT get_system_info_exit
-
- board_id_ok:
- mov io_addr,bp
-
- ;
- ; Since the software will be reading the EEPROM during the
- ; initialization, the 586 needs to be inactive. This is because the
- ; control lines to the EEPROM are shared between the 586 and this
- ; software. To keep from getting fouled up, the 586 reset line is
- ; asserted here (now that we have a base IO address, and we know that
- ; the hardware is present). The 586 is not released from reset until
- ; after its data structures are intialized.
- ;
- CALL reset_586
- ;
- ; Validate the EEPROM by doing a checksum.
- ;
- CALL check_eeprom
- JC get_system_info_exit
- ;
- ; Get the amount of memory on the adapter. If carry clear, then AX
- ; has memory size. Else AX has error code.
- ;
- CALL test_buffer_memory
- JC get_system_info_exit
-
- MOV _64K_not_32K,al
- ;
- ; Get the connection type. If carry clear, then AL has connection
- ; type. Otherwise AX has error code.
- ;
- CALL get_connection_type
- JC get_system_info_exit
-
- MOV connection_type, AL
- ;
- ; Read the Ethernet address out of the EEPROM.
- ;
- MOV AX, ee_ethernet_add_high
- CALL read_eeprom
- xchg ah,al
- MOV word ptr rom_address[0], AX
-
- MOV AX, ee_ethernet_add_mid
- CALL read_eeprom
- xchg ah,al
- MOV word ptr rom_address[2], AX
-
- MOV AX, ee_ethernet_add_low
- CALL read_eeprom
- xchg ah,al
- MOV word ptr rom_address[4], AX
-
- mov ax,ee_int
- call read_eeprom
- mov cl,ee_shift
- shr ax,cl
- mov encoded_int_no,al
- mov bx,offset irq_xlat_table
- mov cl,0
- kg:
- cmp [bx],al
- je found_it
- inc bx
- inc cl
- jmp kg
- found_it:
- mov int_no,cl
-
- ;
- ; Get the Slot width. If carry clear, then AL has the slot width.
- ; Otherwise AX has error code.
- ;
- LEA DX, [BP].@Config
- IN AL, DX
- ;
- ; Slot width is found in the adapters configuration register.
- ;
- and al, slot_width_mask
- mov _16_not_8_bit_slot, al
-
- xor ax, AX
-
- get_system_info_exit:
-
- OR AX, AX
- RET
-
- ;
- ;
- ; Return connection type in AL with carry clear. Otherwise return AX with
- ; unable_to_read_eeprom error code and carry set.
- ;
- ;
- get_connection_type:
-
- ;
- ; Read the connection address from the EEPROM.
- ;
- MOV AX, connection_address
- CALL read_eeprom ;Read_eeprom does not trash DI
-
- ;
- ; Assume AUI type connection. Check connection fields to see if this
- ; is a BNC connection. Jump if it is BNC.
- ;
- MOV BL, aui
- TEST AX, connection_field
- JZ get_connection_type_ret
-
- ;
- ; Here if NOT BNC. Must read another EEPROM word to tell if AUI or
- ; TPE. Assume AUI and then check for TPE.
- ;
- MOV AX, tpe_address
- CALL read_eeprom ;Read_eeprom does not trash DI
-
- ;
- ; Check for AUI connection.
- ;
- mov bl,bnc
- TEST AX, TPE_type_field
- JZ get_connection_type_ret
-
- ;
- ; Here if TPE type connection.
- ;
- MOV BL, TPE
-
- get_connection_type_ret:
-
- MOV AL, BL
-
- CLC
- RET
-
-
- ;
- ;
- ; Do a checksum on the EEPROM. Retrun carry set and AX pointing to an error
- ; message if checksum is bad. Otherwise return carry clear.
- ;
- ; The checksum is the same as the board ID.
- ;
- check_eeprom:
-
- mov cx, 40h
- xor bx, bx
-
- checksum_loop:
-
- mov ax, cx
- dec ax
- call read_eeprom
-
- add bx, ax
- loop checksum_loop
-
- cmp bx, bart_board_id
- jne checksum_error
-
- clc
- ret
-
- checksum_error:
-
- mov ax, offset eeprom_checksum_error
- stc
- ret
-
-
- test_buffer_memory:
- ;enter with bp=io_addr
- ;exit with nc if no error, or cy and di -> address in error.
-
- ; Set up SI with the maximum number of words to test. If there is an
- ; error testing the high 32K of memory, then we will restart the
- ; test at 32K. When the tests pass, the memory size is passed back
- ; in AX.
- ;
- mov si, 64 * (1024/2)
- ;
- ; Warm up the buffer memory with 16 word writes.
- ;
- mov cx, 16
- call write_zeros
-
- cmp cs:is_186,0
- je restart_memory_tests
-
- jmp short start_memory_tests
-
- restart_memory_tests:
- ;
- ; Here if error testing memory and SI is set to 64K buffer size.
- ; We restart the tests for 32K buffer only. If an error occurs
- ; with SI set to 32K, then a memory error is reported.
- ;
- mov si, 32 * (1024/2)
-
- start_memory_tests:
- ;
- ; Zero RAM. Set write pointer to the base address and then fill the
- ; bufffer memory with zeros.
- ;
- mov cx, si
- call write_zeros
-
- call word_memory_test_pattern
- jc buffer_mem_error_exit
-
- cmp cs:is_186,0
- je _8088_quick_exit
-
- mov cx, si
- call write_zeros
-
- call byte_memory_test_pattern
- jc buffer_mem_error_exit
-
- _8088_quick_exit:
- ;
- ; Zero RAM. Set write pointer to the base address and then fill the
- ; bufffer memory with zeros.
- ;
- mov cx, si
- call write_zeros
-
- ;
- ; Set _64K_not_32K to the size of the memory that passed diagnostics.
- ;
- cmp si, 32 * (1024/2) ;did we quit at 32K
- je buffer_mem_exit ;yes, we only have 32K.
-
- mov _64K_not_32K,1 ;no, we must have 64K.
-
- buffer_mem_exit:
- clc
- ret
-
- buffer_mem_error_exit:
- ;
- ; If error occured, and SI is not set for 32K, then retry tests with
- ; SI set for 32K. If the error occurs and the size is 32K, then the
- ; Bart board memory is bad.
- ;
- CMP SI, 32 * (1024/2)
- JNE restart_memory_tests
-
- MOV AX, OFFSET buffer_memory_error
- STC ;Set carry to indicate error.
- RET
-
-
- write_zeros:
- ;enter with bp=io_addr, cx=number of zero words to write.
- ;
- ; Move write pointer to the beginning of the buffer memory.
- ;
- LEA DX, [BP].@Write_Ptr
- XOR AX, AX
- OUT DX, AX
- ;
- ; Set DX to the data register and write out zeros CX times.
- ;
- mov dx, bp ;@Data_Reg
- warm_up:
- out dx, ax
- loop warm_up
- ret
-
-
- word_memory_test_pattern:
- ;enter with si = number of words to test.
-
- ;
- ; Set CX to number of words to test. Set BX to beginning og pattern.
- ;
- MOV CX, SI
- MOV BX, 1
-
- ;
- ; Set DI to beginning of the buffer.
- ;
- XOR DI, DI
-
- word_inc_pattern:
-
- CALL loop_set_up
- IN AX, DX
- OR AX, AX
- JNE word_memory_test_pattern_error
-
- ;
- ; Write Test Pattern.
- ;
- MOV AX, BX
- OUT DX, AX
-
- ;
- ; Increment BX to next test pattern value.
- ;
- ADD BX, 3
-
- ;
- ; Increment DI to next test memory location.
- ;
- ADD DI, 2
- LOOP word_inc_pattern
-
- ;
- ; Set Read pointer to beginning of buffer.
- ;
- LEA DX, [BP].@read_ptr
- XOR AX, AX
- OUT DX, AX
- MOV DX, BP ;@Data_Reg
-
- ;
- ; Set CX to number of words to test. Set BX to beginning og pattern.
- ;
- MOV CX, SI
- MOV BX, 1
-
- word_check_pattern:
-
- IN AX, DX
- CMP AX, BX
- JNE word_memory_test_pattern_error
-
- ;
- ; Increment BX to next test pattern value.
- ;
- ADD BX, 3
-
- LOOP word_check_pattern
-
- CLC
- RET
-
- word_memory_test_pattern_error:
-
- STC
- RET
-
-
- byte_memory_test_pattern:
- ;enter with si = number of bytes to test.
-
- ;
- ; Set CX to number of bytes to test. Set BX to beginning of pattern.
- ;
- MOV CX, SI
- SHL CX, 1
- MOV BL, 1
-
- ;
- ; Set DI to beginning of the buffer.
- ;
- XOR DI, DI
-
- byte_inc_pattern:
-
- CALL loop_set_up
- IN AL, DX
- OR AL, AL
- JNE byte_memory_test_pattern_error
-
- ;
- ; Write Test Pattern.
- ;
- MOV AL, BL
- OUT DX, AL
-
- ;
- ; Increment BX to next test pattern value.
- ;
- ADD BL, 3
-
- ;
- ; Increment DI to next test memory location.
- ;
- INC DI
-
- LOOP byte_inc_pattern
-
- ;
- ; Set Read pointer to beginning of buffer.
- ;
- LEA DX, [BP].@read_ptr
- XOR AX, AX
- OUT DX, AX
- MOV DX, BP ;@Data_Reg
-
- ;
- ; Set CX to number of bytes to test. Set BX to beginning of pattern.
- ;
- MOV CX, SI
- SHL CX, 1
- MOV BL, 1
-
- byte_check_pattern:
-
- IN AL, DX
- CMP AL, BL
- JNE byte_memory_test_pattern_error
-
- ;
- ; Increment BX to next test pattern value.
- ;
- add bl, 3
-
- loop byte_check_pattern
-
- clc
- ret
-
- byte_memory_test_pattern_error:
-
- stc
- ret
-
- loop_set_up:
- ;enter with bp=io_addr, di=buffer address.
- ;exit with ax=value at di, dx=I/O address to access buffer memory at DI
-
- PUSH DI
-
- MOV AX, DI ;SMB_Ptr must be on 16 byte
- AND AX, 0FFE0H
- AND DI, 0001FH
-
- LEA DX, [BP].@SMB_Ptr ;Set IO page frame to the
- OUT DX, AX
-
-
- TEST DI, 0010H
- JZ loop_set_up_1
-
- ADD DI, @MEM_LOC_0
-
- loop_set_up_1:
- AND DI, 0FFEFH
- LEA DX, [BP+DI].@MEM_LOC_0 ;Set DX for IO from buffer and
-
- POP DI
-
- RET
-
-
- read_eeprom:
- ;enter with bp=io_addr, ax = EEPROM location.
- ;exit with ax = EEPROM contents.
- ;preserves di.
- push di
- push bx
- push cx
-
- ; Point to EEPROM control port.
-
- lea dx, [bp].@eeprom_ctrl
- mov bx, ax
-
- ; Select the EEPROM. Mask off the ASIC and 586 reset bits and set
- ; the ee_cs bit in the EEPROM control register.
-
- in al, dx
- and al, 10110010b
- or al, ee_cs
- out dx, al
-
- ; Write out read opcode and EEPROM location.
-
- mov ax, eeprom_read_opcode ;Set AX to READ opcode and
- mov cx, 3 ;Send it to the EEPROM circuit
- call shift_bits_out
-
- mov ax, bx ;Tell EEPROM which register is
- mov cx, 6 ; to be read. 6 bit address.
- call shift_bits_out
-
- call shift_bits_in ;AX gets EEPROM register
-
- call eeprom_clean_up ;Leave EEPROM in known state.
-
- pop cx
- pop bx
- pop di
- ret
-
-
- shift_bits_out:
- ;enter with ax=data to be shifted, cx=# of bits to be shifted.
-
- push bx
-
- ; Data bits are right justified in the AX register. Move the data
- ; into BX and left justify it. This will cause addresses to to
- ; be sent to the EEPROM high order bit first.
-
- mov bx, ax
- mov ch, 16
- sub ch, cl
- xchg cl, ch
- shl bx, cl
- xchg cl, ch
- xor ch, ch
-
- ; Get the EEPROM control register into AL. Mask of the ASIC asn 586
- ; reset bits.
-
- in al, dx
- and al, 10111111b
-
- ; Set or clear DI bit in EEPROM control register based on value of
- ; data in BX.
-
- out_shift_loop:
- and al, not ee_di ;Assume data bit will be zero
-
- rcl bx, 1 ;Is the data bit a one?
- jnc out_with_it ;No
- or al, ee_di ;Yes
- out_with_it:
- out dx, al ;Output a 0 or 1 on data pin
-
- ; Set up time for data is .4 Microseconds. So to be safe (incase of
- ; this software is run on a cray), call delay.
- mov di, 1
- call eeprom_delay
-
- call raise_eeprom_clock ; Clock the data into the EEPROM.
- call lower_eeprom_clock
- loop out_shift_loop ;Send next bit
-
- and al, not ee_di ;Force data bit to zero
- out dx, al ;Output a 0 on data pin
-
- pop bx
-
- ret
-
- shift_bits_in:
- ;exit with ax = register contents.
- push bx
- push cx
-
- ; BX will receive the 16 bits read from the EEPROM. Data is valid in
- ; data out bit (DO) when clock is high. There for, this procedure
- ; raises clock and waits a minimum amount of time. DO is read, and
- ; clock is lowered.
-
- in al, dx ;Init AL to eeprom control
- and al, 10111111b ; register.
-
- xor bx, bx ;Init holding register
- mov cx, 16 ;We'll shift in 16 bits
-
- in_shift_loop:
- shl bx, 1 ;Adjust holding register for
- ; next bit
- call raise_eeprom_clock
-
- in al, dx
- and al, 10111111b
-
- test al, ee_do ;Was the data bit a one?
- jz in_eeprom_delay ;No
-
- or bx, 1 ;Yes, reflect data bit state
- ; in holding register.
-
- in_eeprom_delay:
- call lower_eeprom_clock
- loop in_shift_loop ;CONTINUE
-
- mov ax, bx ;AX = data
-
- pop cx
- pop bx
- ret
-
- raise_eeprom_clock:
- or al, ee_sk ;Clock the bit out by raising
- jmp short eeprom_clock_common
- lower_eeprom_clock:
- and al, not ee_sk ;Lower ee_sk
- eeprom_clock_common:
- out dx, al
- mov di, ee_tick
- call eeprom_delay ;Waste time
- ret
-
-
- ; Lower EEPROM chip select and DI.
- ; Clock EEPROM twice and leave clock low.
-
- eeprom_clean_up:
-
- push ax
-
- in al, dx
- and al, 10111111b
- and al, not (ee_cs or ee_di)
- out dx, al
-
- call raise_eeprom_clock
- call lower_eeprom_clock
-
- pop ax
- ret
-
- ; DI has number of 838 Nanoseconds clock counts
- eeprom_delay:
-
- push ax
- push bx
- push dx
-
- call readtickcounter
- mov bx, ax
-
- eeprom_delay_loop:
-
- call readtickcounter
- neg ax
- add ax, bx
- cmp ax, di
- jb eeprom_delay_loop
-
- pop dx
- pop bx
- pop ax
- ret
-
- iochrdy_test:
- ; First test to see if the driver is supposed to run this test.
- MOV AX, lock_bit_address
- CALL read_eeprom
-
- TEST AX, lock_bit_mask
- JNZ iochrdy_test_exit
- ; Get the configuration register.
-
- LEA DX, [BP].@config
- IN AL, DX
-
- ; Set the iochrdy test bit with and set iochrdy to late.
- OR AL, iochrdy_test_mask+iochrdy_late
- CLI
- OUT DX, AL
-
- ; Test IOCHRDY with IO.
- LEA DX, [BP].@mem_loc_0
- IN AX, DX
-
- ; Read in the results of the test. Save results in BL.
- LEA DX, [BP].@config
- IN AL, DX
- MOV BL, AL
-
- ; Turn iochrdy test off.
- AND AL, NOT iochrdy_test_mask
- OUT DX, AL
- STI
-
- ; Test results. Exit if IOCHRDY_LATE bit is set correctly.
- TEST BL, iochrdy_test_result
- JZ iochrdy_test_exit
-
- ; Here if test failed. Clear the 16 bit override bit (force 8 bit
- ; transfers) and print a warning message.
- AND AL, NOT _16_bit_override_bit
- OUT DX, AL
-
- mov dx, offset iochrdy_problem
- mov ah,9
- int 21h
-
-
- iochrdy_test_exit:
-
- RET
-
-
-
- iochrdy_problem DB 10,13,"IOCHRDY Problem. Bart forced into 8 Bit Mode.$"
- buffer_memory_error DB 10,13,"Memory error on the Bart board$"
-
- reset_error DB 10,13,"ASIC reset failure on Bart board$"
-
- _586_diagnostic_failure DB 10,13,"82586 diagnostic failure on the "
- DB "Bart board$"
-
- _586_not_responding_msg DB 10,13,"82586 did not respond to command "
- DB "on the Bart board$"
-
- command_unit_not_idle DB 10,13,"82586 command unit is not "
- DB "responding on the Bart board$"
-
- invalid_int_no LABEL WORD
- invalid_int_number DB 10,13,"Bart board IRQ/Interrupt number "
- DB "not specified correctly$"
-
- eeprom_checksum_error DB 10,13,"EEPROM failed checksum$"
-
- Board_Not_Installed DB 10,13,"Bart Board not found$"
-
- irq_config_error DB 10,13,"IRQ selection is for 16 bit slot "
- DB "only.$"
-
- code ends
-
- end
-