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

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