Subject: Re: NE2000 Compatible PCMCIA Ethernet Card
To: Rene Hexel <rh@idle.trapdoor.vip.at>
From: Dan Winship <danw@MIT.EDU>
List: tech-net
Date: 03/13/1999 19:41:59
> what is the recommended way of finding out the correct value here (I
> didn't find anything useful in the PCMCIA information provided by
> the card)?
I was trying to do this recently too, and the answer I got was "well,
you just sort of try all the common values until one works". That grew
old fast, so I wrote some code, which didn't work. But from looking at
the Linux code, I think my card (Netgear FA410TX) is weird about where
it puts its hw addr, so I think this code may actually be right, just
not useful for that particular card...
*** if_ne_pcmcia.c.orig Sat Mar 13 14:37:38 1999
--- if_ne_pcmcia.c Sat Mar 13 14:38:17 1999
***************
*** 63,68 ****
--- 63,73 ----
int ne_pcmcia_enable __P((struct dp8390_softc *));
void ne_pcmcia_disable __P((struct dp8390_softc *));
+ #ifdef NE_PCMCIA_DEBUG
+ int ne_pcmcia_find_address __P((char *, struct pcmcia_function *,
+ unsigned char *, int *));
+ #endif
+
struct ne_pcmcia_softc {
struct ne2000_softc sc_ne2000; /* real "ne2000" softc */
***************
*** 449,455 ****
for (i = 0; i < NE2000_NDEVS; i++) {
if ((ne_dev = ne2000_match(pa->card, pa->pf->number, i))
!= NULL) {
! if (ne_dev->enet_maddr >= 0) {
if (pcmcia_mem_alloc(pa->pf,
ETHER_ADDR_LEN * 2, &pcmh)) {
printf("%s: can't alloc mem for"
--- 454,467 ----
for (i = 0; i < NE2000_NDEVS; i++) {
if ((ne_dev = ne2000_match(pa->card, pa->pf->number, i))
!= NULL) {
! #ifdef NE_PCMCIA_DEBUG
! if (ne_dev->enet_maddr == 0) {
! ne_pcmcia_find_address(dsc->sc_dev.dv_xname,
! pa->pf, ne_dev->enet_vendor,
! &ne_dev->enet_maddr);
! }
! #endif
! if (ne_dev->enet_maddr > 0) {
if (pcmcia_mem_alloc(pa->pf,
ETHER_ADDR_LEN * 2, &pcmh)) {
printf("%s: can't alloc mem for"
***************
*** 522,527 ****
--- 534,586 ----
pcmcia_function_disable(pa->pf);
}
+
+ #ifdef NE_PCMCIA_DEBUG
+
+ #define PCMCIA_MEM_ATTR_END 0xffff
+ #define BLOCK_SIZE 0x1000
+
+ int
+ ne_pcmcia_find_address(name, pf, vendor, addr)
+ char *name;
+ struct pcmcia_function *pf;
+ unsigned char *vendor;
+ int *addr;
+ {
+ struct pcmcia_mem_handle pcmh;
+ bus_addr_t offset;
+ int base, mwindow, i;
+
+ if (pcmcia_mem_alloc(pf, BLOCK_SIZE, &pcmh)) {
+ printf("%s: can't alloc mem to find enet addr\n", name);
+ return;
+ }
+
+ for (base = 0; base < PCMCIA_MEM_ATTR_END && !*addr;
+ base += BLOCK_SIZE) {
+ if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, base,
+ BLOCK_SIZE, &pcmh, &offset, &mwindow)) {
+ printf("%s: can't map mem to find enet addr\n", name);
+ return;
+ }
+ for (i = 0; i < BLOCK_SIZE - 6; i++) {
+ if (bus_space_read_1(pcmh.memt, pcmh.memh,
+ offset + i * 2) == vendor[0] &&
+ bus_space_read_1(pcmh.memt, pcmh.memh,
+ offset + i * 2 + 2) == vendor[1] &&
+ bus_space_read_1(pcmh.memt, pcmh.memh,
+ offset + i * 2 + 4) == vendor[2]) {
+ printf("%s: found enet addr at %x\n",
+ name, base + i);
+ *addr = base + i;
+ break;
+ }
+ }
+ pcmcia_mem_unmap(pf, mwindow);
+ }
+ pcmcia_mem_free(pf, &pcmh);
+ }
+ #endif
int
ne_pcmcia_detach(self, flags)