home *** CD-ROM | disk | FTP | other *** search
/ Shareware Supreme Volume 6 #1 / swsii.zip / swsii / 426 / 3C509A.ZIP / 3C509.ASM next >
Assembly Source File  |  1993-02-16  |  35KB  |  1,204 lines

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