2 * Copyright 2006, Hideyuki Abe. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 //! Ethernet Driver for VMware PCnet/PCI virtual network controller
10 #include <ether_driver.h>
13 #include <KernelExport.h>
23 /* debug flag definitions */
26 #define RX 0x0004 /* dump received frames */
27 #define TX 0x0008 /* dump transmitted frames */
28 #define INTERRUPT 0x0010 /* interrupt calls */
29 #define FUNCTION 0x0020 /* function calls */
30 #define PCI_IO 0x0040 /* pci reads and writes */
31 #define SEQ 0x0080 /* trasnmit & receive TCP/IP sequence sequence numbers */
32 #define WARN 0x0100 /* Warnings - off on final release */
35 //#define DEBUG_FLG ( ERR | INFO | WARN )
36 //#define DEBUG_FLG ( ERR | INFO | INTERRUPT | FUNCTION | WARN )
37 #define DEBUG_FLG ( ERR | WARN )
39 #define DEBUG(x) (DEBUG_FLG & (x))
40 #define TRACE(x) dprintf x
42 /* PCI vendor and device ID's */
43 #define VENDOR_ID 0x1022 /* AMD */
44 #define DEVICE_ID 0x2000 /* PCnet/PCI */
47 #define DEVICE_NAME "vlance"
48 #define DEVICE_NAME_LEN 64
50 #define MAX_CARDS 4 /* maximum number of driver instances */
52 #define BUFFER_SIZE 2048L /* B_PAGE_SIZE divided into even amounts that will hold a 1518 frame */
53 #define MAX_FRAME_SIZE 1514 /* 1514 + 4 bytes checksum */
55 /* ring buffer sizes */
56 #define TX_BUFF_IDX (4)
57 #define RX_BUFF_IDX (5)
58 #define TX_BUFFERS (1 << TX_BUFF_IDX)
59 #define RX_BUFFERS (1 << RX_BUFF_IDX) /* Must be a power of 2 */
61 /* max number of multicast address */
74 /* driver intance definition */
76 mac_addr_t mac_addr
; /* MAC address */
77 int32 devID
; /* device identifier */
78 pci_info
*devInfo
; /* device information */
79 uint16 irq
; /* our IRQ line */
80 sem_id ilock
, olock
; /* I/O semaphores */
81 int32 readLock
, writeLock
; /* reentrant read/write lock */
82 int32 blockFlg
; /* for blocking (0) or nonblocking (!=0) read */
83 init_block_t init_blk
; /* Initialization Block */
84 uint32 phys_init_blk
; /* Initialization Block physical address */
85 area_id tx_desc_area
; /* transmit descriptor area */
86 area_id tx_buf_area
; /* transmit buffer area */
87 area_id rx_desc_area
; /* receive descriptor area */
88 area_id rx_buf_area
; /* receive buffer area */
89 uchar
*tx_buf
[TX_BUFFERS
]; /* tx buffers */
90 uchar
*rx_buf
[RX_BUFFERS
]; /* rx buffers */
91 trns_desc_t
*tx_desc
[TX_BUFFERS
]; /* tx frame descriptors */
92 recv_desc_t
*rx_desc
[RX_BUFFERS
]; /* rx frame descriptors */
93 uint32 phys_tx_buf
; /* tx buffer physical address */
94 uint32 phys_rx_buf
; /* rx buffer physical address */
95 uint32 phys_tx_desc
; /* tx descriptor physical address */
96 uint32 phys_rx_desc
; /* rx descriptor physical address */
97 int16 tx_sent
, tx_acked
; /* in & out index to tx buffers */
98 int16 rx_received
, rx_acked
; /* in & out index to rx buffers */
99 int32 nmulti
; /* number of multicast address */
100 mac_addr_t multi
[MAX_MULTI
]; /* multicast address */
101 uint32 reg_base
; /* base address of PCI regs */
105 /* function prototypes */
106 static status_t
vlance_open(const char *name
, uint32 flags
, void **_cookie
);
107 static status_t
vlance_close(void *_device
);
108 static status_t
vlance_free(void *_device
);
109 static status_t
vlance_control(void *cookie
, uint32 msg
, void *buf
, size_t len
);
110 static status_t
vlance_read(void *_device
, off_t pos
, void *buf
, size_t *len
);
111 static status_t
vlance_write(void *_device
, off_t pos
, const void *buf
, size_t *len
);
112 static int32
vlance_interrupt(void *_device
);
114 static device_hooks sDeviceHooks
= {
115 vlance_open
, /* open entry point */
116 vlance_close
, /* close entry point */
117 vlance_free
, /* free entry point */
118 vlance_control
, /* control entry point */
119 vlance_read
, /* read entry point */
120 vlance_write
, /* write entry point */
121 NULL
, /* select entry point */
122 NULL
, /* deselect entry point */
127 int32 api_version
= B_CUR_DRIVER_API_VERSION
;
129 static pci_module_info
*sPCI
;
130 static uint32 sNumOfCards
;
131 static char *sDeviceNames
[MAX_CARDS
+ 1]; /* NULL-terminated */
132 static pci_info
*sCardInfo
[MAX_CARDS
];
133 static int32 sOpenLock
[MAX_CARDS
];
136 #define write8(addr, val) (*sPCI->write_io_8)((addr), (val))
137 #define write16(addr, val) (*sPCI->write_io_16)((addr), (val))
138 #define write32(addr, val) (*sPCI->write_io_32)((addr), (val))
139 #define read8(addr) ((*sPCI->read_io_8)(addr))
140 #define read16(addr) ((*sPCI->read_io_16)(addr))
141 #define read32(addr) ((*sPCI->read_io_32)(addr))
143 #define RNDUP(x, y) (((x) + (y) - 1) & ~((y) - 1))
146 // #pragma mark - register access
150 csr_read(dev_info_t
*device
, uint32 reg_num
)
152 write32(device
->reg_base
+ PCNET_RAP_OFFSET
, reg_num
);
153 return read32(device
->reg_base
+ PCNET_RDP_OFFSET
);
158 csr_write(dev_info_t
*device
, uint32 reg_num
, uint32 data
)
160 write32(device
->reg_base
+ PCNET_RAP_OFFSET
, reg_num
);
161 write32(device
->reg_base
+ PCNET_RDP_OFFSET
, data
);
166 bcr_read(dev_info_t
*device
, uint32 reg_num
)
168 write32(device
->reg_base
+ PCNET_RAP_OFFSET
, reg_num
);
169 return read32(device
->reg_base
+ PCNET_BDP_OFFSET
);
174 bcr_write(dev_info_t
*device
, uint32 reg_num
, uint32 data
)
176 write32(device
->reg_base
+ PCNET_RAP_OFFSET
, reg_num
);
177 write32(device
->reg_base
+ PCNET_BDP_OFFSET
, data
);
181 // #pragma mark - misc
185 get_card_info(pci_info
*info
[])
189 pci_info
*item
= (pci_info
*)malloc(sizeof(pci_info
));
193 for (i
= 0, entries
= 0; entries
< MAX_CARDS
; i
++) {
194 status
= sPCI
->get_nth_pci_info(i
, item
);
198 if (item
->vendor_id
== VENDOR_ID
&& item
->device_id
== DEVICE_ID
) {
199 /* check if the device really has an IRQ */
200 if (item
->u
.h0
.interrupt_line
== 0 || item
->u
.h0
.interrupt_line
== 0xff) {
201 TRACE((DEVICE_NAME
" found with invalid IRQ - check IRQ assignement\n"));
205 TRACE((DEVICE_NAME
" found at IRQ %x\n", item
->u
.h0
.interrupt_line
));
207 info
[entries
++] = item
;
208 item
= (pci_info
*)malloc(sizeof(pci_info
));
218 free_card_info(pci_info
*info
[])
222 for (i
= 0; i
< sNumOfCards
; i
++) {
231 map_pci_addr(dev_info_t
*device
)
233 pci_info
*dev_info
= device
->devInfo
;
236 pci_cmd
= sPCI
->read_pci_config(dev_info
->bus
, dev_info
->device
,
237 dev_info
->function
, PCI_command
, 2);
239 /* turn on I/O port decode, Memory Address Decode, and Bus Mastering */
240 sPCI
->write_pci_config(dev_info
->bus
, dev_info
->device
,
241 dev_info
->function
, PCI_command
, 2,
242 pci_cmd
| PCI_command_io
| PCI_command_memory
| PCI_command_master
);
244 device
->reg_base
= dev_info
->u
.h0
.base_registers
[0];
247 dprintf(DEVICE_NAME
": reg_base=%x\n", device
->reg_base
);
255 alloc_buffers(dev_info_t
*device
)
259 physical_entry entry
;
261 /* get physical address of Initialization Block */
262 size
= RNDUP(sizeof(dev_info_t
), B_PAGE_SIZE
);
263 get_memory_map(&(device
->init_blk
), size
, &entry
, 1);
264 device
->phys_init_blk
= entry
.address
;
266 TRACE((DEVICE_NAME
" init block va=%p pa=%p, size %lx\n",
267 &(device
->init_blk
), (void *)device
->phys_init_blk
, size
));
269 /* create tx descriptor area */
270 size
= RNDUP(sizeof(trns_desc_t
) * TX_BUFFERS
, B_PAGE_SIZE
);
271 device
->tx_desc_area
= create_area(DEVICE_NAME
" tx descriptors",
272 (void **)device
->tx_desc
, B_ANY_KERNEL_ADDRESS
, size
,
273 B_32_BIT_FULL_LOCK
, B_READ_AREA
| B_WRITE_AREA
);
274 if (device
->tx_desc_area
< 0)
275 return device
->tx_desc_area
;
277 for (i
= 1; i
< TX_BUFFERS
; i
++) {
278 device
->tx_desc
[i
] = (device
->tx_desc
[i
-1]) + 1;
280 /* get physical address of tx descriptor */
281 get_memory_map(device
->tx_desc
[0], size
, &entry
, 1);
282 device
->phys_tx_desc
= entry
.address
;
284 TRACE((DEVICE_NAME
" create tx desc area va=%p pa=%p sz=%lx\n",
285 device
->tx_desc
[0], (void *)device
->phys_tx_desc
, size
));
287 /* create tx buffer area */
288 size
= RNDUP(BUFFER_SIZE
* TX_BUFFERS
, B_PAGE_SIZE
);
289 device
->tx_buf_area
= create_area(DEVICE_NAME
" tx buffers",
290 (void **)device
->tx_buf
, B_ANY_KERNEL_ADDRESS
, size
,
291 B_32_BIT_FULL_LOCK
, B_READ_AREA
| B_WRITE_AREA
);
292 if (device
->tx_buf_area
< 0) {
293 delete_area(device
->tx_desc_area
); // sensitive to alloc ordering
294 return device
->tx_buf_area
;
297 for (i
= 1; i
< TX_BUFFERS
; i
++) {
298 device
->tx_buf
[i
] = (device
->tx_buf
[i
-1]) + BUFFER_SIZE
;
301 /* get physical address of tx buffer */
302 get_memory_map(device
->tx_buf
[0], size
, &entry
, 1);
303 device
->phys_tx_buf
= entry
.address
;
305 TRACE((DEVICE_NAME
" create tx buf area va=%p pa=%08lx sz=%lx\n",
306 device
->tx_buf
[0], device
->tx_desc
[0]->s
.tbadr
, size
));
308 /* create rx descriptor area */
309 size
= RNDUP( sizeof(recv_desc_t
) * RX_BUFFERS
, B_PAGE_SIZE
);
310 device
->rx_desc_area
= create_area(DEVICE_NAME
" rx descriptors",
311 (void **)device
->rx_desc
, B_ANY_KERNEL_ADDRESS
, size
,
312 B_32_BIT_FULL_LOCK
, B_READ_AREA
| B_WRITE_AREA
);
313 if (device
->rx_desc_area
< 0) {
314 delete_area(device
->tx_desc_area
);
315 delete_area(device
->tx_buf_area
); // sensitive to alloc ordering
316 return device
->rx_desc_area
;
319 for (i
= 1; i
< RX_BUFFERS
; i
++) {
320 device
->rx_desc
[i
] = (device
->rx_desc
[i
-1]) + 1;
322 /* get physical address of rx descriptor */
323 get_memory_map(device
->rx_desc
[0], size
, &entry
, 1);
324 device
->phys_rx_desc
= entry
.address
;
326 TRACE((DEVICE_NAME
" create rx desc area va=%p pa=%p sz=%lx\n",
327 device
->rx_desc
[0], (void *)device
->phys_rx_desc
, size
));
329 /* create rx buffer area */
330 size
= RNDUP(BUFFER_SIZE
* RX_BUFFERS
, B_PAGE_SIZE
);
331 device
->rx_buf_area
= create_area(DEVICE_NAME
" rx buffers",
332 (void **)device
->rx_buf
, B_ANY_KERNEL_ADDRESS
, size
,
333 B_32_BIT_FULL_LOCK
, B_READ_AREA
| B_WRITE_AREA
);
334 if (device
->rx_buf_area
< 0) {
335 delete_area(device
->tx_desc_area
);
336 delete_area(device
->tx_buf_area
);
337 delete_area(device
->rx_desc_area
); // sensitive to alloc ordering
338 return device
->rx_buf_area
;
340 for (i
= 1; i
< RX_BUFFERS
; i
++) {
341 device
->rx_buf
[i
] = (device
->rx_buf
[i
-1]) + BUFFER_SIZE
;
343 /* get physical address of rx buffer */
344 get_memory_map(device
->rx_buf
[0], size
, &entry
, 1);
345 device
->phys_rx_buf
= entry
.address
;
347 TRACE((DEVICE_NAME
" create rx buf area va=%p pa=%08lx sz=%lx\n",
348 device
->rx_buf
[0], device
->rx_desc
[0]->s
.rbadr
, size
));
355 init_buffers(dev_info_t
*device
)
359 /* initilize tx descriptors */
360 for (i
= 0; i
< TX_BUFFERS
; i
++) {
361 device
->tx_desc
[i
]->s
.tbadr
= device
->phys_tx_buf
+ BUFFER_SIZE
* i
;
362 device
->tx_desc
[i
]->s
.bcnt
= -BUFFER_SIZE
;
363 device
->tx_desc
[i
]->s
.status
= 0;
364 device
->tx_desc
[i
]->s
.misc
= 0UL;
365 device
->tx_desc
[i
]->s
.rsvd
= 0UL;
368 /* initialize rx descriptors */
369 for (i
= 0; i
< RX_BUFFERS
; i
++) {
370 device
->rx_desc
[i
]->s
.rbadr
= device
->phys_rx_buf
+ BUFFER_SIZE
* i
;
371 device
->rx_desc
[i
]->s
.bcnt
= -BUFFER_SIZE
;
372 // device->rx_desc[i]->s.status = 0;
373 device
->rx_desc
[i
]->s
.status
= 0x8000; /* OWN */
374 device
->rx_desc
[i
]->s
.mcnt
= 0UL;
375 device
->rx_desc
[i
]->s
.rsvd
= 0UL;
378 /* initialize frame indexes */
379 device
->tx_sent
= device
->tx_acked
= device
->rx_received
= device
->rx_acked
= 0;
386 free_buffers(dev_info_t
*device
)
388 delete_area(device
->tx_desc_area
);
389 delete_area(device
->tx_buf_area
);
390 delete_area(device
->rx_desc_area
);
391 delete_area(device
->rx_buf_area
);
396 get_mac_addr(dev_info_t
*device
)
400 TRACE((DEVICE_NAME
": Mac address: "));
402 for (i
= 0; i
< 6; i
++) {
403 device
->mac_addr
.ch
[i
] = read8(device
->reg_base
+ PCNET_APROM_OFFSET
+ i
);
404 TRACE((" %02x", device
->mac_addr
.ch
[i
]));
411 /* set hardware so all packets are received. */
413 setpromisc(dev_info_t
*device
)
415 TRACE((DEVICE_NAME
":setpormisc\n"));
417 csr_write(device
, PCNET_CSR_STATUS
, 0x0004UL
);
418 csr_write(device
, PCNET_CSR_MODE
, 0x8000UL
); /* promiscous mode */
419 csr_write(device
, PCNET_CSR_STATUS
, 0x0042UL
);
425 #define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */
428 domulti(dev_info_t
*device
, uint8
*addr
)
430 uint16 mcast_table
[4];
433 uint32 crc
, poly
= CRC_POLYNOMIAL_LE
;
435 if (device
->nmulti
== MAX_MULTI
)
438 for (i
= 0; i
< device
->nmulti
; i
++) {
439 if (memcmp(&device
->multi
[i
], addr
, sizeof(device
->multi
[i
])) == 0)
442 if (i
!= device
->nmulti
)
445 // only copy if it isn't there already
446 memcpy(&device
->multi
[i
], addr
, sizeof(device
->multi
[i
]));
449 TRACE((DEVICE_NAME
": domulti %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
450 addr
[0],addr
[1],addr
[2],addr
[3],addr
[4],addr
[5]));
452 /* clear the multicast filter */
453 mcast_table
[0] = 0; mcast_table
[1] = 0;
454 mcast_table
[2] = 0; mcast_table
[3] = 0;
457 for (i
= 0; i
< device
->nmulti
; i
++) {
458 addrs
= (uint8
*)(&(device
->multi
[i
]));
459 /* multicast address? */
464 for (byte
= 0; byte
< 6; byte
++) {
465 for (bit
= *addrs
++, j
= 0; j
< 8; j
++, bit
>>= 1) {
468 test
= ((bit
^ crc
) & 0x01);
475 mcast_table
[crc
>> 4] |= 1 << (crc
& 0xf);
478 csr_write(device
, PCNET_CSR_STATUS
, 0x0004UL
);
479 csr_write(device
, PCNET_CSR_MODE
, 0x0000UL
); /* portsel ?? */
480 csr_write(device
, PCNET_CSR_LADRF0
, mcast_table
[0]);
481 csr_write(device
, PCNET_CSR_LADRF1
, mcast_table
[1]);
482 csr_write(device
, PCNET_CSR_LADRF2
, mcast_table
[2]);
483 csr_write(device
, PCNET_CSR_LADRF3
, mcast_table
[3]);
484 csr_write(device
, PCNET_CSR_STATUS
, 0x0042UL
);
491 reset_device(dev_info_t
*device
)
493 TRACE((DEVICE_NAME
": reset_device reset the NIC hardware\n"));
495 read32(device
->reg_base
+ PCNET_RST_OFFSET
);
496 write32(device
->reg_base
+ PCNET_RST_OFFSET
, 0UL);
497 snooze(2); /* wait >1us */
502 * allocate and initialize semaphores.
505 alloc_resources(dev_info_t
*device
)
508 device
->ilock
= create_sem(0, DEVICE_NAME
" rx");
509 if (device
->ilock
< 0)
510 return device
->ilock
;
512 set_sem_owner(device
->ilock
, B_SYSTEM_TEAM
);
515 device
->olock
= create_sem(TX_BUFFERS
, DEVICE_NAME
" tx");
516 if (device
->olock
< 0) {
517 delete_sem(device
->ilock
);
518 return device
->olock
;
521 set_sem_owner(device
->olock
, B_SYSTEM_TEAM
);
523 device
->readLock
= device
->writeLock
= 0;
524 device
->blockFlg
= 0; // set blocking
531 free_resources(dev_info_t
*device
)
533 delete_sem(device
->ilock
);
534 delete_sem(device
->olock
);
538 // #pragma mark - driver API
544 TRACE((DEVICE_NAME
": init hardware\n"));
553 char devName
[DEVICE_NAME_LEN
];
556 TRACE((DEVICE_NAME
": init_driver\n"));
558 // TODO: this does not compile with our GCC 2.95.3
564 "movl $0x564d5868, %%eax; "
566 "movw $0x000a, %%cx; "
567 "movw $0x5658, %%dx; "
571 : "eax", "ecx", "edx");
573 TRACE((DEVICE_NAME
": VMware magic number %lx\n", mgc_num
));
575 if (!(mgc_num
== 0x564d5868))
580 status
= get_module(B_PCI_MODULE_NAME
, (module_info
**)&sPCI
);
585 sNumOfCards
= get_card_info(sCardInfo
);
586 if (sNumOfCards
== 0) {
587 free_card_info(sCardInfo
);
588 put_module(B_PCI_MODULE_NAME
);
592 /* create device name list*/
593 for (i
= 0; i
< sNumOfCards
; i
++) {
594 sprintf(devName
, "net/%s/%ld", DEVICE_NAME
, i
);
595 sDeviceNames
[i
] = (char *)malloc(DEVICE_NAME_LEN
);
596 strcpy(sDeviceNames
[i
], devName
);
598 sDeviceNames
[sNumOfCards
] = NULL
;
609 /* free device name list*/
610 for (i
= 0; i
< sNumOfCards
; i
++) {
611 free(sDeviceNames
[i
]);
614 /* free device list*/
615 free_card_info(sCardInfo
);
616 put_module(B_PCI_MODULE_NAME
);
621 publish_devices(void)
623 TRACE((DEVICE_NAME
": publish_devices()\n" ));
624 return (const char **)sDeviceNames
;
629 find_device(const char *name
)
633 /* find device name */
634 for (i
= 0; i
< sNumOfCards
; i
++) {
635 if (!strcmp(name
, sDeviceNames
[i
]))
636 return &sDeviceHooks
;
643 // #pragma mark - device API
647 vlance_open(const char *name
, uint32 flags
, void **cookie
)
653 /* find device name */
654 for (devID
= 0; devID
< sNumOfCards
; devID
++) {
655 if (!strcmp(name
, sDeviceNames
[devID
]))
658 if (devID
>= sNumOfCards
)
661 /* check if the device is busy and set in-use flag if not */
662 if (atomic_or(&(sOpenLock
[devID
]), 1))
665 /* allocate storage for the cookie */
666 *cookie
= device
= (dev_info_t
*)malloc(sizeof(dev_info_t
));
667 if (device
== NULL
) {
668 status
= B_NO_MEMORY
;
671 memset(device
, 0, sizeof(dev_info_t
));
673 /* setup the cookie */
674 device
->devInfo
= sCardInfo
[devID
];
675 device
->devID
= devID
;
677 TRACE((DEVICE_NAME
": open %s device=%p\n", name
, device
));
679 /* enable access to the cards address space */
680 status
= map_pci_addr(device
);
684 status
= alloc_resources(device
);
689 reset_device(device
);
691 /* allocate and initialize frame buffer rings & descriptors */
692 status
= alloc_buffers(device
);
695 status
= init_buffers(device
);
699 /* setup interrupts */
700 install_io_interrupt_handler(device
->devInfo
->u
.h0
.interrupt_line
,
701 vlance_interrupt
, *cookie
, 0);
704 TRACE((DEVICE_NAME
": hardware specific init\n"));
706 write32(device
->reg_base
+ PCNET_RDP_OFFSET
, 0UL); /* DWIO mode */
707 bcr_write(device
, PCNET_BCR_SWS
, 0x0002UL
); /* 32bit mode */
709 get_mac_addr(device
);
711 device
->init_blk
.s
.mode
= ((TX_BUFF_IDX
& 0x0f) << 28) | ((RX_BUFF_IDX
& 0x0f) << 20) | 0x0000UL
; /* TLEN, RLEN */
712 memcpy(device
->init_blk
.s
.padr
, &(device
->mac_addr
), sizeof(mac_addr_t
));
713 device
->init_blk
.s
.padr
[6] = 0;
714 device
->init_blk
.s
.padr
[7] = 0;
715 device
->init_blk
.s
.ladr
[0] = 0UL;
716 device
->init_blk
.s
.ladr
[1] = 0UL;
717 device
->init_blk
.s
.rdra
= device
->phys_rx_desc
;
718 device
->init_blk
.s
.tdra
= device
->phys_tx_desc
;
722 for (i
= 0; i
< sizeof(init_block_t
); i
++) {
723 TRACE((" %02X", *(((unsigned char *)&(device
->init_blk
)) + i
)));
728 csr_write(device
, PCNET_CSR_IADDR0
, (device
->phys_init_blk
) & 0xffffUL
); /* set init block address L */
729 csr_write(device
, PCNET_CSR_IADDR1
, (device
->phys_init_blk
) >> 16); /* set init block address H */
730 csr_write(device
, PCNET_CSR_STATUS
, 0x0001UL
); /* INIT */
731 while (!(csr_read(device
, PCNET_CSR_STATUS
) & 0x0100UL
)); /* check IDON */
732 csr_write(device
, PCNET_CSR_STATUS
, 0x0004UL
); /* STOP */
735 dprintf(DEVICE_NAME
": STATUS = %04X\n", csr_read(device
, PCNET_CSR_STATUS
));
736 dprintf(DEVICE_NAME
": IADDR0 = %04X\n", csr_read(device
, PCNET_CSR_IADDR0
));
737 dprintf(DEVICE_NAME
": IADDR1 = %04X\n", csr_read(device
, PCNET_CSR_IADDR1
));
738 dprintf(DEVICE_NAME
": MODE = %04X\n", csr_read(device
, PCNET_CSR_MODE
));
739 dprintf(DEVICE_NAME
": PADR0 = %04X\n", csr_read(device
, PCNET_CSR_PADR0
));
740 dprintf(DEVICE_NAME
": PADR1 = %04X\n", csr_read(device
, PCNET_CSR_PADR1
));
741 dprintf(DEVICE_NAME
": PADR2 = %04X\n", csr_read(device
, PCNET_CSR_PADR2
));
742 dprintf(DEVICE_NAME
": LADRF0 = %04X\n", csr_read(device
, PCNET_CSR_LADRF0
));
743 dprintf(DEVICE_NAME
": LADRF1 = %04X\n", csr_read(device
, PCNET_CSR_LADRF1
));
744 dprintf(DEVICE_NAME
": LADRF2 = %04X\n", csr_read(device
, PCNET_CSR_LADRF2
));
745 dprintf(DEVICE_NAME
": LADRF3 = %04X\n", csr_read(device
, PCNET_CSR_LADRF3
));
746 dprintf(DEVICE_NAME
": BADRL = %04X\n", csr_read(device
, PCNET_CSR_BADRL
));
747 dprintf(DEVICE_NAME
": BADRH = %04X\n", csr_read(device
, PCNET_CSR_BADRH
));
748 dprintf(DEVICE_NAME
": BADXL = %04X\n", csr_read(device
, PCNET_CSR_BADXL
));
749 dprintf(DEVICE_NAME
": BADXH = %04X\n", csr_read(device
, PCNET_CSR_BADXH
));
750 dprintf(DEVICE_NAME
": BCR18 = %04X\n", bcr_read(device
, PCNET_BCR_BSBC
));
751 dprintf(DEVICE_NAME
": BCR20 = %04X\n", bcr_read(device
, PCNET_BCR_SWS
));
753 csr_write(device
, PCNET_CSR_STATUS
, 0x7f00); /* clear int source */
754 csr_write(device
, PCNET_CSR_STATUS
, 0x0042); /* IENA, STRT */
759 free_buffers(device
);
761 free_resources(device
);
764 atomic_and(&(sOpenLock
[devID
]), 0);
770 vlance_close(void *_device
)
772 dev_info_t
*device
= (dev_info_t
*) _device
;
774 TRACE((DEVICE_NAME
": vlance_close\n"));
776 csr_write(device
, PCNET_CSR_STATUS
, 0x0004); /* STOP */
777 TRACE((DEVICE_NAME
": STATUS = %04lx\n", csr_read(device
,PCNET_CSR_STATUS
)));
779 /* release resources */
780 free_resources(device
);
787 vlance_free(void *cookie
)
789 dev_info_t
*device
= (dev_info_t
*)cookie
;
791 TRACE((DEVICE_NAME
": free %p\n", device
));
793 /* remove Interrupt Handler */
794 remove_io_interrupt_handler(device
->devInfo
->u
.h0
.interrupt_line
, vlance_interrupt
, cookie
);
796 free_buffers(device
);
798 /* device is now available again */
799 atomic_and(&(sOpenLock
[device
->devID
]), 0);
807 vlance_control(void *cookie
, uint32 op
, void *buf
, size_t len
)
809 dev_info_t
*device
= (dev_info_t
*)cookie
;
812 case ETHER_GETADDR
: {
814 TRACE((DEVICE_NAME
": control ether_getaddr\n"));
816 for (i
= 0; i
< 6; i
++) {
817 ((uint8
*)buf
)[i
] = device
->mac_addr
.ch
[i
];
822 TRACE((DEVICE_NAME
": control init\n"));
825 case ETHER_GETFRAMESIZE
:
826 TRACE((DEVICE_NAME
": control get_framesize\n"));
827 *(uint32
*)buf
= MAX_FRAME_SIZE
;
831 TRACE((DEVICE_NAME
": control add multi\n"));
832 return domulti(device
, (unsigned char *)buf
);
834 case ETHER_SETPROMISC
:
835 TRACE((DEVICE_NAME
": control set promiscuous\n"));
836 return setpromisc(device
);
839 TRACE((DEVICE_NAME
": control blocking %ld\n", *((int32
*)buf
)));
842 device
->blockFlg
= 1; // set non-blocking
844 device
->blockFlg
= 0; // set blocking
853 vlance_read(void *_device
, off_t pos
, void *buf
, size_t *len
)
855 dev_info_t
*device
= (dev_info_t
*) _device
;
863 dprintf(DEVICE_NAME
": read buf %p, len %d\n", buf
, *len
);
866 /* block until data is available (default) */
867 flags
= B_CAN_INTERRUPT
;
868 if(device
->blockFlg
) flags
|= B_RELATIVE_TIMEOUT
; // non-blocking (0-timeout)
869 status
= acquire_sem_etc(device
->ilock
, 1, flags
, 0);
870 if(status
!= B_NO_ERROR
) {
872 dprintf(DEVICE_NAME
": cannot acquire rx semaphore\n");
878 dprintf(DEVICE_NAME
": try to atomic_or readLock\n");
880 /* prevent reentrant read */
881 if(atomic_or(&device
->readLock
, 1)) {
883 dprintf(DEVICE_NAME
": cannot atomic_or readLock\n");
885 release_sem_etc(device
->ilock
, 1, 0);
890 /* hardware specific code to copy data from the NIC into buf */
891 if((device
->rx_desc
[device
->rx_acked
]->s
.status
) & 0x8000) { /* owned by controller */
893 dprintf(DEVICE_NAME
": rx desc owned by controller\n");
899 dprintf(DEVICE_NAME
": rx desc owned by host\n");
903 if(!((device
->rx_desc
[device
->rx_acked
]->s
.status
) & 0x4000)) { /* not receive error */
904 frame_size
= (device
->rx_desc
[device
->rx_acked
]->s
.mcnt
) & 0xfff;
905 if(frame_size
> *len
) frame_size
= *len
;
906 memcpy(buf
, device
->rx_buf
[device
->rx_acked
], frame_size
);
909 if(frame_size
< *len
) *len
= frame_size
;
910 device
->rx_desc
[device
->rx_acked
]->s
.mcnt
= 0;
911 device
->rx_desc
[device
->rx_acked
]->s
.status
= 0x8000; /* OWN */
912 device
->rx_acked
= (device
->rx_acked
+ 1) & (RX_BUFFERS
- 1);
915 /* release reentrant lock */
916 atomic_and(&device
->readLock
, 0);
923 vlance_write(void *_device
, off_t pos
, const void *buf
, size_t *len
)
925 dev_info_t
*device
= (dev_info_t
*)_device
;
929 TRACE((DEVICE_NAME
": write buf %p len %lu\n", buf
, *len
));
931 if (*len
> MAX_FRAME_SIZE
) {
933 dprintf(DEVICE_NAME
": write %lu > 1514 tooo long\n", *len
);
935 *len
= MAX_FRAME_SIZE
;
939 status
= acquire_sem_etc(device
->olock
, 1, B_CAN_INTERRUPT
, 0);
940 if (status
!= B_NO_ERROR
) {
945 /* prevent reentrant write */
946 if (atomic_or(&device
->writeLock
, 1)) {
947 release_sem_etc(device
->olock
, 1, 0);
952 /* hardware specific code to transmit buff */
953 if ((device
->tx_desc
[device
->tx_sent
]->s
.status
) & 0x8000) {
954 /* owned by controller */
956 dprintf(DEVICE_NAME
": tx desc owned by controller\n");
959 TRACE((DEVICE_NAME
": tx desc owned by host\n"));
961 memcpy(device
->tx_buf
[device
->tx_sent
], buf
, frame_size
);
962 device
->tx_desc
[device
->tx_sent
]->s
.bcnt
= -frame_size
;
963 // (device->tx_desc[device->tx_sent]->s.status) |= 0x8300; /* OWN, STP, ENP */
964 (device
->tx_desc
[device
->tx_sent
]->s
.status
) |= 0x9300; /* OWN, LTINT, STP, ENP */
965 device
->tx_sent
= (device
->tx_sent
+ 1) & (TX_BUFFERS
- 1);
966 csr_write(device
, PCNET_CSR_STATUS
, 0x0048UL
); /* IENA, TDMD */
969 /* release reentrant lock */
970 atomic_and(&device
->writeLock
, 0);
976 /*! LAN controller interrupt handler */
978 vlance_interrupt(void *_device
)
980 dev_info_t
*device
= (dev_info_t
*)_device
;
981 int32 handled
= B_UNHANDLED_INTERRUPT
;
982 int32 interruptStatus
;
986 dprintf(DEVICE_NAME
": ISR_ENTRY\n");
988 state
= disable_interrupts(); /* disable int state */
990 interruptStatus
= csr_read(device
, PCNET_CSR_STATUS
);
991 if (interruptStatus
& 0x0080) {
993 dprintf(DEVICE_NAME
": status %04X\n", interruptStatus
);
996 /* clear interrupts */
997 csr_write(device
, PCNET_CSR_STATUS
, 0x7f00);
999 if (interruptStatus
& 0x8000) {
1002 dprintf(DEVICE_NAME
": int error status %04lx\n", interruptStatus
);
1004 csr_write(device
, PCNET_CSR_STATUS
, 0x0004); /* STOP */
1005 init_buffers(device
);
1006 csr_write(device
, PCNET_CSR_STATUS
, 0x0001UL
); /* INIT */
1007 while(!(csr_read(device
, PCNET_CSR_STATUS
) & 0x0100UL
)); /* check IDON */
1008 csr_write(device
, PCNET_CSR_STATUS
, 0x0042); /* IENA, STRT */
1009 /* init semaphore ??? */
1010 release_sem_etc(device
->olock
, TX_BUFFERS
, B_DO_NOT_RESCHEDULE
);
1011 acquire_sem_etc(device
->ilock
, RX_BUFFERS
, B_RELATIVE_TIMEOUT
, 0);
1012 /* not count TINT & RINT ??? */
1013 interruptStatus
&= ~0x0600;
1015 if (interruptStatus
& 0x0200) { /* TINT */
1016 while (!((device
->tx_desc
[device
->tx_acked
]->s
.status
) & 0x8000)) {
1017 //dprintf(DEVICE_NAME ": rel tx sem\n");
1018 release_sem_etc(device
->olock
, 1, B_DO_NOT_RESCHEDULE
);
1019 device
->tx_acked
= (device
->tx_acked
+ 1) & (TX_BUFFERS
- 1);
1020 if(device
->tx_acked
== device
->tx_sent
) break;
1023 if (interruptStatus
& 0x0400) { /* RINT */
1024 while (!((device
->rx_desc
[device
->rx_received
]->s
.status
) & 0x8000)) {
1025 //dprintf(DEVICE_NAME ": rel rx sem\n");
1026 release_sem_etc(device
->ilock
, 1, B_DO_NOT_RESCHEDULE
);
1027 device
->rx_received
= (device
->rx_received
+ 1) & (RX_BUFFERS
- 1);
1031 handled
= B_INVOKE_SCHEDULER
; /* set because the interrupt was from the NIC, not some other device sharing the interrupt line */
1033 #if DEBUG(INTERRUPT)
1034 dprintf(DEVICE_NAME
": ISR - its ours\n");
1038 csr_write(device
, PCNET_CSR_STATUS
, 0x0042);
1040 restore_interrupts(state
); /* restore int state */