xref: /original-bsd/sys/pmax/dev/scsi.c (revision e59fb703)
1 /*
2  * Copyright (c) 1992 Regents of the University of California.
3  * 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	7.1 (Berkeley) 01/07/92
11  */
12 
13 /*
14  * SCSI utility routines for making SCSI device drivers easier.
15  */
16 
17 #include "param.h"
18 
19 #include "device.h"
20 #include "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->valid)
119 			printf(", blk %d", (sp->info1 << 24) |
120 				(sp->info2 << 16) | (sp->info3 << 8) |
121 				sp->info4);
122 	}
123 	printf("\n");
124 }
125 
126 /*
127  * Setup a command block for a SCSI Group0 command.
128  */
129 void
130 scsiGroup0Cmd(cmd, lun, block, count, c)
131 	unsigned cmd;			/* group0 SCSI command */
132 	unsigned lun;			/* Logical Unit Number */
133 	register unsigned block;	/* starting block number for transfer */
134 	unsigned count;			/* # of sectors/bytes to transfer */
135 	register ScsiGroup0Cmd *c;	/* command to be filled in */
136 {
137 
138 	c->command = cmd;
139 	c->unitNumber = lun;
140 	c->highAddr = block >> 16;
141 	c->midAddr = block >> 8;
142 	c->lowAddr = block;
143 	c->blockCount = count;
144 	c->control = 0;
145 }
146 
147 /*
148  * Setup a command block for a SCSI Group1 command.
149  */
150 void
151 scsiGroup1Cmd(cmd, lun, block, count, c)
152 	unsigned cmd;			/* group0 SCSI command */
153 	unsigned lun;			/* Logical Unit Number */
154 	register unsigned block;	/* starting block number for transfer */
155 	unsigned count;			/* # of sectors/bytes to transfer */
156 	register ScsiGroup1Cmd *c;	/* command to be filled in */
157 {
158 
159 	c->command = cmd;
160 	c->unitNumber = lun;
161 	c->pad1 = 0;
162 	c->highAddr = block >> 24;
163 	c->midHighAddr = block >> 16;
164 	c->midLowAddr = block >> 8;
165 	c->lowAddr = block;
166 	c->pad2 = 0;
167 	c->highBlockCount = count >> 8;
168 	c->lowBlockCount = count;
169 	c->control = 0;
170 }
171