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
99 1.07 GRG 1998.09.24 Increased reset timeout, added jumbo support
103 #define PCD_VERSION "1.07"
105 #define PCD_NAME "pcd"
108 /* Here are things one can override from the insmod command.
109 Most are autoprobed by paride unless set here. Verbose is off
114 static int verbose
= 0;
115 static int major
= PCD_MAJOR
;
116 static char *name
= PCD_NAME
;
118 static int disable
= 0;
120 static int drive0
[6] = {0,0,0,-1,-1,-1};
121 static int drive1
[6] = {0,0,0,-1,-1,-1};
122 static int drive2
[6] = {0,0,0,-1,-1,-1};
123 static int drive3
[6] = {0,0,0,-1,-1,-1};
125 static int (*drives
[4])[6] = {&drive0
,&drive1
,&drive2
,&drive3
};
126 static int pcd_drive_count
;
135 #define DU (*drives[unit])
137 /* end of parameters */
139 #include <linux/module.h>
140 #include <linux/errno.h>
141 #include <linux/fs.h>
142 #include <linux/kernel.h>
143 #include <linux/delay.h>
144 #include <linux/cdrom.h>
145 #include <linux/spinlock.h>
147 #include <asm/uaccess.h>
153 static STT pcd_stt
[6] = {{"drive0",6,drive0
},
157 {"disable",1,&disable
},
160 void pcd_setup( char *str
, int *ints
)
162 { generic_setup(pcd_stt
,6,str
);
167 MODULE_PARM(verbose
,"i");
168 MODULE_PARM(major
,"i");
169 MODULE_PARM(name
,"s");
170 MODULE_PARM(nice
,"i");
171 MODULE_PARM(drive0
,"1-6i");
172 MODULE_PARM(drive1
,"1-6i");
173 MODULE_PARM(drive2
,"1-6i");
174 MODULE_PARM(drive3
,"1-6i");
178 /* set up defines for blk.h, why don't all drivers do it this way ? */
180 #define MAJOR_NR major
181 #define DEVICE_NAME "PCD"
182 #define DEVICE_REQUEST do_pcd_request
183 #define DEVICE_NR(device) (MINOR(device))
184 #define DEVICE_ON(device)
185 #define DEVICE_OFF(device)
187 #include <linux/blk.h>
191 #define PCD_RETRIES 5
192 #define PCD_TMO 800 /* timeout in jiffies */
193 #define PCD_DELAY 50 /* spin delay in uS */
194 #define PCD_READY_TMO 20 /* in seconds */
195 #define PCD_RESET_TMO 100 /* in tenths of a second */
197 #define PCD_SPIN (1000000*PCD_TMO)/(HZ*PCD_DELAY)
201 #define IDE_READY 0x40
202 #define IDE_BUSY 0x80
205 void cleanup_module( void );
207 static int pcd_open(struct cdrom_device_info
*cdi
, int purpose
);
208 static void pcd_release(struct cdrom_device_info
*cdi
);
209 static int pcd_drive_status(struct cdrom_device_info
*cdi
, int slot_nr
);
210 static int pcd_media_changed(struct cdrom_device_info
*cdi
, int slot_nr
);
211 static int pcd_tray_move(struct cdrom_device_info
*cdi
, int position
);
212 static int pcd_lock_door(struct cdrom_device_info
*cdi
, int lock
);
213 static int pcd_drive_reset(struct cdrom_device_info
*cdi
);
214 static int pcd_get_mcn (struct cdrom_device_info
*cdi
, struct cdrom_mcn
*mcn
);
215 static int pcd_audio_ioctl(struct cdrom_device_info
*cdi
,
216 unsigned int cmd
, void *arg
);
218 static int pcd_detect(void);
219 static void do_pcd_read_drq(void);
220 static void do_pcd_request(void);
221 static void do_pcd_read(void);
223 static int pcd_blocksizes
[PCD_UNITS
];
226 struct pi_adapter pia
; /* interface to paride layer */
227 struct pi_adapter
*pi
;
228 int drive
; /* master/slave */
229 int last_sense
; /* result of last request sense */
230 int changed
; /* media change seen */
231 int present
; /* does this unit exist ? */
232 char *name
; /* pcd0, pcd1, etc */
233 struct cdrom_device_info info
; /* uniform cdrom interface */
236 struct pcd_unit pcd
[PCD_UNITS
];
238 /* 'unit' must be defined in all functions - either as a local or a param */
240 #define PCD pcd[unit]
243 static char pcd_scratch
[64];
244 static char pcd_buffer
[2048]; /* raw block buffer */
245 static int pcd_bufblk
= -1; /* block in buffer, in CD units,
246 -1 for nothing there. See also
250 /* the variables below are used mainly in the I/O request engine, which
251 processes only one request at a time.
254 static int pcd_unit
= -1; /* unit of current request & bufblk */
255 static int pcd_retries
; /* retries on current request */
256 static int pcd_busy
= 0; /* request being processed ? */
257 static int pcd_sector
; /* address of next requested sector */
258 static int pcd_count
; /* number of blocks still to do */
259 static char * pcd_buf
; /* buffer for request in progress */
261 static int pcd_warned
= 0; /* Have we logged a phase warning ? */
263 /* kernel glue structures */
265 static struct cdrom_device_ops pcd_dops
= {
272 0, /* select speed */
274 0, /* get last session */
289 static void pcd_init_units( void )
294 for (unit
=0;unit
<PCD_UNITS
;unit
++) {
299 PCD
.drive
= DU
[D_SLV
];
300 if (DU
[D_PRT
]) pcd_drive_count
++;
303 while ((j
< (sizeof(PCD
.info
.name
)-2)) &&
304 (PCD
.info
.name
[j
]=name
[j
])) j
++;
305 PCD
.info
.name
[j
++] = '0' + unit
;
306 PCD
.info
.name
[j
] = 0;
307 PCD
.name
= &PCD
.info
.name
[0];
309 PCD
.info
.ops
= &pcd_dops
;
310 PCD
.info
.handle
= NULL
;
311 PCD
.info
.dev
= MKDEV(major
,unit
);
313 PCD
.info
.capacity
= 1;
318 int pcd_init (void) /* preliminary initialisation */
322 if (disable
) return -1;
326 if (pcd_detect()) return -1;
328 if (register_blkdev(MAJOR_NR
,name
,&cdrom_fops
)) {
329 printk("pcd: unable to get major number %d\n",MAJOR_NR
);
333 for (unit
=0;unit
<PCD_UNITS
;unit
++)
334 if (PCD
.present
) register_cdrom(&PCD
.info
);
336 blk_dev
[MAJOR_NR
].request_fn
= DEVICE_REQUEST
;
337 read_ahead
[MAJOR_NR
] = 8; /* 8 sector (4kB) read ahead */
339 for (i
=0;i
<PCD_UNITS
;i
++) pcd_blocksizes
[i
] = 1024;
340 blksize_size
[MAJOR_NR
] = pcd_blocksizes
;
345 static int pcd_open(struct cdrom_device_info
*cdi
, int purpose
)
347 { int unit
= DEVICE_NR(cdi
->dev
);
349 if ((unit
>= PCD_UNITS
) || (!PCD
.present
)) return -ENODEV
;
356 static void pcd_release(struct cdrom_device_info
*cdi
)
363 /* Glue for modules ... */
365 int init_module(void)
370 { extern paride_init();
380 void cleanup_module(void)
384 for (unit
=0;unit
<PCD_UNITS
;unit
++)
387 unregister_cdrom(&PCD
.info
);
390 unregister_blkdev(MAJOR_NR
,name
);
395 #define WR(c,r,v) pi_write_regr(PI,c,r,v)
396 #define RR(c,r) (pi_read_regr(PI,c,r))
398 static int pcd_wait( int unit
, int go
, int stop
, char * fun
, char * msg
)
403 while ((((r
=RR(1,6))&go
)||(stop
&&(!(r
&stop
))))&&(j
++<PCD_SPIN
))
406 if ((r
&(IDE_ERR
&stop
))||(j
>=PCD_SPIN
)) {
410 if (j
>= PCD_SPIN
) e
|= 0x100;
411 if (fun
) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
412 " loop=%d phase=%d\n",
413 PCD
.name
,fun
,msg
,r
,s
,e
,j
,p
);
419 static int pcd_command( int unit
, char * cmd
, int dlen
, char * fun
)
423 WR(0,6,0xa0 + 0x10*PCD
.drive
);
425 if (pcd_wait(unit
,IDE_BUSY
|IDE_DRQ
,0,fun
,"before command")) {
432 WR(0,7,0xa0); /* ATAPI packet command */
434 if (pcd_wait(unit
,IDE_BUSY
,IDE_DRQ
,fun
,"command DRQ")) {
440 printk("%s: %s: command phase error\n",PCD
.name
,fun
);
445 pi_write_block(PI
,cmd
,12);
450 static int pcd_completion( int unit
, char * buf
, char * fun
)
452 { int r
, d
, p
, n
, k
, j
;
454 r
= -1; k
= 0; j
= 0;
456 if (!pcd_wait(unit
,IDE_BUSY
,IDE_DRQ
|IDE_READY
|IDE_ERR
,
459 while (RR(0,7)&IDE_DRQ
) {
460 d
= (RR(0,4)+256*RR(0,5));
464 if ((p
== 2) && (n
> 0) && (j
== 0)) {
465 pi_read_block(PI
,buf
,n
);
467 printk("%s: %s: Read %d bytes\n",PCD
.name
,fun
,n
);
471 printk("%s: %s: Unexpected phase %d, d=%d, k=%d\n",
473 if ((verbose
< 2) && !pcd_warned
) {
475 printk("%s: WARNING: ATAPI phase errors\n",PCD
.name
);
480 printk("%s: Stuck DRQ\n",PCD
.name
);
483 if (pcd_wait(unit
,IDE_BUSY
,IDE_DRQ
|IDE_READY
|IDE_ERR
,
496 static void pcd_req_sense( int unit
, char *fun
)
498 { char rs_cmd
[12] = { 0x03,0,0,0,16,0,0,0,0,0,0,0 };
502 r
= pcd_command(unit
,rs_cmd
,16,"Request sense");
504 if (!r
) pcd_completion(unit
,buf
,"Request sense");
506 PCD
.last_sense
= -1; c
= 2;
508 if (fun
) printk("%s: %s: Sense key: %x, ASC: %x, ASQ: %x\n",
509 PCD
.name
,fun
,buf
[2]&0xf,buf
[12],buf
[13]);
511 PCD
.last_sense
= c
| ((buf
[12]&0xff)<<8) | ((buf
[13]&0xff)<<16);
513 if ((c
== 2) || (c
== 6)) PCD
.changed
= 1;
516 static int pcd_atapi( int unit
, char * cmd
, int dlen
, char * buf
, char * fun
)
520 r
= pcd_command(unit
,cmd
,dlen
,fun
);
522 if (!r
) r
= pcd_completion(unit
,buf
,fun
);
523 if (r
) pcd_req_sense(unit
,fun
);
528 #define DBMSG(msg) ((verbose>1)?(msg):NULL)
530 static int pcd_media_changed(struct cdrom_device_info
*cdi
, int slot_nr
)
533 int unit
= DEVICE_NR(cdi
->dev
);
541 static int pcd_lock_door(struct cdrom_device_info
*cdi
, int lock
)
543 { char un_cmd
[12] = { 0x1e,0,0,0,lock
,0,0,0,0,0,0,0 };
544 int unit
= DEVICE_NR(cdi
->dev
);
546 return pcd_atapi(unit
,un_cmd
,0,pcd_scratch
,
547 lock
?"lock door":"unlock door");
550 static int pcd_tray_move(struct cdrom_device_info
*cdi
, int position
)
552 { char ej_cmd
[12] = { 0x1b,0,0,0,3-position
,0,0,0,0,0,0,0 };
553 int unit
= DEVICE_NR(cdi
->dev
);
555 return pcd_atapi(unit
,ej_cmd
,0,pcd_scratch
,
556 position
?"eject":"close tray");
559 static void pcd_sleep( int cs
)
561 { current
->state
= TASK_INTERRUPTIBLE
;
562 schedule_timeout(cs
);
565 static int pcd_reset( int unit
)
568 int expect
[5] = {1,1,1,0x14,0xeb};
571 WR(0,6,0xa0 + 0x10*PCD
.drive
);
574 pcd_sleep(2); /* delay a bit */
577 while ((k
++ < PCD_RESET_TMO
) && (RR(1,6)&IDE_BUSY
))
581 for(i
=0;i
<5;i
++) flg
&= (RR(0,i
+1) == expect
[i
]);
584 printk("%s: Reset (%d) signature = ",PCD
.name
,k
);
585 for (i
=0;i
<5;i
++) printk("%3x",RR(0,i
+1));
586 if (!flg
) printk(" (incorrect)");
594 static int pcd_drive_reset(struct cdrom_device_info
*cdi
)
596 { return pcd_reset(DEVICE_NR(cdi
->dev
));
599 static int pcd_ready_wait( int unit
, int tmo
)
601 { char tr_cmd
[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
607 pcd_atapi(unit
,tr_cmd
,0,NULL
,DBMSG("test unit ready"));
610 if (!(((p
& 0xffff) == 0x0402)||((p
& 0xff) == 6))) return p
;
614 return 0x000020; /* timeout */
617 static int pcd_drive_status(struct cdrom_device_info
*cdi
, int slot_nr
)
619 { char rc_cmd
[12] = { 0x25,0,0,0,0,0,0,0,0,0,0,0};
620 int unit
= DEVICE_NR(cdi
->dev
);
622 if (pcd_ready_wait(unit
,PCD_READY_TMO
))
623 return CDS_DRIVE_NOT_READY
;
624 if (pcd_atapi(unit
,rc_cmd
,8,pcd_scratch
,DBMSG("check media")))
629 static int pcd_identify( int unit
, char * id
)
632 char id_cmd
[12] = {0x12,0,0,0,36,0,0,0,0,0,0,0};
636 s
= pcd_atapi(unit
,id_cmd
,36,pcd_buffer
,"identify");
639 if ((pcd_buffer
[0] & 0x1f) != 5) {
640 if (verbose
) printk("%s: %s is not a CD-ROM\n",
641 PCD
.name
,PCD
.drive
?"Slave":"Master");
644 for (k
=0;k
<16;k
++) id
[k
] = pcd_buffer
[16+k
]; id
[16] = 0;
645 k
= 16; while ((k
>= 0) && (id
[k
] <= 0x20)) { id
[k
] = 0; k
--; }
647 printk("%s: %s: %s\n",PCD
.name
,PCD
.drive
?"Slave":"Master",id
);
652 static int pcd_probe( int unit
, int ms
, char * id
)
654 /* returns 0, with id set if drive is detected
655 -1, if drive detection failed
659 for (PCD
.drive
=0;PCD
.drive
<=1;PCD
.drive
++)
660 if (!pcd_reset(unit
) && !pcd_identify(unit
,id
))
664 if (!pcd_reset(unit
) && !pcd_identify(unit
,id
))
670 static int pcd_detect( void )
675 printk("%s: %s version %s, major %d, nice %d\n",
676 name
,name
,PCD_VERSION
,major
,nice
);
679 if (pcd_drive_count
== 0) { /* nothing spec'd - so autoprobe for 1 */
681 if (pi_init(PI
,1,-1,-1,-1,-1,-1,pcd_buffer
,
682 PI_PCD
,verbose
,PCD
.name
)) {
683 if (!pcd_probe(unit
,-1,id
)) {
686 } else pi_release(PI
);
689 } else for (unit
=0;unit
<PCD_UNITS
;unit
++) if (DU
[D_PRT
])
690 if (pi_init(PI
,0,DU
[D_PRT
],DU
[D_MOD
],DU
[D_UNI
],
691 DU
[D_PRO
],DU
[D_DLY
],pcd_buffer
,PI_PCD
,verbose
,
693 if (!pcd_probe(unit
,DU
[D_SLV
],id
)) {
696 } else pi_release(PI
);
701 printk("%s: No CD-ROM drive found\n",name
);
705 /* I/O request processing */
707 static void do_pcd_request (void)
711 if (pcd_busy
) return;
713 if ((!CURRENT
) || (CURRENT
->rq_status
== RQ_INACTIVE
)) return;
715 if (CURRENT
->cmd
== READ
) {
716 unit
= MINOR(CURRENT
->rq_dev
);
717 if (unit
!= pcd_unit
) {
721 pcd_sector
= CURRENT
->sector
;
722 pcd_count
= CURRENT
->nr_sectors
;
723 pcd_buf
= CURRENT
->buffer
;
725 ps_set_intr(do_pcd_read
,0,0,nice
);
732 static int pcd_ready( void )
734 { int unit
= pcd_unit
;
736 return (((RR(1,6)&(IDE_BUSY
|IDE_DRQ
))==IDE_DRQ
)) ;
739 static void pcd_transfer( void )
743 while (pcd_count
&& (pcd_sector
/4 == pcd_bufblk
)) {
744 o
= (pcd_sector
% 4) * 512;
745 for(k
=0;k
<512;k
++) pcd_buf
[k
] = pcd_buffer
[o
+k
];
752 static void pcd_start( void )
754 { int unit
= pcd_unit
;
756 char rd_cmd
[12] = {0xa8,0,0,0,0,0,0,0,0,1,0,0};
759 pcd_bufblk
= pcd_sector
/ 4;
762 rd_cmd
[5-i
] = b
& 0xff;
766 if (pcd_command(unit
,rd_cmd
,2048,"read block")) {
768 spin_lock_irqsave(&io_request_lock
,saved_flags
);
772 spin_unlock_irqrestore(&io_request_lock
,saved_flags
);
778 ps_set_intr(do_pcd_read_drq
,pcd_ready
,PCD_TMO
,nice
);
782 static void do_pcd_read( void )
785 { int unit
= pcd_unit
;
792 spin_lock_irqsave(&io_request_lock
,saved_flags
);
796 spin_unlock_irqrestore(&io_request_lock
,saved_flags
);
800 pi_do_claimed(PI
,pcd_start
);
803 static void do_pcd_read_drq( void )
805 { int unit
= pcd_unit
;
808 if (pcd_completion(unit
,pcd_buffer
,"read block")) {
809 if (pcd_retries
< PCD_RETRIES
) {
812 pi_do_claimed(PI
,pcd_start
);
815 spin_lock_irqsave(&io_request_lock
,saved_flags
);
820 spin_unlock_irqrestore(&io_request_lock
,saved_flags
);
825 spin_lock_irqsave(&io_request_lock
,saved_flags
);
827 spin_unlock_irqrestore(&io_request_lock
,saved_flags
);
830 /* the audio_ioctl stuff is adapted from sr_ioctl.c */
832 static int pcd_audio_ioctl(struct cdrom_device_info
*cdi
,
833 unsigned int cmd
, void *arg
)
835 { int unit
= DEVICE_NR(cdi
->dev
);
841 { char cmd
[12]={GPCMD_PAUSE_RESUME
,0,0,0,0,0,0,0,0,0,0,0};
843 return (pcd_atapi(unit
,cmd
,0,NULL
,"pause")) * EIO
;
848 { char cmd
[12]={GPCMD_PAUSE_RESUME
,0,0,0,0,0,0,0,1,0,0,0};
850 return (pcd_atapi(unit
,cmd
,0,NULL
,"resume")) * EIO
;
855 { char cmd
[12]={GPCMD_PLAY_AUDIO_MSF
,0,0,0,0,0,0,0,0,0,0,0};
856 struct cdrom_msf
* msf
= (struct cdrom_msf
*)arg
;
858 cmd
[3] = msf
->cdmsf_min0
;
859 cmd
[4] = msf
->cdmsf_sec0
;
860 cmd
[5] = msf
->cdmsf_frame0
;
861 cmd
[6] = msf
->cdmsf_min1
;
862 cmd
[7] = msf
->cdmsf_sec1
;
863 cmd
[8] = msf
->cdmsf_frame1
;
865 return (pcd_atapi(unit
,cmd
,0,NULL
,"play msf")) * EIO
;
870 { char cmd
[12]={GPCMD_PLAY_AUDIO_10
,0,0,0,0,0,0,0,0,0,0,0};
871 struct cdrom_blk
* blk
= (struct cdrom_blk
*)arg
;
873 cmd
[2] = blk
->from
>> 24;
874 cmd
[3] = blk
->from
>> 16;
875 cmd
[4] = blk
->from
>> 8;
877 cmd
[7] = blk
->len
>> 8;
880 return (pcd_atapi(unit
,cmd
,0,NULL
,"play block")) * EIO
;
883 case CDROMPLAYTRKIND
:
885 { char cmd
[12]={GPCMD_PLAYAUDIO_TI
,0,0,0,0,0,0,0,0,0,0,0};
886 struct cdrom_ti
* ti
= (struct cdrom_ti
*)arg
;
888 cmd
[4] = ti
->cdti_trk0
;
889 cmd
[5] = ti
->cdti_ind0
;
890 cmd
[7] = ti
->cdti_trk1
;
891 cmd
[8] = ti
->cdti_ind1
;
893 return (pcd_atapi(unit
,cmd
,0,NULL
,"play track")) * EIO
;
896 case CDROMREADTOCHDR
:
898 { char cmd
[12]={GPCMD_READ_TOC_PMA_ATIP
,0,0,0,0,0,0,0,12,0,0,0};
899 struct cdrom_tochdr
* tochdr
= (struct cdrom_tochdr
*)arg
;
903 r
= pcd_atapi(unit
,cmd
,12,buffer
,"read toc header");
905 tochdr
->cdth_trk0
= buffer
[2];
906 tochdr
->cdth_trk1
= buffer
[3];
911 case CDROMREADTOCENTRY
:
913 { char cmd
[12]={GPCMD_READ_TOC_PMA_ATIP
,0,0,0,0,0,0,0,12,0,0,0};
915 struct cdrom_tocentry
* tocentry
= (struct cdrom_tocentry
*)arg
;
916 unsigned char buffer
[32];
919 cmd
[1] = (tocentry
->cdte_format
== CDROM_MSF
? 0x02 : 0);
920 cmd
[6] = tocentry
->cdte_track
;
922 r
= pcd_atapi(unit
,cmd
,12,buffer
,"read toc entry");
924 tocentry
->cdte_ctrl
= buffer
[5] & 0xf;
925 tocentry
->cdte_adr
= buffer
[5] >> 4;
926 tocentry
->cdte_datamode
= (tocentry
->cdte_ctrl
& 0x04)?1:0;
927 if (tocentry
->cdte_format
== CDROM_MSF
) {
928 tocentry
->cdte_addr
.msf
.minute
= buffer
[9];
929 tocentry
->cdte_addr
.msf
.second
= buffer
[10];
930 tocentry
->cdte_addr
.msf
.frame
= buffer
[11];
932 tocentry
->cdte_addr
.lba
=
933 (((((buffer
[8] << 8) + buffer
[9]) << 8)
934 + buffer
[10]) << 8) + buffer
[11];
941 { char cmd
[12]={GPCMD_START_STOP_UNIT
,1,0,0,0,0,0,0,0,0,0,0};
943 return (pcd_atapi(unit
,cmd
,0,NULL
,"stop")) * EIO
;
948 { char cmd
[12]={GPCMD_START_STOP_UNIT
,1,0,0,1,0,0,0,0,0,0,0};
950 return (pcd_atapi(unit
,cmd
,0,NULL
,"start")) * EIO
;
955 { char cmd
[12]={GPCMD_MODE_SENSE_10
,0,0,0,0,0,0,0,0,0,0,0};
958 struct cdrom_volctrl
* volctrl
= (struct cdrom_volctrl
*)arg
;
963 if (pcd_atapi(unit
,cmd
,28,buffer
,"mode sense vol"))
968 if (pcd_atapi(unit
,cmd
,28,buffer
,"mode sense vol mask"))
973 buffer
[21] = volctrl
->channel0
& mask
[21];
974 buffer
[23] = volctrl
->channel1
& mask
[23];
975 buffer
[25] = volctrl
->channel2
& mask
[25];
976 buffer
[27] = volctrl
->channel3
& mask
[27];
981 return pcd_atapi(unit
,cmd
,28,buffer
,"mode select vol") * EIO
;
986 { char cmd
[12]={GPCMD_MODE_SENSE_10
,0,0,0,0,0,0,0,0,0,0,0};
988 struct cdrom_volctrl
* volctrl
= (struct cdrom_volctrl
*)arg
;
994 r
= pcd_atapi(unit
,cmd
,28,buffer
,"mode sense vol read");
996 volctrl
->channel0
= buffer
[21];
997 volctrl
->channel1
= buffer
[23];
998 volctrl
->channel2
= buffer
[25];
999 volctrl
->channel3
= buffer
[27];
1007 { char cmd
[12]={GPCMD_READ_SUBCHANNEL
,2,0x40,1,0,0,0,0,16,0,0,0};
1008 struct cdrom_subchnl
* subchnl
= (struct cdrom_subchnl
*)arg
;
1011 if (pcd_atapi(unit
,cmd
,16,buffer
,"read subchannel"))
1014 subchnl
->cdsc_audiostatus
= buffer
[1];
1015 subchnl
->cdsc_format
= CDROM_MSF
;
1016 subchnl
->cdsc_ctrl
= buffer
[5] & 0xf;
1017 subchnl
->cdsc_trk
= buffer
[6];
1018 subchnl
->cdsc_ind
= buffer
[7];
1020 subchnl
->cdsc_reladdr
.msf
.minute
= buffer
[13];
1021 subchnl
->cdsc_reladdr
.msf
.second
= buffer
[14];
1022 subchnl
->cdsc_reladdr
.msf
.frame
= buffer
[15];
1023 subchnl
->cdsc_absaddr
.msf
.minute
= buffer
[9];
1024 subchnl
->cdsc_absaddr
.msf
.second
= buffer
[10];
1025 subchnl
->cdsc_absaddr
.msf
.frame
= buffer
[11];
1036 static int pcd_get_mcn (struct cdrom_device_info
*cdi
, struct cdrom_mcn
*mcn
)
1038 { char cmd
[12]={GPCMD_READ_SUBCHANNEL
,0,0x40,2,0,0,0,0,24,0,0,0};
1041 int unit
= DEVICE_NR(cdi
->dev
);
1043 if (pcd_atapi(unit
,cmd
,24,buffer
,"get mcn")) return -EIO
;
1045 for (k
=0;k
<13;k
++) mcn
->medium_catalog_number
[k
] = buffer
[k
+9];
1046 mcn
->medium_catalog_number
[13] = 0;