2 pcd.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
3 Under the terms of the GNU public license.
5 This is a high-level driver for parallel port ATAPI CD-ROM
6 drives based on chips supported by the paride module.
8 By default, the driver will autoprobe for a single parallel
9 port ATAPI CD-ROM drive, but if their individual parameters are
10 specified, the driver can handle up to 4 drives.
12 The behaviour of the pcd driver can be altered by setting
13 some parameters from the insmod command line. The following
14 parameters are adjustable:
16 drive0 These four arguments can be arrays of
17 drive1 1-6 integers as follows:
19 drive3 <prt>,<pro>,<uni>,<mod>,<slv>,<dly>
23 <prt> is the base of the parallel port address for
24 the corresponding drive. (required)
26 <pro> is the protocol number for the adapter that
27 supports this drive. These numbers are
28 logged by 'paride' when the protocol modules
29 are initialised. (0 if not given)
31 <uni> for those adapters that support chained
32 devices, this is the unit selector for the
33 chain of devices on the given port. It should
34 be zero for devices that don't support chaining.
37 <mod> this can be -1 to choose the best mode, or one
38 of the mode numbers supported by the adapter.
41 <slv> ATAPI CD-ROMs can be jumpered to master or slave.
42 Set this to 0 to choose the master drive, 1 to
43 choose the slave, -1 (the default) to choose the
46 <dly> some parallel ports require the driver to
47 go more slowly. -1 sets a default value that
48 should work with the chosen protocol. Otherwise,
49 set this to a small integer, the larger it is
50 the slower the port i/o. In some cases, setting
51 this to zero will speed up the device. (default -1)
53 major You may use this parameter to overide the
54 default major number (46) that this driver
55 will use. Be sure to change the device
58 name This parameter is a character string that
59 contains the name the kernel will use for this
60 device (in /proc output, for instance).
63 verbose This parameter controls the amount of logging
64 that the driver will do. Set it to 0 for
65 normal operation, 1 to see autoprobe progress
66 messages, or 2 to see additional debugging
69 nice This parameter controls the driver's use of
70 idle CPU time, at the expense of some speed.
72 If this driver is built into the kernel, you can use kernel
73 the following command line parameters, with the same values
74 as the corresponding module parameters listed above:
82 In addition, you can use the parameter pcd.disable to disable
89 1.01 GRG 1998.01.24 Added test unit ready support
90 1.02 GRG 1998.05.06 Changes to pcd_completion, ready_wait,
91 and loosen interpretation of ATAPI
92 standard for clearing error status.
93 Use spinlocks. Eliminate sti().
94 1.03 GRG 1998.06.16 Eliminated an Ugh
95 1.04 GRG 1998.08.15 Added extra debugging, improvements to
96 pcd_completion, use HZ in loop timing
97 1.05 GRG 1998.08.16 Conformed to "Uniform CD-ROM" standard
98 1.06 GRG 1998.08.19 Added audio ioctl support
102 #define PCD_VERSION "1.06"
104 #define PCD_NAME "pcd"
107 /* Here are things one can override from the insmod command.
108 Most are autoprobed by paride unless set here. Verbose is off
113 static int verbose
= 0;
114 static int major
= PCD_MAJOR
;
115 static char *name
= PCD_NAME
;
117 static int disable
= 0;
119 static int drive0
[6] = {0,0,0,-1,-1,-1};
120 static int drive1
[6] = {0,0,0,-1,-1,-1};
121 static int drive2
[6] = {0,0,0,-1,-1,-1};
122 static int drive3
[6] = {0,0,0,-1,-1,-1};
124 static int (*drives
[4])[6] = {&drive0
,&drive1
,&drive2
,&drive3
};
125 static int pcd_drive_count
;
134 #define DU (*drives[unit])
136 /* end of parameters */
138 #include <linux/module.h>
139 #include <linux/errno.h>
140 #include <linux/fs.h>
141 #include <linux/kernel.h>
142 #include <linux/delay.h>
143 #include <linux/cdrom.h>
145 #include <asm/uaccess.h>
146 #include <asm/spinlock.h>
152 static STT pcd_stt
[6] = {{"drive0",6,drive0
},
156 {"disable",1,&disable
},
159 void pcd_setup( char *str
, int *ints
)
161 { generic_setup(pcd_stt
,6,str
);
166 MODULE_PARM(verbose
,"i");
167 MODULE_PARM(major
,"i");
168 MODULE_PARM(name
,"s");
169 MODULE_PARM(nice
,"i");
170 MODULE_PARM(drive0
,"1-6i");
171 MODULE_PARM(drive1
,"1-6i");
172 MODULE_PARM(drive2
,"1-6i");
173 MODULE_PARM(drive3
,"1-6i");
177 /* set up defines for blk.h, why don't all drivers do it this way ? */
179 #define MAJOR_NR major
180 #define DEVICE_NAME "PCD"
181 #define DEVICE_REQUEST do_pcd_request
182 #define DEVICE_NR(device) (MINOR(device))
183 #define DEVICE_ON(device)
184 #define DEVICE_OFF(device)
186 #include <linux/blk.h>
190 #define PCD_RETRIES 5
191 #define PCD_TMO 800 /* timeout in jiffies */
192 #define PCD_DELAY 50 /* spin delay in uS */
193 #define PCD_READY_TMO 20 /* in seconds */
194 #define PCD_RESET_TMO 30 /* in tenths of a second */
196 #define PCD_SPIN (1000000*PCD_TMO)/(HZ*PCD_DELAY)
200 #define IDE_READY 0x40
201 #define IDE_BUSY 0x80
204 void cleanup_module( void );
206 static int pcd_open(struct cdrom_device_info
*cdi
, int purpose
);
207 static void pcd_release(struct cdrom_device_info
*cdi
);
208 static int pcd_drive_status(struct cdrom_device_info
*cdi
, int slot_nr
);
209 static int pcd_media_changed(struct cdrom_device_info
*cdi
, int slot_nr
);
210 static int pcd_tray_move(struct cdrom_device_info
*cdi
, int position
);
211 static int pcd_lock_door(struct cdrom_device_info
*cdi
, int lock
);
212 static int pcd_drive_reset(struct cdrom_device_info
*cdi
);
213 static int pcd_get_mcn (struct cdrom_device_info
*cdi
, struct cdrom_mcn
*mcn
);
214 static int pcd_audio_ioctl(struct cdrom_device_info
*cdi
,
215 unsigned int cmd
, void *arg
);
217 static int pcd_detect(void);
218 static void do_pcd_read_drq(void);
219 static void do_pcd_request(void);
220 static void do_pcd_read(void);
222 static int pcd_blocksizes
[PCD_UNITS
];
225 struct pi_adapter pia
; /* interface to paride layer */
226 struct pi_adapter
*pi
;
227 int drive
; /* master/slave */
228 int last_sense
; /* result of last request sense */
229 int changed
; /* media change seen */
230 int present
; /* does this unit exist ? */
231 char *name
; /* pcd0, pcd1, etc */
232 struct cdrom_device_info info
; /* uniform cdrom interface */
235 struct pcd_unit pcd
[PCD_UNITS
];
237 /* 'unit' must be defined in all functions - either as a local or a param */
239 #define PCD pcd[unit]
242 static char pcd_scratch
[64];
243 static char pcd_buffer
[2048]; /* raw block buffer */
244 static int pcd_bufblk
= -1; /* block in buffer, in CD units,
245 -1 for nothing there. See also
249 /* the variables below are used mainly in the I/O request engine, which
250 processes only one request at a time.
253 static int pcd_unit
= -1; /* unit of current request & bufblk */
254 static int pcd_retries
; /* retries on current request */
255 static int pcd_busy
= 0; /* request being processed ? */
256 static int pcd_sector
; /* address of next requested sector */
257 static int pcd_count
; /* number of blocks still to do */
258 static char * pcd_buf
; /* buffer for request in progress */
260 static int pcd_warned
= 0; /* Have we logged a phase warning ? */
262 /* kernel glue structures */
264 static struct cdrom_device_ops pcd_dops
= {
271 0, /* select speed */
273 0, /* get last session */
288 static void pcd_init_units( void )
293 for (unit
=0;unit
<PCD_UNITS
;unit
++) {
298 PCD
.drive
= DU
[D_SLV
];
299 if (DU
[D_PRT
]) pcd_drive_count
++;
302 while ((j
< (sizeof(PCD
.info
.name
)-2)) &&
303 (PCD
.info
.name
[j
]=name
[j
])) j
++;
304 PCD
.info
.name
[j
++] = '0' + unit
;
305 PCD
.info
.name
[j
] = 0;
306 PCD
.name
= &PCD
.info
.name
[0];
308 PCD
.info
.ops
= &pcd_dops
;
309 PCD
.info
.handle
= NULL
;
310 PCD
.info
.dev
= MKDEV(major
,unit
);
312 PCD
.info
.capacity
= 1;
317 int pcd_init (void) /* preliminary initialisation */
321 if (disable
) return -1;
325 if (pcd_detect()) return -1;
327 if (register_blkdev(MAJOR_NR
,name
,&cdrom_fops
)) {
328 printk("pcd: unable to get major number %d\n",MAJOR_NR
);
332 for (unit
=0;unit
<PCD_UNITS
;unit
++)
333 if (PCD
.present
) register_cdrom(&PCD
.info
);
335 blk_dev
[MAJOR_NR
].request_fn
= DEVICE_REQUEST
;
336 read_ahead
[MAJOR_NR
] = 8; /* 8 sector (4kB) read ahead */
338 for (i
=0;i
<PCD_UNITS
;i
++) pcd_blocksizes
[i
] = 1024;
339 blksize_size
[MAJOR_NR
] = pcd_blocksizes
;
344 static int pcd_open(struct cdrom_device_info
*cdi
, int purpose
)
346 { int unit
= DEVICE_NR(cdi
->dev
);
348 if ((unit
>= PCD_UNITS
) || (!PCD
.present
)) return -ENODEV
;
355 static void pcd_release(struct cdrom_device_info
*cdi
)
362 /* Glue for modules ... */
364 int init_module(void)
373 void cleanup_module(void)
377 for (unit
=0;unit
<PCD_UNITS
;unit
++)
380 unregister_cdrom(&PCD
.info
);
383 unregister_blkdev(MAJOR_NR
,name
);
388 #define WR(c,r,v) pi_write_regr(PI,c,r,v)
389 #define RR(c,r) (pi_read_regr(PI,c,r))
391 static int pcd_wait( int unit
, int go
, int stop
, char * fun
, char * msg
)
396 while ((((r
=RR(1,6))&go
)||(stop
&&(!(r
&stop
))))&&(j
++<PCD_SPIN
))
399 if ((r
&(IDE_ERR
&stop
))||(j
>=PCD_SPIN
)) {
403 if (j
>= PCD_SPIN
) e
|= 0x100;
404 if (fun
) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
405 " loop=%d phase=%d\n",
406 PCD
.name
,fun
,msg
,r
,s
,e
,j
,p
);
412 static int pcd_command( int unit
, char * cmd
, int dlen
, char * fun
)
416 WR(0,6,0xa0 + 0x10*PCD
.drive
);
418 if (pcd_wait(unit
,IDE_BUSY
|IDE_DRQ
,0,fun
,"before command")) {
425 WR(0,7,0xa0); /* ATAPI packet command */
427 if (pcd_wait(unit
,IDE_BUSY
,IDE_DRQ
,fun
,"command DRQ")) {
433 printk("%s: %s: command phase error\n",PCD
.name
,fun
);
438 pi_write_block(PI
,cmd
,12);
443 static int pcd_completion( int unit
, char * buf
, char * fun
)
445 { int r
, d
, p
, n
, k
, j
;
447 r
= -1; k
= 0; j
= 0;
449 if (!pcd_wait(unit
,IDE_BUSY
,IDE_DRQ
|IDE_READY
|IDE_ERR
,
452 while (RR(0,7)&IDE_DRQ
) {
453 d
= (RR(0,4)+256*RR(0,5));
457 if ((p
== 2) && (n
> 0) && (j
== 0)) {
458 pi_read_block(PI
,buf
,n
);
460 printk("%s: %s: Read %d bytes\n",PCD
.name
,fun
,n
);
464 printk("%s: %s: Unexpected phase %d, d=%d, k=%d\n",
466 if ((verbose
< 2) && !pcd_warned
) {
468 printk("%s: WARNING: ATAPI phase errors\n",PCD
.name
);
473 printk("%s: Stuck DRQ\n",PCD
.name
);
476 if (pcd_wait(unit
,IDE_BUSY
,IDE_DRQ
|IDE_READY
|IDE_ERR
,
489 static void pcd_req_sense( int unit
, char *fun
)
491 { char rs_cmd
[12] = { 0x03,0,0,0,16,0,0,0,0,0,0,0 };
495 r
= pcd_command(unit
,rs_cmd
,16,"Request sense");
497 if (!r
) pcd_completion(unit
,buf
,"Request sense");
499 PCD
.last_sense
= -1; c
= 2;
501 if (fun
) printk("%s: %s: Sense key: %x, ASC: %x, ASQ: %x\n",
502 PCD
.name
,fun
,buf
[2]&0xf,buf
[12],buf
[13]);
504 PCD
.last_sense
= c
| ((buf
[12]&0xff)<<8) | ((buf
[13]&0xff)<<16);
506 if ((c
== 2) || (c
== 6)) PCD
.changed
= 1;
509 static int pcd_atapi( int unit
, char * cmd
, int dlen
, char * buf
, char * fun
)
513 r
= pcd_command(unit
,cmd
,dlen
,fun
);
515 if (!r
) r
= pcd_completion(unit
,buf
,fun
);
516 if (r
) pcd_req_sense(unit
,fun
);
521 #define DBMSG(msg) ((verbose>1)?(msg):NULL)
523 static int pcd_media_changed(struct cdrom_device_info
*cdi
, int slot_nr
)
526 int unit
= DEVICE_NR(cdi
->dev
);
534 static int pcd_lock_door(struct cdrom_device_info
*cdi
, int lock
)
536 { char un_cmd
[12] = { 0x1e,0,0,0,lock
,0,0,0,0,0,0,0 };
537 int unit
= DEVICE_NR(cdi
->dev
);
539 return pcd_atapi(unit
,un_cmd
,0,pcd_scratch
,
540 lock
?"lock door":"unlock door");
543 static int pcd_tray_move(struct cdrom_device_info
*cdi
, int position
)
545 { char ej_cmd
[12] = { 0x1b,0,0,0,3-position
,0,0,0,0,0,0,0 };
546 int unit
= DEVICE_NR(cdi
->dev
);
548 return pcd_atapi(unit
,ej_cmd
,0,pcd_scratch
,
549 position
?"eject":"close tray");
552 static void pcd_sleep( int cs
)
554 { current
->state
= TASK_INTERRUPTIBLE
;
555 current
->timeout
= jiffies
+ cs
;
559 static int pcd_reset( int unit
)
562 int expect
[5] = {1,1,1,0x14,0xeb};
565 WR(0,6,0xa0 + 0x10*PCD
.drive
);
568 pcd_sleep(2); /* delay a bit */
571 while ((k
++ < PCD_RESET_TMO
) && (RR(1,6)&IDE_BUSY
))
575 for(i
=0;i
<5;i
++) flg
&= (RR(0,i
+1) == expect
[i
]);
578 printk("%s: Reset (%d) signature = ",PCD
.name
,k
);
579 for (i
=0;i
<5;i
++) printk("%3x",RR(0,i
+1));
580 if (!flg
) printk(" (incorrect)");
588 static int pcd_drive_reset(struct cdrom_device_info
*cdi
)
590 { return pcd_reset(DEVICE_NR(cdi
->dev
));
593 static int pcd_ready_wait( int unit
, int tmo
)
595 { char tr_cmd
[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
601 pcd_atapi(unit
,tr_cmd
,0,NULL
,DBMSG("test unit ready"));
604 if (!(((p
& 0xffff) == 0x0402)||((p
& 0xff) == 6))) return p
;
608 return 0x000020; /* timeout */
611 static int pcd_drive_status(struct cdrom_device_info
*cdi
, int slot_nr
)
613 { char rc_cmd
[12] = { 0x25,0,0,0,0,0,0,0,0,0,0,0};
614 int unit
= DEVICE_NR(cdi
->dev
);
616 if (pcd_ready_wait(unit
,PCD_READY_TMO
))
617 return CDS_DRIVE_NOT_READY
;
618 if (pcd_atapi(unit
,rc_cmd
,8,pcd_scratch
,DBMSG("check media")))
623 static int pcd_identify( int unit
, char * id
)
626 char id_cmd
[12] = {0x12,0,0,0,36,0,0,0,0,0,0,0};
630 s
= pcd_atapi(unit
,id_cmd
,36,pcd_buffer
,"identify");
633 if ((pcd_buffer
[0] & 0x1f) != 5) {
634 if (verbose
) printk("%s: %s is not a CD-ROM\n",
635 PCD
.name
,PCD
.drive
?"Slave":"Master");
638 for (k
=0;k
<16;k
++) id
[k
] = pcd_buffer
[16+k
]; id
[16] = 0;
639 k
= 16; while ((k
>= 0) && (id
[k
] <= 0x20)) { id
[k
] = 0; k
--; }
641 printk("%s: %s: %s\n",PCD
.name
,PCD
.drive
?"Slave":"Master",id
);
646 static int pcd_probe( int unit
, int ms
, char * id
)
648 /* returns 0, with id set if drive is detected
649 -1, if drive detection failed
653 for (PCD
.drive
=0;PCD
.drive
<=1;PCD
.drive
++)
654 if (!pcd_reset(unit
) && !pcd_identify(unit
,id
))
658 if (!pcd_reset(unit
) && !pcd_identify(unit
,id
))
664 static int pcd_detect( void )
669 printk("%s: %s version %s, major %d, nice %d\n",
670 name
,name
,PCD_VERSION
,major
,nice
);
673 if (pcd_drive_count
== 0) { /* nothing spec'd - so autoprobe for 1 */
675 if (pi_init(PI
,1,-1,-1,-1,-1,-1,pcd_buffer
,
676 PI_PCD
,verbose
,PCD
.name
)) {
677 if (!pcd_probe(unit
,-1,id
)) {
680 } else pi_release(PI
);
683 } else for (unit
=0;unit
<PCD_UNITS
;unit
++) if (DU
[D_PRT
])
684 if (pi_init(PI
,0,DU
[D_PRT
],DU
[D_MOD
],DU
[D_UNI
],
685 DU
[D_PRO
],DU
[D_DLY
],pcd_buffer
,PI_PCD
,verbose
,
687 if (!pcd_probe(unit
,DU
[D_SLV
],id
)) {
690 } else pi_release(PI
);
695 printk("%s: No CD-ROM drive found\n",name
);
699 /* I/O request processing */
701 static void do_pcd_request (void)
705 if (pcd_busy
) return;
707 if ((!CURRENT
) || (CURRENT
->rq_status
== RQ_INACTIVE
)) return;
709 if (CURRENT
->cmd
== READ
) {
710 unit
= MINOR(CURRENT
->rq_dev
);
711 if (unit
!= pcd_unit
) {
715 pcd_sector
= CURRENT
->sector
;
716 pcd_count
= CURRENT
->nr_sectors
;
717 pcd_buf
= CURRENT
->buffer
;
719 ps_set_intr(do_pcd_read
,0,0,nice
);
726 static int pcd_ready( void )
728 { int unit
= pcd_unit
;
730 return (((RR(1,6)&(IDE_BUSY
|IDE_DRQ
))==IDE_DRQ
)) ;
733 static void pcd_transfer( void )
737 while (pcd_count
&& (pcd_sector
/4 == pcd_bufblk
)) {
738 o
= (pcd_sector
% 4) * 512;
739 for(k
=0;k
<512;k
++) pcd_buf
[k
] = pcd_buffer
[o
+k
];
746 static void pcd_start( void )
748 { int unit
= pcd_unit
;
750 char rd_cmd
[12] = {0xa8,0,0,0,0,0,0,0,0,1,0,0};
753 pcd_bufblk
= pcd_sector
/ 4;
756 rd_cmd
[5-i
] = b
& 0xff;
760 if (pcd_command(unit
,rd_cmd
,2048,"read block")) {
762 spin_lock_irqsave(&io_request_lock
,saved_flags
);
766 spin_unlock_irqrestore(&io_request_lock
,saved_flags
);
772 ps_set_intr(do_pcd_read_drq
,pcd_ready
,PCD_TMO
,nice
);
776 static void do_pcd_read( void )
779 { int unit
= pcd_unit
;
786 spin_lock_irqsave(&io_request_lock
,saved_flags
);
790 spin_unlock_irqrestore(&io_request_lock
,saved_flags
);
794 pi_do_claimed(PI
,pcd_start
);
797 static void do_pcd_read_drq( void )
799 { int unit
= pcd_unit
;
802 if (pcd_completion(unit
,pcd_buffer
,"read block")) {
803 if (pcd_retries
< PCD_RETRIES
) {
806 pi_do_claimed(PI
,pcd_start
);
809 spin_lock_irqsave(&io_request_lock
,saved_flags
);
814 spin_unlock_irqrestore(&io_request_lock
,saved_flags
);
819 spin_lock_irqsave(&io_request_lock
,saved_flags
);
821 spin_unlock_irqrestore(&io_request_lock
,saved_flags
);
824 /* the audio_ioctl stuff is adapted from sr_ioctl.c */
826 static int pcd_audio_ioctl(struct cdrom_device_info
*cdi
,
827 unsigned int cmd
, void *arg
)
829 { int unit
= DEVICE_NR(cdi
->dev
);
835 { char cmd
[12]={SCMD_PAUSE_RESUME
,0,0,0,0,0,0,0,0,0,0,0};
837 return (pcd_atapi(unit
,cmd
,0,NULL
,"pause")) * EIO
;
842 { char cmd
[12]={SCMD_PAUSE_RESUME
,0,0,0,0,0,0,0,1,0,0,0};
844 return (pcd_atapi(unit
,cmd
,0,NULL
,"resume")) * EIO
;
849 { char cmd
[12]={SCMD_PLAYAUDIO_MSF
,0,0,0,0,0,0,0,0,0,0,0};
850 struct cdrom_msf
* msf
= (struct cdrom_msf
*)arg
;
852 cmd
[3] = msf
->cdmsf_min0
;
853 cmd
[4] = msf
->cdmsf_sec0
;
854 cmd
[5] = msf
->cdmsf_frame0
;
855 cmd
[6] = msf
->cdmsf_min1
;
856 cmd
[7] = msf
->cdmsf_sec1
;
857 cmd
[8] = msf
->cdmsf_frame1
;
859 return (pcd_atapi(unit
,cmd
,0,NULL
,"play msf")) * EIO
;
864 { char cmd
[12]={SCMD_PLAYAUDIO10
,0,0,0,0,0,0,0,0,0,0,0};
865 struct cdrom_blk
* blk
= (struct cdrom_blk
*)arg
;
867 cmd
[2] = blk
->from
>> 24;
868 cmd
[3] = blk
->from
>> 16;
869 cmd
[4] = blk
->from
>> 8;
871 cmd
[7] = blk
->len
>> 8;
874 return (pcd_atapi(unit
,cmd
,0,NULL
,"play block")) * EIO
;
877 case CDROMPLAYTRKIND
:
879 { char cmd
[12]={SCMD_PLAYAUDIO_TI
,0,0,0,0,0,0,0,0,0,0,0};
880 struct cdrom_ti
* ti
= (struct cdrom_ti
*)arg
;
882 cmd
[4] = ti
->cdti_trk0
;
883 cmd
[5] = ti
->cdti_ind0
;
884 cmd
[7] = ti
->cdti_trk1
;
885 cmd
[8] = ti
->cdti_ind1
;
887 return (pcd_atapi(unit
,cmd
,0,NULL
,"play track")) * EIO
;
890 case CDROMREADTOCHDR
:
892 { char cmd
[12]={SCMD_READ_TOC
,0,0,0,0,0,0,0,12,0,0,0};
893 struct cdrom_tochdr
* tochdr
= (struct cdrom_tochdr
*)arg
;
897 r
= pcd_atapi(unit
,cmd
,12,buffer
,"read toc header");
899 tochdr
->cdth_trk0
= buffer
[2];
900 tochdr
->cdth_trk1
= buffer
[3];
905 case CDROMREADTOCENTRY
:
907 { char cmd
[12]={SCMD_READ_TOC
,0,0,0,0,0,0,0,12,0,0,0};
909 struct cdrom_tocentry
* tocentry
= (struct cdrom_tocentry
*)arg
;
910 unsigned char buffer
[32];
913 cmd
[1] = (tocentry
->cdte_format
== CDROM_MSF
? 0x02 : 0);
914 cmd
[6] = tocentry
->cdte_track
;
916 r
= pcd_atapi(unit
,cmd
,12,buffer
,"read toc entry");
918 tocentry
->cdte_ctrl
= buffer
[5] & 0xf;
919 tocentry
->cdte_adr
= buffer
[5] >> 4;
920 tocentry
->cdte_datamode
= (tocentry
->cdte_ctrl
& 0x04)?1:0;
921 if (tocentry
->cdte_format
== CDROM_MSF
) {
922 tocentry
->cdte_addr
.msf
.minute
= buffer
[9];
923 tocentry
->cdte_addr
.msf
.second
= buffer
[10];
924 tocentry
->cdte_addr
.msf
.frame
= buffer
[11];
926 tocentry
->cdte_addr
.lba
=
927 (((((buffer
[8] << 8) + buffer
[9]) << 8)
928 + buffer
[10]) << 8) + buffer
[11];
935 { char cmd
[12]={0x1b,1,0,0,0,0,0,0,0,0,0,0};
937 return (pcd_atapi(unit
,cmd
,0,NULL
,"stop")) * EIO
;
942 { char cmd
[12]={0x1b,1,0,0,1,0,0,0,0,0,0,0};
944 return (pcd_atapi(unit
,cmd
,0,NULL
,"start")) * EIO
;
949 { char cmd
[12]={0x5a,0,0,0,0,0,0,0,0,0,0,0};
952 struct cdrom_volctrl
* volctrl
= (struct cdrom_volctrl
*)arg
;
957 if (pcd_atapi(unit
,cmd
,28,buffer
,"mode sense vol"))
962 if (pcd_atapi(unit
,cmd
,28,buffer
,"mode sense vol mask"))
967 buffer
[21] = volctrl
->channel0
& mask
[21];
968 buffer
[23] = volctrl
->channel1
& mask
[23];
969 buffer
[25] = volctrl
->channel2
& mask
[25];
970 buffer
[27] = volctrl
->channel3
& mask
[27];
975 return pcd_atapi(unit
,cmd
,28,buffer
,"mode select vol") * EIO
;
980 { char cmd
[12]={0x5a,0,0,0,0,0,0,0,0,0,0,0};
982 struct cdrom_volctrl
* volctrl
= (struct cdrom_volctrl
*)arg
;
988 r
= pcd_atapi(unit
,cmd
,28,buffer
,"mode sense vol read");
990 volctrl
->channel0
= buffer
[21];
991 volctrl
->channel1
= buffer
[23];
992 volctrl
->channel2
= buffer
[25];
993 volctrl
->channel3
= buffer
[27];
1001 { char cmd
[12]={SCMD_READ_SUBCHANNEL
,2,0x40,1,0,0,0,0,16,0,0,0};
1002 struct cdrom_subchnl
* subchnl
= (struct cdrom_subchnl
*)arg
;
1005 if (pcd_atapi(unit
,cmd
,16,buffer
,"read subchannel"))
1008 subchnl
->cdsc_audiostatus
= buffer
[1];
1009 subchnl
->cdsc_format
= CDROM_MSF
;
1010 subchnl
->cdsc_ctrl
= buffer
[5] & 0xf;
1011 subchnl
->cdsc_trk
= buffer
[6];
1012 subchnl
->cdsc_ind
= buffer
[7];
1014 subchnl
->cdsc_reladdr
.msf
.minute
= buffer
[13];
1015 subchnl
->cdsc_reladdr
.msf
.second
= buffer
[14];
1016 subchnl
->cdsc_reladdr
.msf
.frame
= buffer
[15];
1017 subchnl
->cdsc_absaddr
.msf
.minute
= buffer
[9];
1018 subchnl
->cdsc_absaddr
.msf
.second
= buffer
[10];
1019 subchnl
->cdsc_absaddr
.msf
.frame
= buffer
[11];
1030 static int pcd_get_mcn (struct cdrom_device_info
*cdi
, struct cdrom_mcn
*mcn
)
1032 { char cmd
[12]={SCMD_READ_SUBCHANNEL
,0,0x40,2,0,0,0,0,24,0,0,0};
1035 int unit
= DEVICE_NR(cdi
->dev
);
1037 if (pcd_atapi(unit
,cmd
,24,buffer
,"get mcn")) return -EIO
;
1039 for (k
=0;k
<13;k
++) mcn
->medium_catalog_number
[k
] = buffer
[k
+9];
1040 mcn
->medium_catalog_number
[13] = 0;