103 #define PCD_VERSION "1.07"
105 #define PCD_NAME "pcd"
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;
132 #include <linux/module.h>
134 #include <linux/errno.h>
135 #include <linux/fs.h>
136 #include <linux/kernel.h>
138 #include <linux/cdrom.h>
142 #include <asm/uaccess.h>
159 #define PCD_RETRIES 5
162 #define PCD_READY_TMO 20
163 #define PCD_RESET_TMO 100
165 #define PCD_SPIN (1000000*PCD_TMO)/(HZ*PCD_DELAY)
169 #define IDE_READY 0x40
170 #define IDE_BUSY 0x80
176 unsigned int clearing,
int slot_nr);
182 unsigned int cmd,
void *
arg);
186 static int pcd_detect(
void);
187 static void pcd_probe_capabilities(
void);
188 static void do_pcd_read_drq(
void);
190 static void do_pcd_read(
void);
206 static char pcd_scratch[64];
207 static char pcd_buffer[2048];
208 static int pcd_bufblk = -1;
217 static struct pcd_unit *pcd_current;
218 static struct request *pcd_req;
219 static int pcd_retries;
221 static int pcd_sector;
222 static int pcd_count;
223 static char *pcd_buf;
249 unsigned cmd,
unsigned long arg)
261 static unsigned int pcd_block_check_events(
struct gendisk *
disk,
262 unsigned int clearing)
268 static const struct block_device_operations pcd_bdops = {
270 .open = pcd_block_open,
271 .release = pcd_block_release,
272 .ioctl = pcd_block_ioctl,
273 .check_events = pcd_block_check_events,
278 .release = pcd_release,
279 .drive_status = pcd_drive_status,
280 .check_events = pcd_check_events,
281 .tray_move = pcd_tray_move,
282 .lock_door = pcd_lock_door,
283 .get_mcn = pcd_get_mcn,
284 .reset = pcd_drive_reset,
285 .audio_ioctl = pcd_audio_ioctl,
286 .generic_packet = pcd_packet,
293 static void pcd_init_units(
void)
299 for (unit = 0, cd = pcd; unit <
PCD_UNITS; unit++, cd++) {
309 if ((*drives[unit])[
D_PRT])
314 cd->
info.ops = &pcd_dops;
317 cd->
info.capacity = 1;
320 disk->first_minor =
unit;
322 disk->fops = &pcd_bdops;
323 disk->flags = GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
339 static inline int status_reg(
struct pcd_unit *cd)
359 while ((((r = status_reg(cd)) & go) || (stop && (!(r & stop))))
370 printk(
"%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
371 " loop=%d phase=%d\n",
372 cd->
name, fun, msg, r, s, e, j, p);
378 static int pcd_command(
struct pcd_unit *cd,
char *
cmd,
int dlen,
char *fun)
399 printk(
"%s: %s: command phase error\n", cd->
name, fun);
409 static int pcd_completion(
struct pcd_unit *cd,
char *
buf,
char *fun)
418 fun,
"completion")) {
422 n = (d + 3) & 0xfffc;
425 if ((p == 2) && (n > 0) && (j == 0)) {
428 printk(
"%s: %s: Read %d bytes\n",
435 (
"%s: %s: Unexpected phase %d, d=%d, k=%d\n",
436 cd->
name, fun, p, d, k);
439 "%s: WARNING: ATAPI phase errors\n",
461 static void pcd_req_sense(
struct pcd_unit *cd,
char *fun)
463 char rs_cmd[12] = { 0x03, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 };
467 r = pcd_command(cd, rs_cmd, 16,
"Request sense");
470 pcd_completion(cd, buf,
"Request sense");
476 printk(
"%s: %s: Sense key: %x, ASC: %x, ASQ: %x\n",
477 cd->
name, fun, buf[2] & 0xf, buf[12], buf[13]);
480 c | ((buf[12] & 0xff) << 8) | ((buf[13] & 0xff) << 16);
482 if ((c == 2) || (c == 6))
486 static int pcd_atapi(
struct pcd_unit *cd,
char *cmd,
int dlen,
char *buf,
char *fun)
490 r = pcd_command(cd, cmd, dlen, fun);
493 r = pcd_completion(cd, buf, fun);
495 pcd_req_sense(cd, fun);
506 #define DBMSG(msg) ((verbose>1)?(msg):NULL)
509 unsigned int clearing,
int slot_nr)
515 return res ? DISK_EVENT_MEDIA_CHANGE : 0;
520 char un_cmd[12] = { 0x1e, 0, 0, 0, lock, 0, 0, 0, 0, 0, 0, 0 };
522 return pcd_atapi(cdi->
handle, un_cmd, 0, pcd_scratch,
523 lock ?
"lock door" :
"unlock door");
528 char ej_cmd[12] = { 0x1b, 0, 0, 0, 3 - position, 0, 0, 0, 0, 0, 0, 0 };
530 return pcd_atapi(cdi->
handle, ej_cmd, 0, pcd_scratch,
531 position ?
"eject" :
"close tray");
534 static void pcd_sleep(
int cs)
539 static int pcd_reset(
struct pcd_unit *cd)
542 int expect[5] = { 1, 1, 1, 0x14, 0xeb };
548 pcd_sleep(20 *
HZ / 1000);
555 for (i = 0; i < 5; i++)
556 flg &= (
read_reg(cd, i + 1) == expect[i]);
559 printk(
"%s: Reset (%d) signature = ", cd->
name, k);
560 for (i = 0; i < 5; i++)
573 return pcd_reset(cdi->
handle);
576 static int pcd_ready_wait(
struct pcd_unit *cd,
int tmo)
578 char tr_cmd[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
584 pcd_atapi(cd, tr_cmd, 0,
NULL,
DBMSG(
"test unit ready"));
588 if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6)))
598 char rc_cmd[12] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
603 if (pcd_atapi(cd, rc_cmd, 8, pcd_scratch,
DBMSG(
"check media")))
608 static int pcd_identify(
struct pcd_unit *cd,
char *
id)
611 char id_cmd[12] = { 0x12, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
615 s = pcd_atapi(cd, id_cmd, 36, pcd_buffer,
"identify");
619 if ((pcd_buffer[0] & 0x1f) != 5) {
621 printk(
"%s: %s is not a CD-ROM\n",
622 cd->
name, cd->
drive ?
"Slave" :
"Master");
625 memcpy(
id, pcd_buffer + 16, 16);
628 while ((k >= 0) && (
id[k] <= 0x20)) {
642 static int pcd_probe(
struct pcd_unit *cd,
int ms,
char *
id)
646 if (!pcd_reset(cd) && !pcd_identify(cd,
id))
650 if (!pcd_reset(cd) && !pcd_identify(cd,
id))
656 static void pcd_probe_capabilities(
void)
660 char cmd[12] = { 0x5a, 1 << 3, 0x2a, 0, 0, 0, 0, 18, 0, 0, 0, 0 };
663 for (unit = 0, cd = pcd; unit <
PCD_UNITS; unit++, cd++) {
666 r = pcd_atapi(cd, cmd, 18, buffer,
"mode sense capabilities");
670 if ((buffer[11] & 1) == 0)
672 if ((buffer[11] & 2) == 0)
674 if ((buffer[12] & 1) == 0)
676 if ((buffer[14] & 1) == 0)
678 if ((buffer[14] & 8) == 0)
680 if ((buffer[14] >> 6) == 0)
685 static int pcd_detect(
void)
691 printk(
"%s: %s version %s, major %d, nice %d\n",
695 if (pcd_drive_count == 0) {
697 if (
pi_init(cd->
pi, 1, -1, -1, -1, -1, -1, pcd_buffer,
699 if (!pcd_probe(cd, -1,
id) && cd->
disk) {
706 for (unit = 0, cd = pcd; unit <
PCD_UNITS; unit++, cd++) {
707 int *conf = *drives[
unit];
714 if (!pcd_probe(cd, conf[
D_SLV],
id) && cd->
disk) {
725 for (unit = 0, cd = pcd; unit <
PCD_UNITS; unit++, cd++)
744 if (rq_data_dir(pcd_req) ==
READ) {
745 struct pcd_unit *cd = pcd_req->rq_disk->private_data;
746 if (cd != pcd_current)
749 pcd_sector = blk_rq_pos(pcd_req);
750 pcd_count = blk_rq_cur_sectors(pcd_req);
751 pcd_buf = pcd_req->buffer;
753 ps_set_intr(do_pcd_read,
NULL, 0, nice);
762 static inline void next_request(
int err)
764 unsigned long saved_flags;
770 do_pcd_request(pcd_queue);
771 spin_unlock_irqrestore(&pcd_lock, saved_flags);
774 static int pcd_ready(
void)
776 return (((status_reg(pcd_current) & (IDE_BUSY |
IDE_DRQ)) ==
IDE_DRQ));
779 static void pcd_transfer(
void)
782 while (pcd_count && (pcd_sector / 4 == pcd_bufblk)) {
783 int o = (pcd_sector % 4) * 512;
784 memcpy(pcd_buf, pcd_buffer + o, 512);
791 static void pcd_start(
void)
794 char rd_cmd[12] = { 0xa8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };
796 pcd_bufblk = pcd_sector / 4;
798 for (i = 0; i < 4; i++) {
799 rd_cmd[5 -
i] = b & 0xff;
803 if (pcd_command(pcd_current, rd_cmd, 2048,
"read block")) {
811 ps_set_intr(do_pcd_read_drq, pcd_ready,
PCD_TMO, nice);
814 static void do_pcd_read(
void)
827 static void do_pcd_read_drq(
void)
829 unsigned long saved_flags;
831 if (pcd_completion(pcd_current, pcd_buffer,
"read block")) {
845 do_pcd_request(pcd_queue);
846 spin_unlock_irqrestore(&pcd_lock, saved_flags);
868 r = pcd_atapi(cd, cmd, 12, buffer,
"read toc header");
885 unsigned char buffer[32];
892 r = pcd_atapi(cd, cmd, 12, buffer,
"read toc entry");
895 tocentry->
cdte_adr = buffer[5] >> 4;
904 (((((buffer[8] << 8) + buffer[9]) << 8)
905 + buffer[10]) << 8) + buffer[11];
919 {
GPCMD_READ_SUBCHANNEL, 0, 0x40, 2, 0, 0, 0, 0, 24, 0, 0, 0 };
922 if (pcd_atapi(cdi->
handle, cmd, 24, buffer,
"get mcn"))
931 static int __init pcd_init(
void)
945 pcd_probe_capabilities();
948 for (unit = 0, cd = pcd; unit <
PCD_UNITS; unit++, cd++)
956 for (unit = 0, cd = pcd; unit <
PCD_UNITS; unit++, cd++)
961 for (unit = 0, cd = pcd; unit <
PCD_UNITS; unit++, cd++) {
964 cd->
disk->private_data =
cd;
965 cd->
disk->queue = pcd_queue;
973 static void __exit pcd_exit(
void)
978 for (unit = 0, cd = pcd; unit <
PCD_UNITS; unit++, cd++) {