home *** CD-ROM | disk | FTP | other *** search
/ C/C++ User's Journal & Wi…eveloper's Journal Tools / C-C__Users_Journal_and_Windows_Developers_Journal_Tools_1997.iso / gsidemo / 3c509.asm < prev    next >
Encoding:
Assembly Source File  |  1994-10-17  |  35.5 KB  |  1,242 lines

  1. version    equ    4
  2. ;History:1,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.     or        al, al        ; Is there anything on the stack
  423.     jz        nothing_on_stack
  424.     out        dx, al        ; A write clears the entry for the stack
  425. nothing_on_stack:
  426.     setport    PORT_CmdStatus
  427.     test    al,TXS_UNDERRUN or TXS_JABBERERROR    ;do we need to reset transmitter?
  428.     je    send_pkt_0
  429.     push    ax
  430.     mov    ax,CMD_TXRESET
  431.     out    dx,ax
  432.     pop    ax
  433. send_pkt_0:
  434.  
  435.     test    al,TXS_ERRTYPE        ;any errors?
  436.     je    send_pkt_3        ;no.
  437.     call    count_out_err        ;yes, count it.
  438.     mov    ax,CMD_TXENABLE        ;yes, re-enable the transmitter.
  439.     out    dx,ax
  440. send_pkt_3:
  441.  
  442.     mov    bx,cx            ;adjust for the size of the preamble,
  443.     add    bx,4 + 3        ;and round BX up to dword boundary.
  444.     and    bx,not 3
  445.  
  446.     setport    PORT_TxFree        ;wait for enough bytes in transmit buffer.
  447.     mov    ax,18
  448.     call    set_timeout
  449. send_pkt_1:
  450.     in    ax,dx
  451.     cmp    ax,bx
  452.     jae    send_pkt_2
  453.     call    do_timeout
  454.     jne    send_pkt_1
  455.     mov    dh,CANT_SEND        ;timed out, can't send.
  456.     stc
  457.     ret
  458. send_pkt_toobig:
  459.     mov    dh,NO_SPACE
  460.     stc
  461.     ret
  462. send_pkt_2:
  463.     sub    bx,4            ;reduce by the size of the preamble.
  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> [id_port]",CR,LF,'$'
  829.  
  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 id_port
  887.     call    get_number
  888.     clc
  889.     ret
  890.  
  891.  
  892.     public    etopen
  893. etopen:
  894. ;initialize the driver.  Fill in rom_address with the assigned address of
  895. ;the board.  Exit with nc if all went well, or cy, dx -> $ terminated error msg.
  896. ;if all is okay,
  897.     cmp    is_186,0        ;this version requires a 186 or better.
  898.     jne    etopen_1
  899.     mov    dx,offset needs_186_msg
  900.     stc
  901.     ret
  902. etopen_1:
  903.  
  904.     cmp    is_386,0        ;can we do a real insd?
  905.     je    etopen_2
  906. ;overlay the repinsd routine with a real "rep insd;nop"
  907.     mov    word ptr repinsd+0,066h+0f3h*256
  908.     mov    word ptr repinsd+2,06dh+090h*256
  909. etopen_2:
  910.  
  911.     cmp    is_eisa,0
  912.     jne    etopen_eisa
  913.     jmp    etopen_isa
  914. etopen_eisa:
  915.     mov    cx,0fh
  916. eisa_search:
  917.     mov    dx,cx            ;move it into the first nibble.
  918.     shl    dx,12
  919.     or    dx,0c80h
  920.     in    ax,dx            ;look for the manufacturer's ID
  921.     cmp    ax,EISA_MANUFACTURER_ID
  922.     jne    eisa_search_1
  923.     inc    dx
  924.     inc    dx
  925.     in    ax,dx            ;look for the product ID
  926.     and    ax,PRODUCT_ID_MASK
  927.     cmp    ax,ISA_PRODUCT_ID
  928.     je    eisa_found
  929. eisa_search_1:
  930.     loop    eisa_search
  931.     jmp    etopen_isa        ;;; if it's not EISA-configured, try ISA.
  932.  
  933. eisa_found:
  934.     and    dx,0f000h
  935.     mov    io_addr,dx
  936.  
  937.     loadport
  938.     setwin    WNO_SETUP
  939.  
  940.     setport    PORT_CfgAddress
  941.     in    ax,dx
  942.     mov    address_configuration,ax
  943.  
  944.     setport    PORT_CfgResource
  945.     in    ax,dx
  946.     mov    resource_configuration,ax
  947.  
  948.     setport    PORT_EECmd
  949.     mov    si,offset read_ee_eisa
  950.     call    read_eaddr
  951.  
  952.     jmp    have_configuration
  953.  
  954. etopen_isa:
  955.     and    id_port,01f0h        ;isolate only the bits we can use.
  956.     call    write_id_pat
  957.  
  958.     mov    al,ID_GLOBAL_RESET    ;reset the adapter.
  959.     out    dx,al
  960.     call    delay_27_5ms        ;wait for 310 us.
  961.  
  962.     call    write_id_pat
  963.  
  964.     mov    al,SET_TAG_REGISTER
  965.     out    dx,al
  966.  
  967.     push    dx
  968.     mov    dx,offset reading_msg
  969.     mov    ah,9
  970.     int    21h
  971.     pop    dx
  972.  
  973.     xor    al,al
  974.     xor    di,di
  975.     mov    cx,16
  976. read_isa_checksum:
  977.     push    ax
  978.     push    cx
  979.     call    read_ee_isa
  980.     mov    bx,ax
  981.     mov    al,'.'
  982.     call    chrout
  983.     pop    cx
  984.     pop    ax
  985.     cmp    al,3
  986.     jne    read_isa_checksum_not_3
  987.     push    bx
  988.     and    bx,0f0ffh
  989.     cmp    bx,09050h
  990.     pop    bx
  991.     jne    not_found_isa
  992. read_isa_checksum_not_3:
  993.     cmp    al,7
  994.     jne    read_isa_checksum_not_7
  995.     cmp    bx,6d50h
  996.     jne    not_found_isa
  997. read_isa_checksum_not_7:
  998.     cmp    al,8
  999.     je    read_isa_checksum_1
  1000.     cmp    al,9
  1001.     je    read_isa_checksum_1
  1002.     cmp    al,0dh
  1003.     je    read_isa_checksum_1
  1004.     cmp    al,0fh            ;if it's the checksum itself, just xor.
  1005.     je    read_isa_checksum_2
  1006.     xor    bh,bl            ;accumulate checksum in high byte.
  1007.     xor    bl,bl            ;leave low byte alone.
  1008.     jmp    short read_isa_checksum_2
  1009. read_isa_checksum_1:
  1010.     xor    bl,bh            ;accumulate checksum in low byte.
  1011.     xor    bh,bh            ;leave high byte alone.
  1012. read_isa_checksum_2:
  1013.     xor    di,bx            ;include previous checksum.
  1014.  
  1015.     inc    al            ;and go to the next register.
  1016.     loop    read_isa_checksum
  1017.  
  1018.     call    crlf
  1019.  
  1020.     or    di,di            ;did the checksum compare?
  1021.     je    found_isa        ;yes.
  1022. not_found_isa:
  1023.     mov    dx,offset no_isa_msg
  1024.     stc
  1025.     ret
  1026.  
  1027. found_isa:
  1028.     mov    si,offset read_ee_isa
  1029.     call    read_eaddr
  1030.  
  1031.     mov    al,EE_ADDR_CONFIGURATION
  1032.     call    read_ee_isa
  1033.     mov    address_configuration,ax
  1034.  
  1035.     mov    al,EE_RESOURCE_CONFIGURATION
  1036.     call    read_ee_isa
  1037.     mov    resource_configuration,ax
  1038.  
  1039.     mov    al,ACTIVATE_VULCAN
  1040.     out    dx,al
  1041.  
  1042.     mov    ax,address_configuration
  1043.     and    ax,1fh
  1044.     mov    cl,4
  1045.     shl    ax,cl
  1046.     add    ax,MIN_IO_BASE_ADDR
  1047.     mov    io_addr,ax
  1048.  
  1049. have_configuration:
  1050.     mov    ax,address_configuration
  1051.     and    ax,BNC_XCVR or TP_XCVR or AUI_XCVR    ;include all the bits.
  1052.     cmp    ax,BNC_XCVR        ;does it match BNC?
  1053.     jne    not_10base2
  1054.     inc    is_10base2
  1055. not_10base2:
  1056.     cmp    ax,TP_XCVR        ;does it match TP?
  1057.     jne    not_10baseT
  1058.     inc    is_10baseT
  1059. not_10baseT:
  1060.  
  1061.     mov    bx,resource_configuration
  1062.     mov    cl,12            ;move it over where we need it.
  1063.     shr    bx,cl
  1064.     mov    int_no,bl
  1065.  
  1066.     loadport
  1067.     setwin    WNO_DIAGNOSTICS
  1068.     setport    PORT_MediaStatus
  1069.     in    ax,dx
  1070.     or    ax,MEDIA_LBEATENABLE or MEDIA_JABBERENABLE
  1071.     out    dx,ax
  1072.  
  1073.     setwin    WNO_SETUP        ;select Window 0
  1074.  
  1075.     mov    ax,CMD_TXENABLE        ;Enable the transmitter
  1076.     out    dx,ax
  1077.  
  1078.     mov    ax,CMD_RXENABLE        ;Enable the receiver
  1079.     out    dx,ax
  1080.  
  1081. ;Enable RX Complete interrupts
  1082.     mov    ax,CMD_SETINTMASK + INT_RXCOMPLETE + INT_RXEARLY
  1083.     out    dx,ax
  1084.  
  1085.     mov    ax,CMD_SETRZMASK + 0feh    ;Enable all the status bits.
  1086.     out    dx,ax
  1087.  
  1088.     mov    ax,CMD_SETTXSTART + 0    ;start transmitting after this many bytes.
  1089.     out    dx,ax
  1090.  
  1091.     mov    ax,CMD_SETRXEARLY + 0    ;receive after this many bytes.
  1092.     out    dx,ax
  1093.  
  1094.     cmp    is_10base2,0        ;coax?
  1095.     je    not_10base2_1        ;no.
  1096.     mov    ax,CMD_STARTINTXCVR    ;start internal transciever
  1097.     out    dx,ax
  1098.     call    delay_27_5ms
  1099. not_10base2_1:
  1100.  
  1101.     setport    PORT_CfgControl        ;position to the CCR
  1102.     mov    al,ENABLE_ADAPTER    ;Enable the adapter.
  1103.     out    dx,al
  1104.  
  1105.     call    rcv_mode_3
  1106.  
  1107.     mov    si,offset rom_address    ;set our address.
  1108.     mov    cx,EADDR_LEN
  1109.     call    set_address_4
  1110. ;sets the window to WNO_OPERATING.
  1111.  
  1112.     call    set_recv_isr
  1113.  
  1114.     mov    al, int_no        ; Get board's interrupt vector
  1115.     add    al, 8
  1116.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  1117.     jb    set_int_num        ; No.
  1118.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  1119. set_int_num:
  1120.     xor    ah, ah            ; Clear high byte
  1121.     mov    int_num, ax        ; Set parameter_list int num.
  1122.  
  1123.     clc
  1124.     ret
  1125. ;if we got an error,
  1126.     stc
  1127.     ret
  1128.  
  1129.  
  1130. write_id_pat:
  1131. ;write the 3c509 ID pattern to the ID port.
  1132.     mov    dx,id_port
  1133.     xor    al,al
  1134.     out    dx,al            ;select the ID port.
  1135.     out    dx,al            ;reset hardware pattern generator
  1136.     mov    cx,0ffh
  1137.     mov    al,0ffh
  1138. write_id_pat_1:
  1139.     out    dx,al            ;keep writing matching values...
  1140.     shl    al,1
  1141.     jnc    write_id_pat_2
  1142.     xor    al,0cfh
  1143. write_id_pat_2:
  1144.     loop    write_id_pat_1
  1145.     ret
  1146.  
  1147. read_eaddr:
  1148. ;enter with dx = eeprom register, si -> routine to read eeprom.
  1149.     push    cs
  1150.     pop    es
  1151.     mov    di,offset rom_address
  1152.  
  1153.     mov    al,EE_TCOM_NODE_ADDR_WORD0    ;read the Ethernet address.
  1154.     call    si
  1155.     xchg    ah,al
  1156.     stosw
  1157.     mov    al,EE_TCOM_NODE_ADDR_WORD1
  1158.     call    si
  1159.     xchg    ah,al
  1160.     stosw
  1161.     mov    al,EE_TCOM_NODE_ADDR_WORD2
  1162.     call    si
  1163.     xchg    ah,al
  1164.     stosw
  1165.     ret
  1166.  
  1167.  
  1168. read_ee_eisa:
  1169. ;enter with al = EEPROM address to read, dx = PORT_EECmd
  1170. ;exit with ax = data.
  1171.     or    al,READ_EEPROM
  1172.     out    dx,al
  1173. read_ee_eisa_1:
  1174.     in    ax,dx
  1175.     test    ax,EE_BUSY
  1176.     jnz    read_ee_eisa_1
  1177.     add    dx,PORT_EEData - PORT_EECmd    ;move to data register.
  1178.     in    ax,dx
  1179.     add    dx,PORT_EECmd - PORT_EEData    ;move back to command register.
  1180.     ret
  1181.  
  1182.  
  1183. read_ee_isa:
  1184. ;enter with al = EEPROM address to read, dx = address of ID port.
  1185. ;exit with ax = data, cx = 0.
  1186.     push    bx
  1187.     or    al,READ_EEPROM
  1188.     out    dx,al
  1189. ;wait 400 us here.
  1190.     call    delay_27_5ms
  1191.     mov    cx,16
  1192. read_ee_isa_1:
  1193.     in    al,dx
  1194.     shr    al,1            ;put it into the carry.
  1195.     rcl    bx,1            ;shift it into bx.
  1196.     loop    read_ee_isa_1
  1197.     mov    ax,bx
  1198.     pop    bx
  1199.     ret
  1200.  
  1201.  
  1202. delay_27_5ms:
  1203. ;delay one timeout period, which is 27.5 ms.
  1204.     mov    ax,1
  1205. delay:
  1206. ;delay AX timeout periods, each of which is 27.5 ms.
  1207.     call    set_timeout
  1208. delay_1:
  1209.     call    do_timeout
  1210.     jnz    delay_1
  1211.     ret
  1212.  
  1213.  
  1214.     public    print_parameters
  1215. print_parameters:
  1216. ;echo our command-line parameters
  1217.     mov    di,offset int_no
  1218.     mov    dx,offset int_no_name
  1219.     call    print_number
  1220.     mov    di,offset io_addr
  1221.     mov    dx,offset io_addr_name
  1222.     call    print_number
  1223.     mov    dx,offset aui_xcvr_msg
  1224.     cmp    is_10base2,0        ;coax?
  1225.     je    print_parameters_1
  1226.     mov    dx,offset bnc_xcvr_msg
  1227. print_parameters_1:
  1228.     cmp    is_10baseT,0        ;tp?
  1229.     je    print_parameters_2
  1230.     mov    dx,offset tp_xcvr_msg
  1231. print_parameters_2:
  1232.     mov    ah,9
  1233.     int    21h
  1234.     mov    di,offset id_port
  1235.     mov    dx,offset id_port_name
  1236.     call    print_number
  1237.     ret
  1238.  
  1239. code    ends
  1240.  
  1241.     end
  1242.