Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.38 988 lines 25 kB view raw
1/* 2 pcd.c (c) 1997-8 Grant R. Guenther <grant@torque.net> 3 Under the terms of the GNU General Public License. 4 5 This is a high-level driver for parallel port ATAPI CD-ROM 6 drives based on chips supported by the paride module. 7 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. 11 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: 15 16 drive0 These four arguments can be arrays of 17 drive1 1-6 integers as follows: 18 drive2 19 drive3 <prt>,<pro>,<uni>,<mod>,<slv>,<dly> 20 21 Where, 22 23 <prt> is the base of the parallel port address for 24 the corresponding drive. (required) 25 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) 30 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. 35 (0 if not given) 36 37 <mod> this can be -1 to choose the best mode, or one 38 of the mode numbers supported by the adapter. 39 (-1 if not given) 40 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 44 first drive found. 45 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) 52 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 56 name as well. 57 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). 61 (default "pcd") 62 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 67 output. (default 0) 68 69 nice This parameter controls the driver's use of 70 idle CPU time, at the expense of some speed. 71 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: 75 76 pcd.drive0 77 pcd.drive1 78 pcd.drive2 79 pcd.drive3 80 pcd.nice 81 82 In addition, you can use the parameter pcd.disable to disable 83 the driver entirely. 84 85*/ 86 87/* Changes: 88 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 100 101*/ 102 103#define PCD_VERSION "1.07" 104#define PCD_MAJOR 46 105#define PCD_NAME "pcd" 106#define PCD_UNITS 4 107 108/* Here are things one can override from the insmod command. 109 Most are autoprobed by paride unless set here. Verbose is off 110 by default. 111 112*/ 113 114static int verbose = 0; 115static int major = PCD_MAJOR; 116static char *name = PCD_NAME; 117static int nice = 0; 118static int disable = 0; 119 120static int drive0[6] = { 0, 0, 0, -1, -1, -1 }; 121static int drive1[6] = { 0, 0, 0, -1, -1, -1 }; 122static int drive2[6] = { 0, 0, 0, -1, -1, -1 }; 123static int drive3[6] = { 0, 0, 0, -1, -1, -1 }; 124 125static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3}; 126static int pcd_drive_count; 127 128enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY}; 129 130/* end of parameters */ 131 132#include <linux/module.h> 133#include <linux/init.h> 134#include <linux/errno.h> 135#include <linux/fs.h> 136#include <linux/kernel.h> 137#include <linux/delay.h> 138#include <linux/cdrom.h> 139#include <linux/spinlock.h> 140#include <linux/blkdev.h> 141#include <linux/mutex.h> 142#include <asm/uaccess.h> 143 144static DEFINE_MUTEX(pcd_mutex); 145static DEFINE_SPINLOCK(pcd_lock); 146 147module_param(verbose, bool, 0644); 148module_param(major, int, 0); 149module_param(name, charp, 0); 150module_param(nice, int, 0); 151module_param_array(drive0, int, NULL, 0); 152module_param_array(drive1, int, NULL, 0); 153module_param_array(drive2, int, NULL, 0); 154module_param_array(drive3, int, NULL, 0); 155 156#include "paride.h" 157#include "pseudo.h" 158 159#define PCD_RETRIES 5 160#define PCD_TMO 800 /* timeout in jiffies */ 161#define PCD_DELAY 50 /* spin delay in uS */ 162#define PCD_READY_TMO 20 /* in seconds */ 163#define PCD_RESET_TMO 100 /* in tenths of a second */ 164 165#define PCD_SPIN (1000000*PCD_TMO)/(HZ*PCD_DELAY) 166 167#define IDE_ERR 0x01 168#define IDE_DRQ 0x08 169#define IDE_READY 0x40 170#define IDE_BUSY 0x80 171 172static int pcd_open(struct cdrom_device_info *cdi, int purpose); 173static void pcd_release(struct cdrom_device_info *cdi); 174static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr); 175static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr); 176static int pcd_tray_move(struct cdrom_device_info *cdi, int position); 177static int pcd_lock_door(struct cdrom_device_info *cdi, int lock); 178static int pcd_drive_reset(struct cdrom_device_info *cdi); 179static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn); 180static int pcd_audio_ioctl(struct cdrom_device_info *cdi, 181 unsigned int cmd, void *arg); 182static int pcd_packet(struct cdrom_device_info *cdi, 183 struct packet_command *cgc); 184 185static int pcd_detect(void); 186static void pcd_probe_capabilities(void); 187static void do_pcd_read_drq(void); 188static void do_pcd_request(struct request_queue * q); 189static void do_pcd_read(void); 190 191struct pcd_unit { 192 struct pi_adapter pia; /* interface to paride layer */ 193 struct pi_adapter *pi; 194 int drive; /* master/slave */ 195 int last_sense; /* result of last request sense */ 196 int changed; /* media change seen */ 197 int present; /* does this unit exist ? */ 198 char *name; /* pcd0, pcd1, etc */ 199 struct cdrom_device_info info; /* uniform cdrom interface */ 200 struct gendisk *disk; 201}; 202 203static struct pcd_unit pcd[PCD_UNITS]; 204 205static char pcd_scratch[64]; 206static char pcd_buffer[2048]; /* raw block buffer */ 207static int pcd_bufblk = -1; /* block in buffer, in CD units, 208 -1 for nothing there. See also 209 pd_unit. 210 */ 211 212/* the variables below are used mainly in the I/O request engine, which 213 processes only one request at a time. 214*/ 215 216static struct pcd_unit *pcd_current; /* current request's drive */ 217static struct request *pcd_req; 218static int pcd_retries; /* retries on current request */ 219static int pcd_busy; /* request being processed ? */ 220static int pcd_sector; /* address of next requested sector */ 221static int pcd_count; /* number of blocks still to do */ 222static char *pcd_buf; /* buffer for request in progress */ 223 224/* kernel glue structures */ 225 226static int pcd_block_open(struct block_device *bdev, fmode_t mode) 227{ 228 struct pcd_unit *cd = bdev->bd_disk->private_data; 229 int ret; 230 231 mutex_lock(&pcd_mutex); 232 ret = cdrom_open(&cd->info, bdev, mode); 233 mutex_unlock(&pcd_mutex); 234 235 return ret; 236} 237 238static int pcd_block_release(struct gendisk *disk, fmode_t mode) 239{ 240 struct pcd_unit *cd = disk->private_data; 241 mutex_lock(&pcd_mutex); 242 cdrom_release(&cd->info, mode); 243 mutex_unlock(&pcd_mutex); 244 return 0; 245} 246 247static int pcd_block_ioctl(struct block_device *bdev, fmode_t mode, 248 unsigned cmd, unsigned long arg) 249{ 250 struct pcd_unit *cd = bdev->bd_disk->private_data; 251 int ret; 252 253 mutex_lock(&pcd_mutex); 254 ret = cdrom_ioctl(&cd->info, bdev, mode, cmd, arg); 255 mutex_unlock(&pcd_mutex); 256 257 return ret; 258} 259 260static int pcd_block_media_changed(struct gendisk *disk) 261{ 262 struct pcd_unit *cd = disk->private_data; 263 return cdrom_media_changed(&cd->info); 264} 265 266static const struct block_device_operations pcd_bdops = { 267 .owner = THIS_MODULE, 268 .open = pcd_block_open, 269 .release = pcd_block_release, 270 .ioctl = pcd_block_ioctl, 271 .media_changed = pcd_block_media_changed, 272}; 273 274static struct cdrom_device_ops pcd_dops = { 275 .open = pcd_open, 276 .release = pcd_release, 277 .drive_status = pcd_drive_status, 278 .media_changed = pcd_media_changed, 279 .tray_move = pcd_tray_move, 280 .lock_door = pcd_lock_door, 281 .get_mcn = pcd_get_mcn, 282 .reset = pcd_drive_reset, 283 .audio_ioctl = pcd_audio_ioctl, 284 .generic_packet = pcd_packet, 285 .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | 286 CDC_MCN | CDC_MEDIA_CHANGED | CDC_RESET | 287 CDC_PLAY_AUDIO | CDC_GENERIC_PACKET | CDC_CD_R | 288 CDC_CD_RW, 289}; 290 291static void pcd_init_units(void) 292{ 293 struct pcd_unit *cd; 294 int unit; 295 296 pcd_drive_count = 0; 297 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { 298 struct gendisk *disk = alloc_disk(1); 299 if (!disk) 300 continue; 301 cd->disk = disk; 302 cd->pi = &cd->pia; 303 cd->present = 0; 304 cd->last_sense = 0; 305 cd->changed = 1; 306 cd->drive = (*drives[unit])[D_SLV]; 307 if ((*drives[unit])[D_PRT]) 308 pcd_drive_count++; 309 310 cd->name = &cd->info.name[0]; 311 snprintf(cd->name, sizeof(cd->info.name), "%s%d", name, unit); 312 cd->info.ops = &pcd_dops; 313 cd->info.handle = cd; 314 cd->info.speed = 0; 315 cd->info.capacity = 1; 316 cd->info.mask = 0; 317 disk->major = major; 318 disk->first_minor = unit; 319 strcpy(disk->disk_name, cd->name); /* umm... */ 320 disk->fops = &pcd_bdops; 321 } 322} 323 324static int pcd_open(struct cdrom_device_info *cdi, int purpose) 325{ 326 struct pcd_unit *cd = cdi->handle; 327 if (!cd->present) 328 return -ENODEV; 329 return 0; 330} 331 332static void pcd_release(struct cdrom_device_info *cdi) 333{ 334} 335 336static inline int status_reg(struct pcd_unit *cd) 337{ 338 return pi_read_regr(cd->pi, 1, 6); 339} 340 341static inline int read_reg(struct pcd_unit *cd, int reg) 342{ 343 return pi_read_regr(cd->pi, 0, reg); 344} 345 346static inline void write_reg(struct pcd_unit *cd, int reg, int val) 347{ 348 pi_write_regr(cd->pi, 0, reg, val); 349} 350 351static int pcd_wait(struct pcd_unit *cd, int go, int stop, char *fun, char *msg) 352{ 353 int j, r, e, s, p; 354 355 j = 0; 356 while ((((r = status_reg(cd)) & go) || (stop && (!(r & stop)))) 357 && (j++ < PCD_SPIN)) 358 udelay(PCD_DELAY); 359 360 if ((r & (IDE_ERR & stop)) || (j > PCD_SPIN)) { 361 s = read_reg(cd, 7); 362 e = read_reg(cd, 1); 363 p = read_reg(cd, 2); 364 if (j > PCD_SPIN) 365 e |= 0x100; 366 if (fun) 367 printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x" 368 " loop=%d phase=%d\n", 369 cd->name, fun, msg, r, s, e, j, p); 370 return (s << 8) + r; 371 } 372 return 0; 373} 374 375static int pcd_command(struct pcd_unit *cd, char *cmd, int dlen, char *fun) 376{ 377 pi_connect(cd->pi); 378 379 write_reg(cd, 6, 0xa0 + 0x10 * cd->drive); 380 381 if (pcd_wait(cd, IDE_BUSY | IDE_DRQ, 0, fun, "before command")) { 382 pi_disconnect(cd->pi); 383 return -1; 384 } 385 386 write_reg(cd, 4, dlen % 256); 387 write_reg(cd, 5, dlen / 256); 388 write_reg(cd, 7, 0xa0); /* ATAPI packet command */ 389 390 if (pcd_wait(cd, IDE_BUSY, IDE_DRQ, fun, "command DRQ")) { 391 pi_disconnect(cd->pi); 392 return -1; 393 } 394 395 if (read_reg(cd, 2) != 1) { 396 printk("%s: %s: command phase error\n", cd->name, fun); 397 pi_disconnect(cd->pi); 398 return -1; 399 } 400 401 pi_write_block(cd->pi, cmd, 12); 402 403 return 0; 404} 405 406static int pcd_completion(struct pcd_unit *cd, char *buf, char *fun) 407{ 408 int r, d, p, n, k, j; 409 410 r = -1; 411 k = 0; 412 j = 0; 413 414 if (!pcd_wait(cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR, 415 fun, "completion")) { 416 r = 0; 417 while (read_reg(cd, 7) & IDE_DRQ) { 418 d = read_reg(cd, 4) + 256 * read_reg(cd, 5); 419 n = (d + 3) & 0xfffc; 420 p = read_reg(cd, 2) & 3; 421 422 if ((p == 2) && (n > 0) && (j == 0)) { 423 pi_read_block(cd->pi, buf, n); 424 if (verbose > 1) 425 printk("%s: %s: Read %d bytes\n", 426 cd->name, fun, n); 427 r = 0; 428 j++; 429 } else { 430 if (verbose > 1) 431 printk 432 ("%s: %s: Unexpected phase %d, d=%d, k=%d\n", 433 cd->name, fun, p, d, k); 434 if (verbose < 2) 435 printk_once( 436 "%s: WARNING: ATAPI phase errors\n", 437 cd->name); 438 mdelay(1); 439 } 440 if (k++ > PCD_TMO) { 441 printk("%s: Stuck DRQ\n", cd->name); 442 break; 443 } 444 if (pcd_wait 445 (cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR, fun, 446 "completion")) { 447 r = -1; 448 break; 449 } 450 } 451 } 452 453 pi_disconnect(cd->pi); 454 455 return r; 456} 457 458static void pcd_req_sense(struct pcd_unit *cd, char *fun) 459{ 460 char rs_cmd[12] = { 0x03, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 }; 461 char buf[16]; 462 int r, c; 463 464 r = pcd_command(cd, rs_cmd, 16, "Request sense"); 465 mdelay(1); 466 if (!r) 467 pcd_completion(cd, buf, "Request sense"); 468 469 cd->last_sense = -1; 470 c = 2; 471 if (!r) { 472 if (fun) 473 printk("%s: %s: Sense key: %x, ASC: %x, ASQ: %x\n", 474 cd->name, fun, buf[2] & 0xf, buf[12], buf[13]); 475 c = buf[2] & 0xf; 476 cd->last_sense = 477 c | ((buf[12] & 0xff) << 8) | ((buf[13] & 0xff) << 16); 478 } 479 if ((c == 2) || (c == 6)) 480 cd->changed = 1; 481} 482 483static int pcd_atapi(struct pcd_unit *cd, char *cmd, int dlen, char *buf, char *fun) 484{ 485 int r; 486 487 r = pcd_command(cd, cmd, dlen, fun); 488 mdelay(1); 489 if (!r) 490 r = pcd_completion(cd, buf, fun); 491 if (r) 492 pcd_req_sense(cd, fun); 493 494 return r; 495} 496 497static int pcd_packet(struct cdrom_device_info *cdi, struct packet_command *cgc) 498{ 499 return pcd_atapi(cdi->handle, cgc->cmd, cgc->buflen, cgc->buffer, 500 "generic packet"); 501} 502 503#define DBMSG(msg) ((verbose>1)?(msg):NULL) 504 505static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr) 506{ 507 struct pcd_unit *cd = cdi->handle; 508 int res = cd->changed; 509 if (res) 510 cd->changed = 0; 511 return res; 512} 513 514static int pcd_lock_door(struct cdrom_device_info *cdi, int lock) 515{ 516 char un_cmd[12] = { 0x1e, 0, 0, 0, lock, 0, 0, 0, 0, 0, 0, 0 }; 517 518 return pcd_atapi(cdi->handle, un_cmd, 0, pcd_scratch, 519 lock ? "lock door" : "unlock door"); 520} 521 522static int pcd_tray_move(struct cdrom_device_info *cdi, int position) 523{ 524 char ej_cmd[12] = { 0x1b, 0, 0, 0, 3 - position, 0, 0, 0, 0, 0, 0, 0 }; 525 526 return pcd_atapi(cdi->handle, ej_cmd, 0, pcd_scratch, 527 position ? "eject" : "close tray"); 528} 529 530static void pcd_sleep(int cs) 531{ 532 schedule_timeout_interruptible(cs); 533} 534 535static int pcd_reset(struct pcd_unit *cd) 536{ 537 int i, k, flg; 538 int expect[5] = { 1, 1, 1, 0x14, 0xeb }; 539 540 pi_connect(cd->pi); 541 write_reg(cd, 6, 0xa0 + 0x10 * cd->drive); 542 write_reg(cd, 7, 8); 543 544 pcd_sleep(20 * HZ / 1000); /* delay a bit */ 545 546 k = 0; 547 while ((k++ < PCD_RESET_TMO) && (status_reg(cd) & IDE_BUSY)) 548 pcd_sleep(HZ / 10); 549 550 flg = 1; 551 for (i = 0; i < 5; i++) 552 flg &= (read_reg(cd, i + 1) == expect[i]); 553 554 if (verbose) { 555 printk("%s: Reset (%d) signature = ", cd->name, k); 556 for (i = 0; i < 5; i++) 557 printk("%3x", read_reg(cd, i + 1)); 558 if (!flg) 559 printk(" (incorrect)"); 560 printk("\n"); 561 } 562 563 pi_disconnect(cd->pi); 564 return flg - 1; 565} 566 567static int pcd_drive_reset(struct cdrom_device_info *cdi) 568{ 569 return pcd_reset(cdi->handle); 570} 571 572static int pcd_ready_wait(struct pcd_unit *cd, int tmo) 573{ 574 char tr_cmd[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 575 int k, p; 576 577 k = 0; 578 while (k < tmo) { 579 cd->last_sense = 0; 580 pcd_atapi(cd, tr_cmd, 0, NULL, DBMSG("test unit ready")); 581 p = cd->last_sense; 582 if (!p) 583 return 0; 584 if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6))) 585 return p; 586 k++; 587 pcd_sleep(HZ); 588 } 589 return 0x000020; /* timeout */ 590} 591 592static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr) 593{ 594 char rc_cmd[12] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 595 struct pcd_unit *cd = cdi->handle; 596 597 if (pcd_ready_wait(cd, PCD_READY_TMO)) 598 return CDS_DRIVE_NOT_READY; 599 if (pcd_atapi(cd, rc_cmd, 8, pcd_scratch, DBMSG("check media"))) 600 return CDS_NO_DISC; 601 return CDS_DISC_OK; 602} 603 604static int pcd_identify(struct pcd_unit *cd, char *id) 605{ 606 int k, s; 607 char id_cmd[12] = { 0x12, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 }; 608 609 pcd_bufblk = -1; 610 611 s = pcd_atapi(cd, id_cmd, 36, pcd_buffer, "identify"); 612 613 if (s) 614 return -1; 615 if ((pcd_buffer[0] & 0x1f) != 5) { 616 if (verbose) 617 printk("%s: %s is not a CD-ROM\n", 618 cd->name, cd->drive ? "Slave" : "Master"); 619 return -1; 620 } 621 memcpy(id, pcd_buffer + 16, 16); 622 id[16] = 0; 623 k = 16; 624 while ((k >= 0) && (id[k] <= 0x20)) { 625 id[k] = 0; 626 k--; 627 } 628 629 printk("%s: %s: %s\n", cd->name, cd->drive ? "Slave" : "Master", id); 630 631 return 0; 632} 633 634/* 635 * returns 0, with id set if drive is detected 636 * -1, if drive detection failed 637 */ 638static int pcd_probe(struct pcd_unit *cd, int ms, char *id) 639{ 640 if (ms == -1) { 641 for (cd->drive = 0; cd->drive <= 1; cd->drive++) 642 if (!pcd_reset(cd) && !pcd_identify(cd, id)) 643 return 0; 644 } else { 645 cd->drive = ms; 646 if (!pcd_reset(cd) && !pcd_identify(cd, id)) 647 return 0; 648 } 649 return -1; 650} 651 652static void pcd_probe_capabilities(void) 653{ 654 int unit, r; 655 char buffer[32]; 656 char cmd[12] = { 0x5a, 1 << 3, 0x2a, 0, 0, 0, 0, 18, 0, 0, 0, 0 }; 657 struct pcd_unit *cd; 658 659 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { 660 if (!cd->present) 661 continue; 662 r = pcd_atapi(cd, cmd, 18, buffer, "mode sense capabilities"); 663 if (r) 664 continue; 665 /* we should now have the cap page */ 666 if ((buffer[11] & 1) == 0) 667 cd->info.mask |= CDC_CD_R; 668 if ((buffer[11] & 2) == 0) 669 cd->info.mask |= CDC_CD_RW; 670 if ((buffer[12] & 1) == 0) 671 cd->info.mask |= CDC_PLAY_AUDIO; 672 if ((buffer[14] & 1) == 0) 673 cd->info.mask |= CDC_LOCK; 674 if ((buffer[14] & 8) == 0) 675 cd->info.mask |= CDC_OPEN_TRAY; 676 if ((buffer[14] >> 6) == 0) 677 cd->info.mask |= CDC_CLOSE_TRAY; 678 } 679} 680 681static int pcd_detect(void) 682{ 683 char id[18]; 684 int k, unit; 685 struct pcd_unit *cd; 686 687 printk("%s: %s version %s, major %d, nice %d\n", 688 name, name, PCD_VERSION, major, nice); 689 690 k = 0; 691 if (pcd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */ 692 cd = pcd; 693 if (pi_init(cd->pi, 1, -1, -1, -1, -1, -1, pcd_buffer, 694 PI_PCD, verbose, cd->name)) { 695 if (!pcd_probe(cd, -1, id) && cd->disk) { 696 cd->present = 1; 697 k++; 698 } else 699 pi_release(cd->pi); 700 } 701 } else { 702 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { 703 int *conf = *drives[unit]; 704 if (!conf[D_PRT]) 705 continue; 706 if (!pi_init(cd->pi, 0, conf[D_PRT], conf[D_MOD], 707 conf[D_UNI], conf[D_PRO], conf[D_DLY], 708 pcd_buffer, PI_PCD, verbose, cd->name)) 709 continue; 710 if (!pcd_probe(cd, conf[D_SLV], id) && cd->disk) { 711 cd->present = 1; 712 k++; 713 } else 714 pi_release(cd->pi); 715 } 716 } 717 if (k) 718 return 0; 719 720 printk("%s: No CD-ROM drive found\n", name); 721 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) 722 put_disk(cd->disk); 723 return -1; 724} 725 726/* I/O request processing */ 727static struct request_queue *pcd_queue; 728 729static void do_pcd_request(struct request_queue * q) 730{ 731 if (pcd_busy) 732 return; 733 while (1) { 734 if (!pcd_req) { 735 pcd_req = blk_fetch_request(q); 736 if (!pcd_req) 737 return; 738 } 739 740 if (rq_data_dir(pcd_req) == READ) { 741 struct pcd_unit *cd = pcd_req->rq_disk->private_data; 742 if (cd != pcd_current) 743 pcd_bufblk = -1; 744 pcd_current = cd; 745 pcd_sector = blk_rq_pos(pcd_req); 746 pcd_count = blk_rq_cur_sectors(pcd_req); 747 pcd_buf = pcd_req->buffer; 748 pcd_busy = 1; 749 ps_set_intr(do_pcd_read, NULL, 0, nice); 750 return; 751 } else { 752 __blk_end_request_all(pcd_req, -EIO); 753 pcd_req = NULL; 754 } 755 } 756} 757 758static inline void next_request(int err) 759{ 760 unsigned long saved_flags; 761 762 spin_lock_irqsave(&pcd_lock, saved_flags); 763 if (!__blk_end_request_cur(pcd_req, err)) 764 pcd_req = NULL; 765 pcd_busy = 0; 766 do_pcd_request(pcd_queue); 767 spin_unlock_irqrestore(&pcd_lock, saved_flags); 768} 769 770static int pcd_ready(void) 771{ 772 return (((status_reg(pcd_current) & (IDE_BUSY | IDE_DRQ)) == IDE_DRQ)); 773} 774 775static void pcd_transfer(void) 776{ 777 778 while (pcd_count && (pcd_sector / 4 == pcd_bufblk)) { 779 int o = (pcd_sector % 4) * 512; 780 memcpy(pcd_buf, pcd_buffer + o, 512); 781 pcd_count--; 782 pcd_buf += 512; 783 pcd_sector++; 784 } 785} 786 787static void pcd_start(void) 788{ 789 int b, i; 790 char rd_cmd[12] = { 0xa8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }; 791 792 pcd_bufblk = pcd_sector / 4; 793 b = pcd_bufblk; 794 for (i = 0; i < 4; i++) { 795 rd_cmd[5 - i] = b & 0xff; 796 b = b >> 8; 797 } 798 799 if (pcd_command(pcd_current, rd_cmd, 2048, "read block")) { 800 pcd_bufblk = -1; 801 next_request(-EIO); 802 return; 803 } 804 805 mdelay(1); 806 807 ps_set_intr(do_pcd_read_drq, pcd_ready, PCD_TMO, nice); 808} 809 810static void do_pcd_read(void) 811{ 812 pcd_busy = 1; 813 pcd_retries = 0; 814 pcd_transfer(); 815 if (!pcd_count) { 816 next_request(0); 817 return; 818 } 819 820 pi_do_claimed(pcd_current->pi, pcd_start); 821} 822 823static void do_pcd_read_drq(void) 824{ 825 unsigned long saved_flags; 826 827 if (pcd_completion(pcd_current, pcd_buffer, "read block")) { 828 if (pcd_retries < PCD_RETRIES) { 829 mdelay(1); 830 pcd_retries++; 831 pi_do_claimed(pcd_current->pi, pcd_start); 832 return; 833 } 834 pcd_bufblk = -1; 835 next_request(-EIO); 836 return; 837 } 838 839 do_pcd_read(); 840 spin_lock_irqsave(&pcd_lock, saved_flags); 841 do_pcd_request(pcd_queue); 842 spin_unlock_irqrestore(&pcd_lock, saved_flags); 843} 844 845/* the audio_ioctl stuff is adapted from sr_ioctl.c */ 846 847static int pcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg) 848{ 849 struct pcd_unit *cd = cdi->handle; 850 851 switch (cmd) { 852 853 case CDROMREADTOCHDR: 854 855 { 856 char cmd[12] = 857 { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12, 858 0, 0, 0 }; 859 struct cdrom_tochdr *tochdr = 860 (struct cdrom_tochdr *) arg; 861 char buffer[32]; 862 int r; 863 864 r = pcd_atapi(cd, cmd, 12, buffer, "read toc header"); 865 866 tochdr->cdth_trk0 = buffer[2]; 867 tochdr->cdth_trk1 = buffer[3]; 868 869 return r ? -EIO : 0; 870 } 871 872 case CDROMREADTOCENTRY: 873 874 { 875 char cmd[12] = 876 { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12, 877 0, 0, 0 }; 878 879 struct cdrom_tocentry *tocentry = 880 (struct cdrom_tocentry *) arg; 881 unsigned char buffer[32]; 882 int r; 883 884 cmd[1] = 885 (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0); 886 cmd[6] = tocentry->cdte_track; 887 888 r = pcd_atapi(cd, cmd, 12, buffer, "read toc entry"); 889 890 tocentry->cdte_ctrl = buffer[5] & 0xf; 891 tocentry->cdte_adr = buffer[5] >> 4; 892 tocentry->cdte_datamode = 893 (tocentry->cdte_ctrl & 0x04) ? 1 : 0; 894 if (tocentry->cdte_format == CDROM_MSF) { 895 tocentry->cdte_addr.msf.minute = buffer[9]; 896 tocentry->cdte_addr.msf.second = buffer[10]; 897 tocentry->cdte_addr.msf.frame = buffer[11]; 898 } else 899 tocentry->cdte_addr.lba = 900 (((((buffer[8] << 8) + buffer[9]) << 8) 901 + buffer[10]) << 8) + buffer[11]; 902 903 return r ? -EIO : 0; 904 } 905 906 default: 907 908 return -ENOSYS; 909 } 910} 911 912static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) 913{ 914 char cmd[12] = 915 { GPCMD_READ_SUBCHANNEL, 0, 0x40, 2, 0, 0, 0, 0, 24, 0, 0, 0 }; 916 char buffer[32]; 917 918 if (pcd_atapi(cdi->handle, cmd, 24, buffer, "get mcn")) 919 return -EIO; 920 921 memcpy(mcn->medium_catalog_number, buffer + 9, 13); 922 mcn->medium_catalog_number[13] = 0; 923 924 return 0; 925} 926 927static int __init pcd_init(void) 928{ 929 struct pcd_unit *cd; 930 int unit; 931 932 if (disable) 933 return -EINVAL; 934 935 pcd_init_units(); 936 937 if (pcd_detect()) 938 return -ENODEV; 939 940 /* get the atapi capabilities page */ 941 pcd_probe_capabilities(); 942 943 if (register_blkdev(major, name)) { 944 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) 945 put_disk(cd->disk); 946 return -EBUSY; 947 } 948 949 pcd_queue = blk_init_queue(do_pcd_request, &pcd_lock); 950 if (!pcd_queue) { 951 unregister_blkdev(major, name); 952 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) 953 put_disk(cd->disk); 954 return -ENOMEM; 955 } 956 957 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { 958 if (cd->present) { 959 register_cdrom(&cd->info); 960 cd->disk->private_data = cd; 961 cd->disk->queue = pcd_queue; 962 add_disk(cd->disk); 963 } 964 } 965 966 return 0; 967} 968 969static void __exit pcd_exit(void) 970{ 971 struct pcd_unit *cd; 972 int unit; 973 974 for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { 975 if (cd->present) { 976 del_gendisk(cd->disk); 977 pi_release(cd->pi); 978 unregister_cdrom(&cd->info); 979 } 980 put_disk(cd->disk); 981 } 982 blk_cleanup_queue(pcd_queue); 983 unregister_blkdev(major, name); 984} 985 986MODULE_LICENSE("GPL"); 987module_init(pcd_init) 988module_exit(pcd_exit)