Newer
Older
pr_warning("%s: received oversized frame.\n", dev->name);
dev->stats.rx_dropped++;
}
} else { /* frame !(ok), only with 'save-bad-frames' */
pr_warning("%s: oops! rfd-error-status: %04x\n", dev->name, status);
}
p->rfd_top->status = 0;
p->rfd_top->last = RFD_SUSP;
p->rfd_last->last = 0; /* delete RU_SUSP */
p->rfd_last = p->rfd_top;
p->rfd_top = (struct rfd_struct *) make32(p->rfd_top->next); /* step to next RFD */
}
}
/**********************************************************
* handle 'Receiver went not ready'.
*/
static void elmc_rnr_int(struct net_device *dev)
{
struct priv *p = netdev_priv(dev);
WAIT_4_SCB_CMD(); /* wait for the last cmd */
p->scb->cmd = RUC_ABORT; /* usually the RU is in the 'no resource'-state .. abort it now. */
elmc_attn586();
WAIT_4_SCB_CMD(); /* wait for accept cmd. */
alloc_rfa(dev, (char *) p->rfd_first);
startrecv586(dev); /* restart RU */
pr_warning("%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->status);
}
/**********************************************************
* handle xmit - interrupt
*/
static void elmc_xmt_int(struct net_device *dev)
{
int status;
struct priv *p = netdev_priv(dev);
status = p->xmit_cmds[p->xmit_last]->cmd_status;
if (!(status & STAT_COMPL)) {
pr_warning("%s: strange .. xmit-int without a 'COMPLETE'\n", dev->name);
dev->stats.tx_packets++;
dev->stats.collisions += (status & TCMD_MAXCOLLMASK);
pr_warning("%s: late collision detected.\n", dev->name);
dev->stats.collisions++;
dev->stats.tx_carrier_errors++;
pr_warning("%s: no carrier detected.\n", dev->name);
pr_warning("%s: loss of CTS detected.\n", dev->name);
dev->stats.tx_fifo_errors++;
pr_warning("%s: DMA underrun detected.\n", dev->name);
pr_warning("%s: Max. collisions exceeded.\n", dev->name);
dev->stats.collisions += 16;
}
}
#if (NUM_XMIT_BUFFS != 1)
if ((++p->xmit_last) == NUM_XMIT_BUFFS) {
p->xmit_last = 0;
}
#endif
netif_wake_queue(dev);
}
/***********************************************************
* (re)start the receiver
*/
static void startrecv586(struct net_device *dev)
{
struct priv *p = netdev_priv(dev);
p->scb->rfa_offset = make16(p->rfd_first);
p->scb->cmd = RUC_START;
elmc_attn586(); /* start cmd. */
WAIT_4_SCB_CMD(); /* wait for accept cmd. (no timeout!!) */
}
/******************************************************
* timeout
*/
static void elmc_timeout(struct net_device *dev)
{
struct priv *p = netdev_priv(dev);
/* COMMAND-UNIT active? */
if (p->scb->status & CU_ACTIVE) {
pr_debug("%s: strange ... timeout with CU active?!?\n", dev->name);
pr_debug("%s: X0: %04x N0: %04x N1: %04x %d\n", dev->name,
(int)p->xmit_cmds[0]->cmd_status,
(int)p->nop_cmds[0]->cmd_status,
(int)p->nop_cmds[1]->cmd_status, (int)p->nop_point);
p->scb->cmd = CUC_ABORT;
elmc_attn586();
WAIT_4_SCB_CMD();
p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]);
p->scb->cmd = CUC_START;
elmc_attn586();
WAIT_4_SCB_CMD();
netif_wake_queue(dev);
} else {
pr_debug("%s: xmitter timed out, try to restart! stat: %04x\n",
dev->name, p->scb->status);
pr_debug("%s: command-stats: %04x %04x\n", dev->name,
p->xmit_cmds[0]->cmd_status, p->xmit_cmds[1]->cmd_status);
/******************************************************
* send frame
*/
static int elmc_send_packet(struct sk_buff *skb, struct net_device *dev)
{
int len;
int i;
#ifndef NO_NOPCOMMANDS
int next_nop;
#endif
struct priv *p = netdev_priv(dev);
netif_stop_queue(dev);
len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
if (len != skb->len)
memset((char *) p->xmit_cbuffs[p->xmit_count], 0, ETH_ZLEN);
skb_copy_from_linear_data(skb, (char *) p->xmit_cbuffs[p->xmit_count], skb->len);
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
#if (NUM_XMIT_BUFFS == 1)
#ifdef NO_NOPCOMMANDS
p->xmit_buffs[0]->size = TBD_LAST | len;
for (i = 0; i < 16; i++) {
p->scb->cbl_offset = make16(p->xmit_cmds[0]);
p->scb->cmd = CUC_START;
p->xmit_cmds[0]->cmd_status = 0;
elmc_attn586();
dev->trans_start = jiffies;
if (!i) {
dev_kfree_skb(skb);
}
WAIT_4_SCB_CMD();
if ((p->scb->status & CU_ACTIVE)) { /* test it, because CU sometimes doesn't start immediately */
break;
}
if (p->xmit_cmds[0]->cmd_status) {
break;
}
if (i == 15) {
pr_warning("%s: Can't start transmit-command.\n", dev->name);
}
}
#else
next_nop = (p->nop_point + 1) & 0x1;
p->xmit_buffs[0]->size = TBD_LAST | len;
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
p->xmit_cmds[0]->cmd_link = p->nop_cmds[next_nop]->cmd_link
= make16((p->nop_cmds[next_nop]));
p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0;
p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0]));
dev->trans_start = jiffies;
p->nop_point = next_nop;
dev_kfree_skb(skb);
#endif
#else
p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len;
if ((next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS) {
next_nop = 0;
}
p->xmit_cmds[p->xmit_count]->cmd_status = 0;
p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link
= make16((p->nop_cmds[next_nop]));
p->nop_cmds[next_nop]->cmd_status = 0;
p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count]));
dev->trans_start = jiffies;
p->xmit_count = next_nop;
if (p->xmit_count != p->xmit_last)
netif_wake_queue(dev);
dev_kfree_skb(skb);
#endif
return NETDEV_TX_OK;
}
/*******************************************
* Someone wanna have the statistics
*/
static struct net_device_stats *elmc_get_stats(struct net_device *dev)
{
struct priv *p = netdev_priv(dev);
unsigned short crc, aln, rsc, ovrn;
crc = p->scb->crc_errs; /* get error-statistic from the ni82586 */
p->scb->crc_errs -= crc;
aln = p->scb->aln_errs;
p->scb->aln_errs -= aln;
rsc = p->scb->rsc_errs;
p->scb->rsc_errs -= rsc;
ovrn = p->scb->ovrn_errs;
p->scb->ovrn_errs -= ovrn;
dev->stats.rx_crc_errors += crc;
dev->stats.rx_fifo_errors += ovrn;
dev->stats.rx_frame_errors += aln;
dev->stats.rx_dropped += rsc;
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
}
/********************************************************
* Set MC list ..
*/
#ifdef ELMC_MULTICAST
static void set_multicast_list(struct net_device *dev)
{
if (!dev->start) {
/* without a running interface, promiscuous doesn't work */
return;
}
dev->start = 0;
alloc586(dev);
init586(dev);
startrecv586(dev);
dev->start = 1;
}
#endif
static void netdev_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
strcpy(info->driver, DRV_NAME);
strcpy(info->version, DRV_VERSION);
sprintf(info->bus_info, "MCA 0x%lx", dev->base_addr);
}
static const struct ethtool_ops netdev_ethtool_ops = {
.get_drvinfo = netdev_get_drvinfo,
};
#ifdef MODULE
/* Increase if needed ;) */
#define MAX_3C523_CARDS 4
static struct net_device *dev_elmc[MAX_3C523_CARDS];
static int irq[MAX_3C523_CARDS];
static int io[MAX_3C523_CARDS];
module_param_array(irq, int, NULL, 0);
module_param_array(io, int, NULL, 0);
MODULE_PARM_DESC(io, "EtherLink/MC I/O base address(es)");
MODULE_PARM_DESC(irq, "EtherLink/MC IRQ number(s)");
int __init init_module(void)
/* Loop until we either can't find any more cards, or we have MAX_3C523_CARDS */
for(this_dev=0; this_dev<MAX_3C523_CARDS; this_dev++) {
struct net_device *dev = alloc_etherdev(sizeof(struct priv));
if (!dev)
break;
dev->irq=irq[this_dev];
dev->base_addr=io[this_dev];
if (do_elmc_probe(dev) == 0) {
dev_elmc[this_dev] = dev;
found++;
continue;
}
free_netdev(dev);
if (io[this_dev]==0)
break;
pr_warning("3c523.c: No 3c523 card found at io=%#x\n",io[this_dev]);
if (io[0]==0)
pr_notice("3c523.c: No 3c523 cards found\n");
void __exit cleanup_module(void)
{
int this_dev;
for (this_dev=0; this_dev<MAX_3C523_CARDS; this_dev++) {
struct net_device *dev = dev_elmc[this_dev];
if (dev) {
unregister_netdev(dev);
cleanup_card(dev);
free_netdev(dev);
}
}
}
#endif /* MODULE */