BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / kernel / drivers / network / bcm570x / b57um.c
blob1054dd42769c5b1af89b0f948e080d7d5853f79d
1 #include <PCI.h>
2 #include <Drivers.h>
3 #include <malloc.h>
4 #include <ether_driver.h>
6 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
7 # include <net/if_media.h>
8 #endif
10 #include "mm.h"
11 #include "lm.h"
12 #include "mempool.h"
14 struct pci_module_info *pci = NULL;
16 const char *dev_list[11];
17 struct be_b57_dev be_b57_dev_cards[10];
18 int cards_found = 0;
20 int b57_Packet_Desc_Size = sizeof(struct B_UM_PACKET);
22 #define ROUND_UP_TO_PAGE(size) ((size % 4096 != 0) ? 4096 - (size % 4096) + size : size)
24 struct pci_device_id {
25 unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */
26 unsigned int subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
27 unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */
28 unsigned long driver_data; /* Data private to the driver */
31 #define PCI_ANY_ID 0
33 typedef enum {
34 BCM5700A6 = 0,
35 BCM5700T6,
36 BCM5700A9,
37 BCM5700T9,
38 BCM5700,
39 BCM5701A5,
40 BCM5701T1,
41 BCM5701T8,
42 BCM5701A7,
43 BCM5701A10,
44 BCM5701A12,
45 BCM5701,
46 BCM5702,
47 BCM5703,
48 BCM5703A31,
49 BCM5703ARBUCKLE,
50 TC996T,
51 TC996ST,
52 TC996SSX,
53 TC996SX,
54 TC996BT,
55 TC997T,
56 TC997SX,
57 TC1000T,
58 TC1000BT,
59 TC940BR01,
60 TC942BR01,
61 TC998T,
62 TC998SX,
63 TC999T,
64 NC6770,
65 NC1020,
66 NC150T,
67 NC7760,
68 NC7761,
69 NC7770,
70 NC7771,
71 NC7780,
72 NC7781,
73 NC7772,
74 NC7782,
75 NC7783,
76 NC320T,
77 BCM5704CIOBE,
78 BCM5704,
79 BCM5704S,
80 BCM5705,
81 BCM5705M,
82 BCM5705F,
83 BCM5901,
84 BCM5782,
85 BCM5788,
86 BCM5789,
87 BCM5750,
88 BCM5750M,
89 BCM5720,
90 BCM5751,
91 BCM5751M,
92 BCM5751F,
93 BCM5721,
94 } board_t;
97 /* indexed by board_t, above */
98 static struct {
99 char *name;
100 } board_info[] = {
101 { "Broadcom BCM5700 1000Base-T" },
102 { "Broadcom BCM5700 1000Base-SX" },
103 { "Broadcom BCM5700 1000Base-SX" },
104 { "Broadcom BCM5700 1000Base-T" },
105 { "Broadcom BCM5700" },
106 { "Broadcom BCM5701 1000Base-T" },
107 { "Broadcom BCM5701 1000Base-T" },
108 { "Broadcom BCM5701 1000Base-T" },
109 { "Broadcom BCM5701 1000Base-SX" },
110 { "Broadcom BCM5701 1000Base-T" },
111 { "Broadcom BCM5701 1000Base-T" },
112 { "Broadcom BCM5701" },
113 { "Broadcom BCM5702 1000Base-T" },
114 { "Broadcom BCM5703 1000Base-T" },
115 { "Broadcom BCM5703 1000Base-SX" },
116 { "Broadcom B5703 1000Base-SX" },
117 { "3Com 3C996 10/100/1000 Server NIC" },
118 { "3Com 3C996 10/100/1000 Server NIC" },
119 { "3Com 3C996 Gigabit Fiber-SX Server NIC" },
120 { "3Com 3C996 Gigabit Fiber-SX Server NIC" },
121 { "3Com 3C996B Gigabit Server NIC" },
122 { "3Com 3C997 Gigabit Server NIC" },
123 { "3Com 3C997 Gigabit Fiber-SX Server NIC" },
124 { "3Com 3C1000 Gigabit NIC" },
125 { "3Com 3C1000B-T 10/100/1000 PCI" },
126 { "3Com 3C940 Gigabit LOM (21X21)" },
127 { "3Com 3C942 Gigabit LOM (31X31)" },
128 { "3Com 3C998-T Dual Port 10/100/1000 PCI-X Server NIC" },
129 { "3Com 3C998-SX Dual Port 1000-SX PCI-X Server NIC" },
130 { "3Com 3C999-T Quad Port 10/100/1000 PCI-X Server NIC" },
131 { "HP NC6770 Gigabit Server Adapter" },
132 { "NC1020 HP ProLiant Gigabit Server Adapter 32 PCI" },
133 { "HP ProLiant NC 150T PCI 4-port Gigabit Combo Switch Adapter" },
134 { "HP NC7760 Gigabit Server Adapter" },
135 { "HP NC7761 Gigabit Server Adapter" },
136 { "HP NC7770 Gigabit Server Adapter" },
137 { "HP NC7771 Gigabit Server Adapter" },
138 { "HP NC7780 Gigabit Server Adapter" },
139 { "HP NC7781 Gigabit Server Adapter" },
140 { "HP NC7772 Gigabit Server Adapter" },
141 { "HP NC7782 Gigabit Server Adapter" },
142 { "HP NC7783 Gigabit Server Adapter" },
143 { "HP ProLiant NC 320T PCI Express Gigabit Server Adapter" },
144 { "Broadcom BCM5704 CIOB-E 1000Base-T" },
145 { "Broadcom BCM5704 1000Base-T" },
146 { "Broadcom BCM5704 1000Base-SX" },
147 { "Broadcom BCM5705 1000Base-T" },
148 { "Broadcom BCM5705M 1000Base-T" },
149 { "Broadcom 570x 10/100 Integrated Controller" },
150 { "Broadcom BCM5901 100Base-TX" },
151 { "Broadcom NetXtreme Gigabit Ethernet for hp" },
152 { "Broadcom BCM5788 NetLink 1000Base-T" },
153 { "Broadcom BCM5789 NetLink 1000Base-T PCI Express" },
154 { "Broadcom BCM5750 1000Base-T PCI" },
155 { "Broadcom BCM5750M 1000Base-T PCI" },
156 { "Broadcom BCM5720 1000Base-T PCI" },
157 { "Broadcom BCM5751 1000Base-T PCI Express" },
158 { "Broadcom BCM5751M 1000Base-T PCI Express" },
159 { "Broadcom BCM5751F 100Base-TX PCI Express" },
160 { "Broadcom BCM5721 1000Base-T PCI Express" },
161 { 0 },
164 static struct pci_device_id bcm5700_pci_tbl[] = {
165 {0x14e4, 0x1644, 0x14e4, 0x1644, 0, 0, BCM5700A6 },
166 {0x14e4, 0x1644, 0x14e4, 0x2, 0, 0, BCM5700T6 },
167 {0x14e4, 0x1644, 0x14e4, 0x3, 0, 0, BCM5700A9 },
168 {0x14e4, 0x1644, 0x14e4, 0x4, 0, 0, BCM5700T9 },
169 {0x14e4, 0x1644, 0x1028, 0xd1, 0, 0, BCM5700 },
170 {0x14e4, 0x1644, 0x1028, 0x0106, 0, 0, BCM5700 },
171 {0x14e4, 0x1644, 0x1028, 0x0109, 0, 0, BCM5700 },
172 {0x14e4, 0x1644, 0x1028, 0x010a, 0, 0, BCM5700 },
173 {0x14e4, 0x1644, 0x10b7, 0x1000, 0, 0, TC996T },
174 {0x14e4, 0x1644, 0x10b7, 0x1001, 0, 0, TC996ST },
175 {0x14e4, 0x1644, 0x10b7, 0x1002, 0, 0, TC996SSX },
176 {0x14e4, 0x1644, 0x10b7, 0x1003, 0, 0, TC997T },
177 {0x14e4, 0x1644, 0x10b7, 0x1005, 0, 0, TC997SX },
178 {0x14e4, 0x1644, 0x10b7, 0x1008, 0, 0, TC942BR01 },
179 {0x14e4, 0x1644, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5700 },
180 {0x14e4, 0x1645, 0x14e4, 1, 0, 0, BCM5701A5 },
181 {0x14e4, 0x1645, 0x14e4, 5, 0, 0, BCM5701T1 },
182 {0x14e4, 0x1645, 0x14e4, 6, 0, 0, BCM5701T8 },
183 {0x14e4, 0x1645, 0x14e4, 7, 0, 0, BCM5701A7 },
184 {0x14e4, 0x1645, 0x14e4, 8, 0, 0, BCM5701A10 },
185 {0x14e4, 0x1645, 0x14e4, 0x8008, 0, 0, BCM5701A12 },
186 {0x14e4, 0x1645, 0x0e11, 0xc1, 0, 0, NC6770 },
187 {0x14e4, 0x1645, 0x0e11, 0x7c, 0, 0, NC7770 },
188 {0x14e4, 0x1645, 0x0e11, 0x85, 0, 0, NC7780 },
189 {0x14e4, 0x1645, 0x1028, 0x0121, 0, 0, BCM5701 },
190 {0x14e4, 0x1645, 0x10b7, 0x1004, 0, 0, TC996SX },
191 {0x14e4, 0x1645, 0x10b7, 0x1006, 0, 0, TC996BT },
192 {0x14e4, 0x1645, 0x10b7, 0x1007, 0, 0, TC1000T },
193 {0x14e4, 0x1645, 0x10b7, 0x1008, 0, 0, TC940BR01 },
194 {0x14e4, 0x1645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5701 },
195 {0x14e4, 0x1646, 0x14e4, 0x8009, 0, 0, BCM5702 },
196 {0x14e4, 0x1646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 },
197 {0x14e4, 0x16a6, 0x14e4, 0x8009, 0, 0, BCM5702 },
198 {0x14e4, 0x16a6, 0x14e4, 0x000c, 0, 0, BCM5702 },
199 {0x14e4, 0x16a6, 0x0e11, 0xbb, 0, 0, NC7760 },
200 {0x14e4, 0x16a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 },
201 {0x14e4, 0x16c6, 0x10b7, 0x1100, 0, 0, TC1000BT },
202 {0x14e4, 0x16c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 },
203 {0x14e4, 0x1647, 0x14e4, 0x0009, 0, 0, BCM5703 },
204 {0x14e4, 0x1647, 0x14e4, 0x000a, 0, 0, BCM5703A31 },
205 {0x14e4, 0x1647, 0x14e4, 0x000b, 0, 0, BCM5703 },
206 {0x14e4, 0x1647, 0x14e4, 0x800a, 0, 0, BCM5703 },
207 {0x14e4, 0x1647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 },
208 {0x14e4, 0x16a7, 0x14e4, 0x0009, 0, 0, BCM5703 },
209 {0x14e4, 0x16a7, 0x14e4, 0x000a, 0, 0, BCM5703A31 },
210 {0x14e4, 0x16a7, 0x14e4, 0x000b, 0, 0, BCM5703 },
211 {0x14e4, 0x16a7, 0x14e4, 0x800a, 0, 0, BCM5703 },
212 {0x14e4, 0x16a7, 0x0e11, 0xca, 0, 0, NC7771 },
213 {0x14e4, 0x16a7, 0x0e11, 0xcb, 0, 0, NC7781 },
214 {0x14e4, 0x16a7, 0x1014, 0x0281, 0, 0, BCM5703ARBUCKLE },
215 {0x14e4, 0x16a7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 },
216 {0x14e4, 0x16c7, 0x14e4, 0x000a, 0, 0, BCM5703A31 },
217 {0x14e4, 0x16c7, 0x0e11, 0xca, 0, 0, NC7771 },
218 {0x14e4, 0x16c7, 0x0e11, 0xcb, 0, 0, NC7781 },
219 {0x14e4, 0x16c7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 },
220 {0x14e4, 0x1648, 0x0e11, 0xcf, 0, 0, NC7772 },
221 {0x14e4, 0x1648, 0x0e11, 0xd0, 0, 0, NC7782 },
222 {0x14e4, 0x1648, 0x0e11, 0xd1, 0, 0, NC7783 },
223 {0x14e4, 0x1648, 0x10b7, 0x2000, 0, 0, TC998T },
224 {0x14e4, 0x1648, 0x10b7, 0x3000, 0, 0, TC999T },
225 {0x14e4, 0x1648, 0x1166, 0x1648, 0, 0, BCM5704CIOBE },
226 {0x14e4, 0x1648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5704 },
227 {0x14e4, 0x1649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5704S },
228 {0x14e4, 0x16a8, 0x14e4, 0x16a8, 0, 0, BCM5704S },
229 {0x14e4, 0x16a8, 0x10b7, 0x2001, 0, 0, TC998SX },
230 {0x14e4, 0x16a8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5704S },
231 {0x14e4, 0x1653, 0x0e11, 0x00e3, 0, 0, NC7761 },
232 {0x14e4, 0x1653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705 },
233 {0x14e4, 0x1654, 0x0e11, 0x00e3, 0, 0, NC7761 },
234 {0x14e4, 0x1654, 0x103c, 0x3100, 0, 0, NC1020 },
235 {0x14e4, 0x1654, 0x103c, 0x3226, 0, 0, NC150T },
236 {0x14e4, 0x1654, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705 },
237 {0x14e4, 0x165d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705M },
238 {0x14e4, 0x165e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705M },
239 {0x14e4, 0x166e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705F },
240 {0x14e4, 0x1696, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5782 },
241 {0x14e4, 0x169c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5788 },
242 {0x14e4, 0x169d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5789 },
243 {0x14e4, 0x170d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5901 },
244 {0x14e4, 0x170e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5901 },
245 {0x14e4, 0x1676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5750 },
246 {0x14e4, 0x167c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5750M },
247 {0x14e4, 0x1677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5751 },
248 {0x14e4, 0x167d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5751M },
249 {0x14e4, 0x167e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5751F },
250 {0x14e4, 0x1658, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5720 },
251 {0x14e4, 0x1659, 0x103c, 0x7031, 0, 0, NC320T },
252 {0x14e4, 0x1659, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5721 },
253 {0,}
256 /* -------- BeOS Driver Hooks ------------ */
258 static status_t b57_open(const char *name, uint32 flags, void **cookie);
259 static status_t b57_close(void *cookie);
260 static status_t b57_free(void *cookie);
261 static status_t b57_ioctl(void *cookie,uint32 op,void *data,size_t len);
262 static status_t b57_read(void *cookie,off_t pos,void *data,size_t *numBytes);
263 static status_t b57_write(void *cookie,off_t pos,const void *data,size_t *numBytes);
264 static int32 b57_interrupt(void *cookie);
265 static int32 tx_cleanup_thread(void *us);
267 device_hooks b57_hooks = {b57_open,b57_close,b57_free,b57_ioctl,b57_read,b57_write,NULL,NULL,NULL,NULL};
268 int32 api_version = B_CUR_DRIVER_API_VERSION;
270 //int debug_fd;
273 status_t
274 init_hardware(void)
276 return B_OK;
280 const char **
281 publish_devices(void)
283 return dev_list;
287 device_hooks *
288 find_device(const char *name)
290 return &b57_hooks;
294 status_t
295 init_driver(void)
297 int i = 0, j = 0, is_detected;
298 pci_info dev_info;
300 //debug_fd = open("/tmp/broadcom_traffic_log",O_RDWR | B_CREATE_FILE);
302 if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci) != B_OK)
303 return B_ERROR;
305 while (pci->get_nth_pci_info(i++, &dev_info) == 0) {
306 is_detected = 0;
307 if ((dev_info.class_base == PCI_network) && (dev_info.class_sub == PCI_ethernet)) {
308 for (j = 0; bcm5700_pci_tbl[j].vendor != 0; j++) {
309 if ((dev_info.vendor_id == bcm5700_pci_tbl[j].vendor) && (dev_info.device_id == bcm5700_pci_tbl[j].device)) {
310 is_detected = 1;
311 break;
316 if (!is_detected)
317 continue;
319 if (cards_found >= 10)
320 break;
322 dev_list[cards_found] = (char *)malloc(16 /* net/bcm570x/xx */);
323 sprintf(dev_list[cards_found],"net/bcm570x/%d",cards_found);
324 be_b57_dev_cards[cards_found].pci_data = dev_info;
325 be_b57_dev_cards[cards_found].packet_release_sem = create_sem(0,dev_list[cards_found]);
326 be_b57_dev_cards[cards_found].mem_list_num = 0;
327 be_b57_dev_cards[cards_found].lockmem_list_num = 0;
328 be_b57_dev_cards[cards_found].opened = 0;
329 be_b57_dev_cards[cards_found].block = 1;
330 be_b57_dev_cards[cards_found].lock = 0;
331 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
332 be_b57_dev_cards[cards_found].linkChangeSem = -1;
333 #endif
335 if (LM_GetAdapterInfo(&be_b57_dev_cards[cards_found].lm_dev) != LM_STATUS_SUCCESS) {
336 for (j = 0; j < cards_found; j++) {
337 free(dev_list[j]);
338 delete_sem(be_b57_dev_cards[j].packet_release_sem);
340 put_module(B_PCI_MODULE_NAME);
341 return ENODEV;
344 QQ_InitQueue(&be_b57_dev_cards[cards_found].RxPacketReadQ.Container,MAX_RX_PACKET_DESC_COUNT);
346 cards_found++;
349 mempool_init((MAX_RX_PACKET_DESC_COUNT+MAX_TX_PACKET_DESC_COUNT) * cards_found);
350 dev_list[cards_found] = NULL;
352 return B_OK;
356 void
357 uninit_driver(void)
359 struct be_b57_dev *pUmDevice;
360 int i, j;
362 for (j = 0; j < cards_found; j++) {
363 pUmDevice = &be_b57_dev_cards[j];
365 for (i = 0; i < pUmDevice->mem_list_num; i++)
366 free(pUmDevice->mem_list[i]);
367 for (i = 0; i < pUmDevice->lockmem_list_num; i++)
368 delete_area(pUmDevice->lockmem_list[i]);
370 delete_area(pUmDevice->mem_base);
371 delete_sem(be_b57_dev_cards[j].packet_release_sem);
372 free((void *)dev_list[j]);
375 mempool_exit();
376 put_module(B_PCI_MODULE_NAME);
380 // #pragma mark -
383 static status_t
384 b57_open(const char *name, uint32 flags, void **cookie)
386 struct be_b57_dev *pDevice = NULL;
387 int i;
389 *cookie = NULL;
390 for (i = 0; i < cards_found; i++) {
391 if (strcmp(dev_list[i],name) == 0) {
392 *cookie = pDevice = &be_b57_dev_cards[i];
393 break;
397 if (*cookie == NULL)
398 return B_FILE_NOT_FOUND;
400 if (atomic_or(&pDevice->opened, 1)) {
401 *cookie = pDevice = NULL;
402 return B_BUSY;
405 install_io_interrupt_handler(pDevice->pci_data.u.h0.interrupt_line,
406 b57_interrupt, *cookie, 0);
407 if (LM_InitializeAdapter(&pDevice->lm_dev) != LM_STATUS_SUCCESS) {
408 atomic_and(&pDevice->opened,0);
409 remove_io_interrupt_handler(pDevice->pci_data.u.h0.interrupt_line, b57_interrupt, *cookie);
410 *cookie = NULL;
411 return B_ERROR;
414 /*QQ_InitQueue(&pDevice->rx_out_of_buf_q.Container,
415 MAX_RX_PACKET_DESC_COUNT);*/
417 //pDevice->lm_dev.PhyCrcCount = 0;
418 LM_EnableInterrupt(&pDevice->lm_dev);
420 dprintf("Broadcom 57xx adapter successfully inited at %s:\n", name);
421 dprintf("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
422 pDevice->lm_dev.NodeAddress[0], pDevice->lm_dev.NodeAddress[1],
423 pDevice->lm_dev.NodeAddress[2], pDevice->lm_dev.NodeAddress[3],
424 pDevice->lm_dev.NodeAddress[4], pDevice->lm_dev.NodeAddress[5]);
425 dprintf("PCI Data: 0x%08x\n", pDevice->pci_data.u.h0.base_registers[0]);
426 dprintf("IRQ: %d\n", pDevice->pci_data.u.h0.interrupt_line);
428 return B_OK;
432 static status_t
433 b57_close(void *cookie)
435 struct be_b57_dev *pUmDevice = (struct be_b57_dev *)(cookie);
437 if (cookie == NULL)
438 return B_OK;
440 LM_DisableInterrupt(&pUmDevice->lm_dev);
441 LM_Halt(&pUmDevice->lm_dev);
442 pUmDevice->lm_dev.InitDone = 0;
443 atomic_and(&pUmDevice->opened, 0);
445 return B_OK;
449 static status_t
450 b57_free(void *cookie)
452 struct be_b57_dev *pUmDevice = (struct be_b57_dev *)(cookie);
454 if (cookie == NULL)
455 return B_OK;
457 remove_io_interrupt_handler(pUmDevice->pci_data.u.h1.interrupt_line, b57_interrupt, cookie);
458 return B_OK;
462 static status_t
463 b57_ioctl(void *cookie,uint32 op,void *data,size_t len)
465 struct be_b57_dev *pUmDevice = (struct be_b57_dev *)(cookie);
467 switch (op) {
468 case ETHER_INIT:
469 return B_OK;
470 case ETHER_GETADDR:
471 if (data == NULL)
472 return B_ERROR;
474 memcpy(data, pUmDevice->lm_dev.NodeAddress, 6);
475 return B_OK;
476 case ETHER_NONBLOCK:
477 pUmDevice->block = !*((uint8 *)(data));
478 return B_OK;
479 case ETHER_ADDMULTI:
480 return (LM_MulticastAdd(&pUmDevice->lm_dev,
481 (PLM_UINT8)(data)) == LM_STATUS_SUCCESS) ? B_OK : B_ERROR;
482 case ETHER_REMMULTI:
483 return (LM_MulticastDel(&pUmDevice->lm_dev,
484 (PLM_UINT8)(data)) == LM_STATUS_SUCCESS) ? B_OK : B_ERROR;
485 case ETHER_SETPROMISC:
486 if (*((uint8 *)(data))) {
487 LM_SetReceiveMask(&pUmDevice->lm_dev,
488 pUmDevice->lm_dev.ReceiveMask | LM_PROMISCUOUS_MODE);
489 } else {
490 LM_SetReceiveMask(&pUmDevice->lm_dev,
491 pUmDevice->lm_dev.ReceiveMask & ~LM_PROMISCUOUS_MODE);
493 return B_OK;
494 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
495 case ETHER_GETLINKSTATE:
497 ether_link_state_t *state_buffer = (ether_link_state_t *)(data);
498 state_buffer->link_speed = pUmDevice->lm_dev.LineSpeed;
499 state_buffer->link_quality = (pUmDevice->lm_dev.LinkStatus == LM_STATUS_LINK_DOWN) ? 0.0 : 1.0;
500 state_buffer->duplex_mode = (pUmDevice->lm_dev.DuplexMode == LM_DUPLEX_MODE_FULL);
501 return B_OK;
503 #else
504 case ETHER_GET_LINK_STATE:
506 ether_link_state_t state;
507 state.media = (pUmDevice->lm_dev.LinkStatus
508 == LM_STATUS_LINK_DOWN ? 0 : IFM_ACTIVE) | IFM_ETHER;
509 switch (pUmDevice->lm_dev.LineSpeed) {
510 case LM_LINE_SPEED_10MBPS:
511 state.media |= IFM_10_T;
512 state.speed = 10000000;
513 break;
514 case LM_LINE_SPEED_100MBPS:
515 state.media |= IFM_100_TX;
516 state.speed = 100000000;
517 break;
518 case LM_LINE_SPEED_1000MBPS:
519 state.media |= IFM_1000_T;
520 state.speed = 1000000000;
521 break;
522 default:
523 state.speed = 0;
525 state.media |= (pUmDevice->lm_dev.DuplexMode
526 == LM_DUPLEX_MODE_FULL ? IFM_FULL_DUPLEX : IFM_HALF_DUPLEX);
527 state.quality = 1000;
529 return user_memcpy(data, &state, sizeof(ether_link_state_t));
531 case ETHER_SET_LINK_STATE_SEM:
533 if (user_memcpy(&pUmDevice->linkChangeSem, data, sizeof(sem_id)) < B_OK) {
534 pUmDevice->linkChangeSem = -1;
535 return B_BAD_ADDRESS;
537 return B_OK;
540 #endif
542 return B_ERROR;
546 static int32
547 b57_interrupt(void *cookie)
549 struct be_b57_dev *pUmDevice = (struct be_b57_dev *)cookie;
550 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
551 unsigned int handled = 1;
552 int i, max_intr_loop;
553 LM_UINT32 oldtag, newtag;
555 if (!pDevice->InitDone)
556 return B_UNHANDLED_INTERRUPT;
558 if (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) {
559 max_intr_loop = 50;
560 if (pDevice->Flags & USE_TAGGED_STATUS_FLAG) {
561 MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1);
562 oldtag = pDevice->pStatusBlkVirt->StatusTag;
564 for (i = 0; ; i++) {
565 pDevice->pStatusBlkVirt->Status &=
566 ~STATUS_BLOCK_UPDATED;
568 LM_ServiceInterrupts(pDevice);
569 newtag = pDevice->pStatusBlkVirt->StatusTag;
570 if ((newtag == oldtag) || (i > max_intr_loop)) {
571 MB_REG_WR(pDevice,
572 Mailbox.Interrupt[0].Low,
573 oldtag << 24);
574 pDevice->LastTag = oldtag;
575 if (pDevice->Flags & UNDI_FIX_FLAG) {
576 REG_WR(pDevice, Grc.LocalCtrl,
577 pDevice->GrcLocalCtrl | 0x2);
579 break;
581 oldtag = newtag;
583 } else {
584 i = 0;
585 do {
586 uint dummy;
588 MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1);
589 pDevice->pStatusBlkVirt->Status &=
590 ~STATUS_BLOCK_UPDATED;
591 LM_ServiceInterrupts(pDevice);
592 MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 0);
593 dummy = MB_REG_RD(pDevice,
594 Mailbox.Interrupt[0].Low);
595 i++;
598 while ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) != 0
599 && i < max_intr_loop)
602 if (pDevice->Flags & UNDI_FIX_FLAG) {
603 REG_WR(pDevice, Grc.LocalCtrl,
604 pDevice->GrcLocalCtrl | 0x2);
607 } else
608 handled = 0;
610 if (QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container)
611 || pDevice->QueueAgain) {
612 LM_QueueRxPackets(pDevice);
615 return handled ? B_INVOKE_SCHEDULER : B_UNHANDLED_INTERRUPT;
619 static status_t
620 b57_read(void *cookie,off_t pos,void *data,size_t *numBytes)
622 struct be_b57_dev *pUmDevice = (struct be_b57_dev *)cookie;
623 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
624 PLM_PACKET pPacket;
625 struct B_UM_PACKET *pUmPacket;
626 cpu_status cpu;
628 if (pUmDevice->block)
629 acquire_sem(pUmDevice->packet_release_sem);
630 else {
631 /* Decrement the receive sem anyway, but don't block
632 this is a horrible hack, but it works. */
633 acquire_sem_etc(pUmDevice->packet_release_sem, 1, B_RELATIVE_TIMEOUT, 0);
636 cpu = disable_interrupts();
637 acquire_spinlock(&pUmDevice->lock);
639 pPacket = (PLM_PACKET)
640 QQ_PopHead(&pUmDevice->RxPacketReadQ.Container);
642 release_spinlock(&pUmDevice->lock);
643 restore_interrupts(cpu);
645 if (pPacket == 0) {
646 *numBytes = -1;
647 return B_ERROR;
650 pUmPacket = (struct B_UM_PACKET *) pPacket;
651 if (pPacket->PacketStatus != LM_STATUS_SUCCESS
652 || pPacket->PacketSize > 1518) {
653 cpu = disable_interrupts();
654 acquire_spinlock(&pUmDevice->lock);
656 QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
658 release_spinlock(&pUmDevice->lock);
659 restore_interrupts(cpu);
660 *numBytes = -1;
661 return B_ERROR;
664 if ((pPacket->PacketSize) < *numBytes)
665 *numBytes = pPacket->PacketSize;
667 memcpy(data,pUmPacket->data,*numBytes);
668 cpu = disable_interrupts();
669 acquire_spinlock(&pUmDevice->lock);
671 QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
673 release_spinlock(&pUmDevice->lock);
674 restore_interrupts(cpu);
676 return B_OK;
680 static status_t
681 b57_write(void *cookie,off_t pos,const void *data,size_t *numBytes)
683 struct be_b57_dev *pUmDevice = (struct be_b57_dev *)cookie;
684 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
685 PLM_PACKET pPacket;
686 struct B_UM_PACKET *pUmPacket;
687 cpu_status cpu;
689 /*if ((pDevice->LinkStatus == LM_STATUS_LINK_DOWN) || !pDevice->InitDone)
691 return ENETDOWN;
694 pPacket = (PLM_PACKET)
695 QQ_PopHead(&pDevice->TxPacketFreeQ.Container);
697 if (pPacket == 0)
698 return B_ERROR;
700 pUmPacket = (struct B_UM_PACKET *)pPacket;
701 pUmPacket->data = chunk_pool_get();
703 memcpy(pUmPacket->data,data,*numBytes); /* no guarantee data is contiguous, so we have to copy */
704 pPacket->PacketSize = pUmPacket->size = *numBytes;
706 pPacket->u.Tx.FragCount = 1;
707 pPacket->Flags = 0;
709 tx_cleanup_thread(pUmDevice);
711 cpu = disable_interrupts();
712 acquire_spinlock(&pUmDevice->lock);
714 LM_SendPacket(pDevice, pPacket);
716 release_spinlock(&pUmDevice->lock);
717 restore_interrupts(cpu);
719 return B_OK;
723 // #pragma mark -
724 /* -------- Broadcom MM hooks ----------- */
727 LM_STATUS
728 MM_ReadConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
729 LM_UINT16 *pValue16)
731 *pValue16 = (LM_UINT16)pci->read_pci_config(((struct be_b57_dev *)(pDevice))->pci_data.bus,
732 ((struct be_b57_dev *)(pDevice))->pci_data.device,
733 ((struct be_b57_dev *)(pDevice))->pci_data.function,
734 (uchar)Offset, sizeof(LM_UINT16));
735 return LM_STATUS_SUCCESS;
739 LM_STATUS
740 MM_WriteConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
741 LM_UINT16 Value16)
743 pci->write_pci_config(((struct be_b57_dev *)(pDevice))->pci_data.bus,
744 ((struct be_b57_dev *)(pDevice))->pci_data.device,
745 ((struct be_b57_dev *)(pDevice))->pci_data.function,
746 (uchar)Offset, sizeof(LM_UINT16), (uint32)Value16);
747 return LM_STATUS_SUCCESS;
751 LM_STATUS
752 MM_ReadConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
753 LM_UINT32 *pValue32)
755 *pValue32 = (LM_UINT32)pci->read_pci_config(((struct be_b57_dev *)(pDevice))->pci_data.bus,
756 ((struct be_b57_dev *)(pDevice))->pci_data.device,
757 ((struct be_b57_dev *)(pDevice))->pci_data.function,
758 (uchar)Offset, sizeof(LM_UINT32));
759 return LM_STATUS_SUCCESS;
763 LM_STATUS
764 MM_WriteConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
765 LM_UINT32 Value32)
767 pci->write_pci_config(((struct be_b57_dev *)(pDevice))->pci_data.bus,
768 ((struct be_b57_dev *)(pDevice))->pci_data.device,
769 ((struct be_b57_dev *)(pDevice))->pci_data.function,
770 (uchar)Offset, sizeof(LM_UINT32), (uint32)Value32);
771 return LM_STATUS_SUCCESS;
775 LM_STATUS
776 MM_MapMemBase(PLM_DEVICE_BLOCK pDevice)
778 struct be_b57_dev *pUmDevice = (struct be_b57_dev *)(pDevice);
779 size_t size = pUmDevice->pci_data.u.h0.base_register_sizes[0];
781 size = ROUND_UP_TO_PAGE(size);
782 pUmDevice->mem_base = map_physical_memory("broadcom_regs",
783 pUmDevice->pci_data.u.h0.base_registers[0], size,
784 B_ANY_KERNEL_BLOCK_ADDRESS, 0,
785 (void **)(&pDevice->pMappedMemBase));
787 return LM_STATUS_SUCCESS;
791 LM_STATUS
792 MM_MapIoBase(PLM_DEVICE_BLOCK pDevice)
794 pDevice->pMappedMemBase = pci->ram_address(((struct be_b57_dev *)(pDevice))->pci_data.memory_base);
795 return LM_STATUS_SUCCESS;
799 LM_STATUS
800 MM_IndicateRxPackets(PLM_DEVICE_BLOCK pDevice)
802 struct be_b57_dev *dev = (struct be_b57_dev *)pDevice;
803 PLM_PACKET pPacket;
805 while (1) {
806 pPacket = (PLM_PACKET)
807 QQ_PopHead(&pDevice->RxPacketReceivedQ.Container);
808 if (pPacket == 0)
809 break;
811 acquire_spinlock(&dev->lock);
812 release_sem_etc(dev->packet_release_sem, 1, B_DO_NOT_RESCHEDULE);
813 release_spinlock(&dev->lock);
814 QQ_PushTail(&dev->RxPacketReadQ.Container, pPacket);
817 return LM_STATUS_SUCCESS;
821 LM_STATUS
822 MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice)
824 return LM_STATUS_SUCCESS;
828 int32
829 tx_cleanup_thread(void *us)
831 PLM_PACKET pPacket;
832 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK)(us);
833 struct be_b57_dev *pUmDevice = (struct be_b57_dev *)(us);
834 struct B_UM_PACKET *pUmPacket;
835 cpu_status cpu;
837 while (1) {
838 cpu = disable_interrupts();
839 acquire_spinlock(&pUmDevice->lock);
841 pPacket = (PLM_PACKET)
842 QQ_PopHead(&pDevice->TxPacketXmittedQ.Container);
844 release_spinlock(&pUmDevice->lock);
845 restore_interrupts(cpu);
846 if (pPacket == 0)
847 break;
848 pUmPacket = (struct B_UM_PACKET *)(pPacket);
849 chunk_pool_put(pUmPacket->data);
850 pUmPacket->data = NULL;
852 cpu = disable_interrupts();
853 acquire_spinlock(&pUmDevice->lock);
854 QQ_PushTail(&pDevice->TxPacketFreeQ.Container, pPacket);
855 release_spinlock(&pUmDevice->lock);
856 restore_interrupts(cpu);
858 return LM_STATUS_SUCCESS;
861 /*LM_STATUS MM_StartTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
862 LM_STATUS MM_CompleteTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);*/
864 LM_STATUS
865 MM_AllocateMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
866 PLM_VOID *pMemoryBlockVirt)
868 struct be_b57_dev *dev = (struct be_b57_dev *)(pDevice);
870 if (dev->mem_list_num == 16)
871 return LM_STATUS_FAILURE;
873 *pMemoryBlockVirt = dev->mem_list[(dev->mem_list_num)++] = (void *)malloc(BlockSize);
874 return LM_STATUS_SUCCESS;
878 LM_STATUS
879 MM_AllocateSharedMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
880 PLM_VOID *pMemoryBlockVirt, PLM_PHYSICAL_ADDRESS pMemoryBlockPhy,
881 LM_BOOL cached /* we ignore this */)
883 struct be_b57_dev *dev;
884 void *pvirt = NULL;
885 area_id area_desc;
886 physical_entry entry;
888 dev = (struct be_b57_dev *)(pDevice);
889 area_desc = dev->lockmem_list[dev->lockmem_list_num++] = create_area("broadcom_shared_mem",
890 &pvirt, B_ANY_KERNEL_ADDRESS, ROUND_UP_TO_PAGE(BlockSize),
891 B_CONTIGUOUS, 0);
893 if (area_desc < B_OK)
894 return LM_STATUS_FAILURE;
896 memset(pvirt, 0, BlockSize);
897 *pMemoryBlockVirt = (PLM_VOID) pvirt;
899 get_memory_map(pvirt,BlockSize,&entry,1);
900 pMemoryBlockPhy->Low = (uint32)entry.address;
901 pMemoryBlockPhy->High = (uint32)(entry.address >> 32);
902 /* We only support 32 bit */
904 return LM_STATUS_SUCCESS;
908 LM_STATUS
909 MM_GetConfig(PLM_DEVICE_BLOCK pDevice)
911 pDevice->DisableAutoNeg = FALSE;
912 pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
913 pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_FULL;
914 pDevice->FlowControlCap = LM_FLOW_CONTROL_AUTO_PAUSE;
915 pDevice->RxPacketDescCnt = DEFAULT_RX_PACKET_DESC_COUNT;
916 pDevice->TxPacketDescCnt = DEFAULT_TX_PACKET_DESC_COUNT;
917 pDevice->TxMaxCoalescedFrames = DEFAULT_TX_MAX_COALESCED_FRAMES;
918 pDevice->RxMaxCoalescedFrames = DEFAULT_RX_MAX_COALESCED_FRAMES;
919 pDevice->RxStdDescCnt = DEFAULT_STD_RCV_DESC_COUNT;
920 pDevice->RxCoalescingTicks = DEFAULT_RX_COALESCING_TICKS;
921 pDevice->TxCoalescingTicks = DEFAULT_TX_COALESCING_TICKS;
922 pDevice->StatsCoalescingTicks = DEFAULT_STATS_COALESCING_TICKS;
923 pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
925 return LM_STATUS_SUCCESS;
929 LM_STATUS
930 MM_IndicateStatus(PLM_DEVICE_BLOCK pDevice, LM_STATUS Status)
932 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
933 struct be_b57_dev *pUmDevice = (struct be_b57_dev *)pDevice;
935 if (pUmDevice->linkChangeSem != -1)
936 release_sem_etc(pUmDevice->linkChangeSem, 1,
937 B_DO_NOT_RESCHEDULE);
938 #endif
940 return LM_STATUS_SUCCESS;
944 LM_STATUS
945 MM_InitializeUmPackets(PLM_DEVICE_BLOCK pDevice)
947 int i;
948 struct be_b57_dev *pUmDevice = (struct be_b57_dev *) pDevice;
949 struct B_UM_PACKET *pUmPacket;
950 PLM_PACKET pPacket;
952 for (i = 0; i < pDevice->RxPacketDescCnt; i++) {
953 pPacket = QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
954 pUmPacket = (struct B_UM_PACKET *) pPacket;
955 pUmPacket->data = chunk_pool_get();
956 if (pUmPacket->data == 0) {
957 //QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket);
958 // No pretty rx_out_of_buf_q, but we sure as hell don't want anything to do with these packets, so we leak them.
959 // Probably not the best idea, but it works.
960 continue;
962 QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
965 return LM_STATUS_SUCCESS;
968 LM_STATUS MM_FreeRxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) {
969 struct B_UM_PACKET *pUmPacket;
970 struct be_b57_dev *pUmDevice = (struct be_b57_dev *) pDevice;
971 pUmPacket = (struct B_UM_PACKET *) pPacket;
972 chunk_pool_put(pUmPacket->data);
973 pUmPacket->data = NULL;
974 return LM_STATUS_SUCCESS;
978 void
979 MM_UnmapRxDma(LM_DEVICE_BLOCK *pDevice, LM_PACKET *pPacket)
984 LM_STATUS
985 MM_CoalesceTxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
987 /* Our buffers are pre-coalesced (which slows things down a little) */
988 return LM_STATUS_SUCCESS;
992 LM_DEVICE_BLOCK *
993 MM_FindPeerDev(LM_DEVICE_BLOCK *pDevice)
995 /* I have no idea what this routine does. I think it's optional... */
996 return 0;
1000 LM_STATUS
1001 MM_Sleep(LM_DEVICE_BLOCK *pDevice, LM_UINT32 msec)
1003 snooze(msec*1e3);
1004 return LM_STATUS_SUCCESS;