[net.bugs.4bsd] Autoconfigure doesn't find overlapping disk/tape controllers

donn@sdchema.UUCP (06/09/84)

Subject: Autoconfigure doesn't find overlapping disk/tape controllers
Index:	sys/vax/autoconf.c 4.2BSD

Description:
	When the system is running through autoconfiguration, it can
	miss the fact that two mass storage devices are claimed to be
	at the same CSR.  Moreover the system does not complain if the
	register set of one controller overlaps with another.

Repeat-By:
	We had the following lines in our config file:

	----------------------------------------------------------------
	controller	sc0	at uba0 csr 0176700		vector upintr
	disk		up0	at sc0 drive 0
	disk		up1	at sc0 drive 1
	controller	sc1	at uba0 csr 0176600		vector upintr
	disk		up2	at sc1 drive 0
	disk		up3	at sc1 drive 6
	controller	sc2	at uba0 csr 0176500		vector upintr
	disk		up4	at sc2 drive 0
	disk		up5	at sc2 drive 1
	----------------------------------------------------------------

	Only sc0 was actually in the system.  The default CSR address
	for the 'up' driver is 0176700.  The result was that the system
	did the following when booted:

	----------------------------------------------------------------
	...
	sc0 at uba0 csr 176700 vec 254, ipl 15
	up0 at sc0 slave 0
	sc1 at uba0 csr 176700 didn't interrupt
	sc2 at uba0 csr 176700 didn't interrupt
	...
	----------------------------------------------------------------

	Two things happened here: for sc1 and sc2, the stated CSR was
	not active, so the system tried the default CSR; and the system
	did not realize that the default CSR was already taken.

Fix:
	I have two gripes with the autoconfigure code.  I don't want
	the system to check the 'default address' if the specified CSR
	is not present; and the system should not attempt to locate a
	device in a place in the Unibus I/O page where another device
	has already found.  (The 'default address' can still be used by
	specifying an address of 0 in the config file.) The following
	changes to unifind() in autoconfigure.c make the first behavior
	a compile-time option, and fix the second.  Only the part that
	turns off checking for default addresses has been tested, but
	it all compiles and runs okay.

	----------------------------------------------------------------
	*** /tmp/,RCSt1021690	Fri Jun  8 15:46:41 1984
	--- autoconf.c	Tue Jun  5 17:21:46 1984
	***************
	*** 386,392
		u_short *reg, *ap, addr;
		struct uba_hd *uhp;
		struct uba_driver *udp;
	! 	int i, (**ivec)(), haveubasr;
		caddr_t ualloc, zmemall();
		extern int catcher[256];
	  

	--- 386,392 -----
		u_short *reg, *ap, addr;
		struct uba_hd *uhp;
		struct uba_driver *udp;
	! 	int i, warned, (**ivec)(), haveubasr;
		caddr_t ualloc, zmemall();
		extern int catcher[256];
	  
	***************
	*** 478,484
			 * at that address, try all the standard addresses
			 * in the driver til we find it
			 */
	! 	    for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) {
	  
			if (ualloc[ubaoff(addr)])
				continue;

	--- 478,495 -----
			 * at that address, try all the standard addresses
			 * in the driver til we find it.
			 */
	! #ifdef	STANDARDAUTOCONF
	! 		ap = udp->ud_addr;
	! #else	STANDARDAUTOCONF
	! 		/*
	! 		 * Only check for standard devices if addr is zero.
	! 		 */
	! 		if (addr)
	! 			ap = &addr;
	! 		else
	! 			ap = udp->ud_addr;
	! #endif	STANDARDAUTOCONF
	! 	    for (; addr || (addr = *ap++); addr = 0) {
	  
			if (ualloc[ubaoff(addr)]) {
				if (ap == &addr)
	***************
	*** 480,486
			 */
		    for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) {
	  
	! 		if (ualloc[ubaoff(addr)])
				continue;
			reg = ubaddr(addr);
			if (badaddr((caddr_t)reg, 2))

	--- 491,500 -----
	  #endif	STANDARDAUTOCONF
		    for (; addr || (addr = *ap++); addr = 0) {
	  
	! 		if (ualloc[ubaoff(addr)]) {
	! 			if (ap == &addr)
	! 				printf("WARNING: %s%d: csr %o already used\n",
	! 				    udp->ud_mname, um->um_ctlr, addr);
				continue;
			}
			reg = ubaddr(addr);
	***************
	*** 482,487
	  
			if (ualloc[ubaoff(addr)])
				continue;
			reg = ubaddr(addr);
			if (badaddr((caddr_t)reg, 2))
				continue;

	--- 496,502 -----
					printf("WARNING: %s%d: csr %o already used\n",
					    udp->ud_mname, um->um_ctlr, addr);
				continue;
	+ 		}
			reg = ubaddr(addr);
			if (badaddr((caddr_t)reg, 2))
				continue;
	***************
	*** 512,517
				continue;
			}
			printf("vec %o, ipl %x\n", cvec, br);
			um->um_alive = 1;
			um->um_ubanum = numuba;
			um->um_hd = &uba_hd[numuba];

	--- 527,540 -----
				continue;
			}
			printf("vec %o, ipl %x\n", cvec, br);
	+ 		warned = 0;
	+ 		while ( --i >= 0 )
	+ 			if (! warned && ualloc[ubaoff(addr+i)]) {
	+ 				printf("WARNING: %s%d: Address overlap at %o\n",
	+ 				    udp->ud_mname, um->um_ctlr, (addr+i)&~01);
	+ 				++warned;
	+ 			} else
	+ 				ualloc[ubaoff(addr+i)] = 1;
			um->um_alive = 1;
			um->um_ubanum = numuba;
			um->um_hd = &uba_hd[numuba];
	***************
	*** 558,563
			    ui->ui_alive || ui->ui_slave != -1)
				continue;
			addr = (u_short)ui->ui_addr;
	  
		    for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) {
			

	--- 581,594 -----
			    ui->ui_alive || ui->ui_slave != -1)
				continue;
			addr = (u_short)ui->ui_addr;
	+ #ifdef	STANDARDAUTOCONF
	+ 		ap = udp->ud_addr;
	+ #else	STANDARDAUTOCONF
	+ 		if (addr)
	+ 			ap = &addr;
	+ 		else
	+ 			ap = udp->ud_addr;
	+ #endif	STANDARDAUTOCONF
	  
		    for (; addr || (addr = *ap++); addr = 0) {
			
	***************
	*** 559,565
				continue;
			addr = (u_short)ui->ui_addr;
	  
	! 	    for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) {
			
			if (ualloc[ubaoff(addr)])
				continue;

	--- 590,596 -----
				ap = udp->ud_addr;
	  #endif	STANDARDAUTOCONF
	  
	! 	    for (; addr || (addr = *ap++); addr = 0) {
			
			if (ualloc[ubaoff(addr)]) {
				if (ap == &addr)
	***************
	*** 561,567
	  
		    for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) {
			
	! 		if (ualloc[ubaoff(addr)])
				continue;
			reg = ubaddr(addr);
			if (badaddr((caddr_t)reg, 2))

	--- 592,601 -----
	  
		    for (; addr || (addr = *ap++); addr = 0) {
			
	! 		if (ualloc[ubaoff(addr)]) {
	! 			if (ap == &addr)
	! 				printf("WARNING: %s%d: csr %o already used\n",
	! 				    udp->ud_mname, um->um_ctlr, addr);
				continue;
			}
			reg = ubaddr(addr);
	***************
	*** 563,568
			
			if (ualloc[ubaoff(addr)])
				continue;
			reg = ubaddr(addr);
			if (badaddr((caddr_t)reg, 2))
				continue;

	--- 597,603 -----
					printf("WARNING: %s%d: csr %o already used\n",
					    udp->ud_mname, um->um_ctlr, addr);
				continue;
	+ 		}
			reg = ubaddr(addr);
			if (badaddr((caddr_t)reg, 2))
				continue;
	***************
	*** 593,600
				continue;
			}
			printf("vec %o, ipl %x\n", cvec, br);
	! 		while (--i >= 0)
	! 			ualloc[ubaoff(addr+i)] = 1;
			ui->ui_hd = &uba_hd[numuba];
			for (ivec = ui->ui_intr; *ivec; ivec++) {
				ui->ui_hd->uh_vec[cvec/4] =

	--- 628,641 -----
				continue;
			}
			printf("vec %o, ipl %x\n", cvec, br);
	! 		warned = 0;
	! 		while ( --i >= 0 )
	! 			if (! warned && ualloc[ubaoff(addr+i)]) {
	! 				printf("WARNING: %s%d: Address overlap at %o\n",
	! 				    udp->ud_mname, um->um_ctlr, (addr+i)&~01 );
	! 				++warned;
	! 			} else
	! 				ualloc[ubaoff(addr+i)] = 1;
			ui->ui_hd = &uba_hd[numuba];
			for (ivec = ui->ui_intr; *ivec; ivec++) {
  			ui->ui_hd->uh_vec[cvec/4] =
	----------------------------------------------------------------

More scraps from the software closet,

Donn Seeley    UCSD Chemistry Dept.       ucbvax!sdcsvax!sdchema!donn
32 52' 30"N 117 14' 25"W  (619) 452-4016  sdcsvax!sdchema!donn@nosc.ARPA