root/drivers/cdrom/cm206.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. send_command_polled
  2. receive_echo_polled
  3. send_receive_polled
  4. cm206_interrupt
  5. cm206_timeout
  6. sleep_or_timeout
  7. cm206_delay
  8. send_command
  9. receive_echo
  10. send_receive
  11. wait_dsb
  12. type_0_command
  13. type_1_command
  14. reset_cm260
  15. fsm
  16. fsm2lba
  17. f_s_m2lba
  18. start_read
  19. stop_read
  20. read_background
  21. read_sector
  22. cm206_bh
  23. get_drive_status
  24. get_disc_status
  25. cm206_open
  26. cm206_release
  27. empty_buffer
  28. try_adapter
  29. do_cm206_request
  30. get_multi_session_info
  31. seek
  32. bcdbin
  33. normalize_track
  34. get_toc_lba
  35. update_toc_entry
  36. read_toc_header
  37. play_from_to_msf
  38. play_from_to_track
  39. get_current_q
  40. get_toc_entry
  41. cm206_ioctl
  42. cleanup
  43. probe_base_port
  44. probe_irq
  45. parse_options
  46. cm206_init
  47. cleanup_module
  48. cm206_setup

   1 /* cm206.c. A linux-driver for the cm206 cdrom player with cm260 adapter card.
   2    Copyright (c) 1995 David van Leeuwen.
   3    
   4      This program is free software; you can redistribute it and/or modify
   5      it under the terms of the GNU General Public License as published by
   6      the Free Software Foundation; either version 2 of the License, or
   7      (at your option) any later version.
   8      
   9      This program is distributed in the hope that it will be useful,
  10      but WITHOUT ANY WARRANTY; without even the implied warranty of
  11      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12      GNU General Public License for more details.
  13      
  14      You should have received a copy of the GNU General Public License
  15      along with this program; if not, write to the Free Software
  16      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17 
  18 History:
  19  Started 25 jan 1994. Waiting for documentation...
  20  22 feb 1995: 0.1a first reasonably safe polling driver.
  21               Two major bugs, one in read_sector and one in 
  22               do_cm206_request, happened to cancel!
  23  25 feb 1995: 0.2a first reasonable interrupt driven version of above.
  24               uart writes are still done in polling mode. 
  25  25 feb 1995: 0.21a writes also in interrupt mode, still some
  26               small bugs to be found... Larger buffer. 
  27   2 mrt 1995: 0.22 Bug found (cd-> nowhere, interrupt was called in
  28               initialization), read_ahead of 16. Timeouts implemented.
  29               unclear if they do something...
  30   7 mrt 1995: 0.23 Start of background read-ahead.
  31  18 mrt 1995: 0.24 Working background read-ahead. (still problems)
  32  26 mrt 1995: 0.25 Multi-session ioctl added (kernel v1.2).
  33               Statistics implemented, though separate stats206.h.
  34               Accessible trough ioctl 0x1000 (just a number).
  35               Hard to choose between v1.2 development and 1.1.75.
  36               Bottom-half doesn't work with 1.2...
  37               0.25a: fixed... typo. Still problems...
  38   1 apr 1995: 0.26 Module support added. Most bugs found. Use kernel 1.2.n.
  39   5 apr 1995: 0.27 Auto-probe for the adapter card base address.
  40               Auto-probe for the adaptor card irq line.
  41   7 apr 1995: 0.28 Added lilo setup support for base address and irq.
  42               Use major number 32 (not in this source), officially
  43               assigned to this driver.
  44   9 apr 1995: 0.29 Added very limited audio support. Toc_header, stop, pause,
  45               resume, eject. Play_track ignores track info, because we can't 
  46               read a table-of-contents entry. Toc_entry is implemented
  47               as a `placebo' function: always returns start of disc. 
  48   3 may 1995: 0.30 Audio support completed. The get_toc_entry function
  49               is implemented as a binary search. 
  50  15 may 1995: 0.31 More work on audio stuff. Workman is not easy to 
  51               satisfy; changed binary search into linear search.
  52               Auto-probe for base address somewhat relaxed.
  53   1 jun 1995: 0.32 Removed probe_irq_on/off for module version.
  54  10 jun 1995: 0.33 Workman still behaves funny, but you should be
  55               able to eject and substitute another disc.
  56 
  57  An adaption of 0.33 is included in linux-1.3.7 by Eberhard Moenkeberg
  58 
  59  18 jul 1996: 0.34 Patch by Heiko Eissfeldt included, mainly considering 
  60               verify_area's in the ioctls. Some bugs introduced by 
  61               EM considering the base port and irq fixed. 
  62  * 
  63  * Parts of the code are based upon lmscd.c written by Kai Petzke,
  64  * sbpcd.c written by Eberhard Moenkeberg, and mcd.c by Martin
  65  * Harriss, but any off-the-shelf dynamic programming algorithm won't
  66  * be able to find them.
  67  *
  68  * The cm206 drive interface and the cm260 adapter card seem to be 
  69  * sufficiently different from their cm205/cm250 counterparts
  70  * in order to write a complete new driver.
  71  * 
  72  * I call all routines connected to the Linux kernel something
  73  * with `cm206' in it, as this stuff is too series-dependent. 
  74  * 
  75  * Currently, my limited knowledge is based on:
  76  * - The Linux Kernel Hacker's guide, v. 0.5 , by Michael J. Johnson
  77  * - Linux Kernel Programmierung, by Michael Beck and others
  78  * - Philips/LMS cm206 and cm226 product specification
  79  * - Philips/LMS cm260 product specification
  80  *
  81  *                       David van Leeuwen, david@tm.tno.nl.  */
  82 #define VERSION "0.34"
  83 
  84 #ifdef MODULE                   /* OK, so some of this is stolen */
  85 #include <linux/module.h>       
  86 #include <linux/version.h>
  87 #ifndef CONFIG_MODVERSIONS
  88 char kernel_version[]=UTS_RELEASE;
  89 #endif
  90 #else 
  91 #define MOD_INC_USE_COUNT
  92 #define MOD_DEC_USE_COUNT
  93 #endif MODULE
  94 
  95 #include <linux/errno.h>        /* These include what we really need */
  96 #include <linux/delay.h>
  97 #include <linux/string.h>
  98 #include <linux/sched.h>
  99 #include <linux/interrupt.h>
 100 #include <linux/timer.h>
 101 #include <linux/cdrom.h>
 102 #include <linux/ioport.h>
 103 #include <linux/mm.h>
 104 #include <linux/malloc.h>
 105 
 106 #include <asm/io.h>
 107 
 108 #define MAJOR_NR CM206_CDROM_MAJOR
 109 #include <linux/blk.h>
 110 #include <linux/cm206.h>
 111 
 112 /* This variable defines whether or not to probe for adapter base port 
 113    address and interrupt request. It can be overridden by the boot 
 114    parameter `auto'.
 115 */
 116 static int auto_probe=1;        /* Yes, why not? */
 117 
 118 static int cm206_base = CM206_BASE;
 119 static int cm206_irq = CM206_IRQ; 
 120 
 121 #undef DEBUG
 122 #undef DEBUG_SECTORS
 123 #define STATISTICS
 124 #undef AUTO_PROBE_MODULE
 125 
 126 #define POLLOOP 10000
 127 #define READ_AHEAD 1            /* defines private buffer, waste! */
 128 #define BACK_AHEAD 1            /* defines adapter-read ahead */
 129 #define DATA_TIMEOUT (3*HZ)     /* measured in jiffies (10 ms) */
 130 #define UART_TIMEOUT (5*HZ/100)
 131 #define DSB_TIMEOUT (7*HZ)      /* time for the slowest command to finish */
 132 
 133 #define RAW_SECTOR_SIZE 2352    /* ok, is also defined in cdrom.h */
 134 #define ISO_SECTOR_SIZE 2048
 135 
 136 #ifdef STATISTICS               /* keep track of errors in counters */
 137 #include <linux/stats206.h>
 138 #define stats(i) ++cd->stats[st_ ## i]; \
 139                  cd->last_stat[st_ ## i] = cd->stat_counter++;
 140 #else
 141 #define stats(i) (void) 0
 142 #endif
 143 
 144 #ifdef DEBUG                    /* from lmscd.c */
 145 #define debug(a) printk a
 146 #else
 147 #define debug(a) (void) 0
 148 #endif
 149 
 150 typedef unsigned char uch;      /* 8-bits */
 151 typedef unsigned short ush;     /* 16-bits */
 152 
 153 struct toc_struct{
 154   uch track, fsm[3], q0;
 155 };
 156 
 157 struct cm206_struct {
 158   ush intr_ds;   /* data status read on last interrupt */
 159   ush intr_ls;   /* uart line status read on last interrupt*/
 160   uch intr_ur;                  /* uart receive buffer */
 161   uch dsb, cc;   /* drive status byte and condition (error) code */
 162   uch fool;
 163   int command;                  /* command to be written to te uart */
 164   int openfiles;
 165   ush sector[READ_AHEAD*RAW_SECTOR_SIZE/2]; /* buffered cd-sector */
 166   int sector_first, sector_last;        /* range of these sector */
 167   struct wait_queue * uart;     /* wait for interrupt */
 168   struct wait_queue * data;
 169   struct timer_list timer;      /* time-out */
 170   char timed_out;
 171   signed char max_sectors;
 172   char wait_back;               /* we're waiting for a background-read */
 173   char background;              /* is a read going on in the background? */
 174   int adapter_first;            /* if so, that's the starting sector */
 175   int adapter_last;
 176   char fifo_overflowed;
 177   uch disc_status[7];           /* result of get_disc_status command */
 178 #ifdef STATISTICS
 179   int stats[NR_STATS];
 180   int last_stat[NR_STATS];      /* `time' at which stat was stat */
 181   int stat_counter;
 182 #endif  
 183   struct toc_struct toc[101];   /* The whole table of contents + lead-out */
 184   uch q[10];                    /* Last read q-channel info */
 185   uch audio_status[5];          /* last read position on pause */
 186 };
 187 
 188 #define DISC_STATUS cd->disc_status[0]
 189 #define FIRST_TRACK cd->disc_status[1]
 190 #define LAST_TRACK cd->disc_status[2]
 191 #define PAUSED cd->audio_status[0] /* misuse this memory byte! */
 192 #define PLAY_TO cd->toc[0]      /* toc[0] records end-time in play */
 193 
 194 static struct cm206_struct * cd;
 195 
 196 /* First, we define some polling functions. These are actually
 197    only being used in the initialization. */
 198 
 199 void send_command_polled(int command)
     /* [previous][next][first][last][top][bottom][index][help] */
 200 {
 201   int loop=POLLOOP;
 202   while (!(inw(r_line_status) & ls_transmitter_buffer_empty) && loop>0) 
 203     --loop;
 204   outw(command, r_uart_transmit);
 205 }
 206 
 207 uch receive_echo_polled(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 208 {
 209   int loop=POLLOOP;
 210   while (!(inw(r_line_status) & ls_receive_buffer_full) && loop>0) --loop;
 211   return ((uch) inw(r_uart_receive));
 212 }
 213 
 214 uch send_receive_polled(int command)
     /* [previous][next][first][last][top][bottom][index][help] */
 215 {
 216   send_command_polled(command);
 217   return receive_echo_polled();
 218 }
 219 
 220 /* The interrupt handler. When the cm260 generates an interrupt, very
 221    much care has to be taken in reading out the registers in the right
 222    order; in case of a receive_buffer_full interrupt, first the
 223    uart_receive must be read, and then the line status again to
 224    de-assert the interrupt line. It took me a couple of hours to find
 225    this out:-( 
 226 
 227    The function reset_cm206 appears to cause an interrupt, because
 228    pulling up the INIT line clears both the uart-write-buffer /and/
 229    the uart-write-buffer-empty mask. We call this a `lost interrupt,'
 230    as there seems so reason for this to happen.
 231 */
 232 
 233 static void cm206_interrupt(int sig, struct pt_regs * regs) /* you rang? */
     /* [previous][next][first][last][top][bottom][index][help] */
 234 {
 235   volatile ush fool;
 236     cd->intr_ds = inw(r_data_status); /* resets data_ready, data_error,
 237                                          crc_error, sync_error, toc_ready 
 238                                          interrupts */
 239     cd->intr_ls = inw(r_line_status); /* resets overrun bit */
 240     /* receive buffer full? */
 241     if (cd->intr_ls & ls_receive_buffer_full) { 
 242       cd->intr_ur = inb(r_uart_receive); /* get order right! */
 243       cd->intr_ls = inw(r_line_status); /* resets rbf interrupt */
 244       if (!cd->background && cd->uart) wake_up_interruptible(&cd->uart);
 245     }
 246     /* data ready in fifo? */
 247     else if (cd->intr_ds & ds_data_ready) { 
 248       if (cd->background) ++cd->adapter_last;
 249       if ((cd->wait_back || !cd->background) && cd->data) 
 250           wake_up_interruptible(&cd->data);
 251       stats(data_ready);
 252     }
 253     /* ready to issue a write command? */
 254     else if (cd->command && cd->intr_ls & ls_transmitter_buffer_empty) {
 255       outw(dc_normal | (inw(r_data_status) & 0x7f), r_data_control);
 256       outw(cd->command, r_uart_transmit);
 257       cd->command=0;
 258       if (!cd->background) wake_up_interruptible(&cd->uart);
 259     }
 260     /* now treat errors (at least, identify them for debugging) */
 261     else if (cd->intr_ds & ds_fifo_overflow) {
 262       debug(("Fifo overflow at sectors 0x%x\n", cd->sector_first));
 263       fool = inw(r_fifo_output_buffer); /* de-assert the interrupt */
 264       cd->fifo_overflowed=1;    /* signal one word less should be read */
 265       stats(fifo_overflow);
 266     }
 267     else if (cd->intr_ds & ds_data_error) {
 268       debug(("Data error at sector 0x%x\n", cd->sector_first));
 269       stats(data_error);
 270     }
 271     else if (cd->intr_ds & ds_crc_error) {
 272       debug(("CRC error at sector 0x%x\n", cd->sector_first));
 273       stats(crc_error);
 274     }
 275     else if (cd->intr_ds & ds_sync_error) {
 276       debug(("Sync at sector 0x%x\n", cd->sector_first));
 277       stats(sync_error);
 278     }
 279     else if (cd->intr_ds & ds_toc_ready) {
 280                                 /* do something appropiate */
 281     }
 282     /* couldn't see why this interrupt, maybe due to init */
 283     else {                      
 284       outw(dc_normal | READ_AHEAD, r_data_control);
 285       stats(lost_intr);
 286     }
 287   if (cd->background && (cd->adapter_last-cd->adapter_first == cd->max_sectors
 288       || cd->fifo_overflowed))
 289     mark_bh(CM206_BH);  /* issue a stop read command */
 290   stats(interrupt);
 291 }
 292 
 293 /* we have put the address of the wait queue in who */
 294 void cm206_timeout(unsigned long who)
     /* [previous][next][first][last][top][bottom][index][help] */
 295 {
 296   cd->timed_out = 1;
 297   wake_up_interruptible((struct wait_queue **) who);
 298 }
 299 
 300 /* This function returns 1 if a timeout occurred, 0 if an interrupt
 301    happened */
 302 int sleep_or_timeout(struct wait_queue ** wait, int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 303 {
 304   cd->timer.data=(unsigned long) wait;
 305   cd->timer.expires = jiffies + timeout;
 306   add_timer(&cd->timer);
 307   interruptible_sleep_on(wait);
 308   del_timer(&cd->timer);
 309   if (cd->timed_out) {
 310     cd->timed_out = 0;
 311     return 1;
 312   }
 313   else return 0;
 314 }
 315 
 316 void cm206_delay(int jiffies) 
     /* [previous][next][first][last][top][bottom][index][help] */
 317 {
 318   struct wait_queue * wait = NULL;
 319   sleep_or_timeout(&wait, jiffies);
 320 }
 321 
 322 void send_command(int command)
     /* [previous][next][first][last][top][bottom][index][help] */
 323 {
 324   if (!(inw(r_line_status) & ls_transmitter_buffer_empty)) {
 325     cd->command = command;
 326     cli();                      /* don't interrupt before sleep */
 327     outw(dc_mask_sync_error | dc_no_stop_on_error | 
 328          (inw(r_data_status) & 0x7f), r_data_control);
 329     /* interrupt routine sends command */
 330     if (sleep_or_timeout(&cd->uart, UART_TIMEOUT)) {
 331       debug(("Time out on write-buffer\n"));
 332       stats(write_timeout);
 333       outw(command, r_uart_transmit);
 334     }
 335   }
 336   else outw(command, r_uart_transmit);
 337 }
 338 
 339 uch receive_echo(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 340 {
 341   if (!(inw(r_line_status) & ls_receive_buffer_full) &&
 342       sleep_or_timeout(&cd->uart, UART_TIMEOUT)) {
 343     debug(("Time out on receive-buffer\n"));
 344     stats(receive_timeout);
 345     return ((uch) inw(r_uart_receive));
 346   }
 347   return cd->intr_ur;
 348 }
 349 
 350 inline uch send_receive(int command)
     /* [previous][next][first][last][top][bottom][index][help] */
 351 {
 352   send_command(command);
 353   return receive_echo();
 354 }
 355 
 356 uch wait_dsb(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 357 {
 358   if (!(inw(r_line_status) & ls_receive_buffer_full) &&
 359       sleep_or_timeout(&cd->uart, DSB_TIMEOUT)) {
 360     debug(("Time out on Drive Status Byte\n"));
 361     stats(dsb_timeout);
 362     return ((uch) inw(r_uart_receive));
 363   }
 364   return cd->intr_ur;
 365 }
 366 
 367 int type_0_command(int command, int expect_dsb)
     /* [previous][next][first][last][top][bottom][index][help] */
 368 {
 369   int e;
 370   if (command != (e=send_receive(command))) {
 371     debug(("command 0x%x echoed as 0x%x\n", command, e));
 372     stats(echo);
 373     return -1;
 374   }
 375   if (expect_dsb) {
 376     cd->dsb = wait_dsb();       /* wait for command to finish */
 377   }
 378   return 0;
 379 }
 380 
 381 int type_1_command(int command, int bytes, uch * status) /* returns info */
     /* [previous][next][first][last][top][bottom][index][help] */
 382 {
 383   int i;
 384   if (type_0_command(command,0)) return -1;
 385   for(i=0; i<bytes; i++) 
 386     status[i] = send_receive(c_gimme);
 387   return 0;
 388 }  
 389 
 390 /* This function resets the adapter card. We'd better not do this too */
 391 /* often, because it tends to generate `lost interrupts.' */
 392 void reset_cm260(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 393 {
 394   outw(dc_normal | dc_initialize | READ_AHEAD, r_data_control);
 395   udelay(10);                   /* 3.3 mu sec minimum */
 396   outw(dc_normal | READ_AHEAD, r_data_control);
 397 }
 398 
 399 /* fsm: frame-sec-min from linear address */
 400 void fsm(int lba, uch * fsm) 
     /* [previous][next][first][last][top][bottom][index][help] */
 401 {
 402   fsm[0] = lba % 75;
 403   lba /= 75; lba += 2;
 404   fsm[1] = lba % 60; fsm[2] = lba / 60;
 405 }
 406 
 407 inline int fsm2lba(uch * fsm) 
     /* [previous][next][first][last][top][bottom][index][help] */
 408 {
 409   return fsm[0] + 75*(fsm[1]-2 + 60*fsm[2]);
 410 }
 411 
 412 inline int f_s_m2lba(uch f, uch s, uch m)
     /* [previous][next][first][last][top][bottom][index][help] */
 413 {
 414   return f + 75*(s-2 + 60*m);
 415 }
 416 
 417 int start_read(int start) 
     /* [previous][next][first][last][top][bottom][index][help] */
 418 {
 419   uch read_sector[4] = {c_read_data, };
 420   int i, e;
 421 
 422   fsm(start, &read_sector[1]);
 423   for (i=0; i<4; i++) 
 424     if (read_sector[i] != (e=send_receive(read_sector[i]))) {
 425       debug(("read_sector: %x echoes %x\n", read_sector[i], e));
 426       stats(echo);
 427       return -1;
 428     }
 429   return 0;
 430 }
 431 
 432 int stop_read(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 433 {
 434   type_0_command(c_stop,0);
 435   if(receive_echo() != 0xff) {
 436     debug(("c_stop didn't send 0xff\n"));
 437     stats(stop_0xff);
 438     return -1;
 439   }
 440   return 0;
 441 }  
 442 
 443 /* This function starts to read sectors in adapter memory, the
 444    interrupt routine should stop the read. In fact, the bottom_half
 445    routine takes care of this. Set a flag `background' in the cd
 446    struct to indicate the process. */
 447 
 448 int read_background(int start, int reading)
     /* [previous][next][first][last][top][bottom][index][help] */
 449 {
 450   if (cd->background) return -1; /* can't do twice */
 451   outw(dc_normal | BACK_AHEAD, r_data_control);
 452   if (!reading && start_read(start)) return -2;
 453   cd->adapter_first = cd->adapter_last = start; 
 454   cd->background = 1;           /* flag a read is going on */
 455   return 0;
 456 }
 457 
 458 int read_sector(int start)
     /* [previous][next][first][last][top][bottom][index][help] */
 459 {
 460   if (cd->background) {
 461     cd->background=0;
 462     cd->adapter_last = -1;      /* invalidate adapter memory */
 463     stop_read();
 464   }
 465   cd->fifo_overflowed=0;
 466   reset_cm260();                /* empty fifo etc. */
 467   if (start_read(start)) return -1;
 468   if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
 469     debug(("Read timed out sector 0x%x\n", start));
 470     stats(read_timeout);
 471     stop_read();
 472     return -3;          
 473   }
 474   insw(r_fifo_output_buffer, cd->sector, READ_AHEAD*RAW_SECTOR_SIZE/2);
 475   if (read_background(start+READ_AHEAD,1)) stats(read_background);
 476   cd->sector_first = start; cd->sector_last = start+READ_AHEAD;
 477   stats(read_restarted);
 478   return 0;
 479 }
 480 
 481 /* The function of bottom-half is to send a stop command to the drive
 482    This isn't easy because the routine is not `owned' by any process;
 483    we can't go to sleep! The variable cd->background gives the status:
 484    0 no read pending
 485    1 a read is pending
 486    2 c_stop waits for write_buffer_empty
 487    3 c_stop waits for receive_buffer_full: echo
 488    4 c_stop waits for receive_buffer_full: 0xff
 489 */
 490 
 491 void cm206_bh(void * unused)
     /* [previous][next][first][last][top][bottom][index][help] */
 492 {
 493   debug(("bh: %d\n", cd->background));
 494   switch (cd->background) {
 495   case 1:
 496     stats(bh);
 497     if (!(cd->intr_ls & ls_transmitter_buffer_empty)) {
 498       cd->command = c_stop;
 499       outw(dc_mask_sync_error | dc_no_stop_on_error | 
 500            (inw(r_data_status) & 0x7f), r_data_control);
 501       cd->background=2;
 502       break;                    /* we'd better not time-out here! */
 503     }
 504     else outw(c_stop, r_uart_transmit);
 505     /* fall into case 2: */
 506   case 2:                       
 507     /* the write has been satisfied by interrupt routine */
 508     cd->background=3;
 509     break;
 510   case 3:
 511     if (cd->intr_ur != c_stop) {
 512       debug(("cm206_bh: c_stop echoed 0x%x\n", cd->intr_ur));
 513       stats(echo);
 514     }
 515     cd->background++;
 516     break;
 517   case 4:
 518     if (cd->intr_ur != 0xff) {
 519       debug(("cm206_bh: c_stop reacted with 0x%x\n", cd->intr_ur));
 520       stats(stop_0xff);
 521     }
 522     cd->background=0;
 523   }
 524 }
 525 
 526 void get_drive_status(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 527 {
 528   uch status[2];
 529   type_1_command(c_drive_status, 2, status); /* this might be done faster */
 530   cd->dsb=status[0];
 531   cd->cc=status[1];
 532 }
 533 
 534 void get_disc_status(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 535 {
 536   if (type_1_command(c_disc_status, 7, cd->disc_status)) {
 537     debug(("get_disc_status: error\n"));
 538   }
 539 }
 540 
 541 static int cm206_open(struct inode *ip, struct file *fp)
     /* [previous][next][first][last][top][bottom][index][help] */
 542 {
 543   if (!cd->openfiles) {
 544     cd->background=0;
 545     reset_cm260();
 546     cd->adapter_last = -1;      /* invalidate adapter memory */
 547     cd->sector_last = -1;
 548     get_drive_status();
 549     if (cd->dsb & dsb_tray_not_closed) {
 550       int i=0;
 551       type_0_command(c_close_tray, 1);
 552       while (i++<10 && cd->dsb & dsb_drive_not_ready) {
 553         cm206_delay(100);
 554         get_drive_status();
 555       }
 556     }
 557     if (cd->dsb & (dsb_not_useful)) return -EIO;
 558     if (!(cd->dsb & dsb_disc_present)) return -ENODATA;
 559     if (cd->dsb & dsb_possible_media_change) {
 560       memset(cd->toc, 0, sizeof(cd->toc));
 561       memset(cd->audio_status, 0, sizeof(cd->audio_status));
 562     }
 563     get_disc_status();
 564     type_0_command(c_lock_tray,1);
 565     if (!(cd->dsb & dsb_tray_locked)) {
 566       debug(("Couldn't lock tray\n"));
 567     }
 568 #if 0
 569     if (!(DISC_STATUS & cds_all_audio))
 570       read_background(16,0);    /* do something useful */
 571 #endif
 572   }
 573   ++cd->openfiles; MOD_INC_USE_COUNT;
 574   stats(open);
 575   return 0;
 576 }
 577 
 578 static void cm206_release(struct inode *ip, struct file *fp)
     /* [previous][next][first][last][top][bottom][index][help] */
 579 {
 580   if (cd->openfiles==1) {
 581     if (cd->background) {
 582       cd->background=0;
 583       stop_read();
 584     }
 585     type_0_command(c_unlock_tray,1);
 586     cd->sector_last = -1;       /* Make our internal buffer invalid */
 587     FIRST_TRACK = 0;    /* No valid disc status */
 588     sync_dev(ip -> i_rdev);     /* These two lines are stolen */
 589     invalidate_buffers(ip -> i_rdev);
 590   }
 591   --cd->openfiles; MOD_DEC_USE_COUNT;
 592 }
 593 
 594 /* Empty buffer empties $sectors$ sectors of the adapter card buffer,
 595  * and then reads a sector in kernel memory.  */
 596 void empty_buffer(int sectors) 
     /* [previous][next][first][last][top][bottom][index][help] */
 597 {
 598   while (sectors>=0) {
 599     insw(r_fifo_output_buffer, cd->sector + cd->fifo_overflowed, 
 600          RAW_SECTOR_SIZE/2 - cd->fifo_overflowed);
 601     --sectors;
 602     ++cd->adapter_first;        /* update the current adapter sector */
 603     cd->fifo_overflowed=0;      /* reset overflow bit */
 604     stats(sector_transferred);
 605   } 
 606   cd->sector_first=cd->adapter_first-1;
 607   cd->sector_last=cd->adapter_first; /* update the buffer sector */
 608 }
 609 
 610 /* try_adapter. This function determines of the requested sector is is
 611    in adapter memory, or will appear there soon. Returns 0 upon
 612    success */
 613 int try_adapter(int sector)
     /* [previous][next][first][last][top][bottom][index][help] */
 614 {
 615   if (cd->adapter_first <= sector && sector < cd->adapter_last) { 
 616     /* sector is in adapter memory */
 617     empty_buffer(sector - cd->adapter_first);
 618     return 0;
 619   }
 620   else if (cd->background==1 && cd->adapter_first <= sector
 621            && sector < cd->adapter_first+cd->max_sectors) {
 622     /* a read is going on, we can wait for it */
 623     cd->wait_back=1;
 624     while (sector >= cd->adapter_last) {
 625       if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
 626         debug(("Timed out during background wait: %d %d %d %d\n", sector, 
 627                cd->adapter_last, cd->adapter_first, cd->background));
 628         stats(back_read_timeout);
 629         cd->wait_back=0;
 630         return -1;
 631       }
 632     }
 633     cd->wait_back=0;
 634     empty_buffer(sector - cd->adapter_first);
 635     return 0;
 636   }
 637   else return -2;
 638 }
 639 
 640 /* This is not a very smart implementation. We could optimize for 
 641    consecutive block numbers. I'm not convinced this would really
 642    bring down the processor load. */
 643 static void do_cm206_request(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 644 {
 645   long int i, cd_sec_no;
 646   int quarter, error; 
 647   uch * source, * dest;
 648   
 649   while(1) {     /* repeat until all requests have been satisfied */
 650     INIT_REQUEST;
 651     if (CURRENT == NULL || CURRENT->rq_status == RQ_INACTIVE)
 652       return;
 653     if (CURRENT->cmd != READ) {
 654       debug(("Non-read command %d on cdrom\n", CURRENT->cmd));
 655       end_request(0);
 656       continue;
 657     }
 658     error=0;
 659     for (i=0; i<CURRENT->nr_sectors; i++) {
 660       cd_sec_no = (CURRENT->sector+i)/4; /* 4 times 512 bytes */
 661       quarter = (CURRENT->sector+i) % 4; 
 662       dest = CURRENT->buffer + i*512;
 663       /* is already in buffer memory? */
 664       if (cd->sector_first <= cd_sec_no && cd_sec_no < cd->sector_last) {
 665         source = ((uch *) cd->sector) + 16 + 
 666           quarter*512 + (cd_sec_no-cd->sector_first)*RAW_SECTOR_SIZE;
 667         memcpy(dest, source, 512); 
 668       }
 669       else if (!try_adapter(cd_sec_no) || !read_sector(cd_sec_no)) {
 670         source =  ((uch *) cd->sector)+16+quarter*512;
 671         memcpy(dest, source, 512); 
 672       }
 673       else {
 674         error=1;
 675       }
 676     }
 677     end_request(!error);
 678   }
 679 }
 680 
 681 int get_multi_session_info(struct cdrom_multisession * mssp)
     /* [previous][next][first][last][top][bottom][index][help] */
 682 {
 683   if (!FIRST_TRACK) get_disc_status();
 684   if (mssp) {
 685     if (DISC_STATUS & cds_multi_session) { /* multi-session */
 686       if (mssp->addr_format == CDROM_LBA)
 687         mssp->addr.lba = fsm2lba(&cd->disc_status[3]);
 688       else {
 689         mssp->addr.msf.frame = cd->disc_status[3];
 690         mssp->addr.msf.second = cd->disc_status[4];
 691         mssp->addr.msf.minute = cd->disc_status[5];
 692       }
 693       mssp->xa_flag = 1;
 694     } else {
 695       mssp->xa_flag = 0;
 696     }
 697     return 1;
 698   }
 699   return 0;
 700 }
 701 
 702 /* Audio support. I've tried very hard, but the cm206 drive doesn't 
 703    seem to have a get_toc (table-of-contents) function, while i'm
 704    pretty sure it must read the toc upon disc insertion. Therefore
 705    this function has been implemented through a binary search 
 706    strategy. All track starts that happen to be found are stored in
 707    cd->toc[], for future use. 
 708 
 709    I've spent a whole day on a bug that only shows under Workman---
 710    I don't get it. Tried everything, nothing works. If workman asks
 711    for track# 0xaa, it'll get the wrong time back. Any other program
 712    receives the correct value. I'm stymied.
 713 */
 714 
 715 /* seek seeks to address lba. It does wait to arrive there. */
 716 void seek(int lba)
     /* [previous][next][first][last][top][bottom][index][help] */
 717 {
 718   int i;
 719   uch seek_command[4]={c_seek, };
 720   
 721   fsm(lba, &seek_command[1]);
 722   for (i=0; i<4; i++) type_0_command(seek_command[i], 0);
 723   cd->dsb = wait_dsb();
 724 }
 725 
 726 uch bcdbin(unsigned char bcd)   /* stolen from mcd.c! */
     /* [previous][next][first][last][top][bottom][index][help] */
 727 {
 728   return (bcd >> 4)*10 + (bcd & 0xf);
 729 } 
 730 
 731 inline uch normalize_track(uch track) 
     /* [previous][next][first][last][top][bottom][index][help] */
 732 {
 733   if (track<1) return 1;
 734   if (track>LAST_TRACK) return LAST_TRACK+1;
 735   return track;
 736 }
 737 
 738 /* This function does a binary search for track start. It records all
 739  * tracks seen in the process. Input $track$ must be between 1 and
 740  * #-of-tracks+1 */
 741 int get_toc_lba(uch track)
     /* [previous][next][first][last][top][bottom][index][help] */
 742 {
 743   int max=74*60*75-150, min=0;
 744   int i, lba, l, old_lba=0;
 745   uch * q = cd->q;
 746   uch ct;                       /* current track */
 747   int binary=0;
 748   const skip = 3*60*75;
 749 
 750   for (i=track; i>0; i--) if (cd->toc[i].track) {
 751     min = fsm2lba(cd->toc[i].fsm);
 752     break;
 753   }
 754   lba = min + skip;             /* 3 minutes */
 755   do {
 756     seek(lba); 
 757     type_1_command(c_read_current_q, 10, q);
 758     ct = normalize_track(q[1]);
 759     if (!cd->toc[ct].track) {
 760       l = q[9]-bcdbin(q[5]) + 75*(q[8]-bcdbin(q[4])-2 + 
 761                                   60*(q[7]-bcdbin(q[3])));
 762       cd->toc[ct].track=q[1];   /* lead out still 0xaa */
 763       fsm(l, cd->toc[ct].fsm);
 764       cd->toc[ct].q0 = q[0];    /* contains adr and ctrl info */
 765 /*
 766       if (ct==LAST_TRACK+1) 
 767         printk("Leadout %x %x %x %x %d %d %d \n", q[1], q[3], q[4], q[5],
 768                q[7], q[8], q[9]);
 769 */
 770       if (ct==track) return l;
 771     }
 772     old_lba=lba;
 773     if (binary) {
 774       if (ct < track) min = lba; else max = lba;
 775       lba = (min+max)/2; 
 776     } else {
 777       if(ct < track) lba += skip;
 778       else {
 779         binary=1;
 780         max = lba; min = lba - skip;
 781         lba = (min+max)/2;
 782       }
 783     }
 784   } while (lba!=old_lba);
 785   return lba;
 786 }
 787 
 788 void update_toc_entry(uch track) 
     /* [previous][next][first][last][top][bottom][index][help] */
 789 {
 790   track = normalize_track(track);
 791   if (!cd->toc[track].track) get_toc_lba(track);
 792 }
 793 
 794 int read_toc_header(struct cdrom_tochdr * hp)
     /* [previous][next][first][last][top][bottom][index][help] */
 795 {
 796   if (!FIRST_TRACK) get_disc_status();
 797   if (hp && DISC_STATUS & cds_all_audio) { /* all audio */
 798     int i;
 799     hp->cdth_trk0 = FIRST_TRACK;
 800     hp->cdth_trk1 = LAST_TRACK;
 801     cd->toc[1].track=1;         /* fill in first track position */
 802     for (i=0; i<3; i++) cd->toc[1].fsm[i] = cd->disc_status[3+i];
 803     update_toc_entry(LAST_TRACK+1);             /* find most entries */
 804     return 1;
 805   }
 806   return 0;
 807 }  
 808 
 809 void play_from_to_msf(struct cdrom_msf* msfp)
     /* [previous][next][first][last][top][bottom][index][help] */
 810 {
 811   uch play_command[] = {c_play, 
 812            msfp->cdmsf_frame0, msfp->cdmsf_sec0, msfp->cdmsf_min0,
 813            msfp->cdmsf_frame1, msfp->cdmsf_sec1, msfp->cdmsf_min1, 2, 2};
 814   int i;
 815   for (i=0; i<9; i++) type_0_command(play_command[i], 0);
 816   for (i=0; i<3; i++) 
 817     PLAY_TO.fsm[i] = play_command[i+4];
 818   PLAY_TO.track = 0;            /* say no track end */
 819   cd->dsb = wait_dsb();
 820 }  
 821 
 822 void play_from_to_track(int from, int to)
     /* [previous][next][first][last][top][bottom][index][help] */
 823 {
 824   uch play_command[8] = {c_play, };
 825   int i;
 826 
 827   if (from==0) {                /* continue paused play */
 828     for (i=0; i<3; i++) { 
 829       play_command[i+1] = cd->audio_status[i+2];
 830       play_command[i+4] = PLAY_TO.fsm[i];
 831     }
 832   } else {
 833     update_toc_entry(from); update_toc_entry(to+1);
 834     for (i=0; i<3; i++) {
 835       play_command[i+1] = cd->toc[from].fsm[i];
 836       PLAY_TO.fsm[i] = play_command[i+4] = cd->toc[to+1].fsm[i];
 837     }
 838     PLAY_TO.track = to; 
 839   }
 840   for (i=0; i<7; i++) type_0_command(play_command[i],0);
 841   for (i=0; i<2; i++) type_0_command(0x2, 0); /* volume */
 842   cd->dsb = wait_dsb();
 843 }
 844 
 845 int get_current_q(struct cdrom_subchnl * qp)
     /* [previous][next][first][last][top][bottom][index][help] */
 846 {
 847   int i;
 848   uch * q = cd->q;
 849   if (type_1_command(c_read_current_q, 10, q)) return 0;
 850 /*  q[0] = bcdbin(q[0]); Don't think so! */
 851   for (i=2; i<6; i++) q[i]=bcdbin(q[i]); 
 852   qp->cdsc_adr = q[0] & 0xf; qp->cdsc_ctrl = q[0] >> 4; /* from mcd.c */
 853   qp->cdsc_trk = q[1];  qp->cdsc_ind = q[2];
 854   if (qp->cdsc_format == CDROM_MSF) {
 855     qp->cdsc_reladdr.msf.minute = q[3];
 856     qp->cdsc_reladdr.msf.second = q[4];
 857     qp->cdsc_reladdr.msf.frame = q[5];
 858     qp->cdsc_absaddr.msf.minute = q[7];
 859     qp->cdsc_absaddr.msf.second = q[8];
 860     qp->cdsc_absaddr.msf.frame = q[9];
 861   } else {
 862     qp->cdsc_reladdr.lba = f_s_m2lba(q[5], q[4], q[3]);
 863     qp->cdsc_absaddr.lba = f_s_m2lba(q[9], q[8], q[7]);
 864   }
 865   get_drive_status();
 866   if (cd->dsb & dsb_play_in_progress) 
 867     qp->cdsc_audiostatus = CDROM_AUDIO_PLAY ;
 868   else if (PAUSED) 
 869     qp->cdsc_audiostatus = CDROM_AUDIO_PAUSED;
 870   else qp->cdsc_audiostatus = CDROM_AUDIO_NO_STATUS;
 871   return 1;
 872 }
 873 
 874 void get_toc_entry(struct cdrom_tocentry * ep)
     /* [previous][next][first][last][top][bottom][index][help] */
 875 {
 876   uch track = normalize_track(ep->cdte_track);
 877   update_toc_entry(track);
 878   if (ep->cdte_format == CDROM_MSF) {
 879     ep->cdte_addr.msf.frame = cd->toc[track].fsm[0];
 880     ep->cdte_addr.msf.second = cd->toc[track].fsm[1];
 881     ep->cdte_addr.msf.minute = cd->toc[track].fsm[2];
 882   } 
 883   else ep->cdte_addr.lba = fsm2lba(cd->toc[track].fsm);
 884   ep->cdte_adr = cd->toc[track].q0 & 0xf; 
 885   ep->cdte_ctrl = cd->toc[track].q0 >> 4;
 886   ep->cdte_datamode=0;
 887 }
 888   
 889 /* Ioctl. I have made the statistics accessible through an ioctl
 890    call. The constant is defined in cm206.h, it shouldn't clash with
 891    the standard Linux ioctls. Multisession info is gathered at
 892    run-time, this may turn out to be slow. */
 893 
 894 static int cm206_ioctl(struct inode * inode, struct file * file, 
     /* [previous][next][first][last][top][bottom][index][help] */
 895                        unsigned int cmd, unsigned long arg)
 896 {
 897   switch (cmd) {
 898 #ifdef STATISTICS
 899   case CM206CTL_GET_STAT:
 900     if (arg >= NR_STATS) return -EINVAL;
 901     else return cd->stats[arg];
 902   case CM206CTL_GET_LAST_STAT:
 903     if (arg >= NR_STATS) return -EINVAL;
 904     else return cd->last_stat[arg];
 905 #endif    
 906   case CDROMMULTISESSION: {
 907     struct cdrom_multisession ms_info;
 908     int st;
 909     stats(ioctl_multisession);
 910 
 911     st=verify_area(VERIFY_WRITE, (void *) arg, 
 912                    sizeof(struct cdrom_multisession));
 913     if (st) return (st);
 914     memcpy_fromfs(&ms_info, (struct cdrom_multisession *) arg,
 915                   sizeof(struct cdrom_multisession));
 916     get_multi_session_info(&ms_info);
 917     memcpy_tofs((struct cdrom_multisession *) arg, &ms_info, 
 918                   sizeof(struct cdrom_multisession));
 919     return 0;
 920   }
 921   case CDROMRESET:              /* If needed, it's probably too late anyway */
 922     stop_read();
 923     reset_cm260();
 924     outw(dc_normal | dc_break | READ_AHEAD, r_data_control);
 925     udelay(1000);               /* 750 musec minimum */
 926     outw(dc_normal | READ_AHEAD, r_data_control);
 927     cd->sector_last = -1;       /* flag no data buffered */
 928     cd->adapter_last = -1;    
 929     return 0;
 930   }
 931 
 932   get_drive_status();
 933   if (cd->dsb & (dsb_drive_not_ready | dsb_tray_not_closed) )
 934     return -EAGAIN; 
 935 
 936   switch (cmd) {
 937   case CDROMREADTOCHDR: {
 938     struct cdrom_tochdr header;
 939     int st;
 940 
 941     st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(header));
 942     if (st) return (st);
 943     if (read_toc_header(&header)) {
 944       memcpy_tofs((struct cdrom_tochdr *) arg, &header, sizeof(header));
 945       return 0;
 946     }
 947     else return -ENODATA;
 948   }
 949   case CDROMREADTOCENTRY: {     
 950     struct cdrom_tocentry entry;
 951     int st;
 952 
 953     st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(entry));
 954     if (st) return (st);
 955     memcpy_fromfs(&entry, (struct cdrom_tocentry *) arg, sizeof entry);
 956     get_toc_entry(&entry);
 957     memcpy_tofs((struct cdrom_tocentry *) arg, &entry, sizeof entry);
 958     return 0;
 959   }
 960   case CDROMPLAYMSF: {
 961     struct cdrom_msf msf;
 962     int st;
 963 
 964     st=verify_area(VERIFY_READ, (void *) arg, sizeof(msf));
 965     if (st) return (st);
 966     memcpy_fromfs(&msf, (struct cdrom_mdf *) arg, sizeof msf);
 967     play_from_to_msf(&msf);
 968     return 0;
 969   }
 970   case CDROMPLAYTRKIND: {
 971     struct cdrom_ti track_index;
 972     int st;
 973 
 974     st=verify_area(VERIFY_READ, (void *) arg, sizeof(track_index));
 975     if (st) return (st);
 976     memcpy_fromfs(&track_index, (struct cdrom_ti *) arg, sizeof(track_index));
 977     play_from_to_track(track_index.cdti_trk0, track_index.cdti_trk1);
 978     return 0;
 979   }
 980   case CDROMSTOP: 
 981     PAUSED=0;
 982     if (cd->dsb & dsb_play_in_progress) return type_0_command(c_stop, 1);
 983     return 0;
 984   case CDROMPAUSE: 
 985     if (cd->dsb & dsb_play_in_progress) {
 986       type_0_command(c_stop, 1);
 987       type_1_command(c_audio_status, 5, cd->audio_status);
 988       PAUSED=1; /* say we're paused */
 989     }
 990     return 0;
 991   case CDROMRESUME:
 992     if (PAUSED) play_from_to_track(0,0);
 993     PAUSED=0;
 994     return 0;
 995   case CDROMEJECT:
 996     PAUSED=0;
 997     if (cd->openfiles == 1) {   /* Must do an open before an eject! */
 998       type_0_command(c_open_tray,1);
 999       memset(cd->toc, 0, sizeof(cd->toc));
1000       memset(cd->disc_status, 0, sizeof(cd->disc_status));
1001       return 0;
1002     }
1003     else return -EBUSY;
1004   case CDROMSTART:
1005   case CDROMVOLCTRL:
1006     return 0;
1007   case CDROMSUBCHNL: {
1008     struct cdrom_subchnl q;
1009     int st;
1010 
1011     st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(q));
1012     if (st) return (st);
1013     memcpy_fromfs(&q, (struct cdrom_subchnl *) arg, sizeof q);
1014     if (get_current_q(&q)) {
1015       memcpy_tofs((struct cdrom_subchnl *) arg, &q, sizeof q);
1016       return 0;
1017     }
1018     else return -cmd;
1019   }
1020   case CDROM_GET_UPC: {
1021     uch upc[10];
1022     int st;
1023 
1024     st=verify_area(VERIFY_WRITE, (void *) arg, 8);
1025     if (st) return (st);
1026     if (type_1_command(c_read_upc, 10, upc)) return -EIO;
1027     memcpy_tofs((uch *) arg, &upc[1], 8);
1028     return 0;
1029   } 
1030   default:
1031     debug(("Unknown ioctl call 0x%x\n", cmd));
1032     return -EINVAL;
1033   }
1034 }     
1035 
1036 /* from lmscd.c */
1037 static struct file_operations cm206_fops = {
1038         NULL,                   /* lseek */
1039         block_read,             /* read - general block-dev read */
1040         block_write,            /* write - general block-dev write */
1041         NULL,                   /* readdir */
1042         NULL,                   /* select */
1043         cm206_ioctl,            /* ioctl */
1044         NULL,                   /* mmap */
1045         cm206_open,             /* open */
1046         cm206_release,          /* release */
1047         NULL,                   /* fsync */
1048         NULL,                   /* fasync */
1049         NULL,                   /* media_change */
1050         NULL                    /* revalidate */
1051 };
1052 
1053 /* This routine gets called during init if thing go wrong, can be used
1054  * in cleanup_module as well. */
1055 void cleanup(int level)
     /* [previous][next][first][last][top][bottom][index][help] */
1056 {
1057   switch (level) {
1058   case 4: 
1059     if (unregister_blkdev(MAJOR_NR, "cm206")) {
1060       printk("Can't unregister cm206\n");
1061       return;
1062     }
1063   case 3: 
1064     free_irq(cm206_irq);
1065   case 2: 
1066   case 1: 
1067     kfree(cd);
1068     release_region(cm206_base, 16);
1069   default:
1070   }
1071 }
1072 
1073 /* This function probes for the adapter card. It returns the base
1074    address if it has found the adapter card. One can specify a base 
1075    port to probe specifically, or 0 which means span all possible
1076    bases. 
1077 
1078    Linus says it is too dangerous to use writes for probing, so we
1079    stick with pure reads for a while. Hope that 8 possible ranges,
1080    check_region, 15 bits of one port and 6 of another make things
1081    likely enough to accept the region on the first hit...
1082  */
1083 int probe_base_port(int base)
     /* [previous][next][first][last][top][bottom][index][help] */
1084 {
1085   int b=0x300, e=0x370;         /* this is the range of start addresses */
1086   volatile int fool;
1087 #if 0
1088   const pattern1=0x65, pattern2=0x1a;
1089 #endif
1090 
1091   if (base) b=e=base;
1092   for (base=b; base<=e; base += 0x10) {
1093     if (check_region(base, 0x10)) continue;
1094     fool = inw(base+2);         /* empty possibly uart_receive_buffer */
1095     if((inw(base+6) & 0xffef) != 0x0001 || /* line_status */
1096        (inw(base) & 0xad00) != 0) /* data status */
1097       continue;
1098 #if 0                           /* writes... dangerous... */
1099     outw(dc_normal | pattern1, base+8); 
1100     if ((inw(base) & 0x7f) != pattern1) continue;
1101     outw(dc_normal | pattern2, base+8);
1102     if ((inw(base) & 0x7f) != pattern2) continue;
1103     outw(dc_normal | READ_AHEAD, base+8);
1104 #endif
1105     return(base);
1106   }
1107   return 0;
1108 }
1109 
1110 #if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
1111 /* Probe for irq# nr. If nr==0, probe for all possible irq's. */
1112 int probe_irq(int nr) {
     /* [previous][next][first][last][top][bottom][index][help] */
1113   int irqs, irq;
1114   outw(dc_normal | READ_AHEAD, r_data_control); /* disable irq-generation */
1115   sti(); 
1116   irqs = probe_irq_on();
1117   reset_cm260();                /* causes interrupt */
1118   udelay(10);                   /* wait for it */
1119   irq = probe_irq_off(irqs);
1120   outw(dc_normal | READ_AHEAD, r_data_control); /* services interrupt */
1121   if (nr && irq!=nr && irq>0) return 0; /* wrong interrupt happened */
1122   else return irq;
1123 }
1124 #endif
1125 
1126 #ifdef MODULE
1127 
1128 static int cm206[2] = {0,0};    /* for compatible `insmod' parameter passing */
1129 void parse_options(void) 
     /* [previous][next][first][last][top][bottom][index][help] */
1130 {
1131   int i;
1132   for (i=0; i<2; i++) {
1133     if (0x300 <= cm206[i] && i<= 0x370 && cm206[i] % 0x10 == 0) {
1134       cm206_base = cm206[i];
1135       auto_probe=0;
1136     }
1137     else if (3 <= cm206[i] && cm206[i] <= 15) {
1138       cm206_irq = cm206[i];
1139       auto_probe=0;
1140     }
1141   }
1142 }
1143 
1144 #define cm206_init init_module
1145 
1146 #endif MODULE
1147 
1148 
1149 int cm206_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1150 {
1151   uch e=0;
1152   long int size=sizeof(struct cm206_struct);
1153 
1154   printk("cm206: v" VERSION);
1155 #if defined(MODULE) 
1156   parse_options();
1157 #if !defined(AUTO_PROBE_MODULE)
1158    auto_probe=0;
1159 #endif
1160 #endif
1161   cm206_base = probe_base_port(auto_probe ? 0 : cm206_base);
1162   if (!cm206_base) {
1163     printk(" can't find adapter!\n");
1164     return -EIO;
1165   }
1166   printk(" adapter at 0x%x", cm206_base);
1167   request_region(cm206_base, 16, "cm206");
1168   cd = (struct cm206_struct *) kmalloc(size, GFP_KERNEL);
1169   if (!cd) return -EIO;
1170   /* Now we have found the adaptor card, try to reset it. As we have
1171    * found out earlier, this process generates an interrupt as well,
1172    * so we might just exploit that fact for irq probing! */
1173 #if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
1174   cm206_irq = probe_irq(auto_probe ? 0 : cm206_irq);    
1175   if (cm206_irq<=0) {
1176     printk("can't find IRQ!\n");
1177     cleanup(1);
1178     return -EIO;
1179   }
1180   else printk(" IRQ %d found\n", cm206_irq);
1181 #else
1182   reset_cm260();
1183   printk(" using IRQ %d\n", cm206_irq);
1184 #endif
1185   if (send_receive_polled(c_drive_configuration) != c_drive_configuration) 
1186     {
1187       printk(" drive not there\n");
1188       cleanup(1);
1189       return -EIO;
1190     }
1191   e = send_receive_polled(c_gimme);
1192   printk("Firmware revision %d", e & dcf_revision_code);
1193   if (e & dcf_transfer_rate) printk(" double");
1194   else printk(" single");
1195   printk(" speed drive");
1196   if (e & dcf_motorized_tray) printk(", motorized tray");
1197   if (request_irq(cm206_irq, cm206_interrupt, 0, "cm206")) {
1198     printk("\nUnable to reserve IRQ---aborted\n");
1199     cleanup(2);
1200     return -EIO;
1201   }
1202   printk(".\n");
1203   if (register_blkdev(MAJOR_NR, "cm206", &cm206_fops) != 0) {
1204     printk("Cannot register for major %d!\n", MAJOR_NR);
1205     cleanup(3);
1206     return -EIO;
1207   }
1208   blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1209   read_ahead[MAJOR_NR] = 16;    /* reads ahead what? */
1210   bh_base[CM206_BH].routine = cm206_bh;
1211   enable_bh(CM206_BH);
1212 
1213   memset(cd, 0, sizeof(*cd));   /* give'm some reasonable value */
1214   cd->sector_last = -1;         /* flag no data buffered */
1215   cd->adapter_last = -1;
1216   cd->timer.function = cm206_timeout;
1217   cd->max_sectors = (inw(r_data_status) & ds_ram_size) ? 24 : 97;
1218   printk("%d kB adapter memory available, "  
1219          " %ld bytes kernel memory used.\n", cd->max_sectors*2, size);
1220   return 0;
1221 }
1222 
1223 #ifdef MODULE
1224 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1225 {
1226   cleanup(4);
1227   printk("cm206 removed\n");
1228 }
1229       
1230 #else MODULE
1231 
1232 /* This setup function accepts either `auto' or numbers in the range
1233  * 3--11 (for irq) or 0x300--0x370 (for base port) or both. */
1234 void cm206_setup(char *s, int *p)
     /* [previous][next][first][last][top][bottom][index][help] */
1235 {
1236   int i;
1237   if (!strcmp(s, "auto")) auto_probe=1;
1238   for(i=1; i<=p[0]; i++) {
1239     if (0x300 <= p[i] && i<= 0x370 && p[i] % 0x10 == 0) {
1240       cm206_base = p[i];
1241       auto_probe = 0;
1242     }
1243     else if (3 <= p[i] && p[i] <= 15) {
1244       cm206_irq = p[i];
1245       auto_probe = 0;
1246     }
1247   }
1248 }
1249 #endif MODULE

/* [previous][next][first][last][top][bottom][index][help] */