Subject: Re: PROBLEM SOLVED: SMC card disappears after booting 1.1 INSTADP
To: Marc Unangst <mju@cs.cmu.edu>
From: Daniel Carosone <dan@geek.com.au>
List: port-i386
Date: 04/12/1996 13:20:33
A blast from the past, to set the scene:

> From: Marc Unangst <mju@cs.cmu.edu>
> Subject: PROBLEM SOLVED: SMC card disappears after booting 1.1 INSTADP
> Date: Thu, 21 Dec 1995 01:16:51 -0500
> To: port-i386@NetBSD.ORG
> 
> As some people have noticed, if you have an SMC Ethernet card
> configured for I/O address 0x300, it won't work after you boot either
> of the NetBSD 1.1 installation kernels.  It's not the old problem that
> could be fixed by a cold boot; this time, your card is (apparently)
> dead.  None of the SMC utilities can see the card, and the kernel
> can't recognize it.
> 
> The problem is that the el and wt driver probe routines cooperate to
> overwrite the card's LAN address PROM, and then save the new settings
> to the card's NVRAM.  Because this corrupts the PROM checksum,
> everything assumes that no card is installed.  And because the
> settings get written to NVRAM, a cold boot doesn't fix it.
> 
> However, it is possible to fix this manually.  Here's what to do if
> your SMC card got toasted like mine did.  IMPORTANT: I figured this
> out by reading the ed, el, and wt driver source.  I don't guarantee
> that this is safe, or that it does the right thing.  However, it did
> fix my card...
> 
> You'll need to know your card's Ethernet address, and the card type
> code.  For the SMC Elite16, it's 0x28.  Look in
> /sys/dev/isa/if_edreg.h for the others if you need it.  To get the
> Ethernet address, you can either look at the sticker on the card, or
> (if you don't feel like opening your machine) find an old
> /var/log/messages from when your card used to work, and read it out of
> there.
> 
> Next, boot DOS and run DEBUG.  Note that all the numbers you type have
> to be in hex.  At the "-" prompt, type:
> 
> o 308 <addr0>
> o 30e <type>
> 
> Where <addr0> is the first byte of your Ethernet address, and <type>
> is the type code.  These two steps restore the portions of the address
> PROM that got mangled.  Next, type
> 
> i 301
> 
> Take the number it prints, and add 0x80 to it.  Then type
> 
> o 301 <num+0x80>
> o 301 <num>
> 
> This step writes the contents of the address PROM to NVRAM, so they
> are saved across the next cold boot.
> 
> If you like, you can use "i 308", "i 309", etc. (through 30f) to read
> the 8-byte address PROM and verify that the other entries are correct.
> The first 6 are the Ethernet address, the 7th is the card type, and
> the 8th is a checksum byte.  The 8 bytes should sum to 255 mod 256; if
> they do, then you've probably successfully restored your
> configuration.
> 
> Finally, quit DEBUG (type "q"), and then run EZSETUP to reset the
> card's soft configuration.  (It's likely that your card's IRQ will
> have been stomped on, and possibly the shared memory address.)
> Presto, you should have a working card again!


The following bozotic program may be of assistance. It was easier to
write this than to find (and bring myself to boot) DOS and run DEBUG.


-----8<-------------

/*
 * 	THE BOZO SOFTWARE FOUNDATION MARRIAGE LICENSE
 * 			v0.1
 * 	Bozoleft(P) 1996 The Bozo Softwar Foundation, Inc.
 * 
 * This document must be included in its entirety in all future Bozo Softwar
 * Foundation (BSF) software products, and any works derived from said BSF
 * products, including all documents and files.
 * 
 * The belowpostmentioned belowsigners of this document, or any document
 * which contains this document, which may be reproduced by any means
 * necessary (including blood) agree to be engaged in the most Holy
 * Interlock known in the universe, otherwise known as Marriage. (Except
 * for Noah. He's not allowed.) These aboveformentioned belowsigners
 * agree to:
 * 
 * 	* sleep in the same general area of the country at least
 * 	  once a year
 * 	* donate $50,000 to the charity of their choice (which may
 * 	  be themselves)
 * 	* never rat on each other, unless necessary
 * 	* always use the Ellemtel C++ coding style, even when writing
 * 	  personal correspondence
 * 	* eat at least two square meals a month
 * 	* always leave the toilet seat up, so the next person falls
 * 	  into the bowl and gets stuck
 * 	* bring up their children in the Bozo way
 * 	* criticize each other's grammatical habits consistently
 * 	* not sell this document or any document that contains this
 * 	  license, or remove or modify any part of this document
 * 
 * Any violation of the aboveforementioned agreements will result in
 * the immediate spanking of the violating person by all of the
 * signers, including themselves.
 * 
 * Furthermore, we hereby declare that Bill Gates, Esq. its spousal unit,
 * and any users of the products produced by Bill Gates, Esq., MicroLose,
 * and most especially Windows/NonTasking, have already inherently signed
 * this agreement, and are completely bound by its rules.
 * 
 */ 

/*
 * bozopioker.c
 * 
 * play poker with your machine's PIO space
 * bozotically, it uses a deprecated interface
 *
 * has proven especially bozotic for re-enslaving stoned SMC
 * ethercards who have had their bozo-nature exposed by a certain
 * BozoProbe(BM) routine in the installation kernels for an
 * unspecified 4.4BSD-derived Unix-like Operating System herinafter
 * referred to as "NetBSD 1.1"
 * 
 * CLAIMER: the Bozotic SoftWar Foundation takes all responsibility
 * for anything bozotic you may find (or do) while poking around in PC
 * hardware 
 *
 */

#include <fcntl.h>
#include <stdio.h>
#include <machine/pio.h>

void main (void)
{
  int finished = 0, error = 0;
  unsigned int port, val;
  char cmd, line[80];
    
  printf ("bozotic inb/outb pioker\n");
  if (!open("/dev/io", O_RDWR)) 
    {
      perror("open");
      exit (1);
    }
  
  while (!finished) 
    {
      fgets(line, 79, stdin);
      switch (sscanf(line, "%c %x %x\n", &cmd, &port, &val)) 
	{
	case 1:
	  if (cmd == 'q') 
	    finished = 1; 
	  else 
	    error = 1;
	  break;
	case 2:
	  if (cmd == 'i')
	    printf ("inb %x -- %x\n", port, inb(port));
	  else
	    error = 1;
	  break;
	case 3:
	  if (cmd == 'o') 
	    {
	      printf("outb %x %x\n", port, val);
	      outb(port, val);
	    }
	  else
	    error = 1;
	  break;
	default:
	  error = 1;
	}
      if (error) 
	{
	  printf("bozo \n");
	  error = 0;
	}
    }

  printf("Flush!\n");

}