Add Yaru-dark skin from ConLenov
[kolibrios.git] / drivers / ethernet / pcnet32.asm
blob9f79f6db99bfa45d59406b164f0b0224b4adffaa
1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ;; ;;
3 ;; Copyright (C) KolibriOS team 2004-2021. All rights reserved. ;;
4 ;; Distributed under terms of the GNU General Public License ;;
5 ;; ;;
6 ;; AMD PCnet driver for KolibriOS ;;
7 ;; ;;
8 ;; By hidnplayr & clevermouse ;;
9 ;; ;;
10 ;; Based on the PCnet32 driver for MenuetOS, by Jarek Pelczar ;;
11 ;; ;;
12 ;; GNU GENERAL PUBLIC LICENSE ;;
13 ;; Version 2, June 1991 ;;
14 ;; ;;
15 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17 format PE DLL native
18 entry START
20 CURRENT_API = 0x0200
21 COMPATIBLE_API = 0x0100
22 API_VERSION = (COMPATIBLE_API shl 16) + CURRENT_API
24 ; configureable area
26 MAX_DEVICES = 16 ; Maximum number of devices this driver may handle
28 __DEBUG__ = 1 ; 1 = on, 0 = off
29 __DEBUG_LEVEL__ = 2 ; 1 = verbose, 2 = errors only
31 TX_RING_SIZE = 32 ; Number of packets in send ring buffer
32 RX_RING_SIZE = 32 ; Number of packets in receive ring buffer
34 ; end configureable area
36 section '.flat' readable writable executable
38 include '../struct.inc'
39 include '../macros.inc'
40 include '../proc32.inc'
41 include '../fdo.inc'
42 include '../netdrv.inc'
44 if (bsr TX_RING_SIZE)>(bsf TX_RING_SIZE)
45 display 'TX_RING_SIZE must be a power of two'
46 err
47 end if
49 if (bsr RX_RING_SIZE)>(bsf RX_RING_SIZE)
50 display 'RX_RING_SIZE must be a power of two'
51 err
52 end if
54 PORT_AUI = 0x00
55 PORT_10BT = 0x01
56 PORT_GPSI = 0x02
57 PORT_MII = 0x03
58 PORT_PORTSEL = 0x03
59 PORT_ASEL = 0x04
60 PORT_100 = 0x40
61 PORT_FD = 0x80
63 DMA_MASK = 0xffffffff
65 TX_RING_LEN_BITS = ((bsf TX_RING_SIZE) shl 12)
66 RX_RING_LEN_BITS = ((bsf RX_RING_SIZE) shl 4)
68 PKT_BUF_SZ = 1544
70 WIO_RDP = 0x10
71 WIO_RAP = 0x12
72 WIO_RESET = 0x14
73 WIO_BDP = 0x16
75 DWIO_RDP = 0x10
76 DWIO_RAP = 0x14
77 DWIO_RESET = 0x18
78 DWIO_BDP = 0x1C
80 ; CSR registers
82 CSR_CSR = 0x00
83 CSR_IAB0 = 0x01
84 CSR_IAB1 = 0x02
85 CSR_IMR = 0x03
86 CSR_TFEAT = 0x04
87 CSR_EXTCTL1 = 0x05
88 CSR_DTBLLEN = 0x06
89 CSR_EXTCTL2 = 0x07
90 CSR_MAR0 = 0x08
91 CSR_MAR1 = 0x09
92 CSR_MAR2 = 0x0A
93 CSR_MAR3 = 0x0B
94 CSR_PAR0 = 0x0C
95 CSR_PAR1 = 0x0D
96 CSR_PAR2 = 0x0E
97 CSR_MODE = 0x0F
98 CSR_RXADDR0 = 0x18
99 CSR_RXADDR1 = 0x19
100 CSR_TXADDR0 = 0x1E
101 CSR_TXADDR1 = 0x1F
102 CSR_TXPOLL = 0x2F
103 CSR_RXPOLL = 0x31
104 CSR_RXRINGLEN = 0x4C
105 CSR_TXRINGLEN = 0x4E
106 CSR_DMACTL = 0x50
107 CSR_BUSTIMER = 0x52
108 CSR_MEMERRTIMEO = 0x64
109 CSR_ONNOWMISC = 0x74
110 CSR_ADVFEAT = 0x7A
111 CSR_MACCFG = 0x7D
112 CSR_CHIPID0 = 0x58
113 CSR_CHIPID1 = 0x59
115 ; Control and Status Register (CSR0)
117 CSR_INIT = 0x0001 ;1 shl 0
118 CSR_START = 0x0002 ;1 shl 1
119 CSR_STOP = 0x0004 ;1 shl 2
120 CSR_TX = 0x0008 ;1 shl 3
121 CSR_TXON = 0x0010 ;1 shl 4
122 CSR_RXON = 0x0020 ;1 shl 5
123 CSR_INTEN = 0x0040 ;1 shl 6
124 CSR_INTR = 0x0080 ;1 shl 7
125 CSR_IDONE = 0x0100 ;1 shl 8
126 CSR_TINT = 0x0200 ;1 shl 9
127 CSR_RINT = 0x0400 ;1 shl 10
128 CSR_MERR = 0x0800 ;1 shl 11
129 CSR_MISS = 0x1000 ;1 shl 12
130 CSR_CERR = 0x2000 ;1 shl 13
132 ; Interrupt masks and deferral control (CSR3)
134 IMR_BSWAP = 0x0004
135 IMR_ENMBA = 0x0008 ; enable modified backoff alg
136 IMR_DXMT2PD = 0x0010
137 IMR_LAPPEN = 0x0020 ; lookahead packet processing enb
138 IMR_DXSUFLO = 0x0040 ; disable TX stop on underflow
139 IMR_IDONE = 0x0100
140 IMR_TINT = 0x0200
141 IMR_RINT = 0x0400
142 IMR_MERR = 0x0800
143 IMR_MISS = 0x1000
145 ; Masked interrupts will be disabled.
146 IMR = 0 ;IMR_IDONE ;or IMR_TINT or IMR_RINT or IMR_MERR or IMR_MISS
148 ; Test and features control (CSR4)
150 TFEAT_TXSTRTMASK = 0x0004
151 TFEAT_TXSTRT = 0x0008
152 TFEAT_RXCCOFLOWM = 0x0010 ; Rx collision counter oflow
153 TFEAT_RXCCOFLOW = 0x0020
154 TFEAT_UINT = 0x0040
155 TFEAT_UINTREQ = 0x0080
156 TFEAT_MISSOFLOWM = 0x0100
157 TFEAT_MISSOFLOW = 0x0200
158 TFEAT_STRIP_FCS = 0x0400
159 TFEAT_PAD_TX = 0x0800
160 TFEAT_TXDPOLL = 0x1000
161 TFEAT_DMAPLUS = 0x4000
163 ; Extended control and interrupt 1 (CSR5)
165 EXTCTL1_SPND = 0x0001 ; suspend
166 EXTCTL1_MPMODE = 0x0002 ; magic packet mode
167 EXTCTL1_MPENB = 0x0004 ; magic packet enable
168 EXTCTL1_MPINTEN = 0x0008 ; magic packet interrupt enable
169 EXTCTL1_MPINT = 0x0010 ; magic packet interrupt
170 EXTCTL1_MPPLBA = 0x0020 ; magic packet phys. logical bcast
171 EXTCTL1_EXDEFEN = 0x0040 ; excessive deferral interrupt enb.
172 EXTCTL1_EXDEF = 0x0080 ; excessive deferral interrupt
173 EXTCTL1_SINTEN = 0x0400 ; system interrupt enable
174 EXTCTL1_SINT = 0x0800 ; system interrupt
175 EXTCTL1_LTINTEN = 0x4000 ; last TX interrupt enb
176 EXTCTL1_TXOKINTD = 0x8000 ; TX OK interrupt disable
178 ; RX/TX descriptor len (CSR6)
180 DTBLLEN_RLEN = 0x0F00
181 DTBLLEN_TLEN = 0xF000
183 ; Extended control and interrupt 2 (CSR7)
185 EXTCTL2_MIIPDTINTE = 0x0001
186 EXTCTL2_MIIPDTINT = 0x0002
187 EXTCTL2_MCCIINTE = 0x0004
188 EXTCTL2_MCCIINT = 0x0008
189 EXTCTL2_MCCINTE = 0x0010
190 EXTCTL2_MCCINT = 0x0020
191 EXTCTL2_MAPINTE = 0x0040
192 EXTCTL2_MAPINT = 0x0080
193 EXTCTL2_MREINTE = 0x0100
194 EXTCTL2_MREINT = 0x0200
195 EXTCTL2_STINTE = 0x0400
196 EXTCTL2_STINT = 0x0800
197 EXTCTL2_RXDPOLL = 0x1000
198 EXTCTL2_RDMD = 0x2000
199 EXTCTL2_RXFRTG = 0x4000
200 EXTCTL2_FASTSPNDE = 0x8000
202 ; Mode (CSR15)
204 MODE_RXD = 0x0001 ; RX disable
205 MODE_TXD = 0x0002 ; TX disable
206 MODE_LOOP = 0x0004 ; loopback enable
207 MODE_TXCRCD = 0x0008
208 MODE_FORCECOLL = 0x0010
209 MODE_RETRYD = 0x0020
210 MODE_INTLOOP = 0x0040
211 MODE_PORTSEL = 0x0180
212 MODE_RXVPAD = 0x2000
213 MODE_RXNOBROAD = 0x4000
214 MODE_PROMISC = 0x8000
216 ; BCR (Bus Control Registers)
218 BCR_MMRA = 0x00 ; Master Mode Read Active
219 BCR_MMW = 0x01 ; Master Mode Write Active
220 BCR_MISCCFG = 0x02
221 BCR_LED0 = 0x04
222 BCR_LED1 = 0x05
223 BCR_LED2 = 0x06
224 BCR_LED3 = 0x07
225 BCR_DUPLEX = 0x09
226 BCR_BUSCTL = 0x12
227 BCR_EECTL = 0x13
228 BCR_SSTYLE = 0x14
229 BCR_PCILAT = 0x16
230 BCR_PCISUBVENID = 0x17
231 BCR_PCISUBSYSID = 0x18
232 BCR_SRAMSIZE = 0x19
233 BCR_SRAMBOUND = 0x1A
234 BCR_SRAMCTL = 0x1B
235 BCR_MIICTL = 0x20
236 BCR_MIIADDR = 0x21
237 BCR_MIIDATA = 0x22
238 BCR_PCIVENID = 0x23
239 BCR_PCIPCAP = 0x24
240 BCR_DATA0 = 0x25
241 BCR_DATA1 = 0x26
242 BCR_DATA2 = 0x27
243 BCR_DATA3 = 0x28
244 BCR_DATA4 = 0x29
245 BCR_DATA5 = 0x2A
246 BCR_DATA6 = 0x2B
247 BCR_DATA7 = 0x2C
248 BCR_ONNOWPAT0 = 0x2D
249 BCR_ONNOWPAT1 = 0x2E
250 BCR_ONNOWPAT2 = 0x2F
251 BCR_PHYSEL = 0x31
253 ; RX status register
255 RXSTAT_BPE = 0x0080 ; bus parity error
256 RXSTAT_ENP = 0x0100 ; end of packet
257 RXSTAT_STP = 0x0200 ; start of packet
258 RXSTAT_BUFF = 0x0400 ; buffer error
259 RXSTAT_CRC = 0x0800 ; CRC error
260 RXSTAT_OFLOW = 0x1000 ; rx overrun
261 RXSTAT_FRAM = 0x2000 ; framing error
262 RXSTAT_ERR = 0x4000 ; error summary
263 RXSTAT_OWN = 0x8000
265 ; TX status register
267 TXSTAT_TRC = 0x0000000F ; transmit retries
268 TXSTAT_RTRY = 0x04000000 ; retry
269 TXSTAT_LCAR = 0x08000000 ; lost carrier
270 TXSTAT_LCOL = 0x10000000 ; late collision
271 TXSTAT_EXDEF = 0x20000000 ; excessive deferrals
272 TXSTAT_UFLOW = 0x40000000 ; transmit underrun
273 TXSTAT_BUFF = 0x80000000 ; buffer error
275 TXCTL_OWN = 0x8000
276 TXCTL_ERR = 0x4000 ; error summary
277 TXCTL_ADD_FCS = 0x2000 ; add FCS to pkt
278 TXCTL_MORE_LTINT = 0x1000
279 TXCTL_ONE = 0x0800
280 TXCTL_DEF = 0x0400
281 TXCTL_STP = 0x0200
282 TXCTL_ENP = 0x0100
283 TXCTL_BPE = 0x0080
285 TXCTL_MBO = 0x0000F000
286 TXCTL_BUFSZ = 0x00000FFF
288 MAX_PHYS = 32
291 ; Pcnet configuration structure
292 struct pcnet_init_block
294 mode dw ?
295 tlen_rlen dw ?
296 phys_addr dp ?
297 reserved dw ?
298 filter dq ?
299 rx_ring_phys dd ?
300 tx_ring_phys dd ?
301 ends
304 struct device ETH_DEVICE
306 rb 0x100-($ and 0xff) ; align 256
307 init_block pcnet_init_block
309 rb 0x100-($ and 0xff) ; align 256
310 rx_ring rb RX_RING_SIZE * sizeof.descriptor
312 rb 0x100-($ and 0xff) ; align 256
313 tx_ring rb TX_RING_SIZE * sizeof.descriptor
315 cur_rx dd ?
316 cur_tx dd ?
317 last_tx dd ?
319 options dd ?
320 full_duplex db ?
321 chip_version dw ?
322 mii db ?
323 ltint db ?
324 dxsuflo db ?
325 fset db ?
326 fdx db ?
328 io_addr dd ?
329 irq_line db ?
330 pci_bus dd ?
331 pci_dev dd ?
333 phy dw ?
335 link_timer dd ?
337 rb 0x100-($ and 0xff) ; align 256
339 read_csr dd ?
340 write_csr dd ?
341 read_bcr dd ?
342 write_bcr dd ?
343 read_rap dd ?
344 write_rap dd ?
345 sw_reset dd ?
347 ends
349 struct descriptor
351 base dd ?
352 length dw ?
353 status dw ?
354 msg_length dw ?
355 misc dw ?
356 virtual dd ?
358 ends
361 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
362 ;; ;;
363 ;; proc START ;;
364 ;; ;;
365 ;; (standard driver proc) ;;
366 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
368 proc START c, reason:dword, cmdline:dword
370 cmp [reason], DRV_ENTRY
371 jne .fail
373 DEBUGF 2,"Loading driver\n"
374 invoke RegService, my_service, service_proc
377 .fail:
378 xor eax, eax
381 endp
384 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
385 ;; ;;
386 ;; proc SERVICE_PROC ;;
387 ;; ;;
388 ;; (standard driver proc) ;;
389 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
391 align 4
392 proc service_proc stdcall, ioctl:dword
394 mov edx, [ioctl]
395 mov eax, [edx + IOCTL.io_code]
397 ;------------------------------------------------------
399 cmp eax, 0 ;SRV_GETVERSION
400 jne @F
402 cmp [edx + IOCTL.out_size], 4
403 jb .fail
404 mov eax, [edx + IOCTL.output]
405 mov [eax], dword API_VERSION
407 xor eax, eax
410 ;------------------------------------------------------
412 cmp eax, 1 ;SRV_HOOK
413 jne .fail
415 cmp [edx + IOCTL.inp_size], 3 ; Data input must be at least 3 bytes
416 jb .fail
418 mov eax, [edx + IOCTL.input]
419 cmp byte[eax], 1 ; 1 means device number and bus number (pci) are given
420 jne .fail ; other types arent supported for this card yet
422 ; check if the device is already listed
424 mov ecx, [devices]
425 test ecx, ecx
426 jz .firstdevice
428 mov esi, device_list
429 ; mov eax, [edx + IOCTL.input] ; get the pci bus and device numbers
430 mov ax, [eax+1] ;
431 .nextdevice:
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
438 add esi, 4
439 loop .nextdevice
441 ; This device doesnt have its own eth_device structure yet, lets create one
443 .firstdevice:
444 cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
445 jae .fail
447 allocate_and_clear ebx, sizeof.device, .fail
449 ; Fill in the direct call addresses into the struct
451 mov [ebx + device.reset], reset
452 mov [ebx + device.transmit], transmit
453 mov [ebx + device.unload], unload
454 mov [ebx + device.name], my_service
456 ; save the pci bus and device numbers
458 mov eax, [edx + IOCTL.input]
459 movzx ecx, byte[eax+1]
460 mov [ebx + device.pci_bus], ecx
461 movzx ecx, byte[eax+2]
462 mov [ebx + device.pci_dev], ecx
464 ; Now, it's time to find the base io addres of the PCI device
466 stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev]
467 mov [ebx + device.io_addr], eax
469 ; We've found the io address, find IRQ now
471 invoke PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
472 mov [ebx + device.irq_line], al
474 DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
475 [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.io_addr]:4
477 ; Ok, the eth_device structure is ready, let's probe the device
478 ; Because initialization fires IRQ, IRQ handler must be aware of this device
479 mov eax, [devices] ; Add the device structure to our device list
480 mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
481 inc [devices] ;
483 call probe ; this function will output in eax
484 test eax, eax
485 jnz .destroy ; If an error occured, exit
487 mov [ebx + device.type], NET_TYPE_ETH
488 invoke NetRegDev
489 cmp eax, -1
490 je .destroy
494 ; If the device was already loaded, find the device number and return it in eax
496 .find_devicenum:
497 DEBUGF 1,"Trying to find device number of already registered device\n"
498 invoke NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
499 ; into a device number in edi
500 mov eax, edi ; Application wants it in eax instead
501 DEBUGF 1,"Kernel says: %u\n", eax
504 ; If an error occured, remove all allocated data and exit (returning -1 in eax)
506 .destroy:
507 ; todo: reset device into virgin state
508 add eax, NET_BUFF.data
509 dec [devices]
510 .err:
511 DEBUGF 2,"Error, removing all data !\n"
512 invoke KernelFree, ebx
514 .fail:
515 or eax, -1
518 ;------------------------------------------------------
519 endp
522 ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
523 ;; ;;
524 ;; Actual Hardware dependent code starts here ;;
525 ;; ;;
526 ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
528 align 4
529 unload:
531 cmp [ebx + device.link_timer], 0
532 je @f
533 invoke CancelTimerHS, [ebx + device.link_timer]
536 ; TODO: (in this particular order)
538 ; - Stop the device
539 ; - Detach int handler
540 ; - Remove device from local list (device_list)
541 ; - call unregister function in kernel
542 ; - Remove all allocated structures and buffers the card used
544 or eax, -1
548 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
550 ;; probe: enables the device (if it really is a PCnet device)
552 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
554 align 4
555 probe:
557 mov edx, [ebx + device.io_addr]
559 call wio_reset
561 xor ecx, ecx
562 call wio_read_csr
563 cmp eax, 4
564 jne .try_dwio
566 ; Try Word I/O
567 mov ax, 88
568 add edx, WIO_RAP
569 out dx, ax
572 in ax, dx
573 sub edx, WIO_RAP
574 cmp ax, 88
575 jne .try_dwio
577 call switch_to_wio
579 jmp .L1
581 .try_dwio:
582 call dwio_reset
584 xor ecx, ecx
585 call dwio_read_csr
586 cmp eax, 4
587 jne .no_dev
589 ; Try Dword I/O
590 add edx, DWIO_RAP
591 mov eax, 88
592 out dx, eax
595 in eax, dx
596 sub edx, DWIO_RAP
597 and eax, 0xffff
598 cmp eax, 88
599 jne .no_dev
601 call switch_to_dwio
603 jmp .L1
605 .no_dev:
606 DEBUGF 2,"device not found!\n"
607 mov eax, 1
610 .L1:
611 mov ecx, CSR_CHIPID0
612 call [ebx + device.read_csr]
614 mov esi, eax
615 shr esi, 12
617 and ax, 0xfff
618 cmp ax, 3
619 jne .no_dev
621 mov ecx, CSR_CHIPID1
622 call [ebx + device.read_csr]
623 shl eax, 4
624 or eax, esi
625 mov [ebx + device.chip_version], ax
627 mov [ebx + device.fdx], 0
628 mov [ebx + device.mii], 0
629 mov [ebx + device.fset], 0
630 mov [ebx + device.dxsuflo], 0
631 mov [ebx + device.ltint], 0
633 cmp ax, 0x2420
634 je .L2
635 cmp ax, 0x2430
636 je .L2
638 mov [ebx + device.fdx], 1
640 cmp ax, 0x2621
641 je .L4
642 cmp ax, 0x2623
643 je .L5
644 cmp ax, 0x2624
645 je .L6
646 cmp ax, 0x2625
647 je .L7
648 cmp ax, 0x2626
649 je .L8
650 cmp ax, 0x2627
651 je .L9
653 DEBUGF 2,"Invalid chip rev\n"
654 jmp .no_dev
655 .L2:
656 mov [ebx + device.name], device_l2
657 jmp .L10
658 .L4:
659 mov [ebx + device.name], device_l4
660 ; mov [ebx + device.fdx], 1
661 jmp .L10
662 .L5:
663 mov [ebx + device.name], device_l5
664 ; mov [ebx + device.fdx], 1
665 mov [ebx + device.mii], 1
666 mov [ebx + device.fset], 1
667 mov [ebx + device.ltint], 1
668 jmp .L10
669 .L6:
670 mov [ebx + device.name], device_l6
671 ; mov [ebx + device.fdx], 1
672 mov [ebx + device.mii], 1
673 mov [ebx + device.fset], 1
674 jmp .L10
675 .L7:
676 mov [ebx + device.name], device_l7
677 ; mov [ebx + device.fdx], 1
678 mov [ebx + device.mii], 1
679 jmp .L10
680 .L8:
681 mov [ebx + device.name], device_l8
682 ; mov [ebx + device.fdx], 1
683 mov ecx, CSR_RXPOLL
684 call dword [ebx + device.read_bcr]
685 call dword [ebx + device.write_bcr]
686 jmp .L10
687 .L9:
688 mov [ebx + device.name], device_l9
689 ; mov [ebx + device.fdx], 1
690 mov [ebx + device.mii], 1
691 .L10:
692 DEBUGF 1,"device name: %s\n", [ebx + device.name]
694 cmp [ebx + device.fset], 1
695 jne .L11
696 mov ecx, BCR_BUSCTL
697 call [ebx + device.read_bcr]
698 or eax, 0x800
699 call [ebx + device.write_bcr]
701 mov ecx, CSR_DMACTL
702 ; call [ebx + device.read_csr]
703 mov eax, 0xc00
704 call [ebx + device.write_csr]
706 mov [ebx + device.dxsuflo],1
707 mov [ebx + device.ltint],1
708 .L11:
710 ; Make the device a bus master
711 invoke PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
712 or al, PCI_CMD_MASTER
713 invoke PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
715 mov [ebx + device.options], PORT_ASEL
716 mov [ebx + device.init_block.mode], MODE_RXD + MODE_TXD ; disable receive and transmit
717 mov [ebx + device.init_block.tlen_rlen], (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
719 mov dword[ebx + device.init_block.filter], 0
720 mov dword[ebx + device.init_block.filter+4], 0
722 align 4
723 reset:
725 ; Stop link check timer if it was already running
726 cmp [ebx + device.link_timer], 0
727 je @f
728 invoke CancelTimerHS, [ebx + device.link_timer]
731 ; attach int handler
733 movzx eax, [ebx + device.irq_line]
734 DEBUGF 1,"Attaching int handler to irq %x\n", eax:1
735 invoke AttachIntHandler, eax, int_handler, ebx
736 test eax, eax
737 jnz @f
738 DEBUGF 2,"Could not attach int handler!\n"
739 or eax, -1
743 mov edx, [ebx + device.io_addr]
744 call [ebx + device.sw_reset]
746 ; Switch pcnet32 to 32bit mode
747 mov ecx, BCR_SSTYLE
748 mov eax, 2
749 call [ebx + device.write_bcr]
751 ; set/reset autoselect bit
752 mov ecx, BCR_MISCCFG
753 call [ebx + device.read_bcr]
754 and eax, not 2
755 test [ebx + device.options], PORT_ASEL
756 jz @f
757 or eax, 2
759 call [ebx + device.write_bcr]
761 ; Handle full duplex setting
762 cmp byte [ebx + device.full_duplex], 0
763 je .duplex_ok
764 mov ecx, BCR_DUPLEX
765 call [ebx + device.read_bcr]
766 and eax, not 3
767 test [ebx + device.options], PORT_FD
768 jz @f
769 or eax, 1
770 cmp [ebx + device.options], PORT_FD or PORT_AUI
771 jne .set_duplex
772 or eax, 2
773 jmp .set_duplex
775 test [ebx + device.options], PORT_ASEL
776 jz .set_duplex
777 cmp [ebx + device.chip_version], 0x2627
778 jne .set_duplex
779 or eax, 3
780 .set_duplex:
781 mov ecx, BCR_DUPLEX
782 call [ebx + device.write_bcr]
783 .duplex_ok:
785 ; set/reset GPSI bit in test register
786 mov ecx, 124
787 call [ebx + device.read_csr]
788 mov ecx, [ebx + device.options]
789 and ecx, PORT_PORTSEL
790 cmp ecx, PORT_GPSI
791 jne @f
792 or eax, 0x10
794 call [ebx + device.write_csr]
795 cmp [ebx + device.mii], 0
796 je .L6
797 test [ebx + device.options], PORT_ASEL
798 jnz .L6
799 mov ecx, BCR_MIICTL
800 call [ebx + device.read_bcr]
801 and eax, not 0x38
802 test [ebx + device.options], PORT_FD
803 jz @f
804 or eax, 0x10
806 test [ebx + device.options], PORT_100
807 jz @f
808 or eax, 0x08
810 call [ebx + device.write_bcr]
811 jmp .L9
812 .L6:
813 test [ebx + device.options], PORT_ASEL
814 jz .L9
815 mov ecx, BCR_MIICTL
816 DEBUGF 1,"ASEL, enable auto-negotiation\n"
817 call [ebx + device.read_bcr]
818 and eax, not 0x98
819 or eax, 0x20
820 call [ebx + device.write_bcr]
821 .L9:
822 cmp [ebx + device.ltint], 0
823 je @f
824 mov ecx, 5
825 call [ebx + device.read_csr]
826 or eax, (1 shl 14)
827 call [ebx + device.write_csr]
829 mov eax, [ebx + device.options]
830 and eax, PORT_PORTSEL
831 shl eax, 7
832 mov [ebx + device.init_block.mode], ax
833 mov dword [ebx + device.init_block.filter], -1
834 mov dword [ebx + device.init_block.filter+4], -1
838 ;-----------------------------
840 test [ebx + device.mii], 1
841 jz .no_mii
843 mov [ebx + device.phy], 0
845 .mii_loop:
846 mov ecx, MII_PHYSID1
847 call mdio_read
848 cmp ax, 0xffff
849 je .next
851 DEBUGF 1, "PHY ID1: 0x%x\n", ax
853 mov ecx, MII_PHYSID2
854 call mdio_read
855 cmp ax, 0xffff
856 je .next
858 DEBUGF 1, "PHY ID2: 0x%x\n", ax
860 jmp .got_phy
862 cmp [ebx + device.phy], 31
863 jne .next
864 mov ax, [ebx + device.chip_version]
865 inc ax
866 and ax, 0xfffe
867 cmp ax, 0x2624 ; 79c971 & 79c972 have phantom phy at id 31
868 je .got_phy
870 .next:
871 inc [ebx + device.phy]
872 cmp [ebx + device.phy], MAX_PHYS
873 jb .mii_loop
875 DEBUGF 2, "No PHY found!\n"
876 or eax, -1
879 .got_phy:
880 DEBUGF 1, "Found PHY at 0x%x\n", [ebx + device.phy]:4
882 .no_mii:
884 ;-----------------------------------------------
886 call read_mac
888 lea esi, [ebx + device.mac]
889 lea edi, [ebx + device.init_block.phys_addr]
890 movsd
891 movsw
893 call init_ring
894 test eax, eax
895 jnz .fail
897 mov edx, [ebx + device.io_addr] ; init ring destroys edx
899 lea eax, [ebx + device.init_block]
900 invoke GetPhysAddr
901 push eax
902 and eax, 0xffff
903 mov ecx, CSR_IAB0
904 call [ebx + device.write_csr]
905 pop eax
906 shr eax, 16
907 mov ecx, CSR_IAB1
908 call [ebx + device.write_csr]
910 mov ecx, CSR_TFEAT
911 mov eax, 0x0915 ; Auto TX PAD ?
912 call [ebx + device.write_csr]
914 ; Set the interrupt mask
915 mov ecx, CSR_IMR
916 mov eax, IMR
917 call [ebx + device.write_csr]
919 ; Initialise the device
920 xor ecx, ecx
921 mov eax, CSR_INIT
922 call [ebx + device.write_csr]
924 mov esi, 100
925 ; xor ecx, ecx
927 call [ebx + device.read_csr]
928 test ax, CSR_IDONE
929 jnz @f
931 dec esi
932 jnz @r
933 DEBUGF 2,"Initialize timeout!\n"
936 ; Start the device and enable interrupts
937 xor ecx, ecx
938 mov eax, CSR_START + CSR_INTEN
939 call [ebx + device.write_csr]
941 ; Set the MTU
942 mov [ebx + device.mtu], 1514
944 mov [ebx + device.state], ETH_LINK_UNKNOWN
945 ; Start media check timer
946 cmp [ebx + device.mii], 0
947 je @f
948 mov [ebx + device.state], ETH_LINK_DOWN
949 invoke TimerHS, 0, 50, check_media_mii, ebx
950 mov [ebx + device.link_timer], eax
953 DEBUGF 1,"reset complete\n"
954 xor eax, eax
955 .fail:
959 align 4
960 init_ring:
962 DEBUGF 1,"init ring\n"
964 lea edi, [ebx + device.rx_ring]
965 mov eax, edi
966 invoke GetPhysAddr
967 mov [ebx + device.init_block.rx_ring_phys], eax
968 mov ecx, RX_RING_SIZE
969 .rx_init:
970 push ecx
971 invoke NetAlloc, PKT_BUF_SZ+NET_BUFF.data
972 pop ecx
973 test eax, eax
974 jz .out_of_mem
975 mov [edi + descriptor.virtual], eax
976 invoke GetPhysAddr
977 add eax, NET_BUFF.data
978 mov [edi + descriptor.base], eax
979 mov [edi + descriptor.length], - PKT_BUF_SZ
980 mov dword[edi + descriptor.msg_length], 0 ; also clears misc field
981 mov [edi + descriptor.status], RXSTAT_OWN
982 add edi, sizeof.descriptor
983 dec ecx
984 jnz .rx_init
986 lea edi, [ebx + device.tx_ring]
987 mov eax, edi
988 invoke GetPhysAddr
989 mov [ebx + device.init_block.tx_ring_phys], eax
990 mov ecx, TX_RING_SIZE
991 .tx_init:
992 mov [edi + descriptor.status], 0
993 add edi, sizeof.descriptor
994 dec ecx
995 jnz .tx_init
997 mov [ebx + device.init_block.tlen_rlen], (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
999 mov [ebx + device.cur_tx], 0
1000 mov [ebx + device.last_tx], 0
1001 mov [ebx + device.cur_rx], 0
1003 xor eax, eax
1006 .out_of_mem:
1007 DEBUGF 2,"Out of memory!\n"
1009 or eax, -1
1015 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1016 ;; ;;
1017 ;; Transmit ;;
1018 ;; ;;
1019 ;; In: pointer to device structure in ebx ;;
1020 ;; ;;
1021 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1023 proc transmit stdcall bufferptr
1025 spin_lock_irqsave
1027 mov esi, [bufferptr]
1028 DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
1029 lea eax, [esi + NET_BUFF.data]
1030 DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
1031 [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
1032 [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
1033 [eax+13]:2,[eax+12]:2
1035 cmp [esi + NET_BUFF.length], 1514
1036 ja .error
1037 cmp [esi + NET_BUFF.length], 60
1038 jb .error
1040 ; check descriptor
1041 lea edi, [ebx + device.tx_ring]
1042 mov ecx, [ebx + device.cur_tx]
1043 shl ecx, 4
1044 add edi, ecx
1046 test [edi + descriptor.status], TXCTL_OWN
1047 jnz .overrun
1048 ; descriptor is free, use it
1049 mov [edi + descriptor.virtual], esi
1050 mov eax, esi
1051 add eax, [eax + NET_BUFF.offset]
1052 invoke GetPhysAddr
1053 mov [edi + descriptor.base], eax
1054 ; set length
1055 mov eax, [esi + NET_BUFF.length]
1056 neg eax
1057 mov [edi + descriptor.length], ax
1058 ; put to transfer queue
1059 mov [edi + descriptor.status], TXCTL_OWN + TXCTL_STP + TXCTL_ENP
1061 ; trigger an immediate send
1062 mov edx, [ebx + device.io_addr]
1063 xor ecx, ecx ; CSR0
1064 call [ebx + device.read_csr]
1065 or eax, CSR_TX
1066 call [ebx + device.write_csr]
1068 ; get next descriptor
1069 inc [ebx + device.cur_tx]
1070 and [ebx + device.cur_tx], TX_RING_SIZE - 1
1072 ; Update stats
1073 inc [ebx + device.packets_tx]
1074 mov eax, [esi + NET_BUFF.length]
1075 add dword[ebx + device.bytes_tx], eax
1076 adc dword[ebx + device.bytes_tx + 4], 0
1078 spin_unlock_irqrestore
1079 xor eax, eax
1082 .error:
1083 DEBUGF 2, "TX packet error\n"
1084 inc [ebx + device.packets_tx_err]
1085 invoke NetFree, [bufferptr]
1087 spin_unlock_irqrestore
1088 or eax, -1
1091 .overrun:
1092 DEBUGF 2, "TX overrun\n"
1093 inc [ebx + device.packets_tx_ovr]
1094 invoke NetFree, [bufferptr]
1096 spin_unlock_irqrestore
1097 or eax, -1
1100 endp
1103 ;;;;;;;;;;;;;;;;;;;;;;;
1104 ;; ;;
1105 ;; Interrupt handler ;;
1106 ;; ;;
1107 ;;;;;;;;;;;;;;;;;;;;;;;
1109 align 4
1110 int_handler:
1112 push ebx esi edi
1114 DEBUGF 1,"INT\n"
1116 ; find pointer of device wich made IRQ occur
1118 mov ecx, [devices]
1119 test ecx, ecx
1120 jz .nothing
1121 mov esi, device_list
1122 .nextdevice:
1123 mov ebx, [esi]
1124 mov edx, [ebx + device.io_addr]
1125 push ecx
1126 xor ecx, ecx ; CSR0
1127 call [ebx + device.read_csr] ; get IRQ reason
1128 call [ebx + device.write_csr] ; write it back to ACK
1129 pop ecx
1130 test ax, CSR_RINT or CSR_TINT
1131 jnz .got_it
1132 .continue:
1133 add esi, 4
1134 dec ecx
1135 jnz .nextdevice
1136 .nothing:
1137 pop edi esi ebx
1138 xor eax, eax
1142 .got_it:
1143 DEBUGF 1,"Device: %x status: %x\n", ebx, eax:4
1145 push ax
1146 test ax, CSR_RINT
1147 jz .not_receive
1149 push ebx
1150 .rx_loop:
1151 pop ebx
1152 push ebx
1153 mov eax, [ebx + device.cur_rx]
1154 shl eax, 4
1155 lea edi, [ebx + device.rx_ring]
1156 add edi, eax ; edi now points to current rx ring entry
1158 mov ax, [edi + descriptor.status]
1159 DEBUGF 1,"RX packet status: %x\n", eax:4
1161 test ax, RXSTAT_OWN ; If this bit is set, the controller OWN's the packet, if not, we do
1162 jnz .rx_done
1163 ; Both Start of packet and End of packet bits should be set, we dont support multi frame packets
1164 test ax, RXSTAT_ENP
1165 jz .rx_drop
1166 test ax, RXSTAT_STP
1167 jz .rx_drop
1169 movzx ecx, [edi + descriptor.msg_length] ; get packet length in ecx
1170 sub ecx, 4 ; We dont need the CRC
1171 DEBUGF 1,"Got %u bytes\n", ecx
1173 ; Set pointers for ETH_input
1174 push .rx_loop ; return address
1175 mov eax, [edi + descriptor.virtual]
1176 push eax ; packet address
1177 mov [eax + NET_BUFF.length], ecx
1178 mov [eax + NET_BUFF.device], ebx
1179 mov [eax + NET_BUFF.offset], NET_BUFF.data
1181 ; Update stats
1182 add dword[ebx + device.bytes_rx], ecx
1183 adc dword[ebx + device.bytes_rx + 4], 0
1184 inc [ebx + device.packets_rx]
1186 ; now allocate a new buffer
1187 invoke NetAlloc, PKT_BUF_SZ+NET_BUFF.data ; Allocate a buffer for the next packet
1188 test eax, eax
1189 jz .rx_overrun
1190 mov [edi + descriptor.virtual], eax ; set virtual address
1191 invoke GetPhysAddr
1192 add eax, NET_BUFF.data
1193 mov [edi + descriptor.base], eax ; and physical address
1194 mov [edi + descriptor.status], RXSTAT_OWN ; give it back to PCnet controller
1196 inc [ebx + device.cur_rx] ; set next receive descriptor
1197 and [ebx + device.cur_rx], RX_RING_SIZE - 1
1199 jmp [EthInput]
1201 .rx_overrun:
1202 add esp, 4+4
1203 DEBUGF 2,"RX FIFO overrun\n"
1204 inc [ebx + device.packets_rx_ovr]
1205 jmp .rx_next
1207 .rx_drop:
1208 DEBUGF 2,"Dropping incoming packet\n"
1209 inc [ebx + device.packets_rx_drop]
1211 .rx_next:
1212 mov [edi + descriptor.status], RXSTAT_OWN ; give it back to PCnet controller
1214 inc [ebx + device.cur_rx] ; set next receive descriptor
1215 and [ebx + device.cur_rx], RX_RING_SIZE - 1
1216 jmp .rx_loop
1218 .rx_done:
1219 pop ebx
1221 .not_receive:
1222 pop ax
1224 test ax, CSR_TINT
1225 jz .not_transmit
1227 .tx_loop:
1228 lea edi, [ebx + device.tx_ring]
1229 mov eax, [ebx + device.last_tx]
1230 shl eax, 4
1231 add edi, eax
1233 test [edi + descriptor.status], TXCTL_OWN
1234 jnz .not_transmit
1236 mov eax, [edi + descriptor.virtual]
1237 test eax, eax
1238 jz .not_transmit
1240 mov [edi + descriptor.virtual], 0
1242 DEBUGF 1,"Removing packet %x from memory\n", eax
1244 invoke NetFree, eax
1246 inc [ebx + device.last_tx]
1247 and [ebx + device.last_tx], TX_RING_SIZE - 1
1248 jmp .tx_loop
1250 .not_transmit:
1251 pop edi esi ebx
1252 xor eax, eax
1253 inc eax
1260 ;;;;;;;;;;;;;;;;;;;;;;;
1261 ;; ;;
1262 ;; Write MAC address ;;
1263 ;; ;;
1264 ;;;;;;;;;;;;;;;;;;;;;;;
1266 align 4
1267 write_mac: ; in: mac pushed onto stack (as 3 words)
1269 DEBUGF 1,"Writing MAC: %x-%x-%x-%x-%x-%x\n",\
1270 [esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
1272 mov edx, [ebx + device.io_addr]
1273 add dx, 2
1274 xor eax, eax
1276 mov ecx, CSR_PAR0
1278 pop ax
1279 call [ebx + device.write_csr]
1280 inc ecx
1281 cmp ecx, CSR_PAR2
1282 jb @r
1284 ; Notice this procedure does not ret, but continues to read_mac instead.
1286 ;;;;;;;;;;;;;;;;;;;;;;
1287 ;; ;;
1288 ;; Read MAC address ;;
1289 ;; ;;
1290 ;;;;;;;;;;;;;;;;;;;;;;
1291 align 4
1292 read_mac:
1293 DEBUGF 1,"Reading MAC\n"
1295 mov edx, [ebx + device.io_addr]
1296 lea edi, [ebx + device.mac]
1297 in ax, dx
1298 stosw
1300 inc dx
1301 inc dx
1302 in ax, dx
1303 stosw
1305 inc dx
1306 inc dx
1307 in ax, dx
1308 stosw
1310 DEBUGF 1,"MAC = %x-%x-%x-%x-%x-%x\n",\
1311 [ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,\
1312 [ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
1316 align 4
1317 switch_to_wio:
1319 DEBUGF 1,"Switching to 16-bit mode\n"
1321 mov [ebx + device.read_csr], wio_read_csr
1322 mov [ebx + device.write_csr], wio_write_csr
1323 mov [ebx + device.read_bcr], wio_read_bcr
1324 mov [ebx + device.write_bcr], wio_write_bcr
1325 mov [ebx + device.read_rap], wio_read_rap
1326 mov [ebx + device.write_rap], wio_write_rap
1327 mov [ebx + device.sw_reset], wio_reset
1331 align 4
1332 switch_to_dwio:
1334 DEBUGF 1,"Switching to 32-bit mode\n"
1336 mov [ebx + device.read_csr], dwio_read_csr
1337 mov [ebx + device.write_csr], dwio_write_csr
1338 mov [ebx + device.read_bcr], dwio_read_bcr
1339 mov [ebx + device.write_bcr], dwio_write_bcr
1340 mov [ebx + device.read_rap], dwio_read_rap
1341 mov [ebx + device.write_rap], dwio_write_rap
1342 mov [ebx + device.sw_reset], dwio_reset
1347 ; ecx - index
1348 ; return:
1349 ; eax - data
1350 align 4
1351 wio_read_csr:
1353 add edx, WIO_RAP
1354 mov ax, cx
1355 out dx, ax
1356 add edx, WIO_RDP - WIO_RAP
1357 in ax, dx
1358 and eax, 0xffff
1359 sub edx, WIO_RDP
1364 ; eax - data
1365 ; ecx - index
1366 align 4
1367 wio_write_csr:
1369 add edx, WIO_RAP
1370 xchg eax, ecx
1371 out dx, ax
1372 xchg eax, ecx
1373 add edx, WIO_RDP - WIO_RAP
1374 out dx, ax
1375 sub edx, WIO_RDP
1380 ; ecx - index
1381 ; return:
1382 ; eax - data
1383 align 4
1384 wio_read_bcr:
1386 add edx, WIO_RAP
1387 mov ax, cx
1388 out dx, ax
1389 add edx, WIO_BDP - WIO_RAP
1390 in ax, dx
1391 and eax, 0xffff
1392 sub edx, WIO_BDP
1397 ; eax - data
1398 ; ecx - index
1399 align 4
1400 wio_write_bcr:
1402 add edx, WIO_RAP
1403 xchg eax, ecx
1404 out dx, ax
1405 xchg eax, ecx
1406 add edx, WIO_BDP - WIO_RAP
1407 out dx, ax
1408 sub edx, WIO_BDP
1412 align 4
1413 wio_read_rap:
1415 add edx, WIO_RAP
1416 in ax, dx
1417 and eax, 0xffff
1418 sub edx, WIO_RAP
1422 ; eax - val
1423 align 4
1424 wio_write_rap:
1426 add edx, WIO_RAP
1427 out dx, ax
1428 sub edx, WIO_RAP
1432 align 4
1433 wio_reset:
1435 push eax
1436 add edx, WIO_RESET
1437 in ax, dx
1438 pop eax
1439 sub edx, WIO_RESET
1445 ; ecx - index
1446 ; return:
1447 ; eax - data
1448 align 4
1449 dwio_read_csr:
1451 add edx, DWIO_RAP
1452 mov eax, ecx
1453 out dx, eax
1454 add edx, DWIO_RDP - DWIO_RAP
1455 in eax, dx
1456 and eax, 0xffff
1457 sub edx, DWIO_RDP
1462 ; ecx - index
1463 ; eax - data
1464 align 4
1465 dwio_write_csr:
1467 add edx, DWIO_RAP
1468 xchg eax, ecx
1469 out dx, eax
1470 add edx, DWIO_RDP - DWIO_RAP
1471 xchg eax, ecx
1472 out dx, eax
1473 sub edx, DWIO_RDP
1477 ; ecx - index
1478 ; return:
1479 ; eax - data
1480 align 4
1481 dwio_read_bcr:
1483 add edx, DWIO_RAP
1484 mov eax, ecx
1485 out dx, eax
1486 add edx, DWIO_BDP - DWIO_RAP
1487 in eax, dx
1488 and eax, 0xffff
1489 sub edx, DWIO_BDP
1494 ; ecx - index
1495 ; eax - data
1496 align 4
1497 dwio_write_bcr:
1499 add edx, DWIO_RAP
1500 xchg eax, ecx
1501 out dx, eax
1502 add edx, DWIO_BDP - DWIO_RAP
1503 xchg eax, ecx
1504 out dx, eax
1505 sub edx, DWIO_BDP
1509 align 4
1510 dwio_read_rap:
1512 add edx, DWIO_RAP
1513 in eax, dx
1514 and eax, 0xffff
1515 sub edx, DWIO_RAP
1520 ; eax - val
1521 align 4
1522 dwio_write_rap:
1524 add edx, DWIO_RAP
1525 out dx, eax
1526 sub edx, DWIO_RAP
1530 align 4
1531 dwio_reset:
1533 push eax
1534 add edx, DWIO_RESET
1535 in eax, dx
1536 pop eax
1537 sub edx, DWIO_RESET
1542 align 4
1543 mdio_read:
1545 and ecx, 0x1f
1546 mov ax, [ebx + device.phy]
1547 and ax, 0x1f
1548 shl ax, 5
1549 or ax, cx
1551 mov ecx, BCR_MIIADDR
1552 call [ebx + device.write_bcr]
1554 mov ecx, BCR_MIIDATA
1555 call [ebx + device.read_bcr]
1560 align 4
1561 mdio_write:
1563 push eax
1564 and ecx, 0x1f
1565 mov ax, [ebx + device.phy]
1566 and ax, 0x1f
1567 shl ax, 5
1568 or ax, cx
1570 mov ecx, BCR_MIIADDR
1571 call [ebx + device.write_bcr]
1573 pop eax
1574 mov ecx, BCR_MIIDATA
1575 call [ebx + device.write_bcr]
1582 proc check_media_mii stdcall dev:dword
1584 spin_lock_irqsave
1586 mov ebx, [dev]
1587 mov edx, [ebx + device.io_addr]
1589 mov ecx, MII_BMSR
1590 call mdio_read
1592 mov ecx, MII_BMSR
1593 call mdio_read
1595 mov ecx, eax
1596 and eax, BMSR_LSTATUS
1597 shr eax, 2
1598 cmp eax, [ebx + device.state]
1599 jne .changed
1601 spin_unlock_irqrestore
1604 .changed:
1605 test eax, eax
1606 jz .update
1608 test ecx, BMSR_ANEGCOMPLETE
1609 jz .update
1611 mov ecx, MII_ADVERTISE
1612 call mdio_read
1613 mov esi, eax
1615 mov ecx, MII_LPA
1616 call mdio_read
1617 and eax, esi
1619 test eax, LPA_100FULL
1620 jz @f
1621 mov eax, ETH_LINK_SPEED_100M or ETH_LINK_FULL_DUPLEX
1622 jmp .update
1625 test eax, LPA_100HALF
1626 jz @f
1627 mov eax, ETH_LINK_SPEED_100M
1628 jmp .update
1631 test eax, LPA_10FULL
1632 jz @f
1633 mov eax, ETH_LINK_SPEED_10M or ETH_LINK_FULL_DUPLEX
1634 jmp .update
1637 test eax, LPA_10HALF
1638 jz @f
1639 mov eax, ETH_LINK_SPEED_10M
1640 jmp .update
1643 mov eax, ETH_LINK_UNKNOWN
1645 .update:
1646 mov [ebx + device.state], eax
1647 invoke NetLinkChanged
1650 spin_unlock_irqrestore
1654 endp
1657 ; End of code
1660 data fixups
1661 end data
1663 include '../peimport.inc'
1665 my_service db 'PCNET32',0 ; max 16 chars include zero
1667 device_l2 db "PCnet/PCI 79C970",0
1668 device_l4 db "PCnet/PCI II 79C970A",0
1669 device_l5 db "PCnet/FAST 79C971",0
1670 device_l6 db "PCnet/FAST+ 79C972",0
1671 device_l7 db "PCnet/FAST III 79C973",0
1672 device_l8 db "PCnet/Home 79C978",0
1673 device_l9 db "PCnet/FAST III 79C975",0
1675 options_mapping:
1676 dd PORT_ASEL ; 0 Auto-select
1677 dd PORT_AUI ; 1 BNC/AUI
1678 dd PORT_AUI ; 2 AUI/BNC
1679 dd PORT_ASEL ; 3 not supported
1680 dd PORT_10BT or PORT_FD ; 4 10baseT-FD
1681 dd PORT_ASEL ; 5 not supported
1682 dd PORT_ASEL ; 6 not supported
1683 dd PORT_ASEL ; 7 not supported
1684 dd PORT_ASEL ; 8 not supported
1685 dd PORT_MII ; 9 MII 10baseT
1686 dd PORT_MII or PORT_FD ; 10 MII 10baseT-FD
1687 dd PORT_MII ; 11 MII (autosel)
1688 dd PORT_10BT ; 12 10BaseT
1689 dd PORT_MII or PORT_100 ; 13 MII 100BaseTx
1690 dd PORT_MII or PORT_100 or PORT_FD ; 14 MII 100BaseTx-FD
1691 dd PORT_ASEL ; 15 not supported
1693 include_debug_strings ; All data wich FDO uses will be included here
1696 align 4
1697 devices dd 0
1698 device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling