1 /* SiS 900 chip specific functions
3 * Copyright © 2001-2005 pinc Software. All Rights Reserved.
4 * Distributed under the terms of the MIT license.
9 #include <KernelExport.h>
12 #include <SupportDefs.h>
17 #include "ether_driver.h"
20 #include "interface.h"
26 uint16
sis900_resetPHY(struct sis_info
*info
);
27 void sis900_selectPHY(struct sis_info
*info
);
28 void sis900_setMode(struct sis_info
*info
, int32 mode
);
29 int32
sis900_readMode(struct sis_info
*info
);
32 // MII chip info table
34 #define PHY_ID0_SiS900_INTERNAL 0x001d
35 #define PHY_ID1_SiS900_INTERNAL 0x8000
36 #define PHY_ID0_ICS_1893 0x0015
37 #define PHY_ID1_ICS_1893 0xff40
38 #define PHY_ID0_REALTEK_8201 0x0000
39 #define PHY_ID1_REALTEK_8201 0x8200
40 #define PHY_ID0_VIA_6103 0x0101
41 #define PHY_ID1_VIA_6103 0x8f20
43 #define MII_HOME 0x0001
44 #define MII_LAN 0x0002
46 const static struct mii_chip_info
{
51 {"SiS 900 Internal MII PHY",
52 PHY_ID0_SiS900_INTERNAL
, PHY_ID1_SiS900_INTERNAL
, MII_LAN
},
53 {"SiS 7014 Physical Layer Solution",
54 0x0016, 0xf830, MII_LAN
},
55 {"AMD 79C901 10BASE-T PHY",
56 0x0000, 0x6B70, MII_LAN
},
57 {"AMD 79C901 HomePNA PHY",
58 0x0000, 0x6B90, MII_HOME
},
60 PHY_ID0_ICS_1893
, PHY_ID1_ICS_1893
, MII_LAN
},
62 0x2000, 0x5C20, MII_LAN
| MII_HOME
},
63 {"Realtek RTL8201 PHY",
64 PHY_ID0_REALTEK_8201
, PHY_ID1_REALTEK_8201
, MII_LAN
},
66 PHY_ID0_VIA_6103
, PHY_ID1_VIA_6103
, MII_LAN
},
71 /***************************** helper functions *****************************/
75 physicalAddress(volatile void *address
, uint32 length
)
79 get_memory_map((void *)address
, length
, &table
, 1);
84 /***************************** interrupt handling *****************************/
86 int32 intrCounter
= 0;
91 sis900_rxInterrupt(struct sis_info
*info
)
93 int32 handled
= B_UNHANDLED_INTERRUPT
;
94 int16 releaseRxSem
= 0;
97 acquire_spinlock(&info
->rxSpinlock
);
101 // check for packet ownership
102 for (limit
= info
->rxFree
; limit
> 0; limit
--) {
103 if (!(info
->rxDescriptor
[info
->rxInterruptIndex
].status
& SiS900_DESCR_OWN
)) {
104 // if (limit == info->rxFree)
106 //dprintf("here!\n");
112 //dprintf("received frame %d!\n",info->rxInterruptIndex);
115 info
->rxInterruptIndex
= (info
->rxInterruptIndex
+ 1) & NUM_Rx_MASK
;
118 release_spinlock(&info
->rxSpinlock
);
121 write32(info
->registers
+ SiS900_MAC_COMMAND
, SiS900_MAC_CMD_Rx_ENABLE
);
124 release_sem_etc(info
->rxSem
, releaseRxSem
, B_DO_NOT_RESCHEDULE
);
125 return B_INVOKE_SCHEDULER
;
133 sis900_txInterrupt(struct sis_info
*info
)
135 int16 releaseTxSem
= 0;
139 acquire_spinlock(&info
->txSpinlock
);
143 for (limit
= info
->txSent
; limit
> 0; limit
--) {
144 status
= info
->txDescriptor
[info
->txInterruptIndex
].status
;
146 //dprintf("txIntr: %d: mem = %lx : hardware = %lx\n",info->txInterruptIndex,
147 // physicalAddress(&info->txDescriptor[info->txInterruptIndex],sizeof(struct buffer_desc)),
148 // read32(info->registers + SiS900_MAC_Tx_DESCR));
150 /* Does the device generate extra interrupts? */
151 if (status
& SiS900_DESCR_OWN
) {
152 uint32 descriptor
= read32(info
->registers
+ SiS900_MAC_Tx_DESCR
);
156 && physicalAddress(&info
->txDescriptor
[that
],
157 sizeof(struct buffer_desc
)) != descriptor
;
160 if (that
== NUM_Tx_DESCR
)
163 //dprintf("tx busy %d: %lx (hardware status %d = %lx)!\n",info->txInterruptIndex,status,that,info->txDescriptor[that].status);
164 // if (limit == info->txSent)
166 //dprintf("oh no!\n");
173 if (status
& (SiS900_DESCR_Tx_ABORT
| SiS900_DESCR_Tx_UNDERRUN
174 | SiS900_DESCR_Tx_OOW_COLLISION
)) {
175 dprintf("tx error: %" B_PRIx32
"\n", status
);
177 info
->txDescriptor
[info
->txInterruptIndex
].status
= 0;
179 releaseTxSem
++; /* this many buffers are free */
180 info
->txInterruptIndex
= (info
->txInterruptIndex
+ 1) & NUM_Tx_MASK
;
183 if (info
->txSent
< 0 || info
->txSent
> NUM_Tx_DESCR
)
184 dprintf("ERROR interrupt: txSent = %d\n", info
->txSent
);
186 release_spinlock(&info
->txSpinlock
);
189 release_sem_etc(info
->txSem
, releaseTxSem
, B_DO_NOT_RESCHEDULE
);
190 return B_INVOKE_SCHEDULER
;
193 return B_HANDLED_INTERRUPT
;
198 sis900_interrupt(void *data
)
200 struct sis_info
*info
= data
;
201 int32 handled
= B_UNHANDLED_INTERRUPT
;
202 int16 worklimit
= 20;
206 former
= disable_interrupts();
207 acquire_spinlock(&info
->lock
);
209 while (worklimit
-- > 0) {
210 // reading the interrupt status register clears all interrupts
211 intr
= read32(info
->registers
+ SiS900_MAC_INTR_STATUS
);
215 TRACE(("************ interrupt received: %08lx **************\n", intr
));
216 intrCounter
= (intrCounter
+ 1) % 100;
217 lastIntr
[intrCounter
] = intr
;
219 // wake-up event interrupt
220 if (intr
& SiS900_INTR_WAKEUP_EVENT
) {
221 TRACE(("wake-up event received: %ld\n",
222 read32(info
->registers
+ SiS900_MAC_WAKEUP_EVENT
)));
224 // clear PM event register
225 write32(info
->registers
+ SiS900_MAC_WAKEUP_EVENT
,
226 SiS900_WAKEUP_LINK_ON
| SiS900_WAKEUP_LINK_LOSS
);
227 handled
= B_HANDLED_INTERRUPT
;
230 // receive packet interrupts
231 if (intr
& (/*SiS900_INTR_Rx_STATUS_OVERRUN |*/ SiS900_INTR_Rx_OVERRUN
|
232 SiS900_INTR_Rx_ERROR
| SiS900_INTR_Rx_OK
))
233 handled
= sis900_rxInterrupt(info
);
235 // transmit packet interrupts
236 if (intr
& (SiS900_INTR_Tx_UNDERRUN
| SiS900_INTR_Tx_ERROR
|
237 SiS900_INTR_Tx_IDLE
| SiS900_INTR_Tx_OK
))
238 handled
= sis900_txInterrupt(info
);
241 release_spinlock(&info
->lock
);
242 restore_interrupts(former
);
249 sis900_disableInterrupts(struct sis_info
*info
)
251 write32(info
->registers
+ SiS900_MAC_INTR_MASK
, 0);
252 write32(info
->registers
+ SiS900_MAC_INTR_ENABLE
, 0);
257 sis900_enableInterrupts(struct sis_info
*info
)
259 write32(info
->registers
+ SiS900_MAC_INTR_ENABLE
, 0);
261 // enable link detection
262 write32(info
->registers
+ SiS900_MAC_WAKEUP_CONTROL
,
263 SiS900_WAKEUP_LINK_ON
| SiS900_WAKEUP_LINK_LOSS
);
265 // set interrupt mask
266 write32(info
->registers
+ SiS900_MAC_INTR_MASK
,
267 //SiS900_INTR_WAKEUP_EVENT |
268 SiS900_INTR_Tx_UNDERRUN
| SiS900_INTR_Tx_ERROR
| SiS900_INTR_Tx_IDLE
| SiS900_INTR_Tx_OK
|
269 SiS900_INTR_Rx_STATUS_OVERRUN
| SiS900_INTR_Rx_OVERRUN
|
270 SiS900_INTR_Rx_ERROR
| SiS900_INTR_Rx_OK
);
272 write32(info
->registers
+ SiS900_MAC_INTR_ENABLE
,1);
276 /***************************** PHY and link mode *****************************/
281 sis900_timer(timer
*t
)
283 struct sis_info
*info
= (struct sis_info
*)t
;
285 if (!info
->autoNegotiationComplete
) {
286 int32 mode
= sis900_readMode(info
);
288 sis900_setMode(info
, mode
);
293 if (info
->link
) { // link lost
294 uint16 status
= mdio_status(info
);
296 if ((status
& MII_STATUS_LINK
) == 0) {
298 dprintf(DEVICE_NAME
": link lost\n");
300 // if it's the internal SiS900 MII PHY, reset it
301 if (info
->currentPHY
->id0
== PHY_ID0_SiS900_INTERNAL
302 && (info
->currentPHY
->id1
& 0xfff0) == PHY_ID1_SiS900_INTERNAL
)
303 sis900_resetPHY(info
);
306 if (!info
->link
) { // new link established
309 sis900_selectPHY(info
);
311 status
= mdio_status(info
);
312 if (status
& MII_STATUS_LINK
) {
313 sis900_checkMode(info
);
318 // revision = info->pciInfo->revision;
319 // if (!(revision == SiS900_REVISION_SiS630E || revision == SiS900_REVISION_SiS630EA1
320 // || revision == SiS900_REVISION_SiS630A || revision == SiS900_REVISION_SiS630ET))
321 // bug(DEVICE_NAME ": set_eq() not needed!\n");
323 // bug("********* set_eq() would be needed! ********\n");
330 sis900_resetPHY(struct sis_info
*info
)
332 uint16 status
= mdio_status(info
);
334 mdio_write(info
, MII_CONTROL
, MII_CONTROL_RESET
);
340 sis900_initPHYs(struct sis_info
*info
)
344 // search for total of 32 possible MII PHY addresses
345 for (phy
= 0; phy
< 32; phy
++) {
350 status
= mdio_statusFromPHY(info
, phy
);
351 if (status
== 0xffff || status
== 0x0000)
352 // this MII is not accessable
355 mii
= (struct mii_phy
*)malloc(sizeof(struct mii_phy
));
360 mii
->id0
= mdio_readFromPHY(info
, phy
, MII_PHY_ID0
);
361 mii
->id1
= mdio_readFromPHY(info
, phy
, MII_PHY_ID1
);
362 mii
->types
= MII_HOME
;
363 mii
->next
= info
->firstPHY
;
364 info
->firstPHY
= mii
;
366 for (i
= 0; gMIIChips
[i
].name
; i
++) {
367 if (gMIIChips
[i
].id0
!= mii
->id0
368 || gMIIChips
[i
].id1
!= (mii
->id1
& 0xfff0))
371 dprintf("Found MII PHY: %s\n", gMIIChips
[i
].name
);
373 mii
->types
= gMIIChips
[i
].types
;
376 if (gMIIChips
[i
].name
== NULL
)
377 dprintf("Unknown MII PHY transceiver: id = (%x, %x).\n", mii
->id0
, mii
->id1
);
380 if (info
->firstPHY
== NULL
) {
381 dprintf("No MII PHY transceiver found!\n");
382 return B_ENTRY_NOT_FOUND
;
385 sis900_selectPHY(info
);
387 // if the internal PHY is selected, reset it
388 if (info
->currentPHY
->id0
== PHY_ID0_SiS900_INTERNAL
389 && (info
->currentPHY
->id1
& 0xfff0) == PHY_ID1_SiS900_INTERNAL
) {
390 if (sis900_resetPHY(info
) & MII_STATUS_LINK
) {
391 uint16 poll
= MII_STATUS_LINK
;
393 poll
^= mdio_read(info
, MII_STATUS
) & poll
;
398 // workaround for ICS1893 PHY
399 if (info
->currentPHY
->id0
== PHY_ID0_ICS_1893
400 && (info
->currentPHY
->id1
& 0xfff0) == PHY_ID1_ICS_1893
)
401 mdio_write(info
, 0x0018, 0xD200);
403 // SiS 630E has some bugs on default value of PHY registers
404 if (info
->pciInfo
->revision
== SiS900_REVISION_SiS630E
) {
405 mdio_write(info
, MII_AUTONEG_ADV
, 0x05e1);
406 mdio_write(info
, MII_CONFIG1
, 0x22);
407 mdio_write(info
, MII_CONFIG2
, 0xff00);
408 mdio_write(info
, MII_MASK
, 0xffc0);
411 info
->link
= mdio_status(info
) & MII_STATUS_LINK
;
418 sis900_selectPHY(struct sis_info
*info
)
422 // ToDo: need to be changed, select PHY in relation to the link mode
423 info
->currentPHY
= info
->firstPHY
;
424 info
->phy
= info
->currentPHY
->address
;
426 status
= mdio_read(info
, MII_CONTROL
);
427 status
&= ~MII_CONTROL_ISOLATE
;
429 mdio_write(info
, MII_CONTROL
, status
);
434 sis900_setMode(struct sis_info
*info
, int32 mode
)
436 uint32 address
= info
->registers
+ SiS900_MAC_CONFIG
;
437 uint32 txFlags
= SiS900_Tx_AUTO_PADDING
| SiS900_Tx_FILL_THRES
;
440 info
->speed
= mode
& LINK_SPEED_MASK
;
441 info
->full_duplex
= (mode
& LINK_DUPLEX_MASK
) == LINK_FULL_DUPLEX
;
443 if (read32(address
) & SiS900_MAC_CONFIG_EDB_MASTER
) {
444 TRACE((DEVICE_NAME
": EDB master is set!\n"));
445 txFlags
|= 5 << SiS900_DMA_SHIFT
;
446 rxFlags
= 5 << SiS900_DMA_SHIFT
;
449 // link speed FIFO thresholds
451 if (info
->speed
== LINK_SPEED_HOME
|| info
->speed
== LINK_SPEED_10_MBIT
) {
452 rxFlags
|= SiS900_Rx_10_MBIT_DRAIN_THRES
;
453 txFlags
|= SiS900_Tx_10_MBIT_DRAIN_THRES
;
455 rxFlags
|= SiS900_Rx_100_MBIT_DRAIN_THRES
;
456 txFlags
|= SiS900_Tx_100_MBIT_DRAIN_THRES
;
461 if (info
->full_duplex
) {
462 txFlags
|= SiS900_Tx_CS_IGNORE
| SiS900_Tx_HB_IGNORE
;
463 rxFlags
|= SiS900_Rx_ACCEPT_Tx_PACKETS
;
466 write32(info
->registers
+ SiS900_MAC_Tx_CONFIG
, txFlags
);
467 write32(info
->registers
+ SiS900_MAC_Rx_CONFIG
, rxFlags
);
472 sis900_readMode(struct sis_info
*info
)
474 struct mii_phy
*phy
= info
->currentPHY
;
475 uint16 autoAdv
, autoLinkPartner
;
478 uint16 status
= mdio_status(info
);
479 if (!(status
& MII_STATUS_LINK
)) {
480 dprintf(DEVICE_NAME
": no link detected (status = %x)\n", status
);
484 // auto negotiation completed
485 autoAdv
= mdio_read(info
, MII_AUTONEG_ADV
);
486 autoLinkPartner
= mdio_read(info
, MII_AUTONEG_LINK_PARTNER
);
487 status
= autoAdv
& autoLinkPartner
;
489 speed
= status
& (MII_NWAY_TX
| MII_NWAY_TX_FDX
) ? LINK_SPEED_100_MBIT
: LINK_SPEED_10_MBIT
;
490 duplex
= status
& (MII_NWAY_TX_FDX
| MII_NWAY_T_FDX
) ? LINK_FULL_DUPLEX
: LINK_HALF_DUPLEX
;
492 info
->autoNegotiationComplete
= true;
494 // workaround for Realtek RTL8201 PHY issue
495 if (phy
->id0
== PHY_ID0_REALTEK_8201
&& (phy
->id1
& 0xFFF0) == PHY_ID1_REALTEK_8201
) {
496 if (mdio_read(info
, MII_CONTROL
) & MII_CONTROL_FULL_DUPLEX
)
497 duplex
= LINK_FULL_DUPLEX
;
498 if (mdio_read(info
, 0x0019) & 0x01)
499 speed
= LINK_SPEED_100_MBIT
;
502 dprintf(DEVICE_NAME
": linked, 10%s MBit, %s duplex\n",
503 speed
== LINK_SPEED_100_MBIT
? "0" : "",
504 duplex
== LINK_FULL_DUPLEX
? "full" : "half");
506 return speed
| duplex
;
511 sis900_setAutoNegotiationCapabilities(struct sis_info
*info
)
513 uint16 status
= mdio_status(info
);
514 uint16 capabilities
= MII_NWAY_CSMA_CD
515 | (status
& MII_STATUS_CAN_TX_FDX
? MII_NWAY_TX_FDX
: 0)
516 | (status
& MII_STATUS_CAN_TX
? MII_NWAY_TX
: 0)
517 | (status
& MII_STATUS_CAN_T_FDX
? MII_NWAY_T_FDX
: 0)
518 | (status
& MII_STATUS_CAN_T
? MII_NWAY_T
: 0);
520 TRACE((DEVICE_NAME
": write capabilities %d\n", capabilities
));
521 mdio_write(info
, MII_AUTONEG_ADV
, capabilities
);
526 sis900_autoNegotiate(struct sis_info
*info
)
528 uint16 status
= mdio_status(info
);
530 if ((status
& MII_STATUS_LINK
) == 0)
532 TRACE((DEVICE_NAME
": media link off\n"));
533 info
->autoNegotiationComplete
= true;
536 TRACE((DEVICE_NAME
": auto negotiation started...\n"));
538 // reset auto negotiation
539 mdio_write(info
, MII_CONTROL
, MII_CONTROL_AUTO
| MII_CONTROL_RESET_AUTONEG
);
540 info
->autoNegotiationComplete
= false;
545 sis900_checkMode(struct sis_info
*info
)
547 uint32 address
= info
->registers
+ SiS900_MAC_CONFIG
;
549 if (info
->fixedMode
!= 0) {
550 TRACE((DEVICE_NAME
": link mode set via settings\n"));
552 // ToDo: what about the excessive deferral timer?
554 sis900_setMode(info
, info
->fixedMode
);
555 info
->autoNegotiationComplete
= true;
556 } else if (info
->currentPHY
->types
== MII_LAN
) {
557 TRACE((DEVICE_NAME
": PHY type is LAN\n"));
559 // enable excessive deferral timer
560 write32(address
, ~SiS900_MAC_CONFIG_EXCESSIVE_DEFERRAL
& read32(address
));
562 sis900_setAutoNegotiationCapabilities(info
);
563 sis900_autoNegotiate(info
);
565 TRACE((DEVICE_NAME
": PHY type is not LAN\n"));
567 // disable excessive deferral timer
568 write32(address
, SiS900_MAC_CONFIG_EXCESSIVE_DEFERRAL
| read32(address
));
570 sis900_setMode(info
, LINK_SPEED_HOME
| LINK_HALF_DUPLEX
);
571 info
->autoNegotiationComplete
= true;
576 /***************************** MACs, rings & config *****************************/
581 sis900_getMACAddress(struct sis_info
*info
)
583 if (info
->pciInfo
->revision
>= SiS900_REVISION_SiS96x
) {
584 // SiS 962 & 963 are using a different method to access the EEPROM
585 // than the standard SiS 630
586 addr_t eepromAccess
= info
->registers
+ SiS900_MAC_EEPROM_ACCESS
;
589 write32(eepromAccess
, SiS96x_EEPROM_CMD_REQ
);
591 while (tries
< 1000) {
592 if (read32(eepromAccess
) & SiS96x_EEPROM_CMD_GRANT
) {
595 /* get MAC address from EEPROM */
596 for (i
= 0; i
< 3; i
++) {
599 id
= eeprom_read(info
, SiS900_EEPROM_MAC_ADDRESS
+ i
);
600 info
->address
.ebyte
[i
*2 + 1] = id
>> 8;
601 info
->address
.ebyte
[i
*2] = id
& 0xff;
604 write32(eepromAccess
, SiS96x_EEPROM_CMD_DONE
);
611 write32(eepromAccess
, SiS96x_EEPROM_CMD_DONE
);
613 } else if (info
->pciInfo
->revision
>= SiS900_REVISION_SiS630E
) {
614 /* SiS630E and above are using CMOS RAM to store MAC address */
618 for (index
= 0; pci
->get_nth_pci_info(index
, &isa
) == B_OK
; index
++) {
619 if (isa
.vendor_id
== VENDOR_ID_SiS
620 && isa
.device_id
== DEVICE_ID_SiS_ISA_BRIDGE
) {
622 addr_t registers
= isa
.u
.h0
.base_registers
[0];
624 reg
= pci
->read_pci_config(isa
.bus
,isa
.device
,isa
.function
,0x48,1);
625 pci
->write_pci_config(isa
.bus
,isa
.device
,isa
.function
,0x48,1,reg
| 0x40);
627 for (i
= 0; i
< 6; i
++) {
628 write8(registers
+ 0x70,0x09 + i
);
629 info
->address
.ebyte
[i
] = read8(registers
+ 0x71);
632 pci
->write_pci_config(isa
.bus
,isa
.device
,isa
.function
,0x48,1,reg
& ~0x40);
638 /* SiS630 stores the MAC in an eeprom */
642 /* check to see if we have sane EEPROM */
643 signature
= eeprom_read(info
,SiS900_EEPROM_SIGNATURE
);
644 if (signature
== 0xffff || signature
== 0x0000) {
645 dprintf(DEVICE_NAME
": cannot read EEPROM signature\n");
649 /* get MAC address from EEPROM */
650 for (i
= 0; i
< 3; i
++) {
653 id
= eeprom_read(info
,SiS900_EEPROM_MAC_ADDRESS
+ i
);
654 info
->address
.ebyte
[i
*2 + 1] = id
>> 8;
655 info
->address
.ebyte
[i
*2] = id
& 0xff;
665 sis900_reset(struct sis_info
*info
)
667 addr_t address
= info
->registers
+ SiS900_MAC_COMMAND
;
670 TRACE(("sis900 reset\n"));
672 write32(address
, SiS900_MAC_CMD_RESET
);
674 write32(info
->registers
+ SiS900_MAC_Rx_FILTER_CONTROL
, SiS900_RxF_ENABLE
|
675 SiS900_RxF_ACCEPT_ALL_BROADCAST
| SiS900_RxF_ACCEPT_ALL_MULTICAST
);
677 // wait until the chip leaves reset state
678 while ((read32(address
) & SiS900_MAC_CMD_RESET
) && tries
-- > 0)
681 write32(info
->registers
+ SiS900_MAC_COMMAND
, SiS900_MAC_CMD_Tx_ENABLE
);
688 sis900_setPromiscuous(struct sis_info
*info
, bool on
)
690 addr_t filterControl
= info
->registers
+ SiS900_MAC_Rx_FILTER_CONTROL
;
691 int32 filter
= read32(filterControl
);
693 // accept all incoming packets (or not)
695 write32(filterControl
, SiS900_RxF_ENABLE
|
696 SiS900_RxF_ACCEPT_ALL_BROADCAST
| SiS900_RxF_ACCEPT_ALL_MULTICAST
);
698 write32(filterControl
, filter
| ~SiS900_RxF_ACCEPT_ALL_ADDRESSES
);
703 sis900_setRxFilter(struct sis_info
*info
)
705 addr_t filterControl
= info
->registers
+ SiS900_MAC_Rx_FILTER_CONTROL
;
706 addr_t filterData
= info
->registers
+ SiS900_MAC_Rx_FILTER_DATA
;
709 // set MAC address as receive filter
710 for (i
= 0; i
< 3; i
++) {
711 write32(filterControl
, i
<< SiS900_Rx_FILTER_ADDRESS_SHIFT
);
712 write32(filterData
, info
->address
.ebyte
[i
*2] | (info
->address
.ebyte
[i
*2 + 1] << 8));
714 write32(filterControl
, SiS900_RxF_ENABLE
715 | SiS900_RxF_ACCEPT_ALL_BROADCAST
716 | SiS900_RxF_ACCEPT_ALL_MULTICAST
/*| SiS900_RxF_ACCEPT_ALL_ADDRESSES*/);
721 sis900_deleteRings(struct sis_info
*info
)
723 delete_area(info
->txArea
);
724 delete_area(info
->rxArea
);
729 sis900_createRings(struct sis_info
*info
)
733 // create transmit buffer area
734 info
->txArea
= create_area("sis900 tx buffer", (void **)&info
->txBuffer
[0],
735 B_ANY_KERNEL_ADDRESS
,
736 ROUND_TO_PAGE_SIZE(BUFFER_SIZE
* NUM_Tx_DESCR
),
737 B_32_BIT_FULL_LOCK
, B_READ_AREA
| B_WRITE_AREA
);
738 if (info
->txArea
< B_OK
)
741 // initialize transmit buffer descriptors
742 for (i
= 1; i
< NUM_Tx_DESCR
; i
++)
743 info
->txBuffer
[i
] = (void *)(((addr_t
)info
->txBuffer
[0]) + (i
* BUFFER_SIZE
));
745 for (i
= 0; i
< NUM_Tx_DESCR
; i
++) {
746 info
->txDescriptor
[i
].status
= 0;
747 info
->txDescriptor
[i
].buffer
= physicalAddress(info
->txBuffer
[i
], BUFFER_SIZE
);
748 info
->txDescriptor
[i
].link
=
749 #if (NUM_Tx_DESCR == 1)
752 physicalAddress(&info
->txDescriptor
[(i
+ 1) & NUM_Tx_MASK
], sizeof(struct buffer_desc
));
756 // create receive buffer area
757 info
->rxArea
= create_area("sis900 rx buffer", (void **)&info
->rxBuffer
[0],
758 B_ANY_KERNEL_ADDRESS
,
759 ROUND_TO_PAGE_SIZE(BUFFER_SIZE
* NUM_Rx_DESCR
),
760 B_32_BIT_FULL_LOCK
, B_READ_AREA
| B_WRITE_AREA
);
761 if (info
->rxArea
< B_OK
) {
762 delete_area(info
->txArea
);
766 // initialize receive buffer descriptors
767 for (i
= 1; i
< NUM_Rx_DESCR
; i
++)
768 info
->rxBuffer
[i
] = (void *)(((addr_t
)info
->rxBuffer
[0]) + (i
* BUFFER_SIZE
));
770 for (i
= 0; i
< NUM_Rx_DESCR
; i
++) {
771 info
->rxDescriptor
[i
].status
= MAX_FRAME_SIZE
;
772 info
->rxDescriptor
[i
].buffer
= physicalAddress(info
->rxBuffer
[i
], BUFFER_SIZE
);
773 info
->rxDescriptor
[i
].link
= physicalAddress(&info
->rxDescriptor
[(i
+ 1) & NUM_Rx_MASK
],
774 sizeof(struct buffer_desc
));
776 info
->rxFree
= NUM_Rx_DESCR
;
778 // set descriptor pointer registers
779 write32(info
->registers
+ SiS900_MAC_Tx_DESCR
,
780 physicalAddress(&info
->txDescriptor
[0], sizeof(struct buffer_desc
)));
781 write32(info
->registers
+ SiS900_MAC_Rx_DESCR
,
782 physicalAddress(&info
->rxDescriptor
[0], sizeof(struct buffer_desc
)));