BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / kernel / drivers / network / dp83815 / driver.c
bloba09f76f478772a858c0d5b2c626c8f15886098f6
1 /* National Semiconductor dp83815 driver
2 * Copyright (c) 2006 Urias McCullough (umccullough@gmail.com)
3 * Portions of code Copyright (c) 2003-2004, Niels Sascha Reedijk
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 * Portions of code based on dp83815 driver by: Antonio Carpio (BolivianTONE@nc.rr.com)
25 * Portions of code may be: Copyright (c) 1998, 1999 Be, Inc. All Rights Reserved under terms of Be Sample Code License.
28 #include <KernelExport.h>
29 #include <Drivers.h>
30 #include <Errors.h>
31 #include <PCI.h>
32 #include <malloc.h>
33 #include <stdio.h>
34 #include <string.h>
36 #include "ether_driver.h"
37 #include "util.h"
38 #include "dp83815_regs.h"
40 #define kDevName "dp83815"
41 #define kDevDir "net/" kDevName "/"
42 #define MAX_CARDS 4
43 #define MAX_DESC 128 /* eventually going into config file */
44 #define BUFFER_SIZE 2048 /* make it easy to do math and whatnot */
45 #define MAX_PACKET_SIZE 1518 /* can be 2046 if RXCFG has ALP set */
46 #define NONBLOCK_WAIT 1000
48 //#define DEBUG
49 #ifdef DEBUG
50 # define TRACE(x) dprintf x
51 #else
52 # define TRACE(x) ;
53 #endif
55 typedef struct supported_device {
56 uint16 vendor_id;
57 uint16 device_id;
58 char * name;
59 } supported_device_t;
61 static supported_device_t m_supported_devices[] = {
62 { 0x100B, 0x0020, "National Semiconductor dp83815 (Netgear 311/312)" },
63 { 0, 0, NULL } /* End of list */
66 int32 api_version = B_CUR_DRIVER_API_VERSION; //Procedure
68 typedef struct descriptor {
69 uint32 link; /* Physical address of next descriptor */
70 volatile uint32 cmd; /* info to/from NIC */
71 volatile uint32 ptr; /* Physical address of the buffer */
72 struct descriptor *virt_next; /* virtual address of next descriptor */
73 void *virt_buff; /* virtual address of the buffer */
74 } descriptor_t;
76 typedef struct desc_ring {
77 descriptor_t *Curr; /* Current descriptor to be accessed */
78 sem_id Sem; /* Queue for outstanding reads/writes */
79 spinlock Lock; /* Spinlock used to grab a descriptor */
80 descriptor_t *CurrInt; /* Interrupt Hook's Current Descriptor */
81 } desc_ring_t;
83 typedef struct stats {
84 uint32 rx_ok,
85 tx_ok,
86 tx_err,
87 rx_err,
88 rx_overrun,
89 tx_underrun,
90 collisions,
91 rx_att,
92 tx_att;
93 } stats_t;
95 typedef struct dp83815_properties
97 pci_info *pcii; /* Pointer to PCI Info for the device */
98 uint32 reg_base; /* Base address for registers */
99 area_id ioarea; /* PPC: Area where the mmaped registers are */
100 area_id reg_area,
101 mem_area;
102 uint8 device_id; /* Which device id this is... */
104 ether_address_t address; /* holds the MAC address */
105 sem_id lock; /* lock this structure: still interrupt */
106 int32 blockFlag; /* for blocking or nonblocking reads */
108 stats_t stats;
109 desc_ring_t Rx, Tx;
110 } dp83815_properties_t;
112 static pci_info *m_devices[MAX_CARDS];
113 static pci_module_info *m_pcimodule = 0; //To call methods of pci
114 static char *dp83815_names[MAX_CARDS + 1];
115 static int32 m_openmask = 0; //Is the thing already opened?
116 static uint32 pages_needed(uint32 mem_size);
117 static int32 dp83815_interrupt_hook(void *data); /* interrupt handler */
119 static status_t allocate_resources(dp83815_properties_t *data); /* allocate semaphores & spinlocks */
120 static void free_resources(dp83815_properties_t *data); /* deallocate semaphores & spinlocks */
121 static status_t init_ring_buffers(dp83815_properties_t *data); /* allocate and initialize frame buffer rings */
122 static status_t domulti(dp83815_properties_t *data, uint8 *addr); /* add multicast address to hardware filter list */
123 static status_t free_hook(void *cookie);
124 static status_t close_hook(void *);
126 #ifdef __INTEL__
127 #define write8( offset , value) (m_pcimodule->write_io_8 ((data->reg_base + (offset)), (value) ) )
128 #define write16( offset , value) (m_pcimodule->write_io_16((data->reg_base + (offset)), (value) ) )
129 #define write32( offset , value) (m_pcimodule->write_io_32((data->reg_base + (offset)), (value) ) )
131 #define read8( offset ) (m_pcimodule->read_io_8 ((data->reg_base + offset)))
132 #define read16( offset ) (m_pcimodule->read_io_16((data->reg_base + offset)))
133 #define read32( offset ) (m_pcimodule->read_io_32((data->reg_base + offset)))
135 static void
136 dp83815_init_registers(dp83815_properties_t *data)
138 data->reg_base = data->pcii->u.h0.base_registers[0];
140 #else /* PPC */
141 #include <ByteOrder.h>
142 #define write8( offset , value) (*((volatile uint8 *)(data->reg_base + (offset))) = (value))
143 #define write16( offset , value) (*((volatile uint8 *)(data->reg_base + (offset))) = B_HOST_TO_LENDIAN_INT16(value))
144 #define write32( offset , value) (*((volatile uint8 *)(data->reg_base + (offset))) = B_HOST_TO_LENDIAN_INT32(value))
146 #define read8( offset ) (*((volatile uint8*)(data->reg_base + (offset))))
147 #define read16( offset ) B_LENDIAN_TO_HOST_INT16(*((volatile uint16*)(data->reg_base + (offset))))
148 #define read32( offset ) B_LENDIAN_TO_HOST_INT32(*((volatile uint32*)(data->reg_base + (offset))))
150 static void
151 dp83815_init_registers(rtl8139_properties_t *data)
153 int32 base, size, offset;
154 base = data->pcii->u.h0.base_registers[0];
155 size = data->pcii->u.h0.base_register_sizes[0];
157 /* Round down to nearest page boundary */
158 base = base & ~(B_PAGE_SIZE - 1);
160 /* Adjust the size */
161 offset = data->pcii->u.h0.base_registers[0] - base;
162 size += offset;
163 size = (size + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1);
165 TRACE(( kDevName " _open_hook(): PCI base=%lx size=%lx offset=%lx\n",
166 base, size, offset));
168 data->ioarea = map_physical_memory(kDevName " Regs", base, size,
169 B_ANY_KERNEL_ADDRESS, B_READ_AREA | B_WRITE_AREA,
170 (void **)&data->reg_base);
172 data->reg_base = data->reg_base + offset;
174 #endif
177 uint32
178 pages_needed(uint32 mem_size)
180 uint32 pages = mem_size / B_PAGE_SIZE;
181 if (pages % B_PAGE_SIZE != 0)
182 pages += 1;
183 return pages;
187 status_t
188 init_hardware(void)
190 // Nielx: no special requirements here...
191 TRACE(( kDevName ": init_hardware\n" ));
192 return B_OK;
196 status_t
197 init_driver(void)
199 status_t status; //Storage for statuses
200 pci_info *item; //Storage used while looking through pci
201 int32 i, found; //Counter
203 TRACE(( kDevName ": init_driver()\n" ));
205 // Try if the PCI module is loaded (it would be weird if it wouldn't,
206 // but alas)
207 if ((status = get_module(B_PCI_MODULE_NAME, (module_info **)&m_pcimodule))
208 != B_OK) {
209 TRACE((kDevName " init_driver(): Get PCI module failed! %lu \n",
210 status));
211 return status;
214 i = 0;
215 item = (pci_info *)malloc(sizeof(pci_info));
216 for (i = found = 0; m_pcimodule->get_nth_pci_info(i, item) == B_OK; i++) {
217 supported_device_t *supported;
219 for (supported = m_supported_devices; supported->name; supported++) {
220 if ((item->vendor_id == supported->vendor_id)
221 && (item->device_id == supported->device_id)) {
222 //Also done in etherpci sample code
223 if ((item->u.h0.interrupt_line == 0)
224 || (item->u.h0.interrupt_line == 0xFF)) {
225 TRACE(( kDevName " init_driver(): found %s with invalid IRQ"
226 " - check IRQ assignement\n", supported->name));
227 continue;
230 TRACE(( kDevName " init_driver(): found %s at IRQ %u \n",
231 supported->name, item->u.h0.interrupt_line));
232 m_devices[found] = item;
233 item = (pci_info *)malloc(sizeof(pci_info));
235 found++;
240 free(item);
242 //Check if we have found any devices:
243 if (found == 0) {
244 TRACE(( kDevName " init_driver(): no device found\n" ));
245 put_module(B_PCI_MODULE_NAME); //dereference module
246 return ENODEV;
249 //Create the devices list
251 char name[32];
253 for (i = 0; i < found; i++) {
254 snprintf(name, 32, "%s%ld", kDevDir, i);
255 dp83815_names[i] = strdup(name);
257 dp83815_names[i] = NULL;
259 return B_OK;
263 /* ----------
264 uninit_driver - optional function - called every time the driver
265 is unloaded
266 ----- */
267 void
268 uninit_driver(void)
270 int index;
271 void *item;
272 TRACE(( kDevName ": uninit_driver()\n" ));
274 for (index = 0; (item = dp83815_names[index]) != NULL; index++)
276 free(item);
277 free(m_devices[index]);
280 put_module(B_PCI_MODULE_NAME);
284 static status_t
285 open_hook(const char *name, uint32 flags, void** cookie)
288 dp83815_properties_t *data;
289 uint8 temp8;
290 // uint16 temp16;
291 uint32 temp32;
292 unsigned char cmd;
294 TRACE(( kDevName " open_hook()\n" ));
296 // verify device access
298 char *thisName;
299 int32 mask;
301 // search for device name
302 for (temp8 = 0; (thisName = dp83815_names[temp8]) != NULL; temp8++) {
303 if (!strcmp(name, thisName))
304 break;
306 if (!thisName)
307 return EINVAL;
309 // check if device is already open
310 mask = 1L << temp8;
311 if (atomic_or(&m_openmask, mask) & mask)
312 return B_BUSY;
315 //Create a structure that contains the internals
316 if (!(*cookie = data =
317 (dp83815_properties_t *)malloc(sizeof(dp83815_properties_t)))) {
318 TRACE(( kDevName " open_hook(): Out of memory\n" ));
319 return B_NO_MEMORY;
322 //Set status to open:
323 m_openmask &= ~(1L << temp8);
325 //Clear memory
326 memset(data, 0, sizeof(dp83815_properties_t));
328 //Set the ID
329 data->device_id = temp8;
331 // Create lock
332 data->lock = create_sem(1, kDevName " data protect");
333 set_sem_owner(data->lock, B_SYSTEM_TEAM);
334 data->Rx.Sem = create_sem(0, kDevName " read wait");
335 set_sem_owner(data->Rx.Sem, B_SYSTEM_TEAM);
336 data->Tx.Sem = create_sem(1, kDevName " write wait");
337 set_sem_owner(data->Tx.Sem, B_SYSTEM_TEAM);
339 //Set up the cookie
340 data->pcii = m_devices[data->device_id];
342 //Enable the registers
343 dp83815_init_registers(data);
345 /* enable pci address access */
346 cmd = m_pcimodule->read_pci_config(data->pcii->bus, data->pcii->device,
347 data->pcii->function, PCI_command, 2);
348 cmd = cmd | PCI_command_io | PCI_command_master | PCI_command_memory;
349 m_pcimodule->write_pci_config(data->pcii->bus, data->pcii->device,
350 data->pcii->function, PCI_command, 2, cmd);
352 if (allocate_resources(data) != B_OK)
353 goto err1;
355 /* We want interrupts! */
356 if (install_io_interrupt_handler(data->pcii->u.h0.interrupt_line,
357 dp83815_interrupt_hook, data, 0) != B_OK) {
358 TRACE((kDevName " open_hook(): Error installing interrupt handler\n"));
359 return B_ERROR;
363 temp32 = read32(REG_SRR);
364 TRACE(( "SRR: %x\n", temp32));
367 write32(REG_CR, CR_RXR|CR_TXR); /* Reset Tx & Rx */
369 if (init_ring_buffers(data) != B_OK) /* Init ring buffers */
370 goto err1;
372 write32(REG_RFCR, RFCR_RFEN | RFCR_AAB | RFCR_AAM | RFCR_AAU);
374 write32(REG_RXCFG, RXCFG_ATP | RXCFG_DRTH(31)); /* Set the drth */
376 write32(REG_TXCFG, TXCFG_CSI |
377 TXCFG_HBI |
378 TXCFG_ATP |
379 TXCFG_MXDMA_256 |
380 TXCFG_FLTH(16) |
381 TXCFG_DRTH(16));
383 write32(REG_IMR, ISR_RXIDLE | ISR_TXOK | ISR_RXOK );
385 write32(REG_CR, CR_RXE); /* Enable Rx */
386 write32(REG_IER, 1); /* Enable interrupts */
388 return B_OK;
390 err1:
391 free_resources(data);
392 free(data);
393 return B_ERROR;
397 static status_t
398 read_hook (void* cookie, off_t position, void *buf, size_t* num_bytes)
400 dp83815_properties_t *data = cookie;
401 cpu_status former;
402 descriptor_t* desc;
403 size_t length = 0;
405 TRACE(( kDevName ": read_hook()\n" ));
407 //if( !data->nonblocking )
408 acquire_sem_etc(data->Rx.Sem, 1, B_CAN_INTERRUPT | data->blockFlag,
409 NONBLOCK_WAIT);
412 former = disable_interrupts();
413 acquire_spinlock(&data->Rx.Lock);
414 desc = data->Rx.Curr;
415 data->Rx.Curr = desc->virt_next;
416 release_spinlock(&data->Rx.Lock);
417 restore_interrupts(former);
420 length = DESC_LENGTH&desc->cmd;
422 if (desc->cmd & (DESC_RXA | DESC_RXO | DESC_LONG | DESC_RUNT | DESC_ISE
423 | DESC_CRCE | DESC_FAE | DESC_LBP | DESC_COL))
424 TRACE(( "desc cmd: %x\n", desc->cmd ));
426 if (length < 64) {
427 *num_bytes = 0;
428 return B_ERROR;
431 if (*num_bytes < length)
432 length = *num_bytes;
434 memcpy(buf, desc->virt_buff, length);
435 desc->cmd = DESC_LENGTH&MAX_PACKET_SIZE;
436 *num_bytes = length;
438 atomic_add(&data->stats.rx_att, 1);
440 if (length == 0)
441 return B_ERROR;
443 return B_OK;
447 static status_t
448 write_hook(void* cookie, off_t position, const void* buffer, size_t* num_bytes)
450 dp83815_properties_t *data = cookie;
451 cpu_status former;
452 descriptor_t* desc;
454 TRACE(( kDevName " write_hook()\n" ));
456 acquire_sem(data->lock);
457 acquire_sem_etc(data->Tx.Sem, 1, B_CAN_INTERRUPT | data->blockFlag,
458 NONBLOCK_WAIT);
461 former = disable_interrupts();
462 acquire_spinlock(&data->Tx.Lock);
463 desc = data->Tx.Curr;
464 data->Tx.Curr = desc->virt_next;
465 release_spinlock(&data->Tx.Lock);
466 restore_interrupts(former);
469 if (*num_bytes > MAX_PACKET_SIZE) { /* if needed */
470 TRACE(( "Had to truncate the packet from %d to %d\n", *num_bytes,
471 MAX_PACKET_SIZE));
472 *num_bytes = MAX_PACKET_SIZE; /* truncate the packet */
476 while (desc->cmd & DESC_OWN) { /* make sure a buffer is available */
477 TRACE(( "spinning in the write hook\n"));
478 spin(1000); /* wait a while if not */
481 memcpy(desc->virt_buff, buffer, *num_bytes); /* now copy the data */
482 desc->cmd = DESC_OWN | *num_bytes; /* update the cmd bits */
484 write32(REG_CR, CR_TXE); /* tell the card to start tx */
485 atomic_add(&data->stats.tx_att, 1);
487 release_sem_etc(data->lock, 1, B_DO_NOT_RESCHEDULE);
489 return B_OK;
493 static status_t
494 control_hook (void* cookie, uint32 op, void* arg, size_t len)
496 dp83815_properties_t *data = (dp83815_properties_t *)cookie;
497 TRACE(( kDevName " control_hook()\n" ));
499 switch (op) {
500 case ETHER_INIT:
501 TRACE((kDevName " control_hook(): Wants us to init... ;-)\n"));
502 return B_NO_ERROR;
504 case ETHER_GETADDR:
505 if (data == NULL)
506 return B_ERROR;
508 TRACE((kDevName " control_hook(): Wants our address...\n"));
509 memcpy(arg, (void *) &(data->address), sizeof(ether_address_t));
510 return B_OK;
512 case ETHER_ADDMULTI:
513 return domulti(data, (unsigned char *)arg);
515 case ETHER_NONBLOCK:
516 if (data == NULL)
517 return B_ERROR;
519 TRACE((kDevName " control_hook(): Wants to set block/nonblock\n"));
521 if (*((int32 *)arg))
522 data->blockFlag = B_RELATIVE_TIMEOUT;
523 else
524 data->blockFlag = 0;
526 return B_NO_ERROR;
528 case ETHER_REMMULTI:
529 TRACE((kDevName " control_hook(): Wants REMMULTI\n"));
530 return B_OK;
532 case ETHER_SETPROMISC:
533 TRACE((kDevName " control_hook(): Wants PROMISC\n"));
534 return B_OK;
536 case ETHER_GETFRAMESIZE:
537 TRACE((kDevName " control_hook(): Wants GETFRAMESIZE\n"));
538 *((unsigned int *)arg) = 1514;
539 return B_OK;
542 return B_BAD_VALUE;
546 static int32
547 dp83815_interrupt_hook(void *cookie)
549 dp83815_properties_t *data = (dp83815_properties_t *) cookie;
550 uint32 isr;
551 isr = read32(REG_ISR);
553 if (isr == 0)
554 return B_UNHANDLED_INTERRUPT;
556 if (isr & ISR_RXOK) {
557 int num_packets = 0;
558 descriptor_t *curr = data->Rx.CurrInt;
560 while (curr->cmd & DESC_OWN) {
561 curr = curr->virt_next;
562 num_packets++;
565 data->Rx.CurrInt = curr;
566 data->stats.rx_ok += num_packets;
567 if (num_packets > 1)
568 TRACE(( "received %d descriptors\n", num_packets));
569 if (num_packets)
570 release_sem_etc(data->Rx.Sem, num_packets, B_DO_NOT_RESCHEDULE);
573 if (isr & ISR_TXOK) {
574 data->stats.tx_ok++;
575 release_sem_etc(data->Tx.Sem, 1, B_DO_NOT_RESCHEDULE);
578 if (isr & ISR_RXIDLE)
579 TRACE(("RX IS IDLE!\n"));
581 if (isr & ~(ISR_TXIDLE | ISR_TXOK | ISR_RXOK | ISR_RXIDLE | ISR_RXEARLY))
582 TRACE(("ISR: %x\n", isr));
584 return B_INVOKE_SCHEDULER;
588 static status_t
589 close_hook(void* cookie)
591 dp83815_properties_t * data = (dp83815_properties_t *) cookie;
593 write32(REG_IER, 0); /* Disable interrupts */
594 write32(REG_CR, CR_RXD | CR_TXD); /* Disable Rx & Tx */
596 return B_OK;
600 static status_t
601 free_hook(void* cookie)
603 dp83815_properties_t *data = (dp83815_properties_t *) cookie;
605 TRACE(( kDevName " free_hook()\n" ));
607 while (data->Tx.Lock); /* wait for any current writes to finish */
608 while (data->Rx.Lock); /* wait for any current reads to finish */
610 //Remove interrupt handler
611 remove_io_interrupt_handler(data->pcii->u.h0.interrupt_line,
612 dp83815_interrupt_hook, cookie);
614 m_openmask &= ~(1L << data->device_id);
616 free_resources(data); /* unblock waiting threads */
618 //Finally, free the cookie
619 free(data);
621 //Put the pci module
622 put_module(B_PCI_MODULE_NAME);
624 return B_OK;
628 device_hooks dp83815_hooks = {
629 open_hook, /* -> open entry point */
630 close_hook, /* -> close entry point */
631 free_hook, /* -> free cookie */
632 control_hook, /* -> control entry point */
633 read_hook, /* -> read entry point */
634 write_hook /* -> write entry point */
638 const char**
639 publish_devices()
641 return (const char **)dp83815_names;
645 device_hooks*
646 find_device(const char* name)
648 return &dp83815_hooks;
652 static status_t
653 init_ring_buffers(dp83815_properties_t *data)
655 uint32 i;
656 area_info info;
657 physical_entry map[2];
658 uint32 pages;
660 descriptor_t *RxDescRing = NULL;
661 descriptor_t *TxDescRing = NULL;
663 descriptor_t *desc_base_virt_addr;
664 uint32 desc_base_phys_addr;
666 void *buff_base_virt_addr;
667 uint32 buff_base_phys_addr;
670 data->mem_area = 0;
672 #define NUM_BUFFS 2*MAX_DESC
674 pages = pages_needed(2 * MAX_DESC * sizeof(descriptor_t)
675 + NUM_BUFFS * BUFFER_SIZE);
677 data->mem_area = create_area(kDevName " desc buffer", (void**)&RxDescRing,
678 B_ANY_KERNEL_ADDRESS, pages * B_PAGE_SIZE, B_32_BIT_CONTIGUOUS,
679 B_READ_AREA | B_WRITE_AREA);
680 if (data->mem_area < 0)
681 return B_ERROR;
683 get_area_info(data->mem_area, &info);
684 get_memory_map(info.address, info.size, map, 4);
686 desc_base_phys_addr = map[0].address + NUM_BUFFS * BUFFER_SIZE;
687 desc_base_virt_addr = info.address + NUM_BUFFS * BUFFER_SIZE;
689 buff_base_phys_addr = map[0].address;
690 buff_base_virt_addr = info.address;
692 RxDescRing = desc_base_virt_addr;
693 for (i = 0; i < MAX_DESC; i++) {
694 RxDescRing[i].link = desc_base_phys_addr
695 + ((i + 1) % MAX_DESC) * sizeof(descriptor_t);
696 RxDescRing[i].cmd = MAX_PACKET_SIZE;
697 RxDescRing[i].ptr = buff_base_phys_addr + i * BUFFER_SIZE;
698 RxDescRing[i].virt_next = &RxDescRing[(i + 1) % MAX_DESC];
699 RxDescRing[i].virt_buff = buff_base_virt_addr + i * BUFFER_SIZE;
702 TxDescRing = desc_base_virt_addr + MAX_DESC;
703 for (i = 0; i < MAX_DESC; i++) {
704 TxDescRing[i].link = desc_base_phys_addr
705 + MAX_DESC * sizeof(descriptor_t)
706 + ((i + 1) % MAX_DESC) * sizeof(descriptor_t);
707 TxDescRing[i].cmd = MAX_PACKET_SIZE;
708 TxDescRing[i].ptr = buff_base_phys_addr
709 + ((i + MAX_DESC) * BUFFER_SIZE);
710 TxDescRing[i].virt_next = &TxDescRing[(i + 1) % MAX_DESC];
711 TxDescRing[i].virt_buff = buff_base_virt_addr
712 + ((i + MAX_DESC) * BUFFER_SIZE);
715 data->Rx.Curr = RxDescRing;
716 data->Tx.Curr = TxDescRing;
718 data->Rx.CurrInt = RxDescRing;
719 data->Tx.CurrInt = TxDescRing;
722 write32(REG_RXDP, desc_base_phys_addr); /* set the initial rx descriptor */
724 i = desc_base_phys_addr + MAX_DESC * sizeof(descriptor_t);
725 write32(REG_TXDP, i); /* set the initial tx descriptor */
727 return B_OK;
731 static status_t
732 allocate_resources(dp83815_properties_t *data)
734 /* intialize rx semaphore with zero received packets */
735 if ((data->Rx.Sem = create_sem(0, kDevName " rx")) < 0) {
736 TRACE(( kDevName " create rx sem failed %x \n", data->Rx.Sem));
737 return (data->Rx.Sem);
739 set_sem_owner(data->Rx.Sem, B_SYSTEM_TEAM);
742 /* intialize tx semaphore with the number of free tx buffers */
743 if ((data->Tx.Sem = create_sem(MAX_DESC, kDevName " tx")) < 0) {
744 delete_sem(data->Rx.Sem);
745 TRACE(( kDevName " create read sem failed %x \n", data->Tx.Sem));
746 return (data->Tx.Sem);
749 set_sem_owner(data->Tx.Sem, B_SYSTEM_TEAM);
751 data->blockFlag = 0;
753 return (B_OK);
757 static void free_resources(dp83815_properties_t *data)
759 delete_sem(data->Rx.Sem);
760 delete_sem(data->Tx.Sem);
764 static status_t domulti(dp83815_properties_t *data, uint8 *addr)
766 TRACE(( "Set up multicast filter here\n"));
767 return (B_ERROR);