Subject: Re: "Blue & White" G3 (long)
To: None <port-macppc@netbsd.org>
From: Dan Winship <danw@MIT.EDU>
List: port-macppc
Date: 03/13/1999 17:21:45
OK, as suggested by Jason, here's a badaddr() for powerpc, and patches
to pci_machdep.c to use it to prevent the trap 300 while probing
non-existent PCI devices. The prototype obviously doesn't belong in
pci_machdep.c, but I couldn't put it in trap.h because locore.S
includes that, and I didn't know where else would be better.

This could probably also be used to replace some of the other code in
pci_machdep.c that hardcodes what devices it should look at when
probing the pci bus.

*** arch/powerpc/powerpc/trap.c.orig	Sat Mar 13 14:59:34 1999
--- arch/powerpc/powerpc/trap.c	Sat Mar 13 16:18:11 1999
***************
*** 64,69 ****
--- 64,70 ----
  
  volatile int astpending;
  volatile int want_resched;
+ static int mchk_expected, mchk_received;
  
  void
  trap(frame)
***************
*** 291,296 ****
--- 292,304 ----
  			trapsignal(p, SIGILL, EXC_PGM);
  		break;
  
+ 	case EXC_MCHK:
+ 		if (mchk_expected)
+ 			mchk_received++;
+ 		else
+ 			goto brain_damage;
+ 		break;
+ 
  	default:
  brain_damage:
  		printf("trap type %x at %x\n", type, frame->srr0);
***************
*** 479,481 ****
--- 487,532 ----
  	return 0;
  }
  #endif
+ 
+ int
+ badaddr(addr, size)
+ 	void *addr;
+ 	size_t size;
+ {
+ 	long rcpt;
+ 
+ 	/* Get rid of any stale machine checks that have been waiting. */
+ 	__asm__ volatile ("eieio; sync;");
+ 
+ 	/* Tell the trap code to expect a machine check. */
+ 	mchk_received = 0;
+ 	mchk_expected = 1;
+ 
+ 	/* Read from the test address. */
+ 	switch (size) {
+ 	case sizeof (u_int8_t):
+ 		rcpt = *(volatile u_int8_t *)addr;
+ 		break;
+ 
+ 	case sizeof (u_int16_t):
+ 		rcpt = *(volatile u_int16_t *)addr;
+ 		break;
+ 
+ 	case sizeof (u_int32_t):
+ 		rcpt = *(volatile u_int32_t *)addr;
+ 		break;
+ 
+ 	case sizeof (u_int64_t):
+ 		rcpt = *(volatile u_int64_t *)addr;
+ 		break;
+ 
+ 	default:
+ 		panic("badaddr: invalid size (%ld)\n", size);
+ 	}
+ 
+ 	/* Make sure we took the machine check, if we caused one. */
+ 	__asm__ volatile ("eieio; sync;");
+ 	mchk_expected = 0;
+ 
+ 	return mchk_received;
+ }
*** arch/macppc/pci/pci_machdep.c.orig	Sat Mar 13 15:20:08 1999
--- arch/macppc/pci/pci_machdep.c	Sat Mar 13 15:32:19 1999
***************
*** 59,64 ****
--- 59,66 ----
  #include <machine/pio.h>
  #include <machine/intr.h>
  
+ int	badaddr __P((void *addr, size_t size));
+ 
  #include <dev/pci/pcivar.h>
  #include <dev/pci/pcireg.h>
  
***************
*** 147,153 ****
  		r = &pci_bridges[0];
  
  		out32rb(r->addr, tag | reg);
! 		data = in32rb(r->data);
  		out32rb(r->addr, 0);
  	} else {
  		int bus, dev, func;
--- 149,158 ----
  		r = &pci_bridges[0];
  
  		out32rb(r->addr, tag | reg);
! 		if (badaddr(r->data, sizeof(r->data)))
! 			data = 0xffffffff;
! 		else
! 			data = in32rb(r->data);
  		out32rb(r->addr, 0);
  	} else {
  		int bus, dev, func;
***************
*** 174,180 ****
  		} else
  			out32rb(r->addr, tag | reg | 1);
  		DELAY(10);
! 		data = in32rb(r->data);
  		DELAY(10);
  		out32rb(r->addr, 0);
  		DELAY(10);
--- 179,188 ----
  		} else
  			out32rb(r->addr, tag | reg | 1);
  		DELAY(10);
! 		if (badaddr(r->data, sizeof(r->data)))
! 			data = 0xffffffff;
! 		else
! 			data = in32rb(r->data);
  		DELAY(10);
  		out32rb(r->addr, 0);
  		DELAY(10);