// SPDX-License-Identifier: GPL-1.0+ /* mac8390.c: New driver for 8390-based Nubus (or Nubus-alike)
Ethernet cards on Linux */ /* Based on the former daynaport.c driver, by Alan Cox. Some code taken from or inspired by skeleton.c by Donald Becker, acenic.c by
Jes Sorensen, and ne2k-pci.c by Donald Becker and Paul Gortmaker. */
/* 2000-02-28: support added for Dayna and Kinetics cards by
A.G.deWijn@phys.uu.nl */ /* 2000-04-04: support added for Dayna2 by bart@etpmod.phys.tue.nl */ /* 2001-04-18: support for DaynaPort E/LC-M by rayk@knightsmanor.org */ /* 2001-05-15: support for Cabletron ported from old daynaport driver * and fixed access to Sonic Sys card which masquerades as a Farallon
* by rayk@knightsmanor.org */ /* 2002-12-30: Try to support more cards, some clues from NetBSD driver */ /* 2003-12-26: Make sure Asante cards always work. */
#define WD_START_PG 0x00 /* First page of TX buffer */ #define CABLETRON_RX_START_PG 0x00 /* First page of RX buffer */ #define CABLETRON_RX_STOP_PG 0x30 /* Last page +1 of RX ring */ #define CABLETRON_TX_START_PG CABLETRON_RX_STOP_PG /* First page of TX buffer */
/* * Unfortunately it seems we have to hardcode these for the moment * Shouldn't the card know about this? * Does anyone know where to read it off the card? * Do we trust the data provided by the card?
*/
/* Sane (32-bit chunk memory read/write) - Some Farallon and Apple do this*/ staticvoid sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page); staticvoid sane_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset); staticvoid sane_block_output(struct net_device *dev, int count, constunsignedchar *buf, constint start_page);
/* dayna_memcpy to and from card */ staticvoid dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count); staticvoid dayna_memcpy_tocard(struct net_device *dev, int to, constvoid *from, int count);
/* Dayna - Dayna/Kinetics use this */ staticvoid dayna_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page); staticvoid dayna_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset); staticvoid dayna_block_output(struct net_device *dev, int count, constunsignedchar *buf, int start_page);
/* Slow Sane (16-bit chunk memory read/write) Cabletron uses this */ staticvoid slow_sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page); staticvoid slow_sane_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset); staticvoid slow_sane_block_output(struct net_device *dev, int count, constunsignedchar *buf, int start_page); staticvoid word_memcpy_tocard(unsignedlong tp, constvoid *fp, int count); staticvoid word_memcpy_fromcard(void *tp, unsignedlong fp, int count);
staticenum mac8390_type mac8390_ident(struct nubus_rsrc *fres)
{ switch (fres->dr_sw) { case NUBUS_DRSW_3COM: switch (fres->dr_hw) { case NUBUS_DRHW_APPLE_SONIC_NB: case NUBUS_DRHW_APPLE_SONIC_LC: case NUBUS_DRHW_SONNET: return MAC8390_NONE; default: return MAC8390_APPLE;
}
case NUBUS_DRSW_APPLE: switch (fres->dr_hw) { case NUBUS_DRHW_ASANTE_LC: return MAC8390_NONE; case NUBUS_DRHW_CABLETRON: return MAC8390_CABLETRON; default: return MAC8390_APPLE;
}
case NUBUS_DRSW_ASANTE: return MAC8390_ASANTE;
case NUBUS_DRSW_TECHWORKS: case NUBUS_DRSW_DAYNA2: case NUBUS_DRSW_DAYNA_LC: if (fres->dr_hw == NUBUS_DRHW_CABLETRON) return MAC8390_CABLETRON; else return MAC8390_APPLE;
case NUBUS_DRSW_FARALLON: return MAC8390_FARALLON;
case NUBUS_DRSW_KINETICS: switch (fres->dr_hw) { case NUBUS_DRHW_INTERLAN: return MAC8390_INTERLAN; default: return MAC8390_KINETICS;
}
case NUBUS_DRSW_DAYNA: /* * These correspond to Dayna Sonic cards * which use the macsonic driver
*/ if (fres->dr_hw == NUBUS_DRHW_SMC9194 ||
fres->dr_hw == NUBUS_DRHW_INTERLAN) return MAC8390_NONE; else return MAC8390_DAYNA;
} return MAC8390_NONE;
}
/* Try writing 32 bits */
nubus_writel(outdata, membase); /* Now read it back */
indata = nubus_readl(membase); if (outdata == indata) return ACCESS_32;
outdata = 0xC5C0D5D0;
indata = 0;
/* Write 16 bit output */
word_memcpy_tocard(membase, &outdata, 4); /* Now read it back */
word_memcpy_fromcard(&indata, membase, 4); if (outdata == indata) return ACCESS_16;
return ACCESS_UNKNOWN;
}
staticint mac8390_memsize(unsignedlong membase)
{ unsignedlong flags; int i, j;
local_irq_save(flags); /* Check up to 32K in 4K increments */ for (i = 0; i < 8; i++) { volatileunsignedshort *m = (unsignedshort *)(membase + (i * 0x1000));
/* Unwriteable - we have a fully decoded card and the
RAM end located */ if (hwreg_present(m) == 0) break;
/* write a distinctive byte */
*m = 0xA5A0 | i; /* check that we read back what we wrote */ if (*m != (0xA5A0 | i)) break;
/* check for partial decode and wrap */ for (j = 0; j < i; j++) { volatileunsignedshort *p = (unsignedshort *)(membase + (j * 0x1000)); if (*p != (0xA5A0 | j)) break;
}
}
local_irq_restore(flags); /* * in any case, we stopped once we tried one block too many, * or once we reached 32K
*/ return i * 0x1000;
}
dev->irq = SLOT2IRQ(board->slot); /* This is getting to be a habit */
dev->base_addr = board->slot_addr | ((board->slot & 0xf) << 20);
/* * Get some Nubus info - we will trust the card's idea * of where its memory and registers are.
*/
if (nubus_get_func_dir(fres, &dir) == -1) {
dev_err(&board->dev, "Unable to get Nubus functional directory\n"); returnfalse;
}
/* Get the MAC address */ if (nubus_find_rsrc(&dir, NUBUS_RESID_MAC_ADDRESS, &ent) == -1) {
dev_info(&board->dev, "MAC address resource not found\n"); returnfalse;
}
/* Fill in model-specific information and functions */ switch (type) { case MAC8390_FARALLON: case MAC8390_APPLE: switch (mac8390_testio(dev->mem_start)) { case ACCESS_UNKNOWN:
dev_err(&board->dev, "Don't know how to access card memory\n"); return -ENODEV;
case ACCESS_16: /* 16 bit card, register map is reversed */
ei_status.reset_8390 = mac8390_no_reset;
ei_status.block_input = slow_sane_block_input;
ei_status.block_output = slow_sane_block_output;
ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
ei_status.reg_offset = back4_offsets; break;
case MAC8390_ASANTE: /* Some Asante cards pass the 32 bit test * but overwrite system memory when run at 32 bit. * so we run them all at 16 bit.
*/
ei_status.reset_8390 = mac8390_no_reset;
ei_status.block_input = slow_sane_block_input;
ei_status.block_output = slow_sane_block_output;
ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
ei_status.reg_offset = back4_offsets; break;
case MAC8390_CABLETRON: /* 16 bit card, register map is short forward */
ei_status.reset_8390 = mac8390_no_reset;
ei_status.block_input = slow_sane_block_input;
ei_status.block_output = slow_sane_block_output;
ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
ei_status.reg_offset = fwrd2_offsets; break;
case MAC8390_DAYNA: case MAC8390_KINETICS: /* 16 bit memory, register map is forward */ /* dayna and similar */
ei_status.reset_8390 = mac8390_no_reset;
ei_status.block_input = dayna_block_input;
ei_status.block_output = dayna_block_output;
ei_status.get_8390_hdr = dayna_get_8390_hdr;
ei_status.reg_offset = fwrd4_offsets; break;
case MAC8390_INTERLAN: /* 16 bit memory, register map is forward */
ei_status.reset_8390 = interlan_reset;
ei_status.block_input = slow_sane_block_input;
ei_status.block_output = slow_sane_block_output;
ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
ei_status.reg_offset = fwrd4_offsets; break;
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.