Rev 5522 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5522 | Rev 9188 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2021. All rights reserved. ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
5 | ;; ;; |
5 | ;; ;; |
6 | ;; 3Com network driver for KolibriOS ;; |
6 | ;; 3Com network driver for KolibriOS ;; |
7 | ;; ;; |
7 | ;; ;; |
8 | ;; Ported to KolibriOS net-branch by hidnplayr ;; |
8 | ;; Ported to KolibriOS net-branch by hidnplayr ;; |
9 | ;; ;; |
9 | ;; ;; |
10 | ;; Thanks to: scrap metal recyclers, whom provide me with ;; |
10 | ;; Thanks to: scrap metal recyclers, whom provide me with ;; |
11 | ;; loads of hardware ;; |
11 | ;; loads of hardware ;; |
12 | ;; diamond: who makes me understand KolibriOS ;; |
12 | ;; diamond: who makes me understand KolibriOS ;; |
13 | ;; ;; |
13 | ;; ;; |
14 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
14 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
15 | ;; |
15 | ;; |
16 | ;; Original copyright from menuetos driver: |
16 | ;; Original copyright from menuetos driver: |
17 | ;; |
17 | ;; |
18 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
18 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
19 | ;; ;; |
19 | ;; ;; |
20 | ;; 3C59X.INC ;; |
20 | ;; 3C59X.INC ;; |
21 | ;; ;; |
21 | ;; ;; |
22 | ;; Ethernet driver for Menuet OS ;; |
22 | ;; Ethernet driver for Menuet OS ;; |
23 | ;; ;; |
23 | ;; ;; |
24 | ;; Driver for 3Com fast etherlink 3c59x and ;; |
24 | ;; Driver for 3Com fast etherlink 3c59x and ;; |
25 | ;; etherlink XL 3c900 and 3c905 cards ;; |
25 | ;; etherlink XL 3c900 and 3c905 cards ;; |
26 | ;; References: ;; |
26 | ;; References: ;; |
27 | ;; www.3Com.com - data sheets ;; |
27 | ;; www.3Com.com - data sheets ;; |
28 | ;; DP83840A.pdf - ethernet physical layer ;; |
28 | ;; DP83840A.pdf - ethernet physical layer ;; |
29 | ;; 3c59x.c - linux driver ;; |
29 | ;; 3c59x.c - linux driver ;; |
30 | ;; ethernet driver template by Mike Hibbett ;; |
30 | ;; ethernet driver template by Mike Hibbett ;; |
31 | ;; ;; |
31 | ;; ;; |
32 | ;; Credits ;; |
32 | ;; Credits ;; |
33 | ;; Mike Hibbett, ;; |
33 | ;; Mike Hibbett, ;; |
34 | ;; who kindly supplied me with a 3Com905C-TX-M card ;; |
34 | ;; who kindly supplied me with a 3Com905C-TX-M card ;; |
35 | ;; ;; |
35 | ;; ;; |
36 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
36 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
37 | ;; |
37 | ;; |
38 | ;; Copyright (c) 2004, Endre Kozma |
38 | ;; Copyright (c) 2004, Endre Kozma |
39 | ;; All rights reserved. |
39 | ;; All rights reserved. |
40 | ;; |
40 | ;; |
41 | ;; Redistribution and use in source and binary forms, with or without |
41 | ;; Redistribution and use in source and binary forms, with or without |
42 | ;; modification, are permitted provided that the following conditions are |
42 | ;; modification, are permitted provided that the following conditions are |
43 | ;; met: |
43 | ;; met: |
44 | ;; |
44 | ;; |
45 | ;; 1. Redistributions of source code must retain the above copyright notice, |
45 | ;; 1. Redistributions of source code must retain the above copyright notice, |
46 | ;; this list of conditions and the following disclaimer. |
46 | ;; this list of conditions and the following disclaimer. |
47 | ;; |
47 | ;; |
48 | ;; 2. Redistributions in binary form must reproduce the above copyright |
48 | ;; 2. Redistributions in binary form must reproduce the above copyright |
49 | ;; notice, this list of conditions and the following disclaimer in the |
49 | ;; notice, this list of conditions and the following disclaimer in the |
50 | ;; documentation and/or other materials provided with the distribution. |
50 | ;; documentation and/or other materials provided with the distribution. |
51 | ;; |
51 | ;; |
52 | ;; 3. The name of the author may not be used to endorse or promote products |
52 | ;; 3. The name of the author may not be used to endorse or promote products |
53 | ;; derived from this software without specific prior written permission. |
53 | ;; derived from this software without specific prior written permission. |
54 | ;; |
54 | ;; |
55 | ;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
55 | ;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
56 | ;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
56 | ;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
57 | ;; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
57 | ;; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
58 | ;; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
58 | ;; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
59 | ;; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
59 | ;; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
60 | ;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
60 | ;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
61 | ;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
61 | ;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
62 | ;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
62 | ;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
63 | ;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
63 | ;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
64 | ;; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
64 | ;; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
65 | ;; |
65 | ;; |
66 | ;; History |
66 | ;; History |
67 | ;; ======= |
67 | ;; ======= |
68 | ;; $Log: 3C59X.INC,v $ |
68 | ;; $Log: 3C59X.INC,v $ |
69 | ;; Revision 1.3 2004/07/11 12:21:12 kozma |
69 | ;; Revision 1.3 2004/07/11 12:21:12 kozma |
70 | ;; Support of vortex chips (3c59x) added. |
70 | ;; Support of vortex chips (3c59x) added. |
71 | ;; Support of 3c920 and 3c982 added. |
71 | ;; Support of 3c920 and 3c982 added. |
72 | ;; Corrections. |
72 | ;; Corrections. |
73 | ;; |
73 | ;; |
74 | ;; Revision 1.2 2004/06/12 19:40:20 kozma |
74 | ;; Revision 1.2 2004/06/12 19:40:20 kozma |
75 | ;; Function e3c59x_set_available_media added in order to set |
75 | ;; Function e3c59x_set_available_media added in order to set |
76 | ;; the default media in case auto detection finds no valid link. |
76 | ;; the default media in case auto detection finds no valid link. |
77 | ;; Incorrect mii check removed (3c900 Cyclone works now). |
77 | ;; Incorrect mii check removed (3c900 Cyclone works now). |
78 | ;; Cleanups. |
78 | ;; Cleanups. |
79 | ;; |
79 | ;; |
80 | ;; Revision 1.1 2004/06/12 18:27:15 kozma |
80 | ;; Revision 1.1 2004/06/12 18:27:15 kozma |
81 | ;; Initial revision |
81 | ;; Initial revision |
82 | ;; |
82 | ;; |
83 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
83 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
84 | 84 | ||
85 | 85 | ||
86 | format PE DLL native |
86 | format PE DLL native |
87 | entry START |
87 | entry START |
88 | 88 | ||
89 | CURRENT_API = 0x0200 |
89 | CURRENT_API = 0x0200 |
90 | COMPATIBLE_API = 0x0100 |
90 | COMPATIBLE_API = 0x0100 |
91 | API_VERSION = (COMPATIBLE_API shl 16) + CURRENT_API |
91 | API_VERSION = (COMPATIBLE_API shl 16) + CURRENT_API |
- | 92 | ||
- | 93 | ; configureable area |
|
92 | 94 | ||
- | 95 | MAX_DEVICES = 16 ; Maximum number of devices this driver may handle |
|
93 | MAX_DEVICES = 16 |
96 | |
94 | FORCE_FD = 0 ; forcing full duplex mode makes sense at some cards and link types |
97 | FORCE_FD = 0 ; forcing full duplex mode makes sense at some cards and link types |
95 | 98 | ||
96 | NUM_RX_DESC = 4 ; a power of 2 number |
99 | NUM_RX_DESC = 32 ; Number of receive descriptors (must be power of 2) |
97 | NUM_TX_DESC = 4 ; a power of 2 number |
100 | NUM_TX_DESC = 16 ; Number of transmit descriptors (must be power of 2) |
- | 101 | ||
- | 102 | __DEBUG__ = 1 ; 1 = on, 0 = off |
|
98 | 103 | __DEBUG_LEVEL__ = 2 ; 1 = verbose, 2 = errors only |
|
99 | __DEBUG__ = 1 |
104 | |
100 | __DEBUG_LEVEL__ = 2 ; 1 = verbose, 2 = errors only |
105 | ; end configureable area |
101 | 106 | ||
102 | section '.flat' readable writable executable |
107 | section '.flat' readable writable executable |
103 | 108 | ||
104 | include '../proc32.inc' |
109 | include '../proc32.inc' |
105 | include '../struct.inc' |
110 | include '../struct.inc' |
106 | include '../macros.inc' |
111 | include '../macros.inc' |
107 | include '../fdo.inc' |
112 | include '../fdo.inc' |
108 | include '../netdrv.inc' |
113 | include '../netdrv.inc' |
- | 114 | ||
- | 115 | ||
- | 116 | if (bsr NUM_RX_DESC)>(bsf NUM_RX_DESC) |
|
- | 117 | display 'NUM_RX_DESC must be a power of two' |
|
- | 118 | err |
|
- | 119 | end if |
|
- | 120 | ||
- | 121 | if (bsr NUM_TX_DESC)>(bsf NUM_TX_DESC) |
|
- | 122 | display 'NUM_TX_DESC must be a power of two' |
|
- | 123 | err |
|
- | 124 | end if |
|
109 | 125 | ||
110 | ; Registers |
126 | ; Registers |
111 | REG_POWER_MGMT_CTRL = 0x7c |
127 | REG_POWER_MGMT_CTRL = 0x7c |
112 | REG_UP_LIST_PTR = 0x38 |
128 | REG_UP_LIST_PTR = 0x38 |
113 | REG_UP_PKT_STATUS = 0x30 |
129 | REG_UP_PKT_STATUS = 0x30 |
114 | REG_TX_FREE_THRESH = 0x2f |
130 | REG_TX_FREE_THRESH = 0x2f |
115 | REG_DN_LIST_PTR = 0x24 |
131 | REG_DN_LIST_PTR = 0x24 |
116 | REG_DMA_CTRL = 0x20 |
132 | REG_DMA_CTRL = 0x20 |
117 | REG_TX_STATUS = 0x1b |
133 | REG_TX_STATUS = 0x1b |
118 | REG_RX_STATUS = 0x18 |
134 | REG_RX_STATUS = 0x18 |
119 | REG_TX_DATA = 0x10 |
135 | REG_TX_DATA = 0x10 |
120 | 136 | ||
121 | ; Common window registers |
137 | ; Common window registers |
122 | REG_INT_STATUS = 0xe |
138 | REG_INT_STATUS = 0xe |
123 | REG_COMMAND = 0xe |
139 | REG_COMMAND = 0xe |
124 | 140 | ||
125 | ; Register window 7 |
141 | ; Register window 7 |
126 | REG_MASTER_STATUS = 0xc |
142 | REG_MASTER_STATUS = 0xc |
127 | REG_POWER_MGMT_EVENT = 0xc |
143 | REG_POWER_MGMT_EVENT = 0xc |
128 | REG_MASTER_LEN = 0x6 |
144 | REG_MASTER_LEN = 0x6 |
129 | REG_VLAN_ETHER_TYPE = 0x4 |
145 | REG_VLAN_ETHER_TYPE = 0x4 |
130 | REG_VLAN_MASK = 0x0 |
146 | REG_VLAN_MASK = 0x0 |
131 | REG_MASTER_ADDRESS = 0x0 |
147 | REG_MASTER_ADDRESS = 0x0 |
132 | 148 | ||
133 | ; Register window 6 |
149 | ; Register window 6 |
134 | REG_BYTES_XMITTED_OK = 0xc |
150 | REG_BYTES_XMITTED_OK = 0xc |
135 | REG_BYTES_RCVD_OK = 0xa |
151 | REG_BYTES_RCVD_OK = 0xa |
136 | REG_UPPER_FRAMES_OK = 0x9 |
152 | REG_UPPER_FRAMES_OK = 0x9 |
137 | REG_FRAMES_DEFERRED = 0x8 |
153 | REG_FRAMES_DEFERRED = 0x8 |
138 | REG_FRAMES_RCVD_OK = 0x7 |
154 | REG_FRAMES_RCVD_OK = 0x7 |
139 | REG_FRAMES_XMITTED_OK = 0x6 |
155 | REG_FRAMES_XMITTED_OK = 0x6 |
140 | REG_RX_OVERRUNS = 0x5 |
156 | REG_RX_OVERRUNS = 0x5 |
141 | REG_LATE_COLLISIONS = 0x4 |
157 | REG_LATE_COLLISIONS = 0x4 |
142 | REG_SINGLE_COLLISIONS = 0x3 |
158 | REG_SINGLE_COLLISIONS = 0x3 |
143 | REG_MULTIPLE_COLLISIONS = 0x2 |
159 | REG_MULTIPLE_COLLISIONS = 0x2 |
144 | REG_SQE_ERRORS = 0x1 |
160 | REG_SQE_ERRORS = 0x1 |
145 | REG_CARRIER_LOST = 0x0 |
161 | REG_CARRIER_LOST = 0x0 |
146 | 162 | ||
147 | ; Register window 5 |
163 | ; Register window 5 |
148 | REG_INDICATION_ENABLE = 0xc |
164 | REG_INDICATION_ENABLE = 0xc |
149 | REG_INTERRUPT_ENABLE = 0xa |
165 | REG_INTERRUPT_ENABLE = 0xa |
150 | REG_TX_RECLAIM_THRESH = 0x9 |
166 | REG_TX_RECLAIM_THRESH = 0x9 |
151 | REG_RX_FILTER = 0x8 |
167 | REG_RX_FILTER = 0x8 |
152 | REG_RX_EARLY_THRESH = 0x6 |
168 | REG_RX_EARLY_THRESH = 0x6 |
153 | REG_TX_START_THRESH = 0x0 |
169 | REG_TX_START_THRESH = 0x0 |
154 | 170 | ||
155 | ; Register window 4 |
171 | ; Register window 4 |
156 | REG_UPPER_BYTES_OK = 0xe |
172 | REG_UPPER_BYTES_OK = 0xe |
157 | REG_BAD_SSD = 0xc |
173 | REG_BAD_SSD = 0xc |
158 | REG_MEDIA_STATUS = 0xa |
174 | REG_MEDIA_STATUS = 0xa |
159 | REG_PHYSICAL_MGMT = 0x8 |
175 | REG_PHYSICAL_MGMT = 0x8 |
160 | REG_NETWORK_DIAGNOSTIC = 0x6 |
176 | REG_NETWORK_DIAGNOSTIC = 0x6 |
161 | REG_FIFO_DIAGNOSTIC = 0x4 |
177 | REG_FIFO_DIAGNOSTIC = 0x4 |
162 | REG_VCO_DIAGNOSTIC = 0x2 ; may not supported |
178 | REG_VCO_DIAGNOSTIC = 0x2 ; may not supported |
163 | 179 | ||
164 | ; Bits in register window 4 |
180 | ; Bits in register window 4 |
165 | BIT_AUTOSELECT = 24 |
181 | BIT_AUTOSELECT = 24 |
166 | 182 | ||
167 | ; Register window 3 |
183 | ; Register window 3 |
168 | REG_TX_FREE = 0xc |
184 | REG_TX_FREE = 0xc |
169 | REG_RX_FREE = 0xa |
185 | REG_RX_FREE = 0xa |
170 | REG_MEDIA_OPTIONS = 0x8 |
186 | REG_MEDIA_OPTIONS = 0x8 |
171 | REG_MAC_CONTROL = 0x6 |
187 | REG_MAC_CONTROL = 0x6 |
172 | REG_MAX_PKT_SIZE = 0x4 |
188 | REG_MAX_PKT_SIZE = 0x4 |
173 | REG_INTERNAL_CONFIG = 0x0 |
189 | REG_INTERNAL_CONFIG = 0x0 |
174 | 190 | ||
175 | ; Register window 2 |
191 | ; Register window 2 |
176 | REG_RESET_OPTIONS = 0xc |
192 | REG_RESET_OPTIONS = 0xc |
177 | REG_STATION_MASK_HI = 0xa |
193 | REG_STATION_MASK_HI = 0xa |
178 | REG_STATION_MASK_MID = 0x8 |
194 | REG_STATION_MASK_MID = 0x8 |
179 | REG_STATION_MASK_LO = 0x6 |
195 | REG_STATION_MASK_LO = 0x6 |
180 | REG_STATION_ADDRESS_HI = 0x4 |
196 | REG_STATION_ADDRESS_HI = 0x4 |
181 | REG_STATION_ADDRESS_MID = 0x2 |
197 | REG_STATION_ADDRESS_MID = 0x2 |
182 | REG_STATION_ADDRESS_LO = 0x0 |
198 | REG_STATION_ADDRESS_LO = 0x0 |
183 | 199 | ||
184 | ; Register window 1 |
200 | ; Register window 1 |
185 | REG_TRIGGER_BITS = 0xc |
201 | REG_TRIGGER_BITS = 0xc |
186 | REG_SOS_BITS = 0xa |
202 | REG_SOS_BITS = 0xa |
187 | REG_WAKE_ON_TIMER = 0x8 |
203 | REG_WAKE_ON_TIMER = 0x8 |
188 | REG_SMB_RXBYTES = 0x7 |
204 | REG_SMB_RXBYTES = 0x7 |
189 | REG_SMB_DIAG = 0x5 |
205 | REG_SMB_DIAG = 0x5 |
190 | REG_SMB_ARB = 0x4 |
206 | REG_SMB_ARB = 0x4 |
191 | REG_SMB_STATUS = 0x2 |
207 | REG_SMB_STATUS = 0x2 |
192 | REG_SMB_ADDRESS = 0x1 |
208 | REG_SMB_ADDRESS = 0x1 |
193 | REG_SMB_FIFO_DATA = 0x0 |
209 | REG_SMB_FIFO_DATA = 0x0 |
194 | 210 | ||
195 | ; Register window 0 |
211 | ; Register window 0 |
196 | REG_EEPROM_DATA = 0xc |
212 | REG_EEPROM_DATA = 0xc |
197 | REG_EEPROM_COMMAND = 0xa |
213 | REG_EEPROM_COMMAND = 0xa |
198 | REG_BIOS_ROM_DATA = 0x8 |
214 | REG_BIOS_ROM_DATA = 0x8 |
199 | REG_BIOS_ROM_ADDR = 0x4 |
215 | REG_BIOS_ROM_ADDR = 0x4 |
200 | 216 | ||
201 | ; Physical management bits |
217 | ; Physical management bits |
202 | BIT_MGMT_DIR = 2 ; drive with the data written in mgmtData |
218 | BIT_MGMT_DIR = 2 ; drive with the data written in mgmtData |
203 | BIT_MGMT_DATA = 1 ; MII management data bit |
219 | BIT_MGMT_DATA = 1 ; MII management data bit |
204 | BIT_MGMT_CLK = 0 ; MII management clock |
220 | BIT_MGMT_CLK = 0 ; MII management clock |
205 | 221 | ||
206 | ; MII commands |
222 | ; MII commands |
207 | MII_CMD_MASK = (1111b shl 10) |
223 | MII_CMD_MASK = (1111b shl 10) |
208 | MII_CMD_READ = (0110b shl 10) |
224 | MII_CMD_READ = (0110b shl 10) |
209 | MII_CMD_WRITE = (0101b shl 10) |
225 | MII_CMD_WRITE = (0101b shl 10) |
210 | 226 | ||
211 | ; eeprom bits and commands |
227 | ; eeprom bits and commands |
212 | EEPROM_CMD_READ = 0x80 |
228 | EEPROM_CMD_READ = 0x80 |
213 | EEPROM_BIT_BUSY = 15 |
229 | EEPROM_BIT_BUSY = 15 |
214 | 230 | ||
215 | ; eeprom registers |
231 | ; eeprom registers |
216 | EEPROM_REG_OEM_NODE_ADDR= 0xa |
232 | EEPROM_REG_OEM_NODE_ADDR= 0xa |
217 | EEPROM_REG_CAPABILITIES = 0x10 |
233 | EEPROM_REG_CAPABILITIES = 0x10 |
218 | 234 | ||
219 | ; Commands for command register |
235 | ; Commands for command register |
220 | SELECT_REGISTER_WINDOW = (1 shl 11) |
236 | SELECT_REGISTER_WINDOW = (1 shl 11) |
221 | 237 | ||
222 | ; Hw capabilities bitflags |
238 | ; Hw capabilities bitflags |
223 | IS_VORTEX = 0x0001 |
239 | IS_VORTEX = 0x0001 |
224 | IS_BOOMERANG = 0x0002 |
240 | IS_BOOMERANG = 0x0002 |
225 | IS_CYCLONE = 0x0004 |
241 | IS_CYCLONE = 0x0004 |
226 | IS_TORNADO = 0x0008 |
242 | IS_TORNADO = 0x0008 |
227 | EEPROM_8BIT = 0x0010 |
243 | EEPROM_8BIT = 0x0010 |
228 | HAS_PWR_CTRL = 0x0020 |
244 | HAS_PWR_CTRL = 0x0020 |
229 | HAS_MII = 0x0040 |
245 | HAS_MII = 0x0040 |
230 | HAS_NWAY = 0x0080 |
246 | HAS_NWAY = 0x0080 |
231 | HAS_CB_FNS = 0x0100 |
247 | HAS_CB_FNS = 0x0100 |
232 | INVERT_MII_PWR = 0x0200 |
248 | INVERT_MII_PWR = 0x0200 |
233 | INVERT_LED_PWR = 0x0400 |
249 | INVERT_LED_PWR = 0x0400 |
234 | MAX_COLLISION_RESET = 0x0800 |
250 | MAX_COLLISION_RESET = 0x0800 |
235 | EEPROM_OFFSET = 0x1000 |
251 | EEPROM_OFFSET = 0x1000 |
236 | HAS_HWCKSM = 0x2000 |
252 | HAS_HWCKSM = 0x2000 |
237 | EXTRA_PREAMBLE = 0x4000 |
253 | EXTRA_PREAMBLE = 0x4000 |
238 | 254 | ||
239 | ; Status |
255 | ; Status |
240 | IntLatch = 0x0001 |
256 | IntLatch = 0x0001 |
241 | HostError = 0x0002 |
257 | HostError = 0x0002 |
242 | TxComplete = 0x0004 |
258 | TxComplete = 0x0004 |
243 | TxAvailable = 0x0008 |
259 | TxAvailable = 0x0008 |
244 | RxComplete = 0x0010 |
260 | RxComplete = 0x0010 |
245 | RxEarly = 0x0020 |
261 | RxEarly = 0x0020 |
246 | IntReq = 0x0040 |
262 | IntReq = 0x0040 |
247 | StatsFull = 0x0080 |
263 | StatsFull = 0x0080 |
248 | DMADone = 0x0100 |
264 | DMADone = 0x0100 |
249 | DownComplete = 0x0200 |
265 | DownComplete = 0x0200 |
250 | UpComplete = 0x0400 |
266 | UpComplete = 0x0400 |
251 | DMAInProgress = 0x0800 ; 1 shl 11 (DMA controller is still busy) |
267 | DMAInProgress = 0x0800 ; 1 shl 11 (DMA controller is still busy) |
252 | CmdInProgress = 0x1000 ; 1 shl 12 (EL3_CMD is still busy) |
268 | CmdInProgress = 0x1000 ; 1 shl 12 (EL3_CMD is still busy) |
253 | 269 | ||
254 | S_5_INTS = HostError + RxEarly + UpComplete + DownComplete + StatsFull ;+ TxComplete + RxComplete + TxAvailable |
270 | S_5_INTS = HostError + RxEarly + UpComplete + DownComplete + StatsFull ;+ TxComplete + RxComplete + TxAvailable |
255 | 271 | ||
256 | ; Commands |
272 | ; Commands |
257 | TotalReset = 0 shl 11 |
273 | TotalReset = 0 shl 11 |
258 | SelectWindow = 1 shl 11 |
274 | SelectWindow = 1 shl 11 |
259 | StartCoax = 2 shl 11 |
275 | StartCoax = 2 shl 11 |
260 | RxDisable = 3 shl 11 |
276 | RxDisable = 3 shl 11 |
261 | RxEnable = 4 shl 11 |
277 | RxEnable = 4 shl 11 |
262 | RxReset = 5 shl 11 |
278 | RxReset = 5 shl 11 |
263 | UpStall = 6 shl 11 |
279 | UpStall = 6 shl 11 |
264 | UpUnstall = (6 shl 11)+1 |
280 | UpUnstall = (6 shl 11)+1 |
265 | DownStall = (6 shl 11)+2 |
281 | DownStall = (6 shl 11)+2 |
266 | DownUnstall = (6 shl 11)+3 |
282 | DownUnstall = (6 shl 11)+3 |
267 | RxDiscard = 8 shl 11 |
283 | RxDiscard = 8 shl 11 |
268 | TxEnable = 9 shl 11 |
284 | TxEnable = 9 shl 11 |
269 | TxDisable = 10 shl 11 |
285 | TxDisable = 10 shl 11 |
270 | TxReset = 11 shl 11 |
286 | TxReset = 11 shl 11 |
271 | FakeIntr = 12 shl 11 |
287 | FakeIntr = 12 shl 11 |
272 | AckIntr = 13 shl 11 |
288 | AckIntr = 13 shl 11 |
273 | SetIntrEnb = 14 shl 11 |
289 | SetIntrEnb = 14 shl 11 |
274 | SetStatusEnb = 15 shl 11 |
290 | SetStatusEnb = 15 shl 11 |
275 | SetRxFilter = 16 shl 11 |
291 | SetRxFilter = 16 shl 11 |
276 | SetRxThreshold = 17 shl 11 |
292 | SetRxThreshold = 17 shl 11 |
277 | SetTxThreshold = 18 shl 11 |
293 | SetTxThreshold = 18 shl 11 |
278 | SetTxStart = 19 shl 11 |
294 | SetTxStart = 19 shl 11 |
279 | StartDMAUp = 20 shl 11 |
295 | StartDMAUp = 20 shl 11 |
280 | StartDMADown = (20 shl 11)+1 |
296 | StartDMADown = (20 shl 11)+1 |
281 | StatsEnable = 21 shl 11 |
297 | StatsEnable = 21 shl 11 |
282 | StatsDisable = 22 shl 11 |
298 | StatsDisable = 22 shl 11 |
283 | StopCoax = 23 shl 11 |
299 | StopCoax = 23 shl 11 |
284 | SetFilterBit = 25 shl 11 |
300 | SetFilterBit = 25 shl 11 |
285 | 301 | ||
286 | ; Rx mode bits |
302 | ; Rx mode bits |
287 | RxStation = 1 |
303 | RxStation = 1 |
288 | RxMulticast = 2 |
304 | RxMulticast = 2 |
289 | RxBroadcast = 4 |
305 | RxBroadcast = 4 |
290 | RxProm = 8 |
306 | RxProm = 8 |
291 | 307 | ||
292 | MAX_ETH_FRAME_SIZE = 1514 |
308 | MAX_ETH_FRAME_SIZE = 1514 |
293 | 309 | ||
294 | 310 | ||
295 | struct tx_desc |
311 | struct tx_desc |
296 | 312 | ||
297 | next_ptr dd ? |
313 | next_ptr dd ? |
298 | frame_start_hdr dd ? |
314 | frame_start_hdr dd ? |
299 | frag_addr dd ? ; for packet data |
315 | frag_addr dd ? ; for packet data |
300 | frag_len dd ? ; for packet data |
316 | frag_len dd ? ; for packet data |
301 | realaddr dd ? |
317 | realaddr dd ? |
302 | rd 3 ; align 32 |
318 | rd 3 ; align 32 |
303 | ends |
319 | ends |
304 | 320 | ||
305 | 321 | ||
306 | struct rx_desc |
322 | struct rx_desc |
307 | 323 | ||
308 | next_ptr dd ? |
324 | next_ptr dd ? |
309 | pkt_status dd ? |
325 | pkt_status dd ? |
310 | frag_addr dd ? |
326 | frag_addr dd ? |
311 | frag_len dd ? ; for packet data |
327 | frag_len dd ? ; for packet data |
312 | realaddr dd ? |
328 | realaddr dd ? |
313 | rd 3 ; align 32 |
329 | rd 3 ; align 32 |
314 | ends |
330 | ends |
315 | 331 | ||
316 | 332 | ||
317 | struct device ETH_DEVICE |
333 | struct device ETH_DEVICE |
318 | 334 | ||
319 | io_addr dd ? |
335 | io_addr dd ? |
320 | pci_bus dd ? |
336 | pci_bus dd ? |
321 | pci_dev dd ? |
337 | pci_dev dd ? |
322 | irq_line db ? |
338 | irq_line db ? |
323 | rb 3 ; alignment |
339 | rb 3 ; alignment |
324 | 340 | ||
325 | curr_tx dd ? |
341 | curr_tx dd ? |
326 | curr_rx dd ? |
342 | curr_rx dd ? |
327 | prev_tx_frame dd ? |
343 | prev_tx_frame dd ? |
328 | ver_id db ? |
344 | ver_id db ? |
329 | full_bus_master db ? |
345 | full_bus_master db ? |
330 | has_hwcksm db ? |
346 | has_hwcksm db ? |
331 | preamble db ? |
347 | preamble db ? |
332 | dn_list_ptr_cleared db ? |
348 | dn_list_ptr_cleared db ? |
333 | internal_link dd ? ; link state (to be used only internally by driver) |
349 | internal_link dd ? ; link state (to be used only internally by driver) |
334 | 350 | ||
335 | rb 0x100 - ($ and 0xff) ; align 256 |
351 | rb 0x100 - ($ and 0xff) ; align 256 |
336 | tx_desc_buffer rd (sizeof.tx_desc*NUM_TX_DESC)/4 |
352 | tx_desc_buffer rd (sizeof.tx_desc*NUM_TX_DESC)/4 |
337 | rx_desc_buffer rd (sizeof.rx_desc*NUM_RX_DESC)/4 |
353 | rx_desc_buffer rd (sizeof.rx_desc*NUM_RX_DESC)/4 |
338 | 354 | ||
339 | ends |
355 | ends |
340 | 356 | ||
341 | 357 | ||
342 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
358 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
343 | ;; ;; |
359 | ;; ;; |
344 | ;; proc START ;; |
360 | ;; proc START ;; |
345 | ;; ;; |
361 | ;; ;; |
346 | ;; (standard driver proc) ;; |
362 | ;; (standard driver proc) ;; |
347 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
363 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
348 | 364 | ||
349 | proc START c, reason:dword, cmdline:dword |
365 | proc START c, reason:dword, cmdline:dword |
350 | 366 | ||
351 | cmp [reason], DRV_ENTRY |
367 | cmp [reason], DRV_ENTRY |
352 | jne .fail |
368 | jne .fail |
353 | 369 | ||
354 | DEBUGF 2,"Loading driver\n" |
370 | DEBUGF 2,"Loading driver\n" |
355 | invoke RegService, my_service, service_proc |
371 | invoke RegService, my_service, service_proc |
356 | ret |
372 | ret |
357 | 373 | ||
358 | .fail: |
374 | .fail: |
359 | xor eax, eax |
375 | xor eax, eax |
360 | ret |
376 | ret |
361 | 377 | ||
362 | endp |
378 | endp |
363 | 379 | ||
364 | 380 | ||
365 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
381 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
366 | ;; ;; |
382 | ;; ;; |
367 | ;; proc SERVICE_PROC ;; |
383 | ;; proc SERVICE_PROC ;; |
368 | ;; ;; |
384 | ;; ;; |
369 | ;; (standard driver proc) ;; |
385 | ;; (standard driver proc) ;; |
370 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
386 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
371 | 387 | ||
372 | align 4 |
388 | align 4 |
373 | proc service_proc stdcall, ioctl:dword |
389 | proc service_proc stdcall, ioctl:dword |
374 | 390 | ||
375 | mov edx, [ioctl] |
391 | mov edx, [ioctl] |
376 | mov eax, [edx + IOCTL.io_code] |
392 | mov eax, [edx + IOCTL.io_code] |
377 | 393 | ||
378 | ;------------------------------------------------------ |
394 | ;------------------------------------------------------ |
379 | 395 | ||
380 | cmp eax, 0 ;SRV_GETVERSION |
396 | cmp eax, 0 ;SRV_GETVERSION |
381 | jne @F |
397 | jne @F |
382 | 398 | ||
383 | cmp [edx + IOCTL.out_size], 4 |
399 | cmp [edx + IOCTL.out_size], 4 |
384 | jb .fail |
400 | jb .fail |
385 | mov eax, [edx + IOCTL.output] |
401 | mov eax, [edx + IOCTL.output] |
386 | mov [eax], dword API_VERSION |
402 | mov [eax], dword API_VERSION |
387 | 403 | ||
388 | xor eax, eax |
404 | xor eax, eax |
389 | ret |
405 | ret |
390 | 406 | ||
391 | ;------------------------------------------------------ |
407 | ;------------------------------------------------------ |
392 | @@: |
408 | @@: |
393 | cmp eax, 1 ;SRV_HOOK |
409 | cmp eax, 1 ;SRV_HOOK |
394 | jne .fail |
410 | jne .fail |
395 | 411 | ||
396 | cmp [edx + IOCTL.inp_size], 3 ; Data input must be at least 3 bytes |
412 | cmp [edx + IOCTL.inp_size], 3 ; Data input must be at least 3 bytes |
397 | jb .fail |
413 | jb .fail |
398 | 414 | ||
399 | mov eax, [edx + IOCTL.input] |
415 | mov eax, [edx + IOCTL.input] |
400 | cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given |
416 | cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given |
401 | jne .fail ; other types of this hardware dont exist |
417 | jne .fail ; other types of this hardware dont exist |
402 | 418 | ||
403 | ; check if the device is already listed |
419 | ; check if the device is already listed |
404 | 420 | ||
405 | mov ecx, [vortex_devices] |
421 | mov ecx, [devices] |
406 | test ecx, ecx |
422 | test ecx, ecx |
407 | jz .maybeboomerang |
423 | jz .firstdevice |
408 | 424 | ||
409 | mov esi, vortex_list |
425 | mov esi, device_list |
410 | mov eax, [edx + IOCTL.input] ; get the pci bus and device numbers |
426 | mov eax, [edx + IOCTL.input] ; get the pci bus and device numbers |
411 | mov ax , [eax+1] ; |
427 | mov ax , [eax+1] ; |
412 | .nextdevice: |
428 | .nextdevice: |
413 | mov ebx, [esi] |
429 | mov ebx, [esi] |
414 | cmp al, byte[ebx + device.pci_bus] |
430 | cmp al, byte[ebx + device.pci_bus] |
415 | jne @f |
431 | jne @f |
416 | cmp ah, byte[ebx + device.pci_dev] |
432 | cmp ah, byte[ebx + device.pci_dev] |
417 | je .find_devicenum ; Device is already loaded, let's find it's device number |
433 | je .find_devicenum ; Device is already loaded, let's find it's device number |
418 | @@: |
434 | @@: |
419 | add esi, 4 |
435 | add esi, 4 |
420 | loop .nextdevice |
436 | loop .nextdevice |
421 | - | ||
422 | - | ||
423 | .maybeboomerang: |
- | |
424 | mov ecx, [boomerang_devices] |
- | |
425 | test ecx, ecx |
- | |
426 | jz .firstdevice |
- | |
427 | - | ||
428 | mov esi, boomerang_list |
- | |
429 | mov eax, [edx + IOCTL.input] ; get the pci bus and device numbers |
- | |
430 | mov ax, [eax+1] ; |
- | |
431 | .nextdevice2: |
- | |
432 | mov ebx, [esi] |
- | |
433 | cmp al, byte[ebx + device.pci_bus] |
- | |
434 | jne @f |
- | |
435 | cmp ah, byte[ebx + device.pci_dev] |
- | |
436 | je .find_devicenum ; Device is already loaded, let's find it's device number |
- | |
437 | @@: |
- | |
438 | add esi, 4 |
- | |
439 | loop .nextdevice2 |
- | |
440 | - | ||
441 | 437 | ||
442 | ; This device doesnt have its own eth_device structure yet, lets create one |
438 | ; This device doesnt have its own eth_device structure yet, lets create one |
443 | .firstdevice: |
- | |
444 | mov ecx, [boomerang_devices] |
- | |
445 | add ecx, [vortex_devices] |
439 | .firstdevice: |
446 | cmp ecx, MAX_DEVICES ; First check if the driver can handle one more card |
440 | cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card |
447 | jae .fail |
441 | jae .fail |
448 | 442 | ||
449 | allocate_and_clear ebx, sizeof.device, .fail ; Allocate the buffer for device structure |
443 | allocate_and_clear ebx, sizeof.device, .fail ; Allocate the buffer for device structure |
450 | 444 | ||
451 | ; Fill in the direct call addresses into the struct |
445 | ; Fill in the direct call addresses into the struct |
452 | 446 | ||
453 | mov [ebx + device.reset], reset |
447 | mov [ebx + device.reset], reset |
454 | mov [ebx + device.transmit], null_op |
448 | mov [ebx + device.transmit], null_op |
455 | mov [ebx + device.unload], null_op |
449 | mov [ebx + device.unload], null_op |
456 | mov [ebx + device.name], my_service |
450 | mov [ebx + device.name], my_service |
457 | 451 | ||
458 | ; save the pci bus and device numbers |
452 | ; save the pci bus and device numbers |
459 | 453 | ||
460 | mov eax, [edx + IOCTL.input] |
454 | mov eax, [edx + IOCTL.input] |
461 | movzx ecx, byte[eax+1] |
455 | movzx ecx, byte[eax+1] |
462 | mov [ebx + device.pci_bus], ecx |
456 | mov [ebx + device.pci_bus], ecx |
463 | movzx ecx, byte[eax+2] |
457 | movzx ecx, byte[eax+2] |
464 | mov [ebx + device.pci_dev], ecx |
458 | mov [ebx + device.pci_dev], ecx |
465 | 459 | ||
466 | ; Now, it's time to find the base io addres of the PCI device |
460 | ; Now, it's time to find the base io addres of the PCI device |
467 | 461 | ||
468 | stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev] |
462 | stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev] |
469 | mov [ebx + device.io_addr], eax |
463 | mov [ebx + device.io_addr], eax |
470 | 464 | ||
471 | ; We've found the io address, find IRQ now |
465 | ; We've found the io address, find IRQ now |
472 | 466 | ||
473 | invoke PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line |
467 | invoke PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line |
474 | mov [ebx + device.irq_line], al |
468 | mov [ebx + device.irq_line], al |
475 | 469 | ||
476 | DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\ |
470 | DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\ |
477 | [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.io_addr]:4 |
471 | [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.io_addr]:4 |
478 | 472 | ||
479 | ; Ok, the eth_device structure is ready, let's probe the device |
473 | ; Ok, the eth_device structure is ready, let's probe the device |
480 | call probe ; this function will output in eax |
474 | call probe ; this function will output in eax |
481 | test eax, eax |
475 | test eax, eax |
482 | jnz .err ; If an error occured, exit |
476 | jnz .err ; If an error occured, exit |
483 | - | ||
484 | - | ||
485 | movzx ecx, [ebx + device.ver_id] |
- | |
486 | test word [hw_versions+2+ecx*4], IS_VORTEX |
- | |
487 | jz .not_vortex |
- | |
488 | 477 | ||
489 | mov eax, [vortex_devices] ; Add the device structure to our device list |
478 | mov eax, [devices] ; Add the device structure to our device list |
490 | mov [vortex_list+4*eax], ebx ; (IRQ handler uses this list to find device) |
479 | mov [device_list+4*eax], ebx ; |
491 | inc [vortex_devices] ; |
480 | inc [devices] ; |
492 | 481 | ||
493 | .register: |
482 | .register: |
494 | mov [ebx + device.type], NET_TYPE_ETH |
483 | mov [ebx + device.type], NET_TYPE_ETH |
495 | invoke NetRegDev |
484 | invoke NetRegDev |
496 | 485 | ||
497 | cmp eax, -1 |
486 | cmp eax, -1 |
498 | je .destroy |
487 | je .destroy |
499 | 488 | ||
500 | call start_device |
489 | call start_device |
501 | ret |
490 | ret |
502 | - | ||
503 | .not_vortex: |
- | |
504 | mov eax, [boomerang_devices] ; Add the device structure to our device list |
- | |
505 | mov [boomerang_list+4*eax], ebx ; (IRQ handler uses this list to find device) |
- | |
506 | inc [boomerang_devices] |
- | |
507 | - | ||
508 | jmp .register |
- | |
509 | 491 | ||
510 | ; If the device was already loaded, find the device number and return it in eax |
492 | ; If the device was already loaded, find the device number and return it in eax |
511 | 493 | ||
512 | .find_devicenum: |
494 | .find_devicenum: |
513 | DEBUGF 2,"Trying to find device number of already registered device\n" |
495 | DEBUGF 2,"Trying to find device number of already registered device\n" |
514 | invoke NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx |
496 | invoke NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx |
515 | ; into a device number in edi |
497 | ; into a device number in edi |
516 | mov eax, edi ; Application wants it in eax instead |
498 | mov eax, edi ; Application wants it in eax instead |
517 | DEBUGF 2,"Kernel says: %u\n", eax |
499 | DEBUGF 2,"Kernel says: %u\n", eax |
518 | ret |
500 | ret |
519 | 501 | ||
520 | ; If an error occured, remove all allocated data and exit (returning -1 in eax) |
502 | ; If an error occured, remove all allocated data and exit (returning -1 in eax) |
521 | 503 | ||
522 | .destroy: |
504 | .destroy: |
523 | ; todo: reset device into virgin state |
505 | ; todo: reset device into virgin state |
524 | 506 | ||
525 | .err: |
507 | .err: |
526 | invoke KernelFree, ebx |
508 | invoke KernelFree, ebx |
527 | .fail: |
509 | .fail: |
528 | DEBUGF 2, "Failed to load\n" |
510 | DEBUGF 2, "Failed to load\n" |
529 | or eax, -1 |
511 | or eax, -1 |
530 | ret |
512 | ret |
531 | 513 | ||
532 | ;------------------------------------------------------ |
514 | ;------------------------------------------------------ |
533 | endp |
515 | endp |
534 | 516 | ||
535 | 517 | ||
536 | ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;; |
518 | ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;; |
537 | ;; ;; |
519 | ;; ;; |
538 | ;; Actual Hardware dependent code starts here ;; |
520 | ;; Actual Hardware dependent code starts here ;; |
539 | ;; ;; |
521 | ;; ;; |
540 | ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;; |
522 | ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;; |
541 | 523 | ||
542 | 524 | ||
543 | align 4 |
525 | align 4 |
544 | null_op: |
526 | null_op: |
545 | 527 | ||
546 | ret |
528 | ret |
547 | 529 | ||
548 | 530 | ||
549 | 531 | ||
550 | ;*************************************************************************** |
532 | ;*************************************************************************** |
551 | ; Function |
533 | ; Function |
552 | ; probe |
534 | ; probe |
553 | ; Description |
535 | ; Description |
554 | ; Searches for an ethernet card, enables it and clears the rx buffer |
536 | ; Searches for an ethernet card, enables it and clears the rx buffer |
555 | ; Destroyed registers |
537 | ; Destroyed registers |
556 | ; eax, ebx, ecx, edx, edi, esi |
538 | ; eax, ebx, ecx, edx, edi, esi |
557 | ; |
539 | ; |
558 | ;*************************************************************************** |
540 | ;*************************************************************************** |
559 | 541 | ||
560 | align 4 |
542 | align 4 |
561 | probe: |
543 | probe: |
562 | 544 | ||
563 | DEBUGF 1,"Probing 3com card\n" |
545 | DEBUGF 1,"Probing 3com card\n" |
564 | 546 | ||
565 | ; Make the device a bus master |
547 | ; Make the device a bus master |
566 | invoke PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command |
548 | invoke PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command |
567 | or al, PCI_CMD_MASTER |
549 | or al, PCI_CMD_MASTER |
568 | invoke PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax |
550 | invoke PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax |
569 | 551 | ||
570 | ; wake up the card |
552 | ; wake up the card |
571 | DEBUGF 1,"Checking if the device is awake\n" |
553 | DEBUGF 1,"Checking if the device is awake\n" |
572 | 554 | ||
573 | ; wake up - we directly do it by programming PCI |
555 | ; wake up - we directly do it by programming PCI |
574 | ; check if the device is power management capable |
556 | ; check if the device is power management capable |
575 | invoke PciRead16, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.status |
557 | invoke PciRead16, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.status |
576 | test al, PCI_STATUS_CAPA ; is there "new capabilities" linked list? |
558 | test al, PCI_STATUS_CAPA ; is there "new capabilities" linked list? |
577 | jz .device_awake |
559 | jz .device_awake |
578 | 560 | ||
579 | ; search for power management register |
561 | ; search for power management register |
580 | invoke PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.cap_ptr |
562 | invoke PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.cap_ptr |
581 | and al, not 3 |
563 | and al, not 3 |
582 | cmp al, 0x3f |
564 | cmp al, 0x3f |
583 | jbe .device_awake ; invalid pointer if less then PCI header size |
565 | jbe .device_awake ; invalid pointer if less then PCI header size |
584 | 566 | ||
585 | ; traverse the list |
567 | ; traverse the list |
586 | movzx esi, al |
568 | movzx esi, al |
587 | .pm_loop: |
569 | .pm_loop: |
588 | invoke PciRead16, [ebx + device.pci_bus], [ebx + device.pci_dev], esi |
570 | invoke PciRead16, [ebx + device.pci_bus], [ebx + device.pci_dev], esi |
589 | cmp al, 1 |
571 | cmp al, 1 |
590 | je .set_pm_state |
572 | je .set_pm_state |
591 | movzx esi, ah ; load address of next capability |
573 | movzx esi, ah ; load address of next capability |
592 | test ah, ah ; 0 if none left |
574 | test ah, ah ; 0 if none left |
593 | jnz .pm_loop |
575 | jnz .pm_loop |
594 | jmp .device_awake |
576 | jmp .device_awake |
595 | 577 | ||
596 | ; wake up the device if necessary |
578 | ; wake up the device if necessary |
597 | .set_pm_state: |
579 | .set_pm_state: |
598 | DEBUGF 1,"Waking up the device\n" |
580 | DEBUGF 1,"Waking up the device\n" |
599 | add esi, 4 ; offset for power management |
581 | add esi, 4 ; offset for power management |
600 | invoke PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], esi |
582 | invoke PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], esi |
601 | test al, 11b |
583 | test al, 11b |
602 | jz .device_awake |
584 | jz .device_awake |
603 | and al, not 11b ; set state to D0 |
585 | and al, not 11b ; set state to D0 |
604 | invoke PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], esi, eax |
586 | invoke PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], esi, eax |
605 | 587 | ||
606 | .device_awake: |
588 | .device_awake: |
607 | DEBUGF 1,"Device is awake\n" |
589 | DEBUGF 1,"Device is awake\n" |
608 | 590 | ||
609 | ; Check device/vendor ID |
591 | ; Check device/vendor ID |
610 | invoke PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], 0 |
592 | invoke PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], 0 |
611 | 593 | ||
612 | DEBUGF 1,"Vendor id: 0x%x\n", ax |
594 | DEBUGF 1,"Vendor id: 0x%x\n", ax |
613 | 595 | ||
614 | cmp ax, 0x10B7 |
596 | cmp ax, 0x10B7 |
615 | jne .notfound |
597 | jne .notfound |
616 | shr eax, 16 |
598 | shr eax, 16 |
617 | 599 | ||
618 | DEBUGF 1,"Vendor ok!, device id: 0x%x\n", ax |
600 | DEBUGF 1,"Vendor ok!, device id: 0x%x\n", ax |
619 | 601 | ||
620 | ; get chip version |
602 | ; get chip version |
621 | mov ecx, HW_VERSIONS_SIZE/4-1 |
603 | mov ecx, HW_VERSIONS_SIZE/4-1 |
622 | .loop: |
604 | .loop: |
623 | cmp ax, [hw_versions+ecx*4] |
605 | cmp ax, [hw_versions+ecx*4] |
624 | jz .found |
606 | jz .found |
625 | loop .loop |
607 | loop .loop |
626 | .notfound: |
608 | .notfound: |
627 | DEBUGF 2,"Device id not found in list!\n" |
609 | DEBUGF 2,"Device id not found in list!\n" |
628 | or eax, -1 |
610 | or eax, -1 |
629 | ret |
611 | ret |
630 | .found: |
612 | .found: |
631 | mov esi, [hw_str+ecx*4] |
613 | mov esi, [hw_str+ecx*4] |
632 | DEBUGF 1,"Hardware type: %s\n", esi |
614 | DEBUGF 1,"Hardware type: %s\n", esi |
633 | mov [ebx + device.name], esi |
615 | mov [ebx + device.name], esi |
634 | 616 | ||
635 | mov [ebx + device.ver_id], cl |
617 | mov [ebx + device.ver_id], cl |
636 | test word [hw_versions+2+ecx*4], HAS_HWCKSM |
618 | test word [hw_versions+2+ecx*4], HAS_HWCKSM |
637 | setnz [ebx + device.has_hwcksm] |
619 | setnz [ebx + device.has_hwcksm] |
638 | ; set pci latency for vortex cards |
620 | ; set pci latency for vortex cards |
639 | test word [hw_versions+2+ecx*4], IS_VORTEX |
621 | test word [hw_versions+2+ecx*4], IS_VORTEX |
640 | jz .not_vortex |
622 | jz .not_vortex |
641 | 623 | ||
642 | mov al, 11111000b ; 248 = max latency |
624 | mov al, 11111000b ; 248 = max latency |
643 | invoke PciWrite8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.max_latency, eax |
625 | invoke PciWrite8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.max_latency, eax |
644 | 626 | ||
645 | .not_vortex: |
627 | .not_vortex: |
646 | ; set RX/TX functions |
628 | ; set RX/TX functions |
647 | mov ax, EEPROM_REG_CAPABILITIES |
629 | mov ax, EEPROM_REG_CAPABILITIES |
648 | call read_eeprom |
630 | call read_eeprom |
649 | test al, 100000b ; full bus master? |
631 | test al, 100000b ; full bus master? |
650 | setnz [ebx + device.full_bus_master] |
632 | setnz [ebx + device.full_bus_master] |
651 | jnz .boomerang_func |
633 | jnz .boomerang_func |
652 | mov [ebx + device.transmit], vortex_transmit |
634 | mov [ebx + device.transmit], vortex_transmit |
653 | DEBUGF 2,"Device is a vortex type\n" |
635 | DEBUGF 2,"Device is a vortex type\n" |
654 | DEBUGF 2,"I'm sorry but vortex code hasnt been tested yet\n" |
636 | DEBUGF 2,"I'm sorry but vortex code hasnt been tested yet\n" |
655 | DEBUGF 2,"Please contact me on hidnplayr@kolibrios.org\n" |
637 | DEBUGF 2,"Please contact me on hidnplayr@kolibrios.org\n" |
656 | DEBUGF 2,"If you can help me finish it!\n" |
638 | DEBUGF 2,"If you can help me finish it!\n" |
657 | or eax, -1 |
639 | or eax, -1 |
658 | ret |
640 | ret |
659 | jmp @f |
641 | jmp @f |
660 | .boomerang_func: ; full bus master, so use boomerang functions |
642 | .boomerang_func: ; full bus master, so use boomerang functions |
661 | mov [ebx + device.transmit], boomerang_transmit |
643 | mov [ebx + device.transmit], boomerang_transmit |
662 | DEBUGF 1,"Device is a boomerang type\n" |
644 | DEBUGF 1,"Device is a boomerang type\n" |
663 | @@: |
645 | @@: |
664 | call read_mac_eeprom |
646 | call read_mac_eeprom |
665 | 647 | ||
666 | test byte [ebx + device.full_bus_master], 0xff |
648 | test byte [ebx + device.full_bus_master], 0xff |
667 | jz .set_preamble |
649 | jz .set_preamble |
668 | ; switch to register window 2 |
650 | ; switch to register window 2 |
669 | set_io [ebx + device.io_addr], 0 |
651 | set_io [ebx + device.io_addr], 0 |
670 | set_io [ebx + device.io_addr], REG_COMMAND |
652 | set_io [ebx + device.io_addr], REG_COMMAND |
671 | mov ax, SELECT_REGISTER_WINDOW+2 |
653 | mov ax, SELECT_REGISTER_WINDOW+2 |
672 | out dx, ax |
654 | out dx, ax |
673 | ; activate xcvr by setting some magic bits |
655 | ; activate xcvr by setting some magic bits |
674 | set_io [ebx + device.io_addr], REG_RESET_OPTIONS |
656 | set_io [ebx + device.io_addr], REG_RESET_OPTIONS |
675 | in ax, dx |
657 | in ax, dx |
676 | and ax, not 0x4010 |
658 | and ax, not 0x4010 |
677 | movzx ecx, [ebx + device.ver_id] |
659 | movzx ecx, [ebx + device.ver_id] |
678 | test word [ecx*4+hw_versions+2], INVERT_LED_PWR |
660 | test word [ecx*4+hw_versions+2], INVERT_LED_PWR |
679 | jz @f |
661 | jz @f |
680 | or al, 0x10 |
662 | or al, 0x10 |
681 | @@: |
663 | @@: |
682 | test word [ecx*4+hw_versions+2], INVERT_MII_PWR |
664 | test word [ecx*4+hw_versions+2], INVERT_MII_PWR |
683 | jz @f |
665 | jz @f |
684 | or ah, 0x40 |
666 | or ah, 0x40 |
685 | @@: |
667 | @@: |
686 | out dx, ax |
668 | out dx, ax |
687 | .set_preamble: |
669 | .set_preamble: |
688 | ; use preamble as default |
670 | ; use preamble as default |
689 | mov byte [ebx + device.preamble], 1 ; enable preamble |
671 | mov byte [ebx + device.preamble], 1 ; enable preamble |
690 | 672 | ||
691 | DEBUGF 1,"Global reset..\n" |
673 | DEBUGF 1,"Global reset..\n" |
692 | 674 | ||
693 | ; GlobalReset |
675 | ; GlobalReset |
694 | set_io [ebx + device.io_addr], 0 |
676 | set_io [ebx + device.io_addr], 0 |
695 | set_io [ebx + device.io_addr], REG_COMMAND |
677 | set_io [ebx + device.io_addr], REG_COMMAND |
696 | xor eax, eax |
678 | xor eax, eax |
697 | ; or al, 0x14 |
679 | ; or al, 0x14 |
698 | out dx, ax |
680 | out dx, ax |
699 | ; wait for GlobalReset to complete |
681 | ; wait for GlobalReset to complete |
700 | mov ecx, 64000 |
682 | mov ecx, 2000 |
701 | .rsloop: |
683 | .rsloop: |
702 | in ax , dx |
684 | in ax, dx |
703 | test ah , 10000b ; CmdInProgress |
685 | test ah, 10000b ; CmdInProgress |
- | 686 | ||
- | 687 | pusha |
|
- | 688 | mov esi, 1 |
|
- | 689 | invoke Sleep |
|
- | 690 | popa |
|
- | 691 | ||
704 | loopz .rsloop |
692 | loopz .rsloop |
705 | 693 | ||
706 | DEBUGF 1,"Waiting for nic to boot..\n" |
694 | DEBUGF 1,"Waiting for NIC to boot..\n" |
707 | ; wait for 2 seconds for NIC to boot |
695 | ; wait for 2 seconds for NIC to boot |
708 | mov esi, 2000 ; WTF? FIXME |
696 | mov esi, 2000 ; WTF? FIXME |
709 | invoke Sleep ; 2 seconds |
697 | invoke Sleep ; 2 seconds |
710 | 698 | ||
711 | DEBUGF 1,"Ok!\n" |
699 | DEBUGF 1,"Ok!\n" |
712 | 700 | ||
713 | 701 | ||
714 | ;-------------------------- |
702 | ;-------------------------- |
715 | ; |
703 | ; |
716 | ; RESET |
704 | ; RESET |
717 | ; |
705 | ; |
718 | ;-------------------------- |
706 | ;-------------------------- |
719 | 707 | ||
720 | reset: |
708 | reset: |
721 | 709 | ||
722 | movzx eax, [ebx + device.irq_line] |
710 | movzx eax, [ebx + device.irq_line] |
723 | DEBUGF 1,"Attaching int handler to irq %x\n", eax:1 |
711 | DEBUGF 1,"Attaching int handler to irq %x\n", eax:1 |
724 | 712 | ||
725 | movzx ecx, [ebx + device.ver_id] |
713 | movzx ecx, [ebx + device.ver_id] |
726 | test word [hw_versions+2+ecx*4], IS_VORTEX |
714 | test word [hw_versions+2+ecx*4], IS_VORTEX |
727 | jz .not_vortex |
715 | jz .not_vortex |
728 | mov esi, int_vortex |
716 | mov esi, int_vortex |
729 | jmp .reg_int |
717 | jmp .reg_int |
730 | .not_vortex: |
718 | .not_vortex: |
731 | mov esi, int_boomerang |
719 | mov esi, int_boomerang |
732 | .reg_int: |
720 | .reg_int: |
733 | invoke AttachIntHandler, eax, esi, ebx |
721 | invoke AttachIntHandler, eax, esi, ebx |
734 | test eax, eax |
722 | test eax, eax |
735 | jnz @f |
723 | jnz @f |
736 | DEBUGF 2,"Could not attach int handler!\n" |
724 | DEBUGF 2,"Could not attach int handler!\n" |
737 | or eax, -1 |
725 | or eax, -1 |
738 | ret |
726 | ret |
739 | @@: |
727 | @@: |
740 | 728 | ||
741 | set_io [ebx + device.io_addr], 0 |
729 | set_io [ebx + device.io_addr], 0 |
742 | set_io [ebx + device.io_addr], REG_COMMAND |
730 | set_io [ebx + device.io_addr], REG_COMMAND |
743 | mov ax, SELECT_REGISTER_WINDOW + 0 |
731 | mov ax, SELECT_REGISTER_WINDOW + 0 |
744 | out dx, ax |
732 | out dx, ax |
745 | 733 | ||
746 | mov ax, StopCoax |
734 | mov ax, StopCoax |
747 | out dx, ax ; stop transceiver |
735 | out dx, ax ; stop transceiver |
748 | 736 | ||
749 | mov ax, SELECT_REGISTER_WINDOW + 4 |
737 | mov ax, SELECT_REGISTER_WINDOW + 4 |
750 | out dx, ax ; disable UTP |
738 | out dx, ax ; disable UTP |
751 | 739 | ||
752 | set_io [ebx + device.io_addr], REG_MEDIA_STATUS |
740 | set_io [ebx + device.io_addr], REG_MEDIA_STATUS |
753 | mov ax, 0x0 |
741 | mov ax, 0x0 |
754 | 742 | ||
755 | set_io [ebx + device.io_addr], REG_COMMAND |
743 | set_io [ebx + device.io_addr], REG_COMMAND |
756 | mov ax, SELECT_REGISTER_WINDOW + 0 |
744 | mov ax, SELECT_REGISTER_WINDOW + 0 |
757 | out dx, ax |
745 | out dx, ax |
758 | 746 | ||
759 | set_io [ebx + device.io_addr], REG_FIFO_DIAGNOSTIC |
747 | set_io [ebx + device.io_addr], REG_FIFO_DIAGNOSTIC |
760 | mov ax, 0 |
748 | mov ax, 0 |
761 | out dx, ax ; disable card |
749 | out dx, ax ; disable card |
762 | 750 | ||
763 | mov ax, 1 |
751 | mov ax, 1 |
764 | out dx, ax ; enable card |
752 | out dx, ax ; enable card |
765 | 753 | ||
766 | call write_mac |
754 | call write_mac |
767 | 755 | ||
768 | set_io [ebx + device.io_addr], 0 |
756 | set_io [ebx + device.io_addr], 0 |
769 | set_io [ebx + device.io_addr], REG_COMMAND |
757 | set_io [ebx + device.io_addr], REG_COMMAND |
770 | mov ax, SELECT_REGISTER_WINDOW + 1 |
758 | mov ax, SELECT_REGISTER_WINDOW + 1 |
771 | out dx, ax |
759 | out dx, ax |
772 | 760 | ||
773 | mov ecx, 32 |
761 | mov ecx, 32 |
774 | set_io [ebx + device.io_addr], 0x0b |
762 | set_io [ebx + device.io_addr], 0x0b |
775 | .loop: |
763 | .loop: |
776 | in al, dx |
764 | in al, dx |
777 | loop .loop |
765 | loop .loop |
778 | 766 | ||
779 | ; Get rid of stray ints |
767 | ; Get rid of stray ints |
780 | set_io [ebx + device.io_addr], REG_COMMAND |
768 | set_io [ebx + device.io_addr], REG_COMMAND |
781 | mov ax, AckIntr + 0xff |
769 | mov ax, AckIntr + 0xff |
782 | out dx, ax |
770 | out dx, ax |
783 | 771 | ||
784 | mov ax, SetStatusEnb + S_5_INTS |
772 | mov ax, SetStatusEnb + S_5_INTS |
785 | out dx, ax |
773 | out dx, ax |
786 | 774 | ||
787 | mov ax, SetIntrEnb + S_5_INTS |
775 | mov ax, SetIntrEnb + S_5_INTS |
788 | out dx, ax |
776 | out dx, ax |
789 | 777 | ||
790 | DEBUGF 1,"Setting RX mode\n" |
778 | DEBUGF 1,"Setting RX mode\n" |
791 | 779 | ||
792 | set_io [ebx + device.io_addr], 0 |
780 | set_io [ebx + device.io_addr], 0 |
793 | set_io [ebx + device.io_addr], REG_COMMAND |
781 | set_io [ebx + device.io_addr], REG_COMMAND |
794 | 782 | ||
795 | if defined PROMISCIOUS |
783 | if defined PROMISCIOUS |
796 | mov ax, SetRxFilter + RxStation + RxMulticast + RxBroadcast + RxProm |
784 | mov ax, SetRxFilter + RxStation + RxMulticast + RxBroadcast + RxProm |
797 | else if defined ALLMULTI |
785 | else if defined ALLMULTI |
798 | mov ax, SetRxFilter + RxStation + RxMulticast + RxBroadcast |
786 | mov ax, SetRxFilter + RxStation + RxMulticast + RxBroadcast |
799 | else |
787 | else |
800 | mov ax, SetRxFilter + RxStation + RxBroadcast |
788 | mov ax, SetRxFilter + RxStation + RxBroadcast |
801 | end if |
789 | end if |
802 | out dx, ax |
790 | out dx, ax |
803 | 791 | ||
804 | call set_active_port |
792 | call set_active_port |
805 | 793 | ||
806 | call create_rx_ring |
794 | call create_rx_ring |
807 | test eax, eax |
795 | test eax, eax |
808 | jnz .err |
796 | jnz .err |
809 | 797 | ||
810 | call rx_reset |
798 | call rx_reset |
811 | call tx_reset |
799 | call tx_reset |
812 | 800 | ||
813 | xor eax, eax |
801 | xor eax, eax |
814 | ; clear packet/byte counters |
802 | ; clear packet/byte counters |
815 | 803 | ||
816 | lea edi, [ebx + device.bytes_tx] |
804 | lea edi, [ebx + device.bytes_tx] |
817 | mov ecx, 6 |
805 | mov ecx, 6 |
818 | rep stosd |
806 | rep stosd |
819 | 807 | ||
820 | xor eax, eax |
808 | xor eax, eax |
821 | ret |
809 | ret |
822 | 810 | ||
823 | .err: |
811 | .err: |
824 | DEBUGF 2,"reset failed\n" |
812 | DEBUGF 2,"reset failed\n" |
825 | or eax, -1 |
813 | or eax, -1 |
826 | ret |
814 | ret |
827 | 815 | ||
828 | 816 | ||
829 | align 4 |
817 | align 4 |
830 | start_device: |
818 | start_device: |
831 | DEBUGF 1,"Starting the device\n" |
819 | DEBUGF 1,"Starting the device\n" |
832 | 820 | ||
833 | set_io [ebx + device.io_addr], 0 |
821 | set_io [ebx + device.io_addr], 0 |
834 | set_io [ebx + device.io_addr], REG_COMMAND |
822 | set_io [ebx + device.io_addr], REG_COMMAND |
835 | mov ax, SetTxThreshold + 60 ;2047 ; recommended by the manual :) |
823 | mov ax, SetTxThreshold + 60 ;2047 ; recommended by the manual :) |
836 | out dx, ax |
824 | out dx, ax |
837 | 825 | ||
838 | call check_tx_status |
826 | call check_tx_status |
839 | 827 | ||
840 | set_io [ebx + device.io_addr], 0 |
828 | set_io [ebx + device.io_addr], 0 |
841 | set_io [ebx + device.io_addr], REG_COMMAND |
829 | set_io [ebx + device.io_addr], REG_COMMAND |
842 | ; switch to register window 4 |
830 | ; switch to register window 4 |
843 | mov ax, SELECT_REGISTER_WINDOW+4 |
831 | mov ax, SELECT_REGISTER_WINDOW+4 |
844 | out dx, ax |
832 | out dx, ax |
845 | 833 | ||
846 | ; wait for linkDetect |
834 | ; wait for linkDetect |
847 | set_io [ebx + device.io_addr], REG_MEDIA_STATUS |
835 | set_io [ebx + device.io_addr], REG_MEDIA_STATUS |
848 | mov ecx, 20 ; wait for max 2s |
836 | mov ecx, 20 ; wait for max 2s |
849 | .link_detect_loop: |
837 | .link_detect_loop: |
850 | mov esi, 100 |
838 | mov esi, 100 |
851 | invoke Sleep ; 100 ms |
839 | invoke Sleep ; 100 ms |
852 | in ax, dx |
840 | in ax, dx |
853 | test ah, 1000b ; linkDetect |
841 | test ah, 1000b ; linkDetect |
854 | jnz @f |
842 | jnz @f |
855 | loop .link_detect_loop |
843 | loop .link_detect_loop |
856 | DEBUGF 2,"Link detect timed-out!\n" |
844 | DEBUGF 2,"Link detect timed-out!\n" |
857 | @@: |
845 | @@: |
858 | 846 | ||
859 | ; print link type |
847 | ; print link type |
860 | xor eax, eax |
848 | xor eax, eax |
861 | bsr ax, word[ebx + device.internal_link] |
849 | bsr ax, word[ebx + device.internal_link] |
862 | jz @f |
850 | jz @f |
863 | sub ax, 5 |
851 | sub ax, 5 |
864 | @@: |
852 | @@: |
865 | 853 | ||
866 | mov esi, [link_str+eax*4] |
854 | mov esi, [link_str+eax*4] |
867 | DEBUGF 1,"Established Link type: %s\n", esi |
855 | DEBUGF 1,"Established Link type: %s\n", esi |
868 | 856 | ||
869 | ; enable interrupts |
857 | ; enable interrupts |
870 | set_io [ebx + device.io_addr], REG_COMMAND |
858 | set_io [ebx + device.io_addr], REG_COMMAND |
871 | mov ax, SELECT_REGISTER_WINDOW + 1 |
859 | mov ax, SELECT_REGISTER_WINDOW + 1 |
872 | out dx, ax |
860 | out dx, ax |
873 | 861 | ||
874 | mov ax, AckIntr + 0xff |
862 | mov ax, AckIntr + 0xff |
875 | out dx, ax |
863 | out dx, ax |
876 | 864 | ||
877 | mov ax, SetStatusEnb + S_5_INTS |
865 | mov ax, SetStatusEnb + S_5_INTS |
878 | out dx, ax |
866 | out dx, ax |
879 | 867 | ||
880 | mov ax, SetIntrEnb + S_5_INTS |
868 | mov ax, SetIntrEnb + S_5_INTS |
881 | out dx, ax |
869 | out dx, ax |
882 | 870 | ||
883 | ; Start RX/TX |
871 | ; Start RX/TX |
884 | 872 | ||
885 | set_io [ebx + device.io_addr], 0 |
873 | set_io [ebx + device.io_addr], 0 |
886 | set_io [ebx + device.io_addr], REG_COMMAND |
874 | set_io [ebx + device.io_addr], REG_COMMAND |
887 | mov ax, RxEnable |
875 | mov ax, RxEnable |
888 | out dx, ax |
876 | out dx, ax |
889 | 877 | ||
890 | mov ax, TxEnable |
878 | mov ax, TxEnable |
891 | out dx, ax |
879 | out dx, ax |
892 | 880 | ||
893 | set_io [ebx + device.io_addr], REG_COMMAND |
881 | set_io [ebx + device.io_addr], REG_COMMAND |
894 | mov ax, SetRxThreshold + 208 |
882 | mov ax, SetRxThreshold + 208 |
895 | out dx, ax |
883 | out dx, ax |
896 | 884 | ||
897 | mov ax, SetTxThreshold + 60 ;16 ; recommended by the manual :) |
885 | mov ax, SetTxThreshold + 60 ;16 ; recommended by the manual :) |
898 | out dx, ax |
886 | out dx, ax |
899 | 887 | ||
900 | mov ax, SELECT_REGISTER_WINDOW + 1 |
888 | mov ax, SELECT_REGISTER_WINDOW + 1 |
901 | out dx, ax |
889 | out dx, ax |
902 | 890 | ||
903 | ; Set the mtu, kernel will be able to send now |
891 | ; Set the mtu, kernel will be able to send now |
904 | mov [ebx + device.mtu], 1514 |
892 | mov [ebx + device.mtu], 1514 |
905 | 893 | ||
906 | ; Set link state to unknown |
894 | ; Set link state to unknown |
907 | mov [ebx + device.state], ETH_LINK_UNKNOWN |
895 | mov [ebx + device.state], ETH_LINK_UNKNOWN |
908 | xor eax, eax |
896 | xor eax, eax |
909 | 897 | ||
910 | ret |
898 | ret |
911 | 899 | ||
912 | 900 | ||
913 | 901 | ||
914 | ;*************************************************************************** |
902 | ;*************************************************************************** |
915 | ; Function |
903 | ; Function |
916 | ; tx_reset |
904 | ; tx_reset |
917 | ; Description |
905 | ; Description |
918 | ; resets and enables transmitter engine |
906 | ; resets and enables transmitter engine |
919 | ; |
907 | ; |
920 | ;*************************************************************************** |
908 | ;*************************************************************************** |
921 | 909 | ||
922 | align 4 |
910 | align 4 |
923 | tx_reset: |
911 | tx_reset: |
924 | DEBUGF 1,"tx reset\n" |
912 | DEBUGF 1,"tx reset\n" |
925 | 913 | ||
926 | ; TxReset |
914 | ; TxReset |
927 | set_io [ebx + device.io_addr], 0 |
915 | set_io [ebx + device.io_addr], 0 |
928 | set_io [ebx + device.io_addr], REG_COMMAND |
916 | set_io [ebx + device.io_addr], REG_COMMAND |
929 | mov ax, TxReset |
917 | mov ax, TxReset |
930 | out dx, ax |
918 | out dx, ax |
931 | ; Wait for TxReset to complete |
919 | ; Wait for TxReset to complete |
932 | mov ecx, 200000 |
920 | mov ecx, 200000 |
933 | .tx_reset_loop: |
921 | .tx_reset_loop: |
934 | in ax, dx |
922 | in ax, dx |
935 | test ah, 10000b ; check CmdInProgress |
923 | test ah, 10000b ; check CmdInProgress |
936 | jz .tx_set_prev |
924 | jz .tx_set_prev |
937 | dec ecx |
925 | dec ecx |
938 | jnz .tx_reset_loop |
926 | jnz .tx_reset_loop |
939 | .tx_set_prev: |
927 | .tx_set_prev: |
940 | ; init last TX descriptor |
928 | ; init last TX descriptor |
941 | lea eax, [ebx + device.tx_desc_buffer + (NUM_TX_DESC-1)*sizeof.tx_desc] |
929 | lea eax, [ebx + device.tx_desc_buffer + (NUM_TX_DESC-1)*sizeof.tx_desc] |
942 | mov [ebx + device.curr_tx], eax |
930 | mov [ebx + device.curr_tx], eax |
943 | 931 | ||
944 | .tx_enable: |
932 | .tx_enable: |
945 | ret |
933 | ret |
946 | 934 | ||
947 | 935 | ||
948 | 936 | ||
949 | ;*************************************************************************** |
937 | ;*************************************************************************** |
950 | ; Function |
938 | ; Function |
951 | ; rx_reset |
939 | ; rx_reset |
952 | ; Description |
940 | ; Description |
953 | ; resets and enables receiver engine |
941 | ; resets and enables receiver engine |
954 | ; |
942 | ; |
955 | ;*************************************************************************** |
943 | ;*************************************************************************** |
956 | 944 | ||
957 | align 4 |
945 | align 4 |
958 | rx_reset: |
946 | rx_reset: |
959 | 947 | ||
960 | DEBUGF 1,"rx reset\n" |
948 | DEBUGF 1,"rx reset\n" |
961 | 949 | ||
962 | set_io [ebx + device.io_addr], 0 |
950 | set_io [ebx + device.io_addr], 0 |
963 | set_io [ebx + device.io_addr], REG_COMMAND |
951 | set_io [ebx + device.io_addr], REG_COMMAND |
964 | mov ax, RxReset or 0x4 |
952 | mov ax, RxReset or 0x4 |
965 | out dx, ax |
953 | out dx, ax |
966 | 954 | ||
967 | ; wait for RxReset to complete |
955 | ; wait for RxReset to complete |
968 | mov ecx, 200000 |
956 | mov ecx, 200000 |
969 | .loop: |
957 | .loop: |
970 | in ax, dx |
958 | in ax, dx |
971 | test ah, 10000b ; check CmdInProgress |
959 | test ah, 10000b ; check CmdInProgress |
972 | jz .done |
960 | jz .done |
973 | dec ecx |
961 | dec ecx |
974 | jnz .loop |
962 | jnz .loop |
975 | .done: |
963 | .done: |
976 | 964 | ||
977 | lea eax, [ebx + device.rx_desc_buffer] |
965 | lea eax, [ebx + device.rx_desc_buffer] |
978 | mov [ebx + device.curr_rx], eax |
966 | mov [ebx + device.curr_rx], eax |
979 | invoke GetPhysAddr |
967 | invoke GetPhysAddr |
980 | set_io [ebx + device.io_addr], 0 |
968 | set_io [ebx + device.io_addr], 0 |
981 | set_io [ebx + device.io_addr], REG_UP_LIST_PTR |
969 | set_io [ebx + device.io_addr], REG_UP_LIST_PTR |
982 | out dx, eax |
970 | out dx, eax |
983 | 971 | ||
984 | .rx_enable: |
972 | .rx_enable: |
985 | ret |
973 | ret |
986 | 974 | ||
987 | 975 | ||
988 | 976 | ||
989 | align 4 |
977 | align 4 |
990 | create_rx_ring: |
978 | create_rx_ring: |
991 | ; create rx descriptor ring |
979 | ; create rx descriptor ring |
992 | lea eax, [ebx + device.rx_desc_buffer] |
980 | lea eax, [ebx + device.rx_desc_buffer] |
993 | invoke GetPhysAddr |
981 | invoke GetPhysAddr |
994 | mov edi, eax ; real addr of first descr |
982 | mov edi, eax ; real addr of first descr |
995 | 983 | ||
996 | lea esi, [ebx + device.rx_desc_buffer] ; ptr to first descr |
984 | lea esi, [ebx + device.rx_desc_buffer] ; ptr to first descr |
997 | lea edx, [ebx + device.rx_desc_buffer + (NUM_RX_DESC-1)*sizeof.rx_desc] ; ptr to last descr |
985 | lea edx, [ebx + device.rx_desc_buffer + (NUM_RX_DESC-1)*sizeof.rx_desc] ; ptr to last descr |
998 | 986 | ||
999 | mov ecx, NUM_RX_DESC |
987 | mov ecx, NUM_RX_DESC |
1000 | .loop: |
988 | .loop: |
1001 | mov [edx + rx_desc.next_ptr], edi |
989 | mov [edx + rx_desc.next_ptr], edi |
1002 | 990 | ||
1003 | push ecx edx |
991 | push ecx edx |
1004 | invoke NetAlloc, MAX_ETH_FRAME_SIZE+NET_BUFF.data |
992 | invoke NetAlloc, MAX_ETH_FRAME_SIZE+NET_BUFF.data |
1005 | pop edx ecx |
993 | pop edx ecx |
1006 | test eax, eax |
994 | test eax, eax |
1007 | jz .out_of_mem |
995 | jz .out_of_mem |
1008 | mov [esi + rx_desc.realaddr], eax |
996 | mov [esi + rx_desc.realaddr], eax |
1009 | invoke GetPhysAddr |
997 | invoke GetPhysAddr |
1010 | add eax, NET_BUFF.data |
998 | add eax, NET_BUFF.data |
1011 | mov [esi + rx_desc.frag_addr], eax |
999 | mov [esi + rx_desc.frag_addr], eax |
1012 | and [esi + rx_desc.pkt_status], 0 |
1000 | and [esi + rx_desc.pkt_status], 0 |
1013 | mov [esi + rx_desc.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31) |
1001 | mov [esi + rx_desc.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31) |
1014 | 1002 | ||
1015 | DEBUGF 1,"rx_desc: lin=%x phys=%x len=%x next ptr=%x\n", [esi+rx_desc.realaddr]:8, [esi+rx_desc.frag_addr]:8, [esi+rx_desc.frag_len]:8, edi |
1003 | DEBUGF 1,"rx_desc: lin=%x phys=%x len=%x next ptr=%x\n", [esi+rx_desc.realaddr]:8, [esi+rx_desc.frag_addr]:8, [esi+rx_desc.frag_len]:8, edi |
1016 | DEBUGF 1,"rx_desc: cur=%x prev=%x\n", esi, edx |
1004 | DEBUGF 1,"rx_desc: cur=%x prev=%x\n", esi, edx |
1017 | 1005 | ||
1018 | mov edx, esi |
1006 | mov edx, esi |
1019 | add esi, sizeof.rx_desc |
1007 | add esi, sizeof.rx_desc |
1020 | add edi, sizeof.rx_desc |
1008 | add edi, sizeof.rx_desc |
1021 | dec ecx |
1009 | dec ecx |
1022 | jnz .loop |
1010 | jnz .loop |
1023 | 1011 | ||
1024 | xor eax, eax |
1012 | xor eax, eax |
1025 | ret |
1013 | ret |
1026 | 1014 | ||
1027 | .out_of_mem: |
1015 | .out_of_mem: |
1028 | or eax, -1 |
1016 | or eax, -1 |
1029 | ret |
1017 | ret |
1030 | 1018 | ||
1031 | 1019 | ||
1032 | 1020 | ||
1033 | ;--------------------------------------------------------------------------- |
1021 | ;--------------------------------------------------------------------------- |
1034 | ; Function |
1022 | ; Function |
1035 | ; try_link_detect |
1023 | ; try_link_detect |
1036 | ; Description |
1024 | ; Description |
1037 | ; try_link_detect checks if link exists |
1025 | ; try_link_detect checks if link exists |
1038 | ; Parameters |
1026 | ; Parameters |
1039 | ; ebx = device structure |
1027 | ; ebx = device structure |
1040 | ; Return value |
1028 | ; Return value |
1041 | ; al - 0 ; no link detected |
1029 | ; al - 0 ; no link detected |
1042 | ; al - 1 ; link detected |
1030 | ; al - 1 ; link detected |
1043 | ; Destroyed registers |
1031 | ; Destroyed registers |
1044 | ; eax, ebx, ecx, edx, edi, esi |
1032 | ; eax, ebx, ecx, edx, edi, esi |
1045 | ; |
1033 | ; |
1046 | ;--------------------------------------------------------------------------- |
1034 | ;--------------------------------------------------------------------------- |
1047 | 1035 | ||
1048 | align 4 |
1036 | align 4 |
1049 | try_link_detect: |
1037 | try_link_detect: |
1050 | 1038 | ||
1051 | DEBUGF 1,"Trying to detect link\n" |
1039 | DEBUGF 1,"Trying to detect link\n" |
1052 | 1040 | ||
1053 | ; create self-directed packet |
1041 | ; create self-directed packet |
1054 | invoke NetAlloc, 20+NET_BUFF.data ; create a buffer for the self-directed packet |
1042 | invoke NetAlloc, 20+NET_BUFF.data ; create a buffer for the self-directed packet |
1055 | test eax, eax |
1043 | test eax, eax |
1056 | jz .fail |
1044 | jz .fail |
1057 | 1045 | ||
1058 | push eax |
1046 | push eax |
1059 | mov [eax + NET_BUFF.length], 20 |
1047 | mov [eax + NET_BUFF.length], 20 |
1060 | 1048 | ||
1061 | lea edi, [eax + NET_BUFF.data] |
1049 | lea edi, [eax + NET_BUFF.data] |
1062 | lea esi, [ebx + device.mac] |
1050 | lea esi, [ebx + device.mac] |
1063 | movsw |
1051 | movsw |
1064 | movsd |
1052 | movsd |
1065 | sub esi, 6 |
1053 | sub esi, 6 |
1066 | movsw |
1054 | movsw |
1067 | movsd |
1055 | movsd |
1068 | mov ax , 0x0608 |
1056 | mov ax , 0x0608 |
1069 | stosw |
1057 | stosw |
1070 | 1058 | ||
1071 | ; download self-directed packet |
1059 | ; download self-directed packet |
1072 | call [ebx + device.transmit] |
1060 | call [ebx + device.transmit] |
1073 | 1061 | ||
1074 | ; switch to register window 4 |
1062 | ; switch to register window 4 |
1075 | set_io [ebx + device.io_addr], 0 |
1063 | set_io [ebx + device.io_addr], 0 |
1076 | set_io [ebx + device.io_addr], REG_COMMAND |
1064 | set_io [ebx + device.io_addr], REG_COMMAND |
1077 | mov ax, SELECT_REGISTER_WINDOW+4 |
1065 | mov ax, SELECT_REGISTER_WINDOW+4 |
1078 | out dx, ax |
1066 | out dx, ax |
1079 | 1067 | ||
1080 | ; See if we have received the packet by now.. |
1068 | ; See if we have received the packet by now.. |
1081 | cmp [ebx + device.packets_rx], 0 |
1069 | cmp [ebx + device.packets_rx], 0 |
1082 | jnz .link_detected |
1070 | jnz .link_detected |
1083 | 1071 | ||
1084 | ; switch to register window 4 |
1072 | ; switch to register window 4 |
1085 | set_io [ebx + device.io_addr], REG_COMMAND |
1073 | set_io [ebx + device.io_addr], REG_COMMAND |
1086 | mov ax, SELECT_REGISTER_WINDOW+4 |
1074 | mov ax, SELECT_REGISTER_WINDOW+4 |
1087 | out dx, ax |
1075 | out dx, ax |
1088 | 1076 | ||
1089 | ; read linkbeatdetect |
1077 | ; read linkbeatdetect |
1090 | set_io [ebx + device.io_addr], REG_MEDIA_STATUS |
1078 | set_io [ebx + device.io_addr], REG_MEDIA_STATUS |
1091 | in ax, dx |
1079 | in ax, dx |
1092 | test ah, 1000b ; test linkBeatDetect |
1080 | test ah, 1000b ; test linkBeatDetect |
1093 | jnz .link_detected |
1081 | jnz .link_detected |
1094 | xor al, al |
1082 | xor al, al |
1095 | jmp .finish |
1083 | jmp .finish |
1096 | 1084 | ||
1097 | .link_detected: |
1085 | .link_detected: |
1098 | DEBUGF 1,"Link detected!\n" |
1086 | DEBUGF 1,"Link detected!\n" |
1099 | setb al |
1087 | setb al |
1100 | 1088 | ||
1101 | .finish: |
1089 | .finish: |
1102 | test al, al |
1090 | test al, al |
1103 | jz @f |
1091 | jz @f |
1104 | or byte [ebx + device.internal_link+1], 100b |
1092 | or byte [ebx + device.internal_link+1], 100b |
1105 | @@: |
1093 | @@: |
1106 | xor eax, eax |
1094 | xor eax, eax |
1107 | ret |
1095 | ret |
1108 | 1096 | ||
1109 | .fail: |
1097 | .fail: |
1110 | DEBUGF 1,"No link detected!\n" |
1098 | DEBUGF 1,"No link detected!\n" |
1111 | or eax, -1 |
1099 | or eax, -1 |
1112 | ret |
1100 | ret |
1113 | 1101 | ||
1114 | 1102 | ||
1115 | 1103 | ||
1116 | ;*************************************************************************** |
1104 | ;*************************************************************************** |
1117 | ; Function |
1105 | ; Function |
1118 | ; try_phy |
1106 | ; try_phy |
1119 | ; Description |
1107 | ; Description |
1120 | ; try_phy checks the auto-negotiation function |
1108 | ; try_phy checks the auto-negotiation function |
1121 | ; in the PHY at PHY index. It can also be extended to |
1109 | ; in the PHY at PHY index. It can also be extended to |
1122 | ; include link detection for non-IEEE 802.3u |
1110 | ; include link detection for non-IEEE 802.3u |
1123 | ; auto-negotiation devices, for instance the BCM5000. ; TODO: BCM5000 |
1111 | ; auto-negotiation devices, for instance the BCM5000. ; TODO: BCM5000 |
1124 | ; Parameters |
1112 | ; Parameters |
1125 | ; ah - PHY index |
1113 | ; ah - PHY index |
1126 | ; ebx - device stucture |
1114 | ; ebx - device stucture |
1127 | ; Return value |
1115 | ; Return value |
1128 | ; al - 0 link is auto-negotiated |
1116 | ; al - 0 link is auto-negotiated |
1129 | ; al - 1 no link is auto-negotiated |
1117 | ; al - 1 no link is auto-negotiated |
1130 | ; Destroyed registers |
1118 | ; Destroyed registers |
1131 | ; eax, ebx, ecx, edx, esi |
1119 | ; eax, ebx, ecx, edx, esi |
1132 | ; |
1120 | ; |
1133 | ;*************************************************************************** |
1121 | ;*************************************************************************** |
1134 | 1122 | ||
1135 | align 4 |
1123 | align 4 |
1136 | try_phy: |
1124 | try_phy: |
1137 | 1125 | ||
1138 | DEBUGF 1,"PHY=%u\n", ah |
1126 | DEBUGF 1,"PHY=%u\n", ah |
1139 | DEBUGF 1,"Detecting if device is auto-negotiation capable\n" |
1127 | DEBUGF 1,"Detecting if device is auto-negotiation capable\n" |
1140 | 1128 | ||
1141 | mov al, MII_BMCR |
1129 | mov al, MII_BMCR |
1142 | push eax |
1130 | push eax |
1143 | call mdio_read ; returns with window #4 |
1131 | call mdio_read |
1144 | or ah, 0x80 ; software reset |
1132 | or ax, BMCR_RESET |
1145 | mov esi, eax |
1133 | mov esi, eax |
1146 | mov eax, [esp] |
1134 | mov eax, [esp] |
1147 | call mdio_write ; returns with window #4 |
1135 | call mdio_write |
1148 | 1136 | ||
1149 | ; wait for reset to complete |
1137 | ; wait for reset to complete |
1150 | mov esi, 2000 |
1138 | mov esi, 2000 |
1151 | invoke Sleep ; 2s FIXME |
1139 | invoke Sleep ; 2s FIXME |
- | 1140 | ||
1152 | mov eax, [esp] |
1141 | mov eax, [esp] |
- | 1142 | mov al, MII_BMCR |
|
1153 | call mdio_read ; returns with window #4 |
1143 | call mdio_read |
1154 | test ah, 0x80 |
1144 | test ax, BMCR_RESET |
1155 | jnz .fail1 |
1145 | jnz .fail1 |
1156 | mov eax, [esp] |
- | |
1157 | 1146 | ||
1158 | ; wait for a while after reset |
1147 | ; wait for a while after reset |
1159 | mov esi, 20 |
1148 | mov esi, 20 |
1160 | invoke Sleep ; 20ms |
1149 | invoke Sleep ; 20ms |
- | 1150 | ||
1161 | mov eax, [esp] |
1151 | mov eax, [esp] |
1162 | mov al , MII_BMSR |
1152 | mov al, MII_BMSR |
1163 | call mdio_read ; returns with window #4 |
1153 | call mdio_read |
1164 | test al, 1 ; extended capability supported? |
1154 | test al, BMSR_ERCAP |
1165 | jz .fail2 |
1155 | jz .fail2 |
1166 | DEBUGF 1,"Extended capability supported\n" |
1156 | DEBUGF 1,"Extended capability supported\n" |
1167 | - | ||
1168 | ; auto-neg capable? |
- | |
1169 | test al , 1000b |
1157 | test al, BMSR_ANEGCAPABLE |
1170 | jz .fail2 ; not auto-negotiation capable |
1158 | jz .fail2 |
1171 | DEBUGF 1,"Auto-negotiation capable\n" |
1159 | DEBUGF 1,"Auto-negotiation capable\n" |
1172 | - | ||
1173 | ; auto-neg complete? |
- | |
1174 | test al , 100000b |
1160 | test al, BMSR_ANEGCOMPLETE |
1175 | jnz .auto_neg_ok |
1161 | jnz .auto_neg_ok |
1176 | DEBUGF 1,"Restarting auto-negotiation\n" |
1162 | DEBUGF 1,"Restarting auto-negotiation\n" |
1177 | 1163 | ||
1178 | ; restart auto-negotiation |
1164 | ; restart auto-negotiation |
1179 | mov eax, [esp] |
1165 | mov eax, [esp] |
1180 | mov al, MII_ADVERTISE |
1166 | mov al, MII_ADVERTISE |
1181 | push eax |
1167 | push eax |
1182 | call mdio_read ; returns with window #4 |
1168 | call mdio_read ; returns with window #4 |
1183 | or ax , 1111b shl 5; advertise only 10base-T and 100base-TX |
1169 | or ax, ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL |
1184 | mov esi, eax |
1170 | mov esi, eax |
1185 | pop eax |
1171 | pop eax |
1186 | call mdio_write ; returns with window #4 |
1172 | call mdio_write ; returns with window #4 |
1187 | mov eax, [esp] |
1173 | mov eax, [esp] |
1188 | call mdio_read ; returns with window #4 |
1174 | call mdio_read ; returns with window #4 |
1189 | mov esi, eax |
1175 | mov esi, eax |
1190 | or bh , 10010b ; restart auto-negotiation |
1176 | or bx, BMCR_ANENABLE or BMCR_ANRESTART |
1191 | mov eax, [esp] |
1177 | mov eax, [esp] |
1192 | call mdio_write ; returns with window #4 |
1178 | call mdio_write ; returns with window #4 |
1193 | mov esi, 4000 |
1179 | mov esi, 4000 |
1194 | invoke Sleep ; 4 seconds |
1180 | invoke Sleep ; 4 seconds |
1195 | mov eax, [esp] |
1181 | mov eax, [esp] |
- | 1182 | ||
1196 | mov al , MII_BMSR |
1183 | mov al, MII_BMSR |
1197 | call mdio_read ; returns with window #4 |
1184 | call mdio_read ; returns with window #4 |
1198 | test al , 100000b ; auto-neg complete? |
1185 | test al, BMSR_ANEGCOMPLETE |
1199 | jnz .auto_neg_ok |
1186 | jnz .auto_neg_ok |
- | 1187 | ||
1200 | jmp .fail3 |
1188 | jmp .fail3 |
1201 | .auto_neg_ok: |
1189 | .auto_neg_ok: |
1202 | DEBUGF 1,"Auto-negotiation complete\n" |
1190 | DEBUGF 1,"Auto-negotiation complete\n" |
1203 | 1191 | ||
1204 | ; compare advertisement and link partner ability registers |
1192 | ; compare advertisement and link partner ability registers |
1205 | mov eax, [esp] |
1193 | mov eax, [esp] |
1206 | mov al, MII_ADVERTISE |
1194 | mov al, MII_ADVERTISE |
1207 | call mdio_read ; returns with window #4 |
1195 | call mdio_read ; returns with window #4 |
1208 | xchg eax, [esp] |
1196 | xchg eax, [esp] |
1209 | mov al, MII_LPA |
1197 | mov al, MII_LPA |
1210 | call mdio_read ; returns with window #4 |
1198 | call mdio_read ; returns with window #4 |
1211 | pop esi |
1199 | pop esi |
1212 | and eax, esi |
1200 | and eax, esi |
1213 | and eax, 11111100000b ; Mask off |
1201 | and eax, 11111100000b ; Mask off |
1214 | push eax |
1202 | push eax |
1215 | mov word[ebx + device.internal_link+2], ax |
1203 | mov word[ebx + device.internal_link+2], ax |
1216 | 1204 | ||
1217 | ; switch to register window 3 |
1205 | ; switch to register window 3 |
1218 | set_io [ebx + device.io_addr], 0 |
1206 | set_io [ebx + device.io_addr], 0 |
1219 | set_io [ebx + device.io_addr], REG_COMMAND |
1207 | set_io [ebx + device.io_addr], REG_COMMAND |
1220 | mov ax, SELECT_REGISTER_WINDOW+3 |
1208 | mov ax, SELECT_REGISTER_WINDOW+3 |
1221 | out dx, ax |
1209 | out dx, ax |
1222 | 1210 | ||
1223 | ; set full-duplex mode |
1211 | ; set full-duplex mode |
1224 | set_io [ebx + device.io_addr], REG_MAC_CONTROL |
1212 | set_io [ebx + device.io_addr], REG_MAC_CONTROL |
1225 | in ax, dx |
1213 | in ax, dx |
1226 | and ax, not 0x120 ; clear full duplex and flow control |
1214 | and ax, not 0x120 ; clear full duplex and flow control |
1227 | pop esi |
1215 | pop esi |
1228 | test esi, 1010b shl 5 ; check for full-duplex |
1216 | test esi, 1010b shl 5 ; check for full-duplex |
1229 | jz .half_duplex |
1217 | jz .half_duplex |
1230 | or ax, 0x120 ; set full duplex and flow control |
1218 | or ax, 0x120 ; set full duplex and flow control |
1231 | .half_duplex: |
1219 | .half_duplex: |
1232 | DEBUGF 1,"Using half-duplex\n" |
1220 | DEBUGF 1,"Using half-duplex\n" |
1233 | out dx, ax |
1221 | out dx, ax |
1234 | mov al, 1 |
1222 | mov al, 1 |
1235 | ret |
1223 | ret |
1236 | 1224 | ||
1237 | .fail1: |
1225 | .fail1: |
1238 | DEBUGF 2,"reset failed!\n" |
1226 | DEBUGF 2,"reset failed!\n" |
1239 | pop eax |
1227 | pop eax |
1240 | xor al, al |
1228 | xor al, al |
1241 | ret |
1229 | ret |
1242 | 1230 | ||
1243 | .fail2: |
1231 | .fail2: |
1244 | DEBUGF 2,"This device is not auto-negotiation capable!\n" |
1232 | DEBUGF 2,"This device is not auto-negotiation capable!\n" |
1245 | pop eax |
1233 | pop eax |
1246 | xor al, al |
1234 | xor al, al |
1247 | ret |
1235 | ret |
1248 | 1236 | ||
1249 | .fail3: |
1237 | .fail3: |
1250 | DEBUGF 2,"Auto-negotiation reset failed!\n" |
1238 | DEBUGF 2,"Auto-negotiation reset failed!\n" |
1251 | pop eax |
1239 | pop eax |
1252 | xor al, al |
1240 | xor al, al |
1253 | ret |
1241 | ret |
1254 | 1242 | ||
1255 | 1243 | ||
1256 | 1244 | ||
1257 | ;*************************************************************************** |
1245 | ;*************************************************************************** |
1258 | ; Function |
1246 | ; Function |
1259 | ; try_mii |
1247 | ; try_mii |
1260 | ; Description |
1248 | ; Description |
1261 | ; try_MII checks the on-chip auto-negotiation logic |
1249 | ; try_MII checks the on-chip auto-negotiation logic |
1262 | ; or an off-chip MII PHY, depending upon what is set in |
1250 | ; or an off-chip MII PHY, depending upon what is set in |
1263 | ; xcvrSelect by the caller. |
1251 | ; xcvrSelect by the caller. |
1264 | ; It exits when it finds the first device with a good link. |
1252 | ; It exits when it finds the first device with a good link. |
1265 | ; Parameters |
1253 | ; Parameters |
1266 | ; |
1254 | ; |
1267 | ; Return value |
1255 | ; Return value |
1268 | ; al - 0 |
1256 | ; al - 0 |
1269 | ; al - 1 |
1257 | ; al - 1 |
1270 | ; Destroyed registers |
1258 | ; Destroyed registers |
1271 | ; eax, ebx, ecx, edx, esi |
1259 | ; eax, ebx, ecx, edx, esi |
1272 | ; |
1260 | ; |
1273 | ;*************************************************************************** |
1261 | ;*************************************************************************** |
1274 | 1262 | ||
1275 | align 4 |
1263 | align 4 |
1276 | try_mii: |
1264 | try_mii: |
1277 | 1265 | ||
1278 | DEBUGF 1,"Trying to find MII PHY\n" |
1266 | DEBUGF 1,"Trying to find MII PHY\n" |
1279 | 1267 | ||
1280 | ; switch to register window 3 |
1268 | ; switch to register window 3 |
1281 | set_io [ebx + device.io_addr], 0 |
1269 | set_io [ebx + device.io_addr], 0 |
1282 | set_io [ebx + device.io_addr], REG_COMMAND |
1270 | set_io [ebx + device.io_addr], REG_COMMAND |
1283 | mov ax, SELECT_REGISTER_WINDOW+3 |
1271 | mov ax, SELECT_REGISTER_WINDOW+3 |
1284 | out dx, ax |
1272 | out dx, ax |
1285 | set_io [ebx + device.io_addr], REG_INTERNAL_CONFIG |
1273 | set_io [ebx + device.io_addr], REG_INTERNAL_CONFIG |
1286 | in eax, dx |
1274 | in eax, dx |
1287 | and eax, (1111b shl 20) |
1275 | and eax, (1111b shl 20) |
1288 | cmp eax, (1000b shl 20) ; is auto-negotiation set? |
1276 | cmp eax, (1000b shl 20) ; is auto-negotiation set? |
1289 | jne .mii_device |
1277 | jne .mii_device |
1290 | 1278 | ||
1291 | DEBUGF 1,"Auto-negotiation is set\n" |
1279 | DEBUGF 1,"Auto-negotiation is set\n" |
1292 | ; switch to register window 4 |
1280 | ; switch to register window 4 |
1293 | set_io [ebx + device.io_addr], REG_COMMAND |
1281 | set_io [ebx + device.io_addr], REG_COMMAND |
1294 | mov ax, SELECT_REGISTER_WINDOW+4 |
1282 | mov ax, SELECT_REGISTER_WINDOW+4 |
1295 | out dx, ax |
1283 | out dx, ax |
1296 | 1284 | ||
1297 | ; PHY==24 is the on-chip auto-negotiation logic |
1285 | ; PHY==24 is the on-chip auto-negotiation logic |
1298 | ; it supports only 10base-T and 100base-TX |
1286 | ; it supports only 10base-T and 100base-TX |
1299 | mov ah, 24 |
1287 | mov ah, 24 |
1300 | call try_phy |
1288 | call try_phy |
1301 | test al, al |
1289 | test al, al |
1302 | jz .fail |
1290 | jz .fail |
1303 | 1291 | ||
1304 | mov cl, 24 |
1292 | mov cl, 24 |
1305 | jmp .check_preamble |
1293 | jmp .check_preamble |
1306 | 1294 | ||
1307 | .mii_device: |
1295 | .mii_device: |
1308 | cmp eax, (0110b shl 20) |
1296 | cmp eax, (0110b shl 20) |
1309 | jne .fail |
1297 | jne .fail |
1310 | 1298 | ||
1311 | set_io [ebx + device.io_addr], 0 |
1299 | set_io [ebx + device.io_addr], 0 |
1312 | set_io [ebx + device.io_addr], REG_COMMAND |
1300 | set_io [ebx + device.io_addr], REG_COMMAND |
1313 | mov ax , SELECT_REGISTER_WINDOW+4 |
1301 | mov ax , SELECT_REGISTER_WINDOW+4 |
1314 | out dx , ax |
1302 | out dx , ax |
1315 | 1303 | ||
1316 | set_io [ebx + device.io_addr], REG_PHYSICAL_MGMT |
1304 | set_io [ebx + device.io_addr], REG_PHYSICAL_MGMT |
1317 | in ax , dx |
1305 | in ax , dx |
1318 | and al , (1 shl BIT_MGMT_DIR) or (1 shl BIT_MGMT_DATA) |
1306 | and al , (1 shl BIT_MGMT_DIR) or (1 shl BIT_MGMT_DATA) |
1319 | cmp al , (1 shl BIT_MGMT_DATA) |
1307 | cmp al , (1 shl BIT_MGMT_DATA) |
1320 | je .search_for_phy |
1308 | je .search_for_phy |
1321 | 1309 | ||
1322 | xor al, al |
1310 | xor al, al |
1323 | ret |
1311 | ret |
1324 | 1312 | ||
1325 | .search_for_phy: |
1313 | .search_for_phy: |
1326 | ; search for PHY |
1314 | ; search for PHY |
1327 | mov cx, 31 |
1315 | mov cx, 31 |
1328 | .search_phy_loop: |
1316 | .search_phy_loop: |
1329 | DEBUGF 1,"Searching for the PHY\n" |
1317 | DEBUGF 1,"Searching for the PHY\n" |
1330 | cmp cx, 24 |
1318 | cmp cx, 24 |
1331 | je .next_phy |
1319 | je .next_phy |
1332 | mov ah, cl ; ah = phy |
1320 | mov ah, cl ; ah = phy |
1333 | mov al, MII_BMSR ; al = Basic Mode Status Register ; BUGFIX HERE! :):) |
1321 | mov al, MII_BMSR ; al = Basic Mode Status Register ; BUGFIX HERE! :):) |
1334 | push cx |
1322 | push cx |
1335 | call mdio_read |
1323 | call mdio_read |
1336 | pop cx |
1324 | pop cx |
1337 | test ax, ax |
1325 | test ax, ax |
1338 | jz .next_phy |
1326 | jz .next_phy |
1339 | cmp ax, 0xffff |
1327 | cmp ax, 0xffff |
1340 | je .next_phy |
1328 | je .next_phy |
1341 | mov ah, cl ; ah = phy |
1329 | mov ah, cl ; ah = phy |
1342 | push cx |
1330 | push cx |
1343 | call try_phy |
1331 | call try_phy |
1344 | pop cx |
1332 | pop cx |
1345 | test al, al |
1333 | test al, al |
1346 | jnz .check_preamble |
1334 | jnz .check_preamble |
1347 | .next_phy: |
1335 | .next_phy: |
1348 | loopw .search_phy_loop |
1336 | loopw .search_phy_loop |
1349 | 1337 | ||
1350 | .fail: |
1338 | .fail: |
1351 | DEBUGF 1,"PHY not found\n" |
1339 | DEBUGF 1,"PHY not found\n" |
1352 | xor al, al |
1340 | xor al, al |
1353 | ret |
1341 | ret |
1354 | 1342 | ||
1355 | ; epilog |
1343 | ; epilog |
1356 | .check_preamble: |
1344 | .check_preamble: |
1357 | DEBUGF 1,"Using PHY: %u\nChecking PreAmble\n", cl |
1345 | DEBUGF 1,"Using PHY: %u\nChecking PreAmble\n", cl |
1358 | push eax ; eax contains the return value of try_phy |
1346 | push eax ; eax contains the return value of try_phy |
1359 | ; check hard coded preamble forcing |
1347 | ; check hard coded preamble forcing |
1360 | movzx eax, [ebx + device.ver_id] |
1348 | movzx eax, [ebx + device.ver_id] |
1361 | test word [eax*4+hw_versions+2], EXTRA_PREAMBLE |
1349 | test word [eax*4+hw_versions+2], EXTRA_PREAMBLE |
1362 | setnz [ebx + device.preamble] ; force preamble |
1350 | setnz [ebx + device.preamble] ; force preamble |
1363 | jnz .finish |
1351 | jnz .finish |
1364 | 1352 | ||
1365 | ; check mii for preamble suppression |
1353 | ; check mii for preamble suppression |
1366 | mov ah, cl |
1354 | mov ah, cl |
1367 | mov al, MII_BMSR |
1355 | mov al, MII_BMSR |
1368 | call mdio_read |
1356 | call mdio_read |
1369 | test al, 1000000b ; preamble suppression? |
1357 | test al, 1000000b ; preamble suppression? |
1370 | setz [ebx + device.preamble] ; no |
1358 | setz [ebx + device.preamble] ; no |
1371 | 1359 | ||
1372 | .finish: |
1360 | .finish: |
1373 | pop eax |
1361 | pop eax |
1374 | ret |
1362 | ret |
1375 | 1363 | ||
1376 | 1364 | ||
1377 | 1365 | ||
1378 | ;*************************************************************************** |
1366 | ;*************************************************************************** |
1379 | ; Function |
1367 | ; Function |
1380 | ; test_packet |
1368 | ; test_packet |
1381 | ; Description |
1369 | ; Description |
1382 | ; try_loopback try a loopback packet for 10BASE2 or AUI port |
1370 | ; try_loopback try a loopback packet for 10BASE2 or AUI port |
1383 | ; Parameters |
1371 | ; Parameters |
1384 | ; ebx = device structure |
1372 | ; ebx = device structure |
1385 | ; |
1373 | ; |
1386 | ;*************************************************************************** |
1374 | ;*************************************************************************** |
1387 | 1375 | ||
1388 | align 4 |
1376 | align 4 |
1389 | test_packet: |
1377 | test_packet: |
1390 | 1378 | ||
1391 | DEBUGF 1,"Sending test packet\n" |
1379 | DEBUGF 1,"Sending test packet\n" |
1392 | 1380 | ||
1393 | ; switch to register window 3 |
1381 | ; switch to register window 3 |
1394 | set_io [ebx + device.io_addr], 0 |
1382 | set_io [ebx + device.io_addr], 0 |
1395 | set_io [ebx + device.io_addr], REG_COMMAND |
1383 | set_io [ebx + device.io_addr], REG_COMMAND |
1396 | mov ax, SELECT_REGISTER_WINDOW+3 |
1384 | mov ax, SELECT_REGISTER_WINDOW+3 |
1397 | out dx, ax |
1385 | out dx, ax |
1398 | 1386 | ||
1399 | ; set fullDuplexEnable in MacControl register |
1387 | ; set fullDuplexEnable in MacControl register |
1400 | set_io [ebx + device.io_addr], REG_MAC_CONTROL |
1388 | set_io [ebx + device.io_addr], REG_MAC_CONTROL |
1401 | in ax, dx |
1389 | in ax, dx |
1402 | or ax, 0x120 |
1390 | or ax, 0x120 |
1403 | out dx, ax |
1391 | out dx, ax |
1404 | 1392 | ||
1405 | ; switch to register window 5 |
1393 | ; switch to register window 5 |
1406 | set_io [ebx + device.io_addr], REG_COMMAND |
1394 | set_io [ebx + device.io_addr], REG_COMMAND |
1407 | mov ax, SELECT_REGISTER_WINDOW+5 |
1395 | mov ax, SELECT_REGISTER_WINDOW+5 |
1408 | out dx, ax |
1396 | out dx, ax |
1409 | 1397 | ||
1410 | ; set RxFilter to enable individual address matches |
1398 | ; set RxFilter to enable individual address matches |
1411 | mov ax, (10000b shl 11) |
1399 | mov ax, (10000b shl 11) |
1412 | set_io [ebx + device.io_addr], REG_RX_FILTER |
1400 | set_io [ebx + device.io_addr], REG_RX_FILTER |
1413 | in al, dx |
1401 | in al, dx |
1414 | or al, 1 |
1402 | or al, 1 |
1415 | set_io [ebx + device.io_addr], REG_COMMAND |
1403 | set_io [ebx + device.io_addr], REG_COMMAND |
1416 | out dx, ax |
1404 | out dx, ax |
1417 | 1405 | ||
1418 | ; issue RxEnable and TxEnable |
1406 | ; issue RxEnable and TxEnable |
1419 | call rx_reset |
1407 | call rx_reset |
1420 | call tx_reset |
1408 | call tx_reset |
1421 | 1409 | ||
1422 | ; create self-directed packet |
1410 | ; create self-directed packet |
1423 | invoke NetAlloc, 20 + NET_BUFF.data ; create a buffer for the self-directed packet |
1411 | invoke NetAlloc, 20 + NET_BUFF.data ; create a buffer for the self-directed packet |
1424 | test eax, eax |
1412 | test eax, eax |
1425 | jz .fail |
1413 | jz .fail |
1426 | 1414 | ||
1427 | push eax |
1415 | push eax |
1428 | mov [eax + NET_BUFF.length], 20 |
1416 | mov [eax + NET_BUFF.length], 20 |
1429 | ; mov [eax + NET_BUFF.device], ebx |
1417 | ; mov [eax + NET_BUFF.device], ebx |
1430 | 1418 | ||
1431 | lea edi, [eax + NET_BUFF.data] |
1419 | lea edi, [eax + NET_BUFF.data] |
1432 | lea esi, [ebx + device.mac] |
1420 | lea esi, [ebx + device.mac] |
1433 | movsw |
1421 | movsw |
1434 | movsd |
1422 | movsd |
1435 | sub esi, 6 |
1423 | sub esi, 6 |
1436 | movsw |
1424 | movsw |
1437 | movsd |
1425 | movsd |
1438 | mov ax, 0x0608 |
1426 | mov ax, 0x0608 |
1439 | stosw |
1427 | stosw |
1440 | 1428 | ||
1441 | ; download self-directed packet |
1429 | ; download self-directed packet |
1442 | call [ebx + device.transmit] |
1430 | call [ebx + device.transmit] |
1443 | 1431 | ||
1444 | ; wait for 2s |
1432 | ; wait for 2s |
1445 | mov esi, 2000 ; FIXME |
1433 | mov esi, 2000 ; FIXME |
1446 | invoke Sleep |
1434 | invoke Sleep |
1447 | 1435 | ||
1448 | ; check if self-directed packet is received |
1436 | ; check if self-directed packet is received |
1449 | mov eax, [ebx + device.packets_rx] |
1437 | mov eax, [ebx + device.packets_rx] |
1450 | test eax, eax |
1438 | test eax, eax |
1451 | jnz .finish |
1439 | jnz .finish |
1452 | 1440 | ||
1453 | ; switch to register window 3 |
1441 | ; switch to register window 3 |
1454 | set_io [ebx + device.io_addr], 0 |
1442 | set_io [ebx + device.io_addr], 0 |
1455 | set_io [ebx + device.io_addr], REG_COMMAND |
1443 | set_io [ebx + device.io_addr], REG_COMMAND |
1456 | mov ax, SELECT_REGISTER_WINDOW+3 |
1444 | mov ax, SELECT_REGISTER_WINDOW+3 |
1457 | out dx, ax |
1445 | out dx, ax |
1458 | 1446 | ||
1459 | ; clear fullDuplexEnable in MacControl register |
1447 | ; clear fullDuplexEnable in MacControl register |
1460 | set_io [ebx + device.io_addr], REG_MAC_CONTROL |
1448 | set_io [ebx + device.io_addr], REG_MAC_CONTROL |
1461 | in ax, dx |
1449 | in ax, dx |
1462 | and ax, not 0x120 |
1450 | and ax, not 0x120 |
1463 | out dx, ax |
1451 | out dx, ax |
1464 | .fail: |
1452 | .fail: |
1465 | xor eax, eax |
1453 | xor eax, eax |
1466 | 1454 | ||
1467 | .finish: |
1455 | .finish: |
1468 | ret |
1456 | ret |
1469 | 1457 | ||
1470 | 1458 | ||
1471 | 1459 | ||
1472 | ;*************************************************************************** |
1460 | ;*************************************************************************** |
1473 | ; Function |
1461 | ; Function |
1474 | ; try_loopback |
1462 | ; try_loopback |
1475 | ; Description |
1463 | ; Description |
1476 | ; tries a loopback packet for 10BASE2 or AUI port |
1464 | ; tries a loopback packet for 10BASE2 or AUI port |
1477 | ; Parameters |
1465 | ; Parameters |
1478 | ; al - 0: 10Mbps AUI connector |
1466 | ; al - 0: 10Mbps AUI connector |
1479 | ; 1: 10BASE-2 |
1467 | ; 1: 10BASE-2 |
1480 | ; |
1468 | ; |
1481 | ; Return value |
1469 | ; Return value |
1482 | ; al - 0 |
1470 | ; al - 0 |
1483 | ; al - 1 |
1471 | ; al - 1 |
1484 | ; Destroyed registers |
1472 | ; Destroyed registers |
1485 | ; eax, ebx, ecx, edx, edi, esi |
1473 | ; eax, ebx, ecx, edx, edi, esi |
1486 | ; |
1474 | ; |
1487 | ;*************************************************************************** |
1475 | ;*************************************************************************** |
1488 | 1476 | ||
1489 | align 4 |
1477 | align 4 |
1490 | try_loopback: |
1478 | try_loopback: |
1491 | 1479 | ||
1492 | DEBUGF 1,"trying loopback\n" |
1480 | DEBUGF 1,"trying loopback\n" |
1493 | 1481 | ||
1494 | push eax |
1482 | push eax |
1495 | ; switch to register window 3 |
1483 | ; switch to register window 3 |
1496 | set_io [ebx + device.io_addr], 0 |
1484 | set_io [ebx + device.io_addr], 0 |
1497 | set_io [ebx + device.io_addr], REG_COMMAND |
1485 | set_io [ebx + device.io_addr], REG_COMMAND |
1498 | mov ax, SELECT_REGISTER_WINDOW+3 |
1486 | mov ax, SELECT_REGISTER_WINDOW+3 |
1499 | out dx, ax |
1487 | out dx, ax |
1500 | mov eax, [esp] |
1488 | mov eax, [esp] |
1501 | 1489 | ||
1502 | mov cl, al |
1490 | mov cl, al |
1503 | inc cl |
1491 | inc cl |
1504 | shl cl, 3 |
1492 | shl cl, 3 |
1505 | or byte [ebx + device.internal_link+1], cl |
1493 | or byte [ebx + device.internal_link+1], cl |
1506 | 1494 | ||
1507 | test al, al ; aui or coax? |
1495 | test al, al ; aui or coax? |
1508 | jz .complete_loopback |
1496 | jz .complete_loopback |
1509 | ; enable 100BASE-2 DC-DC converter |
1497 | ; enable 100BASE-2 DC-DC converter |
1510 | mov ax, (10b shl 11) ; EnableDcConverter |
1498 | mov ax, (10b shl 11) ; EnableDcConverter |
1511 | out dx, ax |
1499 | out dx, ax |
1512 | .complete_loopback: |
1500 | .complete_loopback: |
1513 | 1501 | ||
1514 | mov cx, 2 ; give a port 3 chances to complete a loopback |
1502 | mov cx, 2 ; give a port 3 chances to complete a loopback |
1515 | .next_try: |
1503 | .next_try: |
1516 | push ecx |
1504 | push ecx |
1517 | call test_packet |
1505 | call test_packet |
1518 | pop ecx |
1506 | pop ecx |
1519 | test eax, eax |
1507 | test eax, eax |
1520 | loopzw .next_try |
1508 | loopzw .next_try |
1521 | 1509 | ||
1522 | .finish: |
1510 | .finish: |
1523 | xchg eax, [esp] |
1511 | xchg eax, [esp] |
1524 | test al, al |
1512 | test al, al |
1525 | jz .aui_finish |
1513 | jz .aui_finish |
1526 | 1514 | ||
1527 | ; issue DisableDcConverter command |
1515 | ; issue DisableDcConverter command |
1528 | set_io [ebx + device.io_addr], 0 |
1516 | set_io [ebx + device.io_addr], 0 |
1529 | set_io [ebx + device.io_addr], REG_COMMAND |
1517 | set_io [ebx + device.io_addr], REG_COMMAND |
1530 | mov ax, (10111b shl 11) |
1518 | mov ax, (10111b shl 11) |
1531 | out dx, ax |
1519 | out dx, ax |
1532 | .aui_finish: |
1520 | .aui_finish: |
1533 | pop eax ; al contains the result of operation |
1521 | pop eax ; al contains the result of operation |
1534 | 1522 | ||
1535 | test al, al |
1523 | test al, al |
1536 | jnz @f |
1524 | jnz @f |
1537 | and byte [ebx + device.internal_link+1], not 11000b |
1525 | and byte [ebx + device.internal_link+1], not 11000b |
1538 | @@: |
1526 | @@: |
1539 | 1527 | ||
1540 | ret |
1528 | ret |
1541 | 1529 | ||
1542 | 1530 | ||
1543 | ;*************************************************************************** |
1531 | ;*************************************************************************** |
1544 | ; Function |
1532 | ; Function |
1545 | ; set_active_port |
1533 | ; set_active_port |
1546 | ; Description |
1534 | ; Description |
1547 | ; It selects the media port (transceiver) to be used |
1535 | ; It selects the media port (transceiver) to be used |
1548 | ; Return value: |
1536 | ; Return value: |
1549 | ; Destroyed registers |
1537 | ; Destroyed registers |
1550 | ; eax, ebx, ecx, edx, edi, esi |
1538 | ; eax, ebx, ecx, edx, edi, esi |
1551 | ; |
1539 | ; |
1552 | ;*************************************************************************** |
1540 | ;*************************************************************************** |
1553 | 1541 | ||
1554 | align 4 |
1542 | align 4 |
1555 | set_active_port: |
1543 | set_active_port: |
1556 | 1544 | ||
1557 | DEBUGF 1,"Trying to find the active port\n" |
1545 | DEBUGF 1,"Trying to find the active port\n" |
1558 | 1546 | ||
1559 | ; switch to register window 3 |
1547 | ; switch to register window 3 |
1560 | set_io [ebx + device.io_addr], 0 |
1548 | set_io [ebx + device.io_addr], 0 |
1561 | set_io [ebx + device.io_addr], REG_COMMAND |
1549 | set_io [ebx + device.io_addr], REG_COMMAND |
1562 | mov ax, SELECT_REGISTER_WINDOW + 3 |
1550 | mov ax, SELECT_REGISTER_WINDOW + 3 |
1563 | out dx, ax |
1551 | out dx, ax |
1564 | 1552 | ||
1565 | set_io [ebx + device.io_addr], REG_INTERNAL_CONFIG |
1553 | set_io [ebx + device.io_addr], REG_INTERNAL_CONFIG |
1566 | in eax, dx |
1554 | in eax, dx |
1567 | test eax, (1 shl 24) ; check if autoselect enable |
1555 | test eax, (1 shl 24) ; check if autoselect enable |
1568 | jz .set_first_available_media |
1556 | jz .set_first_available_media |
1569 | 1557 | ||
1570 | ; check 100BASE-TX and 10BASE-T |
1558 | ; check 100BASE-TX and 10BASE-T |
1571 | set_io [ebx + device.io_addr], REG_MEDIA_OPTIONS |
1559 | set_io [ebx + device.io_addr], REG_MEDIA_OPTIONS |
1572 | in ax, dx |
1560 | in ax, dx |
1573 | test al, 1010b ; check whether 100BASE-TX or 10BASE-T available |
1561 | test al, 1010b ; check whether 100BASE-TX or 10BASE-T available |
1574 | jz .mii_device ; they are not available |
1562 | jz .mii_device ; they are not available |
1575 | 1563 | ||
1576 | ; set auto-negotiation |
1564 | ; set auto-negotiation |
1577 | set_io [ebx + device.io_addr], REG_INTERNAL_CONFIG |
1565 | set_io [ebx + device.io_addr], REG_INTERNAL_CONFIG |
1578 | in eax, dx |
1566 | in eax, dx |
1579 | and eax, not (1111b shl 20) |
1567 | and eax, not (1111b shl 20) |
1580 | or eax, (1000b shl 20) |
1568 | or eax, (1000b shl 20) |
1581 | out dx, eax |
1569 | out dx, eax |
1582 | call try_mii |
1570 | call try_mii |
1583 | test al, al |
1571 | test al, al |
1584 | jz .mii_device |
1572 | jz .mii_device |
1585 | DEBUGF 1,"Using auto negotiation\n" |
1573 | DEBUGF 1,"Using auto negotiation\n" |
1586 | ret |
1574 | ret |
1587 | 1575 | ||
1588 | .mii_device: |
1576 | .mii_device: |
1589 | ; switch to register window 3 |
1577 | ; switch to register window 3 |
1590 | set_io [ebx + device.io_addr], 0 |
1578 | set_io [ebx + device.io_addr], 0 |
1591 | ; check for off-chip mii device |
1579 | ; check for off-chip mii device |
1592 | set_io [ebx + device.io_addr], REG_MEDIA_OPTIONS |
1580 | set_io [ebx + device.io_addr], REG_MEDIA_OPTIONS |
1593 | in ax, dx |
1581 | in ax, dx |
1594 | test al, 1000000b ; check miiDevice |
1582 | test al, 1000000b ; check miiDevice |
1595 | jz .base_fx |
1583 | jz .base_fx |
1596 | set_io [ebx + device.io_addr], REG_INTERNAL_CONFIG |
1584 | set_io [ebx + device.io_addr], REG_INTERNAL_CONFIG |
1597 | in eax, dx |
1585 | in eax, dx |
1598 | and eax, not (1111b shl 20) |
1586 | and eax, not (1111b shl 20) |
1599 | or eax, (0110b shl 20) ; set MIIDevice |
1587 | or eax, (0110b shl 20) ; set MIIDevice |
1600 | out dx, eax |
1588 | out dx, eax |
1601 | call try_mii |
1589 | call try_mii |
1602 | test al, al |
1590 | test al, al |
1603 | jz .base_fx |
1591 | jz .base_fx |
1604 | DEBUGF 1,"Using off-chip mii device\n" |
1592 | DEBUGF 1,"Using off-chip mii device\n" |
1605 | ret |
1593 | ret |
1606 | 1594 | ||
1607 | .base_fx: |
1595 | .base_fx: |
1608 | ; switch to register window 3 |
1596 | ; switch to register window 3 |
1609 | set_io [ebx + device.io_addr], 0 |
1597 | set_io [ebx + device.io_addr], 0 |
1610 | ; check for 100BASE-FX |
1598 | ; check for 100BASE-FX |
1611 | set_io [ebx + device.io_addr], REG_MEDIA_OPTIONS |
1599 | set_io [ebx + device.io_addr], REG_MEDIA_OPTIONS |
1612 | in ax, dx ; read media option register |
1600 | in ax, dx ; read media option register |
1613 | test al, 100b ; check 100BASE-FX |
1601 | test al, 100b ; check 100BASE-FX |
1614 | jz .aui_enable |
1602 | jz .aui_enable |
1615 | set_io [ebx + device.io_addr], REG_INTERNAL_CONFIG |
1603 | set_io [ebx + device.io_addr], REG_INTERNAL_CONFIG |
1616 | in eax, dx |
1604 | in eax, dx |
1617 | and eax, not (1111b shl 20) |
1605 | and eax, not (1111b shl 20) |
1618 | or eax, (0101b shl 20) ; set 100base-FX |
1606 | or eax, (0101b shl 20) ; set 100base-FX |
1619 | out dx, eax |
1607 | out dx, eax |
1620 | call try_link_detect |
1608 | call try_link_detect |
1621 | test al, al |
1609 | test al, al |
1622 | jz .aui_enable |
1610 | jz .aui_enable |
1623 | DEBUGF 1,"Using 100Base-FX\n" |
1611 | DEBUGF 1,"Using 100Base-FX\n" |
1624 | ret |
1612 | ret |
1625 | 1613 | ||
1626 | .aui_enable: |
1614 | .aui_enable: |
1627 | ; switch to register window 3 |
1615 | ; switch to register window 3 |
1628 | set_io [ebx + device.io_addr], 0 |
1616 | set_io [ebx + device.io_addr], 0 |
1629 | ; check for 10Mbps AUI connector |
1617 | ; check for 10Mbps AUI connector |
1630 | set_io [ebx + device.io_addr], REG_MEDIA_OPTIONS |
1618 | set_io [ebx + device.io_addr], REG_MEDIA_OPTIONS |
1631 | in ax, dx ; read media option register |
1619 | in ax, dx ; read media option register |
1632 | test al, 100000b ; check 10Mbps AUI connector |
1620 | test al, 100000b ; check 10Mbps AUI connector |
1633 | jz .coax_available |
1621 | jz .coax_available |
1634 | set_io [ebx + device.io_addr], REG_INTERNAL_CONFIG |
1622 | set_io [ebx + device.io_addr], REG_INTERNAL_CONFIG |
1635 | in eax, dx |
1623 | in eax, dx |
1636 | and eax, not (1111b shl 20) |
1624 | and eax, not (1111b shl 20) |
1637 | or eax, (0001b shl 20) ; set 10Mbps AUI connector |
1625 | or eax, (0001b shl 20) ; set 10Mbps AUI connector |
1638 | out dx, eax |
1626 | out dx, eax |
1639 | xor al, al ; try 10Mbps AUI connector |
1627 | xor al, al ; try 10Mbps AUI connector |
1640 | call try_loopback |
1628 | call try_loopback |
1641 | test al, al |
1629 | test al, al |
1642 | jz .coax_available |
1630 | jz .coax_available |
1643 | DEBUGF 1,"Using 10Mbps aui\n" |
1631 | DEBUGF 1,"Using 10Mbps aui\n" |
1644 | ret |
1632 | ret |
1645 | 1633 | ||
1646 | .coax_available: |
1634 | .coax_available: |
1647 | ; switch to register window 3 |
1635 | ; switch to register window 3 |
1648 | set_io [ebx + device.io_addr], 0 |
1636 | set_io [ebx + device.io_addr], 0 |
1649 | ; check for coaxial 10BASE-2 port |
1637 | ; check for coaxial 10BASE-2 port |
1650 | set_io [ebx + device.io_addr], REG_MEDIA_OPTIONS |
1638 | set_io [ebx + device.io_addr], REG_MEDIA_OPTIONS |
1651 | in ax, dx ; read media option register |
1639 | in ax, dx ; read media option register |
1652 | test al, 10000b ; check 10BASE-2 |
1640 | test al, 10000b ; check 10BASE-2 |
1653 | jz .set_first_available_media |
1641 | jz .set_first_available_media |
1654 | 1642 | ||
1655 | set_io [ebx + device.io_addr], REG_INTERNAL_CONFIG |
1643 | set_io [ebx + device.io_addr], REG_INTERNAL_CONFIG |
1656 | in eax, dx |
1644 | in eax, dx |
1657 | and eax, not (1111b shl 20) |
1645 | and eax, not (1111b shl 20) |
1658 | or eax, (0011b shl 20) ; set 10BASE-2 |
1646 | or eax, (0011b shl 20) ; set 10BASE-2 |
1659 | out dx, eax |
1647 | out dx, eax |
1660 | mov al, 1 |
1648 | mov al, 1 |
1661 | call try_loopback |
1649 | call try_loopback |
1662 | test al, al |
1650 | test al, al |
1663 | jz .set_first_available_media |
1651 | jz .set_first_available_media |
1664 | DEBUGF 1,"Using 10BASE-2 port\n" |
1652 | DEBUGF 1,"Using 10BASE-2 port\n" |
1665 | ret |
1653 | ret |
1666 | 1654 | ||
1667 | .set_first_available_media: |
1655 | .set_first_available_media: |
1668 | DEBUGF 1,"Using the first available media\n" |
1656 | DEBUGF 1,"Using the first available media\n" |
1669 | 1657 | ||
1670 | ;*************************************************************************** |
1658 | ;*************************************************************************** |
1671 | ; Function |
1659 | ; Function |
1672 | ; set_available_media |
1660 | ; set_available_media |
1673 | ; Description |
1661 | ; Description |
1674 | ; sets the first available media |
1662 | ; sets the first available media |
1675 | ; Parameters |
1663 | ; Parameters |
1676 | ; ebx - ptr to device struct |
1664 | ; ebx - ptr to device struct |
1677 | ; Return value |
1665 | ; Return value |
1678 | ; al - 0 |
1666 | ; al - 0 |
1679 | ; al - 1 |
1667 | ; al - 1 |
1680 | ; Destroyed registers |
1668 | ; Destroyed registers |
1681 | ; eax, edx |
1669 | ; eax, edx |
1682 | ; |
1670 | ; |
1683 | ;*************************************************************************** |
1671 | ;*************************************************************************** |
1684 | 1672 | ||
1685 | align 4 |
1673 | align 4 |
1686 | set_available_media: |
1674 | set_available_media: |
1687 | 1675 | ||
1688 | DEBUGF 1,"Setting the available media\n" |
1676 | DEBUGF 1,"Setting the available media\n" |
1689 | ; switch to register window 3 |
1677 | ; switch to register window 3 |
1690 | set_io [ebx + device.io_addr], 0 |
1678 | set_io [ebx + device.io_addr], 0 |
1691 | set_io [ebx + device.io_addr], REG_COMMAND |
1679 | set_io [ebx + device.io_addr], REG_COMMAND |
1692 | mov ax, SELECT_REGISTER_WINDOW+3 |
1680 | mov ax, SELECT_REGISTER_WINDOW+3 |
1693 | out dx, ax |
1681 | out dx, ax |
1694 | 1682 | ||
1695 | set_io [ebx + device.io_addr], REG_MEDIA_OPTIONS |
1683 | set_io [ebx + device.io_addr], REG_MEDIA_OPTIONS |
1696 | in ax, dx |
1684 | in ax, dx |
1697 | DEBUGF 1,"available media:%x\n", al |
1685 | DEBUGF 1,"available media:%x\n", al |
1698 | mov cl, al |
1686 | mov cl, al |
1699 | 1687 | ||
1700 | set_io [ebx + device.io_addr], REG_INTERNAL_CONFIG |
1688 | set_io [ebx + device.io_addr], REG_INTERNAL_CONFIG |
1701 | in eax, dx |
1689 | in eax, dx |
1702 | and eax, not (1111b shl 20) ; these bits hold the 'transceiver select' value |
1690 | and eax, not (1111b shl 20) ; these bits hold the 'transceiver select' value |
1703 | 1691 | ||
1704 | test cl, 10b ; baseTXAvailable |
1692 | test cl, 10b ; baseTXAvailable |
1705 | jz @f |
1693 | jz @f |
1706 | 1694 | ||
1707 | DEBUGF 1,"base TX is available\n" |
1695 | DEBUGF 1,"base TX is available\n" |
1708 | or eax, (100b shl 20) |
1696 | or eax, (100b shl 20) |
1709 | if FORCE_FD |
1697 | if FORCE_FD |
1710 | mov word [ebx + device.internal_link], (1 shl 8) |
1698 | mov word [ebx + device.internal_link], (1 shl 8) |
1711 | else |
1699 | else |
1712 | mov word [ebx + device.internal_link], (1 shl 7) |
1700 | mov word [ebx + device.internal_link], (1 shl 7) |
1713 | end if |
1701 | end if |
1714 | jmp .set_media |
1702 | jmp .set_media |
1715 | @@: |
1703 | @@: |
1716 | 1704 | ||
1717 | test cl, 100b ; baseFXAvailable |
1705 | test cl, 100b ; baseFXAvailable |
1718 | jz @f |
1706 | jz @f |
1719 | 1707 | ||
1720 | DEBUGF 1,"base FX is available\n" |
1708 | DEBUGF 1,"base FX is available\n" |
1721 | or eax, (101b shl 20) |
1709 | or eax, (101b shl 20) |
1722 | mov word [ebx + device.internal_link], (1 shl 10) |
1710 | mov word [ebx + device.internal_link], (1 shl 10) |
1723 | jmp .set_media |
1711 | jmp .set_media |
1724 | @@: |
1712 | @@: |
1725 | 1713 | ||
1726 | test cl, 1000000b ; miiDevice |
1714 | test cl, 1000000b ; miiDevice |
1727 | jz @f |
1715 | jz @f |
1728 | 1716 | ||
1729 | DEBUGF 1,"mii-device is available\n" |
1717 | DEBUGF 1,"mii-device is available\n" |
1730 | or eax, (0110b shl 20) |
1718 | or eax, (0110b shl 20) |
1731 | mov word [ebx + device.internal_link], (1 shl 13) |
1719 | mov word [ebx + device.internal_link], (1 shl 13) |
1732 | jmp .set_media |
1720 | jmp .set_media |
1733 | @@: |
1721 | @@: |
1734 | 1722 | ||
1735 | test cl, 1000b ; 10bTAvailable |
1723 | test cl, 1000b ; 10bTAvailable |
1736 | jz @f |
1724 | jz @f |
1737 | 1725 | ||
1738 | DEBUGF 1,"10base-T is available\n" |
1726 | DEBUGF 1,"10base-T is available\n" |
1739 | .set_default: |
1727 | .set_default: |
1740 | if FORCE_FD |
1728 | if FORCE_FD |
1741 | mov word [ebx + device.internal_link], (1 shl 6) |
1729 | mov word [ebx + device.internal_link], (1 shl 6) |
1742 | else |
1730 | else |
1743 | mov word [ebx + device.internal_link], (1 shl 5) |
1731 | mov word [ebx + device.internal_link], (1 shl 5) |
1744 | end if |
1732 | end if |
1745 | jmp .set_media |
1733 | jmp .set_media |
1746 | @@: |
1734 | @@: |
1747 | 1735 | ||
1748 | test cl, 10000b ; coaxAvailable |
1736 | test cl, 10000b ; coaxAvailable |
1749 | jz @f |
1737 | jz @f |
1750 | 1738 | ||
1751 | DEBUGF 1,"coax is available\n" |
1739 | DEBUGF 1,"coax is available\n" |
1752 | push eax |
1740 | push eax |
1753 | set_io [ebx + device.io_addr], REG_COMMAND |
1741 | set_io [ebx + device.io_addr], REG_COMMAND |
1754 | mov ax, (10b shl 11) ; EnableDcConverter |
1742 | mov ax, (10b shl 11) ; EnableDcConverter |
1755 | out dx, ax |
1743 | out dx, ax |
1756 | pop eax |
1744 | pop eax |
1757 | 1745 | ||
1758 | or eax, (11b shl 20) |
1746 | or eax, (11b shl 20) |
1759 | mov word [ebx + device.internal_link], (1 shl 12) |
1747 | mov word [ebx + device.internal_link], (1 shl 12) |
1760 | jmp .set_media |
1748 | jmp .set_media |
1761 | @@: |
1749 | @@: |
1762 | 1750 | ||
1763 | test cl, 10000b ; auiAvailable |
1751 | test cl, 10000b ; auiAvailable |
1764 | jz .set_default |
1752 | jz .set_default |
1765 | 1753 | ||
1766 | DEBUGF 1,"AUI is available\n" |
1754 | DEBUGF 1,"AUI is available\n" |
1767 | or eax, (1 shl 20) |
1755 | or eax, (1 shl 20) |
1768 | mov word [ebx + device.internal_link], (1 shl 11) |
1756 | mov word [ebx + device.internal_link], (1 shl 11) |
1769 | 1757 | ||
1770 | .set_media: |
1758 | .set_media: |
1771 | set_io [ebx + device.io_addr], 0 |
1759 | set_io [ebx + device.io_addr], 0 |
1772 | set_io [ebx + device.io_addr], REG_INTERNAL_CONFIG |
1760 | set_io [ebx + device.io_addr], REG_INTERNAL_CONFIG |
1773 | out dx, eax |
1761 | out dx, eax |
1774 | 1762 | ||
1775 | if FORCE_FD |
1763 | if FORCE_FD |
1776 | DEBUGF 1,"Forcing full duplex\n" |
1764 | DEBUGF 1,"Forcing full duplex\n" |
1777 | set_io [ebx + device.io_addr], REG_MAC_CONTROL |
1765 | set_io [ebx + device.io_addr], REG_MAC_CONTROL |
1778 | in ax, dx |
1766 | in ax, dx |
1779 | or ax, 0x120 |
1767 | or ax, 0x120 |
1780 | out dx, ax |
1768 | out dx, ax |
1781 | end if |
1769 | end if |
1782 | 1770 | ||
1783 | mov al, 1 |
1771 | mov al, 1 |
1784 | ret |
1772 | ret |
1785 | 1773 | ||
1786 | ;*************************************************************************** |
1774 | ;*************************************************************************** |
1787 | ; Function |
1775 | ; Function |
1788 | ; write_eeprom |
1776 | ; write_eeprom |
1789 | ; Description |
1777 | ; Description |
1790 | ; reads eeprom |
1778 | ; reads eeprom |
1791 | ; Note : the caller must switch to the register window 0 |
1779 | ; Note : the caller must switch to the register window 0 |
1792 | ; before calling this function |
1780 | ; before calling this function |
1793 | ; Parameters: |
1781 | ; Parameters: |
1794 | ; ax - register to be read (only the first 63 words can be read) |
1782 | ; ax - register to be read (only the first 63 words can be read) |
1795 | ; cx - value to be read into the register |
1783 | ; cx - value to be read into the register |
1796 | ; Return value: |
1784 | ; Return value: |
1797 | ; ax - word read |
1785 | ; ax - word read |
1798 | ; Destroyed registers |
1786 | ; Destroyed registers |
1799 | ; ax, ebx, edx |
1787 | ; ax, ebx, edx |
1800 | ; |
1788 | ; |
1801 | ;*************************************************************************** |
1789 | ;*************************************************************************** |
1802 | ; align 4 |
1790 | ; align 4 |
1803 | ;write_eeprom: |
1791 | ;write_eeprom: |
1804 | ; mov edx, [io_addr] |
1792 | ; mov edx, [io_addr] |
1805 | ; add edx, REG_EEPROM_COMMAND |
1793 | ; add edx, REG_EEPROM_COMMAND |
1806 | ; cmp ah, 11b |
1794 | ; cmp ah, 11b |
1807 | ; ja .finish ; address may have a value of maximal 1023 |
1795 | ; ja .finish ; address may have a value of maximal 1023 |
1808 | ; shl ax, 2 |
1796 | ; shl ax, 2 |
1809 | ; shr al, 2 |
1797 | ; shr al, 2 |
1810 | ; push eax |
1798 | ; push eax |
1811 | ;; wait for busy |
1799 | ;; wait for busy |
1812 | ; mov ebx, 0xffff |
1800 | ; mov ebx, 0xffff |
1813 | ;@@: |
1801 | ;@@: |
1814 | ; in ax, dx |
1802 | ; in ax, dx |
1815 | ; test ah, 0x80 |
1803 | ; test ah, 0x80 |
1816 | ; jz .write_enable |
1804 | ; jz .write_enable |
1817 | ; dec ebx |
1805 | ; dec ebx |
1818 | ; jns @r |
1806 | ; jns @r |
1819 | ;; write enable |
1807 | ;; write enable |
1820 | ;.write_enable: |
1808 | ;.write_enable: |
1821 | ; xor eax, eax |
1809 | ; xor eax, eax |
1822 | ; mov eax, (11b shl 4) |
1810 | ; mov eax, (11b shl 4) |
1823 | ; out dx, ax |
1811 | ; out dx, ax |
1824 | ;; wait for busy |
1812 | ;; wait for busy |
1825 | ; mov ebx, 0xffff |
1813 | ; mov ebx, 0xffff |
1826 | ;@@: |
1814 | ;@@: |
1827 | ; in ax, dx |
1815 | ; in ax, dx |
1828 | ; test ah, 0x80 |
1816 | ; test ah, 0x80 |
1829 | ; jz .erase_loop |
1817 | ; jz .erase_loop |
1830 | ; dec ebx |
1818 | ; dec ebx |
1831 | ; jns @r |
1819 | ; jns @r |
1832 | ;.erase_loop: |
1820 | ;.erase_loop: |
1833 | ; pop eax |
1821 | ; pop eax |
1834 | ; push eax |
1822 | ; push eax |
1835 | ; or ax, (11b shl 6) ; erase register |
1823 | ; or ax, (11b shl 6) ; erase register |
1836 | ; out dx, ax |
1824 | ; out dx, ax |
1837 | ; mov ebx, 0xffff |
1825 | ; mov ebx, 0xffff |
1838 | ;@@: |
1826 | ;@@: |
1839 | ; in ax, dx |
1827 | ; in ax, dx |
1840 | ; test ah, 0x80 |
1828 | ; test ah, 0x80 |
1841 | ; jz .write_reg |
1829 | ; jz .write_reg |
1842 | ; dec ebx |
1830 | ; dec ebx |
1843 | ; jns @r |
1831 | ; jns @r |
1844 | ;.write_reg: |
1832 | ;.write_reg: |
1845 | ; add edx, REG_EEPROM_DATA-REG_EEPROM_COMMAND |
1833 | ; add edx, REG_EEPROM_DATA-REG_EEPROM_COMMAND |
1846 | ; mov eax, ecx |
1834 | ; mov eax, ecx |
1847 | ; out dx, ax |
1835 | ; out dx, ax |
1848 | ;; write enable |
1836 | ;; write enable |
1849 | ; add edx, REG_EEPROM_COMMAND-REG_EEPROM_DATA |
1837 | ; add edx, REG_EEPROM_COMMAND-REG_EEPROM_DATA |
1850 | ; xor eax, eax |
1838 | ; xor eax, eax |
1851 | ; mov eax, (11b shl 4) |
1839 | ; mov eax, (11b shl 4) |
1852 | ; out dx, ax |
1840 | ; out dx, ax |
1853 | ; wait for busy |
1841 | ; wait for busy |
1854 | ; mov ebx, 0xffff |
1842 | ; mov ebx, 0xffff |
1855 | ;@@: |
1843 | ;@@: |
1856 | ; in ax, dx |
1844 | ; in ax, dx |
1857 | ; test ah, 0x80 |
1845 | ; test ah, 0x80 |
1858 | ; jz .issue_write_reg |
1846 | ; jz .issue_write_reg |
1859 | ; dec ebx |
1847 | ; dec ebx |
1860 | ; jns @r |
1848 | ; jns @r |
1861 | ;.issue_write_reg: |
1849 | ;.issue_write_reg: |
1862 | ; pop eax |
1850 | ; pop eax |
1863 | ; or ax, 01b shl 6 |
1851 | ; or ax, 01b shl 6 |
1864 | ; out dx, ax |
1852 | ; out dx, ax |
1865 | ;.finish: |
1853 | ;.finish: |
1866 | ; ret |
1854 | ; ret |
1867 | 1855 | ||
1868 | 1856 | ||
1869 | ;*************************************************************************** |
1857 | ;*************************************************************************** |
1870 | ; Function |
1858 | ; Function |
1871 | ; read_eeprom |
1859 | ; read_eeprom |
1872 | ; Description |
1860 | ; Description |
1873 | ; reads eeprom |
1861 | ; reads eeprom |
1874 | ; Parameters: |
1862 | ; Parameters: |
1875 | ; ax - register to be read (only the first 63 words can be read) |
1863 | ; ax - register to be read (only the first 63 words can be read) |
1876 | ; ebx = driver structure |
1864 | ; ebx = driver structure |
1877 | ; Return value: |
1865 | ; Return value: |
1878 | ; ax - word read |
1866 | ; ax - word read |
1879 | ; Destroyed registers |
1867 | ; Destroyed registers |
1880 | ; ax, ebx, edx |
1868 | ; ax, ebx, edx |
1881 | ; |
1869 | ; |
1882 | ;*************************************************************************** |
1870 | ;*************************************************************************** |
1883 | 1871 | ||
1884 | align 4 |
1872 | align 4 |
1885 | read_eeprom: |
1873 | read_eeprom: |
1886 | 1874 | ||
1887 | DEBUGF 1,"Reading from eeprom.. " |
1875 | DEBUGF 1,"Reading from eeprom.. " |
1888 | 1876 | ||
1889 | push eax |
1877 | push eax |
1890 | ; switch to register window 0 |
1878 | ; switch to register window 0 |
1891 | set_io [ebx + device.io_addr], 0 |
1879 | set_io [ebx + device.io_addr], 0 |
1892 | set_io [ebx + device.io_addr], REG_COMMAND |
1880 | set_io [ebx + device.io_addr], REG_COMMAND |
1893 | mov ax, SELECT_REGISTER_WINDOW+0 |
1881 | mov ax, SELECT_REGISTER_WINDOW+0 |
1894 | out dx, ax |
1882 | out dx, ax |
1895 | pop eax |
1883 | pop eax |
1896 | and ax, 111111b ; take only the first 6 bits into account |
1884 | and ax, 111111b ; take only the first 6 bits into account |
1897 | movzx esi, [ebx + device.ver_id] |
1885 | movzx esi, [ebx + device.ver_id] |
1898 | 1886 | ||
1899 | test word [esi*4+hw_versions+2], EEPROM_8BIT |
1887 | test word [esi*4+hw_versions+2], EEPROM_8BIT |
1900 | jz @f |
1888 | jz @f |
1901 | add ax, 0x230 ; hardware constant |
1889 | add ax, 0x230 ; hardware constant |
1902 | jmp .read |
1890 | jmp .read |
1903 | @@: |
1891 | @@: |
1904 | 1892 | ||
1905 | add ax, EEPROM_CMD_READ |
1893 | add ax, EEPROM_CMD_READ |
1906 | test word [esi*4+hw_versions+2], EEPROM_OFFSET |
1894 | test word [esi*4+hw_versions+2], EEPROM_OFFSET |
1907 | jz .read |
1895 | jz .read |
1908 | add ax, 0x30 |
1896 | add ax, 0x30 |
1909 | .read: |
1897 | .read: |
1910 | 1898 | ||
1911 | set_io [ebx + device.io_addr], REG_EEPROM_COMMAND |
1899 | set_io [ebx + device.io_addr], REG_EEPROM_COMMAND |
1912 | out dx, ax |
1900 | out dx, ax |
1913 | mov ecx, 0xffff ; duration of about 162 us ;-) |
1901 | mov ecx, 0xffff ; duration of about 162 us ;-) |
1914 | .wait_for_reading: |
1902 | .wait_for_reading: |
1915 | in ax, dx |
1903 | in ax, dx |
1916 | test ah, 0x80 ; check bit eepromBusy |
1904 | test ah, 0x80 ; check bit eepromBusy |
1917 | jz .read_data |
1905 | jz .read_data |
1918 | loop .wait_for_reading |
1906 | loop .wait_for_reading |
1919 | .read_data: |
1907 | .read_data: |
1920 | set_io [ebx + device.io_addr], REG_EEPROM_DATA |
1908 | set_io [ebx + device.io_addr], REG_EEPROM_DATA |
1921 | in ax, dx |
1909 | in ax, dx |
1922 | 1910 | ||
1923 | DEBUGF 1,"ok!\n" |
1911 | DEBUGF 1,"ok!\n" |
1924 | 1912 | ||
1925 | ret |
1913 | ret |
1926 | 1914 | ||
1927 | ;*************************************************************************** |
1915 | ;*************************************************************************** |
1928 | ; Function |
1916 | ; Function |
1929 | ; mdio_sync |
1917 | ; mdio_sync |
1930 | ; Description |
1918 | ; Description |
1931 | ; initial synchronization |
1919 | ; initial synchronization |
1932 | ; Parameters |
1920 | ; Parameters |
1933 | ; |
1921 | ; |
1934 | ; Return value |
1922 | ; Return value |
1935 | ; Destroyed registers |
1923 | ; Destroyed registers |
1936 | ; ax, edx, cl |
1924 | ; ax, edx, cl |
1937 | ; |
1925 | ; |
1938 | ;*************************************************************************** |
1926 | ;*************************************************************************** |
1939 | 1927 | ||
1940 | align 4 |
1928 | align 4 |
1941 | mdio_sync: |
1929 | mdio_sync: |
1942 | 1930 | ||
1943 | DEBUGF 1,"syncing mdio\n" |
1931 | DEBUGF 1,"syncing mdio\n" |
1944 | 1932 | ||
1945 | ; switch to register window 4 |
1933 | ; switch to register window 4 |
1946 | set_io [ebx + device.io_addr], 0 |
1934 | set_io [ebx + device.io_addr], 0 |
1947 | set_io [ebx + device.io_addr], REG_COMMAND |
1935 | set_io [ebx + device.io_addr], REG_COMMAND |
1948 | mov ax, SELECT_REGISTER_WINDOW+4 |
1936 | mov ax, SELECT_REGISTER_WINDOW+4 |
1949 | out dx, ax |
1937 | out dx, ax |
1950 | cmp [ebx + device.preamble], 0 |
1938 | cmp [ebx + device.preamble], 0 |
1951 | je .no_preamble |
1939 | je .no_preamble |
1952 | ; send 32 logic ones |
1940 | ; send 32 logic ones |
1953 | set_io [ebx + device.io_addr], REG_PHYSICAL_MGMT |
1941 | set_io [ebx + device.io_addr], REG_PHYSICAL_MGMT |
1954 | mov ecx, 31 |
1942 | mov ecx, 31 |
1955 | .loop: |
1943 | .loop: |
1956 | mov ax, (1 shl BIT_MGMT_DATA) or (1 shl BIT_MGMT_DIR) |
1944 | mov ax, (1 shl BIT_MGMT_DATA) or (1 shl BIT_MGMT_DIR) |
1957 | out dx, ax |
1945 | out dx, ax |
1958 | in ax, dx ; delay |
1946 | in ax, dx ; delay |
1959 | mov ax, (1 shl BIT_MGMT_DATA) or (1 shl BIT_MGMT_DIR) or (1 shl BIT_MGMT_CLK) |
1947 | mov ax, (1 shl BIT_MGMT_DATA) or (1 shl BIT_MGMT_DIR) or (1 shl BIT_MGMT_CLK) |
1960 | out dx, ax |
1948 | out dx, ax |
1961 | in ax, dx ; delay |
1949 | in ax, dx ; delay |
1962 | loop .loop |
1950 | loop .loop |
1963 | .no_preamble: |
1951 | .no_preamble: |
1964 | 1952 | ||
1965 | ret |
1953 | ret |
1966 | 1954 | ||
1967 | ;*************************************************************************** |
1955 | ;*************************************************************************** |
1968 | ; Function |
1956 | ; Function |
1969 | ; mdio_read |
1957 | ; mdio_read |
1970 | ; Description |
1958 | ; Description |
1971 | ; read MII register |
1959 | ; read MII register |
1972 | ; see page 16 in D83840A.pdf |
1960 | ; see page 16 in D83840A.pdf |
1973 | ; Parameters |
1961 | ; Parameters |
1974 | ; ah - PHY addr |
1962 | ; ah - PHY addr |
1975 | ; al - register addr |
1963 | ; al - register addr |
1976 | ; ebx = device structure |
1964 | ; ebx = device structure |
1977 | ; Return value |
1965 | ; Return value |
1978 | ; ax - register read |
1966 | ; ax - register read |
1979 | ; |
1967 | ; |
1980 | ;*************************************************************************** |
1968 | ;*************************************************************************** |
1981 | 1969 | ||
1982 | align 4 |
1970 | align 4 |
1983 | mdio_read: |
1971 | mdio_read: |
1984 | 1972 | ||
1985 | DEBUGF 1,"Reading MII registers\n" |
1973 | DEBUGF 1,"Reading MII registers\n" |
1986 | 1974 | ||
1987 | push eax |
1975 | push eax |
1988 | call mdio_sync ; returns with window #4 |
1976 | call mdio_sync ; returns with window #4 |
1989 | pop eax |
1977 | pop eax |
1990 | set_io [ebx + device.io_addr], 0 |
1978 | set_io [ebx + device.io_addr], 0 |
1991 | set_io [ebx + device.io_addr], REG_PHYSICAL_MGMT |
1979 | set_io [ebx + device.io_addr], REG_PHYSICAL_MGMT |
1992 | shl al, 3 |
1980 | shl al, 3 |
1993 | shr ax, 3 |
1981 | shr ax, 3 |
1994 | and ax, not MII_CMD_MASK |
1982 | and ax, not MII_CMD_MASK |
1995 | or ax, MII_CMD_READ |
1983 | or ax, MII_CMD_READ |
1996 | 1984 | ||
1997 | mov esi, eax |
1985 | mov esi, eax |
1998 | mov ecx, 13 |
1986 | mov ecx, 13 |
1999 | .cmd_loop: |
1987 | .cmd_loop: |
2000 | mov ax, (1 shl BIT_MGMT_DIR) ; write mii |
1988 | mov ax, (1 shl BIT_MGMT_DIR) ; write mii |
2001 | bt esi, ecx |
1989 | bt esi, ecx |
2002 | jnc .zero_bit |
1990 | jnc .zero_bit |
2003 | or al, (1 shl BIT_MGMT_DATA) |
1991 | or al, (1 shl BIT_MGMT_DATA) |
2004 | 1992 | ||
2005 | .zero_bit: |
1993 | .zero_bit: |
2006 | out dx, ax |
1994 | out dx, ax |
2007 | push ax |
1995 | push ax |
2008 | in ax, dx ; delay |
1996 | in ax, dx ; delay |
2009 | pop ax |
1997 | pop ax |
2010 | or al, (1 shl BIT_MGMT_CLK) ; write |
1998 | or al, (1 shl BIT_MGMT_CLK) ; write |
2011 | out dx, ax |
1999 | out dx, ax |
2012 | in ax, dx ; delay |
2000 | in ax, dx ; delay |
2013 | loop .cmd_loop |
2001 | loop .cmd_loop |
2014 | 2002 | ||
2015 | ; read data (18 bits with the two transition bits) |
2003 | ; read data (18 bits with the two transition bits) |
2016 | mov ecx, 17 |
2004 | mov ecx, 17 |
2017 | xor esi, esi |
2005 | xor esi, esi |
2018 | .read_loop: |
2006 | .read_loop: |
2019 | shl esi, 1 |
2007 | shl esi, 1 |
2020 | xor eax, eax ; read comand |
2008 | xor eax, eax ; read comand |
2021 | out dx, ax |
2009 | out dx, ax |
2022 | in ax, dx ; delay |
2010 | in ax, dx ; delay |
2023 | in ax, dx |
2011 | in ax, dx |
2024 | test al, (1 shl BIT_MGMT_DATA) |
2012 | test al, (1 shl BIT_MGMT_DATA) |
2025 | jz .dont_set |
2013 | jz .dont_set |
2026 | inc esi |
2014 | inc esi |
2027 | .dont_set: |
2015 | .dont_set: |
2028 | mov ax, (1 shl BIT_MGMT_CLK) |
2016 | mov ax, (1 shl BIT_MGMT_CLK) |
2029 | out dx, ax |
2017 | out dx, ax |
2030 | in ax, dx ; delay |
2018 | in ax, dx ; delay |
2031 | loop .read_loop |
2019 | loop .read_loop |
2032 | mov eax, esi |
2020 | mov eax, esi |
2033 | 2021 | ||
2034 | ret |
2022 | ret |
2035 | 2023 | ||
2036 | 2024 | ||
2037 | 2025 | ||
2038 | ;*************************************************************************** |
2026 | ;*************************************************************************** |
2039 | ; Function |
2027 | ; Function |
2040 | ; mdio_write |
2028 | ; mdio_write |
2041 | ; Description |
2029 | ; Description |
2042 | ; write MII register |
2030 | ; write MII register |
2043 | ; see page 16 in D83840A.pdf |
2031 | ; see page 16 in D83840A.pdf |
2044 | ; Parameters |
2032 | ; Parameters |
2045 | ; ah - PHY addr |
2033 | ; ah - PHY addr |
2046 | ; al - register addr |
2034 | ; al - register addr |
2047 | ; si - word to be written |
2035 | ; si - word to be written |
2048 | ; Return value |
2036 | ; Return value |
2049 | ; ax - register read |
2037 | ; ax - register read |
2050 | ; |
2038 | ; |
2051 | ;*************************************************************************** |
2039 | ;*************************************************************************** |
2052 | 2040 | ||
2053 | align 4 |
2041 | align 4 |
2054 | mdio_write: |
2042 | mdio_write: |
2055 | 2043 | ||
2056 | DEBUGF 1,"Writing MII registers\n" |
2044 | DEBUGF 1,"Writing MII registers\n" |
2057 | 2045 | ||
2058 | push eax |
2046 | push eax |
2059 | call mdio_sync |
2047 | call mdio_sync |
2060 | pop eax |
2048 | pop eax |
2061 | set_io [ebx + device.io_addr], 0 |
2049 | set_io [ebx + device.io_addr], 0 |
2062 | set_io [ebx + device.io_addr], REG_PHYSICAL_MGMT |
2050 | set_io [ebx + device.io_addr], REG_PHYSICAL_MGMT |
2063 | shl al, 3 |
2051 | shl al, 3 |
2064 | shr ax, 3 |
2052 | shr ax, 3 |
2065 | and ax, not MII_CMD_MASK |
2053 | and ax, not MII_CMD_MASK |
2066 | or ax, MII_CMD_WRITE |
2054 | or ax, MII_CMD_WRITE |
2067 | shl eax, 2 |
2055 | shl eax, 2 |
2068 | or eax, 10b ; transition bits |
2056 | or eax, 10b ; transition bits |
2069 | shl eax, 16 |
2057 | shl eax, 16 |
2070 | mov ax, si |
2058 | mov ax, si |
2071 | mov esi, eax |
2059 | mov esi, eax |
2072 | mov ecx, 31 |
2060 | mov ecx, 31 |
2073 | 2061 | ||
2074 | .cmd_loop: |
2062 | .cmd_loop: |
2075 | mov ax, (1 shl BIT_MGMT_DIR) ; write mii |
2063 | mov ax, (1 shl BIT_MGMT_DIR) ; write mii |
2076 | bt esi, ecx |
2064 | bt esi, ecx |
2077 | jnc @f |
2065 | jnc @f |
2078 | or al, (1 shl BIT_MGMT_DATA) |
2066 | or al, (1 shl BIT_MGMT_DATA) |
2079 | @@: |
2067 | @@: |
2080 | out dx, ax |
2068 | out dx, ax |
2081 | push eax |
2069 | push eax |
2082 | in ax, dx ; delay |
2070 | in ax, dx ; delay |
2083 | pop eax |
2071 | pop eax |
2084 | or al, (1 shl BIT_MGMT_CLK) ; write |
2072 | or al, (1 shl BIT_MGMT_CLK) ; write |
2085 | out dx, ax |
2073 | out dx, ax |
2086 | in ax, dx ; delay |
2074 | in ax, dx ; delay |
2087 | loop .cmd_loop |
2075 | loop .cmd_loop |
2088 | 2076 | ||
2089 | ret |
2077 | ret |
2090 | 2078 | ||
2091 | 2079 | ||
2092 | ;*************************************************************************** |
2080 | ;*************************************************************************** |
2093 | ; Function |
2081 | ; Function |
2094 | ; check_tx_status |
2082 | ; check_tx_status |
2095 | ; Description |
2083 | ; Description |
2096 | ; Checks TxStatus queue. |
2084 | ; Checks TxStatus queue. |
2097 | ; Return value |
2085 | ; Return value |
2098 | ; al - 0 no error was found |
2086 | ; al - 0 no error was found |
2099 | ; al - 1 error was found TxReset was needed |
2087 | ; al - 1 error was found TxReset was needed |
2100 | ; Destroyed registers |
2088 | ; Destroyed registers |
2101 | ; eax, ecx, edx |
2089 | ; eax, ecx, edx |
2102 | ; |
2090 | ; |
2103 | ;*************************************************************************** |
2091 | ;*************************************************************************** |
2104 | 2092 | ||
2105 | align 4 |
2093 | align 4 |
2106 | check_tx_status: |
2094 | check_tx_status: |
2107 | 2095 | ||
2108 | DEBUGF 1,"Checking TX status\n" |
2096 | DEBUGF 1,"Checking TX status\n" |
2109 | 2097 | ||
2110 | ; clear TxStatus queue |
2098 | ; clear TxStatus queue |
2111 | set_io [ebx + device.io_addr], 0 |
2099 | set_io [ebx + device.io_addr], 0 |
2112 | set_io [ebx + device.io_addr], REG_TX_STATUS |
2100 | set_io [ebx + device.io_addr], REG_TX_STATUS |
2113 | mov ecx, 31 ; max number of queue entries |
2101 | mov ecx, 31 ; max number of queue entries |
2114 | 2102 | ||
2115 | .tx_status_loop: |
2103 | .tx_status_loop: |
2116 | in al, dx |
2104 | in al, dx |
2117 | test al, al |
2105 | test al, al |
2118 | jz .finish ; no error |
2106 | jz .finish ; no error |
2119 | test al, 0x3f |
2107 | test al, 0x3f |
2120 | jnz .error |
2108 | jnz .error |
2121 | .no_error_found: |
2109 | .no_error_found: |
2122 | ; clear current TxStatus entry which advances the next one |
2110 | ; clear current TxStatus entry which advances the next one |
2123 | xor al, al |
2111 | xor al, al |
2124 | out dx, al |
2112 | out dx, al |
2125 | loop .tx_status_loop |
2113 | loop .tx_status_loop |
2126 | 2114 | ||
2127 | .finish: |
2115 | .finish: |
2128 | ret |
2116 | ret |
2129 | 2117 | ||
2130 | .error: |
2118 | .error: |
2131 | call tx_reset |
2119 | call tx_reset |
2132 | ret |
2120 | ret |
2133 | 2121 | ||
2134 | 2122 | ||
2135 | 2123 | ||
2136 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2124 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2137 | ;; ;; |
2125 | ;; ;; |
2138 | ;; Transmit (vortex) ;; |
2126 | ;; Transmit (vortex) ;; |
2139 | ;; ;; |
2127 | ;; ;; |
2140 | ;; In: buffer pointer in [esp+4] ;; |
2128 | ;; In: pointer to device structure in ebx ;; |
2141 | ;; pointer to device structure in ebx ;; |
2129 | ;; Out: eax = 0 on success ;; |
2142 | ;; ;; |
2130 | ;; ;; |
2143 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2131 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2144 | 2132 | align 16 |
|
2145 | proc vortex_transmit stdcall bufferptr |
2133 | proc vortex_transmit stdcall bufferptr |
2146 | 2134 | ||
2147 | pushf |
- | |
2148 | cli |
2135 | spin_lock_irqsave |
2149 | 2136 | ||
2150 | mov esi, [bufferptr] |
2137 | mov esi, [bufferptr] |
2151 | DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length] |
2138 | DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length] |
2152 | lea eax, [esi + NET_BUFF.data] |
2139 | lea eax, [esi + NET_BUFF.data] |
2153 | DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\ |
2140 | DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\ |
2154 | [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\ |
2141 | [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\ |
2155 | [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\ |
2142 | [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\ |
2156 | [eax+13]:2,[eax+12]:2 |
2143 | [eax+13]:2,[eax+12]:2 |
2157 | 2144 | ||
2158 | cmp [esi + NET_BUFF.length], 1514 |
2145 | cmp [esi + NET_BUFF.length], 1514 |
2159 | ja .fail |
2146 | ja .error |
2160 | cmp [esi + NET_BUFF.length], 60 |
2147 | cmp [esi + NET_BUFF.length], 60 |
2161 | jb .fail |
2148 | jb .error |
2162 | 2149 | ||
2163 | call check_tx_status |
2150 | call check_tx_status |
2164 | 2151 | ||
2165 | ; switch to register window 7 |
2152 | ; switch to register window 7 |
2166 | set_io [ebx + device.io_addr], 0 |
2153 | set_io [ebx + device.io_addr], 0 |
2167 | set_io [ebx + device.io_addr], REG_COMMAND |
2154 | set_io [ebx + device.io_addr], REG_COMMAND |
2168 | mov ax, SELECT_REGISTER_WINDOW+7 |
2155 | mov ax, SELECT_REGISTER_WINDOW + 7 |
2169 | out dx, ax |
2156 | out dx, ax |
2170 | 2157 | ||
2171 | ; check for master operation in progress |
2158 | ; check for master operation in progress |
2172 | set_io [ebx + device.io_addr], REG_MASTER_STATUS |
2159 | set_io [ebx + device.io_addr], REG_MASTER_STATUS |
2173 | in ax, dx |
2160 | in ax, dx |
2174 | test ah, 0x80 |
2161 | test ah, 0x80 |
2175 | jnz .fail ; no DMA for sending |
2162 | jnz .overrun ; no DMA for sending |
2176 | 2163 | ||
2177 | ; program frame address to be sent |
2164 | ; program frame address to be sent |
2178 | set_io [ebx + device.io_addr], REG_MASTER_ADDRESS |
2165 | set_io [ebx + device.io_addr], REG_MASTER_ADDRESS |
2179 | mov eax, esi |
2166 | mov eax, esi |
2180 | add eax, [eax + NET_BUFF.offset] |
2167 | add eax, [eax + NET_BUFF.offset] |
2181 | invoke GetPhysAddr |
2168 | invoke GetPhysAddr |
2182 | out dx, eax |
2169 | out dx, eax |
2183 | 2170 | ||
2184 | ; program frame length |
2171 | ; program frame length |
2185 | set_io [ebx + device.io_addr], REG_MASTER_LEN |
2172 | set_io [ebx + device.io_addr], REG_MASTER_LEN |
2186 | mov eax, [esi + NET_BUFF.length] |
2173 | mov eax, [esi + NET_BUFF.length] |
2187 | out dx, ax |
2174 | out dx, ax |
2188 | 2175 | ||
2189 | ; start DMA Down |
2176 | ; start DMA Down |
2190 | set_io [ebx + device.io_addr], REG_COMMAND |
2177 | set_io [ebx + device.io_addr], REG_COMMAND |
2191 | mov ax, (10100b shl 11) + 1 ; StartDMADown |
2178 | mov ax, (10100b shl 11) + 1 ; StartDMADown |
2192 | out dx, ax |
2179 | out dx, ax |
- | 2180 | ||
2193 | .finish: |
2181 | ; Update stats |
- | 2182 | inc [ebx + device.packets_tx] |
|
- | 2183 | mov eax, [esi + NET_BUFF.length] |
|
- | 2184 | add dword[ebx + device.bytes_tx], eax |
|
- | 2185 | adc dword[ebx + device.bytes_tx + 4], 0 |
|
- | 2186 | ||
2194 | popf |
2187 | spin_unlock_irqrestore |
2195 | xor eax, eax |
2188 | xor eax, eax |
2196 | ret |
2189 | ret |
2197 | 2190 | ||
- | 2191 | .error: |
|
- | 2192 | DEBUGF 2, "TX packet error\n" |
|
- | 2193 | inc [ebx + device.packets_tx_err] |
|
- | 2194 | invoke NetFree, [bufferptr] |
|
- | 2195 | ||
- | 2196 | spin_unlock_irqrestore |
|
- | 2197 | or eax, -1 |
|
- | 2198 | ret |
|
- | 2199 | ||
2198 | .fail: |
2200 | .overrun: |
- | 2201 | DEBUGF 2, "TX overrun\n" |
|
2199 | DEBUGF 2,"Send failed\n" |
2202 | inc [ebx + device.packets_tx_ovr] |
- | 2203 | invoke NetFree, [bufferptr] |
|
2200 | invoke NetFree, [bufferptr] |
2204 | |
2201 | popf |
2205 | spin_unlock_irqrestore |
2202 | or eax, -1 |
2206 | or eax, -1 |
2203 | ret |
2207 | ret |
2204 | 2208 | ||
2205 | endp |
2209 | endp |
2206 | 2210 | ||
2207 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2211 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2208 | ;; ;; |
2212 | ;; ;; |
2209 | ;; Transmit (boomerang) ;; |
2213 | ;; Transmit (boomerang) ;; |
2210 | ;; ;; |
2214 | ;; ;; |
2211 | ;; In: buffer pointer in [esp+4] ;; |
2215 | ;; In: pointer to device structure in ebx ;; |
2212 | ;; pointer to device structure in ebx ;; |
2216 | ;; Out: eax = 0 on success ;; |
2213 | ;; ;; |
2217 | ;; ;; |
2214 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2218 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2215 | 2219 | align 16 |
|
2216 | proc boomerang_transmit stdcall bufferptr |
2220 | proc boomerang_transmit stdcall bufferptr |
2217 | 2221 | ||
2218 | pushf |
- | |
2219 | cli |
2222 | spin_lock_irqsave |
2220 | 2223 | ||
2221 | mov esi, [bufferptr] |
2224 | mov esi, [bufferptr] |
2222 | DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length] |
2225 | DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length] |
2223 | lea eax, [esi + NET_BUFF.data] |
2226 | lea eax, [esi + NET_BUFF.data] |
2224 | DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\ |
2227 | DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\ |
2225 | [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\ |
2228 | [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\ |
2226 | [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\ |
2229 | [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\ |
2227 | [eax+13]:2,[eax+12]:2 |
2230 | [eax+13]:2,[eax+12]:2 |
2228 | 2231 | ||
2229 | cmp [esi + NET_BUFF.length], 1514 |
2232 | cmp [esi + NET_BUFF.length], 1514 |
2230 | ja .fail |
2233 | ja .error |
2231 | cmp [esi + NET_BUFF.length], 60 |
2234 | cmp [esi + NET_BUFF.length], 60 |
2232 | jb .fail |
2235 | jb .error |
2233 | 2236 | ||
2234 | call check_tx_status ; Reset TX engine if needed |
2237 | call check_tx_status ; Reset TX engine if needed |
2235 | 2238 | ||
2236 | ; calculate descriptor address |
2239 | ; calculate descriptor address |
2237 | mov edi, [ebx + device.curr_tx] |
2240 | mov edi, [ebx + device.curr_tx] |
2238 | DEBUGF 1,"Previous TX desc: %x\n", edi |
2241 | DEBUGF 1,"Previous TX desc: %x\n", edi |
2239 | add edi, sizeof.tx_desc |
2242 | add edi, sizeof.tx_desc |
2240 | lea ecx, [ebx + device.tx_desc_buffer + (NUM_TX_DESC)*sizeof.tx_desc] |
2243 | lea ecx, [ebx + device.tx_desc_buffer + (NUM_TX_DESC)*sizeof.tx_desc] |
2241 | cmp edi, ecx |
2244 | cmp edi, ecx |
2242 | jb @f |
2245 | jb @f |
2243 | lea edi, [ebx + device.tx_desc_buffer] ; Wrap if needed |
2246 | lea edi, [ebx + device.tx_desc_buffer] ; Wrap if needed |
2244 | @@: |
2247 | @@: |
2245 | DEBUGF 1,"Using TX desc: %x\n", esi |
2248 | DEBUGF 1,"Using TX desc: %x\n", esi |
2246 | 2249 | ||
2247 | ; check DnListPtr |
2250 | ; check DnListPtr |
2248 | set_io [ebx + device.io_addr], 0 |
2251 | set_io [ebx + device.io_addr], 0 |
2249 | set_io [ebx + device.io_addr], REG_DN_LIST_PTR |
2252 | set_io [ebx + device.io_addr], REG_DN_LIST_PTR |
2250 | in eax, dx |
2253 | in eax, dx |
2251 | ; mark if Dn_List_Ptr is cleared |
2254 | ; mark if Dn_List_Ptr is cleared |
2252 | test eax, eax |
2255 | test eax, eax |
2253 | setz [ebx + device.dn_list_ptr_cleared] |
2256 | setz [ebx + device.dn_list_ptr_cleared] |
2254 | 2257 | ||
2255 | ; finish if no more free descriptor is available - FIXME! |
2258 | ; finish if no more free descriptor is available - FIXME! |
2256 | ; cmp eax, esi |
2259 | ; cmp eax, esi |
2257 | ; jz .finish |
2260 | ; jz .finish |
2258 | 2261 | ||
2259 | ; update statistics |
2262 | ; update statistics |
2260 | inc [ebx + device.packets_tx] |
2263 | inc [ebx + device.packets_tx] |
2261 | mov ecx, [esi + NET_BUFF.length] |
2264 | mov ecx, [esi + NET_BUFF.length] |
2262 | add dword [ebx + device.bytes_tx], ecx |
2265 | add dword [ebx + device.bytes_tx], ecx |
2263 | adc dword [ebx + device.bytes_tx + 4], 0 |
2266 | adc dword [ebx + device.bytes_tx + 4], 0 |
2264 | 2267 | ||
2265 | ; program DPD |
2268 | ; program DPD |
2266 | and [edi + tx_desc.next_ptr], 0 |
2269 | and [edi + tx_desc.next_ptr], 0 |
2267 | mov eax, [bufferptr] |
2270 | mov eax, [bufferptr] |
2268 | mov [edi + tx_desc.realaddr], eax |
2271 | mov [edi + tx_desc.realaddr], eax |
2269 | add eax, [eax + NET_BUFF.offset] |
2272 | add eax, [eax + NET_BUFF.offset] |
2270 | invoke GetPhysAddr |
2273 | invoke GetPhysAddr |
2271 | mov [edi + tx_desc.frag_addr], eax |
2274 | mov [edi + tx_desc.frag_addr], eax |
2272 | ;;; mov ecx, [buffersize] |
2275 | ;;; mov ecx, [buffersize] |
2273 | or ecx, 0x80000000 ; last fragment flag |
2276 | or ecx, 0x80000000 ; last fragment flag |
2274 | mov [edi + tx_desc.frag_len], ecx |
2277 | mov [edi + tx_desc.frag_len], ecx |
2275 | 2278 | ||
2276 | ;;; mov ecx, [buffersize] ; packet size |
2279 | ;;; mov ecx, [buffersize] ; packet size |
2277 | or ecx, 0x80008000 ; set OWN bit + transmission complete notification flag |
2280 | or ecx, 0x80008000 ; set OWN bit + transmission complete notification flag |
2278 | ; test byte [ebx + device.has_hwcksm], 0xff |
2281 | ; test byte [ebx + device.has_hwcksm], 0xff |
2279 | ; jz @f |
2282 | ; jz @f |
2280 | ; or ecx, (1 shl 26) ; set AddTcpChecksum |
2283 | ; or ecx, (1 shl 26) ; set AddTcpChecksum |
2281 | ;@@: |
2284 | ;@@: |
2282 | mov [edi + tx_desc.frame_start_hdr], ecx |
2285 | mov [edi + tx_desc.frame_start_hdr], ecx |
2283 | DEBUGF 1,"TX desc: lin=%x phys=%x len=%x start hdr=%x\n", [edi+tx_desc.realaddr]:8, [edi+tx_desc.frag_addr]:8, [edi+tx_desc.frag_len]:8, [edi+tx_desc.frame_start_hdr]:8 |
2286 | DEBUGF 1,"TX desc: lin=%x phys=%x len=%x start hdr=%x\n", [edi+tx_desc.realaddr]:8, [edi+tx_desc.frag_addr]:8, [edi+tx_desc.frag_len]:8, [edi+tx_desc.frame_start_hdr]:8 |
2284 | 2287 | ||
2285 | ; calculate physical address of tx descriptor |
2288 | ; calculate physical address of tx descriptor |
2286 | mov eax, edi |
2289 | mov eax, edi |
2287 | invoke GetPhysAddr |
2290 | invoke GetPhysAddr |
2288 | cmp [ebx + device.dn_list_ptr_cleared], 0 |
2291 | cmp [ebx + device.dn_list_ptr_cleared], 0 |
2289 | je .add_to_list |
2292 | je .add_to_list |
2290 | 2293 | ||
2291 | ; write Dn_List_Ptr |
2294 | ; write Dn_List_Ptr |
2292 | DEBUGF 1,"TX desc phys addr=%x\n", eax |
2295 | DEBUGF 1,"TX desc phys addr=%x\n", eax |
2293 | set_io [ebx + device.io_addr], 0 |
2296 | set_io [ebx + device.io_addr], 0 |
2294 | set_io [ebx + device.io_addr], REG_DN_LIST_PTR |
2297 | set_io [ebx + device.io_addr], REG_DN_LIST_PTR |
2295 | out dx, eax |
2298 | out dx, eax |
2296 | jmp .finish |
2299 | jmp .finish |
2297 | 2300 | ||
2298 | .add_to_list: |
2301 | .add_to_list: |
2299 | DEBUGF 1,"Adding To list\n" |
2302 | DEBUGF 1,"Adding To list\n" |
2300 | push eax |
2303 | push eax |
2301 | ; DnStall |
2304 | ; DnStall |
2302 | set_io [ebx + device.io_addr], 0 |
2305 | set_io [ebx + device.io_addr], 0 |
2303 | set_io [ebx + device.io_addr], REG_COMMAND |
2306 | set_io [ebx + device.io_addr], REG_COMMAND |
2304 | mov ax, ((110b shl 11)+2) |
2307 | mov ax, ((110b shl 11)+2) |
2305 | out dx, ax |
2308 | out dx, ax |
2306 | 2309 | ||
2307 | ; wait for DnStall to complete |
2310 | ; wait for DnStall to complete |
2308 | DEBUGF 1,"Waiting for DnStall\n" |
2311 | DEBUGF 1,"Waiting for DnStall\n" |
2309 | mov ecx, 6000 |
2312 | mov ecx, 6000 |
2310 | .wait_for_stall: |
2313 | .wait_for_stall: |
2311 | in ax, dx ; read REG_INT_STATUS |
2314 | in ax, dx ; read REG_INT_STATUS |
2312 | test ah, 10000b |
2315 | test ah, 10000b |
2313 | jz .dnstall_ok |
2316 | jz .dnstall_ok |
2314 | dec ecx |
2317 | dec ecx |
2315 | jnz .wait_for_stall |
2318 | jnz .wait_for_stall |
2316 | 2319 | ||
2317 | .dnstall_ok: |
2320 | .dnstall_ok: |
2318 | DEBUGF 1,"DnStall ok!\n" |
2321 | DEBUGF 1,"DnStall ok!\n" |
2319 | mov ecx, [ebx + device.curr_tx] |
2322 | mov ecx, [ebx + device.curr_tx] |
2320 | mov [ecx + tx_desc.next_ptr], eax |
2323 | mov [ecx + tx_desc.next_ptr], eax |
2321 | 2324 | ||
2322 | set_io [ebx + device.io_addr], 0 |
2325 | set_io [ebx + device.io_addr], 0 |
2323 | set_io [ebx + device.io_addr], REG_DN_LIST_PTR |
2326 | set_io [ebx + device.io_addr], REG_DN_LIST_PTR |
2324 | in eax, dx |
2327 | in eax, dx |
2325 | test eax, eax |
2328 | test eax, eax |
2326 | pop eax |
2329 | pop eax |
2327 | jnz .dnunstall |
2330 | jnz .dnunstall |
2328 | 2331 | ||
2329 | ; if Dn_List_Ptr has been cleared fill it up |
2332 | ; if Dn_List_Ptr has been cleared fill it up |
2330 | DEBUGF 1,"DnList Ptr has been cleared\n" |
2333 | DEBUGF 1,"DnList Ptr has been cleared\n" |
2331 | out dx, eax |
2334 | out dx, eax |
2332 | 2335 | ||
2333 | .dnunstall: |
2336 | .dnunstall: |
2334 | ; DnUnStall |
2337 | ; DnUnStall |
2335 | set_io [ebx + device.io_addr], 0 |
2338 | set_io [ebx + device.io_addr], 0 |
2336 | set_io [ebx + device.io_addr], REG_COMMAND |
2339 | set_io [ebx + device.io_addr], REG_COMMAND |
2337 | mov ax, ((110b shl 11)+3) |
2340 | mov ax, ((110b shl 11)+3) |
2338 | out dx, ax |
2341 | out dx, ax |
2339 | 2342 | ||
2340 | .finish: |
2343 | .finish: |
2341 | mov [ebx + device.curr_tx], edi |
2344 | mov [ebx + device.curr_tx], edi |
- | 2345 | ||
2342 | popf |
2346 | ; Update stats |
- | 2347 | inc [ebx + device.packets_tx] |
|
- | 2348 | mov eax, [esi + NET_BUFF.length] |
|
- | 2349 | add dword[ebx + device.bytes_tx], eax |
|
- | 2350 | adc dword[ebx + device.bytes_tx + 4], 0 |
|
- | 2351 | ||
- | 2352 | spin_unlock_irqrestore |
|
2343 | xor eax, eax |
2353 | xor eax, eax |
2344 | ret |
2354 | ret |
2345 | 2355 | ||
- | 2356 | .error: |
|
- | 2357 | DEBUGF 2, "TX packet error\n" |
|
- | 2358 | inc [ebx + device.packets_tx_err] |
|
- | 2359 | invoke NetFree, [bufferptr] |
|
- | 2360 | ||
- | 2361 | spin_unlock_irqrestore |
|
- | 2362 | or eax, -1 |
|
- | 2363 | ret |
|
- | 2364 | ||
2346 | .fail: |
2365 | .overrun: |
- | 2366 | DEBUGF 2, "TX overrun\n" |
|
2347 | DEBUGF 2,"Send failed\n" |
2367 | inc [ebx + device.packets_tx_ovr] |
- | 2368 | invoke NetFree, [bufferptr] |
|
2348 | invoke NetFree, [bufferptr] |
2369 | |
2349 | popf |
2370 | spin_unlock_irqrestore |
2350 | or eax, -1 |
2371 | or eax, -1 |
2351 | ret |
2372 | ret |
2352 | 2373 | ||
2353 | endp |
2374 | endp |
2354 | 2375 | ||
2355 | 2376 | ||
2356 | 2377 | ||
2357 | ;--------------------------------- |
2378 | ;--------------------------------- |
2358 | ; Write MAC |
2379 | ; Write MAC |
2359 | 2380 | ||
2360 | align 4 |
2381 | align 4 |
2361 | write_mac: |
2382 | write_mac: |
2362 | 2383 | ||
2363 | DEBUGF 1,"Writing mac\n" |
2384 | DEBUGF 1,"Writing mac\n" |
2364 | 2385 | ||
2365 | set_io [ebx + device.io_addr], 0 |
2386 | set_io [ebx + device.io_addr], 0 |
2366 | set_io [ebx + device.io_addr], REG_COMMAND |
2387 | set_io [ebx + device.io_addr], REG_COMMAND |
2367 | 2388 | ||
2368 | ; switch to register window 2 |
2389 | ; switch to register window 2 |
2369 | mov ax, SELECT_REGISTER_WINDOW+2 |
2390 | mov ax, SELECT_REGISTER_WINDOW+2 |
2370 | out dx, ax |
2391 | out dx, ax |
2371 | 2392 | ||
2372 | ; write MAC addres back into the station address registers |
2393 | ; write MAC addres back into the station address registers |
2373 | set_io [ebx + device.io_addr], REG_STATION_ADDRESS_LO |
2394 | set_io [ebx + device.io_addr], REG_STATION_ADDRESS_LO |
2374 | lea esi, [ebx + device.mac] |
2395 | lea esi, [ebx + device.mac] |
2375 | outsw |
2396 | outsw |
2376 | inc dx |
2397 | inc dx |
2377 | inc dx |
2398 | inc dx |
2378 | outsw |
2399 | outsw |
2379 | inc dx |
2400 | inc dx |
2380 | inc dx |
2401 | inc dx |
2381 | outsw |
2402 | outsw |
2382 | 2403 | ||
2383 | 2404 | ||
2384 | ;---------------------------- |
2405 | ;---------------------------- |
2385 | ; Read MAC |
2406 | ; Read MAC |
2386 | 2407 | ||
2387 | align 4 |
2408 | align 4 |
2388 | read_mac: |
2409 | read_mac: |
2389 | 2410 | ||
2390 | DEBUGF 1,"Reading MAC\n" |
2411 | DEBUGF 1,"Reading MAC\n" |
2391 | 2412 | ||
2392 | set_io [ebx + device.io_addr], 0 |
2413 | set_io [ebx + device.io_addr], 0 |
2393 | set_io [ebx + device.io_addr], REG_COMMAND |
2414 | set_io [ebx + device.io_addr], REG_COMMAND |
2394 | 2415 | ||
2395 | ; switch to register window 2 |
2416 | ; switch to register window 2 |
2396 | mov ax, SELECT_REGISTER_WINDOW+2 |
2417 | mov ax, SELECT_REGISTER_WINDOW+2 |
2397 | out dx, ax |
2418 | out dx, ax |
2398 | 2419 | ||
2399 | ; Read the MAC and write it to device.mac |
2420 | ; Read the MAC and write it to device.mac |
2400 | set_io [ebx + device.io_addr], REG_STATION_ADDRESS_LO |
2421 | set_io [ebx + device.io_addr], REG_STATION_ADDRESS_LO |
2401 | lea edi, [ebx + device.mac] |
2422 | lea edi, [ebx + device.mac] |
2402 | insw |
2423 | insw |
2403 | inc dx |
2424 | inc dx |
2404 | inc dx |
2425 | inc dx |
2405 | insw |
2426 | insw |
2406 | inc dx |
2427 | inc dx |
2407 | inc dx |
2428 | inc dx |
2408 | insw |
2429 | insw |
2409 | 2430 | ||
2410 | DEBUGF 1,"%x-%x-%x-%x-%x-%x\n", \ |
2431 | DEBUGF 1,"%x-%x-%x-%x-%x-%x\n", \ |
2411 | [ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,\ |
2432 | [ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,\ |
2412 | [ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2 |
2433 | [ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2 |
2413 | 2434 | ||
2414 | ret |
2435 | ret |
2415 | 2436 | ||
2416 | 2437 | ||
2417 | ;------------------------------------ |
2438 | ;------------------------------------ |
2418 | ; Read MAC from eeprom |
2439 | ; Read MAC from eeprom |
2419 | 2440 | ||
2420 | align 4 |
2441 | align 4 |
2421 | read_mac_eeprom: |
2442 | read_mac_eeprom: |
2422 | 2443 | ||
2423 | DEBUGF 1,"Reading MAC from eeprom\n" |
2444 | DEBUGF 1,"Reading MAC from eeprom\n" |
2424 | 2445 | ||
2425 | ; read MAC from eeprom and write it to device.mac |
2446 | ; read MAC from eeprom and write it to device.mac |
2426 | mov ecx, 3 |
2447 | mov ecx, 3 |
2427 | .mac_loop: |
2448 | .mac_loop: |
2428 | lea ax, [EEPROM_REG_OEM_NODE_ADDR+ecx-1] |
2449 | lea ax, [EEPROM_REG_OEM_NODE_ADDR+ecx-1] |
2429 | push ecx |
2450 | push ecx |
2430 | call read_eeprom |
2451 | call read_eeprom |
2431 | pop ecx |
2452 | pop ecx |
2432 | xchg ah, al |
2453 | xchg ah, al |
2433 | mov word [ebx + device.mac+ecx*2-2], ax |
2454 | mov word [ebx + device.mac+ecx*2-2], ax |
2434 | loop .mac_loop |
2455 | loop .mac_loop |
2435 | 2456 | ||
2436 | DEBUGF 1,"%x-%x-%x-%x-%x-%x\n",\ |
2457 | DEBUGF 1,"%x-%x-%x-%x-%x-%x\n",\ |
2437 | [ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,\ |
2458 | [ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,\ |
2438 | [ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2 |
2459 | [ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2 |
2439 | 2460 | ||
2440 | ret |
2461 | ret |
2441 | 2462 | ||
2442 | 2463 | ||
2443 | 2464 | ||
2444 | 2465 | ||
2445 | 2466 | ||
2446 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2467 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2447 | ;; ;; |
2468 | ;; ;; |
2448 | ;; Vortex Interrupt handler ;; |
2469 | ;; Vortex Interrupt handler ;; |
2449 | ;; ;; |
2470 | ;; ;; |
2450 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2471 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2451 | - | ||
2452 | align 4 |
2472 | align 16 |
2453 | int_vortex: |
2473 | int_vortex: |
2454 | 2474 | ||
2455 | push ebx esi edi |
2475 | push ebx esi edi |
2456 | - | ||
2457 | DEBUGF 1,"INT\n" |
- | |
2458 | - | ||
2459 | ; find pointer of device wich made IRQ occur |
- | |
2460 | 2476 | ||
2461 | mov ecx, [vortex_devices] |
2477 | mov ebx, [esp+4*4] |
2462 | test ecx, ecx |
- | |
2463 | jz .nothing |
- | |
2464 | mov esi, vortex_list |
- | |
2465 | .nextdevice: |
- | |
- | 2478 | DEBUGF 1,"INT for 0x%x\n", ebx |
|
2466 | mov ebx, [esi] |
2479 | |
2467 | 2480 | ; TODO? if we are paranoid, we can check that the value from ebx is present in the current device_list |
|
2468 | 2481 | ||
2469 | set_io [ebx + device.io_addr], 0 |
2482 | set_io [ebx + device.io_addr], 0 |
2470 | set_io [ebx + device.io_addr], REG_INT_STATUS |
2483 | set_io [ebx + device.io_addr], REG_INT_STATUS |
2471 | in ax, dx |
2484 | in ax, dx |
2472 | and ax, S_5_INTS |
2485 | and ax, S_5_INTS |
2473 | jnz .nothing |
2486 | jnz .nothing |
2474 | - | ||
2475 | add esi, 4 |
- | |
2476 | - | ||
2477 | test ax , ax |
- | |
2478 | jnz .got_it |
- | |
2479 | loop .nextdevice |
- | |
2480 | - | ||
2481 | .nothing: |
- | |
2482 | pop edi esi ebx |
- | |
2483 | xor eax, eax |
- | |
2484 | - | ||
2485 | ret |
- | |
2486 | - | ||
2487 | .got_it: |
- | |
2488 | 2487 | ||
2489 | DEBUGF 1,"Device: %x Status: %x\n", ebx, eax:4 |
2488 | DEBUGF 1,"Status: %x\n", eax:4 |
2490 | 2489 | ||
2491 | test ax, RxComplete |
2490 | test ax, RxComplete |
2492 | jz .noRX |
2491 | jz .noRX |
2493 | 2492 | ||
2494 | set_io [ebx + device.io_addr], 0 |
2493 | set_io [ebx + device.io_addr], 0 |
2495 | .rx_status_loop: |
2494 | .rx_status_loop: |
2496 | ; examine RxStatus |
2495 | ; examine RxStatus |
2497 | set_io [ebx + device.io_addr], REG_RX_STATUS |
2496 | set_io [ebx + device.io_addr], REG_RX_STATUS |
2498 | in ax, dx |
2497 | in ax, dx |
2499 | test ax, ax |
2498 | test ax, ax |
2500 | jz .finish |
2499 | jz .finish |
2501 | 2500 | ||
2502 | test ah, 0x80 ; rxIncomplete |
2501 | test ah, 0x80 ; rxIncomplete |
2503 | jnz .finish |
2502 | jnz .finish |
2504 | 2503 | ||
2505 | test ah, 0x40 |
2504 | test ah, 0x40 |
2506 | jz .check_length |
2505 | jz .check_length |
2507 | 2506 | ||
2508 | ; discard the top frame received advancing the next one |
2507 | ; discard the top frame received advancing the next one |
2509 | set_io [ebx + device.io_addr], REG_COMMAND |
2508 | set_io [ebx + device.io_addr], REG_COMMAND |
2510 | mov ax, (01000b shl 11) |
2509 | mov ax, (01000b shl 11) |
2511 | out dx, ax |
2510 | out dx, ax |
2512 | jmp .rx_status_loop |
2511 | jmp .rx_status_loop |
2513 | 2512 | ||
2514 | .check_length: |
2513 | .check_length: |
2515 | and eax, 0x1fff |
2514 | and eax, 0x1fff |
2516 | cmp eax, MAX_ETH_FRAME_SIZE |
2515 | cmp eax, MAX_ETH_FRAME_SIZE |
2517 | ja .discard_frame ; frame is too long discard it |
2516 | ja .discard_frame ; frame is too long discard it |
2518 | 2517 | ||
2519 | .check_dma: |
2518 | .check_dma: |
2520 | mov ecx, eax |
2519 | mov ecx, eax |
2521 | ; switch to register window 7 |
2520 | ; switch to register window 7 |
2522 | set_io [ebx + device.io_addr], 0 |
2521 | set_io [ebx + device.io_addr], 0 |
2523 | set_io [ebx + device.io_addr], REG_COMMAND |
2522 | set_io [ebx + device.io_addr], REG_COMMAND |
2524 | mov ax, SELECT_REGISTER_WINDOW+7 |
2523 | mov ax, SELECT_REGISTER_WINDOW+7 |
2525 | out dx, ax |
2524 | out dx, ax |
2526 | ; check for master operation in progress |
2525 | ; check for master operation in progress |
2527 | set_io [ebx + device.io_addr], REG_MASTER_STATUS |
2526 | set_io [ebx + device.io_addr], REG_MASTER_STATUS |
2528 | in ax, dx |
2527 | in ax, dx |
2529 | 2528 | ||
2530 | test ah, 0x80 |
2529 | test ah, 0x80 |
2531 | jnz .finish |
2530 | jnz .finish |
2532 | 2531 | ||
2533 | .read_frame: |
2532 | .read_frame: |
2534 | ; program buffer address to read in |
2533 | ; program buffer address to read in |
2535 | push ecx |
2534 | push ecx |
2536 | invoke NetAlloc, MAX_ETH_FRAME_SIZE + NET_BUFF.data |
2535 | invoke NetAlloc, MAX_ETH_FRAME_SIZE + NET_BUFF.data |
2537 | pop ecx |
2536 | pop ecx |
2538 | test eax, eax |
2537 | test eax, eax |
2539 | jz .finish |
2538 | jz .finish |
2540 | 2539 | ||
2541 | push .discard_frame |
2540 | push .discard_frame |
2542 | push eax |
2541 | push eax |
2543 | mov [eax + NET_BUFF.length], ecx |
2542 | mov [eax + NET_BUFF.length], ecx |
2544 | mov [eax + NET_BUFF.device], ebx |
2543 | mov [eax + NET_BUFF.device], ebx |
2545 | mov [eax + NET_BUFF.offset], NET_BUFF.data |
2544 | mov [eax + NET_BUFF.offset], NET_BUFF.data |
2546 | invoke GetPhysAddr |
2545 | invoke GetPhysAddr |
2547 | add eax, NET_BUFF.data |
2546 | add eax, NET_BUFF.data |
2548 | set_io [ebx + device.io_addr], REG_MASTER_ADDRESS |
2547 | set_io [ebx + device.io_addr], REG_MASTER_ADDRESS |
2549 | out dx, eax |
2548 | out dx, eax |
2550 | 2549 | ||
2551 | ; program frame length |
2550 | ; program frame length |
2552 | set_io [ebx + device.io_addr], REG_MASTER_LEN |
2551 | set_io [ebx + device.io_addr], REG_MASTER_LEN |
2553 | mov ax, 1560 |
2552 | mov ax, 1560 |
2554 | out dx, ax |
2553 | out dx, ax |
2555 | 2554 | ||
2556 | ; start DMA Up |
2555 | ; start DMA Up |
2557 | set_io [ebx + device.io_addr], REG_COMMAND |
2556 | set_io [ebx + device.io_addr], REG_COMMAND |
2558 | mov ax, (10100b shl 11) ; StartDMAUp |
2557 | mov ax, (10100b shl 11) ; StartDMAUp |
2559 | out dx, ax |
2558 | out dx, ax |
2560 | 2559 | ||
2561 | ; check for master operation in progress |
2560 | ; check for master operation in progress |
2562 | set_io [ebx + device.io_addr], REG_MASTER_STATUS ; TODO: use timeout and reset after timeout expired |
2561 | set_io [ebx + device.io_addr], REG_MASTER_STATUS ; TODO: use timeout and reset after timeout expired |
2563 | .dma_loop: |
2562 | .dma_loop: |
2564 | in ax, dx |
2563 | in ax, dx |
2565 | test ah, 0x80 |
2564 | test ah, 0x80 |
2566 | jnz .dma_loop |
2565 | jnz .dma_loop |
2567 | 2566 | ||
2568 | ; registrate the received packet to kernel |
2567 | ; registrate the received packet to kernel |
2569 | jmp [EthInput] |
2568 | jmp [EthInput] |
2570 | 2569 | ||
2571 | ; discard the top frame received |
2570 | ; discard the top frame received |
2572 | .discard_frame: |
2571 | .discard_frame: |
2573 | set_io [ebx + device.io_addr], 0 |
2572 | set_io [ebx + device.io_addr], 0 |
2574 | set_io [ebx + device.io_addr], REG_COMMAND |
2573 | set_io [ebx + device.io_addr], REG_COMMAND |
2575 | mov ax, (01000b shl 11) |
2574 | mov ax, (01000b shl 11) |
2576 | out dx, ax |
2575 | out dx, ax |
2577 | 2576 | ||
2578 | .finish: |
2577 | .finish: |
2579 | - | ||
2580 | - | ||
2581 | .noRX: |
2578 | .noRX: |
2582 | - | ||
2583 | test ax, DMADone |
2579 | test ax, DMADone |
2584 | jz .noDMA |
2580 | jz .noDMA |
2585 | 2581 | ||
2586 | push ax |
2582 | push ax |
2587 | 2583 | ||
2588 | set_io [ebx + device.io_addr], 0 |
2584 | set_io [ebx + device.io_addr], 0 |
2589 | set_io [ebx + device.io_addr], 12 |
2585 | set_io [ebx + device.io_addr], 12 |
2590 | in ax, dx |
2586 | in ax, dx |
2591 | test ax, 0x1000 |
2587 | test ax, 0x1000 |
2592 | jz .nodmaclear |
2588 | jz .nodmaclear |
2593 | 2589 | ||
2594 | mov ax, 0x1000 |
2590 | mov ax, 0x1000 |
2595 | out dx, ax |
2591 | out dx, ax |
2596 | 2592 | ||
2597 | .nodmaclear: |
2593 | .nodmaclear: |
2598 | - | ||
2599 | pop ax |
2594 | pop ax |
2600 | 2595 | ||
2601 | DEBUGF 1, "DMA Done!\n", cx |
2596 | DEBUGF 1, "DMA Done!\n", cx |
2602 | - | ||
2603 | - | ||
2604 | 2597 | ||
2605 | .noDMA: |
- | |
2606 | - | ||
2607 | - | ||
2608 | 2598 | .noDMA: |
|
2609 | .ACK: |
2599 | .ACK: |
2610 | set_io [ebx + device.io_addr], 0 |
2600 | set_io [ebx + device.io_addr], 0 |
2611 | set_io [ebx + device.io_addr], REG_COMMAND |
2601 | set_io [ebx + device.io_addr], REG_COMMAND |
2612 | mov ax, AckIntr + IntReq + IntLatch |
2602 | mov ax, AckIntr + IntReq + IntLatch |
2613 | out dx, ax |
2603 | out dx, ax |
2614 | 2604 | ||
2615 | pop edi esi ebx |
2605 | pop edi esi ebx |
- | 2606 | xor eax, eax |
|
- | 2607 | inc eax |
|
- | 2608 | ||
- | 2609 | ret |
|
- | 2610 | ||
- | 2611 | .nothing: |
|
- | 2612 | pop edi esi ebx |
|
- | 2613 | xor eax, eax |
|
2616 | 2614 | ||
2617 | ret |
2615 | ret |
2618 | 2616 | ||
2619 | 2617 | ||
2620 | 2618 | ||
2621 | 2619 | ||
2622 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2620 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2623 | ;; ;; |
2621 | ;; ;; |
2624 | ;; Boomerang Interrupt handler ;; |
2622 | ;; Boomerang Interrupt handler ;; |
2625 | ;; ;; |
2623 | ;; ;; |
2626 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2624 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2627 | - | ||
2628 | align 4 |
2625 | align 16 |
2629 | int_boomerang: |
2626 | int_boomerang: |
2630 | 2627 | ||
2631 | push ebx esi edi |
2628 | push ebx esi edi |
- | 2629 | ||
2632 | 2630 | mov ebx, [esp+4*4] |
|
2633 | DEBUGF 1,"INT\n" |
- | |
2634 | - | ||
2635 | ; find pointer of device wich made IRQ occur |
2631 | DEBUGF 1,"INT for 0x%x\n", ebx |
2636 | - | ||
2637 | mov ecx, [boomerang_devices] |
- | |
2638 | test ecx, ecx |
- | |
2639 | jz .nothing |
- | |
2640 | mov esi, boomerang_list |
- | |
2641 | .nextdevice: |
2632 | |
2642 | mov ebx, [esi] |
2633 | ; TODO? if we are paranoid, we can check that the value from ebx is present in the current device_list |
2643 | 2634 | ||
2644 | set_io [ebx + device.io_addr], 0 |
2635 | set_io [ebx + device.io_addr], 0 |
2645 | set_io [ebx + device.io_addr], REG_INT_STATUS |
2636 | set_io [ebx + device.io_addr], REG_INT_STATUS |
2646 | in ax, dx |
2637 | in ax, dx |
2647 | test ax, S_5_INTS |
2638 | test ax, S_5_INTS |
2648 | jnz .got_it |
2639 | jz .nothing |
2649 | .continue: |
- | |
2650 | add esi, 4 |
- | |
2651 | dec ecx |
- | |
2652 | jnz .nextdevice |
- | |
2653 | .nothing: |
- | |
2654 | pop edi esi ebx |
- | |
2655 | xor eax, eax |
- | |
2656 | - | ||
2657 | ret |
- | |
2658 | - | ||
2659 | .got_it: |
2640 | .got_it: |
- | 2641 | DEBUGF 1,"Status: %x\n", ax |
|
2660 | - | ||
2661 | DEBUGF 1,"Device: %x Status: %x\n", ebx, ax |
2642 | |
2662 | push ax |
2643 | push ax |
2663 | 2644 | ||
2664 | ; disable all INTS |
2645 | ; disable all INTS |
2665 | 2646 | ||
2666 | set_io [ebx + device.io_addr], REG_COMMAND |
2647 | set_io [ebx + device.io_addr], REG_COMMAND |
2667 | mov ax, SetIntrEnb |
2648 | mov ax, SetIntrEnb |
2668 | out dx, ax |
2649 | out dx, ax |
2669 | 2650 | ||
2670 | ;-------------------------------------------------------------------------- |
2651 | ;-------------------------------------------------------------------------- |
2671 | test word[esp], UpComplete |
2652 | test word[esp], UpComplete |
2672 | jz .noRX |
2653 | jz .noRX |
2673 | 2654 | ||
2674 | push ebx |
2655 | push ebx |
2675 | 2656 | ||
2676 | .receive: |
2657 | .receive: |
2677 | DEBUGF 1,"UpComplete\n" |
2658 | DEBUGF 1,"UpComplete\n" |
2678 | 2659 | ||
2679 | ; check if packet is uploaded |
2660 | ; check if packet is uploaded |
2680 | mov esi, [ebx + device.curr_rx] |
2661 | mov esi, [ebx + device.curr_rx] |
2681 | test byte [esi+rx_desc.pkt_status+1], 0x80 ; upPktComplete |
2662 | test byte [esi+rx_desc.pkt_status+1], 0x80 ; upPktComplete |
2682 | jz .finish |
2663 | jz .finish |
2683 | DEBUGF 1, "Current RX desc: %x\n", esi |
2664 | DEBUGF 1, "Current RX desc: %x\n", esi |
2684 | ; packet is uploaded check for any error |
2665 | ; packet is uploaded check for any error |
2685 | .check_error: |
2666 | .check_error: |
2686 | test byte [esi + rx_desc.pkt_status+1], 0x40 ; upError |
2667 | test byte [esi + rx_desc.pkt_status+1], 0x40 ; upError |
2687 | jz .copy_packet_length |
2668 | jz .copy_packet_length |
2688 | DEBUGF 1,"Error in packet\n" |
2669 | DEBUGF 1,"Error in packet\n" |
2689 | and [esi + rx_desc.pkt_status], 0 ; mark packet as read |
2670 | and [esi + rx_desc.pkt_status], 0 ; mark packet as read |
2690 | jmp .finish |
2671 | jmp .finish |
2691 | .copy_packet_length: |
2672 | .copy_packet_length: |
2692 | mov ecx, [esi + rx_desc.pkt_status] |
2673 | mov ecx, [esi + rx_desc.pkt_status] |
2693 | and ecx, 0x1fff |
2674 | and ecx, 0x1fff |
2694 | 2675 | ||
2695 | ; cmp ecx, MAX_ETH_PKT_SIZE |
2676 | ; cmp ecx, MAX_ETH_PKT_SIZE |
2696 | ; jbe .copy_packet |
2677 | ; jbe .copy_packet |
2697 | ; and [esi+rx_desc.pkt_status], 0 |
2678 | ; and [esi+rx_desc.pkt_status], 0 |
2698 | ; jmp .finish |
2679 | ; jmp .finish |
2699 | ; .copy_packet: |
2680 | ; .copy_packet: |
2700 | 2681 | ||
2701 | DEBUGF 1, "Received %u bytes in buffer %x\n", ecx, [esi + rx_desc.realaddr]:8 |
2682 | DEBUGF 1, "Received %u bytes in buffer %x\n", ecx, [esi + rx_desc.realaddr]:8 |
2702 | 2683 | ||
2703 | push dword .loop ;.finish |
2684 | push dword .loop ;.finish |
2704 | mov eax, [esi + rx_desc.realaddr] |
2685 | mov eax, [esi + rx_desc.realaddr] |
2705 | push eax |
2686 | push eax |
2706 | mov [eax + NET_BUFF.length], ecx |
2687 | mov [eax + NET_BUFF.length], ecx |
2707 | mov [eax + NET_BUFF.device], ebx |
2688 | mov [eax + NET_BUFF.device], ebx |
2708 | mov [eax + NET_BUFF.offset], NET_BUFF.data |
2689 | mov [eax + NET_BUFF.offset], NET_BUFF.data |
2709 | 2690 | ||
2710 | ; update statistics |
2691 | ; update statistics |
2711 | inc [ebx + device.packets_rx] |
2692 | inc [ebx + device.packets_rx] |
2712 | add dword [ebx + device.bytes_rx], ecx |
2693 | add dword [ebx + device.bytes_rx], ecx |
2713 | adc dword [ebx + device.bytes_rx + 4], 0 |
2694 | adc dword [ebx + device.bytes_rx + 4], 0 |
2714 | 2695 | ||
2715 | ; update rx descriptor (Alloc new buffer for next packet) |
2696 | ; update rx descriptor (Alloc new buffer for next packet) |
2716 | invoke NetAlloc, MAX_ETH_FRAME_SIZE + NET_BUFF.data |
2697 | invoke NetAlloc, MAX_ETH_FRAME_SIZE + NET_BUFF.data |
2717 | mov [esi + rx_desc.realaddr], eax |
2698 | mov [esi + rx_desc.realaddr], eax |
2718 | invoke GetPhysAddr |
2699 | invoke GetPhysAddr |
2719 | add eax, NET_BUFF.data |
2700 | add eax, NET_BUFF.data |
2720 | mov [esi + rx_desc.frag_addr], eax |
2701 | mov [esi + rx_desc.frag_addr], eax |
2721 | and [esi + rx_desc.pkt_status], 0 |
2702 | and [esi + rx_desc.pkt_status], 0 |
2722 | mov [esi + rx_desc.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31) |
2703 | mov [esi + rx_desc.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31) |
2723 | 2704 | ||
2724 | ; Update rx descriptor pointer |
2705 | ; Update rx descriptor pointer |
2725 | add esi, sizeof.rx_desc |
2706 | add esi, sizeof.rx_desc |
2726 | lea ecx, [ebx + device.rx_desc_buffer+(NUM_RX_DESC)*sizeof.rx_desc] |
2707 | lea ecx, [ebx + device.rx_desc_buffer+(NUM_RX_DESC)*sizeof.rx_desc] |
2727 | cmp esi, ecx |
2708 | cmp esi, ecx |
2728 | jb @f |
2709 | jb @f |
2729 | lea esi, [ebx + device.rx_desc_buffer] |
2710 | lea esi, [ebx + device.rx_desc_buffer] |
2730 | @@: |
2711 | @@: |
2731 | mov [ebx + device.curr_rx], esi |
2712 | mov [ebx + device.curr_rx], esi |
2732 | DEBUGF 1, "Next RX desc: %x\n", esi |
2713 | DEBUGF 1, "Next RX desc: %x\n", esi |
2733 | 2714 | ||
2734 | jmp [EthInput] |
2715 | jmp [EthInput] |
2735 | .loop: |
2716 | .loop: |
2736 | 2717 | ||
2737 | mov ebx, [esp] |
2718 | mov ebx, [esp] |
2738 | jmp .receive |
2719 | jmp .receive |
2739 | 2720 | ||
2740 | .finish: |
2721 | .finish: |
2741 | pop ebx |
2722 | pop ebx |
2742 | 2723 | ||
2743 | ; check if the NIC is in the upStall state |
2724 | ; check if the NIC is in the upStall state |
2744 | set_io [ebx + device.io_addr], 0 |
2725 | set_io [ebx + device.io_addr], 0 |
2745 | set_io [ebx + device.io_addr], REG_UP_PKT_STATUS |
2726 | set_io [ebx + device.io_addr], REG_UP_PKT_STATUS |
2746 | in eax, dx |
2727 | in eax, dx |
2747 | test ah, 0x20 ; UpStalled |
2728 | test ah, 0x20 ; UpStalled |
2748 | jz .noUpUnStall |
2729 | jz .noUpUnStall |
2749 | 2730 | ||
2750 | DEBUGF 1, "upUnStalling\n" |
2731 | DEBUGF 1, "upUnStalling\n" |
2751 | ; issue upUnStall command |
2732 | ; issue upUnStall command |
2752 | set_io [ebx + device.io_addr], REG_COMMAND |
2733 | set_io [ebx + device.io_addr], REG_COMMAND |
2753 | mov ax, ((11b shl 12)+1) ; upUnStall |
2734 | mov ax, ((11b shl 12)+1) ; upUnStall |
2754 | out dx, ax |
2735 | out dx, ax |
2755 | 2736 | ||
2756 | ;;;; FIXME: make upunstall work |
2737 | ;;;; FIXME: make upunstall work |
2757 | 2738 | ||
2758 | .noUpUnStall: |
2739 | .noUpUnStall: |
2759 | .noRX: |
2740 | .noRX: |
2760 | test word[esp], DownComplete |
2741 | test word[esp], DownComplete |
2761 | jz .noTX |
2742 | jz .noTX |
2762 | DEBUGF 1, "Downcomplete!\n" |
2743 | DEBUGF 1, "Downcomplete!\n" |
2763 | 2744 | ||
2764 | mov ecx, NUM_TX_DESC |
2745 | mov ecx, NUM_TX_DESC |
2765 | lea esi, [ebx + device.tx_desc_buffer] |
2746 | lea esi, [ebx + device.tx_desc_buffer] |
2766 | .txloop: |
2747 | .txloop: |
2767 | test [esi+tx_desc.frame_start_hdr], 1 shl 31 |
2748 | test [esi+tx_desc.frame_start_hdr], 1 shl 31 |
2768 | jz .maybenext |
2749 | jz .maybenext |
2769 | 2750 | ||
2770 | and [esi+tx_desc.frame_start_hdr], 0 |
2751 | and [esi+tx_desc.frame_start_hdr], 0 |
2771 | push ecx |
2752 | push ecx |
2772 | invoke NetFree, [esi+tx_desc.realaddr] |
2753 | invoke NetFree, [esi+tx_desc.realaddr] |
2773 | pop ecx |
2754 | pop ecx |
2774 | 2755 | ||
2775 | .maybenext: |
2756 | .maybenext: |
2776 | add esi, sizeof.tx_desc |
2757 | add esi, sizeof.tx_desc |
2777 | dec ecx |
2758 | dec ecx |
2778 | jnz .txloop |
2759 | jnz .txloop |
2779 | 2760 | ||
2780 | .noTX: |
2761 | .noTX: |
2781 | pop ax |
2762 | pop ax |
2782 | 2763 | ||
2783 | set_io [ebx + device.io_addr], 0 |
2764 | set_io [ebx + device.io_addr], 0 |
2784 | set_io [ebx + device.io_addr], REG_COMMAND |
2765 | set_io [ebx + device.io_addr], REG_COMMAND |
2785 | or ax, AckIntr |
2766 | or ax, AckIntr |
2786 | out dx, ax |
2767 | out dx, ax |
2787 | 2768 | ||
2788 | set_io [ebx + device.io_addr], REG_INT_STATUS |
2769 | set_io [ebx + device.io_addr], REG_INT_STATUS |
2789 | in ax, dx |
2770 | in ax, dx |
2790 | test ax, S_5_INTS |
2771 | test ax, S_5_INTS |
2791 | jnz .got_it |
2772 | jnz .got_it |
2792 | 2773 | ||
2793 | ;re-enable ints |
2774 | ;re-enable ints |
2794 | set_io [ebx + device.io_addr], REG_COMMAND |
2775 | set_io [ebx + device.io_addr], REG_COMMAND |
2795 | mov ax, SetIntrEnb + S_5_INTS |
2776 | mov ax, SetIntrEnb + S_5_INTS |
2796 | out dx, ax |
2777 | out dx, ax |
2797 | 2778 | ||
2798 | pop edi esi ebx |
2779 | pop edi esi ebx |
- | 2780 | xor eax, eax |
|
- | 2781 | inc eax |
|
- | 2782 | ||
- | 2783 | ret |
|
- | 2784 | ||
- | 2785 | .nothing: |
|
- | 2786 | pop edi esi ebx |
|
- | 2787 | xor eax, eax |
|
2799 | 2788 | ||
2800 | ret |
2789 | ret |
2801 | 2790 | ||
2802 | 2791 | ||
2803 | 2792 | ||
2804 | 2793 | ||
2805 | ; End of code |
2794 | ; End of code |
2806 | 2795 | ||
2807 | data fixups |
2796 | data fixups |
2808 | end data |
2797 | end data |
2809 | 2798 | ||
2810 | include '../peimport.inc' |
2799 | include '../peimport.inc' |
2811 | 2800 | ||
2812 | my_service db '3C59X',0 ; max 16 chars include zero |
2801 | my_service db '3C59X',0 ; max 16 chars include zero |
2813 | 2802 | ||
2814 | macro strtbl name, [string] |
2803 | macro strtbl name, [string] |
2815 | { |
2804 | { |
2816 | common |
2805 | common |
2817 | label name dword |
2806 | label name dword |
2818 | forward |
2807 | forward |
2819 | local label |
2808 | local label |
2820 | dd label |
2809 | dd label |
2821 | forward |
2810 | forward |
2822 | label db string, 0 |
2811 | label db string, 0 |
2823 | } |
2812 | } |
2824 | 2813 | ||
2825 | strtbl link_str, \ |
2814 | strtbl link_str, \ |
2826 | "No valid link type detected", \ |
2815 | "No valid link type detected", \ |
2827 | "10BASE-T half duplex", \ |
2816 | "10BASE-T half duplex", \ |
2828 | "10BASE-T full-duplex", \ |
2817 | "10BASE-T full-duplex", \ |
2829 | "100BASE-TX half duplex", \ |
2818 | "100BASE-TX half duplex", \ |
2830 | "100BASE-TX full duplex", \ |
2819 | "100BASE-TX full duplex", \ |
2831 | "100BASE-T4", \ |
2820 | "100BASE-T4", \ |
2832 | "100BASE-FX", \ |
2821 | "100BASE-FX", \ |
2833 | "10Mbps AUI", \ |
2822 | "10Mbps AUI", \ |
2834 | "10Mbps COAX (BNC)", \ |
2823 | "10Mbps COAX (BNC)", \ |
2835 | "miiDevice - not supported" |
2824 | "miiDevice - not supported" |
2836 | 2825 | ||
2837 | strtbl hw_str, \ |
2826 | strtbl hw_str, \ |
2838 | "3c590 Vortex 10Mbps", \ |
2827 | "3c590 Vortex 10Mbps", \ |
2839 | "3c592 EISA 10Mbps Demon/Vortex", \ |
2828 | "3c592 EISA 10Mbps Demon/Vortex", \ |
2840 | "3c597 EISA Fast Demon/Vortex", \ |
2829 | "3c597 EISA Fast Demon/Vortex", \ |
2841 | "3c595 Vortex 100baseTx", \ |
2830 | "3c595 Vortex 100baseTx", \ |
2842 | "3c595 Vortex 100baseT4", \ |
2831 | "3c595 Vortex 100baseT4", \ |
2843 | "3c595 Vortex 100base-MII", \ |
2832 | "3c595 Vortex 100base-MII", \ |
2844 | "3c900 Boomerang 10baseT", \ |
2833 | "3c900 Boomerang 10baseT", \ |
2845 | "3c900 Boomerang 10Mbps Combo", \ |
2834 | "3c900 Boomerang 10Mbps Combo", \ |
2846 | "3c900 Cyclone 10Mbps TPO", \ |
2835 | "3c900 Cyclone 10Mbps TPO", \ |
2847 | "3c900 Cyclone 10Mbps Combo", \ |
2836 | "3c900 Cyclone 10Mbps Combo", \ |
2848 | "3c900 Cyclone 10Mbps TPC", \ |
2837 | "3c900 Cyclone 10Mbps TPC", \ |
2849 | "3c900B-FL Cyclone 10base-FL", \ |
2838 | "3c900B-FL Cyclone 10base-FL", \ |
2850 | "3c905 Boomerang 100baseTx", \ |
2839 | "3c905 Boomerang 100baseTx", \ |
2851 | "3c905 Boomerang 100baseT4", \ |
2840 | "3c905 Boomerang 100baseT4", \ |
2852 | "3c905B Cyclone 100baseTx", \ |
2841 | "3c905B Cyclone 100baseTx", \ |
2853 | "3c905B Cyclone 10/100/BNC", \ |
2842 | "3c905B Cyclone 10/100/BNC", \ |
2854 | "3c905B-FX Cyclone 100baseFx", \ |
2843 | "3c905B-FX Cyclone 100baseFx", \ |
2855 | "3c905C Tornado", \ |
2844 | "3c905C Tornado", \ |
2856 | "3c980 Cyclone", \ |
2845 | "3c980 Cyclone", \ |
2857 | "3c982 Dual Port Server Cyclone", \ |
2846 | "3c982 Dual Port Server Cyclone", \ |
2858 | "3cSOHO100-TX Hurricane", \ |
2847 | "3cSOHO100-TX Hurricane", \ |
2859 | "3c555 Laptop Hurricane", \ |
2848 | "3c555 Laptop Hurricane", \ |
2860 | "3c556 Laptop Tornado", \ |
2849 | "3c556 Laptop Tornado", \ |
2861 | "3c556B Laptop Hurricane", \ |
2850 | "3c556B Laptop Hurricane", \ |
2862 | "3c575 [Megahertz] 10/100 LAN CardBus", \ |
2851 | "3c575 [Megahertz] 10/100 LAN CardBus", \ |
2863 | "3c575 Boomerang CardBus", \ |
2852 | "3c575 Boomerang CardBus", \ |
2864 | "3CCFE575BT Cyclone CardBus", \ |
2853 | "3CCFE575BT Cyclone CardBus", \ |
2865 | "3CCFE575CT Tornado CardBus", \ |
2854 | "3CCFE575CT Tornado CardBus", \ |
2866 | "3CCFE656 Cyclone CardBus", \ |
2855 | "3CCFE656 Cyclone CardBus", \ |
2867 | "3CCFEM656B Cyclone+Winmodem CardBus", \ |
2856 | "3CCFEM656B Cyclone+Winmodem CardBus", \ |
2868 | "3CXFEM656C Tornado+Winmodem CardBus", \ |
2857 | "3CXFEM656C Tornado+Winmodem CardBus", \ |
2869 | "3c450 HomePNA Tornado", \ |
2858 | "3c450 HomePNA Tornado", \ |
2870 | "3c920 Tornado", \ |
2859 | "3c920 Tornado", \ |
2871 | "3c982 Hydra Dual Port A", \ |
2860 | "3c982 Hydra Dual Port A", \ |
2872 | "3c982 Hydra Dual Port B", \ |
2861 | "3c982 Hydra Dual Port B", \ |
2873 | "3c905B-T4", \ |
2862 | "3c905B-T4", \ |
2874 | "3c920B-EMB-WNM Tornado" |
2863 | "3c920B-EMB-WNM Tornado" |
2875 | 2864 | ||
2876 | 2865 | ||
2877 | 2866 | ||
2878 | align 4 |
2867 | align 4 |
2879 | hw_versions: |
2868 | hw_versions: |
2880 | dw 0x5900, IS_VORTEX ; 3c590 Vortex 10Mbps |
2869 | dw 0x5900, IS_VORTEX ; 3c590 Vortex 10Mbps |
2881 | dw 0x5920, IS_VORTEX ; 3c592 EISA 10Mbps Demon/Vortex |
2870 | dw 0x5920, IS_VORTEX ; 3c592 EISA 10Mbps Demon/Vortex |
2882 | dw 0x5970, IS_VORTEX ; 3c597 EISA Fast Demon/Vortex |
2871 | dw 0x5970, IS_VORTEX ; 3c597 EISA Fast Demon/Vortex |
2883 | dw 0x5950, IS_VORTEX ; 3c595 Vortex 100baseTx |
2872 | dw 0x5950, IS_VORTEX ; 3c595 Vortex 100baseTx |
2884 | dw 0x5951, IS_VORTEX ; 3c595 Vortex 100baseT4 |
2873 | dw 0x5951, IS_VORTEX ; 3c595 Vortex 100baseT4 |
2885 | dw 0x5952, IS_VORTEX ; 3c595 Vortex 100base-MII |
2874 | dw 0x5952, IS_VORTEX ; 3c595 Vortex 100base-MII |
2886 | dw 0x9000, IS_BOOMERANG ; 3c900 Boomerang 10baseT |
2875 | dw 0x9000, IS_BOOMERANG ; 3c900 Boomerang 10baseT |
2887 | dw 0x9001, IS_BOOMERANG ; 3c900 Boomerang 10Mbps Combo |
2876 | dw 0x9001, IS_BOOMERANG ; 3c900 Boomerang 10Mbps Combo |
2888 | dw 0x9004, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPO |
2877 | dw 0x9004, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPO |
2889 | dw 0x9005, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps Combo |
2878 | dw 0x9005, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps Combo |
2890 | dw 0x9006, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPC |
2879 | dw 0x9006, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPC |
2891 | dw 0x900A, IS_CYCLONE or HAS_HWCKSM ; 3c900B-FL Cyclone 10base-FL |
2880 | dw 0x900A, IS_CYCLONE or HAS_HWCKSM ; 3c900B-FL Cyclone 10base-FL |
2892 | dw 0x9050, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseTx |
2881 | dw 0x9050, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseTx |
2893 | dw 0x9051, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseT4 |
2882 | dw 0x9051, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseT4 |
2894 | dw 0x9055, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B Cyclone 100baseTx |
2883 | dw 0x9055, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B Cyclone 100baseTx |
2895 | dw 0x9058, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c905B Cyclone 10/100/BNC |
2884 | dw 0x9058, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c905B Cyclone 10/100/BNC |
2896 | dw 0x905A, IS_CYCLONE or HAS_HWCKSM ; 3c905B-FX Cyclone 100baseFx |
2885 | dw 0x905A, IS_CYCLONE or HAS_HWCKSM ; 3c905B-FX Cyclone 100baseFx |
2897 | dw 0x9200, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c905C Tornado |
2886 | dw 0x9200, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c905C Tornado |
2898 | dw 0x9800, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c980 Cyclone |
2887 | dw 0x9800, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c980 Cyclone |
2899 | dw 0x9805, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c982 Dual Port Server Cyclone |
2888 | dw 0x9805, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c982 Dual Port Server Cyclone |
2900 | dw 0x7646, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3cSOHO100-TX Hurricane |
2889 | dw 0x7646, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3cSOHO100-TX Hurricane |
2901 | dw 0x5055, IS_CYCLONE or EEPROM_8BIT or HAS_HWCKSM ; 3c555 Laptop Hurricane |
2890 | dw 0x5055, IS_CYCLONE or EEPROM_8BIT or HAS_HWCKSM ; 3c555 Laptop Hurricane |
2902 | dw 0x6055, IS_TORNADO or HAS_NWAY or EEPROM_8BIT or HAS_CB_FNS or INVERT_MII_PWR or HAS_HWCKSM ; 3c556 Laptop Tornado |
2891 | dw 0x6055, IS_TORNADO or HAS_NWAY or EEPROM_8BIT or HAS_CB_FNS or INVERT_MII_PWR or HAS_HWCKSM ; 3c556 Laptop Tornado |
2903 | dw 0x6056, IS_TORNADO or HAS_NWAY or EEPROM_OFFSET or HAS_CB_FNS or INVERT_MII_PWR or HAS_HWCKSM ; 3c556B Laptop Hurricane |
2892 | dw 0x6056, IS_TORNADO or HAS_NWAY or EEPROM_OFFSET or HAS_CB_FNS or INVERT_MII_PWR or HAS_HWCKSM ; 3c556B Laptop Hurricane |
2904 | dw 0x5b57, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 [Megahertz] 10/100 LAN CardBus |
2893 | dw 0x5b57, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 [Megahertz] 10/100 LAN CardBus |
2905 | dw 0x5057, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 Boomerang CardBus |
2894 | dw 0x5057, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 Boomerang CardBus |
2906 | dw 0x5157, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE575BT Cyclone CardBus |
2895 | dw 0x5157, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE575BT Cyclone CardBus |
2907 | dw 0x5257, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CCFE575CT Tornado CardBus |
2896 | dw 0x5257, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CCFE575CT Tornado CardBus |
2908 | dw 0x6560, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE656 Cyclone CardBus |
2897 | dw 0x6560, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE656 Cyclone CardBus |
2909 | dw 0x6562, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFEM656B Cyclone+Winmodem CardBus |
2898 | dw 0x6562, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFEM656B Cyclone+Winmodem CardBus |
2910 | dw 0x6564, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CXFEM656C Tornado+Winmodem CardBus |
2899 | dw 0x6564, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CXFEM656C Tornado+Winmodem CardBus |
2911 | dw 0x4500, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c450 HomePNA Tornado |
2900 | dw 0x4500, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c450 HomePNA Tornado |
2912 | dw 0x9201, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920 Tornado |
2901 | dw 0x9201, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920 Tornado |
2913 | dw 0x1201, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port A |
2902 | dw 0x1201, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port A |
2914 | dw 0x1202, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port B |
2903 | dw 0x1202, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port B |
2915 | dw 0x9056, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B-T4 |
2904 | dw 0x9056, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B-T4 |
2916 | dw 0x9210, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920B-EMB-WNM Tornado |
2905 | dw 0x9210, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920B-EMB-WNM Tornado |
2917 | HW_VERSIONS_SIZE = $ - hw_versions |
2906 | HW_VERSIONS_SIZE = $ - hw_versions |
2918 | 2907 | ||
2919 | include_debug_strings ; All data wich FDO uses will be included here |
2908 | include_debug_strings ; All data wich FDO uses will be included here |
2920 | 2909 | ||
2921 | align 4 |
2910 | align 4 |
2922 | vortex_devices dd 0 |
2911 | devices dd 0 |
2923 | boomerang_devices dd 0 |
- | |
2924 | vortex_list rd MAX_DEVICES |
2912 | device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling |
2925 | boomerang_list rd MAX_DEVICES |
- |