|
|
1.1 root 1: #include "u.h"
2: #include "lib.h"
3: #include "mem.h"
4: #include "dat.h"
5: #include "fns.h"
6: #include "io.h"
7:
8: /*
9: * BUG: only LUN 0
10: */
11:
12: static Scsi staticcmd;
13:
14: static Disc *sdrive;
15: static bufbusy;
16:
17: Scsibuf *
18: scsibuf(void)
19: {
20: static Scsibuf b;
21:
22: if(bufbusy)
23: panic("bufbusy\n");
24: bufbusy++;
25: if(b.virt == 0){
26: b.virt = ialloc(Maxxfer, 0);
27: b.phys = (void *)(PADDR(b.virt));
28: }
29: return &b;
30: }
31:
32: void
33: scsifree(Scsibuf*)
34: {
35: if(bufbusy == 0)
36: panic("buf not busy\n");
37: bufbusy = 0;
38: }
39:
40: Scsi *
41: scsicmd(int dev, int cmdbyte, Scsibuf *b, long size)
42: {
43: Scsi *cmd = &staticcmd;
44:
45: cmd->target = dev /*>> 3*/; /* BUG */
46: cmd->lun = 0/*dev & 7*/; /* BUG */
47: cmd->cmd.base = cmd->cmdblk;
48: cmd->cmd.ptr = cmd->cmd.base;
49: memset(cmd->cmdblk, 0, sizeof cmd->cmdblk);
50: cmd->cmdblk[0] = cmdbyte;
51: cmd->cmdblk[1] = cmd->lun << 5;
52: switch(cmdbyte >> 5){
53: case 0:
54: cmd->cmd.lim = &cmd->cmdblk[6];
55: break;
56: case 1:
57: cmd->cmd.lim = &cmd->cmdblk[10];
58: break;
59: default:
60: cmd->cmd.lim = &cmd->cmdblk[12];
61: break;
62: }
63: switch(cmdbyte){
64: case ScsiTestunit:
65: break;
66: case ScsiStartunit:
67: cmd->cmdblk[4] = 1;
68: break;
69: case ScsiModesense:
70: cmd->cmdblk[2] = 1;
71: /* fall through */
72: case ScsiExtsens:
73: case ScsiInquiry:
74: cmd->cmdblk[4] = size;
75: break;
76: case ScsiGetcap:
77: break;
78: }
79: cmd->b = b;
80: cmd->data.base = b->virt;
81: cmd->data.lim = cmd->data.base + size;
82: cmd->data.ptr = cmd->data.base;
83: cmd->save = cmd->data.base;
84: return cmd;
85: }
86:
87: int
88: scsiready(int dev)
89: {
90: Scsi *cmd;
91: int status;
92:
93: cmd = scsicmd(dev, ScsiTestunit, scsibuf(), 0);
94: status = scsiexec(cmd, ScsiOut);
95: scsifree(cmd->b);
96: return status&0xff;
97: }
98:
99: int
100: scsisense(int dev, void *p)
101: {
102: Scsi *cmd;
103: int status;
104:
105: cmd = scsicmd(dev, ScsiExtsens, scsibuf(), 18);
106: status = scsiexec(cmd, ScsiIn);
107: memmove(p, cmd->data.base, 18);
108: scsifree(cmd->b);
109: return status&0xff;
110: }
111:
112: int
113: scsistartstop(int dev, int cmdbyte)
114: {
115: Scsi *cmd;
116: int status;
117:
118: cmd = scsicmd(dev, cmdbyte, scsibuf(), 0);
119: status = scsiexec(cmd, ScsiOut);
120: scsifree(cmd->b);
121: return status&0xff;
122: }
123:
124: int
125: scsicap(int dev, void *p)
126: {
127: Scsi *cmd;
128: int status;
129:
130: cmd = scsicmd(dev, ScsiGetcap, scsibuf(), 8);
131: status = scsiexec(cmd, ScsiIn);
132: memmove(p, cmd->data.base, 8);
133: scsifree(cmd->b);
134: return status&0xFF;
135: }
136:
137: int
138: scsibread(int dev, Scsibuf *b, long n, long blocksize, long blockno)
139: {
140: Scsi *cmd;
141: int cmdbyte;
142:
143: if(blockno <= 0x1fffff && n <= 256)
144: cmdbyte = ScsiRead;
145: else
146: cmdbyte = ScsiExtread;
147:
148: cmd = scsicmd(dev, cmdbyte, b, n*blocksize);
149: switch(cmdbyte){
150: case ScsiRead:
151: cmd->cmdblk[1] |= blockno >> 16;
152: cmd->cmdblk[2] = blockno >> 8;
153: cmd->cmdblk[3] = blockno;
154: cmd->cmdblk[4] = n;
155: break;
156: default:
157: cmd->cmdblk[2] = blockno >> 24;
158: cmd->cmdblk[3] = blockno >> 16;
159: cmd->cmdblk[4] = blockno >> 8;
160: cmd->cmdblk[5] = blockno;
161: cmd->cmdblk[7] = n>>8;
162: cmd->cmdblk[8] = n;
163: break;
164: }
165: scsiexec(cmd, ScsiIn);
166: n = cmd->data.ptr - cmd->data.base;
167: return n;
168: }
169:
170: int
171: scsibwrite(int dev, Scsibuf *b, long n, long blocksize, long blockno)
172: {
173: Scsi *cmd;
174:
175: int cmdbyte;
176:
177: if(blockno <= 0x1fffff && n <= 256)
178: cmdbyte = ScsiWrite;
179: else
180: cmdbyte = ScsiExtwrite;
181:
182: cmd = scsicmd(dev, cmdbyte, b, n*blocksize);
183: switch(cmdbyte){
184: case ScsiWrite:
185: cmd->cmdblk[1] |= blockno >> 16;
186: cmd->cmdblk[2] = blockno >> 8;
187: cmd->cmdblk[3] = blockno;
188: cmd->cmdblk[4] = n;
189: break;
190: default:
191: cmd->cmdblk[2] = blockno >> 24;
192: cmd->cmdblk[3] = blockno >> 16;
193: cmd->cmdblk[4] = blockno >> 8;
194: cmd->cmdblk[5] = blockno;
195: cmd->cmdblk[7] = n>>8;
196: cmd->cmdblk[8] = n;
197: break;
198: }
199: scsiexec(cmd, ScsiOut);
200: n = cmd->data.ptr - cmd->data.base;
201: return n;
202: }
203:
204: long
205: scsiseek(int dev, long off)
206: {
207: sdrive[dev].offset = off;
208: return off;
209: }
210:
211: /*
212: * read partition table. The partition table is just ascii strings.
213: */
214: #define MAGIC "plan9 partitions"
215: static void
216: scsipart(int dev)
217: {
218: Disc *dp;
219: Partition *pp;
220: char *line[Npart+1], *cp;
221: char *field[3];
222: ulong n;
223: int i;
224: Scsibuf *b;
225:
226: dp = &sdrive[dev];
227:
228: /*
229: * we always have a partition for the whole disk
230: * and one for the partition table
231: */
232: pp = &dp->p[0];
233: strcpy(pp->name, "disk");
234: pp->start = 0;
235: pp->end = dp->cap;
236: pp++;
237: strcpy(pp->name, "partition");
238: pp->start = dp->p[0].end - 1;
239: pp->end = dp->p[0].end;
240: dp->npart = 2;
241:
242: /*
243: * read partition table from disk, null terminate
244: */
245: b = scsibuf();
246: if(scsibread(dev, b, 1, dp->bytes, dp->cap-1) <= 0){
247: scsifree(b);
248: print("can't read partition block\n");
249: return;
250: }
251: cp = b->virt;
252: cp[dp->bytes-1] = 0;
253:
254: /*
255: * parse partition table.
256: */
257: n = getfields(cp, line, Npart+1, '\n');
258: if(n && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0){
259: for(i = 1; i < n; i++){
260: pp++;
261: if(getfields(line[i], field, 3, ' ') != 3)
262: break;
263: strncpy(pp->name, field[0], NAMELEN);
264: pp->start = strtoul(field[1], 0, 0);
265: pp->end = strtoul(field[2], 0, 0);
266: if(pp->start > pp->end || pp->start >= dp->p[0].end)
267: break;
268: dp->npart++;
269: }
270: }
271: scsifree(b);
272: return;
273: }
274:
275: Partition*
276: setscsipart(int dev, char *p)
277: {
278: Partition *pp;
279: Disc *dp;
280:
281: dp = &sdrive[dev];
282: for(pp = dp->p; pp < &dp->p[dp->npart]; pp++)
283: if(strcmp(pp->name, p) == 0){
284: dp->current = pp;
285: return pp;
286: }
287: return 0;
288: }
289:
290: static long
291: scsirw(int dev, int write, char *a, ulong len, ulong offset)
292: {
293: Disc *d;
294: Partition *p;
295: Scsibuf *b;
296: ulong block, n, max, x;
297:
298: d = &sdrive[dev];
299: p = d->current;
300: if(p == 0)
301: return -1;
302:
303: block = offset / d->bytes + p->start;
304: n = (offset + len + d->bytes - 1) / d->bytes + p->start - block;
305: max = Maxxfer / d->bytes;
306: if(n > max)
307: n = max;
308: if(block + n > p->end)
309: n = p->end - block;
310: if(block >= p->end || n == 0)
311: return 0;
312: b = scsibuf();
313:
314: offset %= d->bytes;
315: if(write){
316: if(offset || len % d->bytes){
317: x = scsibread(dev, b, n, d->bytes, block);
318: if(x < n * d->bytes){
319: n = x / d->bytes;
320: x = n * d->bytes - offset;
321: if(len > x)
322: len = x;
323: }
324: }
325: memmove((char*)b->virt + offset, a, len);
326: x = scsibwrite(dev, b, n, d->bytes, block);
327: if(x < offset)
328: len = 0;
329: else if(len > x - offset)
330: len = x - offset;
331: }else{
332: x = scsibread(dev, b, n, d->bytes, block);
333: if(x < offset)
334: len = 0;
335: else if(len > x - offset)
336: len = x - offset;
337: memmove(a, (char*)b->virt + offset, len);
338: }
339:
340: scsifree(b);
341: return len;
342: }
343:
344: long
345: scsiread(int dev, void *a, long n)
346: {
347: long len;
348:
349: len = scsirw(dev, 0, a, n, sdrive[dev].offset);
350: if(len > 0)
351: sdrive[dev].offset += len;
352: return len;
353: }
354:
355: extern int (*aha1542reset(void))(Scsi*, int);
356: extern int (*ultra14freset(void))(Scsi*, int);
357:
358: static int (*exec)(Scsi*, int);
359:
360: int
361: scsiexec(Scsi *p, int rflag)
362: {
363: if(exec == 0)
364: return 0;
365: return (*exec)(p, rflag);
366: }
367:
368: int
369: scsiinit(void)
370: {
371: int i, online;
372: uchar buf[32];
373:
374: if((exec = ultra14freset()) == 0 && (exec = aha1542reset()) == 0)
375: return 0;
376: sdrive = ialloc(8 * sizeof(Disc), 0);
377: online = 0;
378: for(i = 0; i < 7; i++){
379: if(scsiready(i) == 0x20) /* timeout */
380: continue;
381: scsisense(i, buf);
382: scsistartstop(i, ScsiStartunit);
383: scsisense(i, buf);
384: if(scsicap(i, buf))
385: continue;
386: online |= (1<<i);
387: sdrive[i].online = 1;
388: sdrive[i].cap = ((buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3])+1;
389: sdrive[i].bytes = (buf[4]<<24)|(buf[5]<<16)|(buf[6]<<8)|buf[7];
390: print("scsi%d: cap %lud, sec %d\n", i, sdrive[i].cap, sdrive[i].bytes);
391: scsipart(i);
392: }
393: return online;
394: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.