xref: /csrg-svn/sys/pmax/dev/scsi.c (revision 52130)
1*52130Smckusick /*
2*52130Smckusick  * Copyright (c) 1992 Regents of the University of California.
3*52130Smckusick  * All rights reserved.
4*52130Smckusick  *
5*52130Smckusick  * This code is derived from software contributed to Berkeley by
6*52130Smckusick  * Ralph Campbell.
7*52130Smckusick  *
8*52130Smckusick  * %sccs.include.redist.c%
9*52130Smckusick  *
10*52130Smckusick  *	@(#)scsi.c	7.1 (Berkeley) 01/07/92
11*52130Smckusick  */
12*52130Smckusick 
13*52130Smckusick /*
14*52130Smckusick  * SCSI utility routines for making SCSI device drivers easier.
15*52130Smckusick  */
16*52130Smckusick 
17*52130Smckusick #include "param.h"
18*52130Smckusick 
19*52130Smckusick #include "device.h"
20*52130Smckusick #include "scsi.h"
21*52130Smckusick 
22*52130Smckusick /*
23*52130Smckusick  * The error codes for class 0-6 sense data are class specific.
24*52130Smckusick  * The follow arrays of strings are used to print error messages.
25*52130Smckusick  */
26*52130Smckusick static char *Class0Errors[] = {
27*52130Smckusick 	"No sense data",
28*52130Smckusick 	"No index signal",
29*52130Smckusick 	"No seek complete",
30*52130Smckusick 	"Write fault",
31*52130Smckusick 	"Drive not ready",
32*52130Smckusick 	"Drive not selected",
33*52130Smckusick 	"No Track 00",
34*52130Smckusick 	"Multiple drives selected",
35*52130Smckusick 	"No address acknowledged",
36*52130Smckusick 	"Media not loaded",
37*52130Smckusick 	"Insufficient capacity",
38*52130Smckusick 	"Drive timeout",
39*52130Smckusick };
40*52130Smckusick static char *Class1Errors[] = {
41*52130Smckusick 	"ID CRC error",
42*52130Smckusick 	"Unrecoverable data error",
43*52130Smckusick 	"ID address mark not found",
44*52130Smckusick 	"Data address mark not found",
45*52130Smckusick 	"Record not found",
46*52130Smckusick 	"Seek error",
47*52130Smckusick 	"DMA timeout error",
48*52130Smckusick 	"Write protected",
49*52130Smckusick 	"Correctable data check",
50*52130Smckusick 	"Bad block found",
51*52130Smckusick 	"Interleave error",
52*52130Smckusick 	"Data transfer incomplete",
53*52130Smckusick 	"Unformatted or bad format on drive",
54*52130Smckusick 	"Self test failed",
55*52130Smckusick 	"Defective track (media errors)",
56*52130Smckusick };
57*52130Smckusick static char *Class2Errors[] = {
58*52130Smckusick 	"Invalid command",
59*52130Smckusick 	"Illegal block address",
60*52130Smckusick 	"Aborted",
61*52130Smckusick 	"Volume overflow",
62*52130Smckusick };
63*52130Smckusick static char *Class7Errors[] = {
64*52130Smckusick 	"No sense data",
65*52130Smckusick 	"Recoverable error",
66*52130Smckusick 	"Drive not ready",
67*52130Smckusick 	"Media error",
68*52130Smckusick 	"Hardware error",
69*52130Smckusick 	"Illegal request",
70*52130Smckusick 	"Unit attention",
71*52130Smckusick 	"Write protected",
72*52130Smckusick 	"Blank check error",
73*52130Smckusick 	"Vendor error",
74*52130Smckusick 	"Powerup failure",
75*52130Smckusick 	"Abort",
76*52130Smckusick 	"Equal",
77*52130Smckusick 	"Overflow",
78*52130Smckusick 	"Reserved14/miscompare",
79*52130Smckusick };
80*52130Smckusick static int scsiNumErrors[] = {
81*52130Smckusick 	sizeof(Class0Errors) / sizeof(char *),
82*52130Smckusick 	sizeof(Class1Errors) / sizeof(char *),
83*52130Smckusick 	sizeof(Class2Errors) / sizeof(char *),
84*52130Smckusick 	0, 0, 0, 0, 0,
85*52130Smckusick };
86*52130Smckusick static char **scsiErrors[] = {
87*52130Smckusick 	Class0Errors,
88*52130Smckusick 	Class1Errors,
89*52130Smckusick 	Class2Errors,
90*52130Smckusick };
91*52130Smckusick 
92*52130Smckusick /*
93*52130Smckusick  * Decode the sense data and print a suitable message.
94*52130Smckusick  */
95*52130Smckusick scsiPrintSense(sp, len)
96*52130Smckusick 	register ScsiClass7Sense *sp;
97*52130Smckusick 	int len;
98*52130Smckusick {
99*52130Smckusick 	ScsiClass0Sense *sp0;
100*52130Smckusick 	int class, code;
101*52130Smckusick 
102*52130Smckusick 	if (sp->error7 != 0x70) {
103*52130Smckusick 		sp0 = (ScsiClass0Sense *)sp;
104*52130Smckusick 		class = sp0->error >> 4;
105*52130Smckusick 		code = sp0->error & 0xF;
106*52130Smckusick 		if (code >= scsiNumErrors[class])
107*52130Smckusick 			printf("sense error 0x%x", sp0->error);
108*52130Smckusick 		else
109*52130Smckusick 			printf("%s", scsiErrors[class][code]);
110*52130Smckusick 		if (sp->valid)
111*52130Smckusick 			printf(", blk %d", (sp0->highAddr << 16) |
112*52130Smckusick 				(sp0->midAddr << 8) | sp0->lowAddr);
113*52130Smckusick 	} else {
114*52130Smckusick 		if (sp->key >= sizeof(Class7Errors) / sizeof(char *))
115*52130Smckusick 			printf("sense class 7 error 0x%x", sp->key);
116*52130Smckusick 		else
117*52130Smckusick 			printf("%s", Class7Errors[sp->key]);
118*52130Smckusick 		if (sp->valid)
119*52130Smckusick 			printf(", blk %d", (sp->info1 << 24) |
120*52130Smckusick 				(sp->info2 << 16) | (sp->info3 << 8) |
121*52130Smckusick 				sp->info4);
122*52130Smckusick 	}
123*52130Smckusick 	printf("\n");
124*52130Smckusick }
125*52130Smckusick 
126*52130Smckusick /*
127*52130Smckusick  * Setup a command block for a SCSI Group0 command.
128*52130Smckusick  */
129*52130Smckusick void
130*52130Smckusick scsiGroup0Cmd(cmd, lun, block, count, c)
131*52130Smckusick 	unsigned cmd;			/* group0 SCSI command */
132*52130Smckusick 	unsigned lun;			/* Logical Unit Number */
133*52130Smckusick 	register unsigned block;	/* starting block number for transfer */
134*52130Smckusick 	unsigned count;			/* # of sectors/bytes to transfer */
135*52130Smckusick 	register ScsiGroup0Cmd *c;	/* command to be filled in */
136*52130Smckusick {
137*52130Smckusick 
138*52130Smckusick 	c->command = cmd;
139*52130Smckusick 	c->unitNumber = lun;
140*52130Smckusick 	c->highAddr = block >> 16;
141*52130Smckusick 	c->midAddr = block >> 8;
142*52130Smckusick 	c->lowAddr = block;
143*52130Smckusick 	c->blockCount = count;
144*52130Smckusick 	c->control = 0;
145*52130Smckusick }
146*52130Smckusick 
147*52130Smckusick /*
148*52130Smckusick  * Setup a command block for a SCSI Group1 command.
149*52130Smckusick  */
150*52130Smckusick void
151*52130Smckusick scsiGroup1Cmd(cmd, lun, block, count, c)
152*52130Smckusick 	unsigned cmd;			/* group0 SCSI command */
153*52130Smckusick 	unsigned lun;			/* Logical Unit Number */
154*52130Smckusick 	register unsigned block;	/* starting block number for transfer */
155*52130Smckusick 	unsigned count;			/* # of sectors/bytes to transfer */
156*52130Smckusick 	register ScsiGroup1Cmd *c;	/* command to be filled in */
157*52130Smckusick {
158*52130Smckusick 
159*52130Smckusick 	c->command = cmd;
160*52130Smckusick 	c->unitNumber = lun;
161*52130Smckusick 	c->pad1 = 0;
162*52130Smckusick 	c->highAddr = block >> 24;
163*52130Smckusick 	c->midHighAddr = block >> 16;
164*52130Smckusick 	c->midLowAddr = block >> 8;
165*52130Smckusick 	c->lowAddr = block;
166*52130Smckusick 	c->pad2 = 0;
167*52130Smckusick 	c->highBlockCount = count >> 8;
168*52130Smckusick 	c->lowBlockCount = count;
169*52130Smckusick 	c->control = 0;
170*52130Smckusick }
171