[BACK]Return to mmc.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / cdio

Annotation of src/usr.bin/cdio/mmc.c, Revision 1.2

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