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

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