4 #include <ether_driver.h>
6 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
7 # include <net/if_media.h>
14 struct pci_module_info
*pci
= NULL
;
16 const char *dev_list
[11];
17 struct be_b57_dev be_b57_dev_cards
[10];
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 */
97 /* indexed by board_t, above */
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" },
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
},
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
;
281 publish_devices(void)
288 find_device(const char *name
)
297 int i
= 0, j
= 0, is_detected
;
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
)
305 while (pci
->get_nth_pci_info(i
++, &dev_info
) == 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
)) {
319 if (cards_found
>= 10)
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;
335 if (LM_GetAdapterInfo(&be_b57_dev_cards
[cards_found
].lm_dev
) != LM_STATUS_SUCCESS
) {
336 for (j
= 0; j
< cards_found
; j
++) {
338 delete_sem(be_b57_dev_cards
[j
].packet_release_sem
);
340 put_module(B_PCI_MODULE_NAME
);
344 QQ_InitQueue(&be_b57_dev_cards
[cards_found
].RxPacketReadQ
.Container
,MAX_RX_PACKET_DESC_COUNT
);
349 mempool_init((MAX_RX_PACKET_DESC_COUNT
+MAX_TX_PACKET_DESC_COUNT
) * cards_found
);
350 dev_list
[cards_found
] = NULL
;
359 struct be_b57_dev
*pUmDevice
;
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
]);
376 put_module(B_PCI_MODULE_NAME
);
384 b57_open(const char *name
, uint32 flags
, void **cookie
)
386 struct be_b57_dev
*pDevice
= 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
];
398 return B_FILE_NOT_FOUND
;
400 if (atomic_or(&pDevice
->opened
, 1)) {
401 *cookie
= pDevice
= NULL
;
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
);
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
);
433 b57_close(void *cookie
)
435 struct be_b57_dev
*pUmDevice
= (struct be_b57_dev
*)(cookie
);
440 LM_DisableInterrupt(&pUmDevice
->lm_dev
);
441 LM_Halt(&pUmDevice
->lm_dev
);
442 pUmDevice
->lm_dev
.InitDone
= 0;
443 atomic_and(&pUmDevice
->opened
, 0);
450 b57_free(void *cookie
)
452 struct be_b57_dev
*pUmDevice
= (struct be_b57_dev
*)(cookie
);
457 remove_io_interrupt_handler(pUmDevice
->pci_data
.u
.h1
.interrupt_line
, b57_interrupt
, cookie
);
463 b57_ioctl(void *cookie
,uint32 op
,void *data
,size_t len
)
465 struct be_b57_dev
*pUmDevice
= (struct be_b57_dev
*)(cookie
);
474 memcpy(data
, pUmDevice
->lm_dev
.NodeAddress
, 6);
477 pUmDevice
->block
= !*((uint8
*)(data
));
480 return (LM_MulticastAdd(&pUmDevice
->lm_dev
,
481 (PLM_UINT8
)(data
)) == LM_STATUS_SUCCESS
) ? B_OK
: B_ERROR
;
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
);
490 LM_SetReceiveMask(&pUmDevice
->lm_dev
,
491 pUmDevice
->lm_dev
.ReceiveMask
& ~LM_PROMISCUOUS_MODE
);
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
);
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;
514 case LM_LINE_SPEED_100MBPS
:
515 state
.media
|= IFM_100_TX
;
516 state
.speed
= 100000000;
518 case LM_LINE_SPEED_1000MBPS
:
519 state
.media
|= IFM_1000_T
;
520 state
.speed
= 1000000000;
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
;
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
) {
560 if (pDevice
->Flags
& USE_TAGGED_STATUS_FLAG
) {
561 MB_REG_WR(pDevice
, Mailbox
.Interrupt
[0].Low
, 1);
562 oldtag
= pDevice
->pStatusBlkVirt
->StatusTag
;
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
)) {
572 Mailbox
.Interrupt
[0].Low
,
574 pDevice
->LastTag
= oldtag
;
575 if (pDevice
->Flags
& UNDI_FIX_FLAG
) {
576 REG_WR(pDevice
, Grc
.LocalCtrl
,
577 pDevice
->GrcLocalCtrl
| 0x2);
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
);
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);
610 if (QQ_GetEntryCnt(&pDevice
->RxPacketFreeQ
.Container
)
611 || pDevice
->QueueAgain
) {
612 LM_QueueRxPackets(pDevice
);
615 return handled
? B_INVOKE_SCHEDULER
: B_UNHANDLED_INTERRUPT
;
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
;
625 struct B_UM_PACKET
*pUmPacket
;
628 if (pUmDevice
->block
)
629 acquire_sem(pUmDevice
->packet_release_sem
);
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
);
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
);
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
);
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
;
686 struct B_UM_PACKET
*pUmPacket
;
689 /*if ((pDevice->LinkStatus == LM_STATUS_LINK_DOWN) || !pDevice->InitDone)
694 pPacket
= (PLM_PACKET
)
695 QQ_PopHead(&pDevice
->TxPacketFreeQ
.Container
);
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;
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
);
724 /* -------- Broadcom MM hooks ----------- */
728 MM_ReadConfig16(PLM_DEVICE_BLOCK pDevice
, LM_UINT32 Offset
,
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
;
740 MM_WriteConfig16(PLM_DEVICE_BLOCK pDevice
, LM_UINT32 Offset
,
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
;
752 MM_ReadConfig32(PLM_DEVICE_BLOCK pDevice
, LM_UINT32 Offset
,
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
;
764 MM_WriteConfig32(PLM_DEVICE_BLOCK pDevice
, LM_UINT32 Offset
,
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
;
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
;
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;
800 MM_IndicateRxPackets(PLM_DEVICE_BLOCK pDevice
)
802 struct be_b57_dev
*dev
= (struct be_b57_dev
*)pDevice
;
806 pPacket
= (PLM_PACKET
)
807 QQ_PopHead(&pDevice
->RxPacketReceivedQ
.Container
);
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
;
822 MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice
)
824 return LM_STATUS_SUCCESS
;
829 tx_cleanup_thread(void *us
)
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
;
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
);
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);*/
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
;
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
;
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
),
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
;
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
;
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
);
940 return LM_STATUS_SUCCESS
;
945 MM_InitializeUmPackets(PLM_DEVICE_BLOCK pDevice
)
948 struct be_b57_dev
*pUmDevice
= (struct be_b57_dev
*) pDevice
;
949 struct B_UM_PACKET
*pUmPacket
;
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.
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
;
979 MM_UnmapRxDma(LM_DEVICE_BLOCK
*pDevice
, LM_PACKET
*pPacket
)
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
;
993 MM_FindPeerDev(LM_DEVICE_BLOCK
*pDevice
)
995 /* I have no idea what this routine does. I think it's optional... */
1001 MM_Sleep(LM_DEVICE_BLOCK
*pDevice
, LM_UINT32 msec
)
1004 return LM_STATUS_SUCCESS
;