From: vixie@pa.dec.com (Paul A Vixie)
Subject: Re: MicroVax II, Reno & Emulex
Organization: DEC Network Software Lab
Date: 10 Nov 92 10:50:37

The UDA50 software interface is not as well-defined as the manual would
like you to believe.  Every UDA50-lookalike is a little bit different,
and to make it work on your Emulex you will probably need to hack.  That
said, here are mine, which work on a KDA50 (QBUS version).  It has patches
from the net, from Chris Torek, and from personal experience.  Runs on Reno.
You will have the best luck with this if you gen your kernel with
"options QBA", which you are probably already doing since you have a GPX.

*** uda.c.orig	Sat Jul 11 18:59:45 1992
--- uda.c	Sun Jul 12 01:58:51 1992
***************
*** 211,215 ****
  struct	disklabel udalabel[NRA];
  
! u_short	udastd[] = { 0772150, 0772550, 0777550, 0 };
  struct	uba_driver udadriver =
   { udaprobe, udaslave, udaattach, udadgo, udastd, "ra", udadinfo, "uda",
--- 211,215 ----
  struct	disklabel udalabel[NRA];
  
! u_short	udastd[] = { 0772150, 0760334, 0772550, 0777550, 0 };
  struct	uba_driver udadriver =
   { udaprobe, udaslave, udaattach, udadgo, udastd, "ra", udadinfo, "uda",
***************
*** 336,344 ****
  	 * this manual myself.
  	 */
- #if defined(QBA) && !defined(GENERIC)
- 	s = spl6();
- #endif
  	tries = 0;
  again:
  	udaddr->udaip = 0;		/* start initialisation */
  	timeout = todr() + 1000;	/* timeout in 10 seconds */
--- 336,345 ----
  	 * this manual myself.
  	 */
  	tries = 0;
  again:
+ #if defined(QBA) && !defined(GENERIC)
+ 	sc->sc_ipl = 0;			/* magic cookie */
+ 	s = splx(0x17);			/* BR3 */
+ #endif
  	udaddr->udaip = 0;		/* start initialisation */
  	timeout = todr() + 1000;	/* timeout in 10 seconds */
***************
*** 346,362 ****
  		if (todr() > timeout)
  			goto bad;
  	udaddr->udasa = UDA_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | UDA_IE |
  		(sc->sc_ivec >> 2);
! 	while ((udaddr->udasa & UDA_STEP2) == 0)
! 		if (todr() > timeout)
  			goto bad;
  
  	/* should have interrupted by now */
  #ifdef QBA
  #ifndef GENERIC
! 	sc->sc_ipl = br = qbgetpri();
  #else
! 	sc->sc_ipl = br = 0x15;
  #endif
  #endif
  	return (sizeof (struct udadevice));
--- 347,393 ----
  		if (todr() > timeout)
  			goto bad;
+ 	/* if we get here, we should conclude an MSCP ctlr is present*/
+ 
+ 	/* program the vector, enable interrupts, and initialize */
  	udaddr->udasa = UDA_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | UDA_IE |
  		(sc->sc_ivec >> 2);
! 	while ((udaddr->udasa & UDA_STEP2) == 0) {
! 		if (todr() > timeout) {
! #if defined(QBA) && !defined(GENERIC)
! 	/* The ctlr is there, but failed to acknowledge that we
! 	 * enabled interrupts.  Perhaps the ctlr is a KDA-50. Before a
! 	 * KDA-50 sets this bit it requests an interrupt, and doesn't
! 	 * set the bit until the CPU acks the interrupt.  But we are
! 	 * running with the CPU at spl6() so that qbgetpri() will work,
! 	 * which means the interrupt isn't granted and the ctlr appears dead.
! 	 * Gross hack: drop the CPU priority and see if the ctlr responds
! 	 * quickly. If so, give up on qbgetpri().
! 	 *
! 	 * (comment and idea from usenet; code below by paul vixie (25may92)
! 	 */
! 			int pri;
! 
! 			for (pri = 0x17;  pri >= 0x14;  pri--) {
! 				splx(pri - 1);
! 				if (udaddr->udasa & UDA_STEP2) {
! 					sc->sc_ipl = br = pri;
! 					break;
! 				}
! 			}
! #else /*QBA && !GENERIC*/
  			goto bad;
+ #endif /*QBA && !GENERIC*/
+ 		} /* if timeout */
+ 	} /* while !STEP2 */
  
  	/* should have interrupted by now */
  #ifdef QBA
+ 	if (!sc->sc_ipl) {
  #ifndef GENERIC
! 		sc->sc_ipl = br = qbgetpri();
  #else
! 		sc->sc_ipl = br = 0x15;
  #endif
+ 	}
  #endif
  	return (sizeof (struct udadevice));
***************
*** 2298,2301 ****
--- 2329,2334 ----
  	register struct disklabel *lp;
  {
+ 	register int part;
+ 
  	lp->d_nsectors = ra->ra_geom.rg_nsectors;
  	lp->d_ntracks = ra->ra_geom.rg_ntracks;
***************
*** 2303,2309 ****
  	lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
  	bcopy("ra??", lp->d_typename, sizeof("ra??"));
! 	lp->d_npartitions = 1;
! 	lp->d_partitions[0].p_offset = 0;
! 	lp->d_partitions[0].p_size = lp->d_secperunit;
  }
  #endif /* NUDA > 0 */
--- 2336,2346 ----
  	lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
  	bcopy("ra??", lp->d_typename, sizeof("ra??"));
! 	for (part = 0;  part < RAWPART;  part++) {
! 		lp->d_partitions[part].p_offset = 0;
! 		lp->d_partitions[part].p_size = 0;
! 	}
! 	lp->d_partitions[part].p_offset = 0;
! 	lp->d_partitions[part].p_size = lp->d_secperunit;
! 	lp->d_npartitions = part+1;
  }
  #endif /* NUDA > 0 */
--
Paul Vixie, DEC Network Systems Lab	
Palo Alto, California, USA         	"Don't be a rebel, or a conformist;
<vixie@pa.dec.com> decwrl!vixie		they're the same thing, anyway.  Find
<paul@vix.com>     vixie!paul		your own path, and stay on it."  -me