Pull altix-mmr into release branch
[sfrench/cifs-2.6.git] / drivers / cdrom / optcd.c
1 /*      linux/drivers/cdrom/optcd.c - Optics Storage 8000 AT CDROM driver
2         $Id: optcd.c,v 1.11 1997/01/26 07:13:00 davem Exp $
3
4         Copyright (C) 1995 Leo Spiekman (spiekman@dutette.et.tudelft.nl)
5
6
7         Based on Aztech CD268 CDROM driver by Werner Zimmermann and preworks
8         by Eberhard Moenkeberg (emoenke@gwdg.de). 
9
10         This program is free software; you can redistribute it and/or modify
11         it under the terms of the GNU General Public License as published by
12         the Free Software Foundation; either version 2, or (at your option)
13         any later version.
14
15         This program is distributed in the hope that it will be useful,
16         but WITHOUT ANY WARRANTY; without even the implied warranty of
17         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18         GNU General Public License for more details.
19
20         You should have received a copy of the GNU General Public License
21         along with this program; if not, write to the Free Software
22         Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24 \f
25 /*      Revision history
26
27
28         14-5-95         v0.0    Plays sound tracks. No reading of data CDs yet.
29                                 Detection of disk change doesn't work.
30         21-5-95         v0.1    First ALPHA version. CD can be mounted. The
31                                 device major nr is borrowed from the Aztech
32                                 driver. Speed is around 240 kb/s, as measured
33                                 with "time dd if=/dev/cdrom of=/dev/null \
34                                 bs=2048 count=4096".
35         24-6-95         v0.2    Reworked the #defines for the command codes
36                                 and the like, as well as the structure of
37                                 the hardware communication protocol, to
38                                 reflect the "official" documentation, kindly
39                                 supplied by C.K. Tan, Optics Storage Pte. Ltd.
40                                 Also tidied up the state machine somewhat.
41         28-6-95         v0.3    Removed the ISP-16 interface code, as this
42                                 should go into its own driver. The driver now
43                                 has its own major nr.
44                                 Disk change detection now seems to work, too.
45                                 This version became part of the standard
46                                 kernel as of version 1.3.7
47         24-9-95         v0.4    Re-inserted ISP-16 interface code which I
48                                 copied from sjcd.c, with a few changes.
49                                 Updated README.optcd. Submitted for
50                                 inclusion in 1.3.21
51         29-9-95         v0.4a   Fixed bug that prevented compilation as module
52         25-10-95        v0.5    Started multisession code. Implementation
53                                 copied from Werner Zimmermann, who copied it
54                                 from Heiko Schlittermann's mcdx.
55         17-1-96         v0.6    Multisession works; some cleanup too.
56         18-4-96         v0.7    Increased some timing constants;
57                                 thanks to Luke McFarlane. Also tidied up some
58                                 printk behaviour. ISP16 initialization
59                                 is now handled by a separate driver.
60                                 
61         09-11-99                Make kernel-parameter implementation work with 2.3.x 
62                                 Removed init_module & cleanup_module in favor of 
63                                 module_init & module_exit.
64                                 Torben Mathiasen <tmm@image.dk>
65 */
66 \f
67 /* Includes */
68
69
70 #include <linux/module.h>
71 #include <linux/mm.h>
72 #include <linux/ioport.h>
73 #include <linux/init.h>
74
75 #include <asm/io.h>
76 #include <linux/blkdev.h>
77
78 #include <linux/cdrom.h>
79 #include "optcd.h"
80
81 #include <asm/uaccess.h>
82
83 #define MAJOR_NR OPTICS_CDROM_MAJOR
84 #define QUEUE (opt_queue)
85 #define CURRENT elv_next_request(opt_queue)
86
87 \f
88 /* Debug support */
89
90
91 /* Don't forget to add new debug flags here. */
92 #if DEBUG_DRIVE_IF | DEBUG_VFS | DEBUG_CONV | DEBUG_TOC | \
93     DEBUG_BUFFERS | DEBUG_REQUEST | DEBUG_STATE | DEBUG_MULTIS
94 #define DEBUG(x) debug x
95 static void debug(int debug_this, const char* fmt, ...)
96 {
97         char s[1024];
98         va_list args;
99
100         if (!debug_this)
101                 return;
102
103         va_start(args, fmt);
104         vsprintf(s, fmt, args);
105         printk(KERN_DEBUG "optcd: %s\n", s);
106         va_end(args);
107 }
108 #else
109 #define DEBUG(x)
110 #endif
111
112 \f
113 /* Drive hardware/firmware characteristics
114    Identifiers in accordance with Optics Storage documentation */
115
116
117 #define optcd_port optcd                        /* Needed for the modutils. */
118 static short optcd_port = OPTCD_PORTBASE;       /* I/O base of drive. */
119 module_param(optcd_port, short, 0);
120 /* Drive registers, read */
121 #define DATA_PORT       optcd_port      /* Read data/status */
122 #define STATUS_PORT     optcd_port+1    /* Indicate data/status availability */
123
124 /* Drive registers, write */
125 #define COMIN_PORT      optcd_port      /* For passing command/parameter */
126 #define RESET_PORT      optcd_port+1    /* Write anything and wait 0.5 sec */
127 #define HCON_PORT       optcd_port+2    /* Host Xfer Configuration */
128
129
130 /* Command completion/status read from DATA register */
131 #define ST_DRVERR               0x80
132 #define ST_DOOR_OPEN            0x40
133 #define ST_MIXEDMODE_DISK       0x20
134 #define ST_MODE_BITS            0x1c
135 #define ST_M_STOP               0x00
136 #define ST_M_READ               0x04
137 #define ST_M_AUDIO              0x04
138 #define ST_M_PAUSE              0x08
139 #define ST_M_INITIAL            0x0c
140 #define ST_M_ERROR              0x10
141 #define ST_M_OTHERS             0x14
142 #define ST_MODE2TRACK           0x02
143 #define ST_DSK_CHG              0x01
144 #define ST_L_LOCK               0x01
145 #define ST_CMD_OK               0x00
146 #define ST_OP_OK                0x01
147 #define ST_PA_OK                0x02
148 #define ST_OP_ERROR             0x05
149 #define ST_PA_ERROR             0x06
150
151
152 /* Error codes (appear as command completion code from DATA register) */
153 /* Player related errors */
154 #define ERR_ILLCMD      0x11    /* Illegal command to player module */
155 #define ERR_ILLPARM     0x12    /* Illegal parameter to player module */
156 #define ERR_SLEDGE      0x13
157 #define ERR_FOCUS       0x14
158 #define ERR_MOTOR       0x15
159 #define ERR_RADIAL      0x16
160 #define ERR_PLL         0x17    /* PLL lock error */
161 #define ERR_SUB_TIM     0x18    /* Subcode timeout error */
162 #define ERR_SUB_NF      0x19    /* Subcode not found error */
163 #define ERR_TRAY        0x1a
164 #define ERR_TOC         0x1b    /* Table of Contents read error */
165 #define ERR_JUMP        0x1c
166 /* Data errors */
167 #define ERR_MODE        0x21
168 #define ERR_FORM        0x22
169 #define ERR_HEADADDR    0x23    /* Header Address not found */
170 #define ERR_CRC         0x24
171 #define ERR_ECC         0x25    /* Uncorrectable ECC error */
172 #define ERR_CRC_UNC     0x26    /* CRC error and uncorrectable error */
173 #define ERR_ILLBSYNC    0x27    /* Illegal block sync error */
174 #define ERR_VDST        0x28    /* VDST not found */
175 /* Timeout errors */
176 #define ERR_READ_TIM    0x31    /* Read timeout error */
177 #define ERR_DEC_STP     0x32    /* Decoder stopped */
178 #define ERR_DEC_TIM     0x33    /* Decoder interrupt timeout error */
179 /* Function abort codes */
180 #define ERR_KEY         0x41    /* Key -Detected abort */
181 #define ERR_READ_FINISH 0x42    /* Read Finish */
182 /* Second Byte diagnostic codes */
183 #define ERR_NOBSYNC     0x01    /* No block sync */
184 #define ERR_SHORTB      0x02    /* Short block */
185 #define ERR_LONGB       0x03    /* Long block */
186 #define ERR_SHORTDSP    0x04    /* Short DSP word */
187 #define ERR_LONGDSP     0x05    /* Long DSP word */
188
189
190 /* Status availability flags read from STATUS register */
191 #define FL_EJECT        0x20
192 #define FL_WAIT         0x10    /* active low */
193 #define FL_EOP          0x08    /* active low */
194 #define FL_STEN         0x04    /* Status available when low */
195 #define FL_DTEN         0x02    /* Data available when low */
196 #define FL_DRQ          0x01    /* active low */
197 #define FL_RESET        0xde    /* These bits are high after a reset */
198 #define FL_STDT         (FL_STEN|FL_DTEN)
199
200
201 /* Transfer mode, written to HCON register */
202 #define HCON_DTS        0x08
203 #define HCON_SDRQB      0x04
204 #define HCON_LOHI       0x02
205 #define HCON_DMA16      0x01
206
207
208 /* Drive command set, written to COMIN register */
209 /* Quick response commands */
210 #define COMDRVST        0x20    /* Drive Status Read */
211 #define COMERRST        0x21    /* Error Status Read */
212 #define COMIOCTLISTAT   0x22    /* Status Read; reset disk changed bit */
213 #define COMINITSINGLE   0x28    /* Initialize Single Speed */
214 #define COMINITDOUBLE   0x29    /* Initialize Double Speed */
215 #define COMUNLOCK       0x30    /* Unlock */
216 #define COMLOCK         0x31    /* Lock */
217 #define COMLOCKST       0x32    /* Lock/Unlock Status */
218 #define COMVERSION      0x40    /* Get Firmware Revision */
219 #define COMVOIDREADMODE 0x50    /* Void Data Read Mode */
220 /* Read commands */
221 #define COMFETCH        0x60    /* Prefetch Data */
222 #define COMREAD         0x61    /* Read */
223 #define COMREADRAW      0x62    /* Read Raw Data */
224 #define COMREADALL      0x63    /* Read All 2646 Bytes */
225 /* Player control commands */
226 #define COMLEADIN       0x70    /* Seek To Lead-in */
227 #define COMSEEK         0x71    /* Seek */
228 #define COMPAUSEON      0x80    /* Pause On */
229 #define COMPAUSEOFF     0x81    /* Pause Off */
230 #define COMSTOP         0x82    /* Stop */
231 #define COMOPEN         0x90    /* Open Tray Door */
232 #define COMCLOSE        0x91    /* Close Tray Door */
233 #define COMPLAY         0xa0    /* Audio Play */
234 #define COMPLAY_TNO     0xa2    /* Audio Play By Track Number */
235 #define COMSUBQ         0xb0    /* Read Sub-q Code */
236 #define COMLOCATION     0xb1    /* Read Head Position */
237 /* Audio control commands */
238 #define COMCHCTRL       0xc0    /* Audio Channel Control */
239 /* Miscellaneous (test) commands */
240 #define COMDRVTEST      0xd0    /* Write Test Bytes */
241 #define COMTEST         0xd1    /* Diagnostic Test */
242 \f
243 /* Low level drive interface. Only here we do actual I/O
244    Waiting for status / data available */
245
246
247 /* Busy wait until FLAG goes low. Return 0 on timeout. */
248 static inline int flag_low(int flag, unsigned long timeout)
249 {
250         int flag_high;
251         unsigned long count = 0;
252
253         while ((flag_high = (inb(STATUS_PORT) & flag)))
254                 if (++count >= timeout)
255                         break;
256
257         DEBUG((DEBUG_DRIVE_IF, "flag_low 0x%x count %ld%s",
258                 flag, count, flag_high ? " timeout" : ""));
259         return !flag_high;
260 }
261
262
263 /* Timed waiting for status or data */
264 static int sleep_timeout;       /* max # of ticks to sleep */
265 static DECLARE_WAIT_QUEUE_HEAD(waitq);
266 static void sleep_timer(unsigned long data);
267 static DEFINE_TIMER(delay_timer, sleep_timer, 0, 0);
268 static DEFINE_SPINLOCK(optcd_lock);
269 static struct request_queue *opt_queue;
270
271 /* Timer routine: wake up when desired flag goes low,
272    or when timeout expires. */
273 static void sleep_timer(unsigned long data)
274 {
275         int flags = inb(STATUS_PORT) & FL_STDT;
276
277         if (flags == FL_STDT && --sleep_timeout > 0) {
278                 mod_timer(&delay_timer, jiffies + HZ/100); /* multi-statement macro */
279         } else
280                 wake_up(&waitq);
281 }
282
283
284 /* Sleep until FLAG goes low. Return 0 on timeout or wrong flag low. */
285 static int sleep_flag_low(int flag, unsigned long timeout)
286 {
287         int flag_high;
288
289         DEBUG((DEBUG_DRIVE_IF, "sleep_flag_low"));
290
291         sleep_timeout = timeout;
292         flag_high = inb(STATUS_PORT) & flag;
293         if (flag_high && sleep_timeout > 0) {
294                 mod_timer(&delay_timer, jiffies + HZ/100);
295                 sleep_on(&waitq);
296                 flag_high = inb(STATUS_PORT) & flag;
297         }
298
299         DEBUG((DEBUG_DRIVE_IF, "flag 0x%x count %ld%s",
300                 flag, timeout, flag_high ? " timeout" : ""));
301         return !flag_high;
302 }
303 \f
304 /* Low level drive interface. Only here we do actual I/O
305    Sending commands and parameters */
306
307
308 /* Errors in the command protocol */
309 #define ERR_IF_CMD_TIMEOUT      0x100
310 #define ERR_IF_ERR_TIMEOUT      0x101
311 #define ERR_IF_RESP_TIMEOUT     0x102
312 #define ERR_IF_DATA_TIMEOUT     0x103
313 #define ERR_IF_NOSTAT           0x104
314
315
316 /* Send command code. Return <0 indicates error */
317 static int send_cmd(int cmd)
318 {
319         unsigned char ack;
320
321         DEBUG((DEBUG_DRIVE_IF, "sending command 0x%02x\n", cmd));
322
323         outb(HCON_DTS, HCON_PORT);      /* Enable Suspend Data Transfer */
324         outb(cmd, COMIN_PORT);          /* Send command code */
325         if (!flag_low(FL_STEN, BUSY_TIMEOUT))   /* Wait for status */
326                 return -ERR_IF_CMD_TIMEOUT;
327         ack = inb(DATA_PORT);           /* read command acknowledge */
328         outb(HCON_SDRQB, HCON_PORT);    /* Disable Suspend Data Transfer */
329         return ack==ST_OP_OK ? 0 : -ack;
330 }
331
332
333 /* Send command parameters. Return <0 indicates error */
334 static int send_params(struct cdrom_msf *params)
335 {
336         unsigned char ack;
337
338         DEBUG((DEBUG_DRIVE_IF, "sending parameters"
339                 " %02x:%02x:%02x"
340                 " %02x:%02x:%02x",
341                 params->cdmsf_min0,
342                 params->cdmsf_sec0,
343                 params->cdmsf_frame0,
344                 params->cdmsf_min1,
345                 params->cdmsf_sec1,
346                 params->cdmsf_frame1));
347
348         outb(params->cdmsf_min0, COMIN_PORT);
349         outb(params->cdmsf_sec0, COMIN_PORT);
350         outb(params->cdmsf_frame0, COMIN_PORT);
351         outb(params->cdmsf_min1, COMIN_PORT);
352         outb(params->cdmsf_sec1, COMIN_PORT);
353         outb(params->cdmsf_frame1, COMIN_PORT);
354         if (!flag_low(FL_STEN, BUSY_TIMEOUT))   /* Wait for status */
355                 return -ERR_IF_CMD_TIMEOUT;
356         ack = inb(DATA_PORT);           /* read command acknowledge */
357         return ack==ST_PA_OK ? 0 : -ack;
358 }
359
360
361 /* Send parameters for SEEK command. Return <0 indicates error */
362 static int send_seek_params(struct cdrom_msf *params)
363 {
364         unsigned char ack;
365
366         DEBUG((DEBUG_DRIVE_IF, "sending seek parameters"
367                 " %02x:%02x:%02x",
368                 params->cdmsf_min0,
369                 params->cdmsf_sec0,
370                 params->cdmsf_frame0));
371
372         outb(params->cdmsf_min0, COMIN_PORT);
373         outb(params->cdmsf_sec0, COMIN_PORT);
374         outb(params->cdmsf_frame0, COMIN_PORT);
375         if (!flag_low(FL_STEN, BUSY_TIMEOUT))   /* Wait for status */
376                 return -ERR_IF_CMD_TIMEOUT;
377         ack = inb(DATA_PORT);           /* read command acknowledge */
378         return ack==ST_PA_OK ? 0 : -ack;
379 }
380
381
382 /* Wait for command execution status. Choice between busy waiting
383    and sleeping. Return value <0 indicates timeout. */
384 static inline int get_exec_status(int busy_waiting)
385 {
386         unsigned char exec_status;
387
388         if (busy_waiting
389             ? !flag_low(FL_STEN, BUSY_TIMEOUT)
390             : !sleep_flag_low(FL_STEN, SLEEP_TIMEOUT))
391                 return -ERR_IF_CMD_TIMEOUT;
392
393         exec_status = inb(DATA_PORT);
394         DEBUG((DEBUG_DRIVE_IF, "returned exec status 0x%02x", exec_status));
395         return exec_status;
396 }
397
398
399 /* Wait busy for extra byte of data that a command returns.
400    Return value <0 indicates timeout. */
401 static inline int get_data(int short_timeout)
402 {
403         unsigned char data;
404
405         if (!flag_low(FL_STEN, short_timeout ? FAST_TIMEOUT : BUSY_TIMEOUT))
406                 return -ERR_IF_DATA_TIMEOUT;
407
408         data = inb(DATA_PORT);
409         DEBUG((DEBUG_DRIVE_IF, "returned data 0x%02x", data));
410         return data;
411 }
412
413
414 /* Returns 0 if failed */
415 static int reset_drive(void)
416 {
417         unsigned long count = 0;
418         int flags;
419
420         DEBUG((DEBUG_DRIVE_IF, "reset drive"));
421
422         outb(0, RESET_PORT);
423         while (++count < RESET_WAIT)
424                 inb(DATA_PORT);
425
426         count = 0;
427         while ((flags = (inb(STATUS_PORT) & FL_RESET)) != FL_RESET)
428                 if (++count >= BUSY_TIMEOUT)
429                         break;
430
431         DEBUG((DEBUG_DRIVE_IF, "reset %s",
432                 flags == FL_RESET ? "succeeded" : "failed"));
433
434         if (flags != FL_RESET)
435                 return 0;               /* Reset failed */
436         outb(HCON_SDRQB, HCON_PORT);    /* Disable Suspend Data Transfer */
437         return 1;                       /* Reset succeeded */
438 }
439
440
441 /* Facilities for asynchronous operation */
442
443 /* Read status/data availability flags FL_STEN and FL_DTEN */
444 static inline int stdt_flags(void)
445 {
446         return inb(STATUS_PORT) & FL_STDT;
447 }
448
449
450 /* Fetch status that has previously been waited for. <0 means not available */
451 static inline int fetch_status(void)
452 {
453         unsigned char status;
454
455         if (inb(STATUS_PORT) & FL_STEN)
456                 return -ERR_IF_NOSTAT;
457
458         status = inb(DATA_PORT);
459         DEBUG((DEBUG_DRIVE_IF, "fetched exec status 0x%02x", status));
460         return status;
461 }
462
463
464 /* Fetch data that has previously been waited for. */
465 static inline void fetch_data(char *buf, int n)
466 {
467         insb(DATA_PORT, buf, n);
468         DEBUG((DEBUG_DRIVE_IF, "fetched 0x%x bytes", n));
469 }
470
471
472 /* Flush status and data fifos */
473 static inline void flush_data(void)
474 {
475         while ((inb(STATUS_PORT) & FL_STDT) != FL_STDT)
476                 inb(DATA_PORT);
477         DEBUG((DEBUG_DRIVE_IF, "flushed fifos"));
478 }
479 \f
480 /* Command protocol */
481
482
483 /* Send a simple command and wait for response. Command codes < COMFETCH
484    are quick response commands */
485 static inline int exec_cmd(int cmd)
486 {
487         int ack = send_cmd(cmd);
488         if (ack < 0)
489                 return ack;
490         return get_exec_status(cmd < COMFETCH);
491 }
492
493
494 /* Send a command with parameters. Don't wait for the response,
495  * which consists of data blocks read from the CD. */
496 static inline int exec_read_cmd(int cmd, struct cdrom_msf *params)
497 {
498         int ack = send_cmd(cmd);
499         if (ack < 0)
500                 return ack;
501         return send_params(params);
502 }
503
504
505 /* Send a seek command with parameters and wait for response */
506 static inline int exec_seek_cmd(int cmd, struct cdrom_msf *params)
507 {
508         int ack = send_cmd(cmd);
509         if (ack < 0)
510                 return ack;
511         ack = send_seek_params(params);
512         if (ack < 0)
513                 return ack;
514         return 0;
515 }
516
517
518 /* Send a command with parameters and wait for response */
519 static inline int exec_long_cmd(int cmd, struct cdrom_msf *params)
520 {
521         int ack = exec_read_cmd(cmd, params);
522         if (ack < 0)
523                 return ack;
524         return get_exec_status(0);
525 }
526 \f
527 /* Address conversion routines */
528
529
530 /* Binary to BCD (2 digits) */
531 static inline void single_bin2bcd(u_char *p)
532 {
533         DEBUG((DEBUG_CONV, "bin2bcd %02d", *p));
534         *p = (*p % 10) | ((*p / 10) << 4);
535 }
536
537
538 /* Convert entire msf struct */
539 static void bin2bcd(struct cdrom_msf *msf)
540 {
541         single_bin2bcd(&msf->cdmsf_min0);
542         single_bin2bcd(&msf->cdmsf_sec0);
543         single_bin2bcd(&msf->cdmsf_frame0);
544         single_bin2bcd(&msf->cdmsf_min1);
545         single_bin2bcd(&msf->cdmsf_sec1);
546         single_bin2bcd(&msf->cdmsf_frame1);
547 }
548
549
550 /* Linear block address to minute, second, frame form */
551 #define CD_FPM  (CD_SECS * CD_FRAMES)   /* frames per minute */
552
553 static void lba2msf(int lba, struct cdrom_msf *msf)
554 {
555         DEBUG((DEBUG_CONV, "lba2msf %d", lba));
556         lba += CD_MSF_OFFSET;
557         msf->cdmsf_min0 = lba / CD_FPM; lba %= CD_FPM;
558         msf->cdmsf_sec0 = lba / CD_FRAMES;
559         msf->cdmsf_frame0 = lba % CD_FRAMES;
560         msf->cdmsf_min1 = 0;
561         msf->cdmsf_sec1 = 0;
562         msf->cdmsf_frame1 = 0;
563         bin2bcd(msf);
564 }
565
566
567 /* Two BCD digits to binary */
568 static inline u_char bcd2bin(u_char bcd)
569 {
570         DEBUG((DEBUG_CONV, "bcd2bin %x%02x", bcd));
571         return (bcd >> 4) * 10 + (bcd & 0x0f);
572 }
573
574
575 static void msf2lba(union cdrom_addr *addr)
576 {
577         addr->lba = addr->msf.minute * CD_FPM
578                     + addr->msf.second * CD_FRAMES
579                     + addr->msf.frame - CD_MSF_OFFSET;
580 }
581
582
583 /* Minute, second, frame address BCD to binary or to linear address,
584    depending on MODE */
585 static void msf_bcd2bin(union cdrom_addr *addr)
586 {
587         addr->msf.minute = bcd2bin(addr->msf.minute);
588         addr->msf.second = bcd2bin(addr->msf.second);
589         addr->msf.frame = bcd2bin(addr->msf.frame);
590 }
591 \f
592 /* High level drive commands */
593
594
595 static int audio_status = CDROM_AUDIO_NO_STATUS;
596 static char toc_uptodate = 0;
597 static char disk_changed = 1;
598
599 /* Get drive status, flagging completion of audio play and disk changes. */
600 static int drive_status(void)
601 {
602         int status;
603
604         status = exec_cmd(COMIOCTLISTAT);
605         DEBUG((DEBUG_DRIVE_IF, "IOCTLISTAT: %03x", status));
606         if (status < 0)
607                 return status;
608         if (status == 0xff)     /* No status available */
609                 return -ERR_IF_NOSTAT;
610
611         if (((status & ST_MODE_BITS) != ST_M_AUDIO) &&
612                 (audio_status == CDROM_AUDIO_PLAY)) {
613                 audio_status = CDROM_AUDIO_COMPLETED;
614         }
615
616         if (status & ST_DSK_CHG) {
617                 toc_uptodate = 0;
618                 disk_changed = 1;
619                 audio_status = CDROM_AUDIO_NO_STATUS;
620         }
621
622         return status;
623 }
624
625
626 /* Read the current Q-channel info. Also used for reading the
627    table of contents. qp->cdsc_format must be set on entry to
628    indicate the desired address format */
629 static int get_q_channel(struct cdrom_subchnl *qp)
630 {
631         int status, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10;
632
633         status = drive_status();
634         if (status < 0)
635                 return status;
636         qp->cdsc_audiostatus = audio_status;
637
638         status = exec_cmd(COMSUBQ);
639         if (status < 0)
640                 return status;
641
642         d1 = get_data(0);
643         if (d1 < 0)
644                 return d1;
645         qp->cdsc_adr = d1;
646         qp->cdsc_ctrl = d1 >> 4;
647
648         d2 = get_data(0);
649         if (d2 < 0)
650                 return d2;
651         qp->cdsc_trk = bcd2bin(d2);
652
653         d3 = get_data(0);
654         if (d3 < 0)
655                 return d3;
656         qp->cdsc_ind = bcd2bin(d3);
657
658         d4 = get_data(0);
659         if (d4 < 0)
660                 return d4;
661         qp->cdsc_reladdr.msf.minute = d4;
662
663         d5 = get_data(0);
664         if (d5 < 0)
665                 return d5;
666         qp->cdsc_reladdr.msf.second = d5;
667
668         d6 = get_data(0);
669         if (d6 < 0)
670                 return d6;
671         qp->cdsc_reladdr.msf.frame = d6;
672
673         d7 = get_data(0);
674         if (d7 < 0)
675                 return d7;
676         /* byte not used */
677
678         d8 = get_data(0);
679         if (d8 < 0)
680                 return d8;
681         qp->cdsc_absaddr.msf.minute = d8;
682
683         d9 = get_data(0);
684         if (d9 < 0)
685                 return d9;
686         qp->cdsc_absaddr.msf.second = d9;
687
688         d10 = get_data(0);
689         if (d10 < 0)
690                 return d10;
691         qp->cdsc_absaddr.msf.frame = d10;
692
693         DEBUG((DEBUG_TOC, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
694                 d1, d2, d3, d4, d5, d6, d7, d8, d9, d10));
695
696         msf_bcd2bin(&qp->cdsc_absaddr);
697         msf_bcd2bin(&qp->cdsc_reladdr);
698         if (qp->cdsc_format == CDROM_LBA) {
699                 msf2lba(&qp->cdsc_absaddr);
700                 msf2lba(&qp->cdsc_reladdr);
701         }
702
703         return 0;
704 }
705 \f
706 /* Table of contents handling */
707
708
709 /* Errors in table of contents */
710 #define ERR_TOC_MISSINGINFO     0x120
711 #define ERR_TOC_MISSINGENTRY    0x121
712
713
714 struct cdrom_disk_info {
715         unsigned char           first;
716         unsigned char           last;
717         struct cdrom_msf0       disk_length;
718         struct cdrom_msf0       first_track;
719         /* Multisession info: */
720         unsigned char           next;
721         struct cdrom_msf0       next_session;
722         struct cdrom_msf0       last_session;
723         unsigned char           multi;
724         unsigned char           xa;
725         unsigned char           audio;
726 };
727 static struct cdrom_disk_info disk_info;
728
729 #define MAX_TRACKS              111
730 static struct cdrom_subchnl toc[MAX_TRACKS];
731
732 #define QINFO_FIRSTTRACK        100 /* bcd2bin(0xa0) */
733 #define QINFO_LASTTRACK         101 /* bcd2bin(0xa1) */
734 #define QINFO_DISKLENGTH        102 /* bcd2bin(0xa2) */
735 #define QINFO_NEXTSESSION       110 /* bcd2bin(0xb0) */
736
737 #define I_FIRSTTRACK    0x01
738 #define I_LASTTRACK     0x02
739 #define I_DISKLENGTH    0x04
740 #define I_NEXTSESSION   0x08
741 #define I_ALL   (I_FIRSTTRACK | I_LASTTRACK | I_DISKLENGTH)
742
743
744 #if DEBUG_TOC
745 static void toc_debug_info(int i)
746 {
747         printk(KERN_DEBUG "#%3d ctl %1x, adr %1x, track %2d index %3d"
748                 "  %2d:%02d.%02d %2d:%02d.%02d\n",
749                 i, toc[i].cdsc_ctrl, toc[i].cdsc_adr,
750                 toc[i].cdsc_trk, toc[i].cdsc_ind,
751                 toc[i].cdsc_reladdr.msf.minute,
752                 toc[i].cdsc_reladdr.msf.second,
753                 toc[i].cdsc_reladdr.msf.frame,
754                 toc[i].cdsc_absaddr.msf.minute,
755                 toc[i].cdsc_absaddr.msf.second,
756                 toc[i].cdsc_absaddr.msf.frame);
757 }
758 #endif
759
760
761 static int read_toc(void)
762 {
763         int status, limit, count;
764         unsigned char got_info = 0;
765         struct cdrom_subchnl q_info;
766 #if DEBUG_TOC
767         int i;
768 #endif
769
770         DEBUG((DEBUG_TOC, "starting read_toc"));
771
772         count = 0;
773         for (limit = 60; limit > 0; limit--) {
774                 int index;
775
776                 q_info.cdsc_format = CDROM_MSF;
777                 status = get_q_channel(&q_info);
778                 if (status < 0)
779                         return status;
780
781                 index = q_info.cdsc_ind;
782                 if (index > 0 && index < MAX_TRACKS
783                     && q_info.cdsc_trk == 0 && toc[index].cdsc_ind == 0) {
784                         toc[index] = q_info;
785                         DEBUG((DEBUG_TOC, "got %d", index));
786                         if (index < 100)
787                                 count++;
788
789                         switch (q_info.cdsc_ind) {
790                         case QINFO_FIRSTTRACK:
791                                 got_info |= I_FIRSTTRACK;
792                                 break;
793                         case QINFO_LASTTRACK:
794                                 got_info |= I_LASTTRACK;
795                                 break;
796                         case QINFO_DISKLENGTH:
797                                 got_info |= I_DISKLENGTH;
798                                 break;
799                         case QINFO_NEXTSESSION:
800                                 got_info |= I_NEXTSESSION;
801                                 break;
802                         }
803                 }
804
805                 if ((got_info & I_ALL) == I_ALL
806                     && toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count
807                        >= toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1)
808                         break;
809         }
810
811         /* Construct disk_info from TOC */
812         if (disk_info.first == 0) {
813                 disk_info.first = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute;
814                 disk_info.first_track.minute =
815                         toc[disk_info.first].cdsc_absaddr.msf.minute;
816                 disk_info.first_track.second =
817                         toc[disk_info.first].cdsc_absaddr.msf.second;
818                 disk_info.first_track.frame =
819                         toc[disk_info.first].cdsc_absaddr.msf.frame;
820         }
821         disk_info.last = toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute;
822         disk_info.disk_length.minute =
823                         toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.minute;
824         disk_info.disk_length.second =
825                         toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.second-2;
826         disk_info.disk_length.frame =
827                         toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.frame;
828         disk_info.next_session.minute =
829                         toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.minute;
830         disk_info.next_session.second =
831                         toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.second;
832         disk_info.next_session.frame =
833                         toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.frame;
834         disk_info.next = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute;
835         disk_info.last_session.minute =
836                         toc[disk_info.next].cdsc_absaddr.msf.minute;
837         disk_info.last_session.second =
838                         toc[disk_info.next].cdsc_absaddr.msf.second;
839         disk_info.last_session.frame =
840                         toc[disk_info.next].cdsc_absaddr.msf.frame;
841         toc[disk_info.last + 1].cdsc_absaddr.msf.minute =
842                         disk_info.disk_length.minute;
843         toc[disk_info.last + 1].cdsc_absaddr.msf.second =
844                         disk_info.disk_length.second;
845         toc[disk_info.last + 1].cdsc_absaddr.msf.frame =
846                         disk_info.disk_length.frame;
847 #if DEBUG_TOC
848         for (i = 1; i <= disk_info.last + 1; i++)
849                 toc_debug_info(i);
850         toc_debug_info(QINFO_FIRSTTRACK);
851         toc_debug_info(QINFO_LASTTRACK);
852         toc_debug_info(QINFO_DISKLENGTH);
853         toc_debug_info(QINFO_NEXTSESSION);
854 #endif
855
856         DEBUG((DEBUG_TOC, "exiting read_toc, got_info %x, count %d",
857                 got_info, count));
858         if ((got_info & I_ALL) != I_ALL
859             || toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count
860                < toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1)
861                 return -ERR_TOC_MISSINGINFO;
862         return 0;
863 }
864
865
866 #ifdef MULTISESSION
867 static int get_multi_disk_info(void)
868 {
869         int sessions, status;
870         struct cdrom_msf multi_index;
871
872
873         for (sessions = 2; sessions < 10 /* %%for now */; sessions++) {
874                 int count;
875
876                 for (count = 100; count < MAX_TRACKS; count++) 
877                         toc[count].cdsc_ind = 0;
878
879                 multi_index.cdmsf_min0 = disk_info.next_session.minute;
880                 multi_index.cdmsf_sec0 = disk_info.next_session.second;
881                 multi_index.cdmsf_frame0 = disk_info.next_session.frame;
882                 if (multi_index.cdmsf_sec0 >= 20)
883                         multi_index.cdmsf_sec0 -= 20;
884                 else {
885                         multi_index.cdmsf_sec0 += 40;
886                         multi_index.cdmsf_min0--;
887                 }
888                 DEBUG((DEBUG_MULTIS, "Try %d: %2d:%02d.%02d", sessions,
889                         multi_index.cdmsf_min0,
890                         multi_index.cdmsf_sec0,
891                         multi_index.cdmsf_frame0));
892                 bin2bcd(&multi_index);
893                 multi_index.cdmsf_min1 = 0;
894                 multi_index.cdmsf_sec1 = 0;
895                 multi_index.cdmsf_frame1 = 1;
896
897                 status = exec_read_cmd(COMREAD, &multi_index);
898                 if (status < 0) {
899                         DEBUG((DEBUG_TOC, "exec_read_cmd COMREAD: %02x",
900                                 -status));
901                         break;
902                 }
903                 status = sleep_flag_low(FL_DTEN, MULTI_SEEK_TIMEOUT) ?
904                                 0 : -ERR_TOC_MISSINGINFO;
905                 flush_data();
906                 if (status < 0) {
907                         DEBUG((DEBUG_TOC, "sleep_flag_low: %02x", -status));
908                         break;
909                 }
910
911                 status = read_toc();
912                 if (status < 0) {
913                         DEBUG((DEBUG_TOC, "read_toc: %02x", -status));
914                         break;
915                 }
916
917                 disk_info.multi = 1;
918         }
919
920         exec_cmd(COMSTOP);
921
922         if (status < 0)
923                 return -EIO;
924         return 0;
925 }
926 #endif /* MULTISESSION */
927
928
929 static int update_toc(void)
930 {
931         int status, count;
932
933         if (toc_uptodate)
934                 return 0;
935
936         DEBUG((DEBUG_TOC, "starting update_toc"));
937
938         disk_info.first = 0;
939         for (count = 0; count < MAX_TRACKS; count++) 
940                 toc[count].cdsc_ind = 0;
941
942         status = exec_cmd(COMLEADIN);
943         if (status < 0)
944                 return -EIO;
945
946         status = read_toc();
947         if (status < 0) {
948                 DEBUG((DEBUG_TOC, "read_toc: %02x", -status));
949                 return -EIO;
950         }
951
952         /* Audio disk detection. Look at first track. */
953         disk_info.audio =
954                 (toc[disk_info.first].cdsc_ctrl & CDROM_DATA_TRACK) ? 0 : 1;
955
956         /* XA detection */
957         disk_info.xa = drive_status() & ST_MODE2TRACK;
958
959         /* Multisession detection: if we want this, define MULTISESSION */
960         disk_info.multi = 0;
961 #ifdef MULTISESSION
962         if (disk_info.xa)
963                 get_multi_disk_info();  /* Here disk_info.multi is set */
964 #endif /* MULTISESSION */
965         if (disk_info.multi)
966                 printk(KERN_WARNING "optcd: Multisession support experimental, "
967                         "see Documentation/cdrom/optcd\n");
968
969         DEBUG((DEBUG_TOC, "exiting update_toc"));
970
971         toc_uptodate = 1;
972         return 0;
973 }
974 \f
975 /* Request handling */
976
977 static int current_valid(void)
978 {
979         return CURRENT &&
980                 CURRENT->cmd == READ &&
981                 CURRENT->sector != -1;
982 }
983
984 /* Buffers for block size conversion. */
985 #define NOBUF           -1
986
987 static char buf[CD_FRAMESIZE * N_BUFS];
988 static volatile int buf_bn[N_BUFS], next_bn;
989 static volatile int buf_in = 0, buf_out = NOBUF;
990
991 static inline void opt_invalidate_buffers(void)
992 {
993         int i;
994
995         DEBUG((DEBUG_BUFFERS, "executing opt_invalidate_buffers"));
996
997         for (i = 0; i < N_BUFS; i++)
998                 buf_bn[i] = NOBUF;
999         buf_out = NOBUF;
1000 }
1001
1002
1003 /* Take care of the different block sizes between cdrom and Linux.
1004    When Linux gets variable block sizes this will probably go away. */
1005 static void transfer(void)
1006 {
1007 #if DEBUG_BUFFERS | DEBUG_REQUEST
1008         printk(KERN_DEBUG "optcd: executing transfer\n");
1009 #endif
1010
1011         if (!current_valid())
1012                 return;
1013         while (CURRENT -> nr_sectors) {
1014                 int bn = CURRENT -> sector / 4;
1015                 int i, offs, nr_sectors;
1016                 for (i = 0; i < N_BUFS && buf_bn[i] != bn; ++i);
1017
1018                 DEBUG((DEBUG_REQUEST, "found %d", i));
1019
1020                 if (i >= N_BUFS) {
1021                         buf_out = NOBUF;
1022                         break;
1023                 }
1024
1025                 offs = (i * 4 + (CURRENT -> sector & 3)) * 512;
1026                 nr_sectors = 4 - (CURRENT -> sector & 3);
1027
1028                 if (buf_out != i) {
1029                         buf_out = i;
1030                         if (buf_bn[i] != bn) {
1031                                 buf_out = NOBUF;
1032                                 continue;
1033                         }
1034                 }
1035
1036                 if (nr_sectors > CURRENT -> nr_sectors)
1037                         nr_sectors = CURRENT -> nr_sectors;
1038                 memcpy(CURRENT -> buffer, buf + offs, nr_sectors * 512);
1039                 CURRENT -> nr_sectors -= nr_sectors;
1040                 CURRENT -> sector += nr_sectors;
1041                 CURRENT -> buffer += nr_sectors * 512;
1042         }
1043 }
1044
1045
1046 /* State machine for reading disk blocks */
1047
1048 enum state_e {
1049         S_IDLE,         /* 0 */
1050         S_START,        /* 1 */
1051         S_READ,         /* 2 */
1052         S_DATA,         /* 3 */
1053         S_STOP,         /* 4 */
1054         S_STOPPING      /* 5 */
1055 };
1056
1057 static volatile enum state_e state = S_IDLE;
1058 #if DEBUG_STATE
1059 static volatile enum state_e state_old = S_STOP;
1060 static volatile int flags_old = 0;
1061 static volatile long state_n = 0;
1062 #endif
1063
1064
1065 /* Used as mutex to keep do_optcd_request (and other processes calling
1066    ioctl) out while some process is inside a VFS call.
1067    Reverse is accomplished by checking if state = S_IDLE upon entry
1068    of opt_ioctl and opt_media_change. */
1069 static int in_vfs = 0;
1070
1071
1072 static volatile int transfer_is_active = 0;
1073 static volatile int error = 0;  /* %% do something with this?? */
1074 static int tries;               /* ibid?? */
1075 static int timeout = 0;
1076
1077 static void poll(unsigned long data);
1078 static struct timer_list req_timer = {.function = poll};
1079
1080
1081 static void poll(unsigned long data)
1082 {
1083         static volatile int read_count = 1;
1084         int flags;
1085         int loop_again = 1;
1086         int status = 0;
1087         int skip = 0;
1088
1089         if (error) {
1090                 printk(KERN_ERR "optcd: I/O error 0x%02x\n", error);
1091                 opt_invalidate_buffers();
1092                 if (!tries--) {
1093                         printk(KERN_ERR "optcd: read block %d failed;"
1094                                 " Giving up\n", next_bn);
1095                         if (transfer_is_active)
1096                                 loop_again = 0;
1097                         if (current_valid())
1098                                 end_request(CURRENT, 0);
1099                         tries = 5;
1100                 }
1101                 error = 0;
1102                 state = S_STOP;
1103         }
1104
1105         while (loop_again)
1106         {
1107                 loop_again = 0; /* each case must flip this back to 1 if we want
1108                                  to come back up here */
1109
1110 #if DEBUG_STATE
1111                 if (state == state_old)
1112                         state_n++;
1113                 else {
1114                         state_old = state;
1115                         if (++state_n > 1)
1116                                 printk(KERN_DEBUG "optcd: %ld times "
1117                                         "in previous state\n", state_n);
1118                         printk(KERN_DEBUG "optcd: state %d\n", state);
1119                         state_n = 0;
1120                 }
1121 #endif
1122
1123                 switch (state) {
1124                 case S_IDLE:
1125                         return;
1126                 case S_START:
1127                         if (in_vfs)
1128                                 break;
1129                         if (send_cmd(COMDRVST)) {
1130                                 state = S_IDLE;
1131                                 while (current_valid())
1132                                         end_request(CURRENT, 0);
1133                                 return;
1134                         }
1135                         state = S_READ;
1136                         timeout = READ_TIMEOUT;
1137                         break;
1138                 case S_READ: {
1139                         struct cdrom_msf msf;
1140                         if (!skip) {
1141                                 status = fetch_status();
1142                                 if (status < 0)
1143                                         break;
1144                                 if (status & ST_DSK_CHG) {
1145                                         toc_uptodate = 0;
1146                                         opt_invalidate_buffers();
1147                                 }
1148                         }
1149                         skip = 0;
1150                         if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) {
1151                                 toc_uptodate = 0;
1152                                 opt_invalidate_buffers();
1153                                 printk(KERN_WARNING "optcd: %s\n",
1154                                         (status & ST_DOOR_OPEN)
1155                                         ? "door open"
1156                                         : "disk removed");
1157                                 state = S_IDLE;
1158                                 while (current_valid())
1159                                         end_request(CURRENT, 0);
1160                                 return;
1161                         }
1162                         if (!current_valid()) {
1163                                 state = S_STOP;
1164                                 loop_again = 1;
1165                                 break;
1166                         }
1167                         next_bn = CURRENT -> sector / 4;
1168                         lba2msf(next_bn, &msf);
1169                         read_count = N_BUFS;
1170                         msf.cdmsf_frame1 = read_count; /* Not BCD! */
1171
1172                         DEBUG((DEBUG_REQUEST, "reading %x:%x.%x %x:%x.%x",
1173                                 msf.cdmsf_min0,
1174                                 msf.cdmsf_sec0,
1175                                 msf.cdmsf_frame0,
1176                                 msf.cdmsf_min1,
1177                                 msf.cdmsf_sec1,
1178                                 msf.cdmsf_frame1));
1179                         DEBUG((DEBUG_REQUEST, "next_bn:%d buf_in:%d"
1180                                 " buf_out:%d buf_bn:%d",
1181                                 next_bn,
1182                                 buf_in,
1183                                 buf_out,
1184                                 buf_bn[buf_in]));
1185
1186                         exec_read_cmd(COMREAD, &msf);
1187                         state = S_DATA;
1188                         timeout = READ_TIMEOUT;
1189                         break;
1190                 }
1191                 case S_DATA:
1192                         flags = stdt_flags() & (FL_STEN|FL_DTEN);
1193
1194 #if DEBUG_STATE
1195                         if (flags != flags_old) {
1196                                 flags_old = flags;
1197                                 printk(KERN_DEBUG "optcd: flags:%x\n", flags);
1198                         }
1199                         if (flags == FL_STEN)
1200                                 printk(KERN_DEBUG "timeout cnt: %d\n", timeout);
1201 #endif
1202
1203                         switch (flags) {
1204                         case FL_DTEN:           /* only STEN low */
1205                                 if (!tries--) {
1206                                         printk(KERN_ERR
1207                                                 "optcd: read block %d failed; "
1208                                                 "Giving up\n", next_bn);
1209                                         if (transfer_is_active) {
1210                                                 tries = 0;
1211                                                 break;
1212                                         }
1213                                         if (current_valid())
1214                                                 end_request(CURRENT, 0);
1215                                         tries = 5;
1216                                 }
1217                                 state = S_START;
1218                                 timeout = READ_TIMEOUT;
1219                                 loop_again = 1;
1220                         case (FL_STEN|FL_DTEN):  /* both high */
1221                                 break;
1222                         default:        /* DTEN low */
1223                                 tries = 5;
1224                                 if (!current_valid() && buf_in == buf_out) {
1225                                         state = S_STOP;
1226                                         loop_again = 1;
1227                                         break;
1228                                 }
1229                                 if (read_count<=0)
1230                                         printk(KERN_WARNING
1231                                                 "optcd: warning - try to read"
1232                                                 " 0 frames\n");
1233                                 while (read_count) {
1234                                         buf_bn[buf_in] = NOBUF;
1235                                         if (!flag_low(FL_DTEN, BUSY_TIMEOUT)) {
1236                                         /* should be no waiting here!?? */
1237                                                 printk(KERN_ERR
1238                                                    "read_count:%d "
1239                                                    "CURRENT->nr_sectors:%ld "
1240                                                    "buf_in:%d\n",
1241                                                         read_count,
1242                                                         CURRENT->nr_sectors,
1243                                                         buf_in);
1244                                                 printk(KERN_ERR
1245                                                         "transfer active: %x\n",
1246                                                         transfer_is_active);
1247                                                 read_count = 0;
1248                                                 state = S_STOP;
1249                                                 loop_again = 1;
1250                                                 end_request(CURRENT, 0);
1251                                                 break;
1252                                         }
1253                                         fetch_data(buf+
1254                                             CD_FRAMESIZE*buf_in,
1255                                             CD_FRAMESIZE);
1256                                         read_count--;
1257
1258                                         DEBUG((DEBUG_REQUEST,
1259                                                 "S_DATA; ---I've read data- "
1260                                                 "read_count: %d",
1261                                                 read_count));
1262                                         DEBUG((DEBUG_REQUEST,
1263                                                 "next_bn:%d  buf_in:%d "
1264                                                 "buf_out:%d  buf_bn:%d",
1265                                                 next_bn,
1266                                                 buf_in,
1267                                                 buf_out,
1268                                                 buf_bn[buf_in]));
1269
1270                                         buf_bn[buf_in] = next_bn++;
1271                                         if (buf_out == NOBUF)
1272                                                 buf_out = buf_in;
1273                                         buf_in = buf_in + 1 ==
1274                                                 N_BUFS ? 0 : buf_in + 1;
1275                                 }
1276                                 if (!transfer_is_active) {
1277                                         while (current_valid()) {
1278                                                 transfer();
1279                                                 if (CURRENT -> nr_sectors == 0)
1280                                                         end_request(CURRENT, 1);
1281                                                 else
1282                                                         break;
1283                                         }
1284                                 }
1285
1286                                 if (current_valid()
1287                                     && (CURRENT -> sector / 4 < next_bn ||
1288                                     CURRENT -> sector / 4 >
1289                                      next_bn + N_BUFS)) {
1290                                         state = S_STOP;
1291                                         loop_again = 1;
1292                                         break;
1293                                 }
1294                                 timeout = READ_TIMEOUT;
1295                                 if (read_count == 0) {
1296                                         state = S_STOP;
1297                                         loop_again = 1;
1298                                         break;
1299                                 }
1300                         }
1301                         break;
1302                 case S_STOP:
1303                         if (read_count != 0)
1304                                 printk(KERN_ERR
1305                                         "optcd: discard data=%x frames\n",
1306                                         read_count);
1307                         flush_data();
1308                         if (send_cmd(COMDRVST)) {
1309                                 state = S_IDLE;
1310                                 while (current_valid())
1311                                         end_request(CURRENT, 0);
1312                                 return;
1313                         }
1314                         state = S_STOPPING;
1315                         timeout = STOP_TIMEOUT;
1316                         break;
1317                 case S_STOPPING:
1318                         status = fetch_status();
1319                         if (status < 0 && timeout)
1320                                         break;
1321                         if ((status >= 0) && (status & ST_DSK_CHG)) {
1322                                 toc_uptodate = 0;
1323                                 opt_invalidate_buffers();
1324                         }
1325                         if (current_valid()) {
1326                                 if (status >= 0) {
1327                                         state = S_READ;
1328                                         loop_again = 1;
1329                                         skip = 1;
1330                                         break;
1331                                 } else {
1332                                         state = S_START;
1333                                         timeout = 1;
1334                                 }
1335                         } else {
1336                                 state = S_IDLE;
1337                                 return;
1338                         }
1339                         break;
1340                 default:
1341                         printk(KERN_ERR "optcd: invalid state %d\n", state);
1342                         return;
1343                 } /* case */
1344         } /* while */
1345
1346         if (!timeout--) {
1347                 printk(KERN_ERR "optcd: timeout in state %d\n", state);
1348                 state = S_STOP;
1349                 if (exec_cmd(COMSTOP) < 0) {
1350                         state = S_IDLE;
1351                         while (current_valid())
1352                                 end_request(CURRENT, 0);
1353                         return;
1354                 }
1355         }
1356
1357         mod_timer(&req_timer, jiffies + HZ/100);
1358 }
1359
1360
1361 static void do_optcd_request(request_queue_t * q)
1362 {
1363         DEBUG((DEBUG_REQUEST, "do_optcd_request(%ld+%ld)",
1364                CURRENT -> sector, CURRENT -> nr_sectors));
1365
1366         if (disk_info.audio) {
1367                 printk(KERN_WARNING "optcd: tried to mount an Audio CD\n");
1368                 end_request(CURRENT, 0);
1369                 return;
1370         }
1371
1372         transfer_is_active = 1;
1373         while (current_valid()) {
1374                 transfer();     /* First try to transfer block from buffers */
1375                 if (CURRENT -> nr_sectors == 0) {
1376                         end_request(CURRENT, 1);
1377                 } else {        /* Want to read a block not in buffer */
1378                         buf_out = NOBUF;
1379                         if (state == S_IDLE) {
1380                                 /* %% Should this block the request queue?? */
1381                                 if (update_toc() < 0) {
1382                                         while (current_valid())
1383                                                 end_request(CURRENT, 0);
1384                                         break;
1385                                 }
1386                                 /* Start state machine */
1387                                 state = S_START;
1388                                 timeout = READ_TIMEOUT;
1389                                 tries = 5;
1390                                 /* %% why not start right away?? */
1391                                 mod_timer(&req_timer, jiffies + HZ/100);
1392                         }
1393                         break;
1394                 }
1395         }
1396         transfer_is_active = 0;
1397
1398         DEBUG((DEBUG_REQUEST, "next_bn:%d  buf_in:%d buf_out:%d  buf_bn:%d",
1399                next_bn, buf_in, buf_out, buf_bn[buf_in]));
1400         DEBUG((DEBUG_REQUEST, "do_optcd_request ends"));
1401 }
1402 \f
1403 /* IOCTLs */
1404
1405
1406 static char auto_eject = 0;
1407
1408 static int cdrompause(void)
1409 {
1410         int status;
1411
1412         if (audio_status != CDROM_AUDIO_PLAY)
1413                 return -EINVAL;
1414
1415         status = exec_cmd(COMPAUSEON);
1416         if (status < 0) {
1417                 DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEON: %02x", -status));
1418                 return -EIO;
1419         }
1420         audio_status = CDROM_AUDIO_PAUSED;
1421         return 0;
1422 }
1423
1424
1425 static int cdromresume(void)
1426 {
1427         int status;
1428
1429         if (audio_status != CDROM_AUDIO_PAUSED)
1430                 return -EINVAL;
1431
1432         status = exec_cmd(COMPAUSEOFF);
1433         if (status < 0) {
1434                 DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEOFF: %02x", -status));
1435                 audio_status = CDROM_AUDIO_ERROR;
1436                 return -EIO;
1437         }
1438         audio_status = CDROM_AUDIO_PLAY;
1439         return 0;
1440 }
1441
1442
1443 static int cdromplaymsf(void __user *arg)
1444 {
1445         int status;
1446         struct cdrom_msf msf;
1447
1448         if (copy_from_user(&msf, arg, sizeof msf))
1449                 return -EFAULT;
1450
1451         bin2bcd(&msf);
1452         status = exec_long_cmd(COMPLAY, &msf);
1453         if (status < 0) {
1454                 DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status));
1455                 audio_status = CDROM_AUDIO_ERROR;
1456                 return -EIO;
1457         }
1458
1459         audio_status = CDROM_AUDIO_PLAY;
1460         return 0;
1461 }
1462
1463
1464 static int cdromplaytrkind(void __user *arg)
1465 {
1466         int status;
1467         struct cdrom_ti ti;
1468         struct cdrom_msf msf;
1469
1470         if (copy_from_user(&ti, arg, sizeof ti))
1471                 return -EFAULT;
1472
1473         if (ti.cdti_trk0 < disk_info.first
1474             || ti.cdti_trk0 > disk_info.last
1475             || ti.cdti_trk1 < ti.cdti_trk0)
1476                 return -EINVAL;
1477         if (ti.cdti_trk1 > disk_info.last)
1478                 ti.cdti_trk1 = disk_info.last;
1479
1480         msf.cdmsf_min0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.minute;
1481         msf.cdmsf_sec0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.second;
1482         msf.cdmsf_frame0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.frame;
1483         msf.cdmsf_min1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.minute;
1484         msf.cdmsf_sec1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.second;
1485         msf.cdmsf_frame1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.frame;
1486
1487         DEBUG((DEBUG_VFS, "play %02d:%02d.%02d to %02d:%02d.%02d",
1488                 msf.cdmsf_min0,
1489                 msf.cdmsf_sec0,
1490                 msf.cdmsf_frame0,
1491                 msf.cdmsf_min1,
1492                 msf.cdmsf_sec1,
1493                 msf.cdmsf_frame1));
1494
1495         bin2bcd(&msf);
1496         status = exec_long_cmd(COMPLAY, &msf);
1497         if (status < 0) {
1498                 DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status));
1499                 audio_status = CDROM_AUDIO_ERROR;
1500                 return -EIO;
1501         }
1502
1503         audio_status = CDROM_AUDIO_PLAY;
1504         return 0;
1505 }
1506
1507
1508 static int cdromreadtochdr(void __user *arg)
1509 {
1510         struct cdrom_tochdr tochdr;
1511
1512         tochdr.cdth_trk0 = disk_info.first;
1513         tochdr.cdth_trk1 = disk_info.last;
1514
1515         return copy_to_user(arg, &tochdr, sizeof tochdr) ? -EFAULT : 0;
1516 }
1517
1518
1519 static int cdromreadtocentry(void __user *arg)
1520 {
1521         struct cdrom_tocentry entry;
1522         struct cdrom_subchnl *tocptr;
1523
1524         if (copy_from_user(&entry, arg, sizeof entry))
1525                 return -EFAULT;
1526
1527         if (entry.cdte_track == CDROM_LEADOUT)
1528                 tocptr = &toc[disk_info.last + 1];
1529         else if (entry.cdte_track > disk_info.last
1530                 || entry.cdte_track < disk_info.first)
1531                 return -EINVAL;
1532         else
1533                 tocptr = &toc[entry.cdte_track];
1534
1535         entry.cdte_adr = tocptr->cdsc_adr;
1536         entry.cdte_ctrl = tocptr->cdsc_ctrl;
1537         entry.cdte_addr.msf.minute = tocptr->cdsc_absaddr.msf.minute;
1538         entry.cdte_addr.msf.second = tocptr->cdsc_absaddr.msf.second;
1539         entry.cdte_addr.msf.frame = tocptr->cdsc_absaddr.msf.frame;
1540         /* %% What should go into entry.cdte_datamode? */
1541
1542         if (entry.cdte_format == CDROM_LBA)
1543                 msf2lba(&entry.cdte_addr);
1544         else if (entry.cdte_format != CDROM_MSF)
1545                 return -EINVAL;
1546
1547         return copy_to_user(arg, &entry, sizeof entry) ? -EFAULT : 0;
1548 }
1549
1550
1551 static int cdromvolctrl(void __user *arg)
1552 {
1553         int status;
1554         struct cdrom_volctrl volctrl;
1555         struct cdrom_msf msf;
1556
1557         if (copy_from_user(&volctrl, arg, sizeof volctrl))
1558                 return -EFAULT;
1559
1560         msf.cdmsf_min0 = 0x10;
1561         msf.cdmsf_sec0 = 0x32;
1562         msf.cdmsf_frame0 = volctrl.channel0;
1563         msf.cdmsf_min1 = volctrl.channel1;
1564         msf.cdmsf_sec1 = volctrl.channel2;
1565         msf.cdmsf_frame1 = volctrl.channel3;
1566
1567         status = exec_long_cmd(COMCHCTRL, &msf);
1568         if (status < 0) {
1569                 DEBUG((DEBUG_VFS, "exec_long_cmd COMCHCTRL: %02x", -status));
1570                 return -EIO;
1571         }
1572         return 0;
1573 }
1574
1575
1576 static int cdromsubchnl(void __user *arg)
1577 {
1578         int status;
1579         struct cdrom_subchnl subchnl;
1580
1581         if (copy_from_user(&subchnl, arg, sizeof subchnl))
1582                 return -EFAULT;
1583
1584         if (subchnl.cdsc_format != CDROM_LBA
1585             && subchnl.cdsc_format != CDROM_MSF)
1586                 return -EINVAL;
1587
1588         status = get_q_channel(&subchnl);
1589         if (status < 0) {
1590                 DEBUG((DEBUG_VFS, "get_q_channel: %02x", -status));
1591                 return -EIO;
1592         }
1593
1594         if (copy_to_user(arg, &subchnl, sizeof subchnl))
1595                 return -EFAULT;
1596         return 0;
1597 }
1598
1599
1600 static struct gendisk *optcd_disk;
1601
1602
1603 static int cdromread(void __user *arg, int blocksize, int cmd)
1604 {
1605         int status;
1606         struct cdrom_msf msf;
1607
1608         if (copy_from_user(&msf, arg, sizeof msf))
1609                 return -EFAULT;
1610
1611         bin2bcd(&msf);
1612         msf.cdmsf_min1 = 0;
1613         msf.cdmsf_sec1 = 0;
1614         msf.cdmsf_frame1 = 1;   /* read only one frame */
1615         status = exec_read_cmd(cmd, &msf);
1616
1617         DEBUG((DEBUG_VFS, "read cmd status 0x%x", status));
1618
1619         if (!sleep_flag_low(FL_DTEN, SLEEP_TIMEOUT))
1620                 return -EIO;
1621
1622         fetch_data(optcd_disk->private_data, blocksize);
1623
1624         if (copy_to_user(arg, optcd_disk->private_data, blocksize))
1625                 return -EFAULT;
1626
1627         return 0;
1628 }
1629
1630
1631 static int cdromseek(void __user *arg)
1632 {
1633         int status;
1634         struct cdrom_msf msf;
1635
1636         if (copy_from_user(&msf, arg, sizeof msf))
1637                 return -EFAULT;
1638
1639         bin2bcd(&msf);
1640         status = exec_seek_cmd(COMSEEK, &msf);
1641
1642         DEBUG((DEBUG_VFS, "COMSEEK status 0x%x", status));
1643
1644         if (status < 0)
1645                 return -EIO;
1646         return 0;
1647 }
1648
1649
1650 #ifdef MULTISESSION
1651 static int cdrommultisession(void __user *arg)
1652 {
1653         struct cdrom_multisession ms;
1654
1655         if (copy_from_user(&ms, arg, sizeof ms))
1656                 return -EFAULT;
1657
1658         ms.addr.msf.minute = disk_info.last_session.minute;
1659         ms.addr.msf.second = disk_info.last_session.second;
1660         ms.addr.msf.frame = disk_info.last_session.frame;
1661
1662         if (ms.addr_format != CDROM_LBA
1663            && ms.addr_format != CDROM_MSF)
1664                 return -EINVAL;
1665         if (ms.addr_format == CDROM_LBA)
1666                 msf2lba(&ms.addr);
1667
1668         ms.xa_flag = disk_info.xa;
1669
1670         if (copy_to_user(arg, &ms, sizeof(struct cdrom_multisession)))
1671                 return -EFAULT;
1672
1673 #if DEBUG_MULTIS
1674         if (ms.addr_format == CDROM_MSF)
1675                 printk(KERN_DEBUG
1676                         "optcd: multisession xa:%d, msf:%02d:%02d.%02d\n",
1677                         ms.xa_flag,
1678                         ms.addr.msf.minute,
1679                         ms.addr.msf.second,
1680                         ms.addr.msf.frame);
1681         else
1682                 printk(KERN_DEBUG
1683                     "optcd: multisession %d, lba:0x%08x [%02d:%02d.%02d])\n",
1684                         ms.xa_flag,
1685                         ms.addr.lba,
1686                         disk_info.last_session.minute,
1687                         disk_info.last_session.second,
1688                         disk_info.last_session.frame);
1689 #endif /* DEBUG_MULTIS */
1690
1691         return 0;
1692 }
1693 #endif /* MULTISESSION */
1694
1695
1696 static int cdromreset(void)
1697 {
1698         if (state != S_IDLE) {
1699                 error = 1;
1700                 tries = 0;
1701         }
1702
1703         toc_uptodate = 0;
1704         disk_changed = 1;
1705         opt_invalidate_buffers();
1706         audio_status = CDROM_AUDIO_NO_STATUS;
1707
1708         if (!reset_drive())
1709                 return -EIO;
1710         return 0;
1711 }
1712 \f
1713 /* VFS calls */
1714
1715
1716 static int opt_ioctl(struct inode *ip, struct file *fp,
1717                      unsigned int cmd, unsigned long arg)
1718 {
1719         int status, err, retval = 0;
1720         void __user *argp = (void __user *)arg;
1721
1722         DEBUG((DEBUG_VFS, "starting opt_ioctl"));
1723
1724         if (!ip)
1725                 return -EINVAL;
1726
1727         if (cmd == CDROMRESET)
1728                 return cdromreset();
1729
1730         /* is do_optcd_request or another ioctl busy? */
1731         if (state != S_IDLE || in_vfs)
1732                 return -EBUSY;
1733
1734         in_vfs = 1;
1735
1736         status = drive_status();
1737         if (status < 0) {
1738                 DEBUG((DEBUG_VFS, "drive_status: %02x", -status));
1739                 in_vfs = 0;
1740                 return -EIO;
1741         }
1742
1743         if (status & ST_DOOR_OPEN)
1744                 switch (cmd) {  /* Actions that can be taken with door open */
1745                 case CDROMCLOSETRAY:
1746                         /* We do this before trying to read the toc. */
1747                         err = exec_cmd(COMCLOSE);
1748                         if (err < 0) {
1749                                 DEBUG((DEBUG_VFS,
1750                                        "exec_cmd COMCLOSE: %02x", -err));
1751                                 in_vfs = 0;
1752                                 return -EIO;
1753                         }
1754                         break;
1755                 default:        in_vfs = 0;
1756                                 return -EBUSY;
1757                 }
1758
1759         err = update_toc();
1760         if (err < 0) {
1761                 DEBUG((DEBUG_VFS, "update_toc: %02x", -err));
1762                 in_vfs = 0;
1763                 return -EIO;
1764         }
1765
1766         DEBUG((DEBUG_VFS, "ioctl cmd 0x%x", cmd));
1767
1768         switch (cmd) {
1769         case CDROMPAUSE:        retval = cdrompause(); break;
1770         case CDROMRESUME:       retval = cdromresume(); break;
1771         case CDROMPLAYMSF:      retval = cdromplaymsf(argp); break;
1772         case CDROMPLAYTRKIND:   retval = cdromplaytrkind(argp); break;
1773         case CDROMREADTOCHDR:   retval = cdromreadtochdr(argp); break;
1774         case CDROMREADTOCENTRY: retval = cdromreadtocentry(argp); break;
1775
1776         case CDROMSTOP:         err = exec_cmd(COMSTOP);
1777                                 if (err < 0) {
1778                                         DEBUG((DEBUG_VFS,
1779                                                 "exec_cmd COMSTOP: %02x",
1780                                                 -err));
1781                                         retval = -EIO;
1782                                 } else
1783                                         audio_status = CDROM_AUDIO_NO_STATUS;
1784                                 break;
1785         case CDROMSTART:        break;  /* This is a no-op */
1786         case CDROMEJECT:        err = exec_cmd(COMUNLOCK);
1787                                 if (err < 0) {
1788                                         DEBUG((DEBUG_VFS,
1789                                                 "exec_cmd COMUNLOCK: %02x",
1790                                                 -err));
1791                                         retval = -EIO;
1792                                         break;
1793                                 }
1794                                 err = exec_cmd(COMOPEN);
1795                                 if (err < 0) {
1796                                         DEBUG((DEBUG_VFS,
1797                                                 "exec_cmd COMOPEN: %02x",
1798                                                 -err));
1799                                         retval = -EIO;
1800                                 }
1801                                 break;
1802
1803         case CDROMVOLCTRL:      retval = cdromvolctrl(argp); break;
1804         case CDROMSUBCHNL:      retval = cdromsubchnl(argp); break;
1805
1806         /* The drive detects the mode and automatically delivers the
1807            correct 2048 bytes, so we don't need these IOCTLs */
1808         case CDROMREADMODE2:    retval = -EINVAL; break;
1809         case CDROMREADMODE1:    retval = -EINVAL; break;
1810
1811         /* Drive doesn't support reading audio */
1812         case CDROMREADAUDIO:    retval = -EINVAL; break;
1813
1814         case CDROMEJECT_SW:     auto_eject = (char) arg;
1815                                 break;
1816
1817 #ifdef MULTISESSION
1818         case CDROMMULTISESSION: retval = cdrommultisession(argp); break;
1819 #endif
1820
1821         case CDROM_GET_MCN:     retval = -EINVAL; break; /* not implemented */
1822         case CDROMVOLREAD:      retval = -EINVAL; break; /* not implemented */
1823
1824         case CDROMREADRAW:
1825                         /* this drive delivers 2340 bytes in raw mode */
1826                         retval = cdromread(argp, CD_FRAMESIZE_RAW1, COMREADRAW);
1827                         break;
1828         case CDROMREADCOOKED:
1829                         retval = cdromread(argp, CD_FRAMESIZE, COMREAD);
1830                         break;
1831         case CDROMREADALL:
1832                         retval = cdromread(argp, CD_FRAMESIZE_RAWER, COMREADALL);
1833                         break;
1834
1835         case CDROMSEEK:         retval = cdromseek(argp); break;
1836         case CDROMPLAYBLK:      retval = -EINVAL; break; /* not implemented */
1837         case CDROMCLOSETRAY:    break;  /* The action was taken earlier */
1838         default:                retval = -EINVAL;
1839         }
1840         in_vfs = 0;
1841         return retval;
1842 }
1843
1844
1845 static int open_count = 0;
1846
1847 /* Open device special file; check that a disk is in. */
1848 static int opt_open(struct inode *ip, struct file *fp)
1849 {
1850         DEBUG((DEBUG_VFS, "starting opt_open"));
1851
1852         if (!open_count && state == S_IDLE) {
1853                 int status;
1854                 char *buf;
1855
1856                 buf = kmalloc(CD_FRAMESIZE_RAWER, GFP_KERNEL);
1857                 if (!buf) {
1858                         printk(KERN_INFO "optcd: cannot allocate read buffer\n");
1859                         return -ENOMEM;
1860                 }
1861                 optcd_disk->private_data = buf;         /* save read buffer */
1862
1863                 toc_uptodate = 0;
1864                 opt_invalidate_buffers();
1865
1866                 status = exec_cmd(COMCLOSE);    /* close door */
1867                 if (status < 0) {
1868                         DEBUG((DEBUG_VFS, "exec_cmd COMCLOSE: %02x", -status));
1869                 }
1870
1871                 status = drive_status();
1872                 if (status < 0) {
1873                         DEBUG((DEBUG_VFS, "drive_status: %02x", -status));
1874                         goto err_out;
1875                 }
1876                 DEBUG((DEBUG_VFS, "status: %02x", status));
1877                 if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) {
1878                         printk(KERN_INFO "optcd: no disk or door open\n");
1879                         goto err_out;
1880                 }
1881                 status = exec_cmd(COMLOCK);             /* Lock door */
1882                 if (status < 0) {
1883                         DEBUG((DEBUG_VFS, "exec_cmd COMLOCK: %02x", -status));
1884                 }
1885                 status = update_toc();  /* Read table of contents */
1886                 if (status < 0) {
1887                         DEBUG((DEBUG_VFS, "update_toc: %02x", -status));
1888                         status = exec_cmd(COMUNLOCK);   /* Unlock door */
1889                         if (status < 0) {
1890                                 DEBUG((DEBUG_VFS,
1891                                        "exec_cmd COMUNLOCK: %02x", -status));
1892                         }
1893                         goto err_out;
1894                 }
1895                 open_count++;
1896         }
1897
1898         DEBUG((DEBUG_VFS, "exiting opt_open"));
1899
1900         return 0;
1901
1902 err_out:
1903         return -EIO;
1904 }
1905
1906
1907 /* Release device special file; flush all blocks from the buffer cache */
1908 static int opt_release(struct inode *ip, struct file *fp)
1909 {
1910         int status;
1911
1912         DEBUG((DEBUG_VFS, "executing opt_release"));
1913         DEBUG((DEBUG_VFS, "inode: %p, device: %s, file: %p\n",
1914                 ip, ip->i_bdev->bd_disk->disk_name, fp));
1915
1916         if (!--open_count) {
1917                 toc_uptodate = 0;
1918                 opt_invalidate_buffers();
1919                 status = exec_cmd(COMUNLOCK);   /* Unlock door */
1920                 if (status < 0) {
1921                         DEBUG((DEBUG_VFS, "exec_cmd COMUNLOCK: %02x", -status));
1922                 }
1923                 if (auto_eject) {
1924                         status = exec_cmd(COMOPEN);
1925                         DEBUG((DEBUG_VFS, "exec_cmd COMOPEN: %02x", -status));
1926                 }
1927                 kfree(optcd_disk->private_data);
1928                 del_timer(&delay_timer);
1929                 del_timer(&req_timer);
1930         }
1931         return 0;
1932 }
1933
1934
1935 /* Check if disk has been changed */
1936 static int opt_media_change(struct gendisk *disk)
1937 {
1938         DEBUG((DEBUG_VFS, "executing opt_media_change"));
1939         DEBUG((DEBUG_VFS, "dev: %s; disk_changed = %d\n",
1940                         disk->disk_name, disk_changed));
1941
1942         if (disk_changed) {
1943                 disk_changed = 0;
1944                 return 1;
1945         }
1946         return 0;
1947 }
1948 \f
1949 /* Driver initialisation */
1950
1951
1952 /* Returns 1 if a drive is detected with a version string
1953    starting with "DOLPHIN". Otherwise 0. */
1954 static int __init version_ok(void)
1955 {
1956         char devname[100];
1957         int count, i, ch, status;
1958
1959         status = exec_cmd(COMVERSION);
1960         if (status < 0) {
1961                 DEBUG((DEBUG_VFS, "exec_cmd COMVERSION: %02x", -status));
1962                 return 0;
1963         }
1964         if ((count = get_data(1)) < 0) {
1965                 DEBUG((DEBUG_VFS, "get_data(1): %02x", -count));
1966                 return 0;
1967         }
1968         for (i = 0, ch = -1; count > 0; count--) {
1969                 if ((ch = get_data(1)) < 0) {
1970                         DEBUG((DEBUG_VFS, "get_data(1): %02x", -ch));
1971                         break;
1972                 }
1973                 if (i < 99)
1974                         devname[i++] = ch;
1975         }
1976         devname[i] = '\0';
1977         if (ch < 0)
1978                 return 0;
1979
1980         printk(KERN_INFO "optcd: Device %s detected\n", devname);
1981         return ((devname[0] == 'D')
1982              && (devname[1] == 'O')
1983              && (devname[2] == 'L')
1984              && (devname[3] == 'P')
1985              && (devname[4] == 'H')
1986              && (devname[5] == 'I')
1987              && (devname[6] == 'N'));
1988 }
1989
1990
1991 static struct block_device_operations opt_fops = {
1992         .owner          = THIS_MODULE,
1993         .open           = opt_open,
1994         .release        = opt_release,
1995         .ioctl          = opt_ioctl,
1996         .media_changed  = opt_media_change,
1997 };
1998
1999 #ifndef MODULE
2000 /* Get kernel parameter when used as a kernel driver */
2001 static int optcd_setup(char *str)
2002 {
2003         int ints[4];
2004         (void)get_options(str, ARRAY_SIZE(ints), ints);
2005         
2006         if (ints[0] > 0)
2007                 optcd_port = ints[1];
2008
2009         return 1;
2010 }
2011
2012 __setup("optcd=", optcd_setup);
2013
2014 #endif /* MODULE */
2015
2016 /* Test for presence of drive and initialize it. Called at boot time
2017    or during module initialisation. */
2018 static int __init optcd_init(void)
2019 {
2020         int status;
2021
2022         if (optcd_port <= 0) {
2023                 printk(KERN_INFO
2024                         "optcd: no Optics Storage CDROM Initialization\n");
2025                 return -EIO;
2026         }
2027         optcd_disk = alloc_disk(1);
2028         if (!optcd_disk) {
2029                 printk(KERN_ERR "optcd: can't allocate disk\n");
2030                 return -ENOMEM;
2031         }
2032         optcd_disk->major = MAJOR_NR;
2033         optcd_disk->first_minor = 0;
2034         optcd_disk->fops = &opt_fops;
2035         sprintf(optcd_disk->disk_name, "optcd");
2036         sprintf(optcd_disk->devfs_name, "optcd");
2037
2038         if (!request_region(optcd_port, 4, "optcd")) {
2039                 printk(KERN_ERR "optcd: conflict, I/O port 0x%x already used\n",
2040                         optcd_port);
2041                 put_disk(optcd_disk);
2042                 return -EIO;
2043         }
2044
2045         if (!reset_drive()) {
2046                 printk(KERN_ERR "optcd: drive at 0x%x not ready\n", optcd_port);
2047                 release_region(optcd_port, 4);
2048                 put_disk(optcd_disk);
2049                 return -EIO;
2050         }
2051         if (!version_ok()) {
2052                 printk(KERN_ERR "optcd: unknown drive detected; aborting\n");
2053                 release_region(optcd_port, 4);
2054                 put_disk(optcd_disk);
2055                 return -EIO;
2056         }
2057         status = exec_cmd(COMINITDOUBLE);
2058         if (status < 0) {
2059                 printk(KERN_ERR "optcd: cannot init double speed mode\n");
2060                 release_region(optcd_port, 4);
2061                 DEBUG((DEBUG_VFS, "exec_cmd COMINITDOUBLE: %02x", -status));
2062                 put_disk(optcd_disk);
2063                 return -EIO;
2064         }
2065         if (register_blkdev(MAJOR_NR, "optcd")) {
2066                 release_region(optcd_port, 4);
2067                 put_disk(optcd_disk);
2068                 return -EIO;
2069         }
2070
2071
2072         opt_queue = blk_init_queue(do_optcd_request, &optcd_lock);
2073         if (!opt_queue) {
2074                 unregister_blkdev(MAJOR_NR, "optcd");
2075                 release_region(optcd_port, 4);
2076                 put_disk(optcd_disk);
2077                 return -ENOMEM;
2078         }
2079
2080         blk_queue_hardsect_size(opt_queue, 2048);
2081         optcd_disk->queue = opt_queue;
2082         add_disk(optcd_disk);
2083
2084         printk(KERN_INFO "optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port);
2085         return 0;
2086 }
2087
2088
2089 static void __exit optcd_exit(void)
2090 {
2091         del_gendisk(optcd_disk);
2092         put_disk(optcd_disk);
2093         if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) {
2094                 printk(KERN_ERR "optcd: what's that: can't unregister\n");
2095                 return;
2096         }
2097         blk_cleanup_queue(opt_queue);
2098         release_region(optcd_port, 4);
2099         printk(KERN_INFO "optcd: module released.\n");
2100 }
2101
2102 module_init(optcd_init);
2103 module_exit(optcd_exit);
2104
2105 MODULE_LICENSE("GPL");
2106 MODULE_ALIAS_BLOCKDEV_MAJOR(OPTICS_CDROM_MAJOR);