Annotation of src/usr.bin/cdio/mmc.c, Revision 1.1
1.1 ! mjc 1: #include <sys/limits.h>
! 2: #include <sys/types.h>
! 3: #include <sys/stat.h>
! 4: #include <sys/scsiio.h>
! 5: #include <err.h>
! 6: #include <fcntl.h>
! 7: #include <stdio.h>
! 8: #include <string.h>
! 9: #include <unistd.h>
! 10: #include "extern.h"
! 11:
! 12: #define WAVHDRLEN 44
! 13: extern int fd;
! 14: extern char *track_types;
! 15:
! 16: int
! 17: blank(void)
! 18: {
! 19: scsireq_t scr;
! 20: int r;
! 21:
! 22: bzero(&scr, sizeof(scr));
! 23: scr.cmd[0] = 0xa1;
! 24: scr.cmd[1] = 0x01;
! 25: scr.cmdlen = 12;
! 26: scr.datalen = 0;
! 27: scr.timeout = 120000;
! 28: scr.flags = SCCMD_ESCAPE;
! 29: scr.senselen = SENSEBUFLEN;
! 30:
! 31: r = ioctl(fd, SCIOCCOMMAND, &scr);
! 32: return (r == 0 ? scr.retsts : -1);
! 33: }
! 34:
! 35: int
! 36: unit_ready(void)
! 37: {
! 38: scsireq_t scr;
! 39: int r;
! 40:
! 41: bzero(&scr, sizeof(scr));
! 42: scr.cmd[0] = 0x00;
! 43: scr.cmdlen = 6;
! 44: scr.datalen = 0;
! 45: scr.timeout = 120000;
! 46: scr.flags = SCCMD_ESCAPE;
! 47: scr.senselen = SENSEBUFLEN;
! 48:
! 49: r = ioctl(fd, SCIOCCOMMAND, &scr);
! 50: return (r == 0 ? scr.retsts : -1);
! 51: }
! 52:
! 53: int
! 54: synchronize_cache(void)
! 55: {
! 56: scsireq_t scr;
! 57: int r;
! 58:
! 59: bzero(&scr, sizeof(scr));
! 60: scr.cmd[0] = 0x35;
! 61: scr.cmdlen = 10;
! 62: scr.datalen = 0;
! 63: scr.timeout = 120000;
! 64: scr.flags = SCCMD_ESCAPE;
! 65: scr.senselen = SENSEBUFLEN;
! 66:
! 67: r = ioctl(fd, SCIOCCOMMAND, &scr);
! 68: return (r == 0 ? scr.retsts : -1);
! 69: }
! 70:
! 71: int
! 72: close_session(void)
! 73: {
! 74: scsireq_t scr;
! 75: int r;
! 76:
! 77: bzero(&scr, sizeof(scr));
! 78: scr.cmd[0] = 0x5b;
! 79: scr.cmd[2] = 0x02; /* close session */
! 80: scr.cmd[5] = 0x00; /* track number */
! 81: scr.cmdlen = 10;
! 82: scr.datalen = 0;
! 83: scr.timeout = 120000;
! 84: scr.flags = SCCMD_ESCAPE;
! 85: scr.senselen = SENSEBUFLEN;
! 86:
! 87: r = ioctl(fd, SCIOCCOMMAND, &scr);
! 88: return (r == 0 ? scr.retsts : -1);
! 89:
! 90: }
! 91:
! 92: int
! 93: writetao(int ntracks, char *track_files[])
! 94: {
! 95: u_char modebuf[70];
! 96: u_int blklen;
! 97: u_int t;
! 98: int i,r;
! 99: u_char bdlen;
! 100:
! 101: if (track_types == NULL)
! 102: track_types = strdup("d");
! 103: if ((r = mode_sense_write(modebuf)) != SCCMD_OK) {
! 104: warnx("mode sense failed: %d", r);
! 105: return (r);
! 106: }
! 107: bdlen = modebuf[7];
! 108: modebuf[2+8+bdlen] |= 0x40; /* Buffer Underrun Free Enable */
! 109: modebuf[2+8+bdlen] |= 0x01; /* change write type to TAO */
! 110:
! 111: for (i = 0, t = 0; t < ntracks; t++) {
! 112: if (track_types[i] == 'd') {
! 113: modebuf[3+8+bdlen] = 0x04; /* track mode = data */
! 114: modebuf[4+8+bdlen] = 0x08; /* 2048 block track mode */
! 115: modebuf[8+8+bdlen] = 0x00; /* turn off XA */
! 116: blklen = 2048;
! 117: } else if (track_types[i] == 'a') {
! 118: modebuf[3+8+bdlen] = 0x00; /* track mode = audio */
! 119: modebuf[4+8+bdlen] = 0x00; /* 2352 block track mode */
! 120: modebuf[8+8+bdlen] = 0x00; /* turn off XA */
! 121: blklen = 2352;
! 122: } else {
! 123: warnx("invalid track type specified");
! 124: return (1);
! 125: }
! 126: while (unit_ready() != SCCMD_OK)
! 127: continue;
! 128: if ((r = mode_select_write(modebuf)) != SCCMD_OK) {
! 129: warnx("mode select failed: %d",r);
! 130: return (r);
! 131: }
! 132: writetrack(track_files[t], blklen, t, track_types[i]);
! 133: synchronize_cache();
! 134: if (track_types[i+1] != '\0')
! 135: i++;
! 136: }
! 137: fprintf(stderr,"\n");
! 138: synchronize_cache();
! 139: close_session();
! 140: return (0);
! 141: }
! 142:
! 143: int
! 144: writetrack(char *file, u_int blklen, u_int trackno, char type)
! 145: {
! 146: u_char databuf[65536];
! 147: struct stat sb;
! 148: scsireq_t scr;
! 149: u_int end_lba, lba;
! 150: u_int tmp;
! 151: int r,rfd;
! 152: u_char nblk;
! 153:
! 154: nblk = 65535/blklen;
! 155: bzero(&scr, sizeof(scr));
! 156: scr.timeout = 300000;
! 157: scr.cmd[0] = 0x2a;
! 158: scr.cmd[1] = 0x00;
! 159: scr.cmd[8] = nblk; /* Transfer length in blocks (LSB) */
! 160: scr.cmdlen = 10;
! 161: scr.databuf = (caddr_t)databuf;
! 162: scr.datalen = nblk * blklen;
! 163: scr.senselen = SENSEBUFLEN;
! 164: scr.flags = SCCMD_ESCAPE|SCCMD_WRITE;
! 165:
! 166: if (get_nwa(&lba) != SCCMD_OK) {
! 167: warnx("cannot get next writable address");
! 168: return (-1);
! 169: }
! 170: tmp = htobe32(lba); /* update lba in cdb */
! 171: memcpy(&scr.cmd[2], &tmp, sizeof(tmp));
! 172:
! 173: if (stat(file, &sb) != 0) {
! 174: warn("cannot stat file %s",file);
! 175: return (-1);
! 176: }
! 177: if (sb.st_size / blklen + 1 > UINT_MAX || sb.st_size < blklen) {
! 178: warnx("file %s has invalid size",file);
! 179: return (-1);
! 180: }
! 181: if (type == 'a')
! 182: sb.st_size -= WAVHDRLEN;
! 183: if (sb.st_size % blklen) {
! 184: warnx("file %s is not multiple of block length %d",file,blklen);
! 185: end_lba = sb.st_size / blklen + lba + 1;
! 186: } else {
! 187: end_lba = sb.st_size / blklen + lba;
! 188: }
! 189: rfd = open(file, O_RDONLY, 0640);
! 190: if (type == 'a') {
! 191: if (lseek(rfd, WAVHDRLEN, SEEK_SET) == -1)
! 192: err(1, "seek failed");
! 193: }
! 194: while ((lba < end_lba) && (nblk != 0)) {
! 195: while (lba + nblk <= end_lba) {
! 196: read(rfd, databuf, nblk * blklen);
! 197: scr.cmd[8] = nblk;
! 198: scr.datalen = nblk * blklen;
! 199: r = ioctl(fd, SCIOCCOMMAND, &scr);
! 200: if (r != 0) {
! 201: warn("ioctl failed while attempting to write");
! 202: return (-1);
! 203: }
! 204: if (scr.retsts != SCCMD_OK) {
! 205: warnx("ioctl returned bad status while attempting to write: %d", scr.retsts);
! 206: return (r);
! 207: }
! 208: lba += nblk;
! 209: fprintf(stderr,"\rLBA: 0x%06x/0x%06x",lba,end_lba);
! 210: tmp = htobe32(lba); /* update lba in cdb */
! 211: memcpy(&scr.cmd[2], &tmp, sizeof(tmp));
! 212: }
! 213: nblk--;
! 214: }
! 215: close(rfd);
! 216: return (0);
! 217: }
! 218:
! 219: int
! 220: mode_sense_write(unsigned char buf[])
! 221: {
! 222: scsireq_t scr;
! 223: int r;
! 224:
! 225: bzero(&scr, sizeof(scr));
! 226: scr.timeout = 4000;
! 227: scr.senselen = SENSEBUFLEN;
! 228: scr.cmd[0] = 0x5a;
! 229: scr.cmd[1] = 0x00;
! 230: scr.cmd[2] = 0x05; /* Write parameters mode page */
! 231: scr.cmd[7] = 0x00;
! 232: scr.cmd[8] = 0x46; /* 16 for the header + size from pg. 89 mmc-r10a.pdf */
! 233: scr.cmdlen = 10;
! 234: scr.datalen= 0x46;
! 235: scr.flags = SCCMD_ESCAPE|SCCMD_READ;
! 236: scr.databuf = (caddr_t)buf;
! 237:
! 238: r = ioctl(fd, SCIOCCOMMAND, &scr);
! 239: return (r == 0 ? scr.retsts : -1);
! 240: }
! 241:
! 242: int
! 243: mode_select_write(unsigned char buf[])
! 244: {
! 245: scsireq_t scr;
! 246: int r;
! 247:
! 248: bzero(&scr, sizeof(scr));
! 249: scr.timeout = 4000;
! 250: scr.senselen = SENSEBUFLEN;
! 251: scr.cmd[0] = 0x55;
! 252: scr.cmd[1] = 0x10; /* pages aren't vendor specific */
! 253: scr.cmd[2] = 0x00;
! 254: scr.cmd[7] = 0x00;
! 255: scr.cmd[8] = 2 + buf[1] + 256 * buf[0];
! 256: scr.cmdlen = 10;
! 257: scr.datalen = 2 + buf[1] + 256 * buf[0];
! 258: scr.flags = SCCMD_ESCAPE|SCCMD_WRITE;
! 259: scr.databuf = (caddr_t)buf;
! 260:
! 261: r = ioctl(fd, SCIOCCOMMAND, &scr);
! 262: return (r == 0 ? scr.retsts : -1);
! 263: }
! 264:
! 265: int
! 266: get_nwa(int *nwa)
! 267: {
! 268: u_char databuf[28];
! 269: scsireq_t scr;
! 270: int r,tmp;
! 271:
! 272: bzero(&scr, sizeof(scr));
! 273: scr.timeout = 4000;
! 274: scr.senselen = SENSEBUFLEN;
! 275: scr.cmd[0] = 0x52; /* READ TRACK INFO */
! 276: scr.cmd[1] = 0x01;
! 277: scr.cmd[5] = 0xff; /* Invisible Track */
! 278: scr.cmd[2] = 0x05; /* Write parameters mode page */
! 279: scr.cmd[7] = 0x00;
! 280: scr.cmd[8] = 0x1c;
! 281: scr.cmdlen = 10;
! 282: scr.datalen= 0x1c;
! 283: scr.flags = SCCMD_ESCAPE|SCCMD_READ;
! 284: scr.databuf = (caddr_t)databuf;
! 285:
! 286: r = ioctl(fd, SCIOCCOMMAND, &scr);
! 287: memcpy(&tmp, &databuf[12], sizeof(tmp));
! 288: *nwa = betoh32(tmp);
! 289: return (r == 0 ? scr.retsts : -1);
! 290: }