OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [cdrom/] [cm206.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* 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.1.1.1 2004-04-15 02:18:52 phoenix 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
 
19
History:
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
 
135
11 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
 
140
13 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
 
144
15 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
 
147
14 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
 
150
21 dec 1997   1.4 Upgrade to Linux 2.1.72.
151
 
152
24 jan 1998   Removed the cm206_disc_status() function, as it was now dead
153
              code.  The Uniform CDROM driver now provides this functionality.
154
 
155
9 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.1.1.1 $"
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
*/
214
static int auto_probe = 1;      /* Yes, why not? */
215
 
216
static int cm206_base = CM206_BASE;
217
static int cm206_irq = CM206_IRQ;
218
#ifdef MODULE
219
static int cm206[2] = { 0, 0 };   /* for compatible `insmod' parameter passing */
220
#endif
221
 
222
MODULE_PARM(cm206_base, "i");   /* base */
223
MODULE_PARM(cm206_irq, "i");    /* irq */
224
MODULE_PARM(cm206, "1-2i");     /* base,irq or irq,base */
225
MODULE_PARM(auto_probe, "i");   /* auto probe base and irq */
226
MODULE_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
 
257
typedef unsigned char uch;      /* 8-bits */
258
typedef unsigned short ush;     /* 16-bits */
259
 
260
struct toc_struct {             /* private copy of Table of Contents */
261
        uch track, fsm[3], q0;
262
};
263
 
264
static int cm206_blocksizes[1] = { 2048 };
265
 
266
struct 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
 
304
static 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
 
309
void 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
 
320
uch 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
 
330
uch send_receive_polled(int command)
331
{
332
        send_command_polled(command);
333
        return receive_echo_polled();
334
}
335
 
336
inline 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
 
360
static 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 */
439
void 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 */
448
int 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
 
464
void cm206_delay(int nr_jiffies)
465
{
466
        DECLARE_WAIT_QUEUE_HEAD(wait);
467
        sleep_or_timeout(&wait, nr_jiffies);
468
}
469
 
470
void 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
 
489
uch 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
 
520
inline uch receive_echo(void)
521
{
522
        return receive_byte(UART_TIMEOUT);
523
}
524
 
525
inline uch send_receive(int command)
526
{
527
        send_command(command);
528
        return receive_echo();
529
}
530
 
531
inline uch wait_dsb(void)
532
{
533
        return receive_byte(DSB_TIMEOUT);
534
}
535
 
536
int 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
 
551
int 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.' */
563
void 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 */
571
void 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
 
580
inline int fsm2lba(uch * fsm)
581
{
582
        return fsm[0] + 75 * (fsm[1] - 2 + 60 * fsm[2]);
583
}
584
 
585
inline int f_s_m2lba(uch f, uch s, uch m)
586
{
587
        return f + 75 * (s - 2 + 60 * m);
588
}
589
 
590
int 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
 
612
int 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
 
629
int 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. */
646
void 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
657
int 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
 
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
 
703
void 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
 */
750
void 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
 
761
void 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
 
768
struct 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
 
779
static 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
 
792
static 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.  */
807
void 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 */
825
int 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. */
853
static 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. */
915
void 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
 
926
uch bcdbin(unsigned char bcd)
927
{                               /* stolen from mcd.c! */
928
        return (bcd >> 4) * 10 + (bcd & 0xf);
929
}
930
 
931
inline 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
 */
944
int 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
 
996
void 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 */
1004
int 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
 
1021
void 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
 
1037
void 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
 
1064
int 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
 
1098
void 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 */
1105
void 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
*/
1122
int 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
 
1172
static 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
 
1194
int 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 */
1210
int 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 */
1218
int 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 */
1229
int 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 */
1242
int 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. */
1253
int 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
 
1273
int 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
 
1292
int 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
 
1305
int 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
 
1327
static 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
 
1348
static 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. */
1357
static 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
 */
1390
int __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. */
1412
int __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
 
1429
int __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
 
1521
static 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
 
1536
int __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
 
1545
void __exit cm206_exit(void)
1546
{
1547
        cleanup(4);
1548
        printk(KERN_INFO "cm206 removed\n");
1549
}
1550
 
1551
module_init(__cm206_init);
1552
module_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
 
1559
static 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
 */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.