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

  1. version    equ    0
  2. ;History:1145,1
  3.  
  4.     .286
  5.  
  6. ;  Copyright, 1988-1992, Russell Nelson, Crynwr Software
  7.  
  8. ;   This program is free software; you can redistribute it and/or modify
  9. ;   it under the terms of the GNU General Public License as published by
  10. ;   the Free Software Foundation, version 1.
  11. ;
  12. ;   This program is distributed in the hope that it will be useful,
  13. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. ;   GNU General Public License for more details.
  16. ;
  17. ;   You should have received a copy of the GNU General Public License
  18. ;   along with this program; if not, write to the Free Software
  19. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21. ;-------------------------------------------------------------------------
  22. ; vA 4/3/93   Hacks for multiple ISA board support added, IJW @ Leeds Univ.
  23. ; vB 10/3/93  Added checks for legal packet size in rx, ijw.
  24. ;-------------------------------------------------------------------------
  25.  
  26.     include    defs.asm
  27.  
  28. code    segment    word public
  29.     assume    cs:code, ds:code
  30.  
  31. ;----------------------------------------------------------------------------;
  32. ;                                                                            ;
  33. ;       This source file is the property of 3Com Corporation and may not be  ;
  34. ;       copied or distributed in any isomorphic form without an appropriate  ;
  35. ;       prior licensing arrangement with 3Com Corporation.                   ;
  36. ;                                                                            ;
  37. ;       Copyright (c) 1988 3Com Corporation                                  ;
  38. ;                                                                            ;
  39. ;------ Equates -------------------------------------------------------------;
  40. ;
  41. ; Command code masks
  42. ;
  43. CMD_CMDMASK         equ 0F800h                  ; command bits
  44. CMD_ARGMASK         equ 007FFh                  ; argument bits
  45. ;
  46. ; Command codes, word form
  47. ;
  48. CMD_GLOBALRESET     equ 00000b shl 11           ; global reset
  49. CMD_SELECTWINDOW    equ 00001B shl 11           ; select register window
  50. CMD_STARTINTXCVR    equ 00010b shl 11           ; start internal transciver
  51. CMD_RXDISABLE       equ 00011b shl 11           ; rx disable
  52. CMD_RXENABLE        equ 00100b shl 11           ; rx enable
  53. CMD_RXRESET         equ 00101b shl 11           ; rx reset
  54. CMD_RXDISCARD       equ 01000b shl 11           ; rx discard top packet
  55. CMD_TXENABLE        equ 01001b shl 11           ; tx enable
  56. CMD_TXDISABLE       equ 01010b shl 11           ; tx disable
  57. CMD_TXRESET         equ 01011b shl 11           ; tx reset
  58. CMD_REQUESTINT      equ 01100b shl 11           ; request interrupt
  59. CMD_ACKNOWLEDGE     equ 01101b shl 11           ; acknowledge interrupt
  60. CMD_SETINTMASK      equ 01110b shl 11           ; set interrupt mask
  61. CMD_SETRZMASK       equ 01111b shl 11           ; set read zero mask
  62. CMD_SETRXFILTER     equ 10000b shl 11           ; set rx filter
  63. CMD_SETRXEARLY      equ 10001b shl 11           ; set rx early threshold
  64. CMD_SETTXAVAILABLE  equ 10010b shl 11           ; set tx available threshold
  65. CMD_SETTXSTART      equ 10011b shl 11           ; set tx start threshold
  66. CMD_STATSENABLE     equ 10101b shl 11           ; statistics enable
  67. CMD_STATSDISABLE    equ 10110b shl 11           ; statistics disable
  68. CMD_STOPINTXCVR     equ 10111b shl 11           ; start internal transciver
  69. ;
  70. ; Command codes, hibyte form (commands without operands only)
  71. ;
  72. CMDH_STARTINTXCVR   equ CMD_STARTINTXCVR shr 8
  73. CMDH_RXDISABLE      equ CMD_RXDISABLE shr 8
  74. CMDH_RXENABLE       equ CMD_RXENABLE shr 8
  75. CMDH_RXDISCARD      equ CMD_RXDISCARD shr 8
  76. CMDH_TXENABLE       equ CMD_TXENABLE shr 8
  77. CMDH_TXDISABLE      equ CMD_TXDISABLE shr 8
  78. CMDH_REQUESTINT     equ CMD_REQUESTINT shr 8
  79. CMDH_STATSENABLE    equ CMD_STATSENABLE shr 8
  80. CMDH_STATSDISABLE   equ CMD_STATSDISABLE shr 8
  81. CMDH_STOPINTXCVR    equ CMD_STOPINTXCVR shr 8
  82. ;
  83. ; Status register bits (INT for interrupt sources, ST for the rest)
  84. ;
  85. INT_LATCH           equ 00001h                  ; interrupt latch
  86. INT_ADAPTERFAIL     equ 00002h                  ; adapter failure
  87. INT_TXCOMPLETE      equ 00004h                  ; tx complete
  88. INT_TXAVAILABLE     equ 00008h                  ; tx available
  89. INT_RXCOMPLETE      equ 00010h                  ; rx complete
  90. INT_RXEARLY         equ 00020h                  ; rx early
  91. INT_REQUESTED       equ 00040h                  ; interrupt requested
  92. INT_UPDATESTATS     equ 00080h                  ; update statistics
  93. ST_FAILED           equ 00800h                  ; command failed
  94. ST_BUSY             equ 01000h                  ; command busy
  95. ST_WINDOW           equ 0E000h                  ; window bits (13-15)
  96.  
  97. STH_FAILED          equ ST_FAILED shr 8
  98. STH_BUSY            equ ST_BUSY shr 8
  99. STH_WINDOW          equ ST_WINDOW shr 8
  100.  
  101. ;
  102. ; RxStatus register bits
  103. ;
  104. RXS_INCOMPLETE      equ 8000h                   ; not completely received
  105. RXS_ERROR           equ 4000h                   ; error in packet
  106. RXS_LENGTH          equ 07FFh                   ; bytes in RxFIFO
  107. RXS_ERRTYPE         equ 3800h                   ; Rx error type, bit 13-11
  108. RXS_OVERRUN         equ 0000h                   ; overrun error
  109. RXS_OVERSIZE        equ 0800h                   ; oversize packet error
  110. RXS_DRIBBLE         equ 1000h                   ; dribble bit (not an error)
  111. RXS_RUNT            equ 1800h                   ; runt packet error
  112. RXS_CRC             equ 2800h                   ; CRC error
  113. RXS_FRAMING         equ 2000h                   ; framing error
  114.  
  115. RXSH_INCOMPLETE     equ RXS_INCOMPLETE shr 8
  116. RXSH_ERROR          equ RXS_ERROR shr 8
  117. RXSH_ERRTYPE        equ RXS_ERRTYPE shr 8
  118. RXSH_OVERRUN        equ RXS_OVERRUN shr 8
  119. RXSH_DRIBBLE        equ RXS_DRIBBLE shr 8
  120. RXSH_CRC            equ RXS_CRC shr 8
  121. RXSH_RUNT           equ RXS_RUNT shr 8
  122. RXSH_OVERSIZE       equ RXS_OVERSIZE shr 8
  123. RXSH_FRAMING        equ RXS_FRAMING shr 8
  124. ;
  125. ; TxStatus register bits
  126. ;
  127. TXS_COMPLETE        equ 80h                     ; tx completed
  128. TXS_INTREQUESTED    equ 40h                     ; interrupt on successfull tx
  129. TXS_ERRTYPE         equ 38h                     ; error bits
  130. TXS_JABBERERROR     equ 20h                     ; jabber error
  131. TXS_UNDERRUN        equ 10h                     ; tx underrun error
  132. TXS_MAXCOLLISIONS   equ 08h                     ; max collisions error
  133. TXS_STATUSOVERFLOW  equ 04h                     ; TX status stack is full
  134. ;
  135. ; Window Numbers
  136. ;
  137. WNO_SETUP           equ 0                       ; setup/configuration
  138. WNO_OPERATING       equ 1                       ; operating set
  139. WNO_STATIONADDRESS  equ 2                       ; station address setup/read
  140. WNO_FIFO            equ 3                       ; FIFO management
  141. WNO_DIAGNOSTICS     equ 4                       ; diagnostics
  142. WNO_READABLE        equ 5                       ; registers set by commands
  143. WNO_STATISTICS      equ 6                       ; statistics
  144. ;
  145. ; Port offsets, Window 1 (WNO_OPERATING)
  146. ;
  147. PORT_CmdStatus      equ 0Eh                     ; command/status
  148. PORT_TxFree         equ 0Ch                     ; free transmit bytes
  149. PORT_TxStatus       equ 0Bh                     ; transmit status (byte)
  150. PORT_Timer          equ 0Ah                     ; latency timer (byte)
  151. PORT_RxStatus       equ 08h                     ; receive status
  152. PORT_RxFIFO         equ 00h                     ; RxFIFO read
  153. PORT_TxFIFO         equ 00h                     ; TxFIFO write
  154. ;
  155. ; Port offsets, Window 0 (WNO_SETUP)
  156. ;
  157. PORT_EEData         equ 0Ch                     ; EEProm data register
  158. PORT_EECmd          equ 0Ah                     ; EEProm command register
  159. PORT_CfgResource    equ 08h                     ; resource configuration
  160. PORT_CfgAddress     equ 06h                     ; address configuration
  161. PORT_CfgControl     equ 04h                     ; configuration control
  162. PORT_ProductID      equ 02h                     ; product id (EISA)
  163. PORT_Manufacturer   equ 00h                     ; Manufacturer code (EISA)
  164. ;
  165. ; Port offsets, Window 2 (WNO_STATIONADDRESS)
  166. ;
  167. PORT_SA0_1          equ 00h                     ; station address bytes 0,1
  168. PORT_SA2_3          equ 02h                     ; station address bytes 2,3
  169. PORT_SA4_5          equ 04h                     ; station address bytes 4,5
  170. ;
  171. ; Port offsets, Window 3 (WNO_FIFO)
  172. ;
  173. PORT_ALT_TxFree     equ 0Ch                     ; free transmit bytes (dup)
  174. PORT_RxFree         equ 0Ah                     ; free receive bytes
  175. ;
  176. ; Port offsets, Window 4 (WNO_DIAGNOSTICS)
  177. ;
  178. PORT_MediaStatus    equ 0Ah                     ; media type/status
  179. PORT_SlingshotStatus equ 08h                    ; Slingshot status
  180. PORT_NetDiagnostic  equ 06h                     ; net diagnostic
  181. PORT_FIFODiagnostic equ 04h                     ; FIFO diagnostic
  182. PORT_HostDiagnostic equ 02h                     ; host diagnostic
  183. PORT_TxDiagnostic   equ 00h                     ; tx diagnostic
  184. ;
  185. ; Port offsets, Window 5 (WNO_READABLE)
  186. ;
  187. PORT_RZMask         equ 0Ch                     ; read zero mask
  188. PORT_IntMask        equ 0Ah                     ; interrupt mask
  189. PORT_RxFilter       equ 08h                     ; receive filter
  190. PORT_RxEarly        equ 06h                     ; rx early threshold
  191. PORT_TxAvailable    equ 02h                     ; tx available threshold
  192. PORT_TxStart        equ 00h                     ; tx start threshold
  193. ;
  194. ; Port offsets, Window 6 (WNO_STATISTICS)
  195. ;
  196. PORT_TXBYTES        equ 0Ch                     ; tx bytes ok
  197. PORT_RXBYTES        equ 0Ah                     ; rx bytes ok
  198. PORT_TXDEFER        equ 08h                     ; tx frames deferred (byte)
  199. PORT_RXFRAMES       equ 07h                     ; rx frames ok (byte)
  200. PORT_TXFRAMES       equ 06h                     ; tx frames ok (byte)
  201. PORT_RXDISCARDED    equ 05h                     ; rx frames discarded (byte)
  202. PORT_TXLATE         equ 04h                     ; tx frames late coll. (byte)
  203. PORT_TXSINGLE       equ 03h                     ; tx frames one coll. (byte)
  204. PORT_TXMULTIPLE     equ 02h                     ; tx frames mult. coll. (byte)
  205. PORT_TXNOCD         equ 01h                     ; tx frames no CDheartbt (byte)
  206. PORT_TXCARRIERLOST  equ 00h                     ; tx frames carrier lost (byte)
  207. ;
  208. ; Various command arguments
  209. ;
  210. INT_ALLDISABLED         equ 00000000000b            ; all interrupts disabled
  211. INT_ALLENABLED          equ 00011111110b            ; all interrupts enabled
  212.  
  213. FILTER_INDIVIDUAL       equ 0001b                   ; individual address
  214. FILTER_MULTICAST        equ 0010b                   ; multicast/group addresses
  215. FILTER_BROADCAST        equ 0100b                   ; broadcast address
  216. FILTER_PROMISCUOUS      equ 1000b                   ; promiscuous mode
  217.  
  218. RXEARLY_DISABLED        equ 2032                    ; RxEarly to disable
  219.  
  220. TXAVAIL_DISABLED        equ 2040                    ; TxAvailable to disable
  221. TXAVAIL_MIN             equ 4
  222.  
  223. TXSTART_DISABLED        equ 2040                    ; TxStart to disable
  224. TXSTART_MIN             equ 0
  225. TXSTART_MAX             equ TXSTART_DISABLED
  226.  
  227. RXLENGTH_MAX            equ 1792                    ; maximum rxlength
  228. ;
  229. ; Transmit Preamble
  230. ;
  231. PREAMBLESIZE            equ 4                       ; transmit preamble size
  232. TXP_INTONSUCCESS        equ 8000h                   ; interrupt on successful tx
  233. ;
  234. ; Bits in various diagnostics registers
  235. ;
  236. MEDIA_TP                equ 8000h                   ; TP transciever
  237. MEDIA_BNC               equ 4000h                   ; Thinnet transciever
  238. MEDIA_INTENDEC          equ 2000h                   ; internal encoder/decoder
  239. MEDIA_SQE               equ 1000h                   ; SQE present
  240. MEDIA_LBEAT             equ 0800h                   ; link beat ok (TP)
  241. MEDIA_POLARITY          equ 0400h                   ; polarity (TP)
  242. MEDIA_JABBER            equ 0200h                   ; jabber (TP)
  243. MEDIA_UNSQUELCH         equ 0100h                   ; unsquelch (TP)
  244. MEDIA_LBEATENABLE       equ 0080h                   ; link beat enable (TP)
  245. MEDIA_JABBERENABLE      equ 0040h                   ; jabber enable (TP)
  246. MEDIA_CRS               equ 0020h                   ; carrier sense
  247. MEDIA_COLLISION         equ 0010h                   ; collision
  248. MEDIA_SQEENABLE         equ 0008h                   ; enable SQE statistics
  249.  
  250. NETD_EXTLOOPBACK        equ 8000h                   ; TP external loopback
  251. NETD_ENDECLOOPBACK      equ 4000h                   ; ENDEC loopback
  252. NETD_CORELOOPBACK       equ 2000h                   ; ethernet core loopback
  253. NETD_FIFOLOOPBACK       equ 1000h                   ; FIFO loopback
  254. NETD_TXENABLED          equ 0800h                   ; tx enabled
  255. NETD_RXENABLED          equ 0400h                   ; rx enabled
  256. NETD_TXTRANSMITTING     equ 0200h                   ; tx transmitting
  257. NETD_TXRESETREQD        equ 0100h                   ; tx reset required
  258.  
  259. FIFOD_RXRECEIVING       equ 8000h                   ; rx receiveing
  260. FIFOD_RXUNDERRUN        equ 2000h                   ; rx underrun
  261. FIFOD_RXSTATUSOVER      equ 1000h                   ; rx status overrun
  262. FIFOD_RXOVERRUN         equ 0800h                   ; rx overrun
  263. FIFOD_TXOVERRUN         equ 0400h                   ; tx overrun
  264. FIFOD_BISTRESULTS       equ 00FFh                   ; BIST results (mask)
  265.  
  266. SLING_TXUNDERRUN        equ 2000h                   ; Slingshot TxUnderrun bit
  267. ;
  268. ; board identification codes, byte swapped in Rev 0
  269. ;
  270. EISA_MANUFACTURER_ID    equ 06D50h                  ; EISA manufacturer code
  271. ISA_PRODUCT_ID          equ 09050h                  ; Product ID for ISA board
  272. PRODUCT_ID_MASK         equ 0F0FFh                  ; Mask off revision nibble
  273. ;
  274. ; EEProm access
  275. ;
  276. EE_BUSY                     equ 8000h                   ; EEProm busy bit in EECmd
  277. EE_TCOM_NODE_ADDR_WORD0     equ 00h
  278. EE_TCOM_NODE_ADDR_WORD1     equ 01h
  279. EE_TCOM_NODE_ADDR_WORD2     equ 02h
  280. EE_VULCAN_PROD_ID           equ 03h
  281. EE_MANUFACTURING_DATA       equ 04h
  282. EE_SERIAL_NUMBER_WORD0      equ 05h
  283. EE_SERIAL_NUMBER_WORD1      equ 06h
  284. EE_MANUFACTURER_CODE        equ 07h
  285. EE_ADDR_CONFIGURATION       equ 08h
  286. EE_RESOURCE_CONFIGURATION   equ 09h
  287. EE_OEM_NODE_ADDR_WORD0      equ 0Ah
  288. EE_OEM_NODE_ADDR_WORD1      equ 0Bh
  289. EE_OEM_NODE_ADDR_WORD2      equ 0Ch
  290. EE_SOFTWARE_CONFIG_INFO     equ 0Dh
  291. EE_CWORD                    equ 0Eh
  292. ;
  293. ; contention logic
  294. ;
  295. READ_EEPROM             equ 080h
  296. ID_GLOBAL_RESET        equ 0C0h
  297. SET_TAG_REGISTER        equ 0D0h
  298. TEST_TAG_REGISTER       equ 0D8h
  299. ACTIVATE_AND_SET_IO     equ 0E0h
  300. ACTIVATE_VULCAN         equ 0FFh
  301. ;
  302. ; Resource Configuration Register bits
  303. ;
  304. RCONFIG_IRQ             equ 0F000h
  305. ;
  306. ; Address Configuration Register bits
  307. ;
  308. ACONFIG_XCVR            equ 0C000h
  309. ACONFIG_IOBASE          equ 0001Fh
  310.  
  311. IOBASE_EISA             equ 0001Fh
  312.  
  313. TP_XCVR                 equ 00000h
  314. BNC_XCVR                equ 0C000h
  315. AUI_XCVR                equ 04000h
  316.  
  317. MIN_IO_BASE_ADDR        equ 200h
  318. MAX_IO_BASE_ADDR        equ 3F0h
  319. REGISTER_SET_SIZE       equ 10h
  320. ;
  321. ; Software Configuration Register bits
  322. ;
  323. SW_OPTIMIZE             equ 0030h
  324. SW_MAXCLI               equ 3F00h
  325. SW_LINKBEAT             equ 4000h
  326. ;
  327. ; Possibilities for SW_OPTIMIZE
  328. ;
  329. OPTIMIZE_DOS_CLIENT     equ 0010h
  330. OPTIMIZE_WINDOWS_CLIENT equ 0020h
  331. OPTIMIZE_SERVER         equ 0030h
  332. ;
  333. ; Configuration Control Register bits
  334. ;
  335. ENABLE_ADAPTER          equ 01h
  336.  
  337. setwin    macro    win
  338.     setport    PORT_CmdStatus
  339.     mov    ax,CMD_SELECTWINDOW+win
  340.     out    dx,ax
  341.     endm
  342.  
  343.     extrn    is_eisa: byte        ;=0 if ISA, =1 if EISA
  344.     extrn    is_186: byte        ;=0 if 808[68], =1 if 80[1234]86.
  345.     extrn    is_386: byte        ;=0 if 80[12]8[68], =1 if 80[34]86.
  346.  
  347.     public    int_no, io_addr
  348. int_no    db    0,0,0,0            ;must be four bytes long for get_number.
  349. io_addr    dw    0,0            ;must be four bytes long for get_number.
  350.  
  351.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  352. driver_class    db    BLUEBOOK,IEEE8023,0    ;null terminated list of classes.
  353. driver_type    db    94        ;assigned by FTP Software, <jbvb@ftp.com>
  354. driver_name    db    '3c509',0    ;name of the driver.
  355. driver_function    db    2
  356. parameter_list    label    byte
  357.     db    1    ;major rev of packet driver specification
  358.     db    9    ;minor rev of packet driver specification
  359.     db    14    ;length of parameter list
  360.     db    EADDR_LEN    ;length of MAC-layer address
  361.     dw    GIANT    ;MTU, including MAC headers
  362.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  363.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  364.     dw    0    ;(# of successive xmits) - 1
  365. int_num    dw    0    ;Interrupt # to hook for post-EOI
  366.             ;processing, 0 == none,
  367.  
  368.     public    rcv_modes
  369. rcv_modes    dw    7        ;number of receive modes in our table.
  370.         dw    0               ;There is no mode zero
  371.         dw    rcv_mode_1
  372.         dw    rcv_mode_2
  373.         dw    rcv_mode_3
  374.         dw    0        ;haven't set up perfect filtering yet.
  375.         dw    rcv_mode_5
  376.         dw    rcv_mode_6
  377.  
  378.     include    timeout.asm
  379.  
  380.     public bad_command_intercept
  381. bad_command_intercept:
  382. ;called with ah=command, unknown to the skeleton.
  383. ;exit with nc if okay, cy, dh=error if not.
  384.     mov    dh,BAD_COMMAND
  385.     stc
  386.     ret
  387.  
  388.     public    as_send_pkt
  389. ; The Asynchronous Transmit Packet routine.
  390. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  391. ;   interrupts possibly enabled.
  392. ; Exit with nc if ok, or else cy if error, dh set to error number.
  393. ;   es:di and interrupt enable flag preserved on exit.
  394. as_send_pkt:
  395.     ret
  396.  
  397.     public    drop_pkt
  398. ; Drop a packet from the queue.
  399. ; Enter with es:di -> iocb.
  400. drop_pkt:
  401.     assume    ds:nothing
  402.     ret
  403.  
  404.     public    xmit
  405. ; Process a transmit interrupt with the least possible latency to achieve
  406. ;   back-to-back packet transmissions.
  407. ; May only use ax and dx.
  408. xmit:
  409.     assume    ds:nothing
  410.     ret
  411.  
  412.  
  413.     public    send_pkt
  414. send_pkt:
  415. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  416. ;  (only if the high-performance bit is set in driver_function)
  417. ;enter with ds:si -> packet, cx = packet length.
  418. ;if we're a high-performance driver, es:di -> upcall.
  419. ;exit with nc if ok, or else cy if error, dh set to error number.
  420.     assume    ds:nothing
  421.     cmp    cx,GIANT        ; Is this packet too large?
  422.     ja    send_pkt_toobig
  423.  
  424.     loadport
  425.     setport    PORT_TxStatus        ;get the previous transmit status.
  426.     in    al,dx
  427.     setport    PORT_CmdStatus
  428.     test    al,TXS_UNDERRUN or TXS_JABBERERROR    ;do we need to reset transmitter?
  429.     je    send_pkt_0
  430.     push    ax
  431.     mov    ax,CMD_TXRESET
  432.     out    dx,ax
  433.     pop    ax
  434. send_pkt_0:
  435.  
  436.     test    al,TXS_ERRTYPE        ;any errors?
  437.     je    send_pkt_3        ;no.
  438.     call    count_out_err        ;yes, count it.
  439.     mov    ax,CMD_TXENABLE        ;yes, re-enable the transmitter.
  440.     out    dx,ax
  441. send_pkt_3:
  442.  
  443.     mov    bx,cx            ;round BX up to dword boundary.
  444.     add    bx,3
  445.     and    bx,not 3
  446.  
  447.     setport    PORT_TxFree        ;wait for enough bytes in transmit buffer.
  448.     mov    ax,18
  449.     call    set_timeout
  450. send_pkt_1:
  451.     in    ax,dx
  452.     cmp    ax,bx
  453.     jae    send_pkt_2
  454.     call    do_timeout
  455.     jne    send_pkt_1
  456.     mov    dh,CANT_SEND        ;timed out, can't send.
  457.     stc
  458.     ret
  459. send_pkt_toobig:
  460.     mov    dh,NO_SPACE
  461.     stc
  462.     ret
  463. send_pkt_2:
  464.  
  465.     setport    PORT_TxFIFO
  466.     mov    ax,cx            ;output the count
  467.     out    dx,ax            ;   (no interrupt requested)
  468.     out    dx,ax            ;output the second reserved word.
  469.     mov    cx,bx            ;output the rest of the packet.
  470.  
  471.     cmp    is_386,0        ;can we output dwords?
  472.     jne    send_pkt_7        ;yes.
  473.     shr    cx,1            ;output 16 bits at a time.
  474.     rep    outsw
  475.     jmp    short send_pkt_6
  476. send_pkt_7:
  477.     .386
  478.     shr    cx,2            ;already rounded up.
  479.     rep    outsd            ;output 32 bits at a time.
  480.     .286
  481. send_pkt_6:
  482.  
  483.     clc
  484.     ret
  485.  
  486.  
  487.     public    set_address
  488. set_address:
  489. ;enter with ds:si -> Ethernet address, CX = length of address.
  490. ;exit with nc if okay, or cy, dh=error if any errors.
  491.     assume    ds:nothing
  492.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  493.     je    set_address_4
  494.     mov    dh,BAD_ADDRESS
  495.     stc
  496.     jmp    short set_address_done
  497. set_address_4:
  498.  
  499.     loadport
  500.     setwin    WNO_STATIONADDRESS
  501.     setport    PORT_SA0_1
  502. set_address_1:
  503.     lodsb
  504.     out    dx,al
  505.     inc    dx
  506.     loop    set_address_1
  507. set_address_okay:
  508.     mov    cx,EADDR_LEN        ;return their address length.
  509.     clc
  510. set_address_done:
  511.     push    cs
  512.     pop    ds
  513.     assume    ds:code
  514.     loadport
  515.     setwin    WNO_OPERATING
  516.     ret
  517.  
  518.  
  519. ;skip past the following two bytes while destroying BX.
  520. skip2    macro
  521.     db    0bbh            ;opcode of "mov bx,0000"
  522.     endm
  523.  
  524. rcv_mode_1:
  525.     mov    al,0            ;receive nothing
  526.     skip2
  527. rcv_mode_2:
  528.     mov    al,1            ;receive individual address
  529.     skip2
  530. rcv_mode_3:
  531.     mov    al,5            ;receive individual address+broadcast
  532.     skip2
  533. rcv_mode_5:
  534.     mov    al,3            ;receive individual address+group addr(multicast)
  535.     skip2
  536. rcv_mode_6:
  537.     mov    al,8            ;receive all packets.
  538.     mov    ah,CMD_SETRXFILTER shr 8    ;set receive filter
  539.     loadport
  540.     setport    PORT_CmdStatus
  541.     out    dx,ax
  542.     ret
  543.  
  544.  
  545.     public    set_multicast_list
  546. set_multicast_list:
  547. ;enter with ds:si ->list of multicast addresses, ax = number of addresses,
  548. ;  cx = number of bytes.
  549. ;return nc if we set all of them, or cy,dh=error if we didn't.
  550.     mov    dh,NO_MULTICAST
  551.     stc
  552.     ret
  553.  
  554.  
  555.     public    terminate
  556. terminate:
  557.     loadport
  558.     setport    PORT_CmdStatus
  559.     mov    ax,CMD_GLOBALRESET
  560.     out    dx,ax
  561.     ret
  562.  
  563.  
  564.     public    reset_interface
  565. reset_interface:
  566. ;reset the interface.
  567.     assume    ds:code
  568.     ret
  569.  
  570.  
  571. ;decide if we know this packet's type.
  572. ;enter with es:di -> packet type, dl = packet class.
  573. ;exit with nc if we know it, cy if not.
  574.     extrn    recv_locate: near
  575.  
  576. ;do the first upcall, get a pointer to the packet.
  577. ;enter with cx = packet length.
  578. ;exit with cx = packet length, es:di -> buffer for the packet.
  579.     extrn    recv_found: near
  580.  
  581. ;called when we want to determine what to do with a received packet.
  582. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  583.     extrn    recv_find: near
  584.  
  585. ;called after we have copied the packet into the buffer.
  586. ;enter with ds:si ->the packet, cx = length of the packet.
  587.     extrn    recv_copy: near
  588.  
  589. ;call this routine to schedule a subroutine that gets run after the
  590. ;recv_isr.  This is done by stuffing routine's address in place
  591. ;of the recv_isr iret's address.  This routine should push the flags when it
  592. ;is entered, and should jump to recv_exiting_exit to leave.
  593. ;enter with ax = address of routine to run.
  594.     extrn    schedule_exiting: near
  595.  
  596. ;recv_exiting jumps here to exit, after pushing the flags.
  597.     extrn    recv_exiting_exit: near
  598.  
  599.     extrn    count_in_err: near
  600.     extrn    count_out_err: near
  601.  
  602. ether_buff    db    EADDR_LEN  dup(?)
  603.         db    EADDR_LEN  dup(?)
  604. ether_type    db    8 dup(?)
  605. ETHER_BUFF_LEN    equ    $ - ether_buff
  606. .erre    (ETHER_BUFF_LEN and 3) eq 0    ;must be an even # of dwords.
  607.  
  608. early_bytes    dw    0        ;the early byte gets the worm.
  609.  
  610. read_header:
  611. ;enter with dx -> PORT_RxFIFO
  612. ;exit with es:di -> packet type.
  613.  
  614.     mov    ax,ds
  615.     mov    es,ax
  616.     mov    di,offset ether_buff
  617.     mov    cx,ETHER_BUFF_LEN/4
  618. repinsd:
  619.     shl    cx,1            ;*** this gets changed into "rep insd"
  620.     rep    insw            ;***   "nop" on a 386 or 486.
  621.  
  622.     mov    di,offset ether_type
  623.  
  624.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  625.     mov    ax, es:[di]
  626.     xchg    ah, al
  627.     cmp     ax, 1500
  628.     ja    read_header_1
  629.     inc    di            ;set di to 802.2 header
  630.     inc    di
  631.     mov    dl, IEEE8023
  632. read_header_1:
  633.     ret
  634.  
  635.  
  636.     public    recv
  637. recv:
  638. ;called from the recv isr.  All registers have been saved, ds=cs,
  639. ;our interrupt has been acknowledged, and our interrupts have been
  640. ;masked at the interrupt controller.
  641.     assume    ds:code
  642. recv_another:
  643.     loadport
  644.     setport    PORT_CmdStatus
  645.     in    ax,dx            ;did we get a packet?
  646.     or    ax,CMD_ACKNOWLEDGE
  647.     out    dx,ax
  648.     setport    PORT_RxStatus
  649.     test    al,INT_RXCOMPLETE
  650.     jne    recv_complete
  651.     test    al,INT_RXEARLY        ;are we getting it early?
  652.     jne    recv_early
  653.     jmp    recv_exit            ;no.
  654. recv_early:
  655.     in    ax,dx            ;get the amount we can read.
  656.     and    ax,RXS_LENGTH
  657.     cmp    ax,ETHER_BUFF_LEN    ;do we have enough to read early?
  658.     jb    recv_early_1        ;no, give up.
  659.  
  660.     mov    early_bytes,ETHER_BUFF_LEN
  661.  
  662.     setport    PORT_RxFIFO
  663.     call    read_header
  664.     call    recv_locate        ;see if this is a type we want.
  665.     jnc    recv_early_1        ;it is, just exit.
  666.     jmp    recv_discard        ;it isn't.
  667.  
  668. recv_early_1:
  669.     jmp    recv_exit
  670.  
  671. ;yes, this is dead code.  It's only in here to ensure that the setport macro
  672. ;has the right value.
  673.     setport    PORT_RxStatus
  674. recv_complete:
  675.     in    ax,dx            ;get the size.
  676.     test    ax,RXS_ERROR        ;any errors?
  677.     je    recv_complete_2        ;no, it's fine.
  678.  
  679.     and    ax,RXS_ERRTYPE        ;get just the error type bits.
  680.     cmp    ax,RXS_DRIBBLE        ;dribble is just a warning.
  681.     jne    recv_complete_1
  682.  
  683. recv_err:
  684.     call    count_in_err
  685.     jmp    recv_discard
  686.  
  687. recv_complete_1:
  688.     in    ax,dx            ;get the size again.
  689. recv_complete_2:
  690. ;Put it on the receive queue
  691.     and    ax,RXS_LENGTH
  692.     mov    cx,ax
  693.  
  694.     cmp    early_bytes,0        ;did we read the header in already?
  695.     jne    recv_complete_3        ;yes, we've already got it.
  696.  
  697.     cmp    cx,RUNT            ;check legal packet size
  698.     jb    recv_err
  699.     cmp    cx,GIANT
  700.     ja    recv_err
  701.  
  702.     push    cx
  703.     setport    PORT_RxFIFO
  704.     call    read_header
  705.     pop    cx
  706.  
  707.     push    cx
  708.     call    recv_find
  709.     pop    cx
  710.     jmp    short    recv_complete_4
  711.  
  712. recv_complete_3:
  713.     add    cx,early_bytes        ;add in the early bytes we got.
  714.  
  715.     cmp    cx,RUNT            ;check legal packet size
  716.     jb    recv_err
  717.     cmp    cx,GIANT
  718.     ja    recv_err
  719.  
  720.     push    cx
  721.     call    recv_found        ;do the first upcall.
  722.     pop    cx
  723.  
  724. recv_complete_4:
  725.     mov    ax,es            ;is this pointer null?
  726.     or    ax,di
  727.     je    recv_discard        ;yes - just free the frame.
  728.  
  729.     push    es            ;remember where the buffer pointer is.
  730.     push    di
  731.  
  732.     mov    bx,cx            ;save the count.
  733.     mov    cx,ETHER_BUFF_LEN/2    ;move the data over.
  734.     mov    si,offset ether_buff
  735.     rep    movsw
  736.  
  737.     loadport            ;restore the I/O port.
  738.     setport    PORT_RxFIFO
  739.     mov    cx,bx            ;restore the count.
  740.     sub    cx,ETHER_BUFF_LEN    ;but leave off what we've already copied.
  741.  
  742.     cmp    is_386,0
  743.     jne    io_input_386
  744. io_input_286:
  745.     push    cx
  746.     shr    cx,1
  747.     rep    insw
  748.     pop    cx
  749.     jnc    io_input_286_1        ;go if the count was even.
  750.     insb                ;get that last byte.
  751.     in    al,dx            ;and get the pad byte.
  752.     test    cx,2            ;even number of words?
  753.     jne    io_input_done        ;no.
  754.     in    ax,dx            ;yes, get the pad word.
  755.     jmp    short io_input_done
  756. io_input_286_1:
  757.     test    cx,2            ;odd number of words?
  758.     je    io_input_done        ;no.
  759.     in    ax,dx            ;yes, get the pad word.
  760.     jmp    short io_input_done
  761.  
  762. io_input_386:
  763.     .386
  764.     push    eax
  765.     push    cx            ;first, get all the full words.
  766.     shr    cx,2
  767.     rep    insd
  768.     pop    cx
  769.     test    cx,3            ;even number of dwords?
  770.     je    io_input_386_one_byte    ;yes.
  771.     in    eax,dx            ;no, get the partial word.
  772.     test    cx,2            ;a full word to be stored?
  773.     je    io_input_386_one_word
  774.     stosw                ;yes, store it,
  775.     shr    eax,16            ;and move over by a word.
  776. io_input_386_one_word:
  777.  
  778.     test    cx,1            ;a full byte to be stored?
  779.     je    io_input_386_one_byte
  780.     stosb                ;yes, store it.
  781. io_input_386_one_byte:
  782.     pop    eax
  783.     .286
  784.  
  785. io_input_done:
  786.  
  787.     mov    cx,bx            ;restore the count.
  788.     pop    si
  789.     pop    ds
  790.     assume    ds:nothing
  791.     call    recv_copy        ;tell them that we copied it.
  792.  
  793.     mov    ax,cs            ;restore our ds.
  794.     mov    ds,ax
  795.     assume    ds:code
  796.  
  797. recv_discard:
  798.     loadport
  799.     setport    PORT_CmdStatus
  800.     mov    ax,CMD_RXDISCARD
  801.     out    dx,ax
  802.  
  803. recv_discard_1:
  804.     in    ax,dx            ;wait for the command to finish.
  805.     test    ax,ST_BUSY
  806.     jne    recv_discard_1
  807.  
  808.     mov    early_bytes,0
  809.  
  810.     jmp    recv_another
  811. recv_exit:
  812.     ret
  813.  
  814.  
  815.     public    timer_isr
  816. timer_isr:
  817. ;if the first instruction is an iret, then the timer is not hooked
  818.     iret
  819.  
  820. ;any code after this will not be kept.  Buffers used by the program, if any,
  821. ;are allocated from the memory between end_resident and end_free_mem.
  822.     public end_resident,end_free_mem
  823. end_resident    label    byte
  824. end_free_mem    label    byte
  825.  
  826.  
  827.     public    usage_msg
  828. usage_msg    db "usage: 3c509 [options] <packet_int_no> "
  829.         db      "[id_port]|[io_port]|[board_num]",CR,LF,'$'
  830.     public    copyright_msg
  831. copyright_msg    db    "Packet driver for a 3c509, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
  832.         db    "Portions Copyright 1992, Crynwr Software",CR,LF,'$'
  833. needs_186_msg    db    "Needs a 186 or higher-numbered processor",CR,LF,'$'
  834. no_isa_msg    db    CR,LF
  835.         db    "No 3c509 found.  Use a different id_port value.  Default is 0x110.",CR,LF,'$'
  836. reading_msg    db    "Reading EEPROM.",'$'
  837.  
  838. multiple_msg    db    "Multiple 3C509s found, specify i/o port",CR,LF,'$'
  839. wrong_port_msg    db    "No 3C509 board found at specified i/o port",CR,LF,'$'
  840. eisa_in_isa_msg    db    "EISA configured board in ISA slot",CR,LF,'$'
  841.  
  842. int_no_name    db    "Interrupt number ",'$'
  843. io_addr_name    db    "I/O port ",'$'
  844. aui_xcvr_msg    db    "Using AUI transceiver",CR,LF,'$'
  845. bnc_xcvr_msg    db    "Using BNC (10Base2) transceiver",CR,LF,'$'
  846. tp_xcvr_msg    db    "Using Twisted Pair (10BaseT) transceiver",CR,LF,'$'
  847. id_port_name    db    "ID port ",'$'
  848.  
  849. ;called when you're ready to receive interrupts.
  850.     extrn    set_recv_isr: near
  851.  
  852. ;enter with si -> argument string, di -> dword to store.
  853. ;if there is no number, don't change the number.
  854.     extrn    get_number: near
  855.  
  856. ;enter with dx -> argument string, di -> dword to print.
  857.     extrn    print_number: near
  858.  
  859. ;-> the unique Ethernet address of the card.  Filled in by the etopen routine.
  860.     extrn    rom_address: byte
  861.  
  862. ;-> current address.  Normally the same as rom_address, unless changed
  863. ;by the set_address() call.
  864.     extrn    my_address: byte
  865.  
  866. address_configuration    dw    ?
  867. resource_configuration    dw    ?
  868.  
  869. is_10base2    db    0
  870. is_10baseT    db    0
  871.  
  872. id_port        dw    110h,0
  873. scratch        dw    0,0        ;for multi-board support
  874. board_number    db    0
  875.  
  876. ;print the character in al.
  877.     extrn    chrout: near
  878.  
  879. ;print a crlf
  880.     extrn    crlf: near
  881.  
  882. ;parse_args is called with si -> first parameter (CR if none).
  883.     public    parse_args
  884. parse_args:
  885. ;exit with nc if all went well, cy otherwise.
  886.     mov    di,offset scratch
  887.     call    get_number        ;also returns number in bx:cx
  888.     jc    pa_ok
  889.     cmp    cx,15            ;board or slot?
  890.     ja    pa_id
  891.     mov    board_number,cl
  892.     jmp    parse_args
  893. pa_id:
  894.     cmp    cx,200h            ;id-port (100-1f0) or io-port (200-3e0) ?
  895.     jae    pa_io
  896.     cmp    cx,100h
  897.     jb    pa_bad
  898.     and    cx,1F0h
  899.     mov    id_port,cx
  900.     jmp    parse_args
  901. pa_io:
  902.     cmp    cx,3E0h
  903.     ja    pa_bad            ; bad value
  904.     and    cx,3F0h
  905.     mov    io_addr,cx
  906.     jmp    parse_args        ; get another arg
  907. pa_ok:
  908.     clc
  909.     ret
  910. pa_bad:
  911.     stc
  912.     ret
  913.  
  914.  
  915.     public    etopen
  916. etopen:
  917. ;initialize the driver.  Fill in rom_address with the assigned address of
  918. ;the board.  Exit with nc if all went well, or cy, dx -> $ terminated error msg.
  919. ;if all is okay,
  920.     cmp    is_186,0        ;this version requires a 186 or better.
  921.     jne    etopen_1
  922.     mov    dx,offset needs_186_msg
  923.     stc
  924.     ret
  925. etopen_1:
  926.  
  927.     cmp    is_386,0        ;can we do a real insd?
  928.     je    etopen_2
  929. ;overlay the repinsd routine with a real "rep insd;nop"
  930.     mov    word ptr repinsd+0,066h+0f3h*256
  931.     mov    word ptr repinsd+2,06dh+090h*256
  932. etopen_2:
  933.  
  934.     cmp    is_eisa,0
  935.     jne    etopen_eisa
  936.     jmp    etopen_isa
  937. etopen_eisa:
  938.     mov    cx,0fh
  939. eisa_search:
  940.     mov    dx,cx            ;move it into the first nibble.
  941.     shl    dx,12
  942.     or    dx,0c80h
  943.     in    ax,dx            ;look for the manufacturer's ID
  944.     cmp    ax,EISA_MANUFACTURER_ID
  945.     jne    eisa_search_1
  946.     inc    dx
  947.     inc    dx
  948.     in    ax,dx            ;look for the product ID
  949.     and    ax,PRODUCT_ID_MASK
  950.     cmp    ax,ISA_PRODUCT_ID
  951.     je    eisa_found
  952. eisa_search_1:
  953.     loop    eisa_search
  954.     jmp    etopen_isa        ;;; if it's not EISA-configured, try ISA.
  955.  
  956. eisa_found:
  957.     and    dx,0f000h
  958.     mov    io_addr,dx
  959.  
  960.     loadport
  961.     setwin    WNO_SETUP
  962.  
  963.     setport    PORT_CfgAddress
  964.     in    ax,dx
  965.     mov    address_configuration,ax
  966.  
  967.     setport    PORT_CfgResource
  968.     in    ax,dx
  969.     mov    resource_configuration,ax
  970.  
  971.     setport    PORT_EECmd
  972.     mov    si,offset read_ee_eisa
  973.     call    read_eaddr
  974.  
  975.     jmp    have_configuration
  976.  
  977. ;---------------------------------------------------------------------------
  978. ; etopen_ISA for multiple 3c509 boards, added 3/93, IJW.
  979. ;
  980. etopen_isa:
  981.     and    id_port,01F0h
  982.     mov    dx,id_port
  983.     xor    bl,bl
  984.  
  985. isa_1:
  986.     cli
  987.     call    write_id_pat
  988.     or    bl,bl            ; first board?
  989.     jnz    isa_2
  990.     mov    al,SET_TAG_REGISTER
  991.     out    dx,al
  992. isa_2:
  993.     mov    al,EE_MANUFACTURER_CODE
  994.     call    read_ee_isa
  995.     cmp    ax,EISA_MANUFACTURER_ID    ; board here ?
  996.     jne    isa_3            ; no
  997.  
  998.     mov    al,EE_OEM_NODE_ADDR_WORD0    ; must read the address..
  999.     call    read_ee_isa            ; else it don't work ?!
  1000.     mov    al,EE_OEM_NODE_ADDR_WORD1    ; address[1]
  1001.     call    read_ee_isa            ; address[2]
  1002.     mov    al,EE_OEM_NODE_ADDR_WORD2
  1003.     call    read_ee_isa            ; address[3]
  1004.  
  1005.     inc    bl            ;count up a board.
  1006.     mov    al,bl
  1007.     or    al,SET_TAG_REGISTER
  1008.     out    dx,al
  1009.     xor    al,al
  1010.     out    dx,al            ; reset
  1011.     sti
  1012.     jmp    isa_1            ; see if any more boards
  1013.  
  1014. isa_3:
  1015.     xor    al,al
  1016.     out    dx,al            ; reset
  1017.     sti
  1018.     or    bl,bl            ; found any boards ?
  1019.     jnz    isa_4
  1020.  
  1021. not_found_isa:
  1022.     mov    dx,offset no_isa_msg
  1023.     stc
  1024.     ret
  1025. isa_multiple:
  1026.     mov    dx,offset multiple_msg
  1027.     stc
  1028.     ret
  1029.  
  1030. isa_4:
  1031.     xor    bl,bl
  1032. isa_5:
  1033.     cli
  1034.     call    write_id_pat
  1035.     inc    bl
  1036.     mov    al,bl
  1037.     add    al,TEST_TAG_REGISTER
  1038.     out    dx,al            ; select the board
  1039.     mov    al,SET_TAG_REGISTER
  1040.     out    dx,al
  1041.     mov    al,EE_MANUFACTURER_CODE
  1042.     call    read_ee_isa
  1043.     cmp    ax,EISA_MANUFACTURER_ID    ; board here ?
  1044.     jne    isa_8
  1045.  
  1046.     cmp    io_addr,0        ; did user give an io_address ?
  1047.     je    isa_6            ; no
  1048.     mov    al,EE_ADDR_CONFIGURATION
  1049.     call    read_ee_isa
  1050.     and    ax,1Fh            ; make real io-address
  1051.     shl    ax,4
  1052.     add    ax,MIN_IO_BASE_ADDR
  1053.     cmp    ax,io_addr        ; this board ?
  1054.     jne    isa_7            ; no
  1055.  
  1056. isa_6:
  1057.     cmp    board_number,0
  1058.     jne    isa_multiple
  1059.     mov    board_number,bl
  1060.  
  1061. isa_7:
  1062.     mov    al,bl
  1063.     add    al,set_tag_register    ; D0
  1064.     out    dx,al
  1065.     xor    al,al            ; reset
  1066.     out    dx,al
  1067.     sti
  1068.     jmp    isa_5            ; find the next board
  1069.  
  1070. isa_8:
  1071.     sti
  1072.     cmp    board_number,0        ; found the board?
  1073.     jne    isa_9            ; yes
  1074.     mov    dx,offset wrong_port_msg
  1075.     stc
  1076.     ret
  1077.  
  1078. isa_9:
  1079.     cli
  1080.     call    write_id_pat
  1081.     mov    al,TEST_TAG_REGISTER
  1082.     add    al,board_number
  1083.     out    dx,al
  1084.     mov    al,SET_TAG_REGISTER
  1085.     out    dx,al
  1086.     mov    al,EE_ADDR_CONFIGURATION
  1087.     call    read_ee_isa
  1088.     mov    address_configuration,ax
  1089.     cmp    io_addr,0        ; know the base address?
  1090.     jne    isa_10            ; yes
  1091.     and    ax,1Fh
  1092.     shl    ax,4
  1093.     add    ax,min_io_base_addr    ; make realworld io addr
  1094.     mov    io_addr,ax
  1095.  
  1096. isa_10:
  1097.     mov    al,EE_RESOURCE_CONFIGURATION
  1098.     call    read_ee_isa
  1099.     mov    resource_configuration,ax
  1100.  
  1101.     mov    si,offset read_ee_isa
  1102.     call    read_eaddr
  1103.  
  1104.     mov    al,SET_TAG_REGISTER
  1105.     or    al,board_number
  1106.     out    dx,al
  1107.     sti
  1108.  
  1109.     cmp    io_addr,3F0h
  1110.     jne    isa_start
  1111.     mov    dx,offset eisa_in_isa_msg
  1112.     stc
  1113.     ret
  1114.  
  1115. isa_start:
  1116.     mov    al,ACTIVATE_VULCAN
  1117.     out    dx,al
  1118.  
  1119. have_configuration:
  1120.     mov    ax,address_configuration
  1121.     and    ax,BNC_XCVR or TP_XCVR or AUI_XCVR    ;include all the bits.
  1122.     cmp    ax,BNC_XCVR        ;does it match BNC?
  1123.     jne    not_10base2
  1124.     inc    is_10base2
  1125. not_10base2:
  1126.     cmp    ax,TP_XCVR        ;does it match TP?
  1127.     jne    not_10baseT
  1128.     inc    is_10baseT
  1129. not_10baseT:
  1130.  
  1131.     mov    bx,resource_configuration
  1132.     mov    cl,12            ;move it over where we need it.
  1133.     shr    bx,cl
  1134.     mov    int_no,bl
  1135.  
  1136.     loadport
  1137.     setwin    WNO_DIAGNOSTICS
  1138.     setport    PORT_MediaStatus
  1139.     in    ax,dx
  1140.     or    ax,MEDIA_LBEATENABLE or MEDIA_JABBERENABLE
  1141.     out    dx,ax
  1142.  
  1143.     setwin    WNO_SETUP        ;select Window 0
  1144.  
  1145.     mov    ax,CMD_TXENABLE        ;Enable the transmitter
  1146.     out    dx,ax
  1147.  
  1148.     mov    ax,CMD_RXENABLE        ;Enable the receiver
  1149.     out    dx,ax
  1150.  
  1151. ;Enable RX Complete interrupts
  1152.     mov    ax,CMD_SETINTMASK + INT_RXCOMPLETE + INT_RXEARLY
  1153.     out    dx,ax
  1154.  
  1155.     mov    ax,CMD_SETRZMASK + 0feh    ;Enable all the status bits.
  1156.     out    dx,ax
  1157.  
  1158.     mov    ax,CMD_SETTXSTART + 0    ;start transmitting after this many bytes.
  1159.     out    dx,ax
  1160.  
  1161.     mov    ax,CMD_SETRXEARLY + 0    ;receive after this many bytes.
  1162.     out    dx,ax
  1163.  
  1164.     cmp    is_10base2,0        ;coax?
  1165.     je    not_10base2_1        ;no.
  1166.     mov    ax,CMD_STARTINTXCVR    ;start internal transciever
  1167.     out    dx,ax
  1168.     call    delay_27_5ms
  1169. not_10base2_1:
  1170.  
  1171.     setport    PORT_CfgControl        ;position to the CCR
  1172.     mov    al,ENABLE_ADAPTER    ;Enable the adapter.
  1173.     out    dx,al
  1174.  
  1175.     call    rcv_mode_3
  1176.  
  1177.     mov    si,offset rom_address    ;set our address.
  1178.     mov    cx,EADDR_LEN
  1179.     call    set_address_4
  1180. ;sets the window to WNO_OPERATING.
  1181.  
  1182.     call    set_recv_isr
  1183.  
  1184.     mov    al, int_no        ; Get board's interrupt vector
  1185.     add    al, 8
  1186.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  1187.     jb    set_int_num        ; No.
  1188.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  1189. set_int_num:
  1190.     xor    ah, ah            ; Clear high byte
  1191.     mov    int_num, ax        ; Set parameter_list int num.
  1192.  
  1193.     clc
  1194.     ret
  1195. ;if we got an error,
  1196.     stc
  1197.     ret
  1198.  
  1199.  
  1200. write_id_pat:
  1201. ;write the 3c509 ID pattern to the ID port.
  1202. ;enter with dx=id_port
  1203.     xor    al,al
  1204.     out    dx,al            ;select the ID port.
  1205.     out    dx,al            ;reset hardware pattern generator
  1206.     mov    cx,0ffh
  1207.     mov    al,0ffh
  1208. write_id_pat_1:
  1209.     out    dx,al            ;keep writing matching values...
  1210.     shl    al,1
  1211.     jnc    write_id_pat_2
  1212.     xor    al,0cfh
  1213. write_id_pat_2:
  1214.     loop    write_id_pat_1
  1215.     ret
  1216.  
  1217. read_eaddr:
  1218. ;enter with dx = eeprom register, si -> routine to read eeprom.
  1219.     push    cs
  1220.     pop    es
  1221.     mov    di,offset rom_address
  1222.  
  1223.     mov    al,EE_TCOM_NODE_ADDR_WORD0    ;read the Ethernet address.
  1224.     call    si
  1225.     xchg    ah,al
  1226.     stosw
  1227.     mov    al,EE_TCOM_NODE_ADDR_WORD1
  1228.     call    si
  1229.     xchg    ah,al
  1230.     stosw
  1231.     mov    al,EE_TCOM_NODE_ADDR_WORD2
  1232.     call    si
  1233.     xchg    ah,al
  1234.     stosw
  1235.     ret
  1236.  
  1237.  
  1238. read_ee_eisa:
  1239. ;enter with al = EEPROM address to read, dx = PORT_EECmd
  1240. ;exit with ax = data.
  1241.     or    al,READ_EEPROM
  1242.     out    dx,al
  1243. read_ee_eisa_1:
  1244.     in    ax,dx
  1245.     test    ax,EE_BUSY
  1246.     jnz    read_ee_eisa_1
  1247.     add    dx,PORT_EEData - PORT_EECmd    ;move to data register.
  1248.     in    ax,dx
  1249.     add    dx,PORT_EECmd - PORT_EEData    ;move back to command register.
  1250.     ret
  1251.  
  1252.  
  1253. read_ee_isa:
  1254. ;enter with al = EEPROM address to read, dx = address of ID port.
  1255. ;exit with ax = data, cx = 0.
  1256.     push    bx
  1257.     or    al,READ_EEPROM
  1258.     out    dx,al
  1259. ;wait 400 us here.
  1260.     call    delay_27_5ms
  1261.     mov    cx,16
  1262. read_ee_isa_1:
  1263.     in    al,dx
  1264.     shr    al,1            ;put it into the carry.
  1265.     rcl    bx,1            ;shift it into bx.
  1266.     loop    read_ee_isa_1
  1267.     mov    ax,bx
  1268.     pop    bx
  1269.     ret
  1270.  
  1271.  
  1272. delay_27_5ms:
  1273. ;delay one timeout period, which is 27.5 ms.
  1274.     mov    ax,1
  1275. delay:
  1276. ;delay AX timeout periods, each of which is 27.5 ms.
  1277.     call    set_timeout
  1278. delay_1:
  1279.     call    do_timeout
  1280.     jnz    delay_1
  1281.     ret
  1282.  
  1283.  
  1284.     public    print_parameters
  1285. print_parameters:
  1286. ;echo our command-line parameters
  1287.     mov    di,offset int_no
  1288.     mov    dx,offset int_no_name
  1289.     call    print_number
  1290.     mov    di,offset io_addr
  1291.     mov    dx,offset io_addr_name
  1292.     call    print_number
  1293.     mov    dx,offset aui_xcvr_msg
  1294.     cmp    is_10base2,0        ;coax?
  1295.     je    print_parameters_1
  1296.     mov    dx,offset bnc_xcvr_msg
  1297. print_parameters_1:
  1298.     cmp    is_10baseT,0        ;tp?
  1299.     je    print_parameters_2
  1300.     mov    dx,offset tp_xcvr_msg
  1301. print_parameters_2:
  1302.     mov    ah,9
  1303.     int    21h
  1304.     mov    di,offset id_port
  1305.     mov    dx,offset id_port_name
  1306.     call    print_number
  1307.     ret
  1308.  
  1309. code    ends
  1310.  
  1311.     end
  1312.