|
|
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.