static int dirdevopen(ScsiReq *rp) { uint64_t blocks; uint8_t data[8+4+20]; /* 16-byte result: lba, blksize, reserved */ memset(data, 0, sizeof data); if(SRstart(rp, 1) == -1 || SRrcapacity(rp, data) == -1) return -1; rp->lbsize = GETBELONG(data+4); blocks = GETBELONG(data); if(debug) fprint(2, "disk: dirdevopen: 10-byte logical block size %lud, " "# blocks %llud\n", rp->lbsize, blocks); if(blocks == 0xffffffff){ if(SRrcapacity16(rp, data) == -1) return -1; rp->lbsize = GETBELONG(data + 8); blocks = (int64_t)GETBELONG(data)<<32 | GETBELONG(data + 4); if(debug) fprint(2, "disk: dirdevopen: 16-byte logical block size" " %lud, # blocks %llud\n", rp->lbsize, blocks); } /* some newer dev's don't support 6-byte commands */ if(blocks > Max24off && !force6bytecmds) rp->flags |= Frw10; return 0; }
int32_t SRwrite(ScsiReq *rp, void *buf, int32_t nbytes) { uint8_t cmd[10]; int32_t n; if(rp->lbsize == 0 || (nbytes % rp->lbsize) || nbytes > Maxiosize){ if(diskdebug) if (nbytes % rp->lbsize) fprint(2, "disk: i/o size %ld %% %ld != 0\n", nbytes, rp->lbsize); else fprint(2, "disk: i/o size %ld > %d\n", nbytes, Maxiosize); rp->status = Status_BADARG; return -1; } /* set up scsi write cmd */ cmd[0] = ScmdWrite; if(rp->flags & Fseqdev) rp->cmd.count = seqdevrw(rp, cmd, nbytes); else rp->cmd.count = dirdevrw(rp, cmd, nbytes); rp->cmd.p = cmd; rp->data.p = buf; rp->data.count = nbytes; rp->data.write = 1; /* issue it */ if((n = SRrequest(rp)) == -1){ if (exabyte) { fprint(2, "write error\n"); rp->status = STcheck; return n; } if(rp->status != Status_SD || rp->sense[2] != Sd2eom) return -1; if(rp->sense[0] & Sd0valid){ n -= GETBELONG(rp->sense+3) * rp->lbsize; rp->data.count = nbytes - n; } else rp->data.count = nbytes; n = rp->data.count; } rp->offset += n / rp->lbsize; return n; }
static int getconfcmd(Drive *drive, uint8_t *resp, int respsz) { int n; uint32_t datalen; uint8_t cmd[10]; initcdb(cmd, sizeof cmd, Scmdgetconf); cmd[3] = 0; /* start with profile list feature */ cmd[7] = respsz >> 8; cmd[8] = respsz; n = scsi(&drive->scsi, cmd, sizeof cmd, resp, respsz, Sread); if (n < 0) { if(vflag) fprint(2, "get config cmd failed\n"); return -1; } if (n < 4) return -1; datalen = GETBELONG(resp+0); if (datalen < 8) return -1; return datalen; }
int32_t SRread(ScsiReq *rp, void *buf, int32_t nbytes) { uint8_t cmd[10]; int32_t n; if(rp->lbsize == 0 || (nbytes % rp->lbsize) || nbytes > Maxiosize){ if(diskdebug) if (nbytes % rp->lbsize) fprint(2, "disk: i/o size %ld %% %ld != 0\n", nbytes, rp->lbsize); else fprint(2, "disk: i/o size %ld > %d\n", nbytes, Maxiosize); rp->status = Status_BADARG; return -1; } /* set up scsi read cmd */ cmd[0] = ScmdRead; if(rp->flags & Fseqdev) rp->cmd.count = seqdevrw(rp, cmd, nbytes); else rp->cmd.count = dirdevrw(rp, cmd, nbytes); rp->cmd.p = cmd; rp->data.p = buf; rp->data.count = nbytes; rp->data.write = 0; /* issue it */ n = SRrequest(rp); if(n != -1){ /* it worked? */ rp->offset += n / rp->lbsize; return n; } /* request failed; maybe we just read a short record? */ if (exabyte) { fprint(2, "read error\n"); rp->status = STcheck; return n; } if(rp->status != Status_SD || !(rp->sense[0] & Sd0valid)) return -1; /* compute # of bytes not read */ n = GETBELONG(rp->sense+3) * rp->lbsize; if(!(rp->flags & Fseqdev)) return -1; /* device is a tape or something similar */ if (rp->sense[2] == Sd2filemark || rp->sense[2] == 0x08 || rp->sense[2] & Sd2ili && n > 0) rp->data.count = nbytes - n; else return -1; n = rp->data.count; if (!rp->readblock++ || debug) fprint(2, "SRread: tape data count %ld%s\n", n, (rp->sense[2] & Sd2ili? " with ILI": "")); rp->status = STok; rp->offset += n / rp->lbsize; return n; }