linux-old/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#include <linux/blk.h>
 202
 203#undef DEBUG
 204#define STATISTICS              /* record times and frequencies of events */
 205#define AUTO_PROBE_MODULE
 206#define USE_INSW
 207
 208#include "cm206.h"
 209
 210/* This variable defines whether or not to probe for adapter base port 
 211   address and interrupt request. It can be overridden by the boot 
 212   parameter `auto'.
 213*/
 214static int auto_probe = 1;      /* Yes, why not? */
 215
 216static int cm206_base = CM206_BASE;
 217static int cm206_irq = CM206_IRQ;
 218#ifdef MODULE
 219static int cm206[2] = { 0, 0 }; /* for compatible `insmod' parameter passing */
 220#endif
 221
 222MODULE_PARM(cm206_base, "i");   /* base */
 223MODULE_PARM(cm206_irq, "i");    /* irq */
 224MODULE_PARM(cm206, "1-2i");     /* base,irq or irq,base */
 225MODULE_PARM(auto_probe, "i");   /* auto probe base and irq */
 226MODULE_LICENSE("GPL");
 227
 228#define POLLOOP 100             /* milliseconds */
 229#define READ_AHEAD 1            /* defines private buffer, waste! */
 230#define BACK_AHEAD 1            /* defines adapter-read ahead */
 231#define DATA_TIMEOUT (3*HZ)     /* measured in jiffies (10 ms) */
 232#define UART_TIMEOUT (5*HZ/100)
 233#define DSB_TIMEOUT (7*HZ)      /* time for the slowest command to finish */
 234#define UR_SIZE 4               /* uart receive buffer fifo size */
 235
 236#define LINUX_BLOCK_SIZE 512    /* WHERE is this defined? */
 237#define RAW_SECTOR_SIZE 2352    /* ok, is also defined in cdrom.h */
 238#define ISO_SECTOR_SIZE 2048
 239#define BLOCKS_ISO (ISO_SECTOR_SIZE/LINUX_BLOCK_SIZE)   /* 4 */
 240#define CD_SYNC_HEAD 16         /* CD_SYNC + CD_HEAD */
 241
 242#ifdef STATISTICS               /* keep track of errors in counters */
 243#define stats(i) { ++cd->stats[st_ ## i]; \
 244                     cd->last_stat[st_ ## i] = cd->stat_counter++; \
 245                 }
 246#else
 247#define stats(i) (void) 0;
 248#endif
 249
 250#define Debug(a) {printk (KERN_DEBUG); printk a;}
 251#ifdef DEBUG
 252#define debug(a) Debug(a)
 253#else
 254#define debug(a) (void) 0;
 255#endif
 256
 257typedef unsigned char uch;      /* 8-bits */
 258typedef unsigned short ush;     /* 16-bits */
 259
 260struct toc_struct {             /* private copy of Table of Contents */
 261        uch track, fsm[3], q0;
 262};
 263
 264static int cm206_blocksizes[1] = { 2048 };
 265
 266struct cm206_struct {
 267        volatile ush intr_ds;   /* data status read on last interrupt */
 268        volatile ush intr_ls;   /* uart line status read on last interrupt */
 269        volatile uch ur[UR_SIZE];       /* uart receive buffer fifo */
 270        volatile uch ur_w, ur_r;        /* write/read buffer index */
 271        volatile uch dsb, cc;   /* drive status byte and condition (error) code */
 272        int command;            /* command to be written to the uart */
 273        int openfiles;
 274        ush sector[READ_AHEAD * RAW_SECTOR_SIZE / 2];   /* buffered cd-sector */
 275        int sector_first, sector_last;  /* range of these sectors */
 276        wait_queue_head_t uart; /* wait queues for interrupt */
 277        wait_queue_head_t data;
 278        struct timer_list timer;        /* time-out */
 279        char timed_out;
 280        signed char max_sectors;        /* number of sectors that fit in adapter mem */
 281        char wait_back;         /* we're waiting for a background-read */
 282        char background;        /* is a read going on in the background? */
 283        int adapter_first;      /* if so, that's the starting sector */
 284        int adapter_last;
 285        char fifo_overflowed;
 286        uch disc_status[7];     /* result of get_disc_status command */
 287#ifdef STATISTICS
 288        int stats[NR_STATS];
 289        int last_stat[NR_STATS];        /* `time' at which stat was stat */
 290        int stat_counter;
 291#endif
 292        struct toc_struct toc[101];     /* The whole table of contents + lead-out */
 293        uch q[10];              /* Last read q-channel info */
 294        uch audio_status[5];    /* last read position on pause */
 295        uch media_changed;      /* record if media changed */
 296};
 297
 298#define DISC_STATUS cd->disc_status[0]
 299#define FIRST_TRACK cd->disc_status[1]
 300#define LAST_TRACK cd->disc_status[2]
 301#define PAUSED cd->audio_status[0]      /* misuse this memory byte! */
 302#define PLAY_TO cd->toc[0]      /* toc[0] records end-time in play */
 303
 304static struct cm206_struct *cd; /* the main memory structure */
 305
 306/* First, we define some polling functions. These are actually
 307   only being used in the initialization. */
 308
 309void send_command_polled(int command)
 310{
 311        int loop = POLLOOP;
 312        while (!(inw(r_line_status) & ls_transmitter_buffer_empty)
 313               && loop > 0) {
 314                mdelay(1);      /* one millisec delay */
 315                --loop;
 316        }
 317        outw(command, r_uart_transmit);
 318}
 319
 320uch receive_echo_polled(void)
 321{
 322        int loop = POLLOOP;
 323        while (!(inw(r_line_status) & ls_receive_buffer_full) && loop > 0) {
 324                mdelay(1);
 325                --loop;
 326        }
 327        return ((uch) inw(r_uart_receive));
 328}
 329
 330uch send_receive_polled(int command)
 331{
 332        send_command_polled(command);
 333        return receive_echo_polled();
 334}
 335
 336inline void clear_ur(void)
 337{
 338        if (cd->ur_r != cd->ur_w) {
 339                debug(("Deleting bytes from fifo:"));
 340                for (; cd->ur_r != cd->ur_w;
 341                     cd->ur_r++, cd->ur_r %= UR_SIZE)
 342                        debug((" 0x%x", cd->ur[cd->ur_r]));
 343                debug(("\n"));
 344        }
 345}
 346
 347/* The interrupt handler. When the cm260 generates an interrupt, very
 348   much care has to be taken in reading out the registers in the right
 349   order; in case of a receive_buffer_full interrupt, first the
 350   uart_receive must be read, and then the line status again to
 351   de-assert the interrupt line. It took me a couple of hours to find
 352   this out:-( 
 353
 354   The function reset_cm206 appears to cause an interrupt, because
 355   pulling up the INIT line clears both the uart-write-buffer /and/
 356   the uart-write-buffer-empty mask. We call this a `lost interrupt,'
 357   as there seems so reason for this to happen.
 358*/
 359
 360static void cm206_interrupt(int sig, void *dev_id, struct pt_regs *regs)
 361/* you rang? */
 362{
 363        volatile ush fool;
 364        cd->intr_ds = inw(r_data_status);       /* resets data_ready, data_error,
 365                                                   crc_error, sync_error, toc_ready 
 366                                                   interrupts */
 367        cd->intr_ls = inw(r_line_status);       /* resets overrun bit */
 368        debug(("Intr, 0x%x 0x%x, %d\n", cd->intr_ds, cd->intr_ls,
 369               cd->background));
 370        if (cd->intr_ls & ls_attention)
 371                stats(attention);
 372        /* receive buffer full? */
 373        if (cd->intr_ls & ls_receive_buffer_full) {
 374                cd->ur[cd->ur_w] = inb(r_uart_receive); /* get order right! */
 375                cd->intr_ls = inw(r_line_status);       /* resets rbf interrupt */
 376                debug(("receiving #%d: 0x%x\n", cd->ur_w,
 377                       cd->ur[cd->ur_w]));
 378                cd->ur_w++;
 379                cd->ur_w %= UR_SIZE;
 380                if (cd->ur_w == cd->ur_r)
 381                        debug(("cd->ur overflow!\n"));
 382                if (waitqueue_active(&cd->uart) && cd->background < 2) {
 383                        del_timer(&cd->timer);
 384                        wake_up_interruptible(&cd->uart);
 385                }
 386        }
 387        /* data ready in fifo? */
 388        else if (cd->intr_ds & ds_data_ready) {
 389                if (cd->background)
 390                        ++cd->adapter_last;
 391                if (waitqueue_active(&cd->data)
 392                    && (cd->wait_back || !cd->background)) {
 393                        del_timer(&cd->timer);
 394                        wake_up_interruptible(&cd->data);
 395                }
 396                stats(data_ready);
 397        }
 398        /* ready to issue a write command? */
 399        else if (cd->command && cd->intr_ls & ls_transmitter_buffer_empty) {
 400                outw(dc_normal | (inw(r_data_status) & 0x7f),
 401                     r_data_control);
 402                outw(cd->command, r_uart_transmit);
 403                cd->command = 0;
 404                if (!cd->background)
 405                        wake_up_interruptible(&cd->uart);
 406        }
 407        /* now treat errors (at least, identify them for debugging) */
 408        else if (cd->intr_ds & ds_fifo_overflow) {
 409                debug(("Fifo overflow at sectors 0x%x\n",
 410                       cd->sector_first));
 411                fool = inw(r_fifo_output_buffer);       /* de-assert the interrupt */
 412                cd->fifo_overflowed = 1;        /* signal one word less should be read */
 413                stats(fifo_overflow);
 414        } else if (cd->intr_ds & ds_data_error) {
 415                debug(("Data error at sector 0x%x\n", cd->sector_first));
 416                stats(data_error);
 417        } else if (cd->intr_ds & ds_crc_error) {
 418                debug(("CRC error at sector 0x%x\n", cd->sector_first));
 419                stats(crc_error);
 420        } else if (cd->intr_ds & ds_sync_error) {
 421                debug(("Sync at sector 0x%x\n", cd->sector_first));
 422                stats(sync_error);
 423        } else if (cd->intr_ds & ds_toc_ready) {
 424                /* do something appropriate */
 425        }
 426        /* couldn't see why this interrupt, maybe due to init */
 427        else {
 428                outw(dc_normal | READ_AHEAD, r_data_control);
 429                stats(lost_intr);
 430        }
 431        if (cd->background
 432            && (cd->adapter_last - cd->adapter_first == cd->max_sectors
 433                || cd->fifo_overflowed))
 434                mark_bh(CM206_BH);      /* issue a stop read command */
 435        stats(interrupt);
 436}
 437
 438/* we have put the address of the wait queue in who */
 439void cm206_timeout(unsigned long who)
 440{
 441        cd->timed_out = 1;
 442        debug(("Timing out\n"));
 443        wake_up_interruptible((wait_queue_head_t *) who);
 444}
 445
 446/* This function returns 1 if a timeout occurred, 0 if an interrupt
 447   happened */
 448int sleep_or_timeout(wait_queue_head_t * wait, int timeout)
 449{
 450        cd->timed_out = 0;
 451        cd->timer.data = (unsigned long) wait;
 452        cd->timer.expires = jiffies + timeout;
 453        add_timer(&cd->timer);
 454        debug(("going to sleep\n"));
 455        interruptible_sleep_on(wait);
 456        del_timer(&cd->timer);
 457        if (cd->timed_out) {
 458                cd->timed_out = 0;
 459                return 1;
 460        } else
 461                return 0;
 462}
 463
 464void cm206_delay(int nr_jiffies)
 465{
 466        DECLARE_WAIT_QUEUE_HEAD(wait);
 467        sleep_or_timeout(&wait, nr_jiffies);
 468}
 469
 470void send_command(int command)
 471{
 472        debug(("Sending 0x%x\n", command));
 473        if (!(inw(r_line_status) & ls_transmitter_buffer_empty)) {
 474                cd->command = command;
 475                cli();          /* don't interrupt before sleep */
 476                outw(dc_mask_sync_error | dc_no_stop_on_error |
 477                     (inw(r_data_status) & 0x7f), r_data_control);
 478                /* interrupt routine sends command */
 479                if (sleep_or_timeout(&cd->uart, UART_TIMEOUT)) {
 480                        debug(("Time out on write-buffer\n"));
 481                        stats(write_timeout);
 482                        outw(command, r_uart_transmit);
 483                }
 484                debug(("Write commmand delayed\n"));
 485        } else
 486                outw(command, r_uart_transmit);
 487}
 488
 489uch receive_byte(int timeout)
 490{
 491        uch ret;
 492        cli();
 493        debug(("cli\n"));
 494        ret = cd->ur[cd->ur_r];
 495        if (cd->ur_r != cd->ur_w) {
 496                sti();
 497                debug(("returning #%d: 0x%x\n", cd->ur_r,
 498                       cd->ur[cd->ur_r]));
 499                cd->ur_r++;
 500                cd->ur_r %= UR_SIZE;
 501                return ret;
 502        } else if (sleep_or_timeout(&cd->uart, timeout)) {      /* does sti() */
 503                debug(("Time out on receive-buffer\n"));
 504#ifdef STATISTICS
 505                if (timeout == UART_TIMEOUT)
 506                        stats(receive_timeout)  /* no `;'! */
 507                            else
 508                        stats(dsb_timeout);
 509#endif
 510                return 0xda;
 511        }
 512        ret = cd->ur[cd->ur_r];
 513        debug(("slept; returning #%d: 0x%x\n", cd->ur_r,
 514               cd->ur[cd->ur_r]));
 515        cd->ur_r++;
 516        cd->ur_r %= UR_SIZE;
 517        return ret;
 518}
 519
 520inline uch receive_echo(void)
 521{
 522        return receive_byte(UART_TIMEOUT);
 523}
 524
 525inline uch send_receive(int command)
 526{
 527        send_command(command);
 528        return receive_echo();
 529}
 530
 531inline uch wait_dsb(void)
 532{
 533        return receive_byte(DSB_TIMEOUT);
 534}
 535
 536int type_0_command(int command, int expect_dsb)
 537{
 538        int e;
 539        clear_ur();
 540        if (command != (e = send_receive(command))) {
 541                debug(("command 0x%x echoed as 0x%x\n", command, e));
 542                stats(echo);
 543                return -1;
 544        }
 545        if (expect_dsb) {
 546                cd->dsb = wait_dsb();   /* wait for command to finish */
 547        }
 548        return 0;
 549}
 550
 551int type_1_command(int command, int bytes, uch * status)
 552{                               /* returns info */
 553        int i;
 554        if (type_0_command(command, 0))
 555                return -1;
 556        for (i = 0; i < bytes; i++)
 557                status[i] = send_receive(c_gimme);
 558        return 0;
 559}
 560
 561/* This function resets the adapter card. We'd better not do this too
 562 * often, because it tends to generate `lost interrupts.' */
 563void reset_cm260(void)
 564{
 565        outw(dc_normal | dc_initialize | READ_AHEAD, r_data_control);
 566        udelay(10);             /* 3.3 mu sec minimum */
 567        outw(dc_normal | READ_AHEAD, r_data_control);
 568}
 569
 570/* fsm: frame-sec-min from linear address; one of many */
 571void fsm(int lba, uch * fsm)
 572{
 573        fsm[0] = lba % 75;
 574        lba /= 75;
 575        lba += 2;
 576        fsm[1] = lba % 60;
 577        fsm[2] = lba / 60;
 578}
 579
 580inline int fsm2lba(uch * fsm)
 581{
 582        return fsm[0] + 75 * (fsm[1] - 2 + 60 * fsm[2]);
 583}
 584
 585inline int f_s_m2lba(uch f, uch s, uch m)
 586{
 587        return f + 75 * (s - 2 + 60 * m);
 588}
 589
 590int start_read(int start)
 591{
 592        uch read_sector[4] = { c_read_data, };
 593        int i, e;
 594
 595        fsm(start, &read_sector[1]);
 596        clear_ur();
 597        for (i = 0; i < 4; i++)
 598                if (read_sector[i] != (e = send_receive(read_sector[i]))) {
 599                        debug(("read_sector: %x echoes %x\n",
 600                               read_sector[i], e));
 601                        stats(echo);
 602                        if (e == 0xff) {        /* this seems to happen often */
 603                                e = receive_echo();
 604                                debug(("Second try %x\n", e));
 605                                if (e != read_sector[i])
 606                                        return -1;
 607                        }
 608                }
 609        return 0;
 610}
 611
 612int stop_read(void)
 613{
 614        int e;
 615        type_0_command(c_stop, 0);
 616        if ((e = receive_echo()) != 0xff) {
 617                debug(("c_stop didn't send 0xff, but 0x%x\n", e));
 618                stats(stop_0xff);
 619                return -1;
 620        }
 621        return 0;
 622}
 623
 624/* This function starts to read sectors in adapter memory, the
 625   interrupt routine should stop the read. In fact, the bottom_half
 626   routine takes care of this. Set a flag `background' in the cd
 627   struct to indicate the process. */
 628
 629int read_background(int start, int reading)
 630{
 631        if (cd->background)
 632                return -1;      /* can't do twice */
 633        outw(dc_normal | BACK_AHEAD, r_data_control);
 634        if (!reading && start_read(start))
 635                return -2;
 636        cd->adapter_first = cd->adapter_last = start;
 637        cd->background = 1;     /* flag a read is going on */
 638        return 0;
 639}
 640
 641#ifdef USE_INSW
 642#define transport_data insw
 643#else
 644/* this routine implements insw(,,). There was a time i had the
 645   impression that there would be any difference in error-behaviour. */
 646void transport_data(int port, ush * dest, int count)
 647{
 648        int i;
 649        ush *d;
 650        for (i = 0, d = dest; i < count; i++, d++)
 651                *d = inw(port);
 652}
 653#endif
 654
 655
 656#define MAX_TRIES 100
 657int read_sector(int start)
 658{
 659        int tries = 0;
 660        if (cd->background) {
 661                cd->background = 0;
 662                cd->adapter_last = -1;  /* invalidate adapter memory */
 663                stop_read();
 664        }
 665        cd->fifo_overflowed = 0;
 666        reset_cm260();          /* empty fifo etc. */
 667        if (start_read(start))
 668                return -1;
 669        do {
 670                if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
 671                        debug(("Read timed out sector 0x%x\n", start));
 672                        stats(read_timeout);
 673                        stop_read();
 674                        return -3;
 675                }
 676                tries++;
 677        } while (cd->intr_ds & ds_fifo_empty && tries < MAX_TRIES);
 678        if (tries > 1)
 679                debug(("Took me some tries\n"))
 680                    else
 681        if (tries == MAX_TRIES)
 682                debug(("MAX_TRIES tries for read sector\n"));
 683        transport_data(r_fifo_output_buffer, cd->sector,
 684                       READ_AHEAD * RAW_SECTOR_SIZE / 2);
 685        if (read_background(start + READ_AHEAD, 1))
 686                stats(read_background);
 687        cd->sector_first = start;
 688        cd->sector_last = start + READ_AHEAD;
 689        stats(read_restarted);
 690        return 0;
 691}
 692
 693/* The function of bottom-half is to send a stop command to the drive
 694   This isn't easy because the routine is not `owned' by any process;
 695   we can't go to sleep! The variable cd->background gives the status:
 696   0 no read pending
 697   1 a read is pending
 698   2 c_stop waits for write_buffer_empty
 699   3 c_stop waits for receive_buffer_full: echo
 700   4 c_stop waits for receive_buffer_full: 0xff
 701*/
 702
 703void cm206_bh(void)
 704{
 705        debug(("bh: %d\n", cd->background));
 706        switch (cd->background) {
 707        case 1:
 708                stats(bh);
 709                if (!(cd->intr_ls & ls_transmitter_buffer_empty)) {
 710                        cd->command = c_stop;
 711                        outw(dc_mask_sync_error | dc_no_stop_on_error |
 712                             (inw(r_data_status) & 0x7f), r_data_control);
 713                        cd->background = 2;
 714                        break;  /* we'd better not time-out here! */
 715                } else
 716                        outw(c_stop, r_uart_transmit);
 717                /* fall into case 2: */
 718        case 2:
 719                /* the write has been satisfied by interrupt routine */
 720                cd->background = 3;
 721                break;
 722        case 3:
 723                if (cd->ur_r != cd->ur_w) {
 724                        if (cd->ur[cd->ur_r] != c_stop) {
 725                                debug(("cm206_bh: c_stop echoed 0x%x\n",
 726                                       cd->ur[cd->ur_r]));
 727                                stats(echo);
 728                        }
 729                        cd->ur_r++;
 730                        cd->ur_r %= UR_SIZE;
 731                }
 732                cd->background++;
 733                break;
 734        case 4:
 735                if (cd->ur_r != cd->ur_w) {
 736                        if (cd->ur[cd->ur_r] != 0xff) {
 737                                debug(("cm206_bh: c_stop reacted with 0x%x\n", cd->ur[cd->ur_r]));
 738                                stats(stop_0xff);
 739                        }
 740                        cd->ur_r++;
 741                        cd->ur_r %= UR_SIZE;
 742                }
 743                cd->background = 0;
 744        }
 745}
 746
 747/* This command clears the dsb_possible_media_change flag, so we must 
 748 * retain it.
 749 */
 750void get_drive_status(void)
 751{
 752        uch status[2];
 753        type_1_command(c_drive_status, 2, status);      /* this might be done faster */
 754        cd->dsb = status[0];
 755        cd->cc = status[1];
 756        cd->media_changed |=
 757            !!(cd->dsb & (dsb_possible_media_change |
 758                          dsb_drive_not_ready | dsb_tray_not_closed));
 759}
 760
 761void get_disc_status(void)
 762{
 763        if (type_1_command(c_disc_status, 7, cd->disc_status)) {
 764                debug(("get_disc_status: error\n"));
 765        }
 766}
 767
 768struct block_device_operations cm206_bdops =
 769{
 770        owner:                  THIS_MODULE,
 771        open:                   cdrom_open,
 772        release:                cdrom_release,
 773        ioctl:                  cdrom_ioctl,
 774        check_media_change:     cdrom_media_changed,
 775};
 776
 777/* The new open. The real opening strategy is defined in cdrom.c. */
 778
 779static int cm206_open(struct cdrom_device_info *cdi, int purpose)
 780{
 781        if (!cd->openfiles) {   /* reset only first time */
 782                cd->background = 0;
 783                reset_cm260();
 784                cd->adapter_last = -1;  /* invalidate adapter memory */
 785                cd->sector_last = -1;
 786        }
 787        ++cd->openfiles;
 788        stats(open);
 789        return 0;
 790}
 791
 792static void cm206_release(struct cdrom_device_info *cdi)
 793{
 794        if (cd->openfiles == 1) {
 795                if (cd->background) {
 796                        cd->background = 0;
 797                        stop_read();
 798                }
 799                cd->sector_last = -1;   /* Make our internal buffer invalid */
 800                FIRST_TRACK = 0;        /* No valid disc status */
 801        }
 802        --cd->openfiles;
 803}
 804
 805/* Empty buffer empties $sectors$ sectors of the adapter card buffer,
 806 * and then reads a sector in kernel memory.  */
 807void empty_buffer(int sectors)
 808{
 809        while (sectors >= 0) {
 810                transport_data(r_fifo_output_buffer,
 811                               cd->sector + cd->fifo_overflowed,
 812                               RAW_SECTOR_SIZE / 2 - cd->fifo_overflowed);
 813                --sectors;
 814                ++cd->adapter_first;    /* update the current adapter sector */
 815                cd->fifo_overflowed = 0;        /* reset overflow bit */
 816                stats(sector_transferred);
 817        }
 818        cd->sector_first = cd->adapter_first - 1;
 819        cd->sector_last = cd->adapter_first;    /* update the buffer sector */
 820}
 821
 822/* try_adapter. This function determines if the requested sector is
 823   in adapter memory, or will appear there soon. Returns 0 upon
 824   success */
 825int try_adapter(int sector)
 826{
 827        if (cd->adapter_first <= sector && sector < cd->adapter_last) {
 828                /* sector is in adapter memory */
 829                empty_buffer(sector - cd->adapter_first);
 830                return 0;
 831        } else if (cd->background == 1 && cd->adapter_first <= sector
 832                   && sector < cd->adapter_first + cd->max_sectors) {
 833                /* a read is going on, we can wait for it */
 834                cd->wait_back = 1;
 835                while (sector >= cd->adapter_last) {
 836                        if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
 837                                debug(("Timed out during background wait: %d %d %d %d\n", sector, cd->adapter_last, cd->adapter_first, cd->background));
 838                                stats(back_read_timeout);
 839                                cd->wait_back = 0;
 840                                return -1;
 841                        }
 842                }
 843                cd->wait_back = 0;
 844                empty_buffer(sector - cd->adapter_first);
 845                return 0;
 846        } else
 847                return -2;
 848}
 849
 850/* This is not a very smart implementation. We could optimize for 
 851   consecutive block numbers. I'm not convinced this would really
 852   bring down the processor load. */
 853static void do_cm206_request(request_queue_t * q)
 854{
 855        long int i, cd_sec_no;
 856        int quarter, error;
 857        uch *source, *dest;
 858
 859        while (1) {             /* repeat until all requests have been satisfied */
 860                INIT_REQUEST;
 861                if (QUEUE_EMPTY || CURRENT->rq_status == RQ_INACTIVE)
 862                        return;
 863                if (CURRENT->cmd != READ) {
 864                        debug(("Non-read command %d on cdrom\n",
 865                               CURRENT->cmd));
 866                        end_request(0);
 867                        continue;
 868                }
 869                spin_unlock_irq(&io_request_lock);
 870                error = 0;
 871                for (i = 0; i < CURRENT->nr_sectors; i++) {
 872                        int e1, e2;
 873                        cd_sec_no = (CURRENT->sector + i) / BLOCKS_ISO; /* 4 times 512 bytes */
 874                        quarter = (CURRENT->sector + i) % BLOCKS_ISO;
 875                        dest = CURRENT->buffer + i * LINUX_BLOCK_SIZE;
 876                        /* is already in buffer memory? */
 877                        if (cd->sector_first <= cd_sec_no
 878                            && cd_sec_no < cd->sector_last) {
 879                                source =
 880                                    ((uch *) cd->sector) + 16 +
 881                                    quarter * LINUX_BLOCK_SIZE +
 882                                    (cd_sec_no -
 883                                     cd->sector_first) * RAW_SECTOR_SIZE;
 884                                memcpy(dest, source, LINUX_BLOCK_SIZE);
 885                        } else if (!(e1 = try_adapter(cd_sec_no)) ||
 886                                   !(e2 = read_sector(cd_sec_no))) {
 887                                source =
 888                                    ((uch *) cd->sector) + 16 +
 889                                    quarter * LINUX_BLOCK_SIZE;
 890                                memcpy(dest, source, LINUX_BLOCK_SIZE);
 891                        } else {
 892                                error = 1;
 893                                debug(("cm206_request: %d %d\n", e1, e2));
 894                        }
 895                }
 896                spin_lock_irq(&io_request_lock);
 897                end_request(!error);
 898        }
 899}
 900
 901/* Audio support. I've tried very hard, but the cm206 drive doesn't 
 902   seem to have a get_toc (table-of-contents) function, while i'm
 903   pretty sure it must read the toc upon disc insertion. Therefore
 904   this function has been implemented through a binary search 
 905   strategy. All track starts that happen to be found are stored in
 906   cd->toc[], for future use. 
 907
 908   I've spent a whole day on a bug that only shows under Workman---
 909   I don't get it. Tried everything, nothing works. If workman asks
 910   for track# 0xaa, it'll get the wrong time back. Any other program
 911   receives the correct value. I'm stymied.
 912*/
 913
 914/* seek seeks to address lba. It does wait to arrive there. */
 915void seek(int lba)
 916{
 917        int i;
 918        uch seek_command[4] = { c_seek, };
 919
 920        fsm(lba, &seek_command[1]);
 921        for (i = 0; i < 4; i++)
 922                type_0_command(seek_command[i], 0);
 923        cd->dsb = wait_dsb();
 924}
 925
 926uch bcdbin(unsigned char bcd)
 927{                               /* stolen from mcd.c! */
 928        return (bcd >> 4) * 10 + (bcd & 0xf);
 929}
 930
 931inline uch normalize_track(uch track)
 932{
 933        if (track < 1)
 934                return 1;
 935        if (track > LAST_TRACK)
 936                return LAST_TRACK + 1;
 937        return track;
 938}
 939
 940/* This function does a binary search for track start. It records all
 941 * tracks seen in the process. Input $track$ must be between 1 and
 942 * #-of-tracks+1.  Note that the start of the disc must be in toc[1].fsm. 
 943 */
 944int get_toc_lba(uch track)
 945{
 946        int max = 74 * 60 * 75 - 150, min = fsm2lba(cd->toc[1].fsm);
 947        int i, lba, l, old_lba = 0;
 948        uch *q = cd->q;
 949        uch ct;                 /* current track */
 950        int binary = 0;
 951        const int skip = 3 * 60 * 75;   /* 3 minutes */
 952
 953        for (i = track; i > 0; i--)
 954                if (cd->toc[i].track) {
 955                        min = fsm2lba(cd->toc[i].fsm);
 956                        break;
 957                }
 958        lba = min + skip;
 959        do {
 960                seek(lba);
 961                type_1_command(c_read_current_q, 10, q);
 962                ct = normalize_track(q[1]);
 963                if (!cd->toc[ct].track) {
 964                        l = q[9] - bcdbin(q[5]) + 75 * (q[8] -
 965                                                        bcdbin(q[4]) - 2 +
 966                                                        60 * (q[7] -
 967                                                              bcdbin(q
 968                                                                     [3])));
 969                        cd->toc[ct].track = q[1];       /* lead out still 0xaa */
 970                        fsm(l, cd->toc[ct].fsm);
 971                        cd->toc[ct].q0 = q[0];  /* contains adr and ctrl info */
 972                        if (ct == track)
 973                                return l;
 974                }
 975                old_lba = lba;
 976                if (binary) {
 977                        if (ct < track)
 978                                min = lba;
 979                        else
 980                                max = lba;
 981                        lba = (min + max) / 2;
 982                } else {
 983                        if (ct < track)
 984                                lba += skip;
 985                        else {
 986                                binary = 1;
 987                                max = lba;
 988                                min = lba - skip;
 989                                lba = (min + max) / 2;
 990                        }
 991                }
 992        } while (lba != old_lba);
 993        return lba;
 994}
 995
 996void update_toc_entry(uch track)
 997{
 998        track = normalize_track(track);
 999        if (!cd->toc[track].track)
1000                get_toc_lba(track);
1001}
1002
1003/* return 0 upon success */
1004int read_toc_header(struct cdrom_tochdr *hp)
1005{
1006        if (!FIRST_TRACK)
1007                get_disc_status();
1008        if (hp) {
1009                int i;
1010                hp->cdth_trk0 = FIRST_TRACK;
1011                hp->cdth_trk1 = LAST_TRACK;
1012                /* fill in first track position */
1013                for (i = 0; i < 3; i++)
1014                        cd->toc[1].fsm[i] = cd->disc_status[3 + i];
1015                update_toc_entry(LAST_TRACK + 1);       /* find most entries */
1016                return 0;
1017        }
1018        return -1;
1019}
1020
1021void play_from_to_msf(struct cdrom_msf *msfp)
1022{
1023        uch play_command[] = { c_play,
1024                msfp->cdmsf_frame0, msfp->cdmsf_sec0, msfp->cdmsf_min0,
1025                msfp->cdmsf_frame1, msfp->cdmsf_sec1, msfp->cdmsf_min1, 2,
1026                    2
1027        };
1028        int i;
1029        for (i = 0; i < 9; i++)
1030                type_0_command(play_command[i], 0);
1031        for (i = 0; i < 3; i++)
1032                PLAY_TO.fsm[i] = play_command[i + 4];
1033        PLAY_TO.track = 0;      /* say no track end */
1034        cd->dsb = wait_dsb();
1035}
1036
1037void play_from_to_track(int from, int to)
1038{
1039        uch play_command[8] = { c_play, };
1040        int i;
1041
1042        if (from == 0) {        /* continue paused play */
1043                for (i = 0; i < 3; i++) {
1044                        play_command[i + 1] = cd->audio_status[i + 2];
1045                        play_command[i + 4] = PLAY_TO.fsm[i];
1046                }
1047        } else {
1048                update_toc_entry(from);
1049                update_toc_entry(to + 1);
1050                for (i = 0; i < 3; i++) {
1051                        play_command[i + 1] = cd->toc[from].fsm[i];
1052                        PLAY_TO.fsm[i] = play_command[i + 4] =
1053                            cd->toc[to + 1].fsm[i];
1054                }
1055                PLAY_TO.track = to;
1056        }
1057        for (i = 0; i < 7; i++)
1058                type_0_command(play_command[i], 0);
1059        for (i = 0; i < 2; i++)
1060                type_0_command(0x2, 0); /* volume */
1061        cd->dsb = wait_dsb();
1062}
1063
1064int get_current_q(struct cdrom_subchnl *qp)
1065{
1066        int i;
1067        uch *q = cd->q;
1068        if (type_1_command(c_read_current_q, 10, q))
1069                return 0;
1070/*  q[0] = bcdbin(q[0]); Don't think so! */
1071        for (i = 2; i < 6; i++)
1072                q[i] = bcdbin(q[i]);
1073        qp->cdsc_adr = q[0] & 0xf;
1074        qp->cdsc_ctrl = q[0] >> 4;      /* from mcd.c */
1075        qp->cdsc_trk = q[1];
1076        qp->cdsc_ind = q[2];
1077        if (qp->cdsc_format == CDROM_MSF) {
1078                qp->cdsc_reladdr.msf.minute = q[3];
1079                qp->cdsc_reladdr.msf.second = q[4];
1080                qp->cdsc_reladdr.msf.frame = q[5];
1081                qp->cdsc_absaddr.msf.minute = q[7];
1082                qp->cdsc_absaddr.msf.second = q[8];
1083                qp->cdsc_absaddr.msf.frame = q[9];
1084        } else {
1085                qp->cdsc_reladdr.lba = f_s_m2lba(q[5], q[4], q[3]);
1086                qp->cdsc_absaddr.lba = f_s_m2lba(q[9], q[8], q[7]);
1087        }
1088        get_drive_status();
1089        if (cd->dsb & dsb_play_in_progress)
1090                qp->cdsc_audiostatus = CDROM_AUDIO_PLAY;
1091        else if (PAUSED)
1092                qp->cdsc_audiostatus = CDROM_AUDIO_PAUSED;
1093        else
1094                qp->cdsc_audiostatus = CDROM_AUDIO_NO_STATUS;
1095        return 0;
1096}
1097
1098void invalidate_toc(void)
1099{
1100        memset(cd->toc, 0, sizeof(cd->toc));
1101        memset(cd->disc_status, 0, sizeof(cd->disc_status));
1102}
1103
1104/* cdrom.c guarantees that cdte_format == CDROM_MSF */
1105void get_toc_entry(struct cdrom_tocentry *ep)
1106{
1107        uch track = normalize_track(ep->cdte_track);
1108        update_toc_entry(track);
1109        ep->cdte_addr.msf.frame = cd->toc[track].fsm[0];
1110        ep->cdte_addr.msf.second = cd->toc[track].fsm[1];
1111        ep->cdte_addr.msf.minute = cd->toc[track].fsm[2];
1112        ep->cdte_adr = cd->toc[track].q0 & 0xf;
1113        ep->cdte_ctrl = cd->toc[track].q0 >> 4;
1114        ep->cdte_datamode = 0;
1115}
1116
1117/* Audio ioctl.  Ioctl commands connected to audio are in such an
1118 * idiosyncratic i/o format, that we leave these untouched. Return 0
1119 * upon success. Memory checking has been done by cdrom_ioctl(), the
1120 * calling function, as well as LBA/MSF sanitization.
1121*/
1122int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
1123                      void *arg)
1124{
1125        switch (cmd) {
1126        case CDROMREADTOCHDR:
1127                return read_toc_header((struct cdrom_tochdr *) arg);
1128        case CDROMREADTOCENTRY:
1129                get_toc_entry((struct cdrom_tocentry *) arg);
1130                return 0;
1131        case CDROMPLAYMSF:
1132                play_from_to_msf((struct cdrom_msf *) arg);
1133                return 0;
1134        case CDROMPLAYTRKIND:   /* admittedly, not particularly beautiful */
1135                play_from_to_track(((struct cdrom_ti *) arg)->cdti_trk0,
1136                                   ((struct cdrom_ti *) arg)->cdti_trk1);
1137                return 0;
1138        case CDROMSTOP:
1139                PAUSED = 0;
1140                if (cd->dsb & dsb_play_in_progress)
1141                        return type_0_command(c_stop, 1);
1142                else
1143                        return 0;
1144        case CDROMPAUSE:
1145                get_drive_status();
1146                if (cd->dsb & dsb_play_in_progress) {
1147                        type_0_command(c_stop, 1);
1148                        type_1_command(c_audio_status, 5,
1149                                       cd->audio_status);
1150                        PAUSED = 1;     /* say we're paused */
1151                }
1152                return 0;
1153        case CDROMRESUME:
1154                if (PAUSED)
1155                        play_from_to_track(0, 0);
1156                PAUSED = 0;
1157                return 0;
1158        case CDROMSTART:
1159        case CDROMVOLCTRL:
1160                return 0;
1161        case CDROMSUBCHNL:
1162                return get_current_q((struct cdrom_subchnl *) arg);
1163        default:
1164                return -EINVAL;
1165        }
1166}
1167
1168/* Ioctl. These ioctls are specific to the cm206 driver. I have made
1169   some driver statistics accessible through ioctl calls.
1170 */
1171
1172static int cm206_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
1173                       unsigned long arg)
1174{
1175        switch (cmd) {
1176#ifdef STATISTICS
1177        case CM206CTL_GET_STAT:
1178                if (arg >= NR_STATS)
1179                        return -EINVAL;
1180                else
1181                        return cd->stats[arg];
1182        case CM206CTL_GET_LAST_STAT:
1183                if (arg >= NR_STATS)
1184                        return -EINVAL;
1185                else
1186                        return cd->last_stat[arg];
1187#endif
1188        default:
1189                debug(("Unknown ioctl call 0x%x\n", cmd));
1190                return -EINVAL;
1191        }
1192}
1193
1194int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr)
1195{
1196        if (cd != NULL) {
1197                int r;
1198                get_drive_status();     /* ensure cd->media_changed OK */
1199                r = cd->media_changed;
1200                cd->media_changed = 0;  /* clear bit */
1201                return r;
1202        } else
1203                return -EIO;
1204}
1205
1206/* The new generic cdrom support. Routines should be concise, most of
1207   the logic should be in cdrom.c */
1208
1209/* returns number of times device is in use */
1210int cm206_open_files(struct cdrom_device_info *cdi)
1211{
1212        if (cd)
1213                return cd->openfiles;
1214        return -1;
1215}
1216
1217/* controls tray movement */
1218int cm206_tray_move(struct cdrom_device_info *cdi, int position)
1219{
1220        if (position) {         /* 1: eject */
1221                type_0_command(c_open_tray, 1);
1222                invalidate_toc();
1223        } else
1224                type_0_command(c_close_tray, 1);        /* 0: close */
1225        return 0;
1226}
1227
1228/* gives current state of the drive */
1229int cm206_drive_status(struct cdrom_device_info *cdi, int slot_nr)
1230{
1231        get_drive_status();
1232        if (cd->dsb & dsb_tray_not_closed)
1233                return CDS_TRAY_OPEN;
1234        if (!(cd->dsb & dsb_disc_present))
1235                return CDS_NO_DISC;
1236        if (cd->dsb & dsb_drive_not_ready)
1237                return CDS_DRIVE_NOT_READY;
1238        return CDS_DISC_OK;
1239}
1240
1241/* locks or unlocks door lock==1: lock; return 0 upon success */
1242int cm206_lock_door(struct cdrom_device_info *cdi, int lock)
1243{
1244        uch command = (lock) ? c_lock_tray : c_unlock_tray;
1245        type_0_command(command, 1);     /* wait and get dsb */
1246        /* the logic calculates the success, 0 means successful */
1247        return lock ^ ((cd->dsb & dsb_tray_locked) != 0);
1248}
1249
1250/* Although a session start should be in LBA format, we return it in 
1251   MSF format because it is slightly easier, and the new generic ioctl
1252   will take care of the necessary conversion. */
1253int cm206_get_last_session(struct cdrom_device_info *cdi,
1254                           struct cdrom_multisession *mssp)
1255{
1256        if (!FIRST_TRACK)
1257                get_disc_status();
1258        if (mssp != NULL) {
1259                if (DISC_STATUS & cds_multi_session) {  /* multi-session */
1260                        mssp->addr.msf.frame = cd->disc_status[3];
1261                        mssp->addr.msf.second = cd->disc_status[4];
1262                        mssp->addr.msf.minute = cd->disc_status[5];
1263                        mssp->addr_format = CDROM_MSF;
1264                        mssp->xa_flag = 1;
1265                } else {
1266                        mssp->xa_flag = 0;
1267                }
1268                return 1;
1269        }
1270        return 0;
1271}
1272
1273int cm206_get_upc(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
1274{
1275        uch upc[10];
1276        char *ret = mcn->medium_catalog_number;
1277        int i;
1278
1279        if (type_1_command(c_read_upc, 10, upc))
1280                return -EIO;
1281        for (i = 0; i < 13; i++) {
1282                int w = i / 2 + 1, r = i % 2;
1283                if (r)
1284                        ret[i] = 0x30 | (upc[w] & 0x0f);
1285                else
1286                        ret[i] = 0x30 | ((upc[w] >> 4) & 0x0f);
1287        }
1288        ret[13] = '\0';
1289        return 0;
1290}
1291
1292int cm206_reset(struct cdrom_device_info *cdi)
1293{
1294        stop_read();
1295        reset_cm260();
1296        outw(dc_normal | dc_break | READ_AHEAD, r_data_control);
1297        mdelay(1);              /* 750 musec minimum */
1298        outw(dc_normal | READ_AHEAD, r_data_control);
1299        cd->sector_last = -1;   /* flag no data buffered */
1300        cd->adapter_last = -1;
1301        invalidate_toc();
1302        return 0;
1303}
1304
1305int cm206_select_speed(struct cdrom_device_info *cdi, int speed)
1306{
1307        int r;
1308        switch (speed) {
1309        case 0:
1310                r = type_0_command(c_auto_mode, 1);
1311                break;
1312        case 1:
1313                r = type_0_command(c_force_1x, 1);
1314                break;
1315        case 2:
1316                r = type_0_command(c_force_2x, 1);
1317                break;
1318        default:
1319                return -1;
1320        }
1321        if (r < 0)
1322                return r;
1323        else
1324                return 1;
1325}
1326
1327static struct cdrom_device_ops cm206_dops = {
1328        open:cm206_open,
1329        release:cm206_release,
1330        drive_status:cm206_drive_status,
1331        media_changed:cm206_media_changed,
1332        tray_move:cm206_tray_move,
1333        lock_door:cm206_lock_door,
1334        select_speed:cm206_select_speed,
1335        get_last_session:cm206_get_last_session,
1336        get_mcn:cm206_get_upc,
1337        reset:cm206_reset,
1338        audio_ioctl:cm206_audio_ioctl,
1339        dev_ioctl:cm206_ioctl,
1340        capability:CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
1341            CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
1342            CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED |
1343            CDC_IOCTLS | CDC_DRIVE_STATUS,
1344        n_minors:1,
1345};
1346
1347
1348static struct cdrom_device_info cm206_info = {
1349        ops:&cm206_dops,
1350        speed:2,
1351        capacity:1,
1352        name:"cm206",
1353};
1354
1355/* This routine gets called during initialization if things go wrong,
1356 * can be used in cleanup_module as well. */
1357static void cleanup(int level)
1358{
1359        switch (level) {
1360        case 4:
1361                if (unregister_cdrom(&cm206_info)) {
1362                        printk("Can't unregister cdrom cm206\n");
1363                        return;
1364                }
1365                if (devfs_unregister_blkdev(MAJOR_NR, "cm206")) {
1366                        printk("Can't unregister major cm206\n");
1367                        return;
1368                }
1369                blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
1370        case 3:
1371                free_irq(cm206_irq, NULL);
1372        case 2:
1373        case 1:
1374                kfree(cd);
1375                release_region(cm206_base, 16);
1376        default:;
1377        }
1378}
1379
1380/* This function probes for the adapter card. It returns the base
1381   address if it has found the adapter card. One can specify a base 
1382   port to probe specifically, or 0 which means span all possible
1383   bases. 
1384
1385   Linus says it is too dangerous to use writes for probing, so we
1386   stick with pure reads for a while. Hope that 8 possible ranges,
1387   check_region, 15 bits of one port and 6 of another make things
1388   likely enough to accept the region on the first hit...
1389 */
1390int __init probe_base_port(int base)
1391{
1392        int b = 0x300, e = 0x370;       /* this is the range of start addresses */
1393        volatile int fool, i;
1394
1395        if (base)
1396                b = e = base;
1397        for (base = b; base <= e; base += 0x10) {
1398                if (check_region(base, 0x10))
1399                        continue;
1400                for (i = 0; i < 3; i++)
1401                        fool = inw(base + 2);   /* empty possibly uart_receive_buffer */
1402                if ((inw(base + 6) & 0xffef) != 0x0001 ||       /* line_status */
1403                    (inw(base) & 0xad00) != 0)  /* data status */
1404                        continue;
1405                return (base);
1406        }
1407        return 0;
1408}
1409
1410#if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
1411/* Probe for irq# nr. If nr==0, probe for all possible irq's. */
1412int __init probe_irq(int nr)
1413{
1414        int irqs, irq;
1415        outw(dc_normal | READ_AHEAD, r_data_control);   /* disable irq-generation */
1416        sti();
1417        irqs = probe_irq_on();
1418        reset_cm260();          /* causes interrupt */
1419        udelay(100);            /* wait for it */
1420        irq = probe_irq_off(irqs);
1421        outw(dc_normal | READ_AHEAD, r_data_control);   /* services interrupt */
1422        if (nr && irq != nr && irq > 0)
1423                return 0;       /* wrong interrupt happened */
1424        else
1425                return irq;
1426}
1427#endif
1428
1429int __init cm206_init(void)
1430{
1431        uch e = 0;
1432        long int size = sizeof(struct cm206_struct);
1433
1434        printk(KERN_INFO "cm206 cdrom driver " REVISION);
1435        cm206_base = probe_base_port(auto_probe ? 0 : cm206_base);
1436        if (!cm206_base) {
1437                printk(" can't find adapter!\n");
1438                return -EIO;
1439        }
1440        printk(" adapter at 0x%x", cm206_base);
1441        request_region(cm206_base, 16, "cm206");
1442        cd = (struct cm206_struct *) kmalloc(size, GFP_KERNEL);
1443        if (!cd)
1444                return -EIO;
1445        /* Now we have found the adaptor card, try to reset it. As we have
1446         * found out earlier, this process generates an interrupt as well,
1447         * so we might just exploit that fact for irq probing! */
1448#if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
1449        cm206_irq = probe_irq(auto_probe ? 0 : cm206_irq);
1450        if (cm206_irq <= 0) {
1451                printk("can't find IRQ!\n");
1452                cleanup(1);
1453                return -EIO;
1454        } else
1455                printk(" IRQ %d found\n", cm206_irq);
1456#else
1457        cli();
1458        reset_cm260();
1459        /* Now, the problem here is that reset_cm260 can generate an
1460           interrupt. It seems that this can cause a kernel oops some time
1461           later. So we wait a while and `service' this interrupt. */
1462        mdelay(1);
1463        outw(dc_normal | READ_AHEAD, r_data_control);
1464        sti();
1465        printk(" using IRQ %d\n", cm206_irq);
1466#endif
1467        if (send_receive_polled(c_drive_configuration) !=
1468            c_drive_configuration) {
1469                printk(KERN_INFO " drive not there\n");
1470                cleanup(1);
1471                return -EIO;
1472        }
1473        e = send_receive_polled(c_gimme);
1474        printk(KERN_INFO "Firmware revision %d", e & dcf_revision_code);
1475        if (e & dcf_transfer_rate)
1476                printk(" double");
1477        else
1478                printk(" single");
1479        printk(" speed drive");
1480        if (e & dcf_motorized_tray)
1481                printk(", motorized tray");
1482        if (request_irq(cm206_irq, cm206_interrupt, 0, "cm206", NULL)) {
1483                printk("\nUnable to reserve IRQ---aborted\n");
1484                cleanup(2);
1485                return -EIO;
1486        }
1487        printk(".\n");
1488        if (devfs_register_blkdev(MAJOR_NR, "cm206", &cm206_bdops) != 0) {
1489                printk(KERN_INFO "Cannot register for major %d!\n",
1490                       MAJOR_NR);
1491                cleanup(3);
1492                return -EIO;
1493        }
1494        cm206_info.dev = MKDEV(MAJOR_NR, 0);
1495        if (register_cdrom(&cm206_info) != 0) {
1496                printk(KERN_INFO "Cannot register for cdrom %d!\n",
1497                       MAJOR_NR);
1498                cleanup(3);
1499                return -EIO;
1500        }
1501        devfs_plain_cdrom(&cm206_info, &cm206_bdops);
1502        blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
1503        blksize_size[MAJOR_NR] = cm206_blocksizes;
1504        read_ahead[MAJOR_NR] = 16;      /* reads ahead what? */
1505        init_bh(CM206_BH, cm206_bh);
1506
1507        memset(cd, 0, sizeof(*cd));     /* give'm some reasonable value */
1508        cd->sector_last = -1;   /* flag no data buffered */
1509        cd->adapter_last = -1;
1510        cd->timer.function = cm206_timeout;
1511        cd->max_sectors = (inw(r_data_status) & ds_ram_size) ? 24 : 97;
1512        printk(KERN_INFO "%d kB adapter memory available, "
1513               " %ld bytes kernel memory used.\n", cd->max_sectors * 2,
1514               size);
1515        return 0;
1516}
1517
1518#ifdef MODULE
1519
1520
1521static void __init parse_options(void)
1522{
1523        int i;
1524        for (i = 0; i < 2; i++) {
1525                if (0x300 <= cm206[i] && i <= 0x370
1526                    && cm206[i] % 0x10 == 0) {
1527                        cm206_base = cm206[i];
1528                        auto_probe = 0;
1529                } else if (3 <= cm206[i] && cm206[i] <= 15) {
1530                        cm206_irq = cm206[i];
1531                        auto_probe = 0;
1532                }
1533        }
1534}
1535
1536int __cm206_init(void)
1537{
1538        parse_options();
1539#if !defined(AUTO_PROBE_MODULE)
1540        auto_probe = 0;
1541#endif
1542        return cm206_init();
1543}
1544
1545void __exit cm206_exit(void)
1546{
1547        cleanup(4);
1548        printk(KERN_INFO "cm206 removed\n");
1549}
1550
1551module_init(__cm206_init);
1552module_exit(cm206_exit);
1553
1554#else                           /* !MODULE */
1555
1556/* This setup function accepts either `auto' or numbers in the range
1557 * 3--11 (for irq) or 0x300--0x370 (for base port) or both. */
1558
1559static int __init cm206_setup(char *s)
1560{
1561        int i, p[4];
1562
1563        (void) get_options(s, ARRAY_SIZE(p), p);
1564
1565        if (!strcmp(s, "auto"))
1566                auto_probe = 1;
1567        for (i = 1; i <= p[0]; i++) {
1568                if (0x300 <= p[i] && i <= 0x370 && p[i] % 0x10 == 0) {
1569                        cm206_base = p[i];
1570                        auto_probe = 0;
1571                } else if (3 <= p[i] && p[i] <= 15) {
1572                        cm206_irq = p[i];
1573                        auto_probe = 0;
1574                }
1575        }
1576        return 1;
1577}
1578
1579__setup("cm206=", cm206_setup);
1580
1581#endif                          /* !MODULE */
1582
1583
1584/*
1585 * Local variables:
1586 * 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"
1587 * End:
1588 */
1589
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.