root/drivers/block/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. init_module
  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 #include <linux/malloc.h>
  88 #ifndef CONFIG_MODVERSIONS
  89 char kernel_version[]=UTS_RELEASE;
  90 #endif
  91 #else 
  92 #define MOD_INC_USE_COUNT
  93 #define MOD_DEC_USE_COUNT
  94 #endif MODULE
  95 
  96 #include <linux/errno.h>        /* These include what we really need */
  97 #include <linux/delay.h>
  98 #include <linux/string.h>
  99 #include <linux/sched.h>
 100 #include <linux/interrupt.h>
 101 #include <linux/timer.h>
 102 #include <linux/cdrom.h>
 103 #include <linux/ioport.h>
 104 #include <linux/mm.h>
 105 
 106 #include <asm/io.h>
 107 
 108 #define MAJOR_NR CM206_CDROM_MAJOR
 109 #include "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 300        /* measured in jiffies (10 ms) */
 130 #define UART_TIMEOUT 5
 131 #define DSB_TIMEOUT 700         /* 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 conviced 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->dev == -1) return;
 652     if (CURRENT->cmd != READ) {
 653       debug(("Non-read command %d on cdrom\n", CURRENT->cmd));
 654       end_request(0);
 655       continue;
 656     }
 657     error=0;
 658     for (i=0; i<CURRENT->nr_sectors; i++) {
 659       cd_sec_no = (CURRENT->sector+i)/4; /* 4 times 512 bytes */
 660       quarter = (CURRENT->sector+i) % 4; 
 661       dest = CURRENT->buffer + i*512;
 662       /* is already in buffer memory? */
 663       if (cd->sector_first <= cd_sec_no && cd_sec_no < cd->sector_last) {
 664         source = ((uch *) cd->sector) + 16 + 
 665           quarter*512 + (cd_sec_no-cd->sector_first)*RAW_SECTOR_SIZE;
 666         memcpy(dest, source, 512); 
 667       }
 668       else if (!try_adapter(cd_sec_no) || !read_sector(cd_sec_no)) {
 669         source =  ((uch *) cd->sector)+16+quarter*512;
 670         memcpy(dest, source, 512); 
 671       }
 672       else {
 673         error=1;
 674       }
 675     }
 676     end_request(!error);
 677   }
 678 }
 679 
 680 int get_multi_session_info(struct cdrom_multisession * mssp)
     /* [previous][next][first][last][top][bottom][index][help] */
 681 {
 682   if (!FIRST_TRACK) get_disc_status();
 683   if (mssp) {
 684     if (DISC_STATUS & cds_multi_session) { /* multi-session */
 685       if (mssp->addr_format == CDROM_LBA)
 686         mssp->addr.lba = fsm2lba(&cd->disc_status[3]);
 687       else {
 688         mssp->addr.msf.frame = cd->disc_status[3];
 689         mssp->addr.msf.second = cd->disc_status[4];
 690         mssp->addr.msf.minute = cd->disc_status[5];
 691       }
 692       mssp->xa_flag = 1;
 693     } else {
 694       mssp->xa_flag = 0;
 695     }
 696     return 1;
 697   }
 698   return 0;
 699 }
 700 
 701 /* Audio support. I've tried very hard, but the cm206 drive doesn't 
 702    seem to have a get_toc (table-of-contents) function, while i'm
 703    pretty sure it must read the toc upon disc insertion. Therefore
 704    this function has been implemented through a binary search 
 705    strategy. All track starts that happen to be found are stored in
 706    cd->toc[], for future use. 
 707 
 708    I've spent a whole day on a bug that only shows under Workman---
 709    I don't get it. Tried everything, nothing works. If workman asks
 710    for track# 0xaa, it'll get the wrong time back. Any other program
 711    receives the correct value. I'm stymied.
 712 */
 713 
 714 /* seek seeks to address lba. It does wait to arrive there. */
 715 void seek(int lba)
     /* [previous][next][first][last][top][bottom][index][help] */
 716 {
 717   int i;
 718   uch seek_command[4]={c_seek, };
 719   
 720   fsm(lba, &seek_command[1]);
 721   for (i=0; i<4; i++) type_0_command(seek_command[i], 0);
 722   cd->dsb = wait_dsb();
 723 }
 724 
 725 uch bcdbin(unsigned char bcd)   /* stolen from mcd.c! */
     /* [previous][next][first][last][top][bottom][index][help] */
 726 {
 727   return (bcd >> 4)*10 + (bcd & 0xf);
 728 } 
 729 
 730 inline uch normalize_track(uch track) 
     /* [previous][next][first][last][top][bottom][index][help] */
 731 {
 732   if (track<1) return 1;
 733   if (track>LAST_TRACK) return LAST_TRACK+1;
 734   return track;
 735 }
 736 
 737 /* This function does a binary search for track start. It records all
 738  * tracks seen in the process. Input $track$ must be between 1 and
 739  * #-of-tracks+1 */
 740 int get_toc_lba(uch track)
     /* [previous][next][first][last][top][bottom][index][help] */
 741 {
 742   int max=74*60*75-150, min=0;
 743   int i, lba, l, old_lba=0;
 744   uch * q = cd->q;
 745   uch ct;                       /* current track */
 746   int binary=0;
 747   const skip = 3*60*75;
 748 
 749   for (i=track; i>0; i--) if (cd->toc[i].track) {
 750     min = fsm2lba(cd->toc[i].fsm);
 751     break;
 752   }
 753   lba = min + skip;             /* 3 minutes */
 754   do {
 755     seek(lba); 
 756     type_1_command(c_read_current_q, 10, q);
 757     ct = normalize_track(q[1]);
 758     if (!cd->toc[ct].track) {
 759       l = q[9]-bcdbin(q[5]) + 75*(q[8]-bcdbin(q[4])-2 + 
 760                                   60*(q[7]-bcdbin(q[3])));
 761       cd->toc[ct].track=q[1];   /* lead out still 0xaa */
 762       fsm(l, cd->toc[ct].fsm);
 763       cd->toc[ct].q0 = q[0];    /* contains adr and ctrl info */
 764 /*
 765       if (ct==LAST_TRACK+1) 
 766         printk("Leadout %x %x %x %x %d %d %d \n", q[1], q[3], q[4], q[5],
 767                q[7], q[8], q[9]);
 768 */
 769       if (ct==track) return l;
 770     }
 771     old_lba=lba;
 772     if (binary) {
 773       if (ct < track) min = lba; else max = lba;
 774       lba = (min+max)/2; 
 775     } else {
 776       if(ct < track) lba += skip;
 777       else {
 778         binary=1;
 779         max = lba; min = lba - skip;
 780         lba = (min+max)/2;
 781       }
 782     }
 783   } while (lba!=old_lba);
 784   return lba;
 785 }
 786 
 787 void update_toc_entry(uch track) 
     /* [previous][next][first][last][top][bottom][index][help] */
 788 {
 789   track = normalize_track(track);
 790   if (!cd->toc[track].track) get_toc_lba(track);
 791 }
 792 
 793 int read_toc_header(struct cdrom_tochdr * hp)
     /* [previous][next][first][last][top][bottom][index][help] */
 794 {
 795   if (!FIRST_TRACK) get_disc_status();
 796   if (hp && DISC_STATUS & cds_all_audio) { /* all audio */
 797     int i;
 798     hp->cdth_trk0 = FIRST_TRACK;
 799     hp->cdth_trk1 = LAST_TRACK;
 800     cd->toc[1].track=1;         /* fill in first track position */
 801     for (i=0; i<3; i++) cd->toc[1].fsm[i] = cd->disc_status[3+i];
 802     update_toc_entry(LAST_TRACK+1);             /* find most entries */
 803     return 1;
 804   }
 805   return 0;
 806 }  
 807 
 808 void play_from_to_msf(struct cdrom_msf* msfp)
     /* [previous][next][first][last][top][bottom][index][help] */
 809 {
 810   uch play_command[] = {c_play, 
 811            msfp->cdmsf_frame0, msfp->cdmsf_sec0, msfp->cdmsf_min0,
 812            msfp->cdmsf_frame1, msfp->cdmsf_sec1, msfp->cdmsf_min1, 2, 2};
 813   int i;
 814   for (i=0; i<9; i++) type_0_command(play_command[i], 0);
 815   for (i=0; i<3; i++) 
 816     PLAY_TO.fsm[i] = play_command[i+4];
 817   PLAY_TO.track = 0;            /* say no track end */
 818   cd->dsb = wait_dsb();
 819 }  
 820 
 821 void play_from_to_track(int from, int to)
     /* [previous][next][first][last][top][bottom][index][help] */
 822 {
 823   uch play_command[8] = {c_play, };
 824   int i;
 825 
 826   if (from==0) {                /* continue paused play */
 827     for (i=0; i<3; i++) { 
 828       play_command[i+1] = cd->audio_status[i+2];
 829       play_command[i+4] = PLAY_TO.fsm[i];
 830     }
 831   } else {
 832     update_toc_entry(from); update_toc_entry(to+1);
 833     for (i=0; i<3; i++) {
 834       play_command[i+1] = cd->toc[from].fsm[i];
 835       PLAY_TO.fsm[i] = play_command[i+4] = cd->toc[to+1].fsm[i];
 836     }
 837     PLAY_TO.track = to; 
 838   }
 839   for (i=0; i<7; i++) type_0_command(play_command[i],0);
 840   for (i=0; i<2; i++) type_0_command(0x2, 0); /* volume */
 841   cd->dsb = wait_dsb();
 842 }
 843 
 844 int get_current_q(struct cdrom_subchnl * qp)
     /* [previous][next][first][last][top][bottom][index][help] */
 845 {
 846   int i;
 847   uch * q = cd->q;
 848   if (type_1_command(c_read_current_q, 10, q)) return 0;
 849 /*  q[0] = bcdbin(q[0]); Don't think so! */
 850   for (i=2; i<6; i++) q[i]=bcdbin(q[i]); 
 851   qp->cdsc_adr = q[0] & 0xf; qp->cdsc_ctrl = q[0] >> 4; /* from mcd.c */
 852   qp->cdsc_trk = q[1];  qp->cdsc_ind = q[2];
 853   if (qp->cdsc_format == CDROM_MSF) {
 854     qp->cdsc_reladdr.msf.minute = q[3];
 855     qp->cdsc_reladdr.msf.second = q[4];
 856     qp->cdsc_reladdr.msf.frame = q[5];
 857     qp->cdsc_absaddr.msf.minute = q[7];
 858     qp->cdsc_absaddr.msf.second = q[8];
 859     qp->cdsc_absaddr.msf.frame = q[9];
 860   } else {
 861     qp->cdsc_reladdr.lba = f_s_m2lba(q[5], q[4], q[3]);
 862     qp->cdsc_absaddr.lba = f_s_m2lba(q[9], q[8], q[7]);
 863   }
 864   get_drive_status();
 865   if (cd->dsb & dsb_play_in_progress) 
 866     qp->cdsc_audiostatus = CDROM_AUDIO_PLAY ;
 867   else if (PAUSED) 
 868     qp->cdsc_audiostatus = CDROM_AUDIO_PAUSED;
 869   else qp->cdsc_audiostatus = CDROM_AUDIO_NO_STATUS;
 870   return 1;
 871 }
 872 
 873 void get_toc_entry(struct cdrom_tocentry * ep)
     /* [previous][next][first][last][top][bottom][index][help] */
 874 {
 875   uch track = normalize_track(ep->cdte_track);
 876   update_toc_entry(track);
 877   if (ep->cdte_format == CDROM_MSF) {
 878     ep->cdte_addr.msf.frame = cd->toc[track].fsm[0];
 879     ep->cdte_addr.msf.second = cd->toc[track].fsm[1];
 880     ep->cdte_addr.msf.minute = cd->toc[track].fsm[2];
 881   } 
 882   else ep->cdte_addr.lba = fsm2lba(cd->toc[track].fsm);
 883   ep->cdte_adr = cd->toc[track].q0 & 0xf; 
 884   ep->cdte_ctrl = cd->toc[track].q0 >> 4;
 885   ep->cdte_datamode=0;
 886 }
 887   
 888 /* Ioctl. I have made the statistics accessible through an ioctl
 889    call. The constant is defined in cm206.h, it shouldn't clash with
 890    the standard Linux ioctls. Multisession info is gathered at
 891    run-time, this may turn out to be slow. */
 892 
 893 static int cm206_ioctl(struct inode * inode, struct file * file, 
     /* [previous][next][first][last][top][bottom][index][help] */
 894                        unsigned int cmd, unsigned long arg)
 895 {
 896   switch (cmd) {
 897 #ifdef STATISTICS
 898   case CM206CTL_GET_STAT:
 899     if (arg >= NR_STATS) return -EINVAL;
 900     else return cd->stats[arg];
 901   case CM206CTL_GET_LAST_STAT:
 902     if (arg >= NR_STATS) return -EINVAL;
 903     else return cd->last_stat[arg];
 904 #endif    
 905   case CDROMMULTISESSION: {
 906     struct cdrom_multisession ms_info;
 907     int st;
 908     stats(ioctl_multisession);
 909 
 910     st=verify_area(VERIFY_WRITE, (void *) arg, 
 911                    sizeof(struct cdrom_multisession));
 912     if (st) return (st);
 913     memcpy_fromfs(&ms_info, (struct cdrom_multisession *) arg,
 914                   sizeof(struct cdrom_multisession));
 915     get_multi_session_info(&ms_info);
 916     memcpy_tofs((struct cdrom_multisession *) arg, &ms_info, 
 917                   sizeof(struct cdrom_multisession));
 918     return 0;
 919   }
 920   case CDROMRESET:              /* If needed, it's probably too late anyway */
 921     stop_read();
 922     reset_cm260();
 923     outw(dc_normal | dc_break | READ_AHEAD, r_data_control);
 924     udelay(1000);               /* 750 musec minimum */
 925     outw(dc_normal | READ_AHEAD, r_data_control);
 926     cd->sector_last = -1;       /* flag no data buffered */
 927     cd->adapter_last = -1;    
 928     return 0;
 929   }
 930 
 931   get_drive_status();
 932   if (cd->dsb & (dsb_drive_not_ready | dsb_tray_not_closed) )
 933     return -EAGAIN; 
 934 
 935   switch (cmd) {
 936   case CDROMREADTOCHDR: {
 937     struct cdrom_tochdr header;
 938     int st;
 939 
 940     st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(header));
 941     if (st) return (st);
 942     if (read_toc_header(&header)) {
 943       memcpy_tofs((struct cdrom_tochdr *) arg, &header, sizeof(header));
 944       return 0;
 945     }
 946     else return -ENODATA;
 947   }
 948   case CDROMREADTOCENTRY: {     
 949     struct cdrom_tocentry entry;
 950     int st;
 951 
 952     st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(entry));
 953     if (st) return (st);
 954     memcpy_fromfs(&entry, (struct cdrom_tocentry *) arg, sizeof entry);
 955     get_toc_entry(&entry);
 956     memcpy_tofs((struct cdrom_tocentry *) arg, &entry, sizeof entry);
 957     return 0;
 958   }
 959   case CDROMPLAYMSF: {
 960     struct cdrom_msf msf;
 961     int st;
 962 
 963     st=verify_area(VERIFY_READ, (void *) arg, sizeof(msf));
 964     if (st) return (st);
 965     memcpy_fromfs(&msf, (struct cdrom_mdf *) arg, sizeof msf);
 966     play_from_to_msf(&msf);
 967     return 0;
 968   }
 969   case CDROMPLAYTRKIND: {
 970     struct cdrom_ti track_index;
 971     int st;
 972 
 973     st=verify_area(VERIFY_READ, (void *) arg, sizeof(track_index));
 974     if (st) return (st);
 975     memcpy_fromfs(&track_index, (struct cdrom_ti *) arg, sizeof(track_index));
 976     play_from_to_track(track_index.cdti_trk0, track_index.cdti_trk1);
 977     return 0;
 978   }
 979   case CDROMSTOP: 
 980     PAUSED=0;
 981     if (cd->dsb & dsb_play_in_progress) return type_0_command(c_stop, 1);
 982     return 0;
 983   case CDROMPAUSE: 
 984     if (cd->dsb & dsb_play_in_progress) {
 985       type_0_command(c_stop, 1);
 986       type_1_command(c_audio_status, 5, cd->audio_status);
 987       PAUSED=1; /* say we're paused */
 988     }
 989     return 0;
 990   case CDROMRESUME:
 991     if (PAUSED) play_from_to_track(0,0);
 992     PAUSED=0;
 993     return 0;
 994   case CDROMEJECT:
 995     PAUSED=0;
 996     if (cd->openfiles == 1) {   /* Must do an open before an eject! */
 997       type_0_command(c_open_tray,1);
 998       memset(cd->toc, 0, sizeof(cd->toc));
 999       memset(cd->disc_status, 0, sizeof(cd->disc_status));
1000       return 0;
1001     }
1002     else return -EBUSY;
1003   case CDROMSTART:
1004   case CDROMVOLCTRL:
1005     return 0;
1006   case CDROMSUBCHNL: {
1007     struct cdrom_subchnl q;
1008     int st;
1009 
1010     st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(q));
1011     if (st) return (st);
1012     memcpy_fromfs(&q, (struct cdrom_subchnl *) arg, sizeof q);
1013     if (get_current_q(&q)) {
1014       memcpy_tofs((struct cdrom_subchnl *) arg, &q, sizeof q);
1015       return 0;
1016     }
1017     else return -cmd;
1018   }
1019   case CDROM_GET_UPC: {
1020     uch upc[10];
1021     int st;
1022 
1023     st=verify_area(VERIFY_WRITE, (void *) arg, 8);
1024     if (st) return (st);
1025     if (type_1_command(c_read_upc, 10, upc)) return -EIO;
1026     memcpy_tofs((uch *) arg, &upc[1], 8);
1027     return 0;
1028   } 
1029   default:
1030     debug(("Unknown ioctl call 0x%x\n", cmd));
1031     return -EINVAL;
1032   }
1033 }     
1034 
1035 /* from lmscd.c */
1036 static struct file_operations cm206_fops = {
1037         NULL,                   /* lseek */
1038         block_read,             /* read - general block-dev read */
1039         block_write,            /* write - general block-dev write */
1040         NULL,                   /* readdir */
1041         NULL,                   /* select */
1042         cm206_ioctl,            /* ioctl */
1043         NULL,                   /* mmap */
1044         cm206_open,             /* open */
1045         cm206_release,          /* release */
1046         NULL,                   /* fsync */
1047         NULL,                   /* fasync */
1048         NULL,                   /* media_change */
1049         NULL                    /* revalidate */
1050 };
1051 
1052 /* This routine gets called during init if thing go wrong, can be used
1053  * in cleanup_module as well. */
1054 void cleanup(int level)
     /* [previous][next][first][last][top][bottom][index][help] */
1055 {
1056   switch (level) {
1057   case 4: 
1058     if (unregister_blkdev(MAJOR_NR, "cm206")) {
1059       printk("Can't unregister cm206\n");
1060       return;
1061     }
1062   case 3: 
1063     free_irq(cm206_irq);
1064   case 2: 
1065   case 1: 
1066 #ifdef MODULE
1067     kfree(cd);
1068 #endif
1069     release_region(cm206_base, 16);
1070   default:
1071   }
1072 }
1073 
1074 /* This function probes for the adapter card. It returns the base
1075    address if it has found the adapter card. One can specify a base 
1076    port to probe specifically, or 0 which means span all possible
1077    bases. 
1078 
1079    Linus says it is too dangerous to use writes for probing, so we
1080    stick with pure reads for a while. Hope that 8 possible ranges,
1081    check_region, 15 bits of one port and 6 of another make things
1082    likely enough to accept the region on the first hit...
1083  */
1084 int probe_base_port(int base)
     /* [previous][next][first][last][top][bottom][index][help] */
1085 {
1086   int b=0x300, e=0x370;         /* this is the range of start addresses */
1087   volatile int fool;
1088 #if 0
1089   const pattern1=0x65, pattern2=0x1a;
1090 #endif
1091 
1092   if (base) b=e=base;
1093   for (base=b; base<=e; base += 0x10) {
1094     if (check_region(base, 0x10)) continue;
1095     fool = inw(base+2);         /* empty possibly uart_receive_buffer */
1096     if((inw(base+6) & 0xffef) != 0x0001 || /* line_status */
1097        (inw(base) & 0xad00) != 0) /* data status */
1098       continue;
1099 #if 0                           /* writes... dangerous... */
1100     outw(dc_normal | pattern1, base+8); 
1101     if ((inw(base) & 0x7f) != pattern1) continue;
1102     outw(dc_normal | pattern2, base+8);
1103     if ((inw(base) & 0x7f) != pattern2) continue;
1104     outw(dc_normal | READ_AHEAD, base+8);
1105 #endif
1106     return(base);
1107   }
1108   return 0;
1109 }
1110 
1111 #if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
1112 /* Probe for irq# nr. If nr==0, probe for all possible irq's. */
1113 int probe_irq(int nr) {
     /* [previous][next][first][last][top][bottom][index][help] */
1114   int irqs, irq;
1115   outw(dc_normal | READ_AHEAD, r_data_control); /* disable irq-generation */
1116   sti(); 
1117   irqs = probe_irq_on();
1118   reset_cm260();                /* causes interrupt */
1119   udelay(10);                   /* wait for it */
1120   irq = probe_irq_off(irqs);
1121   outw(dc_normal | READ_AHEAD, r_data_control); /* services interrupt */
1122   if (nr && irq!=nr && irq>0) return 0; /* wrong interrupt happened */
1123   else return irq;
1124 }
1125 #endif
1126 
1127 #ifdef MODULE
1128 #define OK  0
1129 #define ERROR  -EIO
1130 
1131 static int cm206[2] = {0,0};    /* for compatible `insmod' parameter passing */
1132 void parse_options(void) 
     /* [previous][next][first][last][top][bottom][index][help] */
1133 {
1134   int i;
1135   for (i=0; i<2; i++) {
1136     if (0x300 <= cm206[i] && i<= 0x370 && cm206[i] % 0x10 == 0) {
1137       cm206_base = cm206[i];
1138       auto_probe=0;
1139     }
1140     else if (3 <= cm206[i] && cm206[i] <= 15) {
1141       cm206_irq = cm206[i];
1142       auto_probe=0;
1143     }
1144   }
1145 }
1146 
1147 #else MODULE
1148 
1149 #define OK  mem_start+size
1150 #define ERROR  mem_start
1151 
1152 #endif MODULE
1153 
1154 #ifdef MODULE
1155 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1156 #else 
1157 unsigned long cm206_init(unsigned long mem_start, unsigned long mem_end)
1158 #endif
1159 {
1160   uch e=0;
1161   long int size=sizeof(struct cm206_struct);
1162 
1163   printk("cm206: v" VERSION);
1164 #if defined(MODULE) 
1165   parse_options();
1166 #if !defined(AUTO_PROBE_MODULE)
1167    auto_probe=0;
1168 #endif
1169 #endif
1170   cm206_base = probe_base_port(auto_probe ? 0 : cm206_base);
1171   if (!cm206_base) {
1172     printk(" can't find adapter!\n");
1173     return ERROR;
1174   }
1175   printk(" adapter at 0x%x", cm206_base);
1176   request_region(cm206_base, 16, "cm206");
1177 #ifdef MODULE
1178   cd = (struct cm206_struct *) kmalloc(size, GFP_KERNEL);
1179   if (!cd) return ERROR;
1180 #else 
1181   cd = (struct cm206_struct *) mem_start;
1182 #endif
1183   /* Now we have found the adaptor card, try to reset it. As we have
1184    * found out earlier, this process generates an interrupt as well,
1185    * so we might just exploit that fact for irq probing! */
1186 #if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
1187   cm206_irq = probe_irq(auto_probe ? 0 : cm206_irq);    
1188   if (cm206_irq<=0) {
1189     printk("can't find IRQ!\n");
1190     cleanup(1);
1191     return ERROR;
1192   }
1193   else printk(" IRQ %d found\n", cm206_irq);
1194 #else
1195   reset_cm260();
1196   printk(" using IRQ %d\n", cm206_irq);
1197 #endif
1198   if (send_receive_polled(c_drive_configuration) != c_drive_configuration) 
1199     {
1200       printk(" drive not there\n");
1201       cleanup(1);
1202       return ERROR;
1203     }
1204   e = send_receive_polled(c_gimme);
1205   printk("Firmware revision %d", e & dcf_revision_code);
1206   if (e & dcf_transfer_rate) printk(" double");
1207   else printk(" single");
1208   printk(" speed drive");
1209   if (e & dcf_motorized_tray) printk(", motorized tray");
1210   if (request_irq(cm206_irq, cm206_interrupt, 0, "cm206")) {
1211     printk("\nUnable to reserve IRQ---aborted\n");
1212     cleanup(2);
1213     return ERROR;
1214   }
1215   printk(".\n");
1216   if (register_blkdev(MAJOR_NR, "cm206", &cm206_fops) != 0) {
1217     printk("Cannot register for major %d!\n", MAJOR_NR);
1218     cleanup(3);
1219     return ERROR;
1220   }
1221   blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1222   read_ahead[MAJOR_NR] = 16;    /* reads ahead what? */
1223   bh_base[CM206_BH].routine = cm206_bh;
1224   enable_bh(CM206_BH);
1225 
1226   memset(cd, 0, sizeof(*cd));   /* give'm some reasonable value */
1227   cd->sector_last = -1;         /* flag no data buffered */
1228   cd->adapter_last = -1;
1229   cd->timer.function = cm206_timeout;
1230   cd->max_sectors = (inw(r_data_status) & ds_ram_size) ? 24 : 97;
1231   printk("%d kB adapter memory available, "  
1232          " %ld bytes kernel memory used.\n", cd->max_sectors*2, size);
1233   return OK;
1234 }
1235 #undef OK
1236 #undef ERROR
1237 
1238 #ifdef MODULE
1239 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1240 {
1241   cleanup(4);
1242   printk("cm206 removed\n");
1243 }
1244       
1245 #else MODULE
1246 
1247 /* This setup function accepts either `auto' or numbers in the range
1248  * 3--11 (for irq) or 0x300--0x370 (for base port) or both. */
1249 void cm206_setup(char *s, int *p)
     /* [previous][next][first][last][top][bottom][index][help] */
1250 {
1251   int i;
1252   if (!strcmp(s, "auto")) auto_probe=1;
1253   for(i=1; i<=p[0]; i++) {
1254     if (0x300 <= p[i] && i<= 0x370 && p[i] % 0x10 == 0) {
1255       cm206_base = p[i];
1256       auto_probe = 0;
1257     }
1258     else if (3 <= p[i] && p[i] <= 15) {
1259       cm206_irq = p[i];
1260       auto_probe = 0;
1261     }
1262   }
1263 }
1264 #endif MODULE

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