4 * The codeqlock guarantees that once codes != nil, that pointer will never
5 * change nor become invalid.
7 * The QLock in the Scsi structure moderates access to the raw device.
8 * We should probably export some of the already-locked routines, but
9 * there hasn't been a need.
22 #define codefile "/sys/lib/scsicodes"
25 static QLock codeqlock;
42 if((d = dirstat(codefile)) == nil || (fd = open(codefile, OREAD)) < 0) {
47 codes = malloc(1+d->length+1);
55 codes[0] = '\n'; /* for searches */
56 n = readn(fd, codes+1, d->length);
71 scsierror(int asc, int ascq)
74 static char search[32];
80 sprint(search, "\n%.2ux%.2ux ", asc, ascq);
81 if(p = strstr(codes, search)) {
83 if((q = strchr(p, '\n')) == nil)
85 snprint(buf, sizeof buf, "%.*s", (int)(q-p), p);
89 sprint(search, "\n%.2ux00", asc);
90 if(p = strstr(codes, search)) {
92 if((q = strchr(p, '\n')) == nil)
94 snprint(buf, sizeof buf, "(ascq #%.2ux) %.*s", ascq, (int)(q-p), p);
99 sprint(buf, "scsi #%.2ux %.2ux", asc, ascq);
105 _scsicmd(Scsi *s, uchar *cmd, int ccount, void *data, int dcount, int io, int dolock)
113 if(write(s->rawfd, cmd, ccount) != ccount) {
114 werrstr("cmd write: %r");
122 n = read(s->rawfd, data, dcount);
123 /* read toc errors are frequent and not very interesting */
124 if(n < 0 && (scsiverbose == 1 ||
125 scsiverbose == 2 && cmd[0] != Readtoc))
126 fprint(2, "dat read: %r: cmd 0x%2.2uX\n", cmd[0]);
129 n = write(s->rawfd, data, dcount);
130 if(n != dcount && scsiverbose)
131 fprint(2, "dat write: %r: cmd 0x%2.2uX\n", cmd[0]);
135 n = write(s->rawfd, resp, 0);
136 if(n != 0 && scsiverbose)
137 fprint(2, "none write: %r: cmd 0x%2.2uX\n", cmd[0]);
141 memset(resp, 0, sizeof(resp));
142 if(read(s->rawfd, resp, sizeof(resp)) < 0) {
143 werrstr("resp read: %r\n");
151 resp[sizeof(resp)-1] = '\0';
152 status = atoi((char*)resp);
156 werrstr("cmd %2.2uX: status %luX dcount %d n %d", cmd[0], status, dcount, n);
161 scsicmd(Scsi *s, uchar *cmd, int ccount, void *data, int dcount, int io)
163 return _scsicmd(s, cmd, ccount, data, dcount, io, 1);
167 _scsiready(Scsi *s, int dolock)
169 uchar cmd[6], resp[16];
175 memset(cmd, 0, sizeof(cmd));
176 cmd[0] = 0x00; /* unit ready */
177 if(write(s->rawfd, cmd, sizeof(cmd)) != sizeof(cmd)) {
179 fprint(2, "ur cmd write: %r\n");
182 write(s->rawfd, resp, 0);
183 if(read(s->rawfd, resp, sizeof(resp)) < 0) {
185 fprint(2, "ur resp read: %r\n");
188 resp[sizeof(resp)-1] = '\0';
189 status = atoi((char*)resp);
190 if(status == 0 || status == 0x02) {
196 fprint(2, "target: bad status: %x\n", status);
207 return _scsiready(s, 1);
211 scsi(Scsi *s, uchar *cmd, int ccount, void *v, int dcount, int io)
213 uchar req[6], sense[255], *data;
214 int tries, code, key, n;
220 for(tries=0; tries<2; tries++) {
221 n = _scsicmd(s, cmd, ccount, data, dcount, io, 0);
230 memset(req, 0, sizeof(req));
232 req[4] = sizeof(sense);
233 memset(sense, 0xFF, sizeof(sense));
234 if((n=_scsicmd(s, req, sizeof(req), sense, sizeof(sense), Sread, 0)) < 14)
236 fprint(2, "reqsense scsicmd %d: %r\n", n);
238 if(_scsiready(s, 0) < 0)
240 fprint(2, "unit not ready\n");
244 if(code == 0x17 || code == 0x18) { /* recovered errors */
248 if(code == 0x28 && cmd[0] == Readtoc) {
249 /* read toc and media changed */
251 s->changetime = time(0);
256 /* drive not ready, or medium not present */
257 if(cmd[0] == Readtoc && key == 2 && (code == 0x3a || code == 0x04)) {
264 if(cmd[0] == Readtoc && key == 5 && code == 0x24) /* blank media */
267 p = scsierror(code, sense[13]);
269 werrstr("cmd #%.2ux: %s", cmd[0], p);
272 fprint(2, "scsi cmd #%.2ux: %.2ux %.2ux %.2ux: %s\n",
273 cmd[0], key, code, sense[13], p);
284 int rawfd, ctlfd, l, n;
285 char *name, *p, buf[512];
287 l = strlen(dev)+1+3+1;
292 snprint(name, l, "%s/raw", dev);
293 if((rawfd = open(name, ORDWR)) < 0) {
298 snprint(name, l, "%s/ctl", dev);
299 if((ctlfd = open(name, ORDWR)) < 0) {
307 n = readn(ctlfd, buf, sizeof buf);
312 if(strncmp(buf, "inquiry ", 8) != 0 || (p = strchr(buf, '\n')) == nil)
316 if((p = strdup(buf+8)) == nil)
319 s = mallocz(sizeof(*s), 1);
328 s->changetime = time(0);