cd.c revision 1.18.2.2 1 1.1 cgd /*
2 1.1 cgd * Written by Julian Elischer (julian (at) tfs.com)
3 1.1 cgd * for TRW Financial Systems for use under the MACH(2.5) operating system.
4 1.1 cgd *
5 1.1 cgd * TRW Financial Systems, in accordance with their agreement with Carnegie
6 1.1 cgd * Mellon University, makes this software available to CMU to distribute
7 1.1 cgd * or use in any manner that they see fit as long as this message is kept with
8 1.1 cgd * the software. For this reason TFS also grants any other persons or
9 1.1 cgd * organisations permission to use or modify this software.
10 1.1 cgd *
11 1.1 cgd * TFS supplies this software to be publicly redistributed
12 1.1 cgd * on the understanding that TFS is not responsible for the correct
13 1.1 cgd * functioning of this software in any circumstances.
14 1.1 cgd *
15 1.18.2.2 mycroft * Ported to run under 386BSD by Julian Elischer (julian (at) tfs.com) Sept 1992
16 1.18.2.2 mycroft *
17 1.18.2.2 mycroft * $Id: cd.c,v 1.18.2.2 1993/11/24 05:02:56 mycroft Exp $
18 1.1 cgd */
19 1.1 cgd
20 1.1 cgd #define SPLCD splbio
21 1.1 cgd #define ESUCCESS 0
22 1.18.2.2 mycroft #include <cd.h>
23 1.18.2.2 mycroft #include <sys/types.h>
24 1.18.2.2 mycroft #include <sys/param.h>
25 1.18.2.2 mycroft #include <sys/dkbad.h>
26 1.18.2.2 mycroft #include <sys/systm.h>
27 1.18.2.2 mycroft #include <sys/conf.h>
28 1.18.2.2 mycroft #include <sys/file.h>
29 1.18.2.2 mycroft #include <sys/stat.h>
30 1.18.2.2 mycroft #include <sys/ioctl.h>
31 1.18.2.2 mycroft #include <sys/buf.h>
32 1.18.2.2 mycroft #include <sys/uio.h>
33 1.18.2.2 mycroft #include <sys/malloc.h>
34 1.18.2.2 mycroft #include <sys/cdio.h>
35 1.18.2.2 mycroft
36 1.18.2.2 mycroft #include <sys/errno.h>
37 1.18.2.2 mycroft #include <sys/disklabel.h>
38 1.18.2.2 mycroft #include <scsi/scsi_all.h>
39 1.18.2.2 mycroft #include <scsi/scsi_cd.h>
40 1.18.2.2 mycroft #include <scsi/scsi_disk.h> /* rw_big and start_stop come from there */
41 1.18.2.2 mycroft #include <scsi/scsiconf.h>
42 1.18.2.2 mycroft
43 1.18.2.2 mycroft int32 cdstrats, cdqueues;
44 1.18.2.2 mycroft
45 1.18.2.2 mycroft #include <ddb.h>
46 1.18.2.2 mycroft #if NDDB > 0
47 1.18.2.2 mycroft int Debugger();
48 1.18.2.2 mycroft #else /* NDDB > 0 */
49 1.1 cgd #define Debugger()
50 1.18.2.2 mycroft #endif /* NDDB > 0 */
51 1.1 cgd
52 1.1 cgd #define PAGESIZ 4096
53 1.18.2.2 mycroft #define SECSIZE 2048 /* XXX */ /* default only */
54 1.1 cgd #define CDOUTSTANDING 2
55 1.18.2.2 mycroft #define CDRETRIES 1
56 1.1 cgd
57 1.1 cgd #define UNITSHIFT 3
58 1.1 cgd #define PARTITION(z) (minor(z) & 0x07)
59 1.1 cgd #define RAW_PART 3
60 1.1 cgd #define UNIT(z) ( (minor(z) >> UNITSHIFT) )
61 1.1 cgd
62 1.18.2.2 mycroft extern int hz;
63 1.18.2.2 mycroft errval cdstrategy();
64 1.1 cgd
65 1.18.2.2 mycroft void cdstart();
66 1.18.2.2 mycroft struct scsi_device cd_switch =
67 1.18.2.2 mycroft {
68 1.18.2.2 mycroft NULL, /* use default error handler */
69 1.18.2.2 mycroft cdstart, /* we have a queue, which is started by this */
70 1.18.2.2 mycroft NULL, /* we do not have an async handler */
71 1.18.2.2 mycroft NULL, /* use default 'done' routine */
72 1.18.2.2 mycroft "cd", /* we are to be refered to by this name */
73 1.18.2.2 mycroft 0, /* no device specific flags */
74 1.18.2.2 mycroft 0, 0 /* spares not used */
75 1.18.2.2 mycroft };
76 1.18.2.2 mycroft
77 1.18.2.2 mycroft struct cd_data {
78 1.18.2.2 mycroft u_int32 flags;
79 1.18.2.2 mycroft #define CDINIT 0x04 /* device has been init'd */
80 1.18.2.2 mycroft struct scsi_link *sc_link; /* address of scsi low level switch */
81 1.18.2.2 mycroft u_int32 cmdscount; /* cmds allowed outstanding by board */
82 1.18.2.2 mycroft struct cd_parms {
83 1.18.2.2 mycroft u_int32 blksize;
84 1.18.2.2 mycroft u_long disksize; /* total number sectors */
85 1.18.2.2 mycroft } params;
86 1.18.2.2 mycroft struct disklabel disklabel;
87 1.18.2.2 mycroft u_int32 partflags[MAXPARTITIONS]; /* per partition flags */
88 1.18.2.2 mycroft #define CDOPEN 0x01
89 1.18.2.2 mycroft u_int32 openparts; /* one bit for each open partition */
90 1.18.2.2 mycroft u_int32 xfer_block_wait;
91 1.18.2.2 mycroft struct buf buf_queue;
92 1.18.2.2 mycroft };
93 1.1 cgd
94 1.1 cgd #define CD_STOP 0
95 1.1 cgd #define CD_START 1
96 1.1 cgd #define CD_EJECT -2
97 1.1 cgd
98 1.18.2.2 mycroft struct cd_driver {
99 1.18.2.2 mycroft u_int32 size;
100 1.18.2.2 mycroft struct cd_data **cd_data;
101 1.18.2.2 mycroft } cd_driver;
102 1.18.2.2 mycroft
103 1.18.2.2 mycroft static u_int32 next_cd_unit = 0;
104 1.18.2.2 mycroft
105 1.6 deraadt /*
106 1.6 deraadt * The routine called by the low level scsi routine when it discovers
107 1.6 deraadt * A device suitable for this driver
108 1.6 deraadt */
109 1.18.2.2 mycroft int
110 1.18.2.2 mycroft cdattach(sc_link)
111 1.18.2.2 mycroft struct scsi_link *sc_link;
112 1.1 cgd {
113 1.18.2.2 mycroft u_int32 unit, i;
114 1.1 cgd unsigned char *tbl;
115 1.18.2.2 mycroft struct cd_data *cd, **cdrealloc;
116 1.1 cgd struct cd_parms *dp;
117 1.1 cgd
118 1.18.2.2 mycroft SC_DEBUG(sc_link, SDEV_DB2, ("cdattach "));
119 1.3 deraadt
120 1.18.2.2 mycroft /*
121 1.18.2.2 mycroft * Fill out any more info in the
122 1.18.2.2 mycroft * Link structure that we can
123 1.18.2.2 mycroft */
124 1.18.2.2 mycroft unit = next_cd_unit++;
125 1.18.2.2 mycroft sc_link->device = &cd_switch;
126 1.18.2.2 mycroft sc_link->dev_unit = unit;
127 1.18.2.2 mycroft /*
128 1.18.2.2 mycroft * allocate the resources for another drive
129 1.18.2.2 mycroft * if we have already allocate a cd_data pointer we must
130 1.18.2.2 mycroft * copy the old pointers into a new region that is
131 1.18.2.2 mycroft * larger and release the old region, aka realloc
132 1.18.2.2 mycroft */
133 1.18.2.2 mycroft /* XXX
134 1.18.2.2 mycroft * This if will always be true for now, but future code may
135 1.18.2.2 mycroft * preallocate more units to reduce overhead. This would be
136 1.18.2.2 mycroft * done by changing the malloc to be (next_cd_unit * x) and
137 1.18.2.2 mycroft * the cd_driver.size++ to be +x
138 1.18.2.2 mycroft */
139 1.18.2.2 mycroft if (unit >= cd_driver.size) {
140 1.18.2.2 mycroft cdrealloc =
141 1.18.2.2 mycroft malloc(sizeof(cd_driver.cd_data) * next_cd_unit,
142 1.18.2.2 mycroft M_DEVBUF, M_NOWAIT);
143 1.18.2.2 mycroft if (!cdrealloc) {
144 1.18.2.2 mycroft printf("cd%d: malloc failed for cdrealloc\n", unit);
145 1.18.2.2 mycroft return (0);
146 1.18.2.2 mycroft }
147 1.18.2.2 mycroft /* Make sure we have something to copy before we copy it */
148 1.18.2.2 mycroft bzero(cdrealloc, sizeof(cd_driver.cd_data) * next_cd_unit);
149 1.18.2.2 mycroft if (cd_driver.size) {
150 1.18.2.2 mycroft bcopy(cd_driver.cd_data, cdrealloc,
151 1.18.2.2 mycroft sizeof(cd_driver.cd_data) * cd_driver.size);
152 1.18.2.2 mycroft free(cd_driver.cd_data, M_DEVBUF);
153 1.18.2.2 mycroft }
154 1.18.2.2 mycroft cd_driver.cd_data = cdrealloc;
155 1.18.2.2 mycroft cd_driver.cd_data[unit] = NULL;
156 1.18.2.2 mycroft cd_driver.size++;
157 1.18.2.2 mycroft }
158 1.18.2.2 mycroft if (cd_driver.cd_data[unit]) {
159 1.18.2.2 mycroft printf("cd%d: Already has storage!\n", unit);
160 1.18.2.2 mycroft return (0);
161 1.18.2.2 mycroft }
162 1.18.2.2 mycroft /*
163 1.18.2.2 mycroft * allocate the per drive data area
164 1.18.2.2 mycroft */
165 1.18.2.2 mycroft cd = cd_driver.cd_data[unit] =
166 1.18.2.2 mycroft malloc(sizeof(struct cd_data), M_DEVBUF, M_NOWAIT);
167 1.18.2.2 mycroft if (!cd) {
168 1.18.2.2 mycroft printf("cd%d: malloc failed for cd_data\n", unit);
169 1.18.2.2 mycroft return (0);
170 1.18.2.2 mycroft }
171 1.18.2.2 mycroft bzero(cd, sizeof(struct cd_data));
172 1.18.2.2 mycroft dp = &(cd->params);
173 1.18.2.2 mycroft /*
174 1.18.2.2 mycroft * Store information needed to contact our base driver
175 1.18.2.2 mycroft */
176 1.18.2.2 mycroft cd->sc_link = sc_link;
177 1.18.2.2 mycroft /* only allow 1 outstanding command on tapes */
178 1.18.2.2 mycroft sc_link->opennings = cd->cmdscount = CDOUTSTANDING;
179 1.18.2.2 mycroft
180 1.18.2.2 mycroft /*
181 1.18.2.2 mycroft * Use the subdriver to request information regarding
182 1.18.2.2 mycroft * the drive. We cannot use interrupts yet, so the
183 1.18.2.2 mycroft * request must specify this.
184 1.18.2.2 mycroft */
185 1.18.2.2 mycroft cd_get_parms(unit, SCSI_NOSLEEP | SCSI_NOMASK);
186 1.18.2.2 mycroft if (dp->disksize) {
187 1.18.2.2 mycroft printf("cd%d: cd present.[%d x %d byte records]\n",
188 1.18.2.2 mycroft unit,
189 1.18.2.2 mycroft cd->params.disksize,
190 1.18.2.2 mycroft cd->params.blksize);
191 1.18.2.2 mycroft } else {
192 1.18.2.2 mycroft printf("cd%d: drive empty\n", unit);
193 1.18.2.2 mycroft }
194 1.1 cgd cd->flags |= CDINIT;
195 1.18.2.2 mycroft return (1);
196 1.1 cgd }
197 1.1 cgd
198 1.18.2.2 mycroft /*
199 1.18.2.2 mycroft * open the device. Make sure the partition info is a up-to-date as can be.
200 1.18.2.2 mycroft */
201 1.18.2.2 mycroft errval
202 1.18.2.2 mycroft cdopen(dev)
203 1.1 cgd {
204 1.18.2.2 mycroft errval errcode = 0;
205 1.18.2.2 mycroft u_int32 unit, part;
206 1.1 cgd struct cd_parms cd_parms;
207 1.4 deraadt struct cd_data *cd;
208 1.18.2.2 mycroft struct scsi_link *sc_link;
209 1.18.2.2 mycroft u_int32 heldflags;
210 1.1 cgd
211 1.1 cgd unit = UNIT(dev);
212 1.1 cgd part = PARTITION(dev);
213 1.3 deraadt
214 1.18.2.2 mycroft /*
215 1.18.2.2 mycroft * Check the unit is legal
216 1.18.2.2 mycroft */
217 1.18.2.2 mycroft if (unit >= cd_driver.size) {
218 1.18.2.2 mycroft return (ENXIO);
219 1.18.2.2 mycroft }
220 1.18.2.2 mycroft cd = cd_driver.cd_data[unit];
221 1.18.2.2 mycroft /*
222 1.18.2.2 mycroft * Make sure the device has been initialised
223 1.18.2.2 mycroft */
224 1.18.2.2 mycroft if ((cd == NULL) || (!(cd->flags & CDINIT)))
225 1.18.2.2 mycroft return (ENXIO);
226 1.18.2.2 mycroft
227 1.18.2.2 mycroft sc_link = cd->sc_link;
228 1.18.2.2 mycroft SC_DEBUG(sc_link, SDEV_DB1,
229 1.18.2.2 mycroft ("cdopen: dev=0x%x (unit %d (of %d),partition %d)\n",
230 1.18.2.2 mycroft dev, unit, cd_driver.size, part));
231 1.18.2.2 mycroft /*
232 1.18.2.2 mycroft * If it's been invalidated, and not everybody has closed it then
233 1.18.2.2 mycroft * forbid re-entry. (may have changed media)
234 1.18.2.2 mycroft */
235 1.18.2.2 mycroft if ((!(sc_link->flags & SDEV_MEDIA_LOADED))
236 1.18.2.2 mycroft && (cd->openparts))
237 1.18.2.2 mycroft return (ENXIO);
238 1.18.2.2 mycroft
239 1.18.2.2 mycroft /*
240 1.18.2.2 mycroft * Check that it is still responding and ok.
241 1.18.2.2 mycroft * if the media has been changed this will result in a
242 1.18.2.2 mycroft * "unit attention" error which the error code will
243 1.18.2.2 mycroft * disregard because the SDEV_MEDIA_LOADED flag is not yet set
244 1.18.2.2 mycroft */
245 1.18.2.2 mycroft scsi_test_unit_ready(sc_link, SCSI_SILENT);
246 1.18.2.2 mycroft
247 1.18.2.2 mycroft /*
248 1.18.2.2 mycroft * Next time actually take notice of error returns
249 1.18.2.2 mycroft */
250 1.18.2.2 mycroft sc_link->flags |= SDEV_OPEN; /* unit attn errors are now errors */
251 1.18.2.2 mycroft if (scsi_test_unit_ready(sc_link, SCSI_SILENT) != 0) {
252 1.18.2.2 mycroft SC_DEBUG(sc_link, SDEV_DB3, ("not ready\n"));
253 1.18.2.2 mycroft errcode = ENXIO;
254 1.18.2.2 mycroft goto bad;
255 1.18.2.2 mycroft }
256 1.18.2.2 mycroft SC_DEBUG(sc_link, SDEV_DB3, ("Device present\n"));
257 1.18.2.2 mycroft /*
258 1.18.2.2 mycroft * In case it is a funny one, tell it to start
259 1.18.2.2 mycroft * not needed for some drives
260 1.18.2.2 mycroft */
261 1.18.2.2 mycroft scsi_start_unit(sc_link, CD_START);
262 1.18.2.2 mycroft scsi_prevent(sc_link, PR_PREVENT, SCSI_SILENT);
263 1.18.2.2 mycroft SC_DEBUG(sc_link, SDEV_DB3, ("started "));
264 1.18.2.2 mycroft /*
265 1.18.2.2 mycroft * Load the physical device parameters
266 1.18.2.2 mycroft */
267 1.18.2.2 mycroft if (cd_get_parms(unit, 0)) {
268 1.18.2.2 mycroft errcode = ENXIO;
269 1.18.2.2 mycroft goto bad;
270 1.18.2.2 mycroft }
271 1.18.2.2 mycroft SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded "));
272 1.18.2.2 mycroft /*
273 1.18.2.2 mycroft * Make up some partition information
274 1.18.2.2 mycroft */
275 1.1 cgd cdgetdisklabel(unit);
276 1.18.2.2 mycroft SC_DEBUG(sc_link, SDEV_DB3, ("Disklabel fabricated "));
277 1.18.2.2 mycroft /*
278 1.18.2.2 mycroft * Check the partition is legal
279 1.18.2.2 mycroft */
280 1.18.2.2 mycroft if ((part >= cd->disklabel.d_npartitions)
281 1.18.2.2 mycroft && (part != RAW_PART)) {
282 1.18.2.2 mycroft SC_DEBUG(sc_link, SDEV_DB3, ("partition %d > %d\n", part
283 1.18.2.2 mycroft ,cd->disklabel.d_npartitions));
284 1.18.2.2 mycroft errcode = ENXIO;
285 1.18.2.2 mycroft goto bad;
286 1.1 cgd }
287 1.18.2.2 mycroft /*
288 1.18.2.2 mycroft * Check that the partition exists
289 1.18.2.2 mycroft */
290 1.18.2.2 mycroft if ((cd->disklabel.d_partitions[part].p_fstype == FS_UNUSED)
291 1.18.2.2 mycroft && (part != RAW_PART)) {
292 1.18.2.2 mycroft SC_DEBUG(sc_link, SDEV_DB3, ("part %d type UNUSED\n", part));
293 1.18.2.2 mycroft errcode = ENXIO;
294 1.18.2.2 mycroft goto bad;
295 1.1 cgd }
296 1.18.2.2 mycroft cd->partflags[part] |= CDOPEN;
297 1.18.2.2 mycroft cd->openparts |= (1 << part);
298 1.18.2.2 mycroft SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n"));
299 1.18.2.2 mycroft sc_link->flags |= SDEV_MEDIA_LOADED;
300 1.18.2.2 mycroft return (0);
301 1.18.2.2 mycroft bad:
302 1.18.2.2 mycroft
303 1.18.2.2 mycroft /*
304 1.18.2.2 mycroft * if we would have been the only open
305 1.18.2.2 mycroft * then leave things back as they were
306 1.18.2.2 mycroft */
307 1.18.2.2 mycroft if (!(cd->openparts)) {
308 1.18.2.2 mycroft sc_link->flags &= ~SDEV_OPEN;
309 1.18.2.2 mycroft scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
310 1.1 cgd }
311 1.18.2.2 mycroft return (errcode);
312 1.1 cgd }
313 1.1 cgd
314 1.18.2.2 mycroft /*
315 1.18.2.2 mycroft * close the device.. only called if we are the LAST
316 1.18.2.2 mycroft * occurence of an open device
317 1.18.2.2 mycroft */
318 1.18.2.2 mycroft errval
319 1.18.2.2 mycroft cdclose(dev)
320 1.18.2.2 mycroft dev_t dev;
321 1.18.2.2 mycroft {
322 1.18.2.2 mycroft u_int8 unit, part;
323 1.18.2.2 mycroft u_int32 old_priority;
324 1.18.2.2 mycroft struct cd_data *cd;
325 1.18.2.2 mycroft struct scsi_link *sc_link;
326 1.4 deraadt
327 1.18.2.2 mycroft unit = UNIT(dev);
328 1.18.2.2 mycroft part = PARTITION(dev);
329 1.18.2.2 mycroft cd = cd_driver.cd_data[unit];
330 1.18.2.2 mycroft sc_link = cd->sc_link;
331 1.18.2.2 mycroft SC_DEBUG(sc_link, SDEV_DB2, ("cd%d: closing part %d\n", unit, part));
332 1.18.2.2 mycroft cd->partflags[part] &= ~CDOPEN;
333 1.18.2.2 mycroft cd->openparts &= ~(1 << part);
334 1.18.2.2 mycroft
335 1.18.2.2 mycroft /*
336 1.18.2.2 mycroft * If we were the last open of the entire device, release it.
337 1.18.2.2 mycroft */
338 1.18.2.2 mycroft if (!(cd->openparts)) {
339 1.18.2.2 mycroft scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
340 1.18.2.2 mycroft cd->sc_link->flags &= ~SDEV_OPEN;
341 1.4 deraadt }
342 1.18.2.2 mycroft return (0);
343 1.18.2.2 mycroft }
344 1.18.2.2 mycroft
345 1.18.2.2 mycroft /*
346 1.18.2.2 mycroft * trim the size of the transfer if needed,
347 1.18.2.2 mycroft * called by physio
348 1.18.2.2 mycroft * basically the smaller of our max and the scsi driver's
349 1.18.2.2 mycroft * minphys (note we have no max ourselves)
350 1.18.2.2 mycroft *
351 1.18.2.2 mycroft * Trim buffer length if buffer-size is bigger than page size
352 1.18.2.2 mycroft */
353 1.18.2.2 mycroft void
354 1.18.2.2 mycroft cdminphys(bp)
355 1.18.2.2 mycroft struct buf *bp;
356 1.18.2.2 mycroft {
357 1.18.2.2 mycroft (*(cd_driver.cd_data[UNIT(bp->b_dev)]->sc_link->adapter->scsi_minphys)) (bp);
358 1.18.2.2 mycroft }
359 1.18.2.2 mycroft
360 1.18.2.2 mycroft /*
361 1.18.2.2 mycroft * Actually translate the requested transfer into one the physical driver can
362 1.18.2.2 mycroft * understand. The transfer is described by a buf and will include only one
363 1.18.2.2 mycroft * physical transfer.
364 1.18.2.2 mycroft */
365 1.18.2.2 mycroft errval
366 1.18.2.2 mycroft cdstrategy(bp)
367 1.18.2.2 mycroft struct buf *bp;
368 1.18.2.2 mycroft {
369 1.18.2.2 mycroft struct buf *dp;
370 1.18.2.2 mycroft u_int32 opri;
371 1.18.2.2 mycroft u_int32 unit = UNIT((bp->b_dev));
372 1.18.2.2 mycroft struct cd_data *cd = cd_driver.cd_data[unit];
373 1.18.2.2 mycroft
374 1.18.2.2 mycroft cdstrats++;
375 1.18.2.2 mycroft SC_DEBUG(cd->sc_link, SDEV_DB2, ("\ncdstrategy "));
376 1.18.2.2 mycroft SC_DEBUG(cd->sc_link, SDEV_DB1, ("cd%d: %d bytes @ blk%d\n",
377 1.18.2.2 mycroft unit, bp->b_bcount, bp->b_blkno));
378 1.18.2.2 mycroft cdminphys(bp);
379 1.18.2.2 mycroft /*
380 1.18.2.2 mycroft * If the device has been made invalid, error out
381 1.18.2.2 mycroft * maybe the media changed
382 1.18.2.2 mycroft */
383 1.18.2.2 mycroft if (!(cd->sc_link->flags & SDEV_MEDIA_LOADED)) {
384 1.4 deraadt bp->b_error = EIO;
385 1.4 deraadt goto bad;
386 1.4 deraadt }
387 1.18.2.2 mycroft /*
388 1.18.2.2 mycroft * can't ever write to a CD
389 1.18.2.2 mycroft */
390 1.1 cgd if ((bp->b_flags & B_READ) == 0) {
391 1.1 cgd bp->b_error = EROFS;
392 1.1 cgd goto bad;
393 1.1 cgd }
394 1.18.2.2 mycroft /*
395 1.18.2.2 mycroft * If it's a null transfer, return immediatly
396 1.18.2.2 mycroft */
397 1.1 cgd if (bp->b_bcount == 0) {
398 1.1 cgd goto done;
399 1.1 cgd }
400 1.18.2.2 mycroft /*
401 1.18.2.2 mycroft * Decide which unit and partition we are talking about
402 1.18.2.2 mycroft */
403 1.18.2.2 mycroft if (PARTITION(bp->b_dev) != RAW_PART) {
404 1.1 cgd /*
405 1.1 cgd * do bounds checking, adjust transfer. if error, process.
406 1.1 cgd * if end of partition, just return
407 1.1 cgd */
408 1.18.2.2 mycroft if (bounds_check_with_label(bp, &cd->disklabel, 1) <= 0)
409 1.1 cgd goto done;
410 1.1 cgd /* otherwise, process transfer request */
411 1.1 cgd }
412 1.1 cgd opri = SPLCD();
413 1.18.2.2 mycroft dp = &cd->buf_queue;
414 1.1 cgd
415 1.18.2.2 mycroft /*
416 1.18.2.2 mycroft * Place it in the queue of disk activities for this disk
417 1.18.2.2 mycroft */
418 1.1 cgd disksort(dp, bp);
419 1.1 cgd
420 1.18.2.2 mycroft /*
421 1.18.2.2 mycroft * Tell the device to get going on the transfer if it's
422 1.18.2.2 mycroft * not doing anything, otherwise just wait for completion
423 1.18.2.2 mycroft */
424 1.1 cgd cdstart(unit);
425 1.1 cgd
426 1.1 cgd splx(opri);
427 1.1 cgd return;
428 1.18.2.2 mycroft bad:
429 1.1 cgd bp->b_flags |= B_ERROR;
430 1.18.2.2 mycroft done:
431 1.1 cgd
432 1.18.2.2 mycroft /*
433 1.18.2.2 mycroft * Correctly set the buf to indicate a completed xfer
434 1.18.2.2 mycroft */
435 1.18.2.2 mycroft bp->b_resid = bp->b_bcount;
436 1.1 cgd biodone(bp);
437 1.18.2.2 mycroft return (0);
438 1.1 cgd }
439 1.1 cgd
440 1.18.2.2 mycroft /*
441 1.18.2.2 mycroft * cdstart looks to see if there is a buf waiting for the device
442 1.18.2.2 mycroft * and that the device is not already busy. If both are true,
443 1.18.2.2 mycroft * It deques the buf and creates a scsi command to perform the
444 1.18.2.2 mycroft * transfer in the buf. The transfer request will call scsi_done
445 1.18.2.2 mycroft * on completion, which will in turn call this routine again
446 1.18.2.2 mycroft * so that the next queued transfer is performed.
447 1.18.2.2 mycroft * The bufs are queued by the strategy routine (cdstrategy)
448 1.18.2.2 mycroft *
449 1.18.2.2 mycroft * This routine is also called after other non-queued requests
450 1.18.2.2 mycroft * have been made of the scsi driver, to ensure that the queue
451 1.18.2.2 mycroft * continues to be drained.
452 1.18.2.2 mycroft *
453 1.18.2.2 mycroft * must be called at the correct (highish) spl level
454 1.18.2.2 mycroft * cdstart() is called at SPLCD from cdstrategy and scsi_done
455 1.18.2.2 mycroft */
456 1.18.2.2 mycroft void
457 1.18.2.2 mycroft cdstart(unit)
458 1.18.2.2 mycroft u_int32 unit;
459 1.18.2.2 mycroft {
460 1.18.2.2 mycroft register struct buf *bp = 0;
461 1.18.2.2 mycroft register struct buf *dp;
462 1.18.2.2 mycroft struct scsi_rw_big cmd;
463 1.18.2.2 mycroft u_int32 blkno, nblk;
464 1.18.2.2 mycroft struct partition *p;
465 1.18.2.2 mycroft struct cd_data *cd = cd_driver.cd_data[unit];
466 1.18.2.2 mycroft struct scsi_link *sc_link = cd->sc_link;
467 1.18.2.2 mycroft
468 1.18.2.2 mycroft SC_DEBUG(sc_link, SDEV_DB2, ("cdstart%d ", unit));
469 1.18.2.2 mycroft /*
470 1.18.2.2 mycroft * See if there is a buf to do and we are not already
471 1.18.2.2 mycroft * doing one
472 1.18.2.2 mycroft */
473 1.18.2.2 mycroft if (!sc_link->opennings) {
474 1.18.2.2 mycroft return; /* no room for us, unit already underway */
475 1.1 cgd }
476 1.18.2.2 mycroft if (sc_link->flags & SDEV_WAITING) { /* is room, but a special waits */
477 1.18.2.2 mycroft return; /* give the special that's waiting a chance to run */
478 1.1 cgd }
479 1.18.2.2 mycroft dp = &cd->buf_queue;
480 1.18.2.2 mycroft if ((bp = dp->b_actf) != NULL) { /* yes, an assign */
481 1.18.2.2 mycroft dp->b_actf = bp->av_forw;
482 1.18.2.2 mycroft } else {
483 1.1 cgd return;
484 1.1 cgd }
485 1.18.2.2 mycroft /*
486 1.18.2.2 mycroft * Should reject all queued entries if SDEV_MEDIA_LOADED is not true.
487 1.18.2.2 mycroft */
488 1.18.2.2 mycroft if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
489 1.18.2.2 mycroft goto bad; /* no I/O.. media changed or something */
490 1.18.2.2 mycroft }
491 1.18.2.2 mycroft /*
492 1.18.2.2 mycroft * We have a buf, now we should make a command
493 1.18.2.2 mycroft *
494 1.18.2.2 mycroft * First, translate the block to absolute and put it in terms of the
495 1.18.2.2 mycroft * logical blocksize of the device. Really a bit silly until we have
496 1.18.2.2 mycroft * real partitions, but.
497 1.18.2.2 mycroft */
498 1.18.2.2 mycroft blkno = bp->b_blkno / (cd->params.blksize / 512);
499 1.18.2.2 mycroft if (PARTITION(bp->b_dev) != RAW_PART) {
500 1.18.2.2 mycroft p = cd->disklabel.d_partitions + PARTITION(bp->b_dev);
501 1.18.2.2 mycroft blkno += p->p_offset;
502 1.18.2.2 mycroft }
503 1.1 cgd nblk = (bp->b_bcount + (cd->params.blksize - 1)) / (cd->params.blksize);
504 1.18.2.2 mycroft /* what if something asks for 512 bytes not on a 2k boundary? *//*XXX */
505 1.1 cgd
506 1.18.2.2 mycroft /*
507 1.18.2.2 mycroft * Fill out the scsi command
508 1.18.2.2 mycroft */
509 1.1 cgd bzero(&cmd, sizeof(cmd));
510 1.18.2.2 mycroft cmd.op_code = READ_BIG;
511 1.18.2.2 mycroft cmd.addr_3 = (blkno & 0xff000000) >> 24;
512 1.18.2.2 mycroft cmd.addr_2 = (blkno & 0xff0000) >> 16;
513 1.18.2.2 mycroft cmd.addr_1 = (blkno & 0xff00) >> 8;
514 1.18.2.2 mycroft cmd.addr_0 = blkno & 0xff;
515 1.18.2.2 mycroft cmd.length2 = (nblk & 0xff00) >> 8;
516 1.18.2.2 mycroft cmd.length1 = (nblk & 0xff);
517 1.18.2.2 mycroft
518 1.18.2.2 mycroft /*
519 1.18.2.2 mycroft * Call the routine that chats with the adapter.
520 1.18.2.2 mycroft * Note: we cannot sleep as we may be an interrupt
521 1.18.2.2 mycroft */
522 1.18.2.2 mycroft if (scsi_scsi_cmd(sc_link,
523 1.18.2.2 mycroft (struct scsi_generic *) &cmd,
524 1.18.2.2 mycroft sizeof(cmd),
525 1.18.2.2 mycroft (u_char *) bp->b_un.b_addr,
526 1.18.2.2 mycroft bp->b_bcount,
527 1.18.2.2 mycroft CDRETRIES,
528 1.18.2.2 mycroft 30000,
529 1.18.2.2 mycroft bp,
530 1.18.2.2 mycroft SCSI_NOSLEEP | ((bp->b_flags & B_READ) ?
531 1.18.2.2 mycroft SCSI_DATA_IN : SCSI_DATA_OUT))
532 1.18.2.2 mycroft != SUCCESSFULLY_QUEUED) {
533 1.18.2.2 mycroft bad:
534 1.18.2.2 mycroft printf("cd%d: oops not queued", unit);
535 1.18.2.2 mycroft bp->b_error = EIO;
536 1.18.2.2 mycroft bp->b_flags |= B_ERROR;
537 1.1 cgd biodone(bp);
538 1.18.2.2 mycroft return;
539 1.1 cgd }
540 1.18.2.2 mycroft cdqueues++;
541 1.1 cgd }
542 1.18.2.2 mycroft
543 1.18.2.2 mycroft /*
544 1.18.2.2 mycroft * Perform special action on behalf of the user.
545 1.18.2.2 mycroft * Knows about the internals of this device
546 1.18.2.2 mycroft */
547 1.18.2.2 mycroft errval
548 1.1 cgd cdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
549 1.1 cgd {
550 1.18.2.2 mycroft errval error = 0;
551 1.18.2.2 mycroft u_int32 opri;
552 1.18.2.2 mycroft u_int8 unit, part;
553 1.1 cgd register struct cd_data *cd;
554 1.1 cgd
555 1.18.2.2 mycroft /*
556 1.18.2.2 mycroft * Find the device that the user is talking about
557 1.18.2.2 mycroft */
558 1.1 cgd unit = UNIT(dev);
559 1.1 cgd part = PARTITION(dev);
560 1.18.2.2 mycroft cd = cd_driver.cd_data[unit];
561 1.18.2.2 mycroft SC_DEBUG(cd->sc_link, SDEV_DB2, ("cdioctl 0x%x ", cmd));
562 1.1 cgd
563 1.18.2.2 mycroft /*
564 1.18.2.2 mycroft * If the device is not valid.. abandon ship
565 1.18.2.2 mycroft */
566 1.18.2.2 mycroft if (!(cd->sc_link->flags & SDEV_MEDIA_LOADED))
567 1.18.2.2 mycroft return (EIO);
568 1.18.2.2 mycroft switch (cmd) {
569 1.1 cgd
570 1.1 cgd case DIOCSBAD:
571 1.18.2.2 mycroft error = EINVAL;
572 1.1 cgd break;
573 1.1 cgd
574 1.1 cgd case DIOCGDINFO:
575 1.18.2.2 mycroft *(struct disklabel *) addr = cd->disklabel;
576 1.1 cgd break;
577 1.1 cgd
578 1.18.2.2 mycroft case DIOCGPART:
579 1.18.2.2 mycroft ((struct partinfo *) addr)->disklab = &cd->disklabel;
580 1.18.2.2 mycroft ((struct partinfo *) addr)->part =
581 1.18.2.2 mycroft &cd->disklabel.d_partitions[PARTITION(dev)];
582 1.18.2.2 mycroft break;
583 1.18.2.2 mycroft
584 1.18.2.2 mycroft /*
585 1.18.2.2 mycroft * a bit silly, but someone might want to test something on a
586 1.18.2.2 mycroft * section of cdrom.
587 1.18.2.2 mycroft */
588 1.18.2.2 mycroft case DIOCWDINFO:
589 1.18.2.2 mycroft case DIOCSDINFO:
590 1.18.2.2 mycroft if ((flag & FWRITE) == 0)
591 1.18.2.2 mycroft error = EBADF;
592 1.18.2.2 mycroft else
593 1.18.2.2 mycroft error = setdisklabel(&cd->disklabel,
594 1.18.2.2 mycroft (struct disklabel *) addr,
595 1.18.2.2 mycroft 0,
596 1.18.2.2 mycroft 0);
597 1.18.2.2 mycroft if (error == 0)
598 1.18.2.2 mycroft break;
599 1.1 cgd
600 1.18.2.2 mycroft case DIOCWLABEL:
601 1.18.2.2 mycroft error = EBADF;
602 1.18.2.2 mycroft break;
603 1.1 cgd
604 1.1 cgd case CDIOCPLAYTRACKS:
605 1.1 cgd {
606 1.18.2.2 mycroft struct ioc_play_track *args
607 1.18.2.2 mycroft = (struct ioc_play_track *) addr;
608 1.18.2.2 mycroft struct cd_mode_data data;
609 1.18.2.2 mycroft if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
610 1.18.2.2 mycroft break;
611 1.18.2.2 mycroft data.page.audio.flags &= ~CD_PA_SOTC;
612 1.18.2.2 mycroft data.page.audio.flags |= CD_PA_IMMED;
613 1.18.2.2 mycroft if (error = cd_set_mode(unit, &data))
614 1.18.2.2 mycroft break;
615 1.18.2.2 mycroft return (cd_play_tracks(unit
616 1.18.2.2 mycroft ,args->start_track
617 1.18.2.2 mycroft ,args->start_index
618 1.18.2.2 mycroft ,args->end_track
619 1.18.2.2 mycroft ,args->end_index
620 1.18.2.2 mycroft ));
621 1.1 cgd }
622 1.1 cgd break;
623 1.17 brezak case CDIOCPLAYMSF:
624 1.17 brezak {
625 1.18.2.2 mycroft struct ioc_play_msf *args
626 1.18.2.2 mycroft = (struct ioc_play_msf *) addr;
627 1.18.2.2 mycroft struct cd_mode_data data;
628 1.18.2.2 mycroft if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
629 1.18.2.2 mycroft break;
630 1.18.2.2 mycroft data.page.audio.flags &= ~CD_PA_SOTC;
631 1.18.2.2 mycroft data.page.audio.flags |= CD_PA_IMMED;
632 1.18.2.2 mycroft if (error = cd_set_mode(unit, &data))
633 1.18.2.2 mycroft break;
634 1.18.2.2 mycroft return (cd_play_msf(unit
635 1.18.2.2 mycroft ,args->start_m
636 1.18.2.2 mycroft ,args->start_s
637 1.18.2.2 mycroft ,args->start_f
638 1.18.2.2 mycroft ,args->end_m
639 1.18.2.2 mycroft ,args->end_s
640 1.18.2.2 mycroft ,args->end_f
641 1.18.2.2 mycroft ));
642 1.17 brezak }
643 1.17 brezak break;
644 1.1 cgd case CDIOCPLAYBLOCKS:
645 1.1 cgd {
646 1.18.2.2 mycroft struct ioc_play_blocks *args
647 1.18.2.2 mycroft = (struct ioc_play_blocks *) addr;
648 1.18.2.2 mycroft struct cd_mode_data data;
649 1.18.2.2 mycroft if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
650 1.18.2.2 mycroft break;
651 1.18.2.2 mycroft data.page.audio.flags &= ~CD_PA_SOTC;
652 1.18.2.2 mycroft data.page.audio.flags |= CD_PA_IMMED;
653 1.18.2.2 mycroft if (error = cd_set_mode(unit, &data))
654 1.1 cgd break;
655 1.18.2.2 mycroft return (cd_play(unit, args->blk, args->len));
656 1.1 cgd
657 1.1 cgd }
658 1.1 cgd break;
659 1.1 cgd case CDIOCREADSUBCHANNEL:
660 1.1 cgd {
661 1.1 cgd struct ioc_read_subchannel *args
662 1.18.2.2 mycroft = (struct ioc_read_subchannel *) addr;
663 1.1 cgd struct cd_sub_channel_info data;
664 1.18.2.2 mycroft u_int32 len = args->data_len;
665 1.18.2.2 mycroft if (len > sizeof(data) ||
666 1.18.2.2 mycroft len < sizeof(struct cd_sub_channel_header)) {
667 1.18.2.2 mycroft error = EINVAL;
668 1.1 cgd break;
669 1.1 cgd }
670 1.18.2.2 mycroft if (error = cd_read_subchannel(unit, args->address_format,
671 1.18.2.2 mycroft args->data_format, args->track, &data, len)) {
672 1.1 cgd break;
673 1.1 cgd }
674 1.18.2.2 mycroft len = MIN(len, ((data.header.data_len[0] << 8) + data.header.data_len[1] +
675 1.18.2.2 mycroft sizeof(struct cd_sub_channel_header)));
676 1.18.2.2 mycroft if (copyout(&data, args->data, len) != 0) {
677 1.18.2.2 mycroft error = EFAULT;
678 1.1 cgd }
679 1.1 cgd }
680 1.1 cgd break;
681 1.1 cgd case CDIOREADTOCHEADER:
682 1.1 cgd {
683 1.1 cgd struct ioc_toc_header th;
684 1.18.2.2 mycroft if (error = cd_read_toc(unit, 0, 0, &th, sizeof(th)))
685 1.1 cgd break;
686 1.18.2.2 mycroft th.len = (th.len & 0xff) << 8 + ((th.len >> 8) & 0xff);
687 1.18.2.2 mycroft bcopy(&th, addr, sizeof(th));
688 1.1 cgd }
689 1.1 cgd break;
690 1.1 cgd case CDIOREADTOCENTRYS:
691 1.1 cgd {
692 1.18.2.2 mycroft struct ioc_read_toc_entry *te =
693 1.18.2.2 mycroft (struct ioc_read_toc_entry *) addr;
694 1.1 cgd struct cd_toc_entry data[65];
695 1.1 cgd struct ioc_toc_header *th;
696 1.18.2.2 mycroft u_int32 len = te->data_len;
697 1.18.2.2 mycroft th = (struct ioc_toc_header *) data;
698 1.1 cgd
699 1.18.2.2 mycroft if (len > sizeof(data) || len < sizeof(struct cd_toc_entry)) {
700 1.18.2.2 mycroft error = EINVAL;
701 1.18.2.2 mycroft break;
702 1.18.2.2 mycroft }
703 1.18.2.2 mycroft if (error = cd_read_toc(unit, te->address_format,
704 1.18.2.2 mycroft te->starting_track,
705 1.18.2.2 mycroft data,
706 1.18.2.2 mycroft len))
707 1.18.2.2 mycroft break;
708 1.18.2.2 mycroft len = MIN(len, ((((th->len & 0xff) << 8) + ((th->len >> 8))) +
709 1.18.2.2 mycroft sizeof(*th)));
710 1.18.2.2 mycroft if (copyout(th, te->data, len) != 0) {
711 1.18.2.2 mycroft error = EFAULT;
712 1.1 cgd }
713 1.1 cgd }
714 1.1 cgd break;
715 1.1 cgd case CDIOCSETPATCH:
716 1.1 cgd {
717 1.18.2.2 mycroft struct ioc_patch *arg = (struct ioc_patch *) addr;
718 1.18.2.2 mycroft struct cd_mode_data data;
719 1.18.2.2 mycroft if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
720 1.1 cgd break;
721 1.1 cgd data.page.audio.port[LEFT_PORT].channels = arg->patch[0];
722 1.1 cgd data.page.audio.port[RIGHT_PORT].channels = arg->patch[1];
723 1.1 cgd data.page.audio.port[2].channels = arg->patch[2];
724 1.1 cgd data.page.audio.port[3].channels = arg->patch[3];
725 1.18.2.2 mycroft if (error = cd_set_mode(unit, &data))
726 1.18.2.2 mycroft break; /* eh? */
727 1.1 cgd }
728 1.1 cgd break;
729 1.1 cgd case CDIOCGETVOL:
730 1.1 cgd {
731 1.18.2.2 mycroft struct ioc_vol *arg = (struct ioc_vol *) addr;
732 1.18.2.2 mycroft struct cd_mode_data data;
733 1.18.2.2 mycroft if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
734 1.1 cgd break;
735 1.1 cgd arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume;
736 1.1 cgd arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume;
737 1.1 cgd arg->vol[2] = data.page.audio.port[2].volume;
738 1.1 cgd arg->vol[3] = data.page.audio.port[3].volume;
739 1.1 cgd }
740 1.1 cgd break;
741 1.1 cgd case CDIOCSETVOL:
742 1.1 cgd {
743 1.18.2.2 mycroft struct ioc_vol *arg = (struct ioc_vol *) addr;
744 1.18.2.2 mycroft struct cd_mode_data data;
745 1.18.2.2 mycroft if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
746 1.1 cgd break;
747 1.1 cgd data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT];
748 1.1 cgd data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT];
749 1.1 cgd data.page.audio.port[2].volume = arg->vol[2];
750 1.1 cgd data.page.audio.port[3].volume = arg->vol[3];
751 1.18.2.2 mycroft if (error = cd_set_mode(unit, &data))
752 1.1 cgd break;
753 1.1 cgd }
754 1.1 cgd break;
755 1.1 cgd case CDIOCSETMONO:
756 1.1 cgd {
757 1.18.2.2 mycroft struct ioc_vol *arg = (struct ioc_vol *) addr;
758 1.18.2.2 mycroft struct cd_mode_data data;
759 1.18.2.2 mycroft if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
760 1.1 cgd break;
761 1.18.2.2 mycroft data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL | RIGHT_CHANNEL | 4 | 8;
762 1.18.2.2 mycroft data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL | RIGHT_CHANNEL;
763 1.1 cgd data.page.audio.port[2].channels = 0;
764 1.1 cgd data.page.audio.port[3].channels = 0;
765 1.18.2.2 mycroft if (error = cd_set_mode(unit, &data))
766 1.1 cgd break;
767 1.1 cgd }
768 1.1 cgd break;
769 1.1 cgd case CDIOCSETSTERIO:
770 1.1 cgd {
771 1.18.2.2 mycroft struct ioc_vol *arg = (struct ioc_vol *) addr;
772 1.18.2.2 mycroft struct cd_mode_data data;
773 1.18.2.2 mycroft if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
774 1.1 cgd break;
775 1.1 cgd data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
776 1.1 cgd data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
777 1.1 cgd data.page.audio.port[2].channels = 0;
778 1.1 cgd data.page.audio.port[3].channels = 0;
779 1.18.2.2 mycroft if (error = cd_set_mode(unit, &data))
780 1.1 cgd break;
781 1.1 cgd }
782 1.1 cgd break;
783 1.1 cgd case CDIOCSETMUTE:
784 1.1 cgd {
785 1.18.2.2 mycroft struct ioc_vol *arg = (struct ioc_vol *) addr;
786 1.18.2.2 mycroft struct cd_mode_data data;
787 1.18.2.2 mycroft if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
788 1.1 cgd break;
789 1.1 cgd data.page.audio.port[LEFT_PORT].channels = 0;
790 1.1 cgd data.page.audio.port[RIGHT_PORT].channels = 0;
791 1.1 cgd data.page.audio.port[2].channels = 0;
792 1.1 cgd data.page.audio.port[3].channels = 0;
793 1.18.2.2 mycroft if (error = cd_set_mode(unit, &data))
794 1.1 cgd break;
795 1.1 cgd }
796 1.1 cgd break;
797 1.1 cgd case CDIOCSETLEFT:
798 1.1 cgd {
799 1.18.2.2 mycroft struct ioc_vol *arg = (struct ioc_vol *) addr;
800 1.18.2.2 mycroft struct cd_mode_data data;
801 1.18.2.2 mycroft if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
802 1.18.2.2 mycroft break;
803 1.18.2.2 mycroft data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
804 1.18.2.2 mycroft data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL;
805 1.18.2.2 mycroft data.page.audio.port[2].channels = 0;
806 1.18.2.2 mycroft data.page.audio.port[3].channels = 0;
807 1.18.2.2 mycroft if (error = cd_set_mode(unit, &data))
808 1.1 cgd break;
809 1.1 cgd }
810 1.1 cgd break;
811 1.1 cgd case CDIOCSETRIGHT:
812 1.1 cgd {
813 1.18.2.2 mycroft struct ioc_vol *arg = (struct ioc_vol *) addr;
814 1.18.2.2 mycroft struct cd_mode_data data;
815 1.18.2.2 mycroft if (error = cd_get_mode(unit, &data, AUDIO_PAGE))
816 1.1 cgd break;
817 1.1 cgd data.page.audio.port[LEFT_PORT].channels = RIGHT_CHANNEL;
818 1.1 cgd data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
819 1.1 cgd data.page.audio.port[2].channels = 0;
820 1.1 cgd data.page.audio.port[3].channels = 0;
821 1.18.2.2 mycroft if (error = cd_set_mode(unit, &data))
822 1.1 cgd break;
823 1.1 cgd }
824 1.1 cgd break;
825 1.1 cgd case CDIOCRESUME:
826 1.18.2.2 mycroft error = cd_pause(unit, 1);
827 1.1 cgd break;
828 1.1 cgd case CDIOCPAUSE:
829 1.18.2.2 mycroft error = cd_pause(unit, 0);
830 1.1 cgd break;
831 1.1 cgd case CDIOCSTART:
832 1.18.2.2 mycroft error = scsi_start_unit(cd->sc_link, 0);
833 1.1 cgd break;
834 1.1 cgd case CDIOCSTOP:
835 1.18.2.2 mycroft error = scsi_start_unit(cd->sc_link, 0);
836 1.1 cgd break;
837 1.1 cgd case CDIOCEJECT:
838 1.18.2.2 mycroft error = scsi_start_unit(cd->sc_link, 0);
839 1.1 cgd break;
840 1.1 cgd case CDIOCSETDEBUG:
841 1.18.2.2 mycroft cd->sc_link->flags |= (SDEV_DB1 | SDEV_DB2);
842 1.1 cgd break;
843 1.1 cgd case CDIOCCLRDEBUG:
844 1.18.2.2 mycroft cd->sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2);
845 1.1 cgd break;
846 1.1 cgd case CDIOCRESET:
847 1.18.2.2 mycroft return (cd_reset(unit));
848 1.1 cgd break;
849 1.1 cgd default:
850 1.18.2.2 mycroft if(part == RAW_PART)
851 1.18.2.2 mycroft error = scsi_do_ioctl(cd->sc_link,cmd,addr,flag);
852 1.18.2.2 mycroft else
853 1.18.2.2 mycroft error = ENOTTY;
854 1.1 cgd break;
855 1.1 cgd }
856 1.1 cgd return (error);
857 1.1 cgd }
858 1.1 cgd
859 1.18.2.2 mycroft /*
860 1.18.2.2 mycroft * Load the label information on the named device
861 1.18.2.2 mycroft * Actually fabricate a disklabel
862 1.18.2.2 mycroft *
863 1.18.2.2 mycroft * EVENTUALLY take information about different
864 1.18.2.2 mycroft * data tracks from the TOC and put it in the disklabel
865 1.18.2.2 mycroft */
866 1.18.2.2 mycroft errval
867 1.18.2.2 mycroft cdgetdisklabel(unit)
868 1.18.2.2 mycroft u_int8 unit;
869 1.18.2.2 mycroft {
870 1.18.2.2 mycroft /*unsigned int n, m; */
871 1.18.2.2 mycroft char *errstring;
872 1.18.2.2 mycroft struct cd_data *cd;
873 1.18.2.2 mycroft
874 1.18.2.2 mycroft cd = cd_driver.cd_data[unit];
875 1.1 cgd
876 1.18.2.2 mycroft bzero(&cd->disklabel, sizeof(struct disklabel));
877 1.18.2.2 mycroft /*
878 1.18.2.2 mycroft * make partition 0 the whole disk
879 1.18.2.2 mycroft */
880 1.18.2.2 mycroft strncpy(cd->disklabel.d_typename, "scsi cd_rom", 16);
881 1.18.2.2 mycroft strncpy(cd->disklabel.d_packname, "ficticious", 16);
882 1.18.2.2 mycroft cd->disklabel.d_secsize = cd->params.blksize; /* as long as it's not 0 */
883 1.1 cgd cd->disklabel.d_nsectors = 100;
884 1.1 cgd cd->disklabel.d_ntracks = 1;
885 1.1 cgd cd->disklabel.d_ncylinders = (cd->params.disksize / 100) + 1;
886 1.1 cgd cd->disklabel.d_secpercyl = 100;
887 1.1 cgd cd->disklabel.d_secperunit = cd->params.disksize;
888 1.1 cgd cd->disklabel.d_rpm = 300;
889 1.1 cgd cd->disklabel.d_interleave = 1;
890 1.1 cgd cd->disklabel.d_flags = D_REMOVABLE;
891 1.1 cgd
892 1.18.2.2 mycroft /*
893 1.18.2.2 mycroft * remember that comparisons with the partition are done
894 1.18.2.2 mycroft * assuming the blocks are 512 bytes so fudge it.
895 1.18.2.2 mycroft */
896 1.1 cgd cd->disklabel.d_npartitions = 1;
897 1.18.2.2 mycroft cd->disklabel.d_partitions[0].p_offset = 0;
898 1.18.2.2 mycroft cd->disklabel.d_partitions[0].p_size
899 1.18.2.2 mycroft = cd->params.disksize * (cd->params.blksize / 512);
900 1.18.2.2 mycroft cd->disklabel.d_partitions[0].p_fstype = 9;
901 1.1 cgd
902 1.1 cgd cd->disklabel.d_magic = DISKMAGIC;
903 1.1 cgd cd->disklabel.d_magic2 = DISKMAGIC;
904 1.1 cgd cd->disklabel.d_checksum = dkcksum(&(cd->disklabel));
905 1.1 cgd
906 1.18.2.2 mycroft /*
907 1.18.2.2 mycroft * Signal to other users and routines that we now have a
908 1.18.2.2 mycroft * disklabel that represents the media (maybe)
909 1.18.2.2 mycroft */
910 1.18.2.2 mycroft return (ESUCCESS);
911 1.1 cgd }
912 1.1 cgd
913 1.18.2.2 mycroft /*
914 1.18.2.2 mycroft * Find out from the device what it's capacity is
915 1.18.2.2 mycroft */
916 1.18.2.2 mycroft u_int32
917 1.1 cgd cd_size(unit, flags)
918 1.1 cgd {
919 1.18.2.2 mycroft struct scsi_read_cd_cap_data rdcap;
920 1.18.2.2 mycroft struct scsi_read_cd_capacity scsi_cmd;
921 1.18.2.2 mycroft u_int32 size;
922 1.18.2.2 mycroft u_int32 blksize;
923 1.18.2.2 mycroft struct cd_data *cd = cd_driver.cd_data[unit];
924 1.18.2.2 mycroft
925 1.18.2.2 mycroft /*
926 1.18.2.2 mycroft * make up a scsi command and ask the scsi driver to do
927 1.18.2.2 mycroft * it for you.
928 1.18.2.2 mycroft */
929 1.18.2.2 mycroft bzero(&scsi_cmd, sizeof(scsi_cmd));
930 1.1 cgd scsi_cmd.op_code = READ_CD_CAPACITY;
931 1.1 cgd
932 1.18.2.2 mycroft /*
933 1.18.2.2 mycroft * If the command works, interpret the result as a 4 byte
934 1.18.2.2 mycroft * number of blocks and a blocksize
935 1.18.2.2 mycroft */
936 1.18.2.2 mycroft if (scsi_scsi_cmd(cd->sc_link,
937 1.18.2.2 mycroft (struct scsi_generic *) &scsi_cmd,
938 1.18.2.2 mycroft sizeof(scsi_cmd),
939 1.18.2.2 mycroft (u_char *) & rdcap,
940 1.18.2.2 mycroft sizeof(rdcap),
941 1.18.2.2 mycroft CDRETRIES,
942 1.18.2.2 mycroft 20000, /* might be a disk-changer */
943 1.18.2.2 mycroft NULL,
944 1.18.2.2 mycroft SCSI_DATA_IN | flags) != 0) {
945 1.18.2.2 mycroft printf("cd%d: could not get size\n", unit);
946 1.18.2.2 mycroft return (0);
947 1.1 cgd } else {
948 1.18.2.2 mycroft size = rdcap.addr_0 + 1;
949 1.1 cgd size += rdcap.addr_1 << 8;
950 1.1 cgd size += rdcap.addr_2 << 16;
951 1.1 cgd size += rdcap.addr_3 << 24;
952 1.18.2.2 mycroft blksize = rdcap.length_0;
953 1.1 cgd blksize += rdcap.length_1 << 8;
954 1.1 cgd blksize += rdcap.length_2 << 16;
955 1.1 cgd blksize += rdcap.length_3 << 24;
956 1.1 cgd }
957 1.18.2.2 mycroft if (blksize < 512)
958 1.18.2.2 mycroft blksize = 2048; /* some drives lie ! */
959 1.18.2.2 mycroft if (size < 100)
960 1.18.2.2 mycroft size = 400000; /* ditto */
961 1.18.2.2 mycroft SC_DEBUG(cd->sc_link, SDEV_DB3, ("cd%d: %d %d byte blocks\n"
962 1.18.2.2 mycroft ,unit, size, blksize));
963 1.18.2.2 mycroft cd->params.disksize = size;
964 1.18.2.2 mycroft cd->params.blksize = blksize;
965 1.18.2.2 mycroft return (size);
966 1.18.2.2 mycroft }
967 1.18.2.2 mycroft
968 1.18.2.2 mycroft /*
969 1.18.2.2 mycroft * Get the requested page into the buffer given
970 1.18.2.2 mycroft */
971 1.18.2.2 mycroft errval
972 1.18.2.2 mycroft cd_get_mode(unit, data, page)
973 1.18.2.2 mycroft u_int32 unit;
974 1.18.2.2 mycroft struct cd_mode_data *data;
975 1.18.2.2 mycroft u_int32 page;
976 1.1 cgd {
977 1.1 cgd struct scsi_mode_sense scsi_cmd;
978 1.18.2.2 mycroft errval retval;
979 1.1 cgd
980 1.18.2.2 mycroft bzero(&scsi_cmd, sizeof(scsi_cmd));
981 1.18.2.2 mycroft bzero(data, sizeof(*data));
982 1.1 cgd scsi_cmd.op_code = MODE_SENSE;
983 1.18.2.2 mycroft scsi_cmd.page = page;
984 1.1 cgd scsi_cmd.length = sizeof(*data) & 0xff;
985 1.18.2.2 mycroft retval = scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
986 1.18.2.2 mycroft (struct scsi_generic *) &scsi_cmd,
987 1.18.2.2 mycroft sizeof(scsi_cmd),
988 1.18.2.2 mycroft (u_char *) data,
989 1.18.2.2 mycroft sizeof(*data),
990 1.18.2.2 mycroft CDRETRIES,
991 1.18.2.2 mycroft 20000, /* should be immed */
992 1.18.2.2 mycroft NULL,
993 1.18.2.2 mycroft SCSI_DATA_IN);
994 1.1 cgd return (retval);
995 1.1 cgd }
996 1.18.2.2 mycroft
997 1.18.2.2 mycroft /*
998 1.18.2.2 mycroft * Get the requested page into the buffer given
999 1.18.2.2 mycroft */
1000 1.18.2.2 mycroft errval
1001 1.18.2.2 mycroft cd_set_mode(unit, data)
1002 1.18.2.2 mycroft u_int32 unit;
1003 1.18.2.2 mycroft struct cd_mode_data *data;
1004 1.1 cgd {
1005 1.1 cgd struct scsi_mode_select scsi_cmd;
1006 1.1 cgd
1007 1.18.2.2 mycroft bzero(&scsi_cmd, sizeof(scsi_cmd));
1008 1.1 cgd scsi_cmd.op_code = MODE_SELECT;
1009 1.18.2.2 mycroft scsi_cmd.byte2 |= SMS_PF;
1010 1.1 cgd scsi_cmd.length = sizeof(*data) & 0xff;
1011 1.1 cgd data->header.data_length = 0;
1012 1.18.2.2 mycroft return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
1013 1.18.2.2 mycroft (struct scsi_generic *) &scsi_cmd,
1014 1.18.2.2 mycroft sizeof(scsi_cmd),
1015 1.18.2.2 mycroft (u_char *) data,
1016 1.18.2.2 mycroft sizeof(*data),
1017 1.18.2.2 mycroft CDRETRIES,
1018 1.18.2.2 mycroft 20000, /* should be immed */
1019 1.18.2.2 mycroft NULL,
1020 1.18.2.2 mycroft SCSI_DATA_OUT));
1021 1.18.2.2 mycroft }
1022 1.18.2.2 mycroft
1023 1.18.2.2 mycroft /*
1024 1.18.2.2 mycroft * Get scsi driver to send a "start playing" command
1025 1.18.2.2 mycroft */
1026 1.18.2.2 mycroft errval
1027 1.18.2.2 mycroft cd_play(unit, blk, len)
1028 1.18.2.2 mycroft u_int32 unit, blk, len;
1029 1.1 cgd {
1030 1.1 cgd struct scsi_play scsi_cmd;
1031 1.18.2.2 mycroft errval retval;
1032 1.1 cgd
1033 1.18.2.2 mycroft bzero(&scsi_cmd, sizeof(scsi_cmd));
1034 1.1 cgd scsi_cmd.op_code = PLAY;
1035 1.1 cgd scsi_cmd.blk_addr[0] = (blk >> 24) & 0xff;
1036 1.1 cgd scsi_cmd.blk_addr[1] = (blk >> 16) & 0xff;
1037 1.1 cgd scsi_cmd.blk_addr[2] = (blk >> 8) & 0xff;
1038 1.1 cgd scsi_cmd.blk_addr[3] = blk & 0xff;
1039 1.1 cgd scsi_cmd.xfer_len[0] = (len >> 8) & 0xff;
1040 1.1 cgd scsi_cmd.xfer_len[1] = len & 0xff;
1041 1.18.2.2 mycroft return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
1042 1.18.2.2 mycroft (struct scsi_generic *) &scsi_cmd,
1043 1.18.2.2 mycroft sizeof(scsi_cmd),
1044 1.18.2.2 mycroft 0,
1045 1.18.2.2 mycroft 0,
1046 1.18.2.2 mycroft CDRETRIES,
1047 1.18.2.2 mycroft 200000, /* should be immed */
1048 1.18.2.2 mycroft NULL,
1049 1.18.2.2 mycroft 0));
1050 1.18.2.2 mycroft }
1051 1.18.2.2 mycroft
1052 1.18.2.2 mycroft /*
1053 1.18.2.2 mycroft * Get scsi driver to send a "start playing" command
1054 1.18.2.2 mycroft */
1055 1.18.2.2 mycroft errval
1056 1.18.2.2 mycroft cd_play_big(unit, blk, len)
1057 1.18.2.2 mycroft u_int32 unit, blk, len;
1058 1.1 cgd {
1059 1.1 cgd struct scsi_play_big scsi_cmd;
1060 1.18.2.2 mycroft errval retval;
1061 1.1 cgd
1062 1.18.2.2 mycroft bzero(&scsi_cmd, sizeof(scsi_cmd));
1063 1.1 cgd scsi_cmd.op_code = PLAY_BIG;
1064 1.1 cgd scsi_cmd.blk_addr[0] = (blk >> 24) & 0xff;
1065 1.1 cgd scsi_cmd.blk_addr[1] = (blk >> 16) & 0xff;
1066 1.1 cgd scsi_cmd.blk_addr[2] = (blk >> 8) & 0xff;
1067 1.1 cgd scsi_cmd.blk_addr[3] = blk & 0xff;
1068 1.1 cgd scsi_cmd.xfer_len[0] = (len >> 24) & 0xff;
1069 1.1 cgd scsi_cmd.xfer_len[1] = (len >> 16) & 0xff;
1070 1.1 cgd scsi_cmd.xfer_len[2] = (len >> 8) & 0xff;
1071 1.1 cgd scsi_cmd.xfer_len[3] = len & 0xff;
1072 1.18.2.2 mycroft return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
1073 1.18.2.2 mycroft (struct scsi_generic *) &scsi_cmd,
1074 1.18.2.2 mycroft sizeof(scsi_cmd),
1075 1.18.2.2 mycroft 0,
1076 1.18.2.2 mycroft 0,
1077 1.18.2.2 mycroft CDRETRIES,
1078 1.18.2.2 mycroft 20000, /* should be immed */
1079 1.18.2.2 mycroft NULL,
1080 1.18.2.2 mycroft 0));
1081 1.18.2.2 mycroft }
1082 1.18.2.2 mycroft
1083 1.18.2.2 mycroft /*
1084 1.18.2.2 mycroft * Get scsi driver to send a "start playing" command
1085 1.18.2.2 mycroft */
1086 1.18.2.2 mycroft errval
1087 1.18.2.2 mycroft cd_play_tracks(unit, strack, sindex, etrack, eindex)
1088 1.18.2.2 mycroft u_int32 unit, strack, sindex, etrack, eindex;
1089 1.1 cgd {
1090 1.1 cgd struct scsi_play_track scsi_cmd;
1091 1.18.2.2 mycroft errval retval;
1092 1.1 cgd
1093 1.18.2.2 mycroft bzero(&scsi_cmd, sizeof(scsi_cmd));
1094 1.1 cgd scsi_cmd.op_code = PLAY_TRACK;
1095 1.1 cgd scsi_cmd.start_track = strack;
1096 1.1 cgd scsi_cmd.start_index = sindex;
1097 1.1 cgd scsi_cmd.end_track = etrack;
1098 1.1 cgd scsi_cmd.end_index = eindex;
1099 1.18.2.2 mycroft return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
1100 1.18.2.2 mycroft (struct scsi_generic *) &scsi_cmd,
1101 1.18.2.2 mycroft sizeof(scsi_cmd),
1102 1.18.2.2 mycroft 0,
1103 1.18.2.2 mycroft 0,
1104 1.18.2.2 mycroft CDRETRIES,
1105 1.18.2.2 mycroft 20000, /* should be immed */
1106 1.18.2.2 mycroft NULL,
1107 1.18.2.2 mycroft 0));
1108 1.18.2.2 mycroft }
1109 1.18.2.2 mycroft
1110 1.18.2.2 mycroft /*
1111 1.18.2.2 mycroft * Get scsi driver to send a "play msf" command
1112 1.18.2.2 mycroft */
1113 1.18.2.2 mycroft errval
1114 1.18.2.2 mycroft cd_play_msf(unit, startm, starts, startf, endm, ends, endf)
1115 1.18.2.2 mycroft u_int32 unit, startm, starts, startf, endm, ends, endf;
1116 1.17 brezak {
1117 1.17 brezak struct scsi_play_msf scsi_cmd;
1118 1.17 brezak
1119 1.18.2.2 mycroft bzero(&scsi_cmd, sizeof(scsi_cmd));
1120 1.17 brezak scsi_cmd.op_code = PLAY_MSF;
1121 1.18.2.2 mycroft scsi_cmd.start_m = startm;
1122 1.18.2.2 mycroft scsi_cmd.start_s = starts;
1123 1.18.2.2 mycroft scsi_cmd.start_f = startf;
1124 1.18.2.2 mycroft scsi_cmd.end_m = endm;
1125 1.18.2.2 mycroft scsi_cmd.end_s = ends;
1126 1.18.2.2 mycroft scsi_cmd.end_f = endf;
1127 1.18.2.2 mycroft
1128 1.18.2.2 mycroft return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
1129 1.18.2.2 mycroft (struct scsi_generic *) &scsi_cmd,
1130 1.18.2.2 mycroft sizeof(scsi_cmd),
1131 1.18.2.2 mycroft 0,
1132 1.18.2.2 mycroft 0,
1133 1.18.2.2 mycroft CDRETRIES,
1134 1.18.2.2 mycroft 2000,
1135 1.18.2.2 mycroft NULL,
1136 1.18.2.2 mycroft 0));
1137 1.18.2.2 mycroft }
1138 1.18.2.2 mycroft
1139 1.18.2.2 mycroft /*
1140 1.18.2.2 mycroft * Get scsi driver to send a "start up" command
1141 1.18.2.2 mycroft */
1142 1.18.2.2 mycroft errval
1143 1.18.2.2 mycroft cd_pause(unit, go)
1144 1.18.2.2 mycroft u_int32 unit, go;
1145 1.1 cgd {
1146 1.1 cgd struct scsi_pause scsi_cmd;
1147 1.1 cgd
1148 1.18.2.2 mycroft bzero(&scsi_cmd, sizeof(scsi_cmd));
1149 1.1 cgd scsi_cmd.op_code = PAUSE;
1150 1.1 cgd scsi_cmd.resume = go;
1151 1.1 cgd
1152 1.18.2.2 mycroft return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
1153 1.18.2.2 mycroft (struct scsi_generic *) &scsi_cmd,
1154 1.18.2.2 mycroft sizeof(scsi_cmd),
1155 1.18.2.2 mycroft 0,
1156 1.18.2.2 mycroft 0,
1157 1.18.2.2 mycroft CDRETRIES,
1158 1.18.2.2 mycroft 2000,
1159 1.18.2.2 mycroft NULL,
1160 1.18.2.2 mycroft 0));
1161 1.18.2.2 mycroft }
1162 1.18.2.2 mycroft
1163 1.18.2.2 mycroft /*
1164 1.18.2.2 mycroft * Get scsi driver to send a "RESET" command
1165 1.18.2.2 mycroft */
1166 1.18.2.2 mycroft errval
1167 1.1 cgd cd_reset(unit)
1168 1.18.2.2 mycroft u_int32 unit;
1169 1.1 cgd {
1170 1.18.2.2 mycroft return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
1171 1.18.2.2 mycroft 0,
1172 1.18.2.2 mycroft 0,
1173 1.18.2.2 mycroft 0,
1174 1.18.2.2 mycroft 0,
1175 1.18.2.2 mycroft CDRETRIES,
1176 1.18.2.2 mycroft 2000,
1177 1.18.2.2 mycroft NULL,
1178 1.18.2.2 mycroft SCSI_RESET));
1179 1.1 cgd }
1180 1.18.2.2 mycroft
1181 1.18.2.2 mycroft /*
1182 1.18.2.2 mycroft * Read subchannel
1183 1.18.2.2 mycroft */
1184 1.18.2.2 mycroft errval
1185 1.18.2.2 mycroft cd_read_subchannel(unit, mode, format, track, data, len)
1186 1.18.2.2 mycroft u_int32 unit, mode, format, len;
1187 1.18.2.2 mycroft struct cd_sub_channel_info *data;
1188 1.1 cgd {
1189 1.1 cgd struct scsi_read_subchannel scsi_cmd;
1190 1.18.2.2 mycroft errval error;
1191 1.1 cgd
1192 1.18.2.2 mycroft bzero(&scsi_cmd, sizeof(scsi_cmd));
1193 1.1 cgd
1194 1.18.2.2 mycroft scsi_cmd.op_code = READ_SUBCHANNEL;
1195 1.18.2.2 mycroft if (mode == CD_MSF_FORMAT)
1196 1.18.2.2 mycroft scsi_cmd.byte2 |= CD_MSF;
1197 1.18.2.2 mycroft scsi_cmd.byte3 = SRS_SUBQ;
1198 1.18.2.2 mycroft scsi_cmd.subchan_format = format;
1199 1.18.2.2 mycroft scsi_cmd.track = track;
1200 1.18.2.2 mycroft scsi_cmd.data_len[0] = (len) >> 8;
1201 1.18.2.2 mycroft scsi_cmd.data_len[1] = (len) & 0xff;
1202 1.18.2.2 mycroft return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
1203 1.18.2.2 mycroft (struct scsi_generic *) &scsi_cmd,
1204 1.18.2.2 mycroft sizeof(struct scsi_read_subchannel),
1205 1.18.2.2 mycroft (u_char *) data,
1206 1.1 cgd len,
1207 1.18.2.2 mycroft CDRETRIES,
1208 1.1 cgd 5000,
1209 1.18.2.2 mycroft NULL,
1210 1.18.2.2 mycroft SCSI_DATA_IN));
1211 1.1 cgd }
1212 1.1 cgd
1213 1.18.2.2 mycroft /*
1214 1.18.2.2 mycroft * Read table of contents
1215 1.18.2.2 mycroft */
1216 1.18.2.2 mycroft errval
1217 1.18.2.2 mycroft cd_read_toc(unit, mode, start, data, len)
1218 1.18.2.2 mycroft u_int32 unit, mode, start, len;
1219 1.18.2.2 mycroft struct cd_toc_entry *data;
1220 1.1 cgd {
1221 1.1 cgd struct scsi_read_toc scsi_cmd;
1222 1.18.2.2 mycroft errval error;
1223 1.18.2.2 mycroft u_int32 ntoc;
1224 1.18.2.2 mycroft
1225 1.18.2.2 mycroft bzero(&scsi_cmd, sizeof(scsi_cmd));
1226 1.1 cgd /*if(len!=sizeof(struct ioc_toc_header))
1227 1.18.2.2 mycroft * ntoc=((len)-sizeof(struct ioc_toc_header))/sizeof(struct cd_toc_entry);
1228 1.18.2.2 mycroft * else */
1229 1.18.2.2 mycroft ntoc = len;
1230 1.18.2.2 mycroft
1231 1.18.2.2 mycroft scsi_cmd.op_code = READ_TOC;
1232 1.18.2.2 mycroft if (mode == CD_MSF_FORMAT)
1233 1.18.2.2 mycroft scsi_cmd.byte2 |= CD_MSF;
1234 1.18.2.2 mycroft scsi_cmd.from_track = start;
1235 1.18.2.2 mycroft scsi_cmd.data_len[0] = (ntoc) >> 8;
1236 1.18.2.2 mycroft scsi_cmd.data_len[1] = (ntoc) & 0xff;
1237 1.18.2.2 mycroft return (scsi_scsi_cmd(cd_driver.cd_data[unit]->sc_link,
1238 1.18.2.2 mycroft (struct scsi_generic *) &scsi_cmd,
1239 1.18.2.2 mycroft sizeof(struct scsi_read_toc),
1240 1.18.2.2 mycroft (u_char *) data,
1241 1.18.2.2 mycroft len,
1242 1.18.2.2 mycroft CDRETRIES,
1243 1.18.2.2 mycroft 5000,
1244 1.18.2.2 mycroft NULL,
1245 1.18.2.2 mycroft SCSI_DATA_IN));
1246 1.1 cgd }
1247 1.1 cgd
1248 1.1 cgd #define b2tol(a) (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
1249 1.1 cgd
1250 1.18.2.2 mycroft /*
1251 1.18.2.2 mycroft * Get the scsi driver to send a full inquiry to the device and use the
1252 1.18.2.2 mycroft * results to fill out the disk parameter structure.
1253 1.18.2.2 mycroft */
1254 1.18.2.2 mycroft errval
1255 1.18.2.2 mycroft cd_get_parms(unit, flags)
1256 1.1 cgd {
1257 1.18.2.2 mycroft struct cd_data *cd = cd_driver.cd_data[unit];
1258 1.1 cgd
1259 1.18.2.2 mycroft /*
1260 1.18.2.2 mycroft * First check if we have it all loaded
1261 1.18.2.2 mycroft */
1262 1.18.2.2 mycroft if (cd->sc_link->flags & SDEV_MEDIA_LOADED)
1263 1.18.2.2 mycroft return (0);
1264 1.18.2.2 mycroft /*
1265 1.18.2.2 mycroft * give a number of sectors so that sec * trks * cyls
1266 1.18.2.2 mycroft * is <= disk_size
1267 1.18.2.2 mycroft */
1268 1.18.2.2 mycroft if (cd_size(unit, flags)) {
1269 1.18.2.2 mycroft cd->sc_link->flags |= SDEV_MEDIA_LOADED;
1270 1.18.2.2 mycroft return (0);
1271 1.18.2.2 mycroft } else {
1272 1.18.2.2 mycroft return (ENXIO);
1273 1.1 cgd }
1274 1.1 cgd }
1275 1.1 cgd
1276 1.1 cgd int
1277 1.1 cgd cdsize(dev_t dev)
1278 1.1 cgd {
1279 1.1 cgd return (-1);
1280 1.1 cgd }
1281