Rev 5525 | Rev 5561 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5525 | Rev 5560 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2015. 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 | ;; i8255x (Intel eepro 100) driver for KolibriOS ;; |
6 | ;; i8255x (Intel eepro 100) driver for KolibriOS ;; |
7 | ;; ;; |
7 | ;; ;; |
8 | ;; Written by hidnplayr@kolibrios.org ;; |
8 | ;; Written by hidnplayr@kolibrios.org ;; |
9 | ;; ;; |
9 | ;; ;; |
10 | ;; GNU GENERAL PUBLIC LICENSE ;; |
10 | ;; GNU GENERAL PUBLIC LICENSE ;; |
11 | ;; Version 2, June 1991 ;; |
11 | ;; Version 2, June 1991 ;; |
12 | ;; ;; |
12 | ;; ;; |
13 | ;; Some parts of this driver are based on the code of eepro100.c ;; |
13 | ;; Some parts of this driver are based on the code of eepro100.c ;; |
14 | ;; from linux. ;; |
14 | ;; from linux. ;; |
15 | ;; ;; |
15 | ;; ;; |
16 | ;; Intel's programming manual for i8255x: ;; |
16 | ;; Intel's programming manual for i8255x: ;; |
17 | ;; http://www.intel.com/design/network/manuals/8255x_opensdm.htm ;; |
17 | ;; http://www.intel.com/design/network/manuals/8255x_opensdm.htm ;; |
18 | ;; ;; |
18 | ;; ;; |
19 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
19 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
- | 20 | ||
20 | 21 | ;TODO: use more RX buffers |
|
21 | 22 | ||
22 | format PE DLL native |
23 | format PE DLL native |
23 | entry START |
24 | entry START |
24 | 25 | ||
25 | CURRENT_API = 0x0200 |
26 | CURRENT_API = 0x0200 |
26 | COMPATIBLE_API = 0x0100 |
27 | COMPATIBLE_API = 0x0100 |
27 | API_VERSION = (COMPATIBLE_API shl 16) + CURRENT_API |
28 | API_VERSION = (COMPATIBLE_API shl 16) + CURRENT_API |
28 | 29 | ||
29 | MAX_DEVICES = 16 |
30 | MAX_DEVICES = 16 |
30 | 31 | ||
31 | TX_RING_SIZE = 16 |
32 | TX_RING_SIZE = 16 |
32 | 33 | ||
33 | DEBUG = 1 |
34 | DEBUG = 1 |
34 | __DEBUG__ = 1 |
35 | __DEBUG__ = 1 |
35 | __DEBUG_LEVEL__ = 2 ; 1 = verbose, 2 = errors only |
36 | __DEBUG_LEVEL__ = 2 ; 1 = verbose, 2 = errors only |
36 | 37 | ||
37 | section '.flat' readable writable executable |
38 | section '.flat' readable writable executable |
38 | 39 | ||
39 | include '../proc32.inc' |
40 | include '../proc32.inc' |
40 | include '../struct.inc' |
41 | include '../struct.inc' |
41 | include '../macros.inc' |
42 | include '../macros.inc' |
42 | include '../fdo.inc' |
43 | include '../fdo.inc' |
43 | include '../netdrv.inc' |
44 | include '../netdrv.inc' |
44 | 45 | ||
45 | ; Serial EEPROM |
46 | ; Serial EEPROM |
46 | 47 | ||
47 | EE_SK = 1 shl 0 ; serial clock |
48 | EE_SK = 1 shl 0 ; serial clock |
48 | EE_CS = 1 shl 1 ; chip select |
49 | EE_CS = 1 shl 1 ; chip select |
49 | EE_DI = 1 shl 2 ; data in |
50 | EE_DI = 1 shl 2 ; data in |
50 | EE_DO = 1 shl 3 ; data out |
51 | EE_DO = 1 shl 3 ; data out |
51 | EE_MASK = EE_SK + EE_CS + EE_DI + EE_DO |
52 | EE_MASK = EE_SK + EE_CS + EE_DI + EE_DO |
52 | 53 | ||
53 | ; opcodes, first bit is start bit and must be 1 |
54 | ; opcodes, first bit is start bit and must be 1 |
54 | EE_READ = 110b |
55 | EE_READ = 110b |
55 | EE_WRITE = 101b |
56 | EE_WRITE = 101b |
56 | EE_ERASE = 111b |
57 | EE_ERASE = 111b |
57 | 58 | ||
58 | ; The SCB accepts the following controls for the Tx and Rx units: |
59 | ; The SCB accepts the following controls for the Tx and Rx units: |
59 | 60 | ||
60 | CU_START = 0x0010 |
61 | CU_START = 0x0010 |
61 | CU_RESUME = 0x0020 |
62 | CU_RESUME = 0x0020 |
62 | CU_STATSADDR = 0x0040 |
63 | CU_STATSADDR = 0x0040 |
63 | CU_SHOWSTATS = 0x0050 ; Dump statistics counters. |
64 | CU_SHOWSTATS = 0x0050 ; Dump statistics counters. |
64 | CU_CMD_BASE = 0x0060 ; Base address to add CU commands. |
65 | CU_CMD_BASE = 0x0060 ; Base address to add CU commands. |
65 | CU_DUMPSTATS = 0x0070 ; Dump then reset stats counters. |
66 | CU_DUMPSTATS = 0x0070 ; Dump then reset stats counters. |
66 | 67 | ||
67 | RX_START = 0x0001 |
68 | RX_START = 0x0001 |
68 | RX_RESUME = 0x0002 |
69 | RX_RESUME = 0x0002 |
69 | RX_ABORT = 0x0004 |
70 | RX_ABORT = 0x0004 |
70 | RX_ADDR_LOAD = 0x0006 |
71 | RX_ADDR_LOAD = 0x0006 |
71 | RX_RESUMENR = 0x0007 |
72 | RX_RESUMENR = 0x0007 |
72 | INT_MASK = 0x0100 |
73 | INT_MASK = 0x0100 |
73 | DRVR_INT = 0x0200 ; Driver generated interrupt |
74 | DRVR_INT = 0x0200 ; Driver generated interrupt |
74 | 75 | ||
75 | CmdIASetup = 0x0001 |
76 | CmdIASetup = 0x0001 |
76 | CmdConfigure = 0x0002 |
77 | CmdConfigure = 0x0002 |
77 | CmdTx = 0x0004 |
78 | CmdTx = 0x0004 |
78 | CmdTxFlex = 0x0008 |
79 | CmdTxFlex = 0x0008 |
79 | Cmdsuspend = 0x4000 |
80 | Cmdsuspend = 0x4000 |
80 | 81 | ||
81 | CmdRxFlex = 0x0008 |
82 | CmdRxFlex = 0x0008 |
82 | 83 | ||
83 | reg_scb_status = 0 |
84 | reg_scb_status = 0 |
84 | reg_scb_cmd = 2 |
85 | reg_scb_cmd = 2 |
85 | reg_scb_ptr = 4 |
86 | reg_scb_ptr = 4 |
86 | reg_port = 8 |
87 | reg_port = 8 |
87 | reg_eeprom = 14 |
88 | reg_eeprom = 14 |
88 | reg_mdi_ctrl = 16 |
89 | reg_mdi_ctrl = 16 |
89 | 90 | ||
90 | phy_100a = 0x000003E0 |
91 | phy_100a = 0x000003E0 |
91 | phy_100c = 0x035002A8 |
92 | phy_100c = 0x035002A8 |
92 | phy_82555_tx = 0x015002A8 |
93 | phy_82555_tx = 0x015002A8 |
93 | phy_nsc_tx = 0x5C002000 |
94 | phy_nsc_tx = 0x5C002000 |
94 | phy_82562_et = 0x033002A8 |
95 | phy_82562_et = 0x033002A8 |
95 | phy_82562_em = 0x032002A8 |
96 | phy_82562_em = 0x032002A8 |
96 | phy_82562_ek = 0x031002A8 |
97 | phy_82562_ek = 0x031002A8 |
97 | phy_82562_eh = 0x017002A8 |
98 | phy_82562_eh = 0x017002A8 |
98 | phy_82552_v = 0xd061004d |
99 | phy_82552_v = 0xd061004d |
99 | phy_unknown = 0xFFFFFFFF |
100 | phy_unknown = 0xFFFFFFFF |
100 | 101 | ||
101 | mac_82557_D100_A = 0 |
102 | mac_82557_D100_A = 0 |
102 | mac_82557_D100_B = 1 |
103 | mac_82557_D100_B = 1 |
103 | mac_82557_D100_C = 2 |
104 | mac_82557_D100_C = 2 |
104 | mac_82558_D101_A4 = 4 |
105 | mac_82558_D101_A4 = 4 |
105 | mac_82558_D101_B0 = 5 |
106 | mac_82558_D101_B0 = 5 |
106 | mac_82559_D101M = 8 |
107 | mac_82559_D101M = 8 |
107 | mac_82559_D101S = 9 |
108 | mac_82559_D101S = 9 |
108 | mac_82550_D102 = 12 |
109 | mac_82550_D102 = 12 |
109 | mac_82550_D102_C = 13 |
110 | mac_82550_D102_C = 13 |
110 | mac_82551_E = 14 |
111 | mac_82551_E = 14 |
111 | mac_82551_F = 15 |
112 | mac_82551_F = 15 |
112 | mac_82551_10 = 16 |
113 | mac_82551_10 = 16 |
113 | mac_unknown = 0xFF |
114 | mac_unknown = 0xFF |
114 | 115 | ||
115 | struct rxfd |
116 | struct rxfd |
116 | 117 | ||
117 | status dw ? |
118 | status dw ? |
118 | command dw ? |
119 | command dw ? |
119 | link dd ? |
120 | link dd ? |
120 | rx_buf_addr dd ? |
121 | rx_buf_addr dd ? |
121 | count dw ? |
122 | count dw ? |
122 | size dw ? |
123 | size dw ? |
123 | packet rb 1500 |
124 | packet rb 1500 |
124 | 125 | ||
125 | ends |
126 | ends |
126 | 127 | ||
127 | struct txfd |
128 | struct txfd |
128 | 129 | ||
129 | status dw ? |
130 | status dw ? |
130 | command dw ? |
131 | command dw ? |
131 | link dd ? |
132 | link dd ? |
132 | desc_addr dd ? |
133 | desc_addr dd ? |
133 | count dd ? |
134 | count dd ? |
134 | 135 | ||
135 | buf_addr dd ? |
136 | buf_addr dd ? |
136 | buf_size dd ? |
137 | buf_size dd ? |
137 | virt_addr dd ? |
138 | virt_addr dd ? |
138 | dd ? ; alignment |
139 | dd ? ; alignment |
139 | 140 | ||
140 | ends |
141 | ends |
141 | 142 | ||
142 | struc confcmd { |
143 | struc confcmd { |
143 | 144 | ||
144 | .status dw ? |
145 | .status dw ? |
145 | .command dw ? |
146 | .command dw ? |
146 | .link dd ? |
147 | .link dd ? |
147 | .data rb 64 |
148 | .data rb 64 |
148 | 149 | ||
149 | } |
150 | } |
150 | 151 | ||
151 | struc lstats { |
152 | struc lstats { |
152 | 153 | ||
153 | .tx_good_frames dd ? |
154 | .tx_good_frames dd ? |
154 | .tx_coll16_errs dd ? |
155 | .tx_coll16_errs dd ? |
155 | .tx_late_colls dd ? |
156 | .tx_late_colls dd ? |
156 | .tx_underruns dd ? |
157 | .tx_underruns dd ? |
157 | .tx_lost_carrier dd ? |
158 | .tx_lost_carrier dd ? |
158 | .tx_deferred dd ? |
159 | .tx_deferred dd ? |
159 | .tx_one_colls dd ? |
160 | .tx_one_colls dd ? |
160 | .tx_multi_colls dd ? |
161 | .tx_multi_colls dd ? |
161 | .tx_total_colls dd ? |
162 | .tx_total_colls dd ? |
162 | 163 | ||
163 | .rx_good_frames dd ? |
164 | .rx_good_frames dd ? |
164 | .rx_crc_errs dd ? |
165 | .rx_crc_errs dd ? |
165 | .rx_align_errs dd ? |
166 | .rx_align_errs dd ? |
166 | .rx_resource_errs dd ? |
167 | .rx_resource_errs dd ? |
167 | .rx_overrun_errs dd ? |
168 | .rx_overrun_errs dd ? |
168 | .rx_colls_errs dd ? |
169 | .rx_colls_errs dd ? |
169 | .rx_runt_errs dd ? |
170 | .rx_runt_errs dd ? |
170 | 171 | ||
171 | } |
172 | } |
172 | 173 | ||
173 | struct device ETH_DEVICE |
174 | struct device ETH_DEVICE |
174 | 175 | ||
175 | io_addr dd ? |
176 | io_addr dd ? |
176 | pci_bus dd ? |
177 | pci_bus dd ? |
177 | pci_dev dd ? |
178 | pci_dev dd ? |
178 | rx_desc dd ? |
179 | rx_desc dd ? |
179 | cur_tx dd ? |
180 | cur_tx dd ? |
180 | last_tx dd ? |
181 | last_tx dd ? |
181 | ee_bus_width db ? |
182 | ee_bus_width db ? |
182 | irq_line db ? |
183 | irq_line db ? |
183 | 184 | ||
184 | rb 0x100 - ($ and 0xff) ; align 256 |
185 | rb 0x100 - ($ and 0xff) ; align 256 |
185 | tx_ring rb TX_RING_SIZE*sizeof.txfd |
186 | tx_ring rb TX_RING_SIZE*sizeof.txfd |
186 | 187 | ||
187 | rb 0x100 - ($ and 0xff) ; align 256 |
188 | rb 0x100 - ($ and 0xff) ; align 256 |
188 | confcmd confcmd |
189 | confcmd confcmd |
189 | 190 | ||
190 | rb 0x100 - ($ and 0xff) ; align 256 |
191 | rb 0x100 - ($ and 0xff) ; align 256 |
191 | lstats lstats |
192 | lstats lstats |
192 | 193 | ||
193 | ends |
194 | ends |
194 | 195 | ||
195 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
196 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
196 | ;; ;; |
197 | ;; ;; |
197 | ;; proc START ;; |
198 | ;; proc START ;; |
198 | ;; ;; |
199 | ;; ;; |
199 | ;; (standard driver proc) ;; |
200 | ;; (standard driver proc) ;; |
200 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
201 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
201 | 202 | ||
202 | proc START c, state:dword |
203 | proc START c, state:dword |
203 | 204 | ||
204 | cmp [state], 1 |
205 | cmp [state], 1 |
205 | jne .exit |
206 | jne .exit |
206 | 207 | ||
207 | .entry: |
208 | .entry: |
208 | 209 | ||
209 | DEBUGF 1,"Loading driver\n" |
210 | DEBUGF 1,"Loading driver\n" |
210 | invoke RegService, my_service, service_proc |
211 | invoke RegService, my_service, service_proc |
211 | ret |
212 | ret |
212 | 213 | ||
213 | .fail: |
214 | .fail: |
214 | .exit: |
215 | .exit: |
215 | xor eax, eax |
216 | xor eax, eax |
216 | ret |
217 | ret |
217 | 218 | ||
218 | endp |
219 | endp |
219 | 220 | ||
220 | 221 | ||
221 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
222 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
222 | ;; ;; |
223 | ;; ;; |
223 | ;; proc SERVICE_PROC ;; |
224 | ;; proc SERVICE_PROC ;; |
224 | ;; ;; |
225 | ;; ;; |
225 | ;; (standard driver proc) ;; |
226 | ;; (standard driver proc) ;; |
226 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
227 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
227 | 228 | ||
228 | align 4 |
229 | align 4 |
229 | proc service_proc stdcall, ioctl:dword |
230 | proc service_proc stdcall, ioctl:dword |
230 | 231 | ||
231 | mov edx, [ioctl] |
232 | mov edx, [ioctl] |
232 | mov eax, [edx + IOCTL.io_code] |
233 | mov eax, [edx + IOCTL.io_code] |
233 | 234 | ||
234 | ;------------------------------------------------------ |
235 | ;------------------------------------------------------ |
235 | 236 | ||
236 | cmp eax, 0 ;SRV_GETVERSION |
237 | cmp eax, 0 ;SRV_GETVERSION |
237 | jne @F |
238 | jne @F |
238 | 239 | ||
239 | cmp [edx + IOCTL.out_size], 4 |
240 | cmp [edx + IOCTL.out_size], 4 |
240 | jb .fail |
241 | jb .fail |
241 | mov eax, [edx + IOCTL.output] |
242 | mov eax, [edx + IOCTL.output] |
242 | mov [eax], dword API_VERSION |
243 | mov [eax], dword API_VERSION |
243 | 244 | ||
244 | xor eax, eax |
245 | xor eax, eax |
245 | ret |
246 | ret |
246 | 247 | ||
247 | ;------------------------------------------------------ |
248 | ;------------------------------------------------------ |
248 | @@: |
249 | @@: |
249 | cmp eax, 1 ;SRV_HOOK |
250 | cmp eax, 1 ;SRV_HOOK |
250 | jne .fail |
251 | jne .fail |
251 | 252 | ||
252 | cmp [edx + IOCTL.inp_size], 3 ; Data input must be at least 3 bytes |
253 | cmp [edx + IOCTL.inp_size], 3 ; Data input must be at least 3 bytes |
253 | jb .fail |
254 | jb .fail |
254 | 255 | ||
255 | mov eax, [edx + IOCTL.input] |
256 | mov eax, [edx + IOCTL.input] |
256 | cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given |
257 | cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given |
257 | jne .fail ; other types arent supported for this card yet |
258 | jne .fail ; other types arent supported for this card yet |
258 | 259 | ||
259 | ; check if the device is already listed |
260 | ; check if the device is already listed |
260 | 261 | ||
261 | mov esi, device_list |
262 | mov esi, device_list |
262 | mov ecx, [devices] |
263 | mov ecx, [devices] |
263 | test ecx, ecx |
264 | test ecx, ecx |
264 | jz .firstdevice |
265 | jz .firstdevice |
265 | 266 | ||
266 | ; mov eax, [edx + IOCTL.input] ; get the pci bus and device numbers |
267 | ; mov eax, [edx + IOCTL.input] ; get the pci bus and device numbers |
267 | mov ax , [eax+1] ; |
268 | mov ax , [eax+1] ; |
268 | .nextdevice: |
269 | .nextdevice: |
269 | mov ebx, [esi] |
270 | mov ebx, [esi] |
270 | cmp al, byte[ebx + device.pci_bus] |
271 | cmp al, byte[ebx + device.pci_bus] |
271 | jne @f |
272 | jne @f |
272 | cmp ah, byte[ebx + device.pci_dev] |
273 | cmp ah, byte[ebx + device.pci_dev] |
273 | je .find_devicenum ; Device is already loaded, let's find it's device number |
274 | je .find_devicenum ; Device is already loaded, let's find it's device number |
274 | @@: |
275 | @@: |
275 | add esi, 4 |
276 | add esi, 4 |
276 | loop .nextdevice |
277 | loop .nextdevice |
277 | 278 | ||
278 | 279 | ||
279 | ; This device doesnt have its own eth_device structure yet, lets create one |
280 | ; This device doesnt have its own eth_device structure yet, lets create one |
280 | .firstdevice: |
281 | .firstdevice: |
281 | cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card |
282 | cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card |
282 | jae .fail |
283 | jae .fail |
283 | 284 | ||
284 | allocate_and_clear ebx, sizeof.device, .fail ; Allocate the buffer for device structure |
285 | allocate_and_clear ebx, sizeof.device, .fail ; Allocate the buffer for device structure |
285 | 286 | ||
286 | ; Fill in the direct call addresses into the struct |
287 | ; Fill in the direct call addresses into the struct |
287 | 288 | ||
288 | mov [ebx + device.reset], reset |
289 | mov [ebx + device.reset], reset |
289 | mov [ebx + device.transmit], transmit |
290 | mov [ebx + device.transmit], transmit |
290 | mov [ebx + device.unload], unload |
291 | mov [ebx + device.unload], unload |
291 | mov [ebx + device.name], my_service |
292 | mov [ebx + device.name], my_service |
292 | 293 | ||
293 | ; save the pci bus and device numbers |
294 | ; save the pci bus and device numbers |
294 | 295 | ||
295 | mov eax, [edx + IOCTL.input] |
296 | mov eax, [edx + IOCTL.input] |
296 | movzx ecx, byte[eax+1] |
297 | movzx ecx, byte[eax+1] |
297 | mov [ebx + device.pci_bus], ecx |
298 | mov [ebx + device.pci_bus], ecx |
298 | movzx ecx, byte[eax+2] |
299 | movzx ecx, byte[eax+2] |
299 | mov [ebx + device.pci_dev], ecx |
300 | mov [ebx + device.pci_dev], ecx |
300 | 301 | ||
301 | ; Now, it's time to find the base io addres of the PCI device |
302 | ; Now, it's time to find the base io addres of the PCI device |
302 | 303 | ||
303 | stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev] |
304 | stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev] |
304 | mov [ebx + device.io_addr], eax |
305 | mov [ebx + device.io_addr], eax |
305 | 306 | ||
306 | ; We've found the io address, find IRQ now |
307 | ; We've found the io address, find IRQ now |
307 | 308 | ||
308 | invoke PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line |
309 | invoke PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line |
309 | mov [ebx + device.irq_line], al |
310 | mov [ebx + device.irq_line], al |
310 | 311 | ||
311 | DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\ |
312 | DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\ |
312 | [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.io_addr]:4 |
313 | [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.io_addr]:4 |
313 | 314 | ||
314 | ; Ok, the eth_device structure is ready, let's probe the device |
315 | ; Ok, the eth_device structure is ready, let's probe the device |
315 | 316 | ||
316 | pushf |
317 | pushf |
317 | cli ; disable ints untilm initialisation is done |
318 | cli ; disable ints untilm initialisation is done |
318 | 319 | ||
319 | call probe ; this function will output in eax |
320 | call probe ; this function will output in eax |
320 | test eax, eax |
321 | test eax, eax |
321 | jnz .err ; If an error occured, exit |
322 | jnz .err ; If an error occured, exit |
322 | 323 | ||
323 | mov eax, [devices] ; Add the device structure to our device list |
324 | mov eax, [devices] ; Add the device structure to our device list |
324 | mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device) |
325 | mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device) |
325 | inc [devices] ; |
326 | inc [devices] ; |
326 | 327 | ||
327 | popf |
328 | popf |
328 | 329 | ||
329 | mov [ebx + device.type], NET_TYPE_ETH |
330 | mov [ebx + device.type], NET_TYPE_ETH |
330 | invoke NetRegDev |
331 | invoke NetRegDev |
331 | 332 | ||
332 | cmp eax, -1 |
333 | cmp eax, -1 |
333 | je .err |
334 | je .err |
334 | 335 | ||
335 | ret |
336 | ret |
336 | 337 | ||
337 | ; If the device was already loaded, find the device number and return it in eax |
338 | ; If the device was already loaded, find the device number and return it in eax |
338 | 339 | ||
339 | .find_devicenum: |
340 | .find_devicenum: |
340 | DEBUGF 2,"Trying to find device number of already registered device\n" |
341 | DEBUGF 2,"Trying to find device number of already registered device\n" |
341 | invoke NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx |
342 | invoke NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx |
342 | ; into a device number in edi |
343 | ; into a device number in edi |
343 | mov eax, edi ; Application wants it in eax instead |
344 | mov eax, edi ; Application wants it in eax instead |
344 | DEBUGF 2,"Kernel says: %u\n", eax |
345 | DEBUGF 2,"Kernel says: %u\n", eax |
345 | ret |
346 | ret |
346 | 347 | ||
347 | ; If an error occured, remove all allocated data and exit (returning -1 in eax) |
348 | ; If an error occured, remove all allocated data and exit (returning -1 in eax) |
348 | 349 | ||
349 | .err: |
350 | .err: |
350 | invoke KernelFree, ebx |
351 | invoke KernelFree, ebx |
351 | 352 | ||
352 | .fail: |
353 | .fail: |
353 | or eax, -1 |
354 | or eax, -1 |
354 | ret |
355 | ret |
355 | 356 | ||
356 | ;------------------------------------------------------ |
357 | ;------------------------------------------------------ |
357 | endp |
358 | endp |
358 | 359 | ||
359 | 360 | ||
360 | 361 | ||
361 | 362 | ||
362 | 363 | ||
363 | ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;; |
364 | ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;; |
364 | ;; ;; |
365 | ;; ;; |
365 | ;; Actual Hardware dependent code starts here ;; |
366 | ;; Actual Hardware dependent code starts here ;; |
366 | ;; ;; |
367 | ;; ;; |
367 | ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;; |
368 | ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;; |
368 | 369 | ||
369 | 370 | ||
370 | unload: |
371 | unload: |
371 | ; TODO: (in this particular order) |
372 | ; TODO: (in this particular order) |
372 | ; |
373 | ; |
373 | ; - Stop the device |
374 | ; - Stop the device |
374 | ; - Detach int handler |
375 | ; - Detach int handler |
375 | ; - Remove device from local list (device_list) |
376 | ; - Remove device from local list (device_list) |
376 | ; - call unregister function in kernel |
377 | ; - call unregister function in kernel |
377 | ; - Remove all allocated structures and buffers the card used |
378 | ; - Remove all allocated structures and buffers the card used |
378 | 379 | ||
379 | or eax,-1 |
380 | or eax, -1 |
380 | - | ||
381 | ret |
381 | ret |
382 | 382 | ||
383 | 383 | ||
384 | ;------------- |
384 | ;------------- |
385 | ; |
385 | ; |
386 | ; Probe |
386 | ; Probe |
387 | ; |
387 | ; |
388 | ;------------- |
388 | ;------------- |
389 | 389 | ||
390 | align 4 |
390 | align 4 |
391 | probe: |
391 | probe: |
392 | 392 | ||
393 | DEBUGF 1,"Probing\n" |
393 | DEBUGF 1,"Probing\n" |
394 | 394 | ||
395 | ; Make the device a bus master |
395 | ; Make the device a bus master |
396 | invoke PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command |
396 | invoke PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command |
397 | or al, PCI_CMD_MASTER |
397 | or al, PCI_CMD_MASTER |
398 | invoke PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax |
398 | invoke PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax |
399 | 399 | ||
400 | ;--------------------------- |
400 | ;--------------------------- |
401 | ; First, identify the device |
401 | ; First, identify the device |
402 | 402 | ||
403 | invoke PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header.vendor_id ; get device/vendor id |
403 | invoke PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header.vendor_id ; get device/vendor id |
404 | 404 | ||
405 | DEBUGF 1,"Vendor_id=0x%x\n", ax |
405 | DEBUGF 1,"Vendor_id=0x%x\n", ax |
406 | 406 | ||
407 | cmp ax, 0x8086 |
407 | cmp ax, 0x8086 |
408 | jne .notfound |
408 | jne .notfound |
409 | shr eax, 16 |
409 | shr eax, 16 |
410 | 410 | ||
411 | DEBUGF 1,"Device_id=0x%x\n", ax |
411 | DEBUGF 1,"Device_id=0x%x\n", ax |
412 | 412 | ||
413 | mov ecx, DEVICE_IDs |
413 | mov ecx, DEVICE_IDs |
414 | mov edi, device_id_list |
414 | mov edi, device_id_list |
415 | repne scasw |
415 | repne scasw |
416 | jne .notfound |
416 | jne .notfound |
417 | jmp .found |
417 | jmp .found |
418 | 418 | ||
419 | .notfound: |
419 | .notfound: |
420 | DEBUGF 2,"Unsupported device!\n" |
420 | DEBUGF 2,"Unsupported device!\n" |
421 | or eax, -1 |
421 | or eax, -1 |
422 | ret |
422 | ret |
423 | 423 | ||
424 | .found: |
424 | .found: |
425 | 425 | ||
426 | call ee_get_width |
426 | call ee_get_width |
427 | call MAC_read_eeprom |
427 | call MAC_read_eeprom |
428 | 428 | ||
429 | ;;; TODO: detect phy |
429 | ;;; TODO: detect phy |
430 | 430 | ||
431 | 431 | ||
432 | 432 | ||
433 | ;---------- |
433 | ;---------- |
434 | ; |
434 | ; |
435 | ; Reset |
435 | ; Reset |
436 | ; |
436 | ; |
437 | ;---------- |
437 | ;---------- |
438 | 438 | ||
439 | align 4 |
439 | align 4 |
440 | reset: |
440 | reset: |
441 | 441 | ||
442 | movzx eax, [ebx + device.irq_line] |
442 | movzx eax, [ebx + device.irq_line] |
443 | DEBUGF 1,"Attaching int handler to irq %x\n", eax:1 |
443 | DEBUGF 1,"Attaching int handler to irq %x\n", eax:1 |
444 | invoke AttachIntHandler, eax, int_handler, ebx |
444 | invoke AttachIntHandler, eax, int_handler, ebx |
445 | test eax, eax |
445 | test eax, eax |
446 | jnz @f |
446 | jnz @f |
447 | DEBUGF 2,"Could not attach int handler!\n" |
447 | DEBUGF 2,"Could not attach int handler!\n" |
448 | or eax, -1 |
448 | or eax, -1 |
449 | ret |
449 | ret |
450 | @@: |
450 | @@: |
451 | 451 | ||
452 | DEBUGF 1,"Resetting\n" |
452 | DEBUGF 1,"Resetting\n" |
453 | 453 | ||
454 | ;--------------- |
454 | ;--------------- |
455 | ; reset the card |
455 | ; reset the card |
456 | 456 | ||
457 | set_io [ebx + device.io_addr], 0 |
457 | set_io [ebx + device.io_addr], 0 |
458 | set_io [ebx + device.io_addr], reg_port |
458 | set_io [ebx + device.io_addr], reg_port |
459 | xor eax, eax ; Software Reset |
459 | xor eax, eax ; Software Reset |
460 | out dx, eax |
460 | out dx, eax |
461 | 461 | ||
462 | mov esi, 10 |
462 | mov esi, 10 |
463 | invoke Sleep ; Give the card time to warm up. |
463 | invoke Sleep ; Give the card time to warm up. |
464 | 464 | ||
465 | ;--------------------------------- |
465 | ;--------------------------------- |
466 | ; Tell device where to store stats |
466 | ; Tell device where to store stats |
467 | 467 | ||
468 | lea eax, [ebx + device.lstats.tx_good_frames] ; lstats |
468 | lea eax, [ebx + device.lstats.tx_good_frames] ; lstats |
469 | invoke GetPhysAddr |
469 | invoke GetPhysAddr |
470 | set_io [ebx + device.io_addr], 0 |
470 | set_io [ebx + device.io_addr], 0 |
471 | set_io [ebx + device.io_addr], reg_scb_ptr |
471 | set_io [ebx + device.io_addr], reg_scb_ptr |
472 | out dx, eax |
472 | out dx, eax |
473 | 473 | ||
474 | set_io [ebx + device.io_addr], reg_scb_cmd |
474 | set_io [ebx + device.io_addr], reg_scb_cmd |
475 | mov ax, CU_STATSADDR or INT_MASK |
475 | mov ax, CU_STATSADDR or INT_MASK |
476 | out dx, ax |
476 | out dx, ax |
477 | call cmd_wait |
477 | call cmd_wait |
478 | 478 | ||
479 | ;------------------------ |
479 | ;------------------------ |
480 | ; setup RX base addr to 0 |
480 | ; setup RX base addr to 0 |
481 | 481 | ||
482 | set_io [ebx + device.io_addr], reg_scb_ptr |
482 | set_io [ebx + device.io_addr], reg_scb_ptr |
483 | xor eax, eax |
483 | xor eax, eax |
484 | out dx, eax |
484 | out dx, eax |
485 | 485 | ||
486 | set_io [ebx + device.io_addr], reg_scb_cmd |
486 | set_io [ebx + device.io_addr], reg_scb_cmd |
487 | mov ax, RX_ADDR_LOAD or INT_MASK |
487 | mov ax, RX_ADDR_LOAD or INT_MASK |
488 | out dx, ax |
488 | out dx, ax |
489 | call cmd_wait |
489 | call cmd_wait |
490 | 490 | ||
491 | ;----------------------------- |
491 | ;----------------------------- |
492 | ; Create RX and TX descriptors |
492 | ; Create RX and TX descriptors |
493 | 493 | ||
494 | call init_rx_ring |
494 | call init_rx_ring |
495 | test eax, eax |
495 | test eax, eax |
496 | jz .error |
496 | jz .error |
497 | 497 | ||
498 | call init_tx_ring |
498 | call init_tx_ring |
499 | 499 | ||
500 | 500 | ||
501 | ;--------- |
501 | ;--------- |
502 | ; Start RX |
502 | ; Start RX |
503 | 503 | ||
504 | DEBUGF 1, "Starting RX" |
504 | DEBUGF 1, "Starting RX" |
505 | 505 | ||
506 | set_io [ebx + device.io_addr], 0 |
506 | set_io [ebx + device.io_addr], 0 |
507 | set_io [ebx + device.io_addr], reg_scb_ptr |
507 | set_io [ebx + device.io_addr], reg_scb_ptr |
508 | mov eax, [ebx + device.rx_desc] |
508 | mov eax, [ebx + device.rx_desc] |
509 | invoke GetPhysAddr |
509 | invoke GetPhysAddr |
510 | add eax, NET_BUFF.data |
510 | add eax, NET_BUFF.data |
511 | out dx, eax |
511 | out dx, eax |
512 | 512 | ||
513 | set_io [ebx + device.io_addr], reg_scb_cmd |
513 | set_io [ebx + device.io_addr], reg_scb_cmd |
514 | mov ax, RX_START or INT_MASK |
514 | mov ax, RX_START or INT_MASK |
515 | out dx, ax |
515 | out dx, ax |
516 | call cmd_wait |
516 | call cmd_wait |
517 | 517 | ||
518 | ;---------- |
518 | ;---------- |
519 | ; Set-up TX |
519 | ; Set-up TX |
520 | 520 | ||
521 | set_io [ebx + device.io_addr], reg_scb_ptr |
521 | set_io [ebx + device.io_addr], reg_scb_ptr |
522 | xor eax, eax |
522 | xor eax, eax |
523 | out dx, eax |
523 | out dx, eax |
524 | 524 | ||
525 | set_io [ebx + device.io_addr], reg_scb_cmd |
525 | set_io [ebx + device.io_addr], reg_scb_cmd |
526 | mov ax, CU_CMD_BASE or INT_MASK |
526 | mov ax, CU_CMD_BASE or INT_MASK |
527 | out dx, ax |
527 | out dx, ax |
528 | call cmd_wait |
528 | call cmd_wait |
529 | 529 | ||
530 | ;------------------------- |
530 | ;------------------------- |
531 | ; Individual address setup |
531 | ; Individual address setup |
532 | 532 | ||
533 | mov [ebx + device.confcmd.command], CmdIASetup + Cmdsuspend |
533 | mov [ebx + device.confcmd.command], CmdIASetup + Cmdsuspend |
534 | mov [ebx + device.confcmd.status], 0 |
534 | mov [ebx + device.confcmd.status], 0 |
535 | lea eax, [ebx + device.tx_ring] |
535 | lea eax, [ebx + device.tx_ring] |
536 | invoke GetPhysAddr |
536 | invoke GetPhysAddr |
537 | mov [ebx + device.confcmd.link], eax |
537 | mov [ebx + device.confcmd.link], eax |
538 | lea edi, [ebx + device.confcmd.data] |
538 | lea edi, [ebx + device.confcmd.data] |
539 | lea esi, [ebx + device.mac] |
539 | lea esi, [ebx + device.mac] |
540 | movsd |
540 | movsd |
541 | movsw |
541 | movsw |
542 | 542 | ||
543 | set_io [ebx + device.io_addr], reg_scb_ptr |
543 | set_io [ebx + device.io_addr], reg_scb_ptr |
544 | lea eax, [ebx + device.confcmd.status] |
544 | lea eax, [ebx + device.confcmd.status] |
545 | invoke GetPhysAddr |
545 | invoke GetPhysAddr |
546 | out dx, eax |
546 | out dx, eax |
547 | 547 | ||
548 | set_io [ebx + device.io_addr], reg_scb_cmd |
548 | set_io [ebx + device.io_addr], reg_scb_cmd |
549 | mov ax, CU_START or INT_MASK |
549 | mov ax, CU_START or INT_MASK |
550 | out dx, ax |
550 | out dx, ax |
551 | call cmd_wait |
551 | call cmd_wait |
552 | 552 | ||
553 | ;------------- |
553 | ;------------- |
554 | ; Configure CU |
554 | ; Configure CU |
555 | 555 | ||
556 | mov [ebx + device.confcmd.command], CmdConfigure + Cmdsuspend |
556 | mov [ebx + device.confcmd.command], CmdConfigure + Cmdsuspend |
557 | mov [ebx + device.confcmd.status], 0 |
557 | mov [ebx + device.confcmd.status], 0 |
558 | lea eax, [ebx + device.confcmd.status] |
558 | lea eax, [ebx + device.confcmd.status] |
559 | invoke GetPhysAddr |
559 | invoke GetPhysAddr |
560 | mov [ebx + device.confcmd.link], eax |
560 | mov [ebx + device.confcmd.link], eax |
561 | 561 | ||
562 | mov esi, confcmd_data |
562 | mov esi, confcmd_data |
563 | lea edi, [ebx + device.confcmd.data] |
563 | lea edi, [ebx + device.confcmd.data] |
564 | mov ecx, 22 |
564 | mov ecx, 22 |
565 | rep movsb |
565 | rep movsb |
566 | 566 | ||
567 | mov byte[ebx + device.confcmd.data + 1], 0x88 ; fifo of 8 each |
567 | mov byte[ebx + device.confcmd.data + 1], 0x88 ; fifo of 8 each |
568 | mov byte[ebx + device.confcmd.data + 4], 0 |
568 | mov byte[ebx + device.confcmd.data + 4], 0 |
569 | mov byte[ebx + device.confcmd.data + 5], 0x80 |
569 | mov byte[ebx + device.confcmd.data + 5], 0x80 |
570 | mov byte[ebx + device.confcmd.data + 15], 0x48 |
570 | mov byte[ebx + device.confcmd.data + 15], 0x48 |
571 | mov byte[ebx + device.confcmd.data + 19], 0x80 |
571 | mov byte[ebx + device.confcmd.data + 19], 0x80 |
572 | mov byte[ebx + device.confcmd.data + 21], 0x05 |
572 | mov byte[ebx + device.confcmd.data + 21], 0x05 |
573 | 573 | ||
574 | set_io [ebx + device.io_addr], reg_scb_ptr |
574 | set_io [ebx + device.io_addr], reg_scb_ptr |
575 | lea eax, [ebx + device.confcmd.status] |
575 | lea eax, [ebx + device.confcmd.status] |
576 | invoke GetPhysAddr |
576 | invoke GetPhysAddr |
577 | out dx, eax |
577 | out dx, eax |
578 | 578 | ||
579 | set_io [ebx + device.io_addr], reg_scb_cmd |
579 | set_io [ebx + device.io_addr], reg_scb_cmd |
580 | mov ax, CU_START ; expect Interrupts from now on |
580 | mov ax, CU_START ; expect Interrupts from now on |
581 | out dx, ax |
581 | out dx, ax |
582 | call cmd_wait |
582 | call cmd_wait |
583 | 583 | ||
584 | DEBUGF 1,"Reset complete\n" |
584 | DEBUGF 1,"Reset complete\n" |
585 | mov [ebx + device.mtu], 1514 |
585 | mov [ebx + device.mtu], 1514 |
586 | 586 | ||
587 | ; Set link state to unknown |
587 | ; Set link state to unknown |
588 | mov [ebx + device.state], ETH_LINK_UNKNOWN |
588 | mov [ebx + device.state], ETH_LINK_UNKNOWN |
589 | 589 | ||
590 | xor eax, eax ; indicate that we have successfully reset the card |
590 | xor eax, eax ; indicate that we have successfully reset the card |
591 | ret |
591 | ret |
592 | 592 | ||
593 | .error: |
593 | .error: |
594 | or eax, -1 |
594 | or eax, -1 |
595 | ret |
595 | ret |
596 | 596 | ||
597 | 597 | ||
598 | align 4 |
598 | align 4 |
599 | init_rx_ring: |
599 | init_rx_ring: |
600 | 600 | ||
601 | DEBUGF 1,"Creating ring\n" |
601 | DEBUGF 1,"Creating ring\n" |
602 | 602 | ||
603 | ;--------------------- |
603 | ;--------------------- |
604 | ; build rxfd structure |
604 | ; build rxfd structure |
605 | 605 | ||
606 | invoke NetAlloc, 2000 |
606 | invoke NetAlloc, 2000 |
607 | test eax, eax |
607 | test eax, eax |
608 | jz .out_of_mem |
608 | jz .out_of_mem |
609 | mov [ebx + device.rx_desc], eax |
609 | mov [ebx + device.rx_desc], eax |
610 | mov esi, eax |
610 | mov esi, eax |
611 | invoke GetPhysAddr |
611 | invoke GetPhysAddr |
612 | add eax, NET_BUFF.data |
612 | add eax, NET_BUFF.data |
613 | mov [esi + sizeof.NET_BUFF + rxfd.status], 0x0000 |
613 | mov [esi + sizeof.NET_BUFF + rxfd.status], 0x0000 |
614 | mov [esi + sizeof.NET_BUFF + rxfd.command], 0x0000 |
614 | mov [esi + sizeof.NET_BUFF + rxfd.command], 0xc000 ; End of list + Suspend |
615 | mov [esi + sizeof.NET_BUFF + rxfd.link], eax |
615 | mov [esi + sizeof.NET_BUFF + rxfd.link], eax |
616 | mov [esi + sizeof.NET_BUFF + rxfd.count], 0 |
616 | mov [esi + sizeof.NET_BUFF + rxfd.count], 0 |
617 | mov [esi + sizeof.NET_BUFF + rxfd.size], 1528 |
617 | mov [esi + sizeof.NET_BUFF + rxfd.size], 1528 |
618 | 618 | ||
619 | ret |
619 | ret |
620 | 620 | ||
621 | .out_of_mem: |
621 | .out_of_mem: |
622 | - | ||
623 | ret |
622 | ret |
624 | 623 | ||
625 | 624 | ||
626 | 625 | ||
627 | 626 | ||
628 | align 4 |
627 | align 4 |
629 | init_tx_ring: |
628 | init_tx_ring: |
630 | 629 | ||
631 | DEBUGF 1,"Creating TX ring\n" |
630 | DEBUGF 1,"Creating TX ring\n" |
632 | 631 | ||
633 | lea esi, [ebx + device.tx_ring] |
632 | lea esi, [ebx + device.tx_ring] |
634 | mov eax, esi |
633 | mov eax, esi |
635 | invoke GetPhysAddr |
634 | invoke GetPhysAddr |
636 | mov ecx, TX_RING_SIZE |
635 | mov ecx, TX_RING_SIZE |
637 | .next_desc: |
636 | .next_desc: |
638 | mov [esi + txfd.status], 0 |
637 | mov [esi + txfd.status], 0 |
639 | mov [esi + txfd.command], 0 |
638 | mov [esi + txfd.command], 0 |
640 | lea edx, [eax + txfd.buf_addr] |
639 | lea edx, [eax + txfd.buf_addr] |
641 | mov [esi + txfd.desc_addr], edx |
640 | mov [esi + txfd.desc_addr], edx |
642 | add eax, sizeof.txfd |
641 | add eax, sizeof.txfd |
643 | mov [esi + txfd.link], eax |
642 | mov [esi + txfd.link], eax |
644 | mov [esi + txfd.count], 0x01208000 ; One buffer, 0x20 bytes of transmit threshold, end of frame |
643 | mov [esi + txfd.count], 0x01208000 ; One buffer, 0x20 bytes of transmit threshold, end of frame |
645 | add esi, sizeof.txfd |
644 | add esi, sizeof.txfd |
646 | dec ecx |
645 | dec ecx |
647 | jnz .next_desc |
646 | jnz .next_desc |
648 | 647 | ||
649 | lea eax, [ebx + device.tx_ring] |
648 | lea eax, [ebx + device.tx_ring] |
650 | invoke GetPhysAddr |
649 | invoke GetPhysAddr |
651 | mov dword[ebx + device.tx_ring + sizeof.txfd*(TX_RING_SIZE-1) + txfd.link], eax |
650 | mov dword[ebx + device.tx_ring + sizeof.txfd*(TX_RING_SIZE-1) + txfd.link], eax |
652 | 651 | ||
653 | mov [ebx + device.cur_tx], 0 |
652 | mov [ebx + device.cur_tx], 0 |
654 | mov [ebx + device.last_tx], 0 |
653 | mov [ebx + device.last_tx], 0 |
655 | 654 | ||
656 | ret |
655 | ret |
657 | 656 | ||
658 | 657 | ||
659 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
658 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
660 | ;; ;; |
659 | ;; ;; |
661 | ;; Transmit ;; |
660 | ;; Transmit ;; |
662 | ;; ;; |
661 | ;; ;; |
663 | ;; In: pointer to device structure in ebx ;; |
662 | ;; In: pointer to device structure in ebx ;; |
664 | ;; ;; |
663 | ;; ;; |
665 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
664 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
666 | 665 | ||
667 | proc transmit stdcall bufferptr |
666 | proc transmit stdcall bufferptr |
668 | 667 | ||
669 | pushf |
668 | pushf |
670 | cli |
669 | cli |
671 | 670 | ||
672 | mov esi, [bufferptr] |
671 | mov esi, [bufferptr] |
673 | DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length] |
672 | DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length] |
674 | lea eax, [esi + NET_BUFF.data] |
673 | lea eax, [esi + NET_BUFF.data] |
675 | DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\ |
674 | DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\ |
676 | [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\ |
675 | [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\ |
677 | [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\ |
676 | [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\ |
678 | [eax+13]:2,[eax+12]:2 |
677 | [eax+13]:2,[eax+12]:2 |
679 | 678 | ||
680 | cmp [esi + NET_BUFF.length], 1514 |
679 | cmp [esi + NET_BUFF.length], 1514 |
681 | ja .fail |
680 | ja .fail |
682 | cmp [esi + NET_BUFF.length], 60 |
681 | cmp [esi + NET_BUFF.length], 60 |
683 | jb .fail |
682 | jb .fail |
684 | 683 | ||
685 | ; Get current TX descriptor |
684 | ; Get current TX descriptor |
686 | mov edi, [ebx + device.cur_tx] |
685 | mov edi, [ebx + device.cur_tx] |
687 | mov eax, sizeof.txfd |
686 | mov eax, sizeof.txfd |
688 | mul edi |
687 | mul edi |
689 | lea edi, [ebx + device.tx_ring + eax] |
688 | lea edi, [ebx + device.tx_ring + eax] |
690 | 689 | ||
691 | ; Check if current descriptor is free or still in use |
690 | ; Check if current descriptor is free or still in use |
692 | cmp [edi + txfd.status], 0 |
691 | cmp [edi + txfd.status], 0 |
693 | jne .fail |
692 | jne .fail |
694 | 693 | ||
695 | ; Fill in status and command values |
694 | ; Fill in status and command values |
696 | mov [edi + txfd.status], 0 |
695 | mov [edi + txfd.status], 0 |
697 | mov [edi + txfd.command], Cmdsuspend + CmdTx + CmdTxFlex ;;;+ 1 shl 15 ;;; EL bit |
696 | mov [edi + txfd.command], Cmdsuspend + CmdTx + CmdTxFlex ;;;+ 1 shl 15 ;;; EL bit |
698 | mov [edi + txfd.count], 0x01208000 |
697 | mov [edi + txfd.count], 0x01208000 |
699 | 698 | ||
700 | ; Fill in buffer address and size |
699 | ; Fill in buffer address and size |
701 | mov [edi + txfd.virt_addr], esi |
700 | mov [edi + txfd.virt_addr], esi |
702 | mov eax, esi |
701 | mov eax, esi |
703 | add eax, [esi + NET_BUFF.offset] |
702 | add eax, [esi + NET_BUFF.offset] |
704 | push edi |
703 | push edi |
705 | invoke GetPhysAddr |
704 | invoke GetPhysAddr |
706 | pop edi |
705 | pop edi |
707 | mov [edi + txfd.buf_addr], eax |
706 | mov [edi + txfd.buf_addr], eax |
708 | mov ecx, [esi + NET_BUFF.length] |
707 | mov ecx, [esi + NET_BUFF.length] |
709 | mov [edi + txfd.buf_size], ecx |
708 | mov [edi + txfd.buf_size], ecx |
710 | 709 | ||
711 | ; Inform device of the new/updated transmit descriptor |
710 | ; Inform device of the new/updated transmit descriptor |
712 | mov eax, edi |
711 | mov eax, edi |
713 | invoke GetPhysAddr |
712 | invoke GetPhysAddr |
714 | set_io [ebx + device.io_addr], 0 |
713 | set_io [ebx + device.io_addr], 0 |
715 | set_io [ebx + device.io_addr], reg_scb_ptr |
714 | set_io [ebx + device.io_addr], reg_scb_ptr |
716 | out dx, eax |
715 | out dx, eax |
717 | 716 | ||
718 | ; Start the transmit |
717 | ; Start the transmit |
719 | set_io [ebx + device.io_addr], reg_scb_cmd |
718 | set_io [ebx + device.io_addr], reg_scb_cmd |
720 | mov ax, CU_START |
719 | mov ax, CU_START |
721 | out dx, ax |
720 | out dx, ax |
722 | 721 | ||
723 | ; Update stats |
722 | ; Update stats |
724 | inc [ebx + device.packets_tx] |
723 | inc [ebx + device.packets_tx] |
725 | add dword[ebx + device.bytes_tx], ecx |
724 | add dword[ebx + device.bytes_tx], ecx |
726 | adc dword[ebx + device.bytes_tx + 4], 0 |
725 | adc dword[ebx + device.bytes_tx + 4], 0 |
727 | 726 | ||
728 | ; Wait for command to complete |
727 | ; Wait for command to complete |
729 | call cmd_wait |
728 | call cmd_wait |
730 | 729 | ||
731 | inc [ebx + device.cur_tx] |
730 | inc [ebx + device.cur_tx] |
732 | and [ebx + device.cur_tx], TX_RING_SIZE - 1 |
731 | and [ebx + device.cur_tx], TX_RING_SIZE - 1 |
733 | 732 | ||
734 | DEBUGF 1,"Transmit OK\n" |
733 | DEBUGF 1,"Transmit OK\n" |
735 | popf |
734 | popf |
736 | xor eax, eax |
735 | xor eax, eax |
737 | ret |
736 | ret |
738 | 737 | ||
739 | .fail: |
738 | .fail: |
740 | DEBUGF 2,"Transmit failed!\n" |
739 | DEBUGF 2,"Transmit failed!\n" |
741 | invoke NetFree, [bufferptr] |
740 | invoke NetFree, [bufferptr] |
742 | popf |
741 | popf |
743 | or eax, -1 |
742 | or eax, -1 |
744 | ret |
743 | ret |
745 | 744 | ||
746 | endp |
745 | endp |
747 | 746 | ||
748 | 747 | ||
749 | ;;;;;;;;;;;;;;;;;;;;;;; |
748 | ;;;;;;;;;;;;;;;;;;;;;;; |
750 | ;; ;; |
749 | ;; ;; |
751 | ;; Interrupt handler ;; |
750 | ;; Interrupt handler ;; |
752 | ;; ;; |
751 | ;; ;; |
753 | ;;;;;;;;;;;;;;;;;;;;;;; |
752 | ;;;;;;;;;;;;;;;;;;;;;;; |
754 | 753 | ||
755 | align 4 |
754 | align 4 |
756 | int_handler: |
755 | int_handler: |
757 | 756 | ||
758 | push ebx esi edi |
757 | push ebx esi edi |
759 | 758 | ||
760 | DEBUGF 1,"INT\n" |
759 | DEBUGF 1,"INT\n" |
761 | 760 | ||
762 | ; find pointer of device wich made IRQ occur |
761 | ; find pointer of device wich made IRQ occur |
763 | 762 | ||
764 | mov ecx, [devices] |
763 | mov ecx, [devices] |
765 | test ecx, ecx |
764 | test ecx, ecx |
766 | jz .nothing |
765 | jz .nothing |
767 | mov esi, device_list |
766 | mov esi, device_list |
768 | .nextdevice: |
767 | .nextdevice: |
769 | mov ebx, [esi] |
768 | mov ebx, [esi] |
770 | 769 | ||
771 | ; set_io [ebx + device.io_addr], 0 ; reg_scb_status = 0 |
770 | ; set_io [ebx + device.io_addr], 0 ; reg_scb_status = 0 |
772 | set_io [ebx + device.io_addr], reg_scb_status |
771 | set_io [ebx + device.io_addr], reg_scb_status |
773 | in ax, dx |
772 | in ax, dx |
774 | out dx, ax ; send it back to ACK |
773 | out dx, ax ; send it back to ACK |
775 | test ax, ax |
774 | test ax, ax |
776 | jnz .got_it |
775 | jnz .got_it |
777 | .continue: |
776 | .continue: |
778 | add esi, 4 |
777 | add esi, 4 |
779 | dec ecx |
778 | dec ecx |
780 | jnz .nextdevice |
779 | jnz .nextdevice |
781 | .nothing: |
780 | .nothing: |
782 | pop edi esi ebx |
781 | pop edi esi ebx |
783 | xor eax, eax |
782 | xor eax, eax |
784 | 783 | ||
785 | ret ; If no device was found, abort (The irq was probably for a device, not registered to this driver) |
784 | ret ; If no device was found, abort (The irq was probably for a device, not registered to this driver) |
786 | 785 | ||
787 | .got_it: |
786 | .got_it: |
788 | 787 | ||
789 | DEBUGF 1,"Device: %x Status: %x\n", ebx, ax |
788 | DEBUGF 1,"Device: %x Status: %x\n", ebx, ax |
790 | 789 | ||
791 | test ax, 1 shl 14 ; did we receive a frame? |
790 | test ax, 1 shl 14 ; did we receive a frame? |
792 | jz .no_rx |
791 | jz .no_rx |
793 | 792 | ||
794 | push ax |
793 | push ax |
795 | 794 | ||
796 | DEBUGF 1,"Receiving\n" |
795 | DEBUGF 1,"Receiving\n" |
797 | 796 | ||
798 | push ebx |
797 | push ebx |
799 | .rx_loop: |
798 | .rx_loop: |
800 | pop ebx |
799 | pop ebx |
801 | 800 | ||
802 | mov esi, [ebx + device.rx_desc] |
801 | mov esi, [ebx + device.rx_desc] |
803 | cmp [esi + sizeof.NET_BUFF + rxfd.status], 0 ; we could also check bits C and OK (bit 15 and 13) |
802 | cmp [esi + sizeof.NET_BUFF + rxfd.status], 0 ; we could also check bits C and OK (bit 15 and 13) |
804 | je .nodata |
803 | je .nodata |
805 | 804 | ||
806 | DEBUGF 1,"rxfd status=0x%x\n", [esi + sizeof.NET_BUFF + rxfd.status]:4 |
805 | DEBUGF 1,"rxfd status=0x%x\n", [esi + sizeof.NET_BUFF + rxfd.status]:4 |
807 | 806 | ||
808 | movzx ecx, [esi + sizeof.NET_BUFF + rxfd.count] |
807 | movzx ecx, [esi + sizeof.NET_BUFF + rxfd.count] |
809 | and ecx, 0x3fff |
808 | and ecx, 0x3fff |
810 | 809 | ||
811 | push ebx |
810 | push ebx |
812 | push .rx_loop |
811 | push .rx_loop |
813 | push esi |
812 | push esi |
814 | mov [esi + NET_BUFF.length], ecx |
813 | mov [esi + NET_BUFF.length], ecx |
815 | mov [esi + NET_BUFF.device], ebx |
814 | mov [esi + NET_BUFF.device], ebx |
816 | mov [esi + NET_BUFF.offset], NET_BUFF.data + rxfd.packet |
815 | mov [esi + NET_BUFF.offset], NET_BUFF.data + rxfd.packet |
817 | 816 | ||
818 | ; Update stats |
817 | ; Update stats |
819 | add dword [ebx + device.bytes_rx], ecx |
818 | add dword [ebx + device.bytes_rx], ecx |
820 | adc dword [ebx + device.bytes_rx + 4], 0 |
819 | adc dword [ebx + device.bytes_rx + 4], 0 |
821 | inc dword [ebx + device.packets_rx] |
820 | inc dword [ebx + device.packets_rx] |
822 | 821 | ||
823 | ; allocate new descriptor |
822 | ; allocate new descriptor |
824 | 823 | ||
825 | invoke NetAlloc, 2000 |
824 | invoke NetAlloc, 2000 |
826 | mov [ebx + device.rx_desc], eax |
825 | mov [ebx + device.rx_desc], eax |
827 | mov esi, eax |
826 | mov esi, eax |
828 | invoke GetPhysAddr |
827 | invoke GetPhysAddr |
829 | add eax, NET_BUFF.data |
828 | add eax, NET_BUFF.data |
830 | mov [esi + sizeof.NET_BUFF + rxfd.status], 0x0000 |
829 | mov [esi + sizeof.NET_BUFF + rxfd.status], 0x0000 |
831 | mov [esi + sizeof.NET_BUFF + rxfd.command], 0xc000 ; End of list + Suspend |
830 | mov [esi + sizeof.NET_BUFF + rxfd.command], 0xc000 ; End of list + Suspend |
832 | mov [esi + sizeof.NET_BUFF + rxfd.link], eax |
831 | mov [esi + sizeof.NET_BUFF + rxfd.link], eax |
833 | mov [esi + sizeof.NET_BUFF + rxfd.count], 0 |
832 | mov [esi + sizeof.NET_BUFF + rxfd.count], 0 |
834 | mov [esi + sizeof.NET_BUFF + rxfd.size], 1528 |
833 | mov [esi + sizeof.NET_BUFF + rxfd.size], 1528 |
835 | 834 | ||
836 | ; restart RX |
835 | ; restart RX |
837 | 836 | ||
838 | set_io [ebx + device.io_addr], 0 |
837 | set_io [ebx + device.io_addr], 0 |
839 | set_io [ebx + device.io_addr], reg_scb_ptr |
838 | set_io [ebx + device.io_addr], reg_scb_ptr |
840 | ; lea eax, [ebx + device.rx_desc] |
839 | ; mov eax, [ebx + device.rx_desc] |
841 | ; invoke GetPhysAddr |
840 | ; invoke GetPhysAddr |
- | 841 | ; add eax, NET_BUFF.data |
|
842 | out dx, eax |
842 | out dx, eax |
843 | 843 | ||
844 | set_io [ebx + device.io_addr], reg_scb_cmd |
844 | set_io [ebx + device.io_addr], reg_scb_cmd |
845 | mov ax, RX_START |
845 | mov ax, RX_START |
846 | out dx, ax |
846 | out dx, ax |
847 | call cmd_wait |
847 | call cmd_wait |
848 | 848 | ||
849 | ; And give packet to kernel |
849 | ; And give packet to kernel |
850 | jmp [EthInput] |
850 | jmp [EthInput] |
851 | 851 | ||
852 | .nodata: |
852 | .nodata: |
853 | DEBUGF 1, "no more data\n" |
853 | DEBUGF 1, "no more data\n" |
854 | pop ax |
854 | pop ax |
855 | 855 | ||
856 | .no_rx: |
856 | .no_rx: |
857 | 857 | ||
858 | test ax, 1 shl 13 |
858 | test ax, 1 shl 13 |
859 | jz .no_tx |
859 | jz .no_tx |
860 | DEBUGF 1, "Command completed\n" |
860 | DEBUGF 1, "Command completed\n" |
861 | 861 | ||
862 | push eax |
862 | push eax |
863 | .loop_tx: |
863 | .loop_tx: |
864 | mov edi, [ebx + device.last_tx] |
864 | mov edi, [ebx + device.last_tx] |
865 | mov eax, sizeof.txfd |
865 | mov eax, sizeof.txfd |
866 | mul eax |
866 | mul eax |
867 | lea edi, [ebx + device.tx_ring + eax] |
867 | lea edi, [ebx + device.tx_ring + eax] |
868 | 868 | ||
869 | cmp [edi + txfd.status], 0 |
869 | cmp [edi + txfd.status], 0 |
870 | je .tx_done |
870 | je .tx_done |
871 | 871 | ||
872 | cmp [edi + txfd.virt_addr], 0 |
872 | cmp [edi + txfd.virt_addr], 0 |
873 | je .tx_done |
873 | je .tx_done |
874 | 874 | ||
875 | DEBUGF 1,"Freeing buffer 0x%x\n", [edi + txfd.virt_addr] |
875 | DEBUGF 1,"Freeing buffer 0x%x\n", [edi + txfd.virt_addr] |
876 | 876 | ||
877 | push [edi + txfd.virt_addr] |
877 | push [edi + txfd.virt_addr] |
878 | mov [edi + txfd.virt_addr], 0 |
878 | mov [edi + txfd.virt_addr], 0 |
879 | invoke NetFree |
879 | invoke NetFree |
880 | 880 | ||
881 | inc [ebx + device.last_tx] |
881 | inc [ebx + device.last_tx] |
882 | and [ebx + device.last_tx], TX_RING_SIZE - 1 |
882 | and [ebx + device.last_tx], TX_RING_SIZE - 1 |
883 | 883 | ||
884 | jmp .loop_tx |
884 | jmp .loop_tx |
885 | .tx_done: |
885 | .tx_done: |
886 | pop eax |
886 | pop eax |
887 | .no_tx: |
887 | .no_tx: |
888 | 888 | ||
889 | and ax, 00111100b |
889 | and ax, 00111100b |
890 | cmp ax, 00001000b |
890 | cmp ax, 00001000b |
891 | jne .fail |
891 | jne .fail |
892 | 892 | ||
893 | DEBUGF 1, "out of resources!\n" |
- | |
894 | ; Restart the RX |
- | |
895 | - | ||
896 | ; allocate new descriptor |
893 | DEBUGF 2, "Out of resources!\n" |
897 | - | ||
898 | invoke KernelAlloc, 2000 |
894 | |
899 | mov [ebx + device.rx_desc], eax |
895 | ; call init_rx_ring |
900 | mov esi, eax |
- | |
901 | invoke GetPhysAddr |
- | |
902 | mov [esi + rxfd.status], 0x0000 |
- | |
903 | mov [esi + rxfd.command], 0xc000 ; End of list + Suspend |
- | |
904 | mov [esi + rxfd.link], eax |
- | |
905 | mov [esi + rxfd.count], 0 |
896 | ; test eax, eax |
906 | mov [esi + rxfd.size], 1528 |
- | |
907 | 897 | ; jz .fail |
|
908 | ; restart RX |
898 | |
909 | 899 | ; restart RX |
|
910 | set_io [ebx + device.io_addr], 0 |
900 | set_io [ebx + device.io_addr], 0 |
- | 901 | set_io [ebx + device.io_addr], reg_scb_ptr |
|
911 | set_io [ebx + device.io_addr], reg_scb_ptr |
902 | mov eax, [ebx + device.rx_desc] |
912 | ; lea eax, [ebx + device.rx_desc] |
903 | invoke GetPhysAddr |
913 | ; invoke GetPhysAddr |
904 | add eax, NET_BUFF.data |
914 | out dx, eax |
905 | out dx, eax |
915 | 906 | ||
916 | set_io [ebx + device.io_addr], reg_scb_cmd |
907 | set_io [ebx + device.io_addr], reg_scb_cmd |
917 | mov ax, RX_START |
908 | mov ax, RX_START |
918 | out dx, ax |
909 | out dx, ax |
919 | call cmd_wait |
910 | call cmd_wait |
920 | 911 | ||
921 | .fail: |
912 | .fail: |
922 | pop edi esi ebx |
913 | pop edi esi ebx |
923 | xor eax, eax |
914 | xor eax, eax |
924 | inc eax |
915 | inc eax |
925 | 916 | ||
926 | ret |
917 | ret |
927 | 918 | ||
928 | 919 | ||
929 | 920 | ||
930 | 921 | ||
931 | align 4 |
922 | align 4 |
932 | cmd_wait: |
923 | cmd_wait: |
933 | 924 | ||
934 | in al, dx |
925 | in al, dx |
935 | test al, al |
926 | test al, al |
936 | jnz cmd_wait |
927 | jnz cmd_wait |
937 | 928 | ||
938 | ret |
929 | ret |
939 | 930 | ||
940 | 931 | ||
941 | 932 | ||
942 | 933 | ||
943 | 934 | ||
944 | 935 | ||
945 | align 4 |
936 | align 4 |
946 | ee_read: ; esi = address to read |
937 | ee_read: ; esi = address to read |
947 | 938 | ||
948 | DEBUGF 1,"Eeprom read from 0x%x\n", esi |
939 | DEBUGF 1,"Eeprom read from 0x%x\n", esi |
949 | 940 | ||
950 | set_io [ebx + device.io_addr], 0 |
941 | set_io [ebx + device.io_addr], 0 |
951 | set_io [ebx + device.io_addr], reg_eeprom |
942 | set_io [ebx + device.io_addr], reg_eeprom |
952 | 943 | ||
953 | ;----------------------------------------------------- |
944 | ;----------------------------------------------------- |
954 | ; Prepend start bit + read opcode to the address field |
945 | ; Prepend start bit + read opcode to the address field |
955 | ; and shift it to the very left bits of esi |
946 | ; and shift it to the very left bits of esi |
956 | 947 | ||
957 | mov cl, 29 |
948 | mov cl, 29 |
958 | sub cl, [ebx + device.ee_bus_width] |
949 | sub cl, [ebx + device.ee_bus_width] |
959 | shl esi, cl |
950 | shl esi, cl |
960 | or esi, EE_READ shl 29 |
951 | or esi, EE_READ shl 29 |
961 | 952 | ||
962 | movzx ecx, [ebx + device.ee_bus_width] |
953 | movzx ecx, [ebx + device.ee_bus_width] |
963 | add ecx, 3 |
954 | add ecx, 3 |
964 | 955 | ||
965 | mov al, EE_CS |
956 | mov al, EE_CS |
966 | out dx, al |
957 | out dx, al |
967 | call udelay |
958 | call udelay |
968 | 959 | ||
969 | ;----------------------- |
960 | ;----------------------- |
970 | ; Write this to the chip |
961 | ; Write this to the chip |
971 | 962 | ||
972 | .loop: |
963 | .loop: |
973 | mov al, EE_CS + EE_SK |
964 | mov al, EE_CS + EE_SK |
974 | shl esi, 1 |
965 | shl esi, 1 |
975 | jnc @f |
966 | jnc @f |
976 | or al, EE_DI |
967 | or al, EE_DI |
977 | @@: |
968 | @@: |
978 | out dx, al |
969 | out dx, al |
979 | call udelay |
970 | call udelay |
980 | 971 | ||
981 | and al, not EE_SK |
972 | and al, not EE_SK |
982 | out dx, al |
973 | out dx, al |
983 | call udelay |
974 | call udelay |
984 | 975 | ||
985 | loop .loop |
976 | loop .loop |
986 | 977 | ||
987 | ;------------------------------ |
978 | ;------------------------------ |
988 | ; Now read the data from eeprom |
979 | ; Now read the data from eeprom |
989 | 980 | ||
990 | xor esi, esi |
981 | xor esi, esi |
991 | mov ecx, 16 |
982 | mov ecx, 16 |
992 | 983 | ||
993 | .loop2: |
984 | .loop2: |
994 | shl esi, 1 |
985 | shl esi, 1 |
995 | mov al, EE_CS + EE_SK |
986 | mov al, EE_CS + EE_SK |
996 | out dx, al |
987 | out dx, al |
997 | call udelay |
988 | call udelay |
998 | 989 | ||
999 | in al, dx |
990 | in al, dx |
1000 | test al, EE_DO |
991 | test al, EE_DO |
1001 | jz @f |
992 | jz @f |
1002 | inc esi |
993 | inc esi |
1003 | @@: |
994 | @@: |
1004 | 995 | ||
1005 | mov al, EE_CS |
996 | mov al, EE_CS |
1006 | out dx, al |
997 | out dx, al |
1007 | call udelay |
998 | call udelay |
1008 | 999 | ||
1009 | loop .loop2 |
1000 | loop .loop2 |
1010 | 1001 | ||
1011 | ;----------------------- |
1002 | ;----------------------- |
1012 | ; de-activate the eeprom |
1003 | ; de-activate the eeprom |
1013 | 1004 | ||
1014 | xor ax, ax |
1005 | xor ax, ax |
1015 | out dx, ax |
1006 | out dx, ax |
1016 | 1007 | ||
1017 | 1008 | ||
1018 | DEBUGF 1,"0x%x\n", esi:4 |
1009 | DEBUGF 1,"0x%x\n", esi:4 |
1019 | ret |
1010 | ret |
1020 | 1011 | ||
1021 | 1012 | ||
1022 | 1013 | ||
1023 | align 4 |
1014 | align 4 |
1024 | ee_write: ; esi = address to write to, di = data |
1015 | ee_write: ; esi = address to write to, di = data |
1025 | 1016 | ||
1026 | DEBUGF 1,"Eeprom write 0x%x to 0x%x\n", di, esi |
1017 | DEBUGF 1,"Eeprom write 0x%x to 0x%x\n", di, esi |
1027 | 1018 | ||
1028 | set_io [ebx + device.io_addr], 0 |
1019 | set_io [ebx + device.io_addr], 0 |
1029 | set_io [ebx + device.io_addr], reg_eeprom |
1020 | set_io [ebx + device.io_addr], reg_eeprom |
1030 | 1021 | ||
1031 | ;----------------------------------------------------- |
1022 | ;----------------------------------------------------- |
1032 | ; Prepend start bit + write opcode to the address field |
1023 | ; Prepend start bit + write opcode to the address field |
1033 | ; and shift it to the very left bits of esi |
1024 | ; and shift it to the very left bits of esi |
1034 | 1025 | ||
1035 | mov cl, 29 |
1026 | mov cl, 29 |
1036 | sub cl, [ebx + device.ee_bus_width] |
1027 | sub cl, [ebx + device.ee_bus_width] |
1037 | shl esi, cl |
1028 | shl esi, cl |
1038 | or esi, EE_WRITE shl 29 |
1029 | or esi, EE_WRITE shl 29 |
1039 | 1030 | ||
1040 | movzx ecx, [ebx + device.ee_bus_width] |
1031 | movzx ecx, [ebx + device.ee_bus_width] |
1041 | add ecx, 3 |
1032 | add ecx, 3 |
1042 | 1033 | ||
1043 | mov al, EE_CS ; enable chip |
1034 | mov al, EE_CS ; enable chip |
1044 | out dx, al |
1035 | out dx, al |
1045 | 1036 | ||
1046 | ;----------------------- |
1037 | ;----------------------- |
1047 | ; Write this to the chip |
1038 | ; Write this to the chip |
1048 | 1039 | ||
1049 | .loop: |
1040 | .loop: |
1050 | mov al, EE_CS + EE_SK |
1041 | mov al, EE_CS + EE_SK |
1051 | shl esi, 1 |
1042 | shl esi, 1 |
1052 | jnc @f |
1043 | jnc @f |
1053 | or al, EE_DI |
1044 | or al, EE_DI |
1054 | @@: |
1045 | @@: |
1055 | out dx, al |
1046 | out dx, al |
1056 | call udelay |
1047 | call udelay |
1057 | 1048 | ||
1058 | and al, not EE_SK |
1049 | and al, not EE_SK |
1059 | out dx, al |
1050 | out dx, al |
1060 | call udelay |
1051 | call udelay |
1061 | 1052 | ||
1062 | loop .loop |
1053 | loop .loop |
1063 | 1054 | ||
1064 | ;----------------------------- |
1055 | ;----------------------------- |
1065 | ; Now write the data to eeprom |
1056 | ; Now write the data to eeprom |
1066 | 1057 | ||
1067 | mov ecx, 16 |
1058 | mov ecx, 16 |
1068 | 1059 | ||
1069 | .loop2: |
1060 | .loop2: |
1070 | mov al, EE_CS + EE_SK |
1061 | mov al, EE_CS + EE_SK |
1071 | shl di, 1 |
1062 | shl di, 1 |
1072 | jnc @f |
1063 | jnc @f |
1073 | or al, EE_DI |
1064 | or al, EE_DI |
1074 | @@: |
1065 | @@: |
1075 | out dx, al |
1066 | out dx, al |
1076 | call udelay |
1067 | call udelay |
1077 | 1068 | ||
1078 | and al, not EE_SK |
1069 | and al, not EE_SK |
1079 | out dx, al |
1070 | out dx, al |
1080 | call udelay |
1071 | call udelay |
1081 | 1072 | ||
1082 | loop .loop2 |
1073 | loop .loop2 |
1083 | 1074 | ||
1084 | ;----------------------- |
1075 | ;----------------------- |
1085 | ; de-activate the eeprom |
1076 | ; de-activate the eeprom |
1086 | 1077 | ||
1087 | xor al, al |
1078 | xor al, al |
1088 | out dx, al |
1079 | out dx, al |
1089 | 1080 | ||
1090 | 1081 | ||
1091 | ret |
1082 | ret |
1092 | 1083 | ||
1093 | 1084 | ||
1094 | 1085 | ||
1095 | align 4 |
1086 | align 4 |
1096 | ee_get_width: |
1087 | ee_get_width: |
1097 | 1088 | ||
1098 | set_io [ebx + device.io_addr], 0 |
1089 | set_io [ebx + device.io_addr], 0 |
1099 | set_io [ebx + device.io_addr], reg_eeprom |
1090 | set_io [ebx + device.io_addr], reg_eeprom |
1100 | 1091 | ||
1101 | mov al, EE_CS ; activate eeprom |
1092 | mov al, EE_CS ; activate eeprom |
1102 | out dx, al |
1093 | out dx, al |
1103 | call udelay |
1094 | call udelay |
1104 | 1095 | ||
1105 | mov si, EE_READ shl 13 |
1096 | mov si, EE_READ shl 13 |
1106 | xor ecx, ecx |
1097 | xor ecx, ecx |
1107 | .loop: |
1098 | .loop: |
1108 | mov al, EE_CS + EE_SK |
1099 | mov al, EE_CS + EE_SK |
1109 | shl si, 1 |
1100 | shl si, 1 |
1110 | jnc @f |
1101 | jnc @f |
1111 | or al, EE_DI |
1102 | or al, EE_DI |
1112 | @@: |
1103 | @@: |
1113 | out dx, al |
1104 | out dx, al |
1114 | call udelay |
1105 | call udelay |
1115 | 1106 | ||
1116 | and al, not EE_SK |
1107 | and al, not EE_SK |
1117 | out dx, al |
1108 | out dx, al |
1118 | call udelay |
1109 | call udelay |
1119 | 1110 | ||
1120 | inc ecx |
1111 | inc ecx |
1121 | 1112 | ||
1122 | cmp ecx, 15 |
1113 | cmp ecx, 15 |
1123 | jae .give_up |
1114 | jae .give_up |
1124 | 1115 | ||
1125 | in al, dx |
1116 | in al, dx |
1126 | test al, EE_DO |
1117 | test al, EE_DO |
1127 | jnz .loop |
1118 | jnz .loop |
1128 | 1119 | ||
1129 | xor al, al |
1120 | xor al, al |
1130 | out dx, al ; de-activate eeprom |
1121 | out dx, al ; de-activate eeprom |
1131 | 1122 | ||
1132 | sub cl, 3 ; dont count the opcode bits |
1123 | sub cl, 3 ; dont count the opcode bits |
1133 | mov [ebx + device.ee_bus_width], cl |
1124 | mov [ebx + device.ee_bus_width], cl |
1134 | DEBUGF 1, "Eeprom width=%u bit\n", ecx |
1125 | DEBUGF 1, "Eeprom width=%u bit\n", ecx |
1135 | 1126 | ||
1136 | ret |
1127 | ret |
1137 | 1128 | ||
1138 | .give_up: |
1129 | .give_up: |
1139 | DEBUGF 2, "Eeprom not found!\n" |
1130 | DEBUGF 2, "Eeprom not found!\n" |
1140 | 1131 | ||
1141 | xor al, al |
1132 | xor al, al |
1142 | out dx, al ; de-activate eeprom |
1133 | out dx, al ; de-activate eeprom |
1143 | 1134 | ||
1144 | ret |
1135 | ret |
1145 | 1136 | ||
1146 | 1137 | ||
1147 | ; Wait a minimum of 2µs |
1138 | ; Wait a minimum of 2µs |
1148 | udelay: |
1139 | udelay: |
1149 | pusha |
1140 | pusha |
1150 | mov esi, 1 |
1141 | mov esi, 1 |
1151 | invoke Sleep |
1142 | invoke Sleep |
1152 | popa |
1143 | popa |
1153 | 1144 | ||
1154 | ret |
1145 | ret |
1155 | 1146 | ||
1156 | 1147 | ||
1157 | 1148 | ||
1158 | ; cx = phy addr |
1149 | ; cx = phy addr |
1159 | ; dx = phy reg addr |
1150 | ; dx = phy reg addr |
1160 | 1151 | ||
1161 | ; ax = data |
1152 | ; ax = data |
1162 | 1153 | ||
1163 | align 4 |
1154 | align 4 |
1164 | mdio_read: |
1155 | mdio_read: |
1165 | 1156 | ||
1166 | DEBUGF 1,"MDIO read\n" |
1157 | DEBUGF 1,"MDIO read\n" |
1167 | 1158 | ||
1168 | shl ecx, 21 ; PHY addr |
1159 | shl ecx, 21 ; PHY addr |
1169 | shl edx, 16 ; PHY reg addr |
1160 | shl edx, 16 ; PHY reg addr |
1170 | 1161 | ||
1171 | mov eax, ecx |
1162 | mov eax, ecx |
1172 | or eax, edx |
1163 | or eax, edx |
1173 | or eax, 10b shl 26 ; read opcode |
1164 | or eax, 10b shl 26 ; read opcode |
1174 | 1165 | ||
1175 | set_io [ebx + device.io_addr], 0 |
1166 | set_io [ebx + device.io_addr], 0 |
1176 | set_io [ebx + device.io_addr], reg_mdi_ctrl |
1167 | set_io [ebx + device.io_addr], reg_mdi_ctrl |
1177 | out dx, eax |
1168 | out dx, eax |
1178 | 1169 | ||
1179 | .wait: |
1170 | .wait: |
1180 | call udelay |
1171 | call udelay |
1181 | in eax, dx |
1172 | in eax, dx |
1182 | test eax, 1 shl 28 ; ready bit |
1173 | test eax, 1 shl 28 ; ready bit |
1183 | jz .wait |
1174 | jz .wait |
1184 | 1175 | ||
1185 | ret |
1176 | ret |
1186 | 1177 | ||
1187 | ; ax = data |
1178 | ; ax = data |
1188 | ; cx = phy addr |
1179 | ; cx = phy addr |
1189 | ; dx = phy reg addr |
1180 | ; dx = phy reg addr |
1190 | 1181 | ||
1191 | ; ax = data |
1182 | ; ax = data |
1192 | 1183 | ||
1193 | align 4 |
1184 | align 4 |
1194 | mdio_write: |
1185 | mdio_write: |
1195 | 1186 | ||
1196 | DEBUGF 1,"MDIO write\n" |
1187 | DEBUGF 1,"MDIO write\n" |
1197 | 1188 | ||
1198 | and eax, 0xffff |
1189 | and eax, 0xffff |
1199 | 1190 | ||
1200 | shl ecx, 21 ; PHY addr |
1191 | shl ecx, 21 ; PHY addr |
1201 | shl edx, 16 ; PHY reg addr |
1192 | shl edx, 16 ; PHY reg addr |
1202 | 1193 | ||
1203 | or eax, ecx |
1194 | or eax, ecx |
1204 | or eax, edx |
1195 | or eax, edx |
1205 | or eax, 01b shl 26 ; write opcode |
1196 | or eax, 01b shl 26 ; write opcode |
1206 | 1197 | ||
1207 | set_io [ebx + device.io_addr], 0 |
1198 | set_io [ebx + device.io_addr], 0 |
1208 | set_io [ebx + device.io_addr], reg_mdi_ctrl |
1199 | set_io [ebx + device.io_addr], reg_mdi_ctrl |
1209 | out dx, eax |
1200 | out dx, eax |
1210 | 1201 | ||
1211 | .wait: |
1202 | .wait: |
1212 | call udelay |
1203 | call udelay |
1213 | in eax, dx |
1204 | in eax, dx |
1214 | test eax, 1 shl 28 ; ready bit |
1205 | test eax, 1 shl 28 ; ready bit |
1215 | jz .wait |
1206 | jz .wait |
1216 | 1207 | ||
1217 | ret |
1208 | ret |
1218 | 1209 | ||
1219 | read_mac: |
1210 | read_mac: |
1220 | 1211 | ||
1221 | ret |
1212 | ret |
1222 | 1213 | ||
1223 | 1214 | ||
1224 | 1215 | ||
1225 | align 4 |
1216 | align 4 |
1226 | MAC_read_eeprom: |
1217 | MAC_read_eeprom: |
1227 | 1218 | ||
1228 | mov esi, 0 |
1219 | mov esi, 0 |
1229 | call ee_read |
1220 | call ee_read |
1230 | mov word[ebx + device.mac], si |
1221 | mov word[ebx + device.mac], si |
1231 | 1222 | ||
1232 | mov esi, 1 |
1223 | mov esi, 1 |
1233 | call ee_read |
1224 | call ee_read |
1234 | mov word[ebx + device.mac+2], si |
1225 | mov word[ebx + device.mac+2], si |
1235 | 1226 | ||
1236 | mov esi, 2 |
1227 | mov esi, 2 |
1237 | call ee_read |
1228 | call ee_read |
1238 | mov word[ebx + device.mac+4], si |
1229 | mov word[ebx + device.mac+4], si |
1239 | 1230 | ||
1240 | 1231 | ||
1241 | ret |
1232 | ret |
1242 | 1233 | ||
1243 | 1234 | ||
1244 | align 4 |
1235 | align 4 |
1245 | MAC_write: |
1236 | MAC_write: |
1246 | 1237 | ||
1247 | ;;;; |
1238 | ;;;; |
1248 | 1239 | ||
1249 | ret |
1240 | ret |
1250 | 1241 | ||
1251 | 1242 | ||
1252 | 1243 | ||
1253 | 1244 | ||
1254 | ; End of code |
1245 | ; End of code |
1255 | 1246 | ||
1256 | 1247 | ||
1257 | data fixups |
1248 | data fixups |
1258 | end data |
1249 | end data |
1259 | 1250 | ||
1260 | include '../peimport.inc' |
1251 | include '../peimport.inc' |
1261 | 1252 | ||
1262 | my_service db 'I8255X', 0 ; max 16 chars include zero |
1253 | my_service db 'I8255X', 0 ; max 16 chars include zero |
1263 | devicename db 'Intel Etherexpress pro/100', 0 |
1254 | devicename db 'Intel Etherexpress pro/100', 0 |
1264 | 1255 | ||
1265 | confcmd_data db 22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1 |
1256 | confcmd_data db 22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1 |
1266 | db 0, 0x2e, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2 |
1257 | db 0, 0x2e, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2 |
1267 | db 0x80, 0x3f, 0x05 ; 22 bytes total |
1258 | db 0x80, 0x3f, 0x05 ; 22 bytes total |
1268 | 1259 | ||
1269 | 1260 | ||
1270 | device_id_list: |
1261 | device_id_list: |
1271 | 1262 | ||
1272 | dw 0x1029 |
1263 | dw 0x1029 |
1273 | dw 0x1030 |
1264 | dw 0x1030 |
1274 | dw 0x1031 |
1265 | dw 0x1031 |
1275 | dw 0x1032 |
1266 | dw 0x1032 |
1276 | dw 0x1033 |
1267 | dw 0x1033 |
1277 | dw 0x1034 |
1268 | dw 0x1034 |
1278 | dw 0x1038 |
1269 | dw 0x1038 |
1279 | dw 0x1039 |
1270 | dw 0x1039 |
1280 | dw 0x103A |
1271 | dw 0x103A |
1281 | dw 0x103B |
1272 | dw 0x103B |
1282 | dw 0x103C |
1273 | dw 0x103C |
1283 | dw 0x103D |
1274 | dw 0x103D |
1284 | dw 0x103E |
1275 | dw 0x103E |
1285 | dw 0x1050 |
1276 | dw 0x1050 |
1286 | dw 0x1051 |
1277 | dw 0x1051 |
1287 | dw 0x1052 |
1278 | dw 0x1052 |
1288 | dw 0x1053 |
1279 | dw 0x1053 |
1289 | dw 0x1054 |
1280 | dw 0x1054 |
1290 | dw 0x1055 |
1281 | dw 0x1055 |
1291 | dw 0x1056 |
1282 | dw 0x1056 |
1292 | dw 0x1057 |
1283 | dw 0x1057 |
1293 | dw 0x1059 |
1284 | dw 0x1059 |
1294 | dw 0x1064 |
1285 | dw 0x1064 |
1295 | dw 0x1065 |
1286 | dw 0x1065 |
1296 | dw 0x1066 |
1287 | dw 0x1066 |
1297 | dw 0x1067 |
1288 | dw 0x1067 |
1298 | dw 0x1068 |
1289 | dw 0x1068 |
1299 | dw 0x1069 |
1290 | dw 0x1069 |
1300 | dw 0x106A |
1291 | dw 0x106A |
1301 | dw 0x106B |
1292 | dw 0x106B |
1302 | dw 0x1091 |
1293 | dw 0x1091 |
1303 | dw 0x1092 |
1294 | dw 0x1092 |
1304 | dw 0x1093 |
1295 | dw 0x1093 |
1305 | dw 0x1094 |
1296 | dw 0x1094 |
1306 | dw 0x1095 |
1297 | dw 0x1095 |
1307 | dw 0x10fe |
1298 | dw 0x10fe |
1308 | dw 0x1209 |
1299 | dw 0x1209 |
1309 | dw 0x1229 |
1300 | dw 0x1229 |
1310 | dw 0x2449 |
1301 | dw 0x2449 |
1311 | dw 0x2459 |
1302 | dw 0x2459 |
1312 | dw 0x245D |
1303 | dw 0x245D |
1313 | dw 0x27DC |
1304 | dw 0x27DC |
1314 | 1305 | ||
1315 | DEVICE_IDs = ($ - device_id_list) / 2 |
1306 | DEVICE_IDs = ($ - device_id_list) / 2 |
1316 | 1307 | ||
1317 | include_debug_strings ; All data wich FDO uses will be included here |
1308 | include_debug_strings ; All data wich FDO uses will be included here |
1318 | 1309 | ||
1319 | align 4 |
1310 | align 4 |
1320 | devices dd 0 ; number of currently running devices |
1311 | devices dd 0 ; number of currently running devices |
1321 | device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling |
1312 | device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling |