linux-bk/drivers/cdrom/cm206.c
<<
>>
Prefs
   1/* cm206.c. A linux-driver for the cm206 cdrom player with cm260 adapter card.
   2   Copyright (c) 1995--1997 David A. van Leeuwen.
   3   $Id: cm206.c,v 1.5 1997/12/26 11:02:51 david Exp $
   4   
   5     This program is free software; you can redistribute it and/or modify
   6     it under the terms of the GNU General Public License as published by
   7     the Free Software Foundation; either version 2 of the License, or
   8     (at your option) any later version.
   9     
  10     This program is distributed in the hope that it will be useful,
  11     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13     GNU General Public License for more details.
  14     
  15     You should have received a copy of the GNU General Public License
  16     along with this program; if not, write to the Free Software
  17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18
  19History:
  20 Started 25 jan 1994. Waiting for documentation...
  21 22 feb 1995: 0.1a first reasonably safe polling driver.
  22              Two major bugs, one in read_sector and one in 
  23              do_cm206_request, happened to cancel!
  24 25 feb 1995: 0.2a first reasonable interrupt driven version of above.
  25              uart writes are still done in polling mode. 
  26 25 feb 1995: 0.21a writes also in interrupt mode, still some
  27              small bugs to be found... Larger buffer. 
  28  2 mrt 1995: 0.22 Bug found (cd-> nowhere, interrupt was called in
  29              initialization), read_ahead of 16. Timeouts implemented.
  30              unclear if they do something...
  31  7 mrt 1995: 0.23 Start of background read-ahead.
  32 18 mrt 1995: 0.24 Working background read-ahead. (still problems)
  33 26 mrt 1995: 0.25 Multi-session ioctl added (kernel v1.2).
  34              Statistics implemented, though separate stats206.h.
  35              Accessible trough ioctl 0x1000 (just a number).
  36              Hard to choose between v1.2 development and 1.1.75.
  37              Bottom-half doesn't work with 1.2...
  38              0.25a: fixed... typo. Still problems...
  39  1 apr 1995: 0.26 Module support added. Most bugs found. Use kernel 1.2.n.
  40  5 apr 1995: 0.27 Auto-probe for the adapter card base address.
  41              Auto-probe for the adaptor card irq line.
  42  7 apr 1995: 0.28 Added lilo setup support for base address and irq.
  43              Use major number 32 (not in this source), officially
  44              assigned to this driver.
  45  9 apr 1995: 0.29 Added very limited audio support. Toc_header, stop, pause,
  46              resume, eject. Play_track ignores track info, because we can't 
  47              read a table-of-contents entry. Toc_entry is implemented
  48              as a `placebo' function: always returns start of disc. 
  49  3 may 1995: 0.30 Audio support completed. The get_toc_entry function
  50              is implemented as a binary search. 
  51 15 may 1995: 0.31 More work on audio stuff. Workman is not easy to 
  52              satisfy; changed binary search into linear search.
  53              Auto-probe for base address somewhat relaxed.
  54  1 jun 1995: 0.32 Removed probe_irq_on/off for module version.
  55 10 jun 1995: 0.33 Workman still behaves funny, but you should be
  56              able to eject and substitute another disc.
  57
  58 An adaptation of 0.33 is included in linux-1.3.7 by Eberhard Moenkeberg
  59
  60 18 jul 1995: 0.34 Patch by Heiko Eissfeldt included, mainly considering 
  61              verify_area's in the ioctls. Some bugs introduced by 
  62              EM considering the base port and irq fixed. 
  63
  64 18 dec 1995: 0.35 Add some code for error checking... no luck...
  65
  66 We jump to reach our goal: version 1.0 in the next stable linux kernel.
  67
  68 19 mar 1996: 0.95 Different implementation of CDROM_GET_UPC, on
  69              request of Thomas Quinot. 
  70 25 mar 1996: 0.96 Interpretation of opening with O_WRONLY or O_RDWR:
  71              open only for ioctl operation, e.g., for operation of
  72              tray etc.
  73 4 apr 1996:  0.97 First implementation of layer between VFS and cdrom
  74              driver, a generic interface. Much of the functionality
  75              of cm206_open() and cm206_ioctl() is transferred to a
  76              new file cdrom.c and its header ucdrom.h. 
  77
  78              Upgrade to Linux kernel 1.3.78. 
  79
  80 11 apr 1996  0.98 Upgrade to Linux kernel 1.3.85
  81              More code moved to cdrom.c
  82 
  83              0.99 Some more small changes to decrease number
  84              of oopses at module load; 
  85 
  86 27 jul 1996  0.100 Many hours of debugging, kernel change from 1.2.13
  87              to 2.0.7 seems to have introduced some weird behavior
  88              in (interruptible_)sleep_on(&cd->data): the process
  89              seems to be woken without any explicit wake_up in my own
  90              code. Patch to try 100x in case such untriggered wake_up's 
  91              occur. 
  92
  93 28 jul 1996  0.101 Rewriting of the code that receives the command echo,
  94              using a fifo to store echoed bytes. 
  95
  96              Branch from 0.99:
  97 
  98              0.99.1.0 Update to kernel release 2.0.10 dev_t -> kdev_t
  99              (emoenke) various typos found by others.  extra
 100              module-load oops protection.
 101 
 102              0.99.1.1 Initialization constant cdrom_dops.speed
 103              changed from float (2.0) to int (2); Cli()-sti() pair
 104              around cm260_reset() in module initialization code.
 105 
 106              0.99.1.2 Changes literally as proposed by Scott Snyder
 107              <snyder@d0sgif.fnal.gov> for the 2.1 kernel line, which
 108              have to do mainly with the poor minor support i had. The
 109              major new concept is to change a cdrom driver's
 110              operations struct from the capabilities struct. This
 111              reflects the fact that there is one major for a driver,
 112              whilst there can be many minors whith completely
 113              different capabilities.
 114
 115              0.99.1.3 More changes for operations/info separation.
 116
 117              0.99.1.4 Added speed selection (someone had to do this
 118              first).
 119
 120  23 jan 1997 0.99.1.5 MODULE_PARMS call added.
 121
 122  23 jan 1997 0.100.1.2--0.100.1.5 following similar lines as 
 123              0.99.1.1--0.99.1.5. I get too many complaints about the
 124              drive making read errors. What't wrong with the 2.0+
 125              kernel line? Why get i (and othe cm206 owners) weird
 126              results? Why were things good in the good old 1.1--1.2 
 127              era? Why don't i throw away the drive?
 128
 129 2 feb 1997   0.102 Added `volatile' to values in cm206_struct. Seems to 
 130              reduce many of the problems. Rewrote polling routines
 131              to use fixed delays between polls. 
 132              0.103 Changed printk behavior. 
 133              0.104 Added a 0.100 -> 0.100.1.1 change
 134
 13511 feb 1997   0.105 Allow auto_probe during module load, disable
 136              with module option "auto_probe=0". Moved some debugging
 137              statements to lower priority. Implemented select_speed()
 138              function. 
 139
 14013 feb 1997   1.0 Final version for 2.0 kernel line. 
 141
 142              All following changes will be for the 2.1 kernel line. 
 143
 14415 feb 1997   1.1 Keep up with kernel 2.1.26, merge in changes from 
 145              cdrom.c 0.100.1.1--1.0. Add some more MODULE_PARMS. 
 146
 14714 sep 1997   1.2 Upgrade to Linux 2.1.55.  Added blksize_size[], patch
 148              sent by James Bottomley <James.Bottomley@columbiasc.ncr.com>.
 149
 15021 dec 1997   1.4 Upgrade to Linux 2.1.72.  
 151
 15224 jan 1998   Removed the cm206_disc_status() function, as it was now dead
 153              code.  The Uniform CDROM driver now provides this functionality.
 154              
 1559 Nov. 1999   Make kernel-parameter implementation work with 2.3.x 
 156              Removed init_module & cleanup_module in favor of 
 157              module_init & module_exit.
 158              Torben Mathiasen <tmm@image.dk>
 159 * 
 160 * Parts of the code are based upon lmscd.c written by Kai Petzke,
 161 * sbpcd.c written by Eberhard Moenkeberg, and mcd.c by Martin
 162 * Harriss, but any off-the-shelf dynamic programming algorithm won't
 163 * be able to find them.
 164 *
 165 * The cm206 drive interface and the cm260 adapter card seem to be 
 166 * sufficiently different from their cm205/cm250 counterparts
 167 * in order to write a complete new driver.
 168 * 
 169 * I call all routines connected to the Linux kernel something
 170 * with `cm206' in it, as this stuff is too series-dependent. 
 171 * 
 172 * Currently, my limited knowledge is based on:
 173 * - The Linux Kernel Hacker's guide, v. 0.5, by Michael K. Johnson
 174 * - Linux Kernel Programmierung, by Michael Beck and others
 175 * - Philips/LMS cm206 and cm226 product specification
 176 * - Philips/LMS cm260 product specification
 177 *
 178 * David van Leeuwen, david@tm.tno.nl.  */
 179#define REVISION "$Revision: 1.5 $"
 180
 181#include <linux/module.h>
 182
 183#include <linux/errno.h>        /* These include what we really need */
 184#include <linux/delay.h>
 185#include <linux/string.h>
 186#include <linux/sched.h>
 187#include <linux/interrupt.h>
 188#include <linux/timer.h>
 189#include <linux/cdrom.h>
 190#include <linux/devfs_fs_kernel.h>
 191#include <linux/ioport.h>
 192#include <linux/mm.h>
 193#include <linux/slab.h>
 194#include <linux/init.h>
 195
 196/* #include <linux/ucdrom.h> */
 197
 198#include <asm/io.h>
 199
 200#define MAJOR_NR CM206_CDROM_MAJOR
 201
 202#include <linux/blkdev.h>
 203
 204#undef DEBUG
 205#define STATISTICS              /* record times and frequencies of events */
 206#define AUTO_PROBE_MODULE
 207#define USE_INSW
 208
 209#include "cm206.h"
 210
 211/* This variable defines whether or not to probe for adapter base port 
 212   address and interrupt request. It can be overridden by the boot 
 213   parameter `auto'.
 214*/
 215static int auto_probe = 1;      /* Yes, why not? */
 216
 217static int cm206_base = CM206_BASE;
 218static int cm206_irq = CM206_IRQ;
 219#ifdef MODULE
 220static int cm206[2] = { 0, 0 }; /* for compatible `insmod' parameter passing */
 221#endif
 222
 223MODULE_PARM(cm206_base, "i");   /* base */
 224MODULE_PARM(cm206_irq, "i");    /* irq */
 225MODULE_PARM(cm206, "1-2i");     /* base,irq or irq,base */
 226MODULE_PARM(auto_probe, "i");   /* auto probe base and irq */
 227MODULE_LICENSE("GPL");
 228
 229#define POLLOOP 100             /* milliseconds */
 230#define READ_AHEAD 1            /* defines private buffer, waste! */
 231#define BACK_AHEAD 1            /* defines adapter-read ahead */
 232#define DATA_TIMEOUT (3*HZ)     /* measured in jiffies (10 ms) */
 233#define UART_TIMEOUT (5*HZ/100)
 234#define DSB_TIMEOUT (7*HZ)      /* time for the slowest command to finish */
 235#define UR_SIZE 4               /* uart receive buffer fifo size */
 236
 237#define LINUX_BLOCK_SIZE 512    /* WHERE is this defined? */
 238#define RAW_SECTOR_SIZE 2352    /* ok, is also defined in cdrom.h */
 239#define ISO_SECTOR_SIZE 2048
 240#define BLOCKS_ISO (ISO_SECTOR_SIZE/LINUX_BLOCK_SIZE)   /* 4 */
 241#define CD_SYNC_HEAD 16         /* CD_SYNC + CD_HEAD */
 242
 243#ifdef STATISTICS               /* keep track of errors in counters */
 244#define stats(i) { ++cd->stats[st_ ## i]; \
 245                     cd->last_stat[st_ ## i] = cd->stat_counter++; \
 246                 }
 247#else
 248#define stats(i) (void) 0;
 249#endif
 250
 251#define Debug(a) {printk (KERN_DEBUG); printk a;}
 252#ifdef DEBUG
 253#define debug(a) Debug(a)
 254#else
 255#define debug(a) (void) 0;
 256#endif
 257
 258typedef unsigned char uch;      /* 8-bits */
 259typedef unsigned short ush;     /* 16-bits */
 260
 261struct toc_struct {             /* private copy of Table of Contents */
 262        uch track, fsm[3], q0;
 263};
 264
 265struct cm206_struct {
 266        volatile ush intr_ds;   /* data status read on last interrupt */
 267        volatile ush intr_ls;   /* uart line status read on last interrupt */
 268        volatile uch ur[UR_SIZE];       /* uart receive buffer fifo */
 269        volatile uch ur_w, ur_r;        /* write/read buffer index */
 270        volatile uch dsb, cc;   /* drive status byte and condition (error) code */
 271        int command;            /* command to be written to the uart */
 272        int openfiles;
 273        ush sector[READ_AHEAD * RAW_SECTOR_SIZE / 2];   /* buffered cd-sector */
 274        int sector_first, sector_last;  /* range of these sectors */
 275        wait_queue_head_t uart; /* wait queues for interrupt */
 276        wait_queue_head_t data;
 277        struct timer_list timer;        /* time-out */
 278        char timed_out;
 279        signed char max_sectors;        /* number of sectors that fit in adapter mem */
 280        char wait_back;         /* we're waiting for a background-read */
 281        char background;        /* is a read going on in the background? */
 282        int adapter_first;      /* if so, that's the starting sector */
 283        int adapter_last;
 284        char fifo_overflowed;
 285        uch disc_status[7];     /* result of get_disc_status command */
 286#ifdef STATISTICS
 287        int stats[NR_STATS];
 288        int last_stat[NR_STATS];        /* `time' at which stat was stat */
 289        int stat_counter;
 290#endif
 291        struct toc_struct toc[101];     /* The whole table of contents + lead-out */
 292        uch q[10];              /* Last read q-channel info */
 293        uch audio_status[5];    /* last read position on pause */
 294        uch media_changed;      /* record if media changed */
 295};
 296
 297#define DISC_STATUS cd->disc_status[0]
 298#define FIRST_TRACK cd->disc_status[1]
 299#define LAST_TRACK cd->disc_status[2]
 300#define PAUSED cd->audio_status[0]      /* misuse this memory byte! */
 301#define PLAY_TO cd->toc[0]      /* toc[0] records end-time in play */
 302
 303static struct cm206_struct *cd; /* the main memory structure */
 304static struct request_queue *cm206_queue;
 305static spinlock_t cm206_lock = SPIN_LOCK_UNLOCKED;
 306
 307/* First, we define some polling functions. These are actually
 308   only being used in the initialization. */
 309
 310void send_command_polled(int command)
 311{
 312        int loop = POLLOOP;
 313        while (!(inw(r_line_status) & ls_transmitter_buffer_empty)
 314               && loop > 0) {
 315                mdelay(1);      /* one millisec delay */
 316                --loop;
 317        }
 318        outw(command, r_uart_transmit);
 319}
 320
 321uch receive_echo_polled(void)
 322{
 323        int loop = POLLOOP;
 324        while (!(inw(r_line_status) & ls_receive_buffer_full) && loop > 0) {
 325                mdelay(1);
 326                --loop;
 327        }
 328        return ((uch) inw(r_uart_receive));
 329}
 330
 331uch send_receive_polled(int command)
 332{
 333        send_command_polled(command);
 334        return receive_echo_polled();
 335}
 336
 337inline void clear_ur(void)
 338{
 339        if (cd->ur_r != cd->ur_w) {
 340                debug(("Deleting bytes from fifo:"));
 341                for (; cd->ur_r != cd->ur_w;
 342                     cd->ur_r++, cd->ur_r %= UR_SIZE)
 343                        debug((" 0x%x", cd->ur[cd->ur_r]));
 344                debug(("\n"));
 345        }
 346}
 347
 348static struct tasklet_struct cm206_tasklet;
 349
 350/* The interrupt handler. When the cm260 generates an interrupt, very
 351   much care has to be taken in reading out the registers in the right
 352   order; in case of a receive_buffer_full interrupt, first the
 353   uart_receive must be read, and then the line status again to
 354   de-assert the interrupt line. It took me a couple of hours to find
 355   this out:-( 
 356
 357   The function reset_cm206 appears to cause an interrupt, because
 358   pulling up the INIT line clears both the uart-write-buffer /and/
 359   the uart-write-buffer-empty mask. We call this a `lost interrupt,'
 360   as there seems so reason for this to happen.
 361*/
 362
 363static irqreturn_t cm206_interrupt(int sig, void *dev_id, struct pt_regs *regs)
 364{
 365        volatile ush fool;
 366        cd->intr_ds = inw(r_data_status);       /* resets data_ready, data_error,
 367                                                   crc_error, sync_error, toc_ready 
 368                                                   interrupts */
 369        cd->intr_ls = inw(r_line_status);       /* resets overrun bit */
 370        debug(("Intr, 0x%x 0x%x, %d\n", cd->intr_ds, cd->intr_ls,
 371               cd->background));
 372        if (cd->intr_ls & ls_attention)
 373                stats(attention);
 374        /* receive buffer full? */
 375        if (cd->intr_ls & ls_receive_buffer_full) {
 376                cd->ur[cd->ur_w] = inb(r_uart_receive); /* get order right! */
 377                cd->intr_ls = inw(r_line_status);       /* resets rbf interrupt */
 378                debug(("receiving #%d: 0x%x\n", cd->ur_w,
 379                       cd->ur[cd->ur_w]));
 380                cd->ur_w++;
 381                cd->ur_w %= UR_SIZE;
 382                if (cd->ur_w == cd->ur_r)
 383                        debug(("cd->ur overflow!\n"));
 384                if (waitqueue_active(&cd->uart) && cd->background < 2) {
 385                        del_timer(&cd->timer);
 386                        wake_up_interruptible(&cd->uart);
 387                }
 388        }
 389        /* data ready in fifo? */
 390        else if (cd->intr_ds & ds_data_ready) {
 391                if (cd->background)
 392                        ++cd->adapter_last;
 393                if (waitqueue_active(&cd->data)
 394                    && (cd->wait_back || !cd->background)) {
 395                        del_timer(&cd->timer);
 396                        wake_up_interruptible(&cd->data);
 397                }
 398                stats(data_ready);
 399        }
 400        /* ready to issue a write command? */
 401        else if (cd->command && cd->intr_ls & ls_transmitter_buffer_empty) {
 402                outw(dc_normal | (inw(r_data_status) & 0x7f),
 403                     r_data_control);
 404                outw(cd->command, r_uart_transmit);
 405                cd->command = 0;
 406                if (!cd->background)
 407                        wake_up_interruptible(&cd->uart);
 408        }
 409        /* now treat errors (at least, identify them for debugging) */
 410        else if (cd->intr_ds & ds_fifo_overflow) {
 411                debug(("Fifo overflow at sectors 0x%x\n",
 412                       cd->sector_first));
 413                fool = inw(r_fifo_output_buffer);       /* de-assert the interrupt */
 414                cd->fifo_overflowed = 1;        /* signal one word less should be read */
 415                stats(fifo_overflow);
 416        } else if (cd->intr_ds & ds_data_error) {
 417                debug(("Data error at sector 0x%x\n", cd->sector_first));
 418                stats(data_error);
 419        } else if (cd->intr_ds & ds_crc_error) {
 420                debug(("CRC error at sector 0x%x\n", cd->sector_first));
 421                stats(crc_error);
 422        } else if (cd->intr_ds & ds_sync_error) {
 423                debug(("Sync at sector 0x%x\n", cd->sector_first));
 424                stats(sync_error);
 425        } else if (cd->intr_ds & ds_toc_ready) {
 426                /* do something appropriate */
 427        }
 428        /* couldn't see why this interrupt, maybe due to init */
 429        else {
 430                outw(dc_normal | READ_AHEAD, r_data_control);
 431                stats(lost_intr);
 432        }
 433        if (cd->background
 434            && (cd->adapter_last - cd->adapter_first == cd->max_sectors
 435                || cd->fifo_overflowed))
 436                tasklet_schedule(&cm206_tasklet);       /* issue a stop read command */
 437        stats(interrupt);
 438        return IRQ_HANDLED;
 439}
 440
 441/* we have put the address of the wait queue in who */
 442void cm206_timeout(unsigned long who)
 443{
 444        cd->timed_out = 1;
 445        debug(("Timing out\n"));
 446        wake_up_interruptible((wait_queue_head_t *) who);
 447}
 448
 449/* This function returns 1 if a timeout occurred, 0 if an interrupt
 450   happened */
 451int sleep_or_timeout(wait_queue_head_t * wait, int timeout)
 452{
 453        cd->timed_out = 0;
 454        init_timer(&cd->timer);
 455        cd->timer.data = (unsigned long) wait;
 456        cd->timer.expires = jiffies + timeout;
 457        add_timer(&cd->timer);
 458        debug(("going to sleep\n"));
 459        interruptible_sleep_on(wait);
 460        del_timer(&cd->timer);
 461        if (cd->timed_out) {
 462                cd->timed_out = 0;
 463                return 1;
 464        } else
 465                return 0;
 466}
 467
 468void cm206_delay(int nr_jiffies)
 469{
 470        DECLARE_WAIT_QUEUE_HEAD(wait);
 471        sleep_or_timeout(&wait, nr_jiffies);
 472}
 473
 474void send_command(int command)
 475{
 476        debug(("Sending 0x%x\n", command));
 477        if (!(inw(r_line_status) & ls_transmitter_buffer_empty)) {
 478                cd->command = command;
 479                cli();          /* don't interrupt before sleep */
 480                outw(dc_mask_sync_error | dc_no_stop_on_error |
 481                     (inw(r_data_status) & 0x7f), r_data_control);
 482                /* interrupt routine sends command */
 483                if (sleep_or_timeout(&cd->uart, UART_TIMEOUT)) {
 484                        debug(("Time out on write-buffer\n"));
 485                        stats(write_timeout);
 486                        outw(command, r_uart_transmit);
 487                }
 488                debug(("Write commmand delayed\n"));
 489        } else
 490                outw(command, r_uart_transmit);
 491}
 492
 493uch receive_byte(int timeout)
 494{
 495        uch ret;
 496        cli();
 497        debug(("cli\n"));
 498        ret = cd->ur[cd->ur_r];
 499        if (cd->ur_r != cd->ur_w) {
 500                sti();
 501                debug(("returning #%d: 0x%x\n", cd->ur_r,
 502                       cd->ur[cd->ur_r]));
 503                cd->ur_r++;
 504                cd->ur_r %= UR_SIZE;
 505                return ret;
 506        } else if (sleep_or_timeout(&cd->uart, timeout)) {      /* does sti() */
 507                debug(("Time out on receive-buffer\n"));
 508#ifdef STATISTICS
 509                if (timeout == UART_TIMEOUT)
 510                        stats(receive_timeout)  /* no `;'! */
 511                            else
 512                        stats(dsb_timeout);
 513#endif
 514                return 0xda;
 515        }
 516        ret = cd->ur[cd->ur_r];
 517        debug(("slept; returning #%d: 0x%x\n", cd->ur_r,
 518               cd->ur[cd->ur_r]));
 519        cd->ur_r++;
 520        cd->ur_r %= UR_SIZE;
 521        return ret;
 522}
 523
 524inline uch receive_echo(void)
 525{
 526        return receive_byte(UART_TIMEOUT);
 527}
 528
 529inline uch send_receive(int command)
 530{
 531        send_command(command);
 532        return receive_echo();
 533}
 534
 535inline uch wait_dsb(void)
 536{
 537        return receive_byte(DSB_TIMEOUT);
 538}
 539
 540int type_0_command(int command, int expect_dsb)
 541{
 542        int e;
 543        clear_ur();
 544        if (command != (e = send_receive(command))) {
 545                debug(("command 0x%x echoed as 0x%x\n", command, e));
 546                stats(echo);
 547                return -1;
 548        }
 549        if (expect_dsb) {
 550                cd->dsb = wait_dsb();   /* wait for command to finish */
 551        }
 552        return 0;
 553}
 554
 555int type_1_command(int command, int bytes, uch * status)
 556{                               /* returns info */
 557        int i;
 558        if (type_0_command(command, 0))
 559                return -1;
 560        for (i = 0; i < bytes; i++)
 561                status[i] = send_receive(c_gimme);
 562        return 0;
 563}
 564
 565/* This function resets the adapter card. We'd better not do this too
 566 * often, because it tends to generate `lost interrupts.' */
 567void reset_cm260(void)
 568{
 569        outw(dc_normal | dc_initialize | READ_AHEAD, r_data_control);
 570        udelay(10);             /* 3.3 mu sec minimum */
 571        outw(dc_normal | READ_AHEAD, r_data_control);
 572}
 573
 574/* fsm: frame-sec-min from linear address; one of many */
 575void fsm(int lba, uch * fsm)
 576{
 577        fsm[0] = lba % 75;
 578        lba /= 75;
 579        lba += 2;
 580        fsm[1] = lba % 60;
 581        fsm[2] = lba / 60;
 582}
 583
 584inline int fsm2lba(uch * fsm)
 585{
 586        return fsm[0] + 75 * (fsm[1] - 2 + 60 * fsm[2]);
 587}
 588
 589inline int f_s_m2lba(uch f, uch s, uch m)
 590{
 591        return f + 75 * (s - 2 + 60 * m);
 592}
 593
 594int start_read(int start)
 595{
 596        uch read_sector[4] = { c_read_data, };
 597        int i, e;
 598
 599        fsm(start, &read_sector[1]);
 600        clear_ur();
 601        for (i = 0; i < 4; i++)
 602                if (read_sector[i] != (e = send_receive(read_sector[i]))) {
 603                        debug(("read_sector: %x echoes %x\n",
 604                               read_sector[i], e));
 605                        stats(echo);
 606                        if (e == 0xff) {        /* this seems to happen often */
 607                                e = receive_echo();
 608                                debug(("Second try %x\n", e));
 609                                if (e != read_sector[i])
 610                                        return -1;
 611                        }
 612                }
 613        return 0;
 614}
 615
 616int stop_read(void)
 617{
 618        int e;
 619        type_0_command(c_stop, 0);
 620        if ((e = receive_echo()) != 0xff) {
 621                debug(("c_stop didn't send 0xff, but 0x%x\n", e));
 622                stats(stop_0xff);
 623                return -1;
 624        }
 625        return 0;
 626}
 627
 628/* This function starts to read sectors in adapter memory, the
 629   interrupt routine should stop the read. In fact, the bottom_half
 630   routine takes care of this. Set a flag `background' in the cd
 631   struct to indicate the process. */
 632
 633int read_background(int start, int reading)
 634{
 635        if (cd->background)
 636                return -1;      /* can't do twice */
 637        outw(dc_normal | BACK_AHEAD, r_data_control);
 638        if (!reading && start_read(start))
 639                return -2;
 640        cd->adapter_first = cd->adapter_last = start;
 641        cd->background = 1;     /* flag a read is going on */
 642        return 0;
 643}
 644
 645#ifdef USE_INSW
 646#define transport_data insw
 647#else
 648/* this routine implements insw(,,). There was a time i had the
 649   impression that there would be any difference in error-behaviour. */
 650void transport_data(int port, ush * dest, int count)
 651{
 652        int i;
 653        ush *d;
 654        for (i = 0, d = dest; i < count; i++, d++)
 655                *d = inw(port);
 656}
 657#endif
 658
 659
 660#define MAX_TRIES 100
 661int read_sector(int start)
 662{
 663        int tries = 0;
 664        if (cd->background) {
 665                cd->background = 0;
 666                cd->adapter_last = -1;  /* invalidate adapter memory */
 667                stop_read();
 668        }
 669        cd->fifo_overflowed = 0;
 670        reset_cm260();          /* empty fifo etc. */
 671        if (start_read(start))
 672                return -1;
 673        do {
 674                if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
 675                        debug(("Read timed out sector 0x%x\n", start));
 676                        stats(read_timeout);
 677                        stop_read();
 678                        return -3;
 679                }
 680                tries++;
 681        } while (cd->intr_ds & ds_fifo_empty && tries < MAX_TRIES);
 682        if (tries > 1)
 683                debug(("Took me some tries\n"))
 684                    else
 685        if (tries == MAX_TRIES)
 686                debug(("MAX_TRIES tries for read sector\n"));
 687        transport_data(r_fifo_output_buffer, cd->sector,
 688                       READ_AHEAD * RAW_SECTOR_SIZE / 2);
 689        if (read_background(start + READ_AHEAD, 1))
 690                stats(read_background);
 691        cd->sector_first = start;
 692        cd->sector_last = start + READ_AHEAD;
 693        stats(read_restarted);
 694        return 0;
 695}
 696
 697/* The function of bottom-half is to send a stop command to the drive
 698   This isn't easy because the routine is not `owned' by any process;
 699   we can't go to sleep! The variable cd->background gives the status:
 700   0 no read pending
 701   1 a read is pending
 702   2 c_stop waits for write_buffer_empty
 703   3 c_stop waits for receive_buffer_full: echo
 704   4 c_stop waits for receive_buffer_full: 0xff
 705*/
 706
 707static void cm206_tasklet_func(unsigned long ignore)
 708{
 709        debug(("bh: %d\n", cd->background));
 710        switch (cd->background) {
 711        case 1:
 712                stats(bh);
 713                if (!(cd->intr_ls & ls_transmitter_buffer_empty)) {
 714                        cd->command = c_stop;
 715                        outw(dc_mask_sync_error | dc_no_stop_on_error |
 716                             (inw(r_data_status) & 0x7f), r_data_control);
 717                        cd->background = 2;
 718                        break;  /* we'd better not time-out here! */
 719                } else
 720                        outw(c_stop, r_uart_transmit);
 721                /* fall into case 2: */
 722        case 2:
 723                /* the write has been satisfied by interrupt routine */
 724                cd->background = 3;
 725                break;
 726        case 3:
 727                if (cd->ur_r != cd->ur_w) {
 728                        if (cd->ur[cd->ur_r] != c_stop) {
 729                                debug(("cm206_bh: c_stop echoed 0x%x\n",
 730                                       cd->ur[cd->ur_r]));
 731                                stats(echo);
 732                        }
 733                        cd->ur_r++;
 734                        cd->ur_r %= UR_SIZE;
 735                }
 736                cd->background++;
 737                break;
 738        case 4:
 739                if (cd->ur_r != cd->ur_w) {
 740                        if (cd->ur[cd->ur_r] != 0xff) {
 741                                debug(("cm206_bh: c_stop reacted with 0x%x\n", cd->ur[cd->ur_r]));
 742                                stats(stop_0xff);
 743                        }
 744                        cd->ur_r++;
 745                        cd->ur_r %= UR_SIZE;
 746                }
 747                cd->background = 0;
 748        }
 749}
 750
 751static DECLARE_TASKLET(cm206_tasklet, cm206_tasklet_func, 0);
 752
 753/* This command clears the dsb_possible_media_change flag, so we must 
 754 * retain it.
 755 */
 756void get_drive_status(void)
 757{
 758        uch status[2];
 759        type_1_command(c_drive_status, 2, status);      /* this might be done faster */
 760        cd->dsb = status[0];
 761        cd->cc = status[1];
 762        cd->media_changed |=
 763            !!(cd->dsb & (dsb_possible_media_change |
 764                          dsb_drive_not_ready | dsb_tray_not_closed));
 765}
 766
 767void get_disc_status(void)
 768{
 769        if (type_1_command(c_disc_status, 7, cd->disc_status)) {
 770                debug(("get_disc_status: error\n"));
 771        }
 772}
 773
 774/* The new open. The real opening strategy is defined in cdrom.c. */
 775
 776static int cm206_open(struct cdrom_device_info *cdi, int purpose)
 777{
 778        if (!cd->openfiles) {   /* reset only first time */
 779                cd->background = 0;
 780                reset_cm260();
 781                cd->adapter_last = -1;  /* invalidate adapter memory */
 782                cd->sector_last = -1;
 783        }
 784        ++cd->openfiles;
 785        stats(open);
 786        return 0;
 787}
 788
 789static void cm206_release(struct cdrom_device_info *cdi)
 790{
 791        if (cd->openfiles == 1) {
 792                if (cd->background) {
 793                        cd->background = 0;
 794                        stop_read();
 795                }
 796                cd->sector_last = -1;   /* Make our internal buffer invalid */
 797                FIRST_TRACK = 0;        /* No valid disc status */
 798        }
 799        --cd->openfiles;
 800}
 801
 802/* Empty buffer empties $sectors$ sectors of the adapter card buffer,
 803 * and then reads a sector in kernel memory.  */
 804void empty_buffer(int sectors)
 805{
 806        while (sectors >= 0) {
 807                transport_data(r_fifo_output_buffer,
 808                               cd->sector + cd->fifo_overflowed,
 809                               RAW_SECTOR_SIZE / 2 - cd->fifo_overflowed);
 810                --sectors;
 811                ++cd->adapter_first;    /* update the current adapter sector */
 812                cd->fifo_overflowed = 0;        /* reset overflow bit */
 813                stats(sector_transferred);
 814        }
 815        cd->sector_first = cd->adapter_first - 1;
 816        cd->sector_last = cd->adapter_first;    /* update the buffer sector */
 817}
 818
 819/* try_adapter. This function determines if the requested sector is
 820   in adapter memory, or will appear there soon. Returns 0 upon
 821   success */
 822int try_adapter(int sector)
 823{
 824        if (cd->adapter_first <= sector && sector < cd->adapter_last) {
 825                /* sector is in adapter memory */
 826                empty_buffer(sector - cd->adapter_first);
 827                return 0;
 828        } else if (cd->background == 1 && cd->adapter_first <= sector
 829                   && sector < cd->adapter_first + cd->max_sectors) {
 830                /* a read is going on, we can wait for it */
 831                cd->wait_back = 1;
 832                while (sector >= cd->adapter_last) {
 833                        if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
 834                                debug(("Timed out during background wait: %d %d %d %d\n", sector, cd->adapter_last, cd->adapter_first, cd->background));
 835                                stats(back_read_timeout);
 836                                cd->wait_back = 0;
 837                                return -1;
 838                        }
 839                }
 840                cd->wait_back = 0;
 841                empty_buffer(sector - cd->adapter_first);
 842                return 0;
 843        } else
 844                return -2;
 845}
 846
 847/* This is not a very smart implementation. We could optimize for 
 848   consecutive block numbers. I'm not convinced this would really
 849   bring down the processor load. */
 850static void do_cm206_request(request_queue_t * q)
 851{
 852        long int i, cd_sec_no;
 853        int quarter, error;
 854        uch *source, *dest;
 855        struct request *req;
 856
 857        while (1) {     /* repeat until all requests have been satisfied */
 858                req = elv_next_request(q);
 859                if (!req)
 860                        return;
 861
 862                if (req->cmd != READ) {
 863                        debug(("Non-read command %d on cdrom\n", req->cmd));
 864                        end_request(req, 0);
 865                        continue;
 866                }
 867                spin_unlock_irq(q->queue_lock);
 868                error = 0;
 869                for (i = 0; i < req->nr_sectors; i++) {
 870                        int e1, e2;
 871                        cd_sec_no = (req->sector + i) / BLOCKS_ISO;     /* 4 times 512 bytes */
 872                        quarter = (req->sector + i) % BLOCKS_ISO;
 873                        dest = req->buffer + i * LINUX_BLOCK_SIZE;
 874                        /* is already in buffer memory? */
 875                        if (cd->sector_first <= cd_sec_no
 876                            && cd_sec_no < cd->sector_last) {
 877                                source =
 878                                    ((uch *) cd->sector) + 16 +
 879                                    quarter * LINUX_BLOCK_SIZE +
 880                                    (cd_sec_no -
 881                                     cd->sector_first) * RAW_SECTOR_SIZE;
 882                                memcpy(dest, source, LINUX_BLOCK_SIZE);
 883                        } else if (!(e1 = try_adapter(cd_sec_no)) ||
 884                                   !(e2 = read_sector(cd_sec_no))) {
 885                                source =
 886                                    ((uch *) cd->sector) + 16 +
 887                                    quarter * LINUX_BLOCK_SIZE;
 888                                memcpy(dest, source, LINUX_BLOCK_SIZE);
 889                        } else {
 890                                error = 1;
 891                                debug(("cm206_request: %d %d\n", e1, e2));
 892                        }
 893                }
 894                spin_lock_irq(q->queue_lock);
 895                end_request(req, !error);
 896        }
 897}
 898
 899/* Audio support. I've tried very hard, but the cm206 drive doesn't 
 900   seem to have a get_toc (table-of-contents) function, while i'm
 901   pretty sure it must read the toc upon disc insertion. Therefore
 902   this function has been implemented through a binary search 
 903   strategy. All track starts that happen to be found are stored in
 904   cd->toc[], for future use. 
 905
 906   I've spent a whole day on a bug that only shows under Workman---
 907   I don't get it. Tried everything, nothing works. If workman asks
 908   for track# 0xaa, it'll get the wrong time back. Any other program
 909   receives the correct value. I'm stymied.
 910*/
 911
 912/* seek seeks to address lba. It does wait to arrive there. */
 913void seek(int lba)
 914{
 915        int i;
 916        uch seek_command[4] = { c_seek, };
 917
 918        fsm(lba, &seek_command[1]);
 919        for (i = 0; i < 4; i++)
 920                type_0_command(seek_command[i], 0);
 921        cd->dsb = wait_dsb();
 922}
 923
 924uch bcdbin(unsigned char bcd)
 925{                               /* stolen from mcd.c! */
 926        return (bcd >> 4) * 10 + (bcd & 0xf);
 927}
 928
 929inline uch normalize_track(uch track)
 930{
 931        if (track < 1)
 932                return 1;
 933        if (track > LAST_TRACK)
 934                return LAST_TRACK + 1;
 935        return track;
 936}
 937
 938/* This function does a binary search for track start. It records all
 939 * tracks seen in the process. Input $track$ must be between 1 and
 940 * #-of-tracks+1.  Note that the start of the disc must be in toc[1].fsm. 
 941 */
 942int get_toc_lba(uch track)
 943{
 944        int max = 74 * 60 * 75 - 150, min = fsm2lba(cd->toc[1].fsm);
 945        int i, lba, l, old_lba = 0;
 946        uch *q = cd->q;
 947        uch ct;                 /* current track */
 948        int binary = 0;
 949        const int skip = 3 * 60 * 75;   /* 3 minutes */
 950
 951        for (i = track; i > 0; i--)
 952                if (cd->toc[i].track) {
 953                        min = fsm2lba(cd->toc[i].fsm);
 954                        break;
 955                }
 956        lba = min + skip;
 957        do {
 958                seek(lba);
 959                type_1_command(c_read_current_q, 10, q);
 960                ct = normalize_track(q[1]);
 961                if (!cd->toc[ct].track) {
 962                        l = q[9] - bcdbin(q[5]) + 75 * (q[8] -
 963                                                        bcdbin(q[4]) - 2 +
 964                                                        60 * (q[7] -
 965                                                              bcdbin(q
 966                                                                     [3])));
 967                        cd->toc[ct].track = q[1];       /* lead out still 0xaa */
 968                        fsm(l, cd->toc[ct].fsm);
 969                        cd->toc[ct].q0 = q[0];  /* contains adr and ctrl info */
 970                        if (ct == track)
 971                                return l;
 972                }
 973                old_lba = lba;
 974                if (binary) {
 975                        if (ct < track)
 976                                min = lba;
 977                        else
 978                                max = lba;
 979                        lba = (min + max) / 2;
 980                } else {
 981                        if (ct < track)
 982                                lba += skip;
 983                        else {
 984                                binary = 1;
 985                                max = lba;
 986                                min = lba - skip;
 987                                lba = (min + max) / 2;
 988                        }
 989                }
 990        } while (lba != old_lba);
 991        return lba;
 992}
 993
 994void update_toc_entry(uch track)
 995{
 996        track = normalize_track(track);
 997        if (!cd->toc[track].track)
 998                get_toc_lba(track);
 999}
1000
1001/* return 0 upon success */
1002int read_toc_header(struct cdrom_tochdr *hp)
1003{
1004        if (!FIRST_TRACK)
1005                get_disc_status();
1006        if (hp) {
1007                int i;
1008                hp->cdth_trk0 = FIRST_TRACK;
1009                hp->cdth_trk1 = LAST_TRACK;
1010                /* fill in first track position */
1011                for (i = 0; i < 3; i++)
1012                        cd->toc[1].fsm[i] = cd->disc_status[3 + i];
1013                update_toc_entry(LAST_TRACK + 1);       /* find most entries */
1014                return 0;
1015        }
1016        return -1;
1017}
1018
1019void play_from_to_msf(struct cdrom_msf *msfp)
1020{
1021        uch play_command[] = { c_play,
1022                msfp->cdmsf_frame0, msfp->cdmsf_sec0, msfp->cdmsf_min0,
1023                msfp->cdmsf_frame1, msfp->cdmsf_sec1, msfp->cdmsf_min1, 2,
1024                    2
1025        };
1026        int i;
1027        for (i = 0; i < 9; i++)
1028                type_0_command(play_command[i], 0);
1029        for (i = 0; i < 3; i++)
1030                PLAY_TO.fsm[i] = play_command[i + 4];
1031        PLAY_TO.track = 0;      /* say no track end */
1032        cd->dsb = wait_dsb();
1033}
1034
1035void play_from_to_track(int from, int to)
1036{
1037        uch play_command[8] = { c_play, };
1038        int i;
1039
1040        if (from == 0) {        /* continue paused play */
1041                for (i = 0; i < 3; i++) {
1042                        play_command[i + 1] = cd->audio_status[i + 2];
1043                        play_command[i + 4] = PLAY_TO.fsm[i];
1044                }
1045        } else {
1046                update_toc_entry(from);
1047                update_toc_entry(to + 1);
1048                for (i = 0; i < 3; i++) {
1049                        play_command[i + 1] = cd->toc[from].fsm[i];
1050                        PLAY_TO.fsm[i] = play_command[i + 4] =
1051                            cd->toc[to + 1].fsm[i];
1052                }
1053                PLAY_TO.track = to;
1054        }
1055        for (i = 0; i < 7; i++)
1056                type_0_command(play_command[i], 0);
1057        for (i = 0; i < 2; i++)
1058                type_0_command(0x2, 0); /* volume */
1059        cd->dsb = wait_dsb();
1060}
1061
1062int get_current_q(struct cdrom_subchnl *qp)
1063{
1064        int i;
1065        uch *q = cd->q;
1066        if (type_1_command(c_read_current_q, 10, q))
1067                return 0;
1068/*  q[0] = bcdbin(q[0]); Don't think so! */
1069        for (i = 2; i < 6; i++)
1070                q[i] = bcdbin(q[i]);
1071        qp->cdsc_adr = q[0] & 0xf;
1072        qp->cdsc_ctrl = q[0] >> 4;      /* from mcd.c */
1073        qp->cdsc_trk = q[1];
1074        qp->cdsc_ind = q[2];
1075        if (qp->cdsc_format == CDROM_MSF) {
1076                qp->cdsc_reladdr.msf.minute = q[3];
1077                qp->cdsc_reladdr.msf.second = q[4];
1078                qp->cdsc_reladdr.msf.frame = q[5];
1079                qp->cdsc_absaddr.msf.minute = q[7];
1080                qp->cdsc_absaddr.msf.second = q[8];
1081                qp->cdsc_absaddr.msf.frame = q[9];
1082        } else {
1083                qp->cdsc_reladdr.lba = f_s_m2lba(q[5], q[4], q[3]);
1084                qp->cdsc_absaddr.lba = f_s_m2lba(q[9], q[8], q[7]);
1085        }
1086        get_drive_status();
1087        if (cd->dsb & dsb_play_in_progress)
1088                qp->cdsc_audiostatus = CDROM_AUDIO_PLAY;
1089        else if (PAUSED)
1090                qp->cdsc_audiostatus = CDROM_AUDIO_PAUSED;
1091        else
1092                qp->cdsc_audiostatus = CDROM_AUDIO_NO_STATUS;
1093        return 0;
1094}
1095
1096void invalidate_toc(void)
1097{
1098        memset(cd->toc, 0, sizeof(cd->toc));
1099        memset(cd->disc_status, 0, sizeof(cd->disc_status));
1100}
1101
1102/* cdrom.c guarantees that cdte_format == CDROM_MSF */
1103void get_toc_entry(struct cdrom_tocentry *ep)
1104{
1105        uch track = normalize_track(ep->cdte_track);
1106        update_toc_entry(track);
1107        ep->cdte_addr.msf.frame = cd->toc[track].fsm[0];
1108        ep->cdte_addr.msf.second = cd->toc[track].fsm[1];
1109        ep->cdte_addr.msf.minute = cd->toc[track].fsm[2];
1110        ep->cdte_adr = cd->toc[track].q0 & 0xf;
1111        ep->cdte_ctrl = cd->toc[track].q0 >> 4;
1112        ep->cdte_datamode = 0;
1113}
1114
1115/* Audio ioctl.  Ioctl commands connected to audio are in such an
1116 * idiosyncratic i/o format, that we leave these untouched. Return 0
1117 * upon success. Memory checking has been done by cdrom_ioctl(), the
1118 * calling function, as well as LBA/MSF sanitization.
1119*/
1120int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
1121                      void *arg)
1122{
1123        switch (cmd) {
1124        case CDROMREADTOCHDR:
1125                return read_toc_header((struct cdrom_tochdr *) arg);
1126        case CDROMREADTOCENTRY:
1127                get_toc_entry((struct cdrom_tocentry *) arg);
1128                return 0;
1129        case CDROMPLAYMSF:
1130                play_from_to_msf((struct cdrom_msf *) arg);
1131                return 0;
1132        case CDROMPLAYTRKIND:   /* admittedly, not particularly beautiful */
1133                play_from_to_track(((struct cdrom_ti *) arg)->cdti_trk0,
1134                                   ((struct cdrom_ti *) arg)->cdti_trk1);
1135                return 0;
1136        case CDROMSTOP:
1137                PAUSED = 0;
1138                if (cd->dsb & dsb_play_in_progress)
1139                        return type_0_command(c_stop, 1);
1140                else
1141                        return 0;
1142        case CDROMPAUSE:
1143                get_drive_status();
1144                if (cd->dsb & dsb_play_in_progress) {
1145                        type_0_command(c_stop, 1);
1146                        type_1_command(c_audio_status, 5,
1147                                       cd->audio_status);
1148                        PAUSED = 1;     /* say we're paused */
1149                }
1150                return 0;
1151        case CDROMRESUME:
1152                if (PAUSED)
1153                        play_from_to_track(0, 0);
1154                PAUSED = 0;
1155                return 0;
1156        case CDROMSTART:
1157        case CDROMVOLCTRL:
1158                return 0;
1159        case CDROMSUBCHNL:
1160                return get_current_q((struct cdrom_subchnl *) arg);
1161        default:
1162                return -EINVAL;
1163        }
1164}
1165
1166/* Ioctl. These ioctls are specific to the cm206 driver. I have made
1167   some driver statistics accessible through ioctl calls.
1168 */
1169
1170static int cm206_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
1171                       unsigned long arg)
1172{
1173        switch (cmd) {
1174#ifdef STATISTICS
1175        case CM206CTL_GET_STAT:
1176                if (arg >= NR_STATS)
1177                        return -EINVAL;
1178                else
1179                        return cd->stats[arg];
1180        case CM206CTL_GET_LAST_STAT:
1181                if (arg >= NR_STATS)
1182                        return -EINVAL;
1183                else
1184                        return cd->last_stat[arg];
1185#endif
1186        default:
1187                debug(("Unknown ioctl call 0x%x\n", cmd));
1188                return -EINVAL;
1189        }
1190}
1191
1192int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr)
1193{
1194        if (cd != NULL) {
1195                int r;
1196                get_drive_status();     /* ensure cd->media_changed OK */
1197                r = cd->media_changed;
1198                cd->media_changed = 0;  /* clear bit */
1199                return r;
1200        } else
1201                return -EIO;
1202}
1203
1204/* The new generic cdrom support. Routines should be concise, most of
1205   the logic should be in cdrom.c */
1206
1207/* returns number of times device is in use */
1208int cm206_open_files(struct cdrom_device_info *cdi)
1209{
1210        if (cd)
1211                return cd->openfiles;
1212        return -1;
1213}
1214
1215/* controls tray movement */
1216int cm206_tray_move(struct cdrom_device_info *cdi, int position)
1217{
1218        if (position) {         /* 1: eject */
1219                type_0_command(c_open_tray, 1);
1220                invalidate_toc();
1221        } else
1222                type_0_command(c_close_tray, 1);        /* 0: close */
1223        return 0;
1224}
1225
1226/* gives current state of the drive */
1227int cm206_drive_status(struct cdrom_device_info *cdi, int slot_nr)
1228{
1229        get_drive_status();
1230        if (cd->dsb & dsb_tray_not_closed)
1231                return CDS_TRAY_OPEN;
1232        if (!(cd->dsb & dsb_disc_present))
1233                return CDS_NO_DISC;
1234        if (cd->dsb & dsb_drive_not_ready)
1235                return CDS_DRIVE_NOT_READY;
1236        return CDS_DISC_OK;
1237}
1238
1239/* locks or unlocks door lock==1: lock; return 0 upon success */
1240int cm206_lock_door(struct cdrom_device_info *cdi, int lock)
1241{
1242        uch command = (lock) ? c_lock_tray : c_unlock_tray;
1243        type_0_command(command, 1);     /* wait and get dsb */
1244        /* the logic calculates the success, 0 means successful */
1245        return lock ^ ((cd->dsb & dsb_tray_locked) != 0);
1246}
1247
1248/* Although a session start should be in LBA format, we return it in 
1249   MSF format because it is slightly easier, and the new generic ioctl
1250   will take care of the necessary conversion. */
1251int cm206_get_last_session(struct cdrom_device_info *cdi,
1252                           struct cdrom_multisession *mssp)
1253{
1254        if (!FIRST_TRACK)
1255                get_disc_status();
1256        if (mssp != NULL) {
1257                if (DISC_STATUS & cds_multi_session) {  /* multi-session */
1258                        mssp->addr.msf.frame = cd->disc_status[3];
1259                        mssp->addr.msf.second = cd->disc_status[4];
1260                        mssp->addr.msf.minute = cd->disc_status[5];
1261                        mssp->addr_format = CDROM_MSF;
1262                        mssp->xa_flag = 1;
1263                } else {
1264                        mssp->xa_flag = 0;
1265                }
1266                return 1;
1267        }
1268        return 0;
1269}
1270
1271int cm206_get_upc(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
1272{
1273        uch upc[10];
1274        char *ret = mcn->medium_catalog_number;
1275        int i;
1276
1277        if (type_1_command(c_read_upc, 10, upc))
1278                return -EIO;
1279        for (i = 0; i < 13; i++) {
1280                int w = i / 2 + 1, r = i % 2;
1281                if (r)
1282                        ret[i] = 0x30 | (upc[w] & 0x0f);
1283                else
1284                        ret[i] = 0x30 | ((upc[w] >> 4) & 0x0f);
1285        }
1286        ret[13] = '\0';
1287        return 0;
1288}
1289
1290int cm206_reset(struct cdrom_device_info *cdi)
1291{
1292        stop_read();
1293        reset_cm260();
1294        outw(dc_normal | dc_break | READ_AHEAD, r_data_control);
1295        mdelay(1);              /* 750 musec minimum */
1296        outw(dc_normal | READ_AHEAD, r_data_control);
1297        cd->sector_last = -1;   /* flag no data buffered */
1298        cd->adapter_last = -1;
1299        invalidate_toc();
1300        return 0;
1301}
1302
1303int cm206_select_speed(struct cdrom_device_info *cdi, int speed)
1304{
1305        int r;
1306        switch (speed) {
1307        case 0:
1308                r = type_0_command(c_auto_mode, 1);
1309                break;
1310        case 1:
1311                r = type_0_command(c_force_1x, 1);
1312                break;
1313        case 2:
1314                r = type_0_command(c_force_2x, 1);
1315                break;
1316        default:
1317                return -1;
1318        }
1319        if (r < 0)
1320                return r;
1321        else
1322                return 1;
1323}
1324
1325static struct cdrom_device_ops cm206_dops = {
1326        .open                   = cm206_open,
1327        .release                = cm206_release,
1328        .drive_status           = cm206_drive_status,
1329        .media_changed          = cm206_media_changed,
1330        .tray_move              = cm206_tray_move,
1331        .lock_door              = cm206_lock_door,
1332        .select_speed           = cm206_select_speed,
1333        .get_last_session       = cm206_get_last_session,
1334        .get_mcn                = cm206_get_upc,
1335        .reset                  = cm206_reset,
1336        .audio_ioctl            = cm206_audio_ioctl,
1337        .dev_ioctl              = cm206_ioctl,
1338        .capability             = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
1339                                  CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
1340                                  CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED |
1341                                  CDC_IOCTLS | CDC_DRIVE_STATUS,
1342        .n_minors               = 1,
1343};
1344
1345
1346static struct cdrom_device_info cm206_info = {
1347        .ops            = &cm206_dops,
1348        .speed          = 2,
1349        .capacity       = 1,
1350        .name           = "cm206",
1351};
1352
1353static int cm206_block_open(struct inode *inode, struct file *file)
1354{
1355        return cdrom_open(&cm206_info, inode, file);
1356}
1357
1358static int cm206_block_release(struct inode *inode, struct file *file)
1359{
1360        return cdrom_release(&cm206_info, file);
1361}
1362
1363static int cm206_block_ioctl(struct inode *inode, struct file *file,
1364                                unsigned cmd, unsigned long arg)
1365{
1366        return cdrom_ioctl(file, &cm206_info, inode, cmd, arg);
1367}
1368
1369static int cm206_block_media_changed(struct gendisk *disk)
1370{
1371        return cdrom_media_changed(&cm206_info);
1372}
1373
1374static struct block_device_operations cm206_bdops =
1375{
1376        .owner          = THIS_MODULE,
1377        .open           = cm206_block_open,
1378        .release        = cm206_block_release,
1379        .ioctl          = cm206_block_ioctl,
1380        .media_changed  = cm206_block_media_changed,
1381};
1382
1383static struct gendisk *cm206_gendisk;
1384
1385/* This function probes for the adapter card. It returns the base
1386   address if it has found the adapter card. One can specify a base 
1387   port to probe specifically, or 0 which means span all possible
1388   bases. 
1389
1390   Linus says it is too dangerous to use writes for probing, so we
1391   stick with pure reads for a while. Hope that 8 possible ranges,
1392   request_region, 15 bits of one port and 6 of another make things
1393   likely enough to accept the region on the first hit...
1394 */
1395int __init probe_base_port(int base)
1396{
1397        int b = 0x300, e = 0x370;       /* this is the range of start addresses */
1398        volatile int fool, i;
1399
1400        if (base)
1401                b = e = base;
1402        for (base = b; base <= e; base += 0x10) {
1403                if (!request_region(base, 0x10,"cm206"))
1404                        continue;
1405                for (i = 0; i < 3; i++)
1406                        fool = inw(base + 2);   /* empty possibly uart_receive_buffer */
1407                if ((inw(base + 6) & 0xffef) != 0x0001 ||       /* line_status */
1408                    (inw(base) & 0xad00) != 0)  { /* data status */
1409                        release_region(base,0x10);
1410                        continue;
1411                }
1412                return (base);
1413        }
1414        return 0;
1415}
1416
1417#if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
1418/* Probe for irq# nr. If nr==0, probe for all possible irq's. */
1419int __init probe_irq(int nr)
1420{
1421        int irqs, irq;
1422        outw(dc_normal | READ_AHEAD, r_data_control);   /* disable irq-generation */
1423        sti();
1424        irqs = probe_irq_on();
1425        reset_cm260();          /* causes interrupt */
1426        udelay(100);            /* wait for it */
1427        irq = probe_irq_off(irqs);
1428        outw(dc_normal | READ_AHEAD, r_data_control);   /* services interrupt */
1429        if (nr && irq != nr && irq > 0)
1430                return 0;       /* wrong interrupt happened */
1431        else
1432                return irq;
1433}
1434#endif
1435
1436int __init cm206_init(void)
1437{
1438        uch e = 0;
1439        long int size = sizeof(struct cm206_struct);
1440        struct gendisk *disk;
1441
1442        printk(KERN_INFO "cm206 cdrom driver " REVISION);
1443        cm206_base = probe_base_port(auto_probe ? 0 : cm206_base);
1444        if (!cm206_base) {
1445                printk(" can't find adapter!\n");
1446                return -EIO;
1447        }
1448        printk(" adapter at 0x%x", cm206_base);
1449        cd = (struct cm206_struct *) kmalloc(size, GFP_KERNEL);
1450        if (!cd)
1451               goto out_base;
1452        /* Now we have found the adaptor card, try to reset it. As we have
1453         * found out earlier, this process generates an interrupt as well,
1454         * so we might just exploit that fact for irq probing! */
1455#if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
1456        cm206_irq = probe_irq(auto_probe ? 0 : cm206_irq);
1457        if (cm206_irq <= 0) {
1458                printk("can't find IRQ!\n");
1459                goto out_probe;
1460        } else
1461                printk(" IRQ %d found\n", cm206_irq);
1462#else
1463        cli();
1464        reset_cm260();
1465        /* Now, the problem here is that reset_cm260 can generate an
1466           interrupt. It seems that this can cause a kernel oops some time
1467           later. So we wait a while and `service' this interrupt. */
1468        mdelay(1);
1469        outw(dc_normal | READ_AHEAD, r_data_control);
1470        sti();
1471        printk(" using IRQ %d\n", cm206_irq);
1472#endif
1473        if (send_receive_polled(c_drive_configuration) !=
1474            c_drive_configuration) {
1475                printk(KERN_INFO " drive not there\n");
1476                goto out_probe;
1477        }
1478        e = send_receive_polled(c_gimme);
1479        printk(KERN_INFO "Firmware revision %d", e & dcf_revision_code);
1480        if (e & dcf_transfer_rate)
1481                printk(" double");
1482        else
1483                printk(" single");
1484        printk(" speed drive");
1485        if (e & dcf_motorized_tray)
1486                printk(", motorized tray");
1487        if (request_irq(cm206_irq, cm206_interrupt, 0, "cm206", NULL)) {
1488                printk("\nUnable to reserve IRQ---aborted\n");
1489                goto out_probe;
1490        }
1491        printk(".\n");
1492
1493        if (register_blkdev(MAJOR_NR, "cm206"))
1494                goto out_blkdev;
1495
1496        disk = alloc_disk(1);
1497        if (!disk)
1498                goto out_disk;
1499        disk->major = MAJOR_NR;
1500        disk->first_minor = 0;
1501        sprintf(disk->disk_name, "cm206cd");
1502        disk->fops = &cm206_bdops;
1503        disk->flags = GENHD_FL_CD;
1504        cm206_gendisk = disk;
1505        if (register_cdrom(&cm206_info) != 0) {
1506                printk(KERN_INFO "Cannot register for cdrom %d!\n", MAJOR_NR);
1507                goto out_cdrom;
1508        }
1509        cm206_queue = blk_init_queue(do_cm206_request, &cm206_lock);
1510        if (!cm206_queue)
1511                goto out_queue;
1512                
1513        blk_queue_hardsect_size(cm206_queue, 2048);
1514        disk->queue = cm206_queue;
1515        add_disk(disk);
1516
1517        memset(cd, 0, sizeof(*cd));     /* give'm some reasonable value */
1518        cd->sector_last = -1;   /* flag no data buffered */
1519        cd->adapter_last = -1;
1520        init_timer(&cd->timer);
1521        cd->timer.function = cm206_timeout;
1522        cd->max_sectors = (inw(r_data_status) & ds_ram_size) ? 24 : 97;
1523        printk(KERN_INFO "%d kB adapter memory available, "
1524               " %ld bytes kernel memory used.\n", cd->max_sectors * 2,
1525               size);
1526        return 0;
1527
1528out_queue:
1529        unregister_cdrom(&cm206_info);
1530out_cdrom:
1531        put_disk(disk);
1532out_disk:
1533        unregister_blkdev(MAJOR_NR, "cm206");
1534out_blkdev:
1535        free_irq(cm206_irq, NULL);
1536out_probe:
1537        kfree(cd);
1538out_base:
1539        release_region(cm206_base, 16);
1540        return -EIO;
1541}
1542
1543#ifdef MODULE
1544
1545
1546static void __init parse_options(void)
1547{
1548        int i;
1549        for (i = 0; i < 2; i++) {
1550                if (0x300 <= cm206[i] && i <= 0x370
1551                    && cm206[i] % 0x10 == 0) {
1552                        cm206_base = cm206[i];
1553                        auto_probe = 0;
1554                } else if (3 <= cm206[i] && cm206[i] <= 15) {
1555                        cm206_irq = cm206[i];
1556                        auto_probe = 0;
1557                }
1558        }
1559}
1560
1561int __cm206_init(void)
1562{
1563        parse_options();
1564#if !defined(AUTO_PROBE_MODULE)
1565        auto_probe = 0;
1566#endif
1567        return cm206_init();
1568}
1569
1570void __exit cm206_exit(void)
1571{
1572        del_gendisk(cm206_gendisk);
1573        put_disk(cm206_gendisk);
1574        if (unregister_cdrom(&cm206_info)) {
1575                printk("Can't unregister cdrom cm206\n");
1576                return;
1577        }
1578        if (unregister_blkdev(MAJOR_NR, "cm206")) {
1579                printk("Can't unregister major cm206\n");
1580                return;
1581        }
1582        blk_cleanup_queue(cm206_queue);
1583        free_irq(cm206_irq, NULL);
1584        kfree(cd);
1585        release_region(cm206_base, 16);
1586        printk(KERN_INFO "cm206 removed\n");
1587}
1588
1589module_init(__cm206_init);
1590module_exit(cm206_exit);
1591
1592#else                           /* !MODULE */
1593
1594/* This setup function accepts either `auto' or numbers in the range
1595 * 3--11 (for irq) or 0x300--0x370 (for base port) or both. */
1596
1597static int __init cm206_setup(char *s)
1598{
1599        int i, p[4];
1600
1601        (void) get_options(s, ARRAY_SIZE(p), p);
1602
1603        if (!strcmp(s, "auto"))
1604                auto_probe = 1;
1605        for (i = 1; i <= p[0]; i++) {
1606                if (0x300 <= p[i] && i <= 0x370 && p[i] % 0x10 == 0) {
1607                        cm206_base = p[i];
1608                        auto_probe = 0;
1609                } else if (3 <= p[i] && p[i] <= 15) {
1610                        cm206_irq = p[i];
1611                        auto_probe = 0;
1612                }
1613        }
1614        return 1;
1615}
1616
1617__setup("cm206=", cm206_setup);
1618
1619#endif                          /* !MODULE */
1620MODULE_ALIAS_BLOCKDEV_MAJOR(CM206_CDROM_MAJOR);
1621
1622/*
1623 * Local variables:
1624 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -m486 -DMODULE -DMODVERSIONS -include /usr/src/linux/include/linux/modversions.h  -c -o cm206.o cm206.c"
1625 * End:
1626 */
1627
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.