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 128#define D_PRT 0 129#define D_PRO 1 130#define D_UNI 2 131#define D_MOD 3 132#define D_SLV 4 133#define D_DLY 5 134 135#define DU (*drives[unit]) 136 137/* end of parameters */ 138 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> 146 147#include <asm/uaccess.h> 148 149#ifndef MODULE 150 151#include "setup.h" 152 153static STT pcd_stt[6] = {{"drive0",6,drive0}, 154 {"drive1",6,drive1}, 155 {"drive2",6,drive2}, 156 {"drive3",6,drive3}, 157 {"disable",1,&disable}, 158 {"nice",1,&nice}}; 159 160void pcd_setup( char *str, int *ints) 161 162{ generic_setup(pcd_stt,6,str); 163} 164 165#endif 166 167MODULE_PARM(verbose,"i"); 168MODULE_PARM(major,"i"); 169MODULE_PARM(name,"s"); 170MODULE_PARM(nice,"i"); 171MODULE_PARM(drive0,"1-6i"); 172MODULE_PARM(drive1,"1-6i"); 173MODULE_PARM(drive2,"1-6i"); 174MODULE_PARM(drive3,"1-6i"); 175 176#include "paride.h" 177 178/* set up defines for blk.h, why don't all drivers do it this way ? */ 179 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) 186 187#include <linux/blk.h> 188 189#include "pseudo.h" 190 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 */ 196 197#define PCD_SPIN (1000000*PCD_TMO)/(HZ*PCD_DELAY) 198 199#define IDE_ERR 0x01 200#define IDE_DRQ 0x08 201#define IDE_READY 0x40 202#define IDE_BUSY 0x80 203 204int pcd_init(void); 205void cleanup_module( void ); 206 207static int pcd_open(struct cdrom_device_info *cdi, int purpose); 208static void pcd_release(struct cdrom_device_info *cdi); 209static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr); 210static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr); 211static int pcd_tray_move(struct cdrom_device_info *cdi, int position); 212static int pcd_lock_door(struct cdrom_device_info *cdi, int lock); 213static int pcd_drive_reset(struct cdrom_device_info *cdi); 214static int pcd_get_mcn (struct cdrom_device_info *cdi, struct cdrom_mcn *mcn); 215static int pcd_audio_ioctl(struct cdrom_device_info *cdi, 216 unsigned int cmd, void *arg); 217static int pcd_packet(struct cdrom_device_info *cdi, 218 struct cdrom_generic_command *cgc); 219 220static int pcd_detect(void); 221static void pcd_probe_capabilities(void); 222static void do_pcd_read_drq(void); 223static void do_pcd_request(request_queue_t * q); 224static void do_pcd_read(void); 225 226static int pcd_blocksizes[PCD_UNITS]; 227 228struct pcd_unit { 229 struct pi_adapter pia; /* interface to paride layer */ 230 struct pi_adapter *pi; 231 int drive; /* master/slave */ 232 int last_sense; /* result of last request sense */ 233 int changed; /* media change seen */ 234 int present; /* does this unit exist ? */ 235 char *name; /* pcd0, pcd1, etc */ 236 struct cdrom_device_info info; /* uniform cdrom interface */ 237 }; 238 239struct pcd_unit pcd[PCD_UNITS]; 240 241/* 'unit' must be defined in all functions - either as a local or a param */ 242 243#define PCD pcd[unit] 244#define PI PCD.pi 245 246static char pcd_scratch[64]; 247static char pcd_buffer[2048]; /* raw block buffer */ 248static int pcd_bufblk = -1; /* block in buffer, in CD units, 249 -1 for nothing there. See also 250 pd_unit. 251 */ 252 253/* the variables below are used mainly in the I/O request engine, which 254 processes only one request at a time. 255*/ 256 257static int pcd_unit = -1; /* unit of current request & bufblk */ 258static int pcd_retries; /* retries on current request */ 259static int pcd_busy = 0; /* request being processed ? */ 260static int pcd_sector; /* address of next requested sector */ 261static int pcd_count; /* number of blocks still to do */ 262static char * pcd_buf; /* buffer for request in progress */ 263 264static int pcd_warned = 0; /* Have we logged a phase warning ? */ 265 266/* kernel glue structures */ 267 268static struct block_device_operations pcd_bdops = { 269 owner: THIS_MODULE, 270 open: cdrom_open, 271 release: cdrom_release, 272 ioctl: cdrom_ioctl, 273 check_media_change: cdrom_media_changed, 274}; 275 276static struct cdrom_device_ops pcd_dops = { 277 pcd_open, 278 pcd_release, 279 pcd_drive_status, 280 pcd_media_changed, 281 pcd_tray_move, 282 pcd_lock_door, 283 0, /* select speed */ 284 0, /* select disk */ 285 0, /* get last session */ 286 pcd_get_mcn, 287 pcd_drive_reset, 288 pcd_audio_ioctl, 289 0, /* dev_ioctl */ 290 CDC_CLOSE_TRAY | 291 CDC_OPEN_TRAY | 292 CDC_LOCK | 293 CDC_MCN | 294 CDC_MEDIA_CHANGED | 295 CDC_RESET | 296 CDC_PLAY_AUDIO | 297 CDC_GENERIC_PACKET | 298 CDC_CD_R | 299 CDC_CD_RW, 300 0, 301 pcd_packet, 302}; 303 304static void pcd_init_units( void ) 305 306{ int unit, j; 307 308 pcd_drive_count = 0; 309 for (unit=0;unit<PCD_UNITS;unit++) { 310 PCD.pi = & PCD.pia; 311 PCD.present = 0; 312 PCD.last_sense = 0; 313 PCD.changed = 1; 314 PCD.drive = DU[D_SLV]; 315 if (DU[D_PRT]) pcd_drive_count++; 316 317 j = 0; 318 while ((j < (sizeof(PCD.info.name)-2)) && 319 (PCD.info.name[j]=name[j])) j++; 320 PCD.info.name[j++] = '0' + unit; 321 PCD.info.name[j] = 0; 322 PCD.name = &PCD.info.name[0]; 323 324 PCD.info.ops = &pcd_dops; 325 PCD.info.handle = NULL; 326 PCD.info.dev = MKDEV(major,unit); 327 PCD.info.speed = 0; 328 PCD.info.capacity = 1; 329 PCD.info.mask = 0; 330 } 331} 332 333int pcd_init (void) /* preliminary initialisation */ 334 335{ int i, unit; 336 337 if (disable) return -1; 338 339 pcd_init_units(); 340 341 if (pcd_detect()) return -1; 342 343 /* get the atapi capabilities page */ 344 pcd_probe_capabilities(); 345 346 if (register_blkdev(MAJOR_NR,name,&pcd_bdops)) { 347 printk("pcd: unable to get major number %d\n",MAJOR_NR); 348 return -1; 349 } 350 351 for (unit=0;unit<PCD_UNITS;unit++) { 352 if (PCD.present) { 353 register_cdrom(&PCD.info); 354 devfs_plain_cdrom(&PCD.info, &pcd_bdops); 355 } 356 } 357 358 blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); 359 read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */ 360 361 for (i=0;i<PCD_UNITS;i++) pcd_blocksizes[i] = 1024; 362 blksize_size[MAJOR_NR] = pcd_blocksizes; 363 364 return 0; 365} 366 367static int pcd_open(struct cdrom_device_info *cdi, int purpose) 368 369{ int unit = DEVICE_NR(cdi->dev); 370 371 if ((unit >= PCD_UNITS) || (!PCD.present)) return -ENODEV; 372 373 return 0; 374} 375 376static void pcd_release(struct cdrom_device_info *cdi) 377 378{ 379} 380 381#ifdef MODULE 382 383/* Glue for modules ... */ 384 385int init_module(void) 386 387{ int err; 388 389#ifdef PARIDE_JUMBO 390 { extern paride_init(); 391 paride_init(); 392 } 393#endif 394 395 err = pcd_init(); 396 397 return err; 398} 399 400void cleanup_module(void) 401 402{ int unit; 403 404 for (unit=0;unit<PCD_UNITS;unit++) 405 if (PCD.present) { 406 pi_release(PI); 407 unregister_cdrom(&PCD.info); 408 } 409 410 unregister_blkdev(MAJOR_NR,name); 411} 412 413#endif 414 415#define WR(c,r,v) pi_write_regr(PI,c,r,v) 416#define RR(c,r) (pi_read_regr(PI,c,r)) 417 418static int pcd_wait( int unit, int go, int stop, char * fun, char * msg ) 419 420{ int j, r, e, s, p; 421 422 j = 0; 423 while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(j++<PCD_SPIN)) 424 udelay(PCD_DELAY); 425 426 if ((r&(IDE_ERR&stop))||(j>=PCD_SPIN)) { 427 s = RR(0,7); 428 e = RR(0,1); 429 p = RR(0,2); 430 if (j >= PCD_SPIN) e |= 0x100; 431 if (fun) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x" 432 " loop=%d phase=%d\n", 433 PCD.name,fun,msg,r,s,e,j,p); 434 return (s<<8)+r; 435 } 436 return 0; 437} 438 439static int pcd_command( int unit, char * cmd, int dlen, char * fun ) 440 441{ pi_connect(PI); 442 443 WR(0,6,0xa0 + 0x10*PCD.drive); 444 445 if (pcd_wait(unit,IDE_BUSY|IDE_DRQ,0,fun,"before command")) { 446 pi_disconnect(PI); 447 return -1; 448 } 449 450 WR(0,4,dlen % 256); 451 WR(0,5,dlen / 256); 452 WR(0,7,0xa0); /* ATAPI packet command */ 453 454 if (pcd_wait(unit,IDE_BUSY,IDE_DRQ,fun,"command DRQ")) { 455 pi_disconnect(PI); 456 return -1; 457 } 458 459 if (RR(0,2) != 1) { 460 printk("%s: %s: command phase error\n",PCD.name,fun); 461 pi_disconnect(PI); 462 return -1; 463 } 464 465 pi_write_block(PI,cmd,12); 466 467 return 0; 468} 469 470static int pcd_completion( int unit, char * buf, char * fun ) 471 472{ int r, d, p, n, k, j; 473 474 r = -1; k = 0; j = 0; 475 476 if (!pcd_wait(unit,IDE_BUSY,IDE_DRQ|IDE_READY|IDE_ERR, 477 fun,"completion")) { 478 r = 0; 479 while (RR(0,7)&IDE_DRQ) { 480 d = (RR(0,4)+256*RR(0,5)); 481 n = ((d+3)&0xfffc); 482 p = RR(0,2)&3; 483 484 if ((p == 2) && (n > 0) && (j == 0)) { 485 pi_read_block(PI,buf,n); 486 if (verbose > 1) 487 printk("%s: %s: Read %d bytes\n",PCD.name,fun,n); 488 r = 0; j++; 489 } else { 490 if (verbose > 1) 491 printk("%s: %s: Unexpected phase %d, d=%d, k=%d\n", 492 PCD.name,fun,p,d,k); 493 if ((verbose < 2) && !pcd_warned) { 494 pcd_warned = 1; 495 printk("%s: WARNING: ATAPI phase errors\n",PCD.name); 496 } 497 mdelay(1); 498 } 499 if (k++ > PCD_TMO) { 500 printk("%s: Stuck DRQ\n",PCD.name); 501 break; 502 } 503 if (pcd_wait(unit,IDE_BUSY,IDE_DRQ|IDE_READY|IDE_ERR, 504 fun,"completion")) { 505 r = -1; 506 break; 507 } 508 } 509 } 510 511 pi_disconnect(PI); 512 513 return r; 514} 515 516static void pcd_req_sense( int unit, char *fun ) 517 518{ char rs_cmd[12] = { 0x03,0,0,0,16,0,0,0,0,0,0,0 }; 519 char buf[16]; 520 int r, c; 521 522 r = pcd_command(unit,rs_cmd,16,"Request sense"); 523 mdelay(1); 524 if (!r) pcd_completion(unit,buf,"Request sense"); 525 526 PCD.last_sense = -1; c = 2; 527 if (!r) { 528 if (fun) printk("%s: %s: Sense key: %x, ASC: %x, ASQ: %x\n", 529 PCD.name,fun,buf[2]&0xf,buf[12],buf[13]); 530 c = buf[2]&0xf; 531 PCD.last_sense = c | ((buf[12]&0xff)<<8) | ((buf[13]&0xff)<<16); 532 } 533 if ((c == 2) || (c == 6)) PCD.changed = 1; 534} 535 536static int pcd_atapi( int unit, char * cmd, int dlen, char * buf, char * fun ) 537 538{ int r; 539 540 r = pcd_command(unit,cmd,dlen,fun); 541 mdelay(1); 542 if (!r) r = pcd_completion(unit,buf,fun); 543 if (r) pcd_req_sense(unit,fun); 544 545 return r; 546} 547 548static int pcd_packet(struct cdrom_device_info *cdi, 549 struct cdrom_generic_command *cgc) 550{ 551 char *un_cmd; 552 int unit = DEVICE_NR(cdi->dev); 553 554 un_cmd = cgc->cmd; 555 return pcd_atapi(unit,un_cmd,cgc->buflen,cgc->buffer, "generic packet"); 556} 557 558#define DBMSG(msg) ((verbose>1)?(msg):NULL) 559 560static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr) 561 562{ int r; 563 int unit = DEVICE_NR(cdi->dev); 564 565 r = PCD.changed; 566 PCD.changed = 0; 567 568 return r; 569} 570 571static int pcd_lock_door(struct cdrom_device_info *cdi, int lock) 572 573{ char un_cmd[12] = { 0x1e,0,0,0,lock,0,0,0,0,0,0,0 }; 574 int unit = DEVICE_NR(cdi->dev); 575 576 return pcd_atapi(unit,un_cmd,0,pcd_scratch, 577 lock?"lock door":"unlock door"); 578} 579 580static int pcd_tray_move(struct cdrom_device_info *cdi, int position) 581 582{ char ej_cmd[12] = { 0x1b,0,0,0,3-position,0,0,0,0,0,0,0 }; 583 int unit = DEVICE_NR(cdi->dev); 584 585 return pcd_atapi(unit,ej_cmd,0,pcd_scratch, 586 position?"eject":"close tray"); 587} 588 589static void pcd_sleep( int cs ) 590 591{ current->state = TASK_INTERRUPTIBLE; 592 schedule_timeout(cs); 593} 594 595static int pcd_reset( int unit ) 596 597{ int i, k, flg; 598 int expect[5] = {1,1,1,0x14,0xeb}; 599 600 pi_connect(PI); 601 WR(0,6,0xa0 + 0x10*PCD.drive); 602 WR(0,7,8); 603 604 pcd_sleep(20*HZ/1000); /* delay a bit */ 605 606 k = 0; 607 while ((k++ < PCD_RESET_TMO) && (RR(1,6)&IDE_BUSY)) 608 pcd_sleep(HZ/10); 609 610 flg = 1; 611 for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]); 612 613 if (verbose) { 614 printk("%s: Reset (%d) signature = ",PCD.name,k); 615 for (i=0;i<5;i++) printk("%3x",RR(0,i+1)); 616 if (!flg) printk(" (incorrect)"); 617 printk("\n"); 618 } 619 620 pi_disconnect(PI); 621 return flg-1; 622} 623 624static int pcd_drive_reset(struct cdrom_device_info *cdi) 625 626{ return pcd_reset(DEVICE_NR(cdi->dev)); 627} 628 629static int pcd_ready_wait( int unit, int tmo ) 630 631{ char tr_cmd[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; 632 int k, p; 633 634 k = 0; 635 while (k < tmo) { 636 PCD.last_sense = 0; 637 pcd_atapi(unit,tr_cmd,0,NULL,DBMSG("test unit ready")); 638 p = PCD.last_sense; 639 if (!p) return 0; 640 if (!(((p & 0xffff) == 0x0402)||((p & 0xff) == 6))) return p; 641 k++; 642 pcd_sleep(HZ); 643 } 644 return 0x000020; /* timeout */ 645} 646 647static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr) 648 649{ char rc_cmd[12] = { 0x25,0,0,0,0,0,0,0,0,0,0,0}; 650 int unit = DEVICE_NR(cdi->dev); 651 652 if (pcd_ready_wait(unit,PCD_READY_TMO)) 653 return CDS_DRIVE_NOT_READY; 654 if (pcd_atapi(unit,rc_cmd,8,pcd_scratch,DBMSG("check media"))) 655 return CDS_NO_DISC; 656 return CDS_DISC_OK; 657} 658 659static int pcd_identify( int unit, char * id ) 660 661{ int k, s; 662 char id_cmd[12] = {0x12,0,0,0,36,0,0,0,0,0,0,0}; 663 664 pcd_bufblk = -1; 665 666 s = pcd_atapi(unit,id_cmd,36,pcd_buffer,"identify"); 667 668 if (s) return -1; 669 if ((pcd_buffer[0] & 0x1f) != 5) { 670 if (verbose) printk("%s: %s is not a CD-ROM\n", 671 PCD.name,PCD.drive?"Slave":"Master"); 672 return -1; 673 } 674 for (k=0;k<16;k++) id[k] = pcd_buffer[16+k]; id[16] = 0; 675 k = 16; while ((k >= 0) && (id[k] <= 0x20)) { id[k] = 0; k--; } 676 677 printk("%s: %s: %s\n",PCD.name,PCD.drive?"Slave":"Master",id); 678 679 return 0; 680} 681 682static int pcd_probe( int unit, int ms, char * id ) 683 684/* returns 0, with id set if drive is detected 685 -1, if drive detection failed 686*/ 687 688{ if (ms == -1) { 689 for (PCD.drive=0;PCD.drive<=1;PCD.drive++) 690 if (!pcd_reset(unit) && !pcd_identify(unit,id)) 691 return 0; 692 } else { 693 PCD.drive = ms; 694 if (!pcd_reset(unit) && !pcd_identify(unit,id)) 695 return 0; 696 } 697 return -1; 698} 699 700static void pcd_probe_capabilities( void ) 701 702{ int unit, r; 703 char buffer[32]; 704 char cmd[12]={0x5a,1<<3,0x2a,0,0,0,0,18,0,0,0,0}; 705 706 for (unit=0;unit<PCD_UNITS;unit++) { 707 if (!PCD.present) continue; 708 r = pcd_atapi(unit,cmd,18, buffer,"mode sense capabilities"); 709 if (r) continue; 710 /* we should now have the cap page */ 711 if ((buffer[11] & 1) == 0) 712 PCD.info.mask |= CDC_CD_R; 713 if ((buffer[11] & 2) == 0) 714 PCD.info.mask |= CDC_CD_RW; 715 if ((buffer[12] & 1) == 0) 716 PCD.info.mask |= CDC_PLAY_AUDIO; 717 if ((buffer[14] & 1) == 0) 718 PCD.info.mask |= CDC_LOCK; 719 if ((buffer[14] & 8) == 0) 720 PCD.info.mask |= CDC_OPEN_TRAY; 721 if ((buffer[14] >> 6) == 0) 722 PCD.info.mask |= CDC_CLOSE_TRAY; 723 } 724} 725 726static int pcd_detect( void ) 727 728{ char id[18]; 729 int k, unit; 730 731 printk("%s: %s version %s, major %d, nice %d\n", 732 name,name,PCD_VERSION,major,nice); 733 734 k = 0; 735 if (pcd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */ 736 unit = 0; 737 if (pi_init(PI,1,-1,-1,-1,-1,-1,pcd_buffer, 738 PI_PCD,verbose,PCD.name)) { 739 if (!pcd_probe(unit,-1,id)) { 740 PCD.present = 1; 741 k++; 742 } else pi_release(PI); 743 } 744 745 } else for (unit=0;unit<PCD_UNITS;unit++) if (DU[D_PRT]) 746 if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI], 747 DU[D_PRO],DU[D_DLY],pcd_buffer,PI_PCD,verbose, 748 PCD.name)) { 749 if (!pcd_probe(unit,DU[D_SLV],id)) { 750 PCD.present = 1; 751 k++; 752 } else pi_release(PI); 753 } 754 755 if (k) return 0; 756 757 printk("%s: No CD-ROM drive found\n",name); 758 return -1; 759} 760 761/* I/O request processing */ 762 763static void do_pcd_request (request_queue_t * q) 764 765{ int unit; 766 767 if (pcd_busy) return; 768 while (1) { 769 if (QUEUE_EMPTY || (CURRENT->rq_status == RQ_INACTIVE)) return; 770 INIT_REQUEST; 771 if (CURRENT->cmd == READ) { 772 unit = MINOR(CURRENT->rq_dev); 773 if (unit != pcd_unit) { 774 pcd_bufblk = -1; 775 pcd_unit = unit; 776 } 777 pcd_sector = CURRENT->sector; 778 pcd_count = CURRENT->current_nr_sectors; 779 pcd_buf = CURRENT->buffer; 780 pcd_busy = 1; 781 ps_set_intr(do_pcd_read,0,0,nice); 782 return; 783 } 784 else end_request(0); 785 } 786} 787 788static int pcd_ready( void ) 789 790{ int unit = pcd_unit; 791 792 return (((RR(1,6)&(IDE_BUSY|IDE_DRQ))==IDE_DRQ)) ; 793} 794 795static void pcd_transfer( void ) 796 797{ int k, o; 798 799 while (pcd_count && (pcd_sector/4 == pcd_bufblk)) { 800 o = (pcd_sector % 4) * 512; 801 for(k=0;k<512;k++) pcd_buf[k] = pcd_buffer[o+k]; 802 pcd_count--; 803 pcd_buf += 512; 804 pcd_sector++; 805 } 806} 807 808static void pcd_start( void ) 809 810{ int unit = pcd_unit; 811 int b, i; 812 char rd_cmd[12] = {0xa8,0,0,0,0,0,0,0,0,1,0,0}; 813 unsigned long saved_flags; 814 815 pcd_bufblk = pcd_sector / 4; 816 b = pcd_bufblk; 817 for(i=0;i<4;i++) { 818 rd_cmd[5-i] = b & 0xff; 819 b = b >> 8; 820 } 821 822 if (pcd_command(unit,rd_cmd,2048,"read block")) { 823 pcd_bufblk = -1; 824 spin_lock_irqsave(&io_request_lock,saved_flags); 825 pcd_busy = 0; 826 end_request(0); 827 do_pcd_request(NULL); 828 spin_unlock_irqrestore(&io_request_lock,saved_flags); 829 return; 830 } 831 832 mdelay(1); 833 834 ps_set_intr(do_pcd_read_drq,pcd_ready,PCD_TMO,nice); 835 836} 837 838static void do_pcd_read( void ) 839 840 841{ int unit = pcd_unit; 842 unsigned long saved_flags; 843 844 pcd_busy = 1; 845 pcd_retries = 0; 846 pcd_transfer(); 847 if (!pcd_count) { 848 spin_lock_irqsave(&io_request_lock,saved_flags); 849 end_request(1); 850 pcd_busy = 0; 851 do_pcd_request(NULL); 852 spin_unlock_irqrestore(&io_request_lock,saved_flags); 853 return; 854 } 855 856 pi_do_claimed(PI,pcd_start); 857} 858 859static void do_pcd_read_drq( void ) 860 861{ int unit = pcd_unit; 862 unsigned long saved_flags; 863 864 if (pcd_completion(unit,pcd_buffer,"read block")) { 865 if (pcd_retries < PCD_RETRIES) { 866 mdelay(1); 867 pcd_retries++; 868 pi_do_claimed(PI,pcd_start); 869 return; 870 } 871 spin_lock_irqsave(&io_request_lock,saved_flags); 872 pcd_busy = 0; 873 pcd_bufblk = -1; 874 end_request(0); 875 do_pcd_request(NULL); 876 spin_unlock_irqrestore(&io_request_lock,saved_flags); 877 return; 878 } 879 880 do_pcd_read(); 881 spin_lock_irqsave(&io_request_lock,saved_flags); 882 do_pcd_request(NULL); 883 spin_unlock_irqrestore(&io_request_lock,saved_flags); 884} 885 886/* the audio_ioctl stuff is adapted from sr_ioctl.c */ 887 888static int pcd_audio_ioctl(struct cdrom_device_info *cdi, 889 unsigned int cmd, void *arg) 890 891{ int unit = DEVICE_NR(cdi->dev); 892 893 switch (cmd) { 894 895 case CDROMREADTOCHDR: 896 897 { char cmd[12]={GPCMD_READ_TOC_PMA_ATIP,0,0,0,0,0,0,0,12,0,0,0}; 898 struct cdrom_tochdr* tochdr = (struct cdrom_tochdr*)arg; 899 char buffer[32]; 900 int r; 901 902 r = pcd_atapi(unit,cmd,12,buffer,"read toc header"); 903 904 tochdr->cdth_trk0 = buffer[2]; 905 tochdr->cdth_trk1 = buffer[3]; 906 907 return r * EIO; 908 } 909 910 case CDROMREADTOCENTRY: 911 912 { char cmd[12]={GPCMD_READ_TOC_PMA_ATIP,0,0,0,0,0,0,0,12,0,0,0}; 913 914 struct cdrom_tocentry* tocentry = (struct cdrom_tocentry*)arg; 915 unsigned char buffer[32]; 916 int r; 917 918 cmd[1] = (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0); 919 cmd[6] = tocentry->cdte_track; 920 921 r = pcd_atapi(unit,cmd,12,buffer,"read toc entry"); 922 923 tocentry->cdte_ctrl = buffer[5] & 0xf; 924 tocentry->cdte_adr = buffer[5] >> 4; 925 tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04)?1:0; 926 if (tocentry->cdte_format == CDROM_MSF) { 927 tocentry->cdte_addr.msf.minute = buffer[9]; 928 tocentry->cdte_addr.msf.second = buffer[10]; 929 tocentry->cdte_addr.msf.frame = buffer[11]; 930 } else 931 tocentry->cdte_addr.lba = 932 (((((buffer[8] << 8) + buffer[9]) << 8) 933 + buffer[10]) << 8) + buffer[11]; 934 935 return r * EIO; 936 } 937 938 default: 939 940 return -ENOSYS; 941 } 942} 943 944static int pcd_get_mcn (struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) 945 946{ char cmd[12]={GPCMD_READ_SUBCHANNEL,0,0x40,2,0,0,0,0,24,0,0,0}; 947 char buffer[32]; 948 int k; 949 int unit = DEVICE_NR(cdi->dev); 950 951 if (pcd_atapi(unit,cmd,24,buffer,"get mcn")) return -EIO; 952 953 for (k=0;k<13;k++) mcn->medium_catalog_number[k] = buffer[k+9]; 954 mcn->medium_catalog_number[13] = 0; 955 956 return 0; 957} 958 959/* end of pcd.c */ 960 961MODULE_LICENSE("GPL"); 962