|
|
1.1 root 1: #include "u.h"
2: #include "../port/lib.h"
3: #include "mem.h"
4: #include "dat.h"
5: #include "fns.h"
6: #include "../port/error.h"
7: #include "devtab.h"
8:
9: #define DPRINT if(debug)kprint
10:
11: #define DATASIZE (256*512)
12: #define NBUS 2
13:
14: static Scsi staticcmd[NBUS]; /* BUG: should be one per scsi device */
15:
16: enum
17: {
18: Qscsiid = 1, /* Top level */
19:
20: Qdir = 0, /* Sub-directory */
21: Qcmd,
22: Qdata,
23: Qdebug,
24: };
25:
26: static Dirtab scsidir[]={
27: "cmd", {Qcmd}, 0, 0666,
28: "data", {Qdata}, 0, 0666,
29: "debug", {Qdebug}, 1, 0666,
30: };
31: #define NSCSI (sizeof scsidir/sizeof(Dirtab))
32:
33: extern int scsidebugs[];
34: extern int scsiownid;
35:
36: static int
37: scsigen1(Chan *c, long qid, Dir *dp)
38: {
39: if (qid == CHDIR)
40: devdir(c, (Qid){qid,0}, ".", 0, eve, 0555, dp);
41: else if (qid == Qscsiid)
42: devdir(c, (Qid){Qscsiid,0}, "scsiid", NUMSIZE, eve, 0666, dp);
43: else if (qid&CHDIR) {
44: char name[2];
45: name[0] = '0'+((qid>>4)&7), name[1] = 0;
46: devdir(c, (Qid){qid,0}, name, 0, eve, 0555, dp);
47: } else {
48: Dirtab *tab = &scsidir[(qid&7)-1];
49: devdir(c, (Qid){qid,0}, tab->name, tab->length, eve, tab->perm, dp);
50: }
51: return 1;
52: }
53:
54: static int
55: scsigeno(Chan *c, Dirtab *tab, long ntab, long s, Dir *dp)
56: {
57: USED(tab, ntab, s);
58: return scsigen1(c, c->qid.path, dp);
59: }
60:
61: static int
62: scsigen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dp)
63: {
64: USED(tab, ntab);
65: if (c->qid.path == CHDIR) {
66: if (0<=s && s<=7)
67: return scsigen1(c, CHDIR|0x100|(s<<4), dp);
68: else if (s == 8)
69: return scsigen1(c, 1, dp);
70: else
71: return -1;
72: }
73: if (s >= NSCSI)
74: return -1;
75: return scsigen1(c, (c->qid.path&~CHDIR)+s+1, dp);
76: }
77:
78: void
79: scsireset(void)
80: {
81: scsibufreset(DATASIZE);
82: resetscsi();
83: }
84:
85: void
86: scsiinit(void)
87: {
88: int i;
89:
90: for(i = 0; i < NBUS; i++)
91: staticcmd[i].bus = i;
92:
93: initscsi();
94: }
95:
96: Chan *
97: scsiattach(char *param)
98: {
99: Chan *c;
100:
101: c = devattach('S', param);
102: c->dev = 0;
103: if(param[0] == '1')
104: c->dev = 1;
105: return c;
106: }
107:
108: Chan *
109: scsiclone(Chan *c, Chan *nc)
110: {
111: return devclone(c, nc);
112: }
113:
114: int
115: scsiwalk(Chan *c, char *name)
116: {
117: return devwalk(c, name, 0, 0, scsigen);
118: }
119:
120: void
121: scsistat(Chan *c, char *db)
122: {
123: devstat(c, db, 0, 0, scsigeno);
124: }
125:
126: Chan *
127: scsiopen(Chan *c, int omode)
128: {
129: return devopen(c, omode, 0, 0, scsigeno);
130: }
131:
132: void
133: scsicreate(Chan *c, char *name, int omode, ulong perm)
134: {
135: USED(c, name, omode, perm);
136: error(Eperm);
137: }
138:
139: void
140: scsiclose(Chan *c)
141: {
142: Scsi *cmd = &staticcmd[c->dev];
143:
144: if((c->qid.path & CHDIR) || c->qid.path==1)
145: return;
146: if((c->qid.path & 0xf) == Qcmd){
147: if(canqlock(cmd) || cmd->pid == u->p->pid){
148: cmd->pid = 0;
149: qunlock(cmd);
150: }
151: }
152: }
153:
154: long
155: scsiread(Chan *c, char *a, long n, ulong offset)
156: {
157: Scsi *cmd = &staticcmd[c->dev];
158:
159: if(n == 0)
160: return 0;
161: if(c->qid.path & CHDIR)
162: return devdirread(c, a, n, 0, 0, scsigen);
163: if(c->qid.path==Qscsiid){
164: n = readnum(offset, a, n, scsiownid, NUMSIZE);
165: }else switch(c->qid.path & 0xf){
166: case Qcmd:
167: if(n < 4)
168: error(Ebadarg);
169: if(canqlock(cmd)){
170: qunlock(cmd);
171: error(Egreg);
172: }
173: if(cmd->pid != u->p->pid)
174: error(Egreg);
175: n = 4;
176: *a++ = 0;
177: *a++ = 0;
178: *a++ = cmd->status >> 8;
179: *a = cmd->status;
180: cmd->pid = 0;
181: qunlock(cmd);
182: break;
183: case Qdata:
184: if(canqlock(cmd)){
185: qunlock(cmd);
186: error(Egreg);
187: }
188: if(cmd->pid != u->p->pid)
189: error(Egreg);
190: if (n > DATASIZE)
191: error(Ebadarg);
192: cmd->b = scsibuf();
193: cmd->data.base = cmd->b->virt;
194: if(waserror()){
195: scsifree(cmd->b);
196: nexterror();
197: }
198: cmd->data.lim = cmd->data.base + n;
199: cmd->data.ptr = cmd->data.base;
200: cmd->save = cmd->data.base;
201: scsiexec(cmd, ScsiIn);
202: n = cmd->data.ptr - cmd->data.base;
203: memmove(a, cmd->data.base, n);
204: poperror();
205: scsifree(cmd->b);
206: break;
207: case Qdebug:
208: if(offset == 0){
209: n=1;
210: *a="01"[scsidebugs[(c->qid.path>>4)&7]!=0];
211: }else
212: n = 0;
213: break;
214: default:
215: panic("scsiread");
216: }
217: return n;
218: }
219:
220: long
221: scsiwrite(Chan *c, char *a, long n, ulong offset)
222: {
223: Scsi *cmd;
224: int id, m;
225: char buf[NUMSIZE+1];
226:
227: cmd = &staticcmd[c->dev];
228: if(c->qid.path==Qscsiid && n>0) {
229: m = n;
230: if(m > NUMSIZE)
231: m = NUMSIZE;
232: memmove(buf, a, m);
233: buf[m] = '\0';
234: id = strtoul(buf, 0, 0);
235: if(id < 0 || id > 15)
236: error(Ebadarg);
237: scsiownid=id;
238: scsireset();
239: }else switch(c->qid.path & 0xf){
240: case Qcmd:
241: if(n < 6 || n > sizeof cmd->cmdblk)
242: error(Ebadarg);
243: qlock(cmd);
244: cmd->pid = u->p->pid;
245: cmd->cmd.base = cmd->cmdblk;
246: memmove(cmd->cmd.base, a, n);
247: cmd->cmd.lim = cmd->cmd.base + n;
248: cmd->cmd.ptr = cmd->cmd.base;
249: cmd->target = (c->qid.path>>4)&7;
250: cmd->lun = (a[1]>>5)&7;
251: cmd->status = 0xFFFF;
252: break;
253: case Qdata:
254: if(canqlock(cmd)){
255: qunlock(cmd);
256: error(Egreg);
257: }
258: if(cmd->pid != u->p->pid)
259: error(Egreg);
260: if (n > DATASIZE)
261: error(Ebadarg);
262: cmd->b = scsibuf();
263: cmd->data.base = cmd->b->virt;
264: if(waserror()){
265: scsifree(cmd->b);
266: nexterror();
267: }
268: cmd->data.lim = cmd->data.base + n;
269: cmd->data.ptr = cmd->data.base;
270: cmd->save = cmd->data.base;
271: memmove(cmd->data.base, a, n);
272: scsiexec(cmd, ScsiOut);
273: n = cmd->data.ptr - cmd->data.base;
274: poperror();
275: scsifree(cmd->b);
276: break;
277: case Qdebug:
278: if(offset == 0){
279: scsidebugs[(c->qid.path>>4)&7] = (*a=='1');
280: n = 1;
281: }else
282: n = 0;
283: break;
284: default:
285: panic("scsiwrite");
286: }
287: return n;
288: }
289:
290: void
291: scsiremove(Chan *c)
292: {
293: USED(c);
294: error(Eperm);
295: }
296:
297: void
298: scsiwstat(Chan *c, char *dp)
299: {
300: USED(c, dp);
301: error(Eperm);
302: }
303:
304: Scsi *
305: scsicmd(int dev, int cmdbyte, Scsibuf *b, long size)
306: {
307: Scsi *cmd = &staticcmd[0];
308:
309: qlock(cmd);
310: cmd->target = dev >> 3;
311: cmd->lun = dev & 7;
312: cmd->cmd.base = cmd->cmdblk;
313: cmd->cmd.ptr = cmd->cmd.base;
314: memset(cmd->cmdblk, 0, sizeof cmd->cmdblk);
315: cmd->cmdblk[0] = cmdbyte;
316: cmd->cmdblk[1] = cmd->lun << 5;
317: switch(cmdbyte >> 5){
318: case 0:
319: cmd->cmd.lim = &cmd->cmdblk[6];
320: break;
321: case 1:
322: cmd->cmd.lim = &cmd->cmdblk[10];
323: break;
324: default:
325: cmd->cmd.lim = &cmd->cmdblk[12];
326: break;
327: }
328: switch(cmdbyte){
329: case ScsiTestunit:
330: break;
331: case ScsiStartunit:
332: cmd->cmdblk[4] = 1;
333: break;
334: case ScsiModesense:
335: cmd->cmdblk[2] = 1;
336: /* fall through */
337: case ScsiExtsens:
338: case ScsiInquiry:
339: cmd->cmdblk[4] = size;
340: break;
341: case ScsiGetcap:
342: break;
343: }
344: cmd->b = b;
345: cmd->data.base = b->virt;
346: cmd->data.lim = cmd->data.base + size;
347: cmd->data.ptr = cmd->data.base;
348: cmd->save = cmd->data.base;
349: return cmd;
350: }
351:
352: int
353: scsiready(int dev)
354: {
355: Scsi *cmd;
356: int status;
357:
358: cmd = scsicmd(dev, ScsiTestunit, scsibuf(), 0);
359: if(waserror()){
360: scsifree(cmd->b);
361: qunlock(cmd);
362: nexterror();
363: }
364: status = scsiexec(cmd, ScsiOut);
365: poperror();
366: scsifree(cmd->b);
367: qunlock(cmd);
368: if((status&0xff00) != 0x6000)
369: error(Eio);
370: return status&0xff;
371: }
372:
373: int
374: scsistartstop(int dev, int cmdbyte)
375: {
376: Scsi *cmd;
377: int status;
378:
379: cmd = scsicmd(dev, cmdbyte, scsibuf(), 0);
380: if(waserror()){
381: scsifree(cmd->b);
382: qunlock(cmd);
383: nexterror();
384: }
385: status = scsiexec(cmd, ScsiOut);
386: poperror();
387: scsifree(cmd->b);
388: qunlock(cmd);
389: if((status&0xff00) != 0x6000)
390: error(Eio);
391: return status&0xff;
392: }
393:
394: int
395: scsisense(int dev, void *p)
396: {
397: Scsi *cmd;
398: int status;
399:
400: cmd = scsicmd(dev, ScsiExtsens, scsibuf(), 18);
401: if(waserror()){
402: scsifree(cmd->b);
403: qunlock(cmd);
404: nexterror();
405: }
406: status = scsiexec(cmd, ScsiIn);
407: memmove(p, cmd->data.base, 18);
408: poperror();
409: scsifree(cmd->b);
410: qunlock(cmd);
411: if((status&0xff00) != 0x6000)
412: error(Eio);
413: return status&0xff;
414: }
415:
416: int
417: scsicap(int dev, void *p)
418: {
419: Scsi *cmd;
420: int status;
421:
422: cmd = scsicmd(dev, ScsiGetcap, scsibuf(), 8);
423: if(waserror()){
424: scsifree(cmd->b);
425: qunlock(cmd);
426: nexterror();
427: }
428: status = scsiexec(cmd, ScsiIn);
429: memmove(p, cmd->data.base, 8);
430: poperror();
431: scsifree(cmd->b);
432: qunlock(cmd);
433: if((status&0xff00) != 0x6000)
434: error(Eio);
435: if(status & 0xFF)
436: scsisense(dev, p);
437: return status&0xff;
438: }
439:
440: int
441: scsiinquiry(int dev, void *p, int size)
442: {
443: Scsi *cmd;
444: int status;
445:
446: cmd = scsicmd(dev, ScsiInquiry, scsibuf(), size);
447: if(waserror()){
448: scsifree(cmd->b);
449: qunlock(cmd);
450: nexterror();
451: }
452: status = scsiexec(cmd, ScsiIn);
453: memmove(p, cmd->data.base, size);
454: poperror();
455: scsifree(cmd->b);
456: qunlock(cmd);
457: if((status&0xff00) != 0x6000)
458: error(Eio);
459: if(status & 0xFF)
460: scsisense(dev, p);
461: return status&0xff;
462: }
463:
464: int
465: scsiwp(int dev)
466: {
467: /* Device specific
468: Scsi *cmd;
469: int r, status;
470:
471: cmd = scsicmd(dev, ScsiModesense, scsibuf(), 12);
472: if(waserror()){
473: scsifree(cmd->b);
474: qunlock(cmd);
475: nexterror();
476: }
477: status = scsiexec(cmd, ScsiIn);
478: r = cmd->data.base[2] & 0x80;
479: poperror();
480: scsifree(cmd->b);
481: qunlock(cmd);
482: if ((status&0xffff) != 0x6000)
483: error(Eio);
484: return r;
485: */
486: USED(dev);
487: return 0;
488: }
489:
490: int
491: scsimodesense(int dev, int page, void *p, int size)
492: {
493: Scsi *cmd;
494: int status;
495:
496: cmd = scsicmd(dev, ScsiModesense, scsibuf(), size);
497: cmd->cmdblk[2] = page;
498: if(waserror()){
499: scsifree(cmd->b);
500: qunlock(cmd);
501: nexterror();
502: }
503: status = scsiexec(cmd, ScsiIn);
504: memmove(p, cmd->data.base, size);
505: poperror();
506: scsifree(cmd->b);
507: qunlock(cmd);
508: if ((status&0xffff) != 0x6000)
509: error(Eio);
510: return status&0xff;
511: }
512:
513: int
514: scsibread(int dev, Scsibuf *b, long n, long blocksize, long blockno)
515: {
516: Scsi *cmd;
517: int cmdbyte, status;
518:
519: if(blockno <= 0x1fffff && n <= 256)
520: cmdbyte = ScsiRead;
521: else
522: cmdbyte = ScsiExtread;
523:
524: cmd = scsicmd(dev, cmdbyte, b, n*blocksize);
525: if(waserror()){
526: qunlock(cmd);
527: nexterror();
528: }
529: switch(cmdbyte){
530: case ScsiRead:
531: cmd->cmdblk[1] |= blockno >> 16;
532: cmd->cmdblk[2] = blockno >> 8;
533: cmd->cmdblk[3] = blockno;
534: cmd->cmdblk[4] = n;
535: break;
536: default:
537: cmd->cmdblk[2] = blockno >> 24;
538: cmd->cmdblk[3] = blockno >> 16;
539: cmd->cmdblk[4] = blockno >> 8;
540: cmd->cmdblk[5] = blockno;
541: cmd->cmdblk[7] = n>>8;
542: cmd->cmdblk[8] = n;
543: break;
544: }
545: status = scsiexec(cmd, ScsiIn);
546: n = cmd->data.ptr - cmd->data.base;
547: poperror();
548: qunlock(cmd);
549: if(n <= 0 && status == 0x6002)
550: error(Eio);
551:
552: return n;
553: }
554:
555: int
556: scsibwrite(int dev, Scsibuf *b, long n, long blocksize, long blockno)
557: {
558: Scsi *cmd;
559: int cmdbyte, status;
560:
561: if(blockno <= 0x1fffff && n <= 256)
562: cmdbyte = ScsiWrite;
563: else
564: cmdbyte = ScsiExtwrite;
565:
566: cmd = scsicmd(dev, cmdbyte, b, n*blocksize);
567: if(waserror()){
568: qunlock(cmd);
569: nexterror();
570: }
571: switch(cmdbyte){
572: case ScsiWrite:
573: cmd->cmdblk[1] |= blockno >> 16;
574: cmd->cmdblk[2] = blockno >> 8;
575: cmd->cmdblk[3] = blockno;
576: cmd->cmdblk[4] = n;
577: break;
578: default:
579: cmd->cmdblk[2] = blockno >> 24;
580: cmd->cmdblk[3] = blockno >> 16;
581: cmd->cmdblk[4] = blockno >> 8;
582: cmd->cmdblk[5] = blockno;
583: cmd->cmdblk[7] = n>>8;
584: cmd->cmdblk[8] = n;
585: break;
586: }
587: status = scsiexec(cmd, ScsiOut);
588: n = cmd->data.ptr - cmd->data.base;
589: poperror();
590: qunlock(cmd);
591: if(n <= 0 && status == 0x6002)
592: error(Eio);
593: return n;
594: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.