#if DEBUGGING staticunsignedint net_debug = DEBUGGING; #else #define net_debug 0/* gcc will remove all the debug code for us */ #endif
/* The number of low I/O ports used by the ethercard. */ #define NETCARD_IO_EXTENT 16
/* we allow the user to override various values normally set in the EEPROM */ #define FORCE_RJ45 0x0001 /* pick one of these three */ #define FORCE_AUI 0x0002 #define FORCE_BNC 0x0004
#define FORCE_AUTO 0x0010 /* pick one of these three */ #define FORCE_HALF 0x0020 #define FORCE_FULL 0x0030
/* Information that need to be kept for each board. */ struct net_local { int chip_type; /* one of: CS8900, CS8920, CS8920M */ char chip_revision; /* revision letter of the chip ('A'...) */ int send_cmd; /* the proper send command: TX_NOW, TX_AFTER_381, or TX_AFTER_ALL */ int auto_neg_cnf; /* auto-negotiation word from EEPROM */ int adapter_cnf; /* adapter configuration from EEPROM */ int isa_config; /* ISA configuration from EEPROM */ int irq_map; /* IRQ map from EEPROM */ int rx_mode; /* what mode are we in? 0, RX_MULTCAST_ACCEPT, or RX_ALL_ACCEPT */ int curr_rx_cfg; /* a copy of PP_RxCFG */ int linectl; /* either 0 or LOW_RX_SQUELCH, depending on configuration. */ int send_underrun; /* keep track of how many underruns in a row we get */ int force; /* force various values; see FORCE* above. */
spinlock_t lock; void __iomem *virt_addr;/* CS89x0 virtual address. */ #if ALLOW_DMA int use_dma; /* Flag: we're using dma */ int dma; /* DMA channel */ int dmasize; /* 16 or 64 */ unsignedchar *dma_buff; /* points to the beginning of the buffer */ unsignedchar *end_dma_buff; /* points to the end of the buffer */ unsignedchar *rx_dma_ptr; /* points to the next packet */ #endif
};
/* Example routines you must write ;->. */ #define tx_done(dev) 1
staticint __init
wait_eeprom_ready(struct net_device *dev)
{ unsignedlong timeout = jiffies; /* check to see if the EEPROM is ready, *atimeoutisusedjustincaseEEPROMisreadywhen *SI_BUSYinthePP_SelfSTisclear
*/ while (readreg(dev, PP_SelfST) & SI_BUSY) if (time_after_eq(jiffies, timeout + 40)) return -1; return0;
}
staticint __init
get_eeprom_data(struct net_device *dev, int off, int len, int *buffer)
{ int i;
cs89_dbg(3, info, "EEPROM data from %x for %x:", off, len); for (i = 0; i < len; i++) { if (wait_eeprom_ready(dev) < 0) return -1; /* Now send the EEPROM read command and EEPROM location to read */
writereg(dev, PP_EECMD, (off + i) | EEPROM_READ_CMD); if (wait_eeprom_ready(dev) < 0) return -1;
buffer[i] = readreg(dev, PP_EEData);
cs89_dbg(3, cont, " %04x", buffer[i]);
}
cs89_dbg(3, cont, "\n"); return0;
}
staticint __init
get_eeprom_cksum(int off, int len, int *buffer)
{ int i, cksum;
cksum = 0; for (i = 0; i < len; i++)
cksum += buffer[i];
cksum &= 0xffff; if (cksum == 0) return0; return -1;
}
staticvoid
write_irq(struct net_device *dev, int chip_type, int irq)
{ int i;
if (chip_type == CS8900) { #if IS_ENABLED(CONFIG_CS89x0_ISA) /* Search the mapping table for the corresponding IRQ pin. */ for (i = 0; i != ARRAY_SIZE(cs8900_irq_map); i++) if (cs8900_irq_map[i] == irq) break; /* Not found */ if (i == ARRAY_SIZE(cs8900_irq_map))
i = 3; #else /* INTRQ0 pin is used for interrupt generation. */
i = 0; #endif
writereg(dev, PP_CS8900_ISAINT, i);
} else {
writereg(dev, PP_CS8920_ISAINT, irq);
}
}
staticvoid
count_rx_errors(int status, struct net_device *dev)
{
dev->stats.rx_errors++; if (status & RX_RUNT)
dev->stats.rx_length_errors++; if (status & RX_EXTRA_DATA)
dev->stats.rx_length_errors++; if ((status & RX_CRC_ERROR) && !(status & (RX_EXTRA_DATA | RX_RUNT))) /* per str 172 */
dev->stats.rx_crc_errors++; if (status & RX_DRIBBLE)
dev->stats.rx_frame_errors++;
}
staticvoid
control_dc_dc(struct net_device *dev, int on_not_off)
{ struct net_local *lp = netdev_priv(dev); unsignedint selfcontrol; unsignedlong timenow = jiffies; /* control the DC to DC convertor in the SelfControl register. *Note:Thisishookeduptoageneralpurposepin,mightnot *alwaysbeaDCtoDCconvertor.
*/
selfcontrol = HCB1_ENBL; /* Enable the HCB1 bit as an output */ if (((lp->adapter_cnf & A_CNF_DC_DC_POLARITY) != 0) ^ on_not_off)
selfcontrol |= HCB1; else
selfcontrol &= ~HCB1;
writereg(dev, PP_SelfCTL, selfcontrol);
/* Wait for the DC/DC converter to power up - 500ms */ while (time_before(jiffies, timenow + HZ))
;
}
/* send a test packet - return true if carrier bits are ok */ staticint
send_test_pkt(struct net_device *dev)
{ struct net_local *lp = netdev_priv(dev); char test_packet[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, /* A 46 in network order */ 0, 0, /* DSAP=0 & SSAP=0 fields */ 0xf3, 0/* Control (Test Req + P bit set) */
}; unsignedlong timenow = jiffies;
/* Test to see if the chip has allocated memory for the packet */ while (time_before(jiffies, timenow + 5)) if (readreg(dev, PP_BusST) & READY_FOR_TX_NOW) break; if (time_after_eq(jiffies, timenow + 5)) return0; /* this shouldn't happen */
/* Write the contents of the packet */
writewords(lp, TX_FRAME_PORT, test_packet, (ETH_ZLEN + 1) >> 1);
cs89_dbg(1, debug, "Sending test packet "); /* wait a couple of jiffies for packet to be received */ for (timenow = jiffies; time_before(jiffies, timenow + 3);)
; if ((readreg(dev, PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) {
cs89_dbg(1, cont, "succeeded\n"); return1;
}
cs89_dbg(1, cont, "failed\n"); return0;
}
/* If connected to another full duplex capable 10-Base-T card *thelinkpulsesseemtobelostwhentheautodetectbitin *theLineCTLisset.Toovercomethistheautodetectbitwill *beclearedwhilsttestingthe10-Base-Tinterface.Thiswould *notbenecessaryforthesparrowchipbutissimplertodoit *anyway.
*/
writereg(dev, PP_LineCTL, lp->linectl & ~AUI_ONLY);
control_dc_dc(dev, 0);
/* Delay for the hardware to work out if the TP cable is present *-150ms
*/ for (timenow = jiffies; time_before(jiffies, timenow + 15);)
; if ((readreg(dev, PP_LineST) & LINK_OK) == 0) return DETECTED_NONE;
if (lp->chip_type == CS8900) { switch (lp->force & 0xf0) { #if0 case FORCE_AUTO:
pr_info("%s: cs8900 doesn't autonegotiate\n",
dev->name); return DETECTED_NONE; #endif /* CS8900 doesn't support AUTO, change to HALF*/ case FORCE_AUTO:
lp->force &= ~FORCE_AUTO;
lp->force |= FORCE_HALF; break; case FORCE_HALF: break; case FORCE_FULL:
writereg(dev, PP_TestCTL,
readreg(dev, PP_TestCTL) | FDX_8900); break;
}
fdx = readreg(dev, PP_TestCTL) & FDX_8900;
} else { switch (lp->force & 0xf0) { case FORCE_AUTO:
lp->auto_neg_cnf = AUTO_NEG_ENABLE; break; case FORCE_HALF:
lp->auto_neg_cnf = 0; break; case FORCE_FULL:
lp->auto_neg_cnf = RE_NEG_NOW | ALLOW_FDX; break;
}
if (send_test_pkt(dev)) return DETECTED_AUI; else return DETECTED_NONE;
}
/* We have a good packet(s), get it/them out of the buffers. */ staticvoid
net_rx(struct net_device *dev)
{ struct net_local *lp = netdev_priv(dev); struct sk_buff *skb; int status, length;
status = ioread16(lp->virt_addr + RX_FRAME_PORT);
length = ioread16(lp->virt_addr + RX_FRAME_PORT);
staticint
net_open(struct net_device *dev)
{ struct net_local *lp = netdev_priv(dev); int result = 0; int i; int ret;
if (dev->irq < 2) { /* Allow interrupts to be generated by the chip */ /* Cirrus' release had this: */ #if0
writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) | ENABLE_IRQ); #endif /* And 2.3.47 had this: */
writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON);
for (i = 2; i < CS8920_NO_INTS; i++) { if ((1 << i) & lp->irq_map) { if (request_irq(i, net_interrupt, 0, dev->name,
dev) == 0) {
dev->irq = i;
write_irq(dev, lp->chip_type, i); /* writereg(dev, PP_BufCFG, GENERATE_SW_INTERRUPT); */ break;
}
}
}
if (i >= CS8920_NO_INTS) {
writereg(dev, PP_BusCTL, 0); /* disable interrupts. */
pr_err("can't get an interrupt\n");
ret = -EAGAIN; goto bad_out;
}
} else { #if IS_ENABLED(CONFIG_CS89x0_ISA) if (((1 << dev->irq) & lp->irq_map) == 0) {
pr_err("%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
dev->name, dev->irq, lp->irq_map);
ret = -EAGAIN; goto bad_out;
} #endif /* FIXME: Cirrus' release had this: */
writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ); /* And 2.3.47 had this: */ #if0
writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON); #endif
write_irq(dev, lp->chip_type, dev->irq);
ret = request_irq(dev->irq, net_interrupt, 0, dev->name, dev); if (ret) {
pr_err("request_irq(%d) failed\n", dev->irq); goto bad_out;
}
}
/* set the Ethernet address */ for (i = 0; i < ETH_ALEN / 2; i++)
writereg(dev, PP_IA + i * 2,
(dev->dev_addr[i * 2] |
(dev->dev_addr[i * 2 + 1] << 8)));
/* while we're testing the interface, leave interrupts disabled */
writereg(dev, PP_BusCTL, MEMORY_ON);
/* Set the LineCTL quintuplet based on adapter configuration read from EEPROM */ if ((lp->adapter_cnf & A_CNF_EXTND_10B_2) &&
(lp->adapter_cnf & A_CNF_LOW_RX_SQUELCH))
lp->linectl = LOW_RX_SQUELCH; else
lp->linectl = 0;
/* check to make sure that they have the "right" hardware available */ switch (lp->adapter_cnf & A_CNF_MEDIA_TYPE) { case A_CNF_MEDIA_10B_T:
result = lp->adapter_cnf & A_CNF_10B_T; break; case A_CNF_MEDIA_AUI:
result = lp->adapter_cnf & A_CNF_AUI; break; case A_CNF_MEDIA_10B_2:
result = lp->adapter_cnf & A_CNF_10B_2; break; default:
result = lp->adapter_cnf & (A_CNF_10B_T |
A_CNF_AUI |
A_CNF_10B_2);
} if (!result) {
pr_err("%s: EEPROM is configured for unavailable media\n",
dev->name);
release_dma: #if ALLOW_DMA
free_dma(dev->dma);
release_irq:
release_dma_buff(lp); #endif
writereg(dev, PP_LineCTL,
readreg(dev, PP_LineCTL) & ~(SERIAL_TX_ON | SERIAL_RX_ON));
free_irq(dev->irq, dev);
ret = -EAGAIN; goto bad_out;
}
/* set the hardware to the configured choice */ switch (lp->adapter_cnf & A_CNF_MEDIA_TYPE) { case A_CNF_MEDIA_10B_T:
result = detect_tp(dev); if (result == DETECTED_NONE) {
pr_warn("%s: 10Base-T (RJ-45) has no cable\n",
dev->name); if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
result = DETECTED_RJ45H; /* Yes! I don't care if I see a link pulse */
} break; case A_CNF_MEDIA_AUI:
result = detect_aui(dev); if (result == DETECTED_NONE) {
pr_warn("%s: 10Base-5 (AUI) has no cable\n", dev->name); if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
result = DETECTED_AUI; /* Yes! I don't care if I see a carrier */
} break; case A_CNF_MEDIA_10B_2:
result = detect_bnc(dev); if (result == DETECTED_NONE) {
pr_warn("%s: 10Base-2 (BNC) has no cable\n", dev->name); if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
result = DETECTED_BNC; /* Yes! I don't care if I can xmit a packet */
} break; case A_CNF_MEDIA_AUTO:
writereg(dev, PP_LineCTL, lp->linectl | AUTO_AUI_10BASET); if (lp->adapter_cnf & A_CNF_10B_T) {
result = detect_tp(dev); if (result != DETECTED_NONE) break;
} if (lp->adapter_cnf & A_CNF_AUI) {
result = detect_aui(dev); if (result != DETECTED_NONE) break;
} if (lp->adapter_cnf & A_CNF_10B_2) {
result = detect_bnc(dev); if (result != DETECTED_NONE) break;
}
pr_err("%s: no media detected\n", dev->name); goto release_dma;
} switch (result) { case DETECTED_NONE:
pr_err("%s: no network cable attached to configured media\n",
dev->name); goto release_dma; case DETECTED_RJ45H:
pr_info("%s: using half-duplex 10Base-T (RJ-45)\n", dev->name); break; case DETECTED_RJ45F:
pr_info("%s: using full-duplex 10Base-T (RJ-45)\n", dev->name); break; case DETECTED_AUI:
pr_info("%s: using 10Base-5 (AUI)\n", dev->name); break; case DETECTED_BNC:
pr_info("%s: using 10Base-2 (BNC)\n", dev->name); break;
}
/* Turn on both receive and transmit operations */
writereg(dev, PP_LineCTL,
readreg(dev, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON);
/* Receive only error free packets addressed to this card */
lp->rx_mode = 0;
writereg(dev, PP_RxCTL, DEF_RX_ACCEPT);
/* Get the current statistics. *Thismaybecalledwiththecardopenorclosed.
*/ staticstruct net_device_stats *
net_get_stats(struct net_device *dev)
{ struct net_local *lp = netdev_priv(dev); unsignedlong flags;
spin_lock_irqsave(&lp->lock, flags); /* Update the statistics from the device registers. */
dev->stats.rx_missed_errors += (readreg(dev, PP_RxMiss) >> 6);
dev->stats.collisions += (readreg(dev, PP_TxCol) >> 6);
spin_unlock_irqrestore(&lp->lock, flags);
return &dev->stats;
}
staticvoid net_timeout(struct net_device *dev, unsignedint txqueue)
{ /* If we get here, some higher level has decided we are broken.
There should really be a "kick me" function call instead. */
cs89_dbg(0, err, "%s: transmit timed out, %s?\n",
dev->name,
tx_done(dev) ? "IRQ conflict" : "network cable problem"); /* Try to restart the adaptor. */
netif_wake_queue(dev);
}
/* Test to see if the chip has allocated memory for the packet */ if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) { /* Gasp! It hasn't. But that shouldn't happen since *we'rewaitingforTxOk,soreturn1andrequeuethispacket.
*/
spin_unlock_irqrestore(&lp->lock, flags);
cs89_dbg(0, err, "Tx buffer not free!\n"); return NETDEV_TX_BUSY;
} /* Write the contents of the packet */
writewords(lp, TX_FRAME_PORT, skb->data, (skb->len + 1) >> 1);
spin_unlock_irqrestore(&lp->lock, flags);
dev->stats.tx_bytes += skb->len;
dev_consume_skb_any(skb);
/* We DO NOT call netif_wake_queue() here. *WealsoDONOTcallnetif_start_queue(). * *Eitherofthesewouldcauseanotherbottomhalfrunthrough *net_send_packet()beforethispackethasfullygoneout. *Thatcausesustohitthe"Gasp!"aboveandthesendisrescheduled. *itrunslikeadog.WejustreturnandwaitfortheTxcompletion *interrupthandlertorestartthenetdevicelayer
*/
/* Wait until the chip is reset */
reset_start_time = jiffies; while ((readreg(dev, PP_SelfST) & INIT_DONE) == 0 &&
time_before(jiffies, reset_start_time + 2))
; #endif/* !CONFIG_MACH_MX31ADS */
}
/* This is the real probe routine. *LinuxhasahistoryoffriendlydeviceprobesontheISAbus. *Agooddeviceprobesavoidsdoingwrites,and *verifiesthatthecorrectdeviceexistsandfunctions. *Return0onsuccess.
*/ staticint __init
cs89x0_probe1(struct net_device *dev, void __iomem *ioaddr, int modular)
{ struct net_local *lp = netdev_priv(dev); int i; int tmp; unsigned rev_type = 0; int eeprom_buff[CHKSUM_LEN];
u8 addr[ETH_ALEN]; int retval;
/* Initialize the device structure. */ if (!modular) {
memset(lp, 0, sizeof(*lp));
spin_lock_init(&lp->lock); #ifndef MODULE #if ALLOW_DMA if (g_cs89x0_dma) {
lp->use_dma = 1;
lp->dma = g_cs89x0_dma;
lp->dmasize = 16; /* Could make this an option... */
} #endif
lp->force = g_cs89x0_media__force; #endif
}
/* get the chip type */
rev_type = readreg(dev, PRODUCT_ID_ADD);
lp->chip_type = rev_type & ~REVISON_BITS;
lp->chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
/* Check the chip type and revision in order to set the correct *sendcommand.CS8920revisionCandCS8900revisionFcanuse *thefastersend.
*/
lp->send_cmd = TX_AFTER_381; if (lp->chip_type == CS8900 && lp->chip_revision >= 'F')
lp->send_cmd = TX_NOW; if (lp->chip_type != CS8900 && lp->chip_revision >= 'C')
lp->send_cmd = TX_NOW;
/* Here we read the current configuration of the chip. *IfthereisnoExtendedEEPROMthentheideaistonotdisturb *thechipconfiguration,itshouldhavebeencorrectlysetupby *automaticEEPROMreadonreset.So,ifthechipsaysitread *theEEPROMthedriverwillalwaysdo*something*insteadof *complainthatadapter_cnfis0.
*/
if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) ==
(EEPROM_OK | EEPROM_PRESENT)) { /* Load the MAC. */ for (i = 0; i < ETH_ALEN / 2; i++) { unsignedint Addr;
Addr = readreg(dev, PP_IA + i * 2);
addr[i * 2] = Addr & 0xFF;
addr[i * 2 + 1] = Addr >> 8;
}
eth_hw_addr_set(dev, addr);
lp->adapter_cnf = 0;
i = readreg(dev, PP_LineCTL); /* Preserve the setting of the HCB1 pin. */ if ((i & (HCB1 | HCB1_ENBL)) == (HCB1 | HCB1_ENBL))
lp->adapter_cnf |= A_CNF_DC_DC_POLARITY; /* Save the sqelch bit */ if ((i & LOW_RX_SQUELCH) == LOW_RX_SQUELCH)
lp->adapter_cnf |= A_CNF_EXTND_10B_2 | A_CNF_LOW_RX_SQUELCH; /* Check if the card is in 10Base-t only mode */ if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == 0)
lp->adapter_cnf |= A_CNF_10B_T | A_CNF_MEDIA_10B_T; /* Check if the card is in AUI only mode */ if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == AUI_ONLY)
lp->adapter_cnf |= A_CNF_AUI | A_CNF_MEDIA_AUI; /* Check if the card is in Auto mode. */ if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == AUTO_AUI_10BASET)
lp->adapter_cnf |= A_CNF_AUI | A_CNF_10B_T |
A_CNF_MEDIA_AUI | A_CNF_MEDIA_10B_T | A_CNF_MEDIA_AUTO;
cs89_dbg(1, info, "%s: PP_LineCTL=0x%x, adapter_cnf=0x%x\n",
dev->name, i, lp->adapter_cnf);
/* IRQ. Other chips already probe, see below. */ if (lp->chip_type == CS8900)
lp->isa_config = readreg(dev, PP_CS8900_ISAINT) & INT_NO_MASK;
pr_cont("[Cirrus EEPROM] ");
}
pr_cont("\n");
/* First check to see if an EEPROM is attached. */
if ((readreg(dev, PP_SelfST) & EEPROM_PRESENT) == 0)
pr_warn("No EEPROM, relying on command line....\n"); elseif (get_eeprom_data(dev, START_EEPROM_DATA, CHKSUM_LEN, eeprom_buff) < 0) {
pr_warn("EEPROM read failed, relying on command line\n");
} elseif (get_eeprom_cksum(START_EEPROM_DATA, CHKSUM_LEN, eeprom_buff) < 0) { /* Check if the chip was able to read its own configuration starting
at 0 in the EEPROM*/ if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) !=
(EEPROM_OK | EEPROM_PRESENT))
pr_warn("Extended EEPROM checksum bad and no Cirrus EEPROM, relying on command line\n");
} else { /* This reads an extended EEPROM that is not documented *intheCS8900datasheet.
*/
/* get transmission control word but keep the autonegotiation bits */ if (!lp->auto_neg_cnf)
lp->auto_neg_cnf = eeprom_buff[AUTO_NEG_CNF_OFFSET / 2]; /* Store adapter configuration */ if (!lp->adapter_cnf)
lp->adapter_cnf = eeprom_buff[ADAPTER_CNF_OFFSET / 2]; /* Store ISA configuration */
lp->isa_config = eeprom_buff[ISA_CNF_OFFSET / 2];
dev->mem_start = eeprom_buff[PACKET_PAGE_OFFSET / 2] << 8;
/* eeprom_buff has 32-bit ints, so we can't just memcpy it */ /* store the initial memory base address */ for (i = 0; i < ETH_ALEN / 2; i++) {
addr[i * 2] = eeprom_buff[i];
addr[i * 2 + 1] = eeprom_buff[i] >> 8;
}
eth_hw_addr_set(dev, addr);
cs89_dbg(1, debug, "%s: new adapter_cnf: 0x%x\n",
dev->name, lp->adapter_cnf);
}
/* allow them to force multiple transceivers. If they force multiple, autosense */
{ int count = 0; if (lp->force & FORCE_RJ45) {
lp->adapter_cnf |= A_CNF_10B_T;
count++;
} if (lp->force & FORCE_AUI) {
lp->adapter_cnf |= A_CNF_AUI;
count++;
} if (lp->force & FORCE_BNC) {
lp->adapter_cnf |= A_CNF_10B_2;
count++;
} if (count > 1)
lp->adapter_cnf |= A_CNF_MEDIA_AUTO; elseif (lp->force & FORCE_RJ45)
lp->adapter_cnf |= A_CNF_MEDIA_10B_T; elseif (lp->force & FORCE_AUI)
lp->adapter_cnf |= A_CNF_MEDIA_AUI; elseif (lp->force & FORCE_BNC)
lp->adapter_cnf |= A_CNF_MEDIA_10B_2;
}
cs89_dbg(1, debug, "%s: after force 0x%x, adapter_cnf=0x%x\n",
dev->name, lp->force, lp->adapter_cnf);
/* FIXME: We don't let you set dc-dc polarity or low RX squelch from the command line: add it here */
/* FIXME: We don't let you set the IMM bit from the command line: add it to lp->auto_neg_cnf here */
/* FIXME: we don't set the Ethernet address on the command line. Use *ifconfigIFACEhwetherAABBCCDDEEFF
*/
/* If this is a CS8900 then no pnp soft */ if (lp->chip_type != CS8900 && /* Check if the ISA IRQ has been set */
(i = readreg(dev, PP_CS8920_ISAINT) & 0xff,
(i != 0 && i < CS8920_NO_INTS))) { if (!dev->irq)
dev->irq = i;
} else {
i = lp->isa_config & INT_NO_MASK; #if IS_ENABLED(CONFIG_CS89x0_ISA) if (lp->chip_type == CS8900) { /* Translate the IRQ using the IRQ mapping table. */ if (i >= ARRAY_SIZE(cs8900_irq_map))
pr_err("invalid ISA interrupt number %d\n", i); else
i = cs8900_irq_map[i];
lp->irq_map = CS8900_IRQ_MAP; /* fixed IRQ map for CS8900 */
} else { int irq_map_buff[IRQ_MAP_LEN/2];
if (!request_region(ioport, NETCARD_IO_EXTENT, DRV_NAME)) {
ret = -EBUSY; goto out;
}
io_mem = ioport_map(ioport & ~3, NETCARD_IO_EXTENT); if (!io_mem) {
ret = -ENOMEM; goto release;
}
/* if they give us an odd I/O address, then do ONE write to *theaddressport,togetitbacktoaddresszero,wherewe *expecttofindtheEISAsignatureword.AnIOwithabaseof0x3 *willskipthetestfortheADD_PORT.
*/ if (ioport & 1) {
cs89_dbg(1, info, "%s: odd ioaddr 0x%lx\n", dev->name, ioport); if ((ioport & 2) != 2) { if ((ioread16(io_mem + ADD_PORT) & ADD_MASK) !=
ADD_SIG) {
pr_err("%s: bad signature 0x%x\n",
dev->name, ioread16(io_mem + ADD_PORT));
ret = -ENODEV; goto unmap;
}
}
}
ret = cs89x0_probe1(dev, io_mem, modular); if (!ret) goto out;
unmap:
ioport_unmap(io_mem);
release:
release_region(ioport, NETCARD_IO_EXTENT);
out: return ret;
}
#ifndef MODULE /* Check for a network adaptor of this type, and return '0' iff one exists. *Ifdev->base_addr==0,probealllikelylocations. *Ifdev->base_addr==1,alwaysreturnfailure. *Ifdev->base_addr==2,allocatespaceforthedeviceandreturnsuccess *(detachabledevicesonly). *Return0onsuccess.
*/
struct net_device * __init cs89x0_probe(int unit)
{ struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); unsigned *port; int err = 0; int irq; int io;
/* boy, they'd better get these right */ if (!strcmp(media, "rj45"))
lp->adapter_cnf = A_CNF_MEDIA_10B_T | A_CNF_10B_T; elseif (!strcmp(media, "aui"))
lp->adapter_cnf = A_CNF_MEDIA_AUI | A_CNF_AUI; elseif (!strcmp(media, "bnc"))
lp->adapter_cnf = A_CNF_MEDIA_10B_2 | A_CNF_10B_2; else
lp->adapter_cnf = A_CNF_MEDIA_10B_T | A_CNF_10B_T;
if (duplex == -1)
lp->auto_neg_cnf = AUTO_NEG_ENABLE;
if (io == 0) {
pr_err("Module autoprobing not allowed\n");
pr_err("Append io=0xNNN\n");
ret = -EPERM; goto out;
} elseif (io <= 0x1ff) {
ret = -ENXIO; goto out;
}
#if ALLOW_DMA if (use_dma && dmasize != 16 && dmasize != 64) {
pr_err("dma size must be either 16K or 64K, not %dK\n",
dmasize);
ret = -EPERM; goto out;
} #endif
ret = cs89x0_ioport_probe(dev, io, 1); if (ret) goto out;
/* This platform_get_resource() call will not return NULL, because *thesamecallincs89x0_platform_probe()hasreturnedanonNULL *value.
*/
unregister_netdev(dev);
free_netdev(dev);
}
¤ 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.0.39Bemerkung:
(vorverarbeitet am 2026-09-29)
¤
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.