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

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