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