staticvoid e100_hw_reset(struct nic *nic)
{ /* Put CU and RU into idle with a selective reset to get
* device off of PCI bus */
iowrite32(selective_reset, &nic->csr->port);
e100_write_flush(nic); udelay(20);
/* Now fully reset device */
iowrite32(software_reset, &nic->csr->port);
e100_write_flush(nic); udelay(20);
/* Mask off our interrupt line - it's unmasked after reset */
e100_disable_irq(nic);
}
/* General technique stolen from the eepro100 driver - very clever */ static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
{
u32 cmd_addr_data;
u16 data = 0;
u8 ctrl; int i;
/* Eeprom drives a dummy zero to EEDO after receiving
* complete address. Use this to adjust addr_len. */
ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); if (!(ctrl & eedo) && i > 16) {
*addr_len -= (i - 16);
i = 17;
}
/* The checksum, stored in the last word, is calculated such that
* the sum of words should be 0xBABA */ if (cpu_to_le16(0xBABA - checksum) != nic->eeprom[nic->eeprom_wc - 1]) {
netif_err(nic, probe, nic->netdev, "EEPROM corrupted\n"); if (!eeprom_bad_csum_allow) return -EAGAIN;
}
return0;
}
/* Save (portion of) driver EEPROM cache to device and update checksum */ staticint e100_eeprom_save(struct nic *nic, u16 start, u16 count)
{
u16 addr, addr_len = 8, checksum = 0;
/* Try reading with an 8-bit addr len to discover actual addr len */
e100_eeprom_read(nic, &addr_len, 0);
nic->eeprom_wc = 1 << addr_len;
if (start + count >= nic->eeprom_wc) return -EINVAL;
/* The checksum, stored in the last word, is calculated such that
* the sum of words should be 0xBABA */ for (addr = 0; addr < nic->eeprom_wc - 1; addr++)
checksum += le16_to_cpu(nic->eeprom[addr]);
nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum);
e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1,
nic->eeprom[nic->eeprom_wc - 1]);
return0;
}
#define E100_WAIT_SCB_TIMEOUT 20000/* we might have to wait 100ms!!! */ #define E100_WAIT_SCB_FAST 20/* delay like the old code */ staticint e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr)
{ unsignedlong flags; unsignedint i; int err = 0;
spin_lock_irqsave(&nic->cmd_lock, flags);
/* Previous command is accepted when SCB clears */ for (i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { if (likely(!ioread8(&nic->csr->scb.cmd_lo))) break;
cpu_relax(); if (unlikely(i > E100_WAIT_SCB_FAST))
udelay(5);
} if (unlikely(i == E100_WAIT_SCB_TIMEOUT)) {
err = -EAGAIN; goto err_unlock;
}
if (unlikely(cmd != cuc_resume))
iowrite32(dma_addr, &nic->csr->scb.gen_ptr);
iowrite8(cmd, &nic->csr->scb.cmd_lo);
err = cb_prepare(nic, cb, skb); if (err) goto err_unlock;
if (unlikely(!nic->cbs_avail))
err = -ENOSPC;
/* Order is important otherwise we'll be in a race with h/w:
* set S-bit in current first, then clear S-bit in previous. */
cb->command |= cpu_to_le16(cb_s);
dma_wmb();
cb->prev->command &= cpu_to_le16(~cb_s);
while (nic->cb_to_send != nic->cb_to_use) { if (unlikely(e100_exec_cmd(nic, nic->cuc_cmd,
nic->cb_to_send->dma_addr))) { /* Ok, here's where things get sticky. It's *possiblethatwecan'tschedulethecommand *becausethecontrolleristoobusy,so *let'sjustqueuethecommandandtryagain
* when another command is scheduled. */ if (err == -ENOSPC) { //request a reset
schedule_work(&nic->tx_timeout_task);
} break;
} else {
nic->cuc_cmd = cuc_resume;
nic->cb_to_send = nic->cb_to_send->next;
}
}
/* the standard mdio_ctrl() function for usual MII-compliant hardware */ static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data)
{
u32 data_out = 0; unsignedint i; unsignedlong flags;
/* *Stratus87247:weshouldn'tbewritingtheMDIcontrol *registeruntiltheReadybitshowsTrue.Also,since *manipulationoftheMDIcontrolregistersisamulti-step *procedureitshouldbedoneunderlock.
*/
spin_lock_irqsave(&nic->mdio_lock, flags); for (i = 100; i; --i) { if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready) break;
udelay(20);
} if (unlikely(!i)) {
netdev_err(nic->netdev, "e100.mdio_ctrl won't go Ready\n");
spin_unlock_irqrestore(&nic->mdio_lock, flags); return0; /* No way to indicate timeout error */
}
iowrite32((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl);
for (i = 0; i < 100; i++) {
udelay(20); if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready) break;
}
spin_unlock_irqrestore(&nic->mdio_lock, flags);
netif_printk(nic, hw, KERN_DEBUG, nic->netdev, "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n",
dir == mdi_read ? "READ" : "WRITE",
addr, reg, data, data_out); return (u16)data_out;
}
/* slightly tweaked mdio_ctrl() function for phy_82552_v specifics */ static u16 mdio_ctrl_phy_82552_v(struct nic *nic,
u32 addr,
u32 dir,
u32 reg,
u16 data)
{ if ((reg == MII_BMCR) && (dir == mdi_write)) { if (data & (BMCR_ANRESTART | BMCR_ANENABLE)) {
u16 advert = mdio_read(nic->netdev, nic->mii.phy_id,
MII_ADVERTISE);
/* *WorkaroundSiissuewheresometimesthepartwillnot *autonegto100Mbpsevenwhenadvertised.
*/ if (advert & ADVERTISE_100FULL)
data |= BMCR_SPEED100 | BMCR_FULLDPLX; elseif (advert & ADVERTISE_100HALF)
data |= BMCR_SPEED100;
}
} return mdio_ctrl_hw(nic, addr, dir, reg, data);
}
/* Fully software-emulated mdio_ctrl() function for cards without *MII-compliantPHYs. *Fornow,thisismainlygearedtowards80c24support;incaseoffurther *requirementsforothertypes(i82503,...?)eitherextendthismechanism *orsplitit,whicheveriscleaner.
*/ static u16 mdio_ctrl_phy_mii_emulated(struct nic *nic,
u32 addr,
u32 dir,
u32 reg,
u16 data)
{ /* might need to allocate a netdev_priv'ed register array eventually *tobeabletorecordstatechanges,butfornow
* some fully hardcoded register handling ought to be ok I guess. */
if (dir == mdi_read) { switch (reg) { case MII_BMCR: /* Auto-negotiation, right? */ return BMCR_ANENABLE |
BMCR_FULLDPLX; case MII_BMSR: return BMSR_LSTATUS /* for mii_link_ok() */ |
BMSR_ANEGCAPABLE |
BMSR_10FULL; case MII_ADVERTISE: /* 80c24 is a "combo card" PHY, right? */ return ADVERTISE_10HALF |
ADVERTISE_10FULL; default:
netif_printk(nic, hw, KERN_DEBUG, nic->netdev, "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n",
dir == mdi_read ? "READ" : "WRITE",
addr, reg, data); return0xFFFF;
}
} else { switch (reg) { default:
netif_printk(nic, hw, KERN_DEBUG, nic->netdev, "%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n",
dir == mdi_read ? "READ" : "WRITE",
addr, reg, data); return0xFFFF;
}
}
} staticinlineint e100_phy_supports_mii(struct nic *nic)
{ /* for now, just check it by comparing whether we areusingMIIsoftwareemulation.
*/ return (nic->mdio_ctrl != mdio_ctrl_phy_mii_emulated);
}
/* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */
nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; if (nic->mac == mac_unknown)
nic->mac = mac_82557_D100_A;
nic->params.rfds = rfds;
nic->params.cbs = cbs;
/* Quadwords to DMA into FIFO before starting frame transmit */
nic->tx_threshold = 0xE0;
/* no interrupt for every tx completion, delay = 256us if not 557 */
nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf |
((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i));
/* Template for a freshly allocated RFD */
nic->blank_rfd.command = 0;
nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF);
nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN + ETH_FCS_LEN);
/* if you wish to disable the ucode functionality, while maintaining the *workaroundsitprovides,setthefollowingdefinesto: *BUNDLESMALL0 *BUNDLEMAX1 *INTDELAY1
*/ #define BUNDLESMALL 1 #define BUNDLEMAX (u16)6 #define INTDELAY (u16)1536/* 0x600 */
/* do not load u-code for ICH devices */ if (nic->flags & ich) return NULL;
/* Search for ucode match against h/w revision * *BasedoncommentsinthesourcecodefortheFreeBSDfxp *driver,theFIRMWARE_D102EucodeincludesbothCPUSaverand * *"fixesforbugsintheB-stephardware(specifically,bugs *withInlineReceive)." * *Sowemustfailifitcannotbeloaded. * *Theothermicrocodefilesareonlyrequiredfortheoptional *CPUSaverfeature.Nicetohave,butnoreasontofail.
*/ if (nic->mac == mac_82559_D101M) {
fw_name = FIRMWARE_D101M;
} elseif (nic->mac == mac_82559_D101S) {
fw_name = FIRMWARE_D101S;
} elseif (nic->mac == mac_82551_F || nic->mac == mac_82551_10) {
fw_name = FIRMWARE_D102E;
required = true;
} else { /* No ucode on other devices */ return NULL;
}
/* If the firmware has not previously been loaded, request a pointer *toit.Ifitwaspreviouslyloaded,wearereinitializingthe *adapter,possiblyinaresumefromhibernate,inwhichcase *request_firmware()cannotbeused.
*/ if (!fw)
err = request_firmware(&fw, fw_name, &nic->pdev->dev);
staticinlineint e100_load_ucode_wait(struct nic *nic)
{ conststruct firmware *fw; int err = 0, counter = 50; struct cb *cb = nic->cb_to_clean;
fw = e100_request_firmware(nic); /* If it's NULL, then no ucode is required */ if (IS_ERR_OR_NULL(fw)) return PTR_ERR_OR_ZERO(fw);
if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode)))
netif_err(nic, probe, nic->netdev, "ucode cmd failed with error %d\n", err);
/* must restart cuc */
nic->cuc_cmd = cuc_start;
/* wait for completion */
e100_write_flush(nic);
udelay(10);
/* wait for possibly (ouch) 500ms */ while (!(cb->status & cpu_to_le16(cb_complete))) {
msleep(10); if (!--counter) break;
}
/* ack any interrupts, something could have been set */
iowrite8(~0, &nic->csr->scb.stat_ack);
/* if the command failed, or is not OK, notify and return */ if (!counter || !(cb->status & cpu_to_le16(cb_ok))) {
netif_err(nic, probe, nic->netdev, "ucode load failed\n");
err = -EPERM;
}
switch (phy_type) { case NoSuchPhy: /* Non-MII PHY; UNTESTED! */ case I82503: /* Non-MII PHY; UNTESTED! */ case S80C24: /* Non-MII PHY; tested and working */ /* paragraph from the FreeBSD driver, "FXP_PHY_80C24": *TheSeeq80c24AutoDUPLEX(tm)EthernetInterfaceAdapter *doesn'thaveaprogramminginterfaceofanysort.The *mediaissensedautomaticallybasedonhowthelinkpartner *isconfigured.Thisis,inessence,manualconfiguration.
*/
netif_info(nic, probe, nic->netdev, "found MII-less i82503 or 80c24 or other PHY\n");
nic->mdio_ctrl = mdio_ctrl_phy_mii_emulated;
nic->mii.phy_id = 0; /* is this ok for an MII-less PHY? */
/* these might be needed for certain MII-less cards... *nic->flags|=ich;
* nic->flags |= ich_10h_workaround; */
staticvoid e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex)
{ /* Adjust inter-frame-spacing (IFS) between two transmits if
* we're getting collisions on a half-duplex connection. */
if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) {
netdev_info(nic->netdev, "NIC Link is Up %u Mbps %s Duplex\n",
speed == SPEED_100 ? 100 : 10,
cmd.duplex == DUPLEX_FULL ? "Full" : "Half");
} elseif (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) {
netdev_info(nic->netdev, "NIC Link is Down\n");
}
mii_check_link(&nic->mii);
/* Software generated interrupt to recover from (rare) Rx *allocationfailure. *Unfortunatelyhavetouseaspinlocktonotre-enableinterrupts *accidentally,duetohardwarethatsharesaregisterbetweenthe
* interrupt mask bit and the SW Interrupt generation bit */
spin_lock_irq(&nic->cmd_lock);
iowrite8(ioread8(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi);
e100_write_flush(nic);
spin_unlock_irq(&nic->cmd_lock);
dma_addr = dma_map_single(&nic->pdev->dev, skb->data, skb->len,
DMA_TO_DEVICE); /* If we can't map the skb, have the upper layer try later */ if (dma_mapping_error(&nic->pdev->dev, dma_addr)) return -ENOMEM;
static netdev_tx_t e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{ struct nic *nic = netdev_priv(netdev); int err;
if (nic->flags & ich_10h_workaround) { /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. IssueaNOPcommandfollowedbya1usdelaybefore
issuing the Tx command. */ if (e100_exec_cmd(nic, cuc_nop, 0))
netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, "exec cuc_nop failed\n");
udelay(1);
}
err = e100_exec_cb(nic, skb, e100_xmit_prepare);
switch (err) { case -ENOSPC: /* We queued the skb, but now we're out of space. */
netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, "No space for CB\n");
netif_stop_queue(netdev); break; case -ENOMEM: /* This is a hard error - log it. */
netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev, "Out of Tx resources, returning skb\n");
netif_stop_queue(netdev); return NETDEV_TX_BUSY;
}
return NETDEV_TX_OK;
}
staticint e100_tx_clean(struct nic *nic)
{ struct net_device *dev = nic->netdev; struct cb *cb; int tx_cleaned = 0;
spin_lock(&nic->cb_lock);
/* Clean CBs marked complete */ for (cb = nic->cb_to_clean;
cb->status & cpu_to_le16(cb_complete);
cb = nic->cb_to_clean = cb->next) {
dma_rmb(); /* read skb after status */
netif_printk(nic, tx_done, KERN_DEBUG, nic->netdev, "cb[%d]->status = 0x%04X\n",
(int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)),
cb->status);
if (likely(cb->skb != NULL)) {
dev->stats.tx_packets++;
dev->stats.tx_bytes += cb->skb->len;
/* Recover from running out of Tx resources in xmit_frame */ if (unlikely(tx_cleaned && netif_queue_stopped(nic->netdev)))
netif_wake_queue(nic->netdev);
staticinlinevoid e100_start_receiver(struct nic *nic, struct rx *rx)
{ if (!nic->rxs) return; if (RU_SUSPENDED != nic->ru_running) return;
/* handle init time starts */ if (!rx) rx = nic->rxs;
/* (Re)start RU if suspended or idle and RFA is non-NULL */ if (rx->skb) {
e100_exec_cmd(nic, ruc_start, rx->dma_addr);
nic->ru_running = RU_RUNNING;
}
}
/* Link the RFD to end of RFA by linking previous RFD to *thisone.WearesafetotouchthepreviousRFDbecause
* it is protected by the before last buffer's el bit being set */ if (rx->prev->skb) { struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data;
put_unaligned_le32(rx->dma_addr, &prev_rfd->link);
dma_sync_single_for_device(&nic->pdev->dev,
rx->prev->dma_addr, sizeof(struct rfd),
DMA_BIDIRECTIONAL);
}
if (unlikely(work_done && *work_done >= work_to_do)) return -EAGAIN;
/* Need to sync before taking a peek at cb_complete bit */
dma_sync_single_for_cpu(&nic->pdev->dev, rx->dma_addr, sizeof(struct rfd), DMA_BIDIRECTIONAL);
rfd_status = le16_to_cpu(rfd->status);
netif_printk(nic, rx_status, KERN_DEBUG, nic->netdev, "status=0x%04X\n", rfd_status);
dma_rmb(); /* read size after status bit */
/* If data isn't ready, nothing to indicate */ if (unlikely(!(rfd_status & cb_complete))) { /* If the next buffer has the el bit, but we think the receiver *isstillrunning,checktoseeifitreallystoppedwhile *wehadinterruptsoff. *Thisallowsforafastrestartwithoutre-enabling
* interrupts */ if ((le16_to_cpu(rfd->command) & cb_el) &&
(RU_RUNNING == nic->ru_running))
/* Get actual data size */ if (unlikely(dev->features & NETIF_F_RXFCS))
fcs_pad = 4;
actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd)))
actual_size = RFD_BUF_LEN - sizeof(struct rfd);
/* Get data */
dma_unmap_single(&nic->pdev->dev, rx->dma_addr, RFD_BUF_LEN,
DMA_BIDIRECTIONAL);
/* If this buffer has the el bit, but we think the receiver *isstillrunning,checktoseeifitreallystoppedwhile *wehadinterruptsoff. *Thisallowsforafastrestartwithoutre-enablinginterrupts. *ThiscanhappenwhentheRUseesthesizechangebutalsosees
* the el bit set. */ if ((le16_to_cpu(rfd->command) & cb_el) &&
(RU_RUNNING == nic->ru_running)) {
if (ioread8(&nic->csr->scb.status) & rus_no_res)
nic->ru_running = RU_SUSPENDED;
}
/* Pull off the RFD and put the actual data (minus eth hdr) */
skb_reserve(skb, sizeof(struct rfd));
skb_put(skb, actual_size);
skb->protocol = eth_type_trans(skb, nic->netdev);
/* If we are receiving all frames, then don't bother *checkingforerrors.
*/ if (unlikely(dev->features & NETIF_F_RXALL)) { if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN + fcs_pad) /* Received oversized frame, but keep it. */
nic->rx_over_length_errors++; goto process_skb;
}
/* Indicate newly arrived packets */ for (rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) {
err = e100_rx_indicate(nic, rx, work_done, work_to_do); /* Hit quota or no more to clean */ if (-EAGAIN == err || -ENODATA == err) break;
}
/* On EAGAIN, hit quota so have more work to do, restart once *cleanupiscomplete. *Else,arewealreadyrnr?thenpayattention!!!thisensuresthat *thestatemachineprogressionneverallowsastartwitha *partiallycleanedlist,avoidingaracebetweenhardware
* and rx_to_clean when in NAPI mode */ if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running)
restart_required = 1;
/* Alloc new skbs to refill list */ for (rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { if (unlikely(e100_rx_alloc_skb(nic, rx))) break; /* Better luck next time (see watchdog) */
}
new_before_last_rx = nic->rx_to_use->prev->prev; if (new_before_last_rx != old_before_last_rx) { /* Set the el-bit on the buffer that is before the last buffer. *Thisletsusupdatethenextpointeronthelastbuffer *withoutworryingabouthardwaretouchingit. *Wesetthesizeto0topreventhardwarefromtouchingthis *buffer. *Whenthehardwarehitsthebeforelastbufferwithel-bit *andsizeof0,itwillRNRinterrupt,theRUSwillgointo *theNoResourcesstate.Itwillnotcompletenorwriteto
* this buffer. */
new_before_last_rfd =
(struct rfd *)new_before_last_rx->skb->data;
new_before_last_rfd->size = 0;
new_before_last_rfd->command |= cpu_to_le16(cb_el);
dma_sync_single_for_device(&nic->pdev->dev,
new_before_last_rx->dma_addr, sizeof(struct rfd),
DMA_BIDIRECTIONAL);
/* Now that we have a new stopping point, we can clear the old *stoppingpoint.Wemustsynctwicetogettheproper
* ordering on the hardware side of things. */
old_before_last_rfd->command &= ~cpu_to_le16(cb_el);
dma_sync_single_for_device(&nic->pdev->dev,
old_before_last_rx->dma_addr, sizeof(struct rfd),
DMA_BIDIRECTIONAL);
old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN
+ ETH_FCS_LEN);
dma_sync_single_for_device(&nic->pdev->dev,
old_before_last_rx->dma_addr, sizeof(struct rfd),
DMA_BIDIRECTIONAL);
}
if (restart_required) { // ack the rnr?
iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack);
e100_start_receiver(nic, nic->rx_to_clean); if (work_done)
(*work_done)++;
}
}
staticvoid e100_rx_clean_list(struct nic *nic)
{ struct rx *rx; unsignedint i, count = nic->params.rfds.count;
nic->ru_running = RU_UNINITIALIZED;
if (nic->rxs) { for (rx = nic->rxs, i = 0; i < count; rx++, i++) { if (rx->skb) {
dma_unmap_single(&nic->pdev->dev,
rx->dma_addr, RFD_BUF_LEN,
DMA_BIDIRECTIONAL);
dev_kfree_skb(rx->skb);
}
}
kfree(nic->rxs);
nic->rxs = NULL;
}
nic->rx_to_use = nic->rx_to_clean = NULL;
}
staticint e100_rx_alloc_list(struct nic *nic)
{ struct rx *rx; unsignedint i, count = nic->params.rfds.count; struct rfd *before_last;
if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_KERNEL))) return -ENOMEM;
for (rx = nic->rxs, i = 0; i < count; rx++, i++) {
rx->next = (i + 1 < count) ? rx + 1 : nic->rxs;
rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; if (e100_rx_alloc_skb(nic, rx)) {
e100_rx_clean_list(nic); return -ENOMEM;
}
} /* Set the el-bit on the buffer that is before the last buffer. *Thisletsusupdatethenextpointeronthelastbufferwithout *worryingabouthardwaretouchingit. *Wesetthesizeto0topreventhardwarefromtouchingthisbuffer. *Whenthehardwarehitsthebeforelastbufferwithel-bitandsize *of0,itwillRNRinterrupt,theRUwillgointotheNoResources
* state. It will not complete nor write to this buffer. */
rx = nic->rxs->prev->prev;
before_last = (struct rfd *)rx->skb->data;
before_last->command |= cpu_to_le16(cb_el);
before_last->size = 0;
dma_sync_single_for_device(&nic->pdev->dev, rx->dma_addr, sizeof(struct rfd), DMA_BIDIRECTIONAL);
rtnl_lock(); if (netif_running(netdev)) {
e100_down(netdev_priv(netdev));
e100_up(netdev_priv(netdev));
}
rtnl_unlock();
}
staticint e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
{ int err; struct sk_buff *skb;
/* Use driver resources to perform internal MAC or PHY *loopbacktest.Asinglepacketispreparedandtransmitted *inloopbackmode,andthetestpassesifthereceived
* packet compares byte-for-byte to the transmitted packet. */
if ((err = e100_rx_alloc_list(nic))) return err; if ((err = e100_alloc_cbs(nic))) goto err_clean_rx;
/* ICH PHY loopback is broken so do MAC loopback instead */ if (nic->flags & ich && loopback_mode == lb_phy)
loopback_mode = lb_mac;
nic->loopback = loopback_mode; if ((err = e100_hw_init(nic))) goto err_loopback_none;
if (loopback_mode == lb_phy)
mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR,
BMCR_LOOPBACK);
#define MII_LED_CONTROL 0x1B #define E100_82552_LED_OVERRIDE 0x19 #define E100_82552_LED_ON 0x000F /* LEDTX and LED_RX both on */ #define E100_82552_LED_OFF 0x000A /* LEDTX and LED_RX both off */
/* We know the number of registers, and the size of the dump buffer. *Calculatethetotalsizeinbytes.
*/ return (1 + E100_PHY_REGS) * sizeof(u32) + sizeof(nic->mem->dump_buf);
}
if (ent->driver_data)
nic->flags |= ich; else
nic->flags &= ~ich;
e100_get_defaults(nic);
/* D100 MAC doesn't allow rx of vlan packets with normal MTU */ if (nic->mac < mac_82558_D101_A4)
netdev->features |= NETIF_F_VLAN_CHALLENGED;
/* locks must be initialized before calling hw_reset */
spin_lock_init(&nic->cb_lock);
spin_lock_init(&nic->cmd_lock);
spin_lock_init(&nic->mdio_lock);
/* Reset the device before pci_set_master() in case device is in some *funkystateandhasaninterruptpending-hint:wedon'thavethe
* interrupt handler registered yet. */
e100_hw_reset(nic);
if ((err = e100_eeprom_load(nic))) goto err_out_free;
e100_phy_init(nic);
eth_hw_addr_set(netdev, (u8 *)nic->eeprom); if (!is_valid_ether_addr(netdev->dev_addr)) { if (!eeprom_bad_csum_allow) {
netif_err(nic, probe, nic->netdev, "Invalid MAC address from EEPROM, aborting\n");
err = -EAGAIN; goto err_out_free;
} else {
netif_err(nic, probe, nic->netdev, "Invalid MAC address from EEPROM, you MUST configure one.\n");
}
}
/* Wol magic packet can be enabled from eeprom */ if ((nic->mac >= mac_82558_D101_A4) &&
(le16_to_cpu(nic->eeprom[eeprom_id]) & eeprom_id_wol)) {
nic->flags |= wol_magic;
device_set_wakeup_enable(&pdev->dev, true);
}
/* ack any pending wake events, disable PME */
pci_pme_active(pdev, false);
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.72Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-10-02)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.