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