Rev 7827 | Rev 9147 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
7809 | hidnplayr | 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
||
9146 | hidnplayr | 3 | ;; Copyright (C) KolibriOS team 2018-2021. All rights reserved. ;; |
7809 | hidnplayr | 4 | ;; Distributed under terms of the GNU General Public License ;; |
5 | ;; ;; |
||
6 | ;; AR81XX driver for KolibriOS ;; |
||
7 | ;; ;; |
||
8 | ;; based on alx driver from TI-OpenLink ;; |
||
9 | ;; ;; |
||
7827 | hidnplayr | 10 | ;; Written by hidnplayr (hidnplayr@gmail.com) ;; |
7809 | hidnplayr | 11 | ;; ;; |
7827 | hidnplayr | 12 | ;; Thanks to: floppy121 for kindly providing me with the hardware ;; |
13 | ;; that made the development of this driver possible. ;; |
||
14 | ;; ;; |
||
7809 | hidnplayr | 15 | ;; GNU GENERAL PUBLIC LICENSE ;; |
16 | ;; Version 2, June 1991 ;; |
||
17 | ;; ;; |
||
18 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
19 | |||
20 | format PE DLL native |
||
21 | entry START |
||
22 | |||
23 | CURRENT_API = 0x0200 |
||
24 | COMPATIBLE_API = 0x0100 |
||
25 | API_VERSION = (COMPATIBLE_API shl 16) + CURRENT_API |
||
26 | |||
9146 | hidnplayr | 27 | ; configureable area |
7809 | hidnplayr | 28 | |
9146 | hidnplayr | 29 | MAX_DEVICES = 16 ; Maximum number of devices this driver may handle |
7809 | hidnplayr | 30 | |
9146 | hidnplayr | 31 | __DEBUG__ = 1 ; 1 = on, 0 = off |
32 | __DEBUG_LEVEL__ = 2 ; 1 = verbose, 2 = errors only |
||
7809 | hidnplayr | 33 | |
9146 | hidnplayr | 34 | TX_RING_SIZE = 128 ; Number of packets in send ring buffer |
35 | RX_RING_SIZE = 128 ; Number of packets in receive ring buffer |
||
36 | |||
7809 | hidnplayr | 37 | RX_BUFFER_SIZE = 1536 |
38 | |||
39 | SMB_TIMER = 400 |
||
9146 | hidnplayr | 40 | IMT = 200 ; IRQ Modulo Timer |
41 | ITH_TPD = TX_RING_SIZE / 3 ; Interrupt Threshold TPD |
||
7809 | hidnplayr | 42 | |
9146 | hidnplayr | 43 | ; end configureable area |
44 | |||
7809 | hidnplayr | 45 | section '.flat' readable writable executable |
46 | |||
47 | include '../proc32.inc' |
||
48 | include '../struct.inc' |
||
49 | include '../macros.inc' |
||
50 | include '../fdo.inc' |
||
51 | include '../netdrv.inc' |
||
52 | |||
53 | include 'ar81xx.inc' |
||
54 | |||
9146 | hidnplayr | 55 | if (bsr TX_RING_SIZE)>(bsf TX_RING_SIZE) |
56 | display 'TX_RING_SIZE must be a power of two' |
||
57 | err |
||
58 | end if |
||
59 | |||
60 | if (bsr RX_RING_SIZE)>(bsf RX_RING_SIZE) |
||
61 | display 'RX_RING_SIZE must be a power of two' |
||
62 | err |
||
63 | end if |
||
64 | |||
7809 | hidnplayr | 65 | ; Transmit Packet Descriptor |
66 | struct alx_tpd |
||
67 | length dw ? |
||
68 | vlan_tag dw ? |
||
69 | word1 dd ? |
||
70 | addr_l dd ? |
||
71 | addr_h dd ? |
||
72 | ends |
||
73 | |||
74 | ; Receive Return Descriptor |
||
75 | struct alx_rrd |
||
76 | word0 dd ? ; IP payload cksum + number of RFDs + start index of RFD-ring |
||
77 | rss_hash dd ? |
||
78 | word2 dd ? ; VLAN tag + Protocol ID + RSS Q num + RSS Hash algorithm |
||
79 | word3 dd ? ; Packet length + status |
||
80 | ends |
||
81 | |||
82 | ; Receive Free Descriptor |
||
83 | struct alx_rfd |
||
84 | addr_l dd ? |
||
85 | addr_h dd ? |
||
86 | ends |
||
87 | |||
88 | struct device ETH_DEVICE |
||
89 | |||
90 | io_addr dd ? |
||
91 | pci_bus dd ? |
||
92 | pci_dev dd ? |
||
7827 | hidnplayr | 93 | pci_vid dw ? ; Vendor ID |
94 | pci_did dw ? ; Device ID |
||
7809 | hidnplayr | 95 | irq_line dd ? |
96 | pci_rev dd ? |
||
97 | chip_rev dd ? |
||
98 | mmio_addr dd ? |
||
99 | |||
100 | max_dma_chnl dd ? |
||
101 | |||
102 | int_mask dd ? |
||
103 | rx_ctrl dd ? |
||
104 | |||
105 | rxq_read_idx dd ? |
||
106 | rxq_write_idx dd ? |
||
107 | ; rxq_rrd_read_idx dd ? |
||
108 | txq_read_idx dd ? |
||
109 | txq_write_idx dd ? |
||
110 | |||
111 | rb 0x100 - ($ and 0xff) ; align 256 |
||
112 | tpd_ring rb ((TX_RING_SIZE*sizeof.alx_tpd+16) and 0xfffffff0) |
||
113 | rrd_ring rb ((RX_RING_SIZE*sizeof.alx_rrd+16) and 0xfffffff0) |
||
114 | rfd_ring rb ((RX_RING_SIZE*sizeof.alx_rfd+16) and 0xfffffff0) |
||
115 | tpd_ring_virt rd TX_RING_SIZE |
||
116 | rfd_ring_virt rd RX_RING_SIZE |
||
117 | |||
118 | ends |
||
119 | |||
120 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
121 | ;; ;; |
||
122 | ;; proc START ;; |
||
123 | ;; ;; |
||
124 | ;; (standard driver proc) ;; |
||
125 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
126 | |||
127 | proc START c, reason:dword, cmdline:dword |
||
128 | |||
129 | cmp [reason], DRV_ENTRY |
||
130 | jne .fail |
||
131 | |||
132 | DEBUGF 2,"Loading driver\n" |
||
133 | invoke RegService, my_service, service_proc |
||
134 | ret |
||
135 | |||
136 | .fail: |
||
137 | xor eax, eax |
||
138 | ret |
||
139 | |||
140 | endp |
||
141 | |||
142 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
143 | ;; ;; |
||
144 | ;; proc SERVICE_PROC ;; |
||
145 | ;; ;; |
||
146 | ;; (standard driver proc) ;; |
||
147 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
148 | |||
149 | proc service_proc stdcall, ioctl:dword |
||
150 | |||
151 | mov edx, [ioctl] |
||
152 | mov eax, [edx + IOCTL.io_code] |
||
153 | |||
154 | ;------------------------------------------------------ |
||
155 | |||
156 | cmp eax, 0 ;SRV_GETVERSION |
||
157 | jne @F |
||
158 | |||
159 | cmp [edx + IOCTL.out_size], 4 |
||
160 | jb .fail |
||
161 | mov eax, [edx + IOCTL.output] |
||
162 | mov [eax], dword API_VERSION |
||
163 | |||
164 | xor eax, eax |
||
165 | ret |
||
166 | |||
167 | ;------------------------------------------------------ |
||
168 | @@: |
||
169 | cmp eax, 1 ;SRV_HOOK |
||
170 | jne .fail |
||
171 | |||
172 | cmp [edx + IOCTL.inp_size], 3 ; Data input must be at least 3 bytes |
||
173 | jb .fail |
||
174 | |||
175 | mov eax, [edx + IOCTL.input] |
||
176 | cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given |
||
177 | jne .fail ; other types arent supported for this card yet |
||
178 | |||
179 | ; check if the device is already listed |
||
180 | |||
181 | mov esi, device_list |
||
182 | mov ecx, [devices] |
||
183 | test ecx, ecx |
||
184 | jz .firstdevice |
||
185 | |||
186 | ; mov eax, [edx + IOCTL.input] ; get the pci bus and device numbers |
||
187 | mov ax , [eax+1] ; |
||
188 | .nextdevice: |
||
189 | mov ebx, [esi] |
||
190 | cmp al, byte[ebx + device.pci_bus] |
||
191 | jne @f |
||
192 | cmp ah, byte[ebx + device.pci_dev] |
||
193 | je .find_devicenum ; Device is already loaded, let's find it's device number |
||
194 | @@: |
||
195 | add esi, 4 |
||
196 | loop .nextdevice |
||
197 | |||
198 | ; This device doesnt have its own eth_device structure yet, lets create one |
||
199 | .firstdevice: |
||
200 | cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card |
||
201 | jae .fail |
||
202 | |||
203 | allocate_and_clear ebx, sizeof.device, .fail ; Allocate the buffer for device structure |
||
204 | |||
205 | ; Fill in the direct call addresses into the struct |
||
206 | |||
207 | mov [ebx + device.reset], reset |
||
208 | mov [ebx + device.transmit], transmit |
||
209 | mov [ebx + device.unload], unload |
||
210 | mov [ebx + device.name], my_service |
||
211 | |||
212 | ; save the pci bus and device numbers |
||
213 | |||
214 | mov eax, [edx + IOCTL.input] |
||
215 | movzx ecx, byte[eax+1] |
||
216 | mov [ebx + device.pci_bus], ecx |
||
217 | movzx ecx, byte[eax+2] |
||
218 | mov [ebx + device.pci_dev], ecx |
||
219 | |||
220 | ; Now, it's time to find the base mmio addres of the PCI device |
||
221 | |||
222 | stdcall PCI_find_mmio, [ebx + device.pci_bus], [ebx + device.pci_dev] ; returns in eax |
||
223 | test eax, eax |
||
224 | jz .destroy |
||
225 | |||
226 | ; Create virtual mapping of the physical memory |
||
227 | |||
228 | invoke MapIoMem, eax, 10000h, PG_SW+PG_NOCACHE |
||
229 | mov [ebx + device.mmio_addr], eax |
||
230 | |||
231 | ; We've found the mmio address, find IRQ now |
||
232 | invoke PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line |
||
233 | and eax, 0xff |
||
234 | mov [ebx + device.irq_line], eax |
||
235 | |||
236 | DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\ |
||
237 | [ebx + device.pci_dev]:1, [ebx + device.pci_bus]:1, [ebx + device.irq_line]:1, [ebx + device.mmio_addr]:8 |
||
238 | |||
239 | ; Ok, the eth_device structure is ready, let's probe the device |
||
240 | |||
241 | mov eax, [devices] ; Add the device structure to our device list |
||
242 | mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device) |
||
243 | inc [devices] ; |
||
244 | |||
245 | call probe ; this function will output in eax |