[net.sources] bad memory chip location

phil (05/09/83)

So you say you've been getting soft memory errors? Tired of looking through
the tables to find the location of the faulty chip? I was, so with the help
of David Galloway we came up with this handy dandy badchip address converter.
If you are using National Semiconductor memory it may be of some use to you.


						...utcsrgv!utecfa!phil

/* badchip address syndrome -- Takes the address and syndrome bits printed
 * by the 4.1BSD kernel soft memory error message. It translates the address
 * into the board and bank number where the failing chip can be found and
 * then translates the bank and syndrome numbers into a chip location according
 * to the map on page 20 of the NS780 MEMORY INSTALLATION GUIDE.
 */

/* Assumes National Semiconductor 512K boards, with the memory boards in
 * odd slot numbers, and plenum (blank) boards in even slot numbers.
 */

long atox();

main(argc, argv)
	int argc;
	char *argv[];
	{
	long address, syndrome;
	int slot, bank;
	int offset,border,U0;

	if(argc != 3)
		{
		printf("usage: badchip address syndrome\n");
		exit(1);
		}

	address = atox(argv[1]);
	syndrome = atox(argv[2]);

	/* The slot number comes from bits 19-17 of the address */
	slot = (address>>17)&07;
	slot = 17 - 2*slot;

	/* The bank number (0-3) comes from bits 16-15 of the address */
	bank = (address>>15)&03;

	printf("Board in slot %d, bank %d", slot, bank);

	/* RAM DECODE according to NS780 INSTALLATION GUIDE */
	/* Find the U# for bank 0, then adjust for correct bank. */


	/* The syndrome numbers associated with data bits C0 - C7 do not */
	/* easily map to their respective RAMS, so they are done separately */

	switch(syndrome)
	{
	case 128:
		U0 = 54;
		break;

	case 32:
		U0 = 55;
		break;

	case 8:
		U0 = 72;
		break;

	case 2:
		U0 = 73;
		break;

	case 64:
		U0 = 90;
		break;

	case 16:
		U0 = 91;
		break;

	case 4:
		U0 = 108;
		break;

	case 1:
		U0 = 109;
		break;

	/* Decode majority of syndrome numbers */

	default:

	/* Syndrome number is 8 bits long. "border" holds value of*/
	/* bit 0 and bit 7 (first & last bits). This is used to break the   */
	/* syndrome numbers into four categories 00, 01 */
	/* 10,11 according to their border.             */

		border = ((syndrome >> 6) & 00002);
		border |= (syndrome & 000001);

	/* Lowest U# is 38, so an offset is used to adjust */

		offset = 0;
		U0 = 0;

		switch(border)
		{

	/* border of 2 or 3 uses bits 6 4 3 2 1 (of the syndrome) */
	/* in positions               4 3 2 1 0, for the U#.      */

		case 2:
			offset = 36;
		case 3:
			offset += 57;
			U0 = (syndrome & 00036) >>1 ;
			U0 |= (syndrome & 0100) >> 2;
			U0 = offset - U0;
			break;

	/* border of 0 or 1 uses bits 6 4 3 2 1 (of the syndrome) */
	/* in posotions               3 2 4 1 0, for the U#       */

		case 0:
			offset = 36;
		case 1:
			offset += 75;
			U0 = (syndrome & 00006) >>1;
			if((syndrome & 0130) == 0130)
			{
				U0 |= (00020);
			}
			else
			{
				U0 |= (syndrome & 0020) >> 2;
				U0 |= (syndrome & 00100) >> 3;
				
			}
			U0 = offset - U0;
			break;
		default:
			printf("something went wrong with the border bits\n");
			exit(1);
		}
		break;
	}

	/* adjust for correct bank */

	printf("   U%d\n",bank*72 + U0);
}



long atox(string)
	char *string;
	{
	long var;

	sscanf(string, "%x", &var);
	return(var);
	}