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: }