[comp.bugs.4bsd] ts11 driver races in open, has bogus probe routine

chris@mimsy.UUCP (Chris Torek) (11/01/87)

Index: sys/vaxuba/ts.c 4.3BSD Fix

Description:
	The configuration code for the ts11 driver guesses at
	the interrupt vector (0224 or 0260) instead of making
	the device interrupt.  The open routine can allow two
	processes to open the drive simultaneously.

	[Other bugs, not fixed here, include
	 - large raw I/O (>63kB) fails (not a problem ... yet)
	 - configuring two ts'es on one zs break things
	 - the dump code does not do anything]

Repeat-by:
	The race is hard to repeat.  The other problem is obvious.

Fix:
	Beware: this is not what I am running.  (I changed many
	other things; that context diff is bigger than the source.)
	It should work though.  The DELAYs can probably be reduced,
	but an extra 40 milliseconds per boot is not long.

RCS file: RCS/ts.c,v
retrieving revision 1.1
retrieving revision 1.2.1.2
diff -c2 -r1.1 -r1.2.1.2
*** /tmp/,RCSt1007746	Sun Nov  1 04:52:25 1987
--- /tmp/,RCSt2007746	Sun Nov  1 04:52:33 1987
***************
*** 116,123 ****
   */
  /*ARGSUSED*/
! tsprobe(reg)
  	caddr_t reg;
  {
  	register int br, cvec;		/* must be r11,r10; value-result */
  
  #ifdef lint
--- 116,129 ----
   */
  /*ARGSUSED*/
! tsprobe(reg, ctlr, um)
  	caddr_t reg;
+ 	int ctlr;
+ 	struct uba_ctlr *um;
  {
  	register int br, cvec;		/* must be r11,r10; value-result */
+ 	register struct tsdevice *addr = (struct tsdevice *)reg;
+ 	register struct ts_softc *sc;
+ 	register int i;
+ 	int a;
  
  #ifdef lint
***************
*** 125,135 ****
  	tsintr(0);
  #endif
! 	((struct tsdevice *)reg)->tssr = 0;
  	DELAY(100);
! 	if ((((struct tsdevice *)reg)->tssr & TS_NBA) == 0)
! 		return(0);
! 	/* IT'S TOO HARD TO MAKE THIS THING INTERRUPT JUST TO FIND ITS VECTOR */
! 	cvec = ((unsigned)reg) & 07 ? 0260 : 0224;
! 	br = 0x15;
  	return (sizeof (struct tsdevice));
  }
--- 131,168 ----
  	tsintr(0);
  #endif
! 	addr->tssr = 0;		/* initialize subsystem */
  	DELAY(100);
! 	if ((addr->tssr & TS_NBA) == 0)
! 		return (0);
! 
! 	/*
! 	 * Make it interrupt.
! 	 * TS_SETCHR|TS_IE alone refuses to interrupt for me.
! 	 */
! 	sc = &ts_softc[ctlr];
! 	a = uballoc(numuba, (caddr_t)sc, sizeof(*sc), 0);
! 	sc->sc_ubaddr = (struct ts_softc *)UBAI_ADDR(a);
! 	i = (int)&sc->sc_ubaddr->sc_cmd;
! 	sc->sc_uba = i + ((i >> 16) & 3);
! 	i = (int)&sc->sc_ubaddr->sc_char;
! 	sc->sc_cmd.c_loba = i;
! 	sc->sc_cmd.c_hiba = (i >> 16) & 3;
! 	sc->sc_cmd.c_size = sizeof(struct ts_char);
! 	sc->sc_cmd.c_cmd = TS_ACK | TS_SETCHR;
! 	sc->sc_char.char_addr = (int)&sc->sc_ubaddr->sc_sts;
! 	sc->sc_char.char_size = sizeof(struct ts_sts);
! 	sc->sc_char.char_mode = 0; /* mode is unimportant */
! 	addr->tsdb = sc->sc_uba;
! 	DELAY(20000);
! 	sc->sc_cmd.c_cmd = TS_ACK | TS_CVC | TS_IE | TS_SENSE;
! 	sc->sc_cmd.c_repcnt = 1;
! 	addr->tsdb = sc->sc_uba;
! 	DELAY(20000);
! 	/* should have interrupted by now */
! 
! 	addr->tssr = 0;		/* put it back the way it was */
! 	DELAY(100);
! 	ubarelse(numuba, &a);
! 
  	return (sizeof (struct tsdevice));
  }
***************
*** 184,191 ****
  	if ((sc = &ts_softc[tsunit])->sc_openf)
  		return (EBUSY);
! 	if (tsinit(tsunit))
  		return (ENXIO);
  	tscommand(dev, TS_SENSE, 1);
  	if ((sc->sc_sts.s_xs0&TS_ONL) == 0) {
  		uprintf("ts%d: not online\n", tsunit);
  		return (EIO);
--- 217,228 ----
  	if ((sc = &ts_softc[tsunit])->sc_openf)
  		return (EBUSY);
! 	sc->sc_openf = 1;
! 	if (tsinit(tsunit)) {
! 		sc->sc_openf = 0;
  		return (ENXIO);
+ 	}
  	tscommand(dev, TS_SENSE, 1);
  	if ((sc->sc_sts.s_xs0&TS_ONL) == 0) {
+ 		sc->sc_openf = 0;
  		uprintf("ts%d: not online\n", tsunit);
  		return (EIO);
***************
*** 192,199 ****
  	}
  	if ((flag&FWRITE) && (sc->sc_sts.s_xs0&TS_WLK)) {
  		uprintf("ts%d: no write ring\n", tsunit);
  		return (EIO);
  	}
- 	sc->sc_openf = 1;
  	sc->sc_blkno = (daddr_t)0;
  	sc->sc_nxrec = INF;
--- 229,236 ----
  	}
  	if ((flag&FWRITE) && (sc->sc_sts.s_xs0&TS_WLK)) {
+ 		sc->sc_openf = 0;
  		uprintf("ts%d: no write ring\n", tsunit);
  		return (EIO);
  	}
  	sc->sc_blkno = (daddr_t)0;
  	sc->sc_nxrec = INF;
***************
*** 252,260 ****
  	 */
  	if (sc->sc_mapped == 0) {
! 		ctsbuf[unit].b_un.b_addr = (caddr_t)sc;
! 		ctsbuf[unit].b_bcount = sizeof(*sc);
! 		i = ubasetup(um->um_ubanum, &ctsbuf[unit], 0);
! 		i &= 0777777;
! 		sc->sc_ubaddr = (struct ts_softc *)i;
  		sc->sc_mapped++;
  	}
--- 289,295 ----
  	 */
  	if (sc->sc_mapped == 0) {
! 		sc->sc_ubaddr =
! 			(struct ts_softc *)UBAI_ADDR(uballoc(um->um_ubanum,
! 				(caddr_t)sc, sizeof(*sc), 0));
  		sc->sc_mapped++;
  	}
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris