xref: /csrg-svn/sys/pmax/dev/scsi.c (revision 63207)
152130Smckusick /*
2*63207Sbostic  * Copyright (c) 1992, 1993
3*63207Sbostic  *	The Regents of the University of California.  All rights reserved.
452130Smckusick  *
552130Smckusick  * This code is derived from software contributed to Berkeley by
652130Smckusick  * Ralph Campbell.
752130Smckusick  *
852130Smckusick  * %sccs.include.redist.c%
952130Smckusick  *
10*63207Sbostic  *	@(#)scsi.c	8.1 (Berkeley) 06/10/93
1152130Smckusick  */
1252130Smckusick 
1352130Smckusick /*
1452130Smckusick  * SCSI utility routines for making SCSI device drivers easier.
1552130Smckusick  */
1652130Smckusick 
1756522Sbostic #include <sys/param.h>
1852130Smckusick 
1956525Sbostic #include <pmax/dev/device.h>
2056525Sbostic #include <pmax/dev/scsi.h>
2152130Smckusick 
2252130Smckusick /*
2352130Smckusick  * The error codes for class 0-6 sense data are class specific.
2452130Smckusick  * The follow arrays of strings are used to print error messages.
2552130Smckusick  */
2652130Smckusick static char *Class0Errors[] = {
2752130Smckusick 	"No sense data",
2852130Smckusick 	"No index signal",
2952130Smckusick 	"No seek complete",
3052130Smckusick 	"Write fault",
3152130Smckusick 	"Drive not ready",
3252130Smckusick 	"Drive not selected",
3352130Smckusick 	"No Track 00",
3452130Smckusick 	"Multiple drives selected",
3552130Smckusick 	"No address acknowledged",
3652130Smckusick 	"Media not loaded",
3752130Smckusick 	"Insufficient capacity",
3852130Smckusick 	"Drive timeout",
3952130Smckusick };
4052130Smckusick static char *Class1Errors[] = {
4152130Smckusick 	"ID CRC error",
4252130Smckusick 	"Unrecoverable data error",
4352130Smckusick 	"ID address mark not found",
4452130Smckusick 	"Data address mark not found",
4552130Smckusick 	"Record not found",
4652130Smckusick 	"Seek error",
4752130Smckusick 	"DMA timeout error",
4852130Smckusick 	"Write protected",
4952130Smckusick 	"Correctable data check",
5052130Smckusick 	"Bad block found",
5152130Smckusick 	"Interleave error",
5252130Smckusick 	"Data transfer incomplete",
5352130Smckusick 	"Unformatted or bad format on drive",
5452130Smckusick 	"Self test failed",
5552130Smckusick 	"Defective track (media errors)",
5652130Smckusick };
5752130Smckusick static char *Class2Errors[] = {
5852130Smckusick 	"Invalid command",
5952130Smckusick 	"Illegal block address",
6052130Smckusick 	"Aborted",
6152130Smckusick 	"Volume overflow",
6252130Smckusick };
6352130Smckusick static char *Class7Errors[] = {
6452130Smckusick 	"No sense data",
6552130Smckusick 	"Recoverable error",
6652130Smckusick 	"Drive not ready",
6752130Smckusick 	"Media error",
6852130Smckusick 	"Hardware error",
6952130Smckusick 	"Illegal request",
7052130Smckusick 	"Unit attention",
7152130Smckusick 	"Write protected",
7252130Smckusick 	"Blank check error",
7352130Smckusick 	"Vendor error",
7452130Smckusick 	"Powerup failure",
7552130Smckusick 	"Abort",
7652130Smckusick 	"Equal",
7752130Smckusick 	"Overflow",
7852130Smckusick 	"Reserved14/miscompare",
7952130Smckusick };
8052130Smckusick static int scsiNumErrors[] = {
8152130Smckusick 	sizeof(Class0Errors) / sizeof(char *),
8252130Smckusick 	sizeof(Class1Errors) / sizeof(char *),
8352130Smckusick 	sizeof(Class2Errors) / sizeof(char *),
8452130Smckusick 	0, 0, 0, 0, 0,
8552130Smckusick };
8652130Smckusick static char **scsiErrors[] = {
8752130Smckusick 	Class0Errors,
8852130Smckusick 	Class1Errors,
8952130Smckusick 	Class2Errors,
9052130Smckusick };
9152130Smckusick 
9252130Smckusick /*
9352130Smckusick  * Decode the sense data and print a suitable message.
9452130Smckusick  */
scsiPrintSense(sp,len)9552130Smckusick scsiPrintSense(sp, len)
9652130Smckusick 	register ScsiClass7Sense *sp;
9752130Smckusick 	int len;
9852130Smckusick {
9952130Smckusick 	ScsiClass0Sense *sp0;
10052130Smckusick 	int class, code;
10152130Smckusick 
10252130Smckusick 	if (sp->error7 != 0x70) {
10352130Smckusick 		sp0 = (ScsiClass0Sense *)sp;
10452130Smckusick 		class = sp0->error >> 4;
10552130Smckusick 		code = sp0->error & 0xF;
10652130Smckusick 		if (code >= scsiNumErrors[class])
10752130Smckusick 			printf("sense error 0x%x", sp0->error);
10852130Smckusick 		else
10952130Smckusick 			printf("%s", scsiErrors[class][code]);
11052130Smckusick 		if (sp->valid)
11152130Smckusick 			printf(", blk %d", (sp0->highAddr << 16) |
11252130Smckusick 				(sp0->midAddr << 8) | sp0->lowAddr);
11352130Smckusick 	} else {
11452130Smckusick 		if (sp->key >= sizeof(Class7Errors) / sizeof(char *))
11552130Smckusick 			printf("sense class 7 error 0x%x", sp->key);
11652130Smckusick 		else
11752130Smckusick 			printf("%s", Class7Errors[sp->key]);
11853082Sralph 		if (sp->fileMark)
11953082Sralph 			printf(", file mark seen");
12053082Sralph 		if (sp->endOfMedia)
12153082Sralph 			printf(", end of media seen");
12253082Sralph 		if (sp->badBlockLen)
12353082Sralph 			printf(", block length mis-match");
12452130Smckusick 		if (sp->valid)
12552130Smckusick 			printf(", blk %d", (sp->info1 << 24) |
12652130Smckusick 				(sp->info2 << 16) | (sp->info3 << 8) |
12752130Smckusick 				sp->info4);
12852130Smckusick 	}
12952130Smckusick 	printf("\n");
13052130Smckusick }
13152130Smckusick 
13252130Smckusick /*
13352130Smckusick  * Setup a command block for a SCSI Group0 command.
13452130Smckusick  */
13552130Smckusick void
scsiGroup0Cmd(cmd,lun,block,count,c)13652130Smckusick scsiGroup0Cmd(cmd, lun, block, count, c)
13752130Smckusick 	unsigned cmd;			/* group0 SCSI command */
13852130Smckusick 	unsigned lun;			/* Logical Unit Number */
13952130Smckusick 	register unsigned block;	/* starting block number for transfer */
14052130Smckusick 	unsigned count;			/* # of sectors/bytes to transfer */
14152130Smckusick 	register ScsiGroup0Cmd *c;	/* command to be filled in */
14252130Smckusick {
14352130Smckusick 
14452130Smckusick 	c->command = cmd;
14552130Smckusick 	c->unitNumber = lun;
14652130Smckusick 	c->highAddr = block >> 16;
14752130Smckusick 	c->midAddr = block >> 8;
14852130Smckusick 	c->lowAddr = block;
14952130Smckusick 	c->blockCount = count;
15052130Smckusick 	c->control = 0;
15152130Smckusick }
15252130Smckusick 
15352130Smckusick /*
15452130Smckusick  * Setup a command block for a SCSI Group1 command.
15552130Smckusick  */
15652130Smckusick void
scsiGroup1Cmd(cmd,lun,block,count,c)15752130Smckusick scsiGroup1Cmd(cmd, lun, block, count, c)
15852130Smckusick 	unsigned cmd;			/* group0 SCSI command */
15952130Smckusick 	unsigned lun;			/* Logical Unit Number */
16052130Smckusick 	register unsigned block;	/* starting block number for transfer */
16152130Smckusick 	unsigned count;			/* # of sectors/bytes to transfer */
16252130Smckusick 	register ScsiGroup1Cmd *c;	/* command to be filled in */
16352130Smckusick {
16452130Smckusick 
16552130Smckusick 	c->command = cmd;
16652130Smckusick 	c->unitNumber = lun;
16752130Smckusick 	c->pad1 = 0;
16852130Smckusick 	c->highAddr = block >> 24;
16952130Smckusick 	c->midHighAddr = block >> 16;
17052130Smckusick 	c->midLowAddr = block >> 8;
17152130Smckusick 	c->lowAddr = block;
17252130Smckusick 	c->pad2 = 0;
17352130Smckusick 	c->highBlockCount = count >> 8;
17452130Smckusick 	c->lowBlockCount = count;
17552130Smckusick 	c->control = 0;
17652130Smckusick }
177