This source file includes following definitions.
- optFlags
- sten_low
- dten_low
- sleep_timer
- sleep_status
- sleep_sten_low
- sleep_dten_low
- optSendCmd
- optSendParams
- optGetExecStatus
- optSleepTillExecStatus
- optStatus
- optGetData
- optReadData
- optFlushData
- optResetDrive
- optCmd
- optPlayCmd
- optReadCmd
- bin2bcd
- hsg2msf
- bcd2bin
- msf2hsg
- optGetStatus
- optGetQChannelInfo
- optGetDiskInfo
- optGetToc
- optUpdateToc
- opt_invalidate_buffers
- opt_transfer
- opt_poll
- do_optcd_request
- opt_ioctl
- opt_open
- opt_release
- version_ok
- optcd_setup
- optcd_init
- init_module
- cleanup_module
- isp16_detect
- isp16_no_ide__detect
- isp16_with_ide__detect
- isp16_config
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 #include <linux/major.h>
52 #include <linux/config.h>
53
54 #ifdef MODULE
55 # include <linux/module.h>
56 # include <linux/version.h>
57 # ifndef CONFIG_MODVERSIONS
58 char kernel_version[]= UTS_RELEASE;
59 # endif
60 #else
61 # define MOD_INC_USE_COUNT
62 # define MOD_DEC_USE_COUNT
63 #endif
64
65 #include <linux/errno.h>
66 #include <linux/mm.h>
67 #include <linux/fs.h>
68 #include <linux/timer.h>
69 #include <linux/kernel.h>
70 #include <linux/cdrom.h>
71 #include <linux/ioport.h>
72 #include <asm/io.h>
73
74 #define MAJOR_NR OPTICS_CDROM_MAJOR
75
76 # include "blk.h"
77 #define optcd_port optcd
78 # include <linux/optcd.h>
79
80
81
82
83 #define ISP16_DRIVE_X 0x00
84 #define ISP16_SONY 0x02
85 #define ISP16_PANASONIC0 0x02
86 #define ISP16_SANYO0 0x02
87 #define ISP16_MITSUMI 0x04
88 #define ISP16_PANASONIC1 0x06
89 #define ISP16_SANYO1 0x06
90 #define ISP16_DRIVE_NOT_USED 0x08
91 #define ISP16_DRIVE_SET_MASK 0xF1
92
93 #define ISP16_DRIVE_SET_PORT 0xF8D
94
95 #define ISP16_BASE_340 0x00
96 #define ISP16_BASE_330 0x40
97 #define ISP16_BASE_360 0x80
98 #define ISP16_BASE_320 0xC0
99 #define ISP16_IRQ_X 0x00
100 #define ISP16_IRQ_5 0x04
101 #define ISP16_IRQ_7 0x08
102 #define ISP16_IRQ_3 0x0C
103 #define ISP16_IRQ_9 0x10
104 #define ISP16_IRQ_10 0x14
105 #define ISP16_IRQ_11 0x18
106 #define ISP16_DMA_X 0x03
107 #define ISP16_DMA_3 0x00
108 #define ISP16_DMA_5 0x00
109 #define ISP16_DMA_6 0x01
110 #define ISP16_DMA_7 0x02
111 #define ISP16_IO_SET_MASK 0x20
112
113 #define ISP16_IO_SET_PORT 0xF8E
114
115 #define ISP16_NO_IDE__ENABLE_CDROM_PORT 0xF90
116 #define ISP16_IDE__ENABLE_CDROM_PORT 0xF91
117 #define ISP16_ENABLE_CDROM 0x80
118
119
120 #define ISP16_CTRL_PORT 0xF8F
121 #define ISP16_NO_IDE__CTRL 0xE2
122 #define ISP16_IDE__CTRL 0xE3
123
124 static short isp16_detect(void);
125 static short isp16_no_ide__detect(void);
126 static short isp16_with_ide__detect(void);
127 static short isp16_config( int base, u_char drive_type, int irq, int dma );
128 static short isp16_type;
129 static u_char isp16_ctrl;
130 static u_short isp16_enable_cdrom_port;
131
132
133 static short optcd_port = OPTCD_PORTBASE;
134
135
136 inline static int optFlags(void) {
137 return inb(STATUS_PORT) & FL_STDT;
138 }
139
140
141 static int sten_low(void) {
142 int no_status;
143 unsigned long count = 0;
144 while ((no_status = (optFlags() & FL_STEN)))
145 if (++count >= BUSY_TIMEOUT)
146 break;
147 #ifdef DEBUG_DRIVE_IF
148 if (no_status)
149 printk("optcd: timeout waiting for STEN low\n");
150 else
151 printk("optcd: STEN low after %ld\n", count);
152 #endif
153 return no_status;
154 }
155
156
157 static int dten_low(void) {
158 int no_data;
159 unsigned long count = 0;
160 while ((no_data = (optFlags() & FL_DTEN)))
161 if (++count >= BUSY_TIMEOUT)
162 break;
163 #ifdef DEBUG_DRIVE_IF
164 if (no_data)
165 printk("optcd: timeout waiting for DTEN low\n");
166 else
167 printk("optcd: DTEN low after %ld\n", count);
168 #endif
169 return no_data;
170 }
171
172
173 static int sleep_timeout;
174 static unsigned char sleep_flags;
175 static struct wait_queue *waitq = NULL;
176 static struct timer_list delay_timer = {NULL, NULL, 0, 0, NULL};
177
178
179
180
181 static void sleep_timer(void) {
182 if ((sleep_flags = optFlags()) != FL_STDT) {
183 wake_up(&waitq);
184 return;
185 }
186 if (--sleep_timeout <= 0) {
187 wake_up(&waitq);
188 return;
189 }
190 SET_TIMER(sleep_timer, 1);
191 }
192
193
194
195
196 static int sleep_status(void) {
197 #ifdef DEBUG_DRIVE_IF
198 printk("optcd: sleeping %d on status\n", sleep_timeout);
199 #endif
200 if (sleep_timeout <= 0)
201 return FL_STDT;
202 if ((sleep_flags = optFlags()) == FL_STDT) {
203 SET_TIMER(sleep_timer, 1);
204 sleep_on(&waitq);
205 }
206 #ifdef DEBUG_DRIVE_IF
207 printk("optcd: woken up with %d to go, flags %d\n",
208 sleep_timeout, sleep_flags);
209 #endif
210 return sleep_flags;
211 }
212
213
214 inline static int sleep_sten_low(void) {
215 int flags;
216 sleep_timeout = SLEEP_TIMEOUT;
217 flags = sleep_status();
218 #ifdef DEBUG_DRIVE_IF
219 if (!(flags & FL_DTEN))
220 printk("optcd: DTEN while waiting for STEN\n");
221 #endif
222 return flags & FL_STEN;
223 }
224
225
226 inline static int sleep_dten_low(void) {
227 int flags;
228 sleep_timeout = SLEEP_TIMEOUT;
229 flags = sleep_status();
230 #ifdef DEBUG_DRIVE_IF
231 if (!(flags & FL_STEN))
232 printk("optcd: STEN while waiting for DTEN\n");
233 #endif
234 return flags & FL_DTEN;
235 }
236
237
238 static int optSendCmd(int cmd) {
239 unsigned char ack;
240 #if defined(DEBUG_DRIVE_IF)||defined(DEBUG_COMMANDS)
241 printk("optcd: executing command 0x%02x\n", cmd);
242 #endif
243 outb(HCON_DTS, HCON_PORT);
244 outb(cmd, COMIN_PORT);
245 if (sten_low())
246 return -ERR_IF_CMD_TIMEOUT;
247 ack = inb(DATA_PORT);
248 #ifdef DEBUG_DRIVE_IF
249 printk("optcd: acknowledge code 0x%02x\n", ack);
250 #endif
251 outb(HCON_SDRQB, HCON_PORT);
252 return ack==ST_OP_OK ? 0 : -ack;
253 }
254
255
256 static int optSendParams(struct opt_Play_msf *params) {
257 unsigned char ack;
258 #if defined(DEBUG_DRIVE_IF)||defined(DEBUG_COMMANDS)
259 printk("optcd: params %02x:%02x:%02x %02x:%02x:%02x\n",
260 params->start.min, params->start.sec, params->start.frame,
261 params->end.min, params->end.sec, params->end.frame);
262 #endif
263 outb(params -> start.min, COMIN_PORT);
264 outb(params -> start.sec, COMIN_PORT);
265 outb(params -> start.frame, COMIN_PORT);
266 outb(params -> end.min, COMIN_PORT);
267 outb(params -> end.sec, COMIN_PORT);
268 outb(params -> end.frame, COMIN_PORT);
269 if (sten_low())
270 return -ERR_IF_CMD_TIMEOUT;
271 ack = inb(DATA_PORT);
272 #ifdef DEBUG_DRIVE_IF
273 printk("optcd: acknowledge code 0x%02x\n", ack);
274 #endif
275 return ack==ST_PA_OK ? 0 : -ack;
276 }
277
278
279
280
281 static int optGetExecStatus(void) {
282 unsigned char exec_status;
283 if (sten_low())
284 return -ERR_IF_CMD_TIMEOUT;
285 exec_status = inb(DATA_PORT);
286 #ifdef DEBUG_DRIVE_IF
287 printk("optcd: returned execution status: 0x%02x\n", exec_status);
288 #endif
289 return exec_status;
290 }
291
292
293
294
295 static int optSleepTillExecStatus(void) {
296 unsigned char exec_status;
297 if (sleep_sten_low())
298 return -ERR_IF_CMD_TIMEOUT;
299 exec_status = inb(DATA_PORT);
300 #ifdef DEBUG_DRIVE_IF
301 printk("optcd: returned execution status: 0x%02x\n", exec_status);
302 #endif
303 return exec_status;
304 }
305
306
307 inline static int optStatus(void) {
308 unsigned char status;
309 if (optFlags() & FL_STEN)
310 return -ERR_IF_NOSTAT;
311 status = inb(DATA_PORT);
312 #ifdef DEBUG_DRIVE_IF
313 printk("optcd: read status: 0x%02x\n", status);
314 #endif
315 return status;
316 }
317
318
319 static int optGetData(void) {
320 unsigned char data;
321 if (sten_low())
322 return -ERR_IF_DATA_TIMEOUT;
323 data = inb(DATA_PORT);
324 #ifdef DEBUG_DRIVE_IF
325 printk("optcd: read data: 0x%02x\n", data);
326 #endif
327 return data;
328 }
329
330
331 inline static void optReadData(char *buf, int n) {
332 insb(DATA_PORT, buf, n);
333 }
334
335
336 inline static void optFlushData(void) {
337 while (optFlags() != FL_STDT)
338 inb(DATA_PORT);
339 }
340
341
342 static int optResetDrive(void) {
343 unsigned long count = 0;
344 int flags;
345 #ifdef DEBUG_DRIVE_IF
346 printk("optcd: reset drive\n");
347 #endif
348 outb(0, RESET_PORT);
349 while (++count < RESET_WAIT)
350 inb(DATA_PORT);
351 count = 0;
352 while ((flags = (inb(STATUS_PORT) & FL_RESET)) != FL_RESET)
353 if (++count >= BUSY_TIMEOUT)
354 break;
355 #ifdef DEBUG_DRIVE_IF
356 if (flags == FL_RESET)
357 printk("optcd: drive reset\n");
358 else
359 printk("optcd: reset failed\n");
360 #endif
361 if (flags != FL_RESET)
362 return 0;
363 outb(HCON_SDRQB, HCON_PORT);
364 return 1;
365 }
366
367
368
369
370
371 inline static int optCmd(int cmd) {
372 int ack = optSendCmd(cmd);
373 if (ack < 0)
374 return ack;
375 if (cmd < COMFETCH)
376 return optGetExecStatus();
377 else
378 return optSleepTillExecStatus();
379 }
380
381
382 inline static int optPlayCmd(int cmd, struct opt_Play_msf *params) {
383 int ack = optSendCmd(cmd);
384 if (ack < 0)
385 return ack;
386 if ((ack = optSendParams(params)) < 0)
387 return ack;
388 return optSleepTillExecStatus();
389 }
390
391
392
393 inline static int optReadCmd(int cmd, struct opt_Play_msf *params) {
394 int ack = optSendCmd(cmd);
395 if (ack < 0)
396 return ack;
397 return optSendParams(params);
398 }
399
400
401
402
403
404 inline static unsigned char bin2bcd(unsigned char p) {
405 #ifdef DEBUG_CONV
406 if (p > 99)
407 printk("optcd: error bin2bcd %d\n", p);
408 #endif
409 return (p % 10) | ((p / 10) << 4);
410 }
411
412
413 static void hsg2msf(long hsg, struct msf *msf) {
414 hsg += 150;
415 msf -> min = hsg / 4500;
416 hsg %= 4500;
417 msf -> sec = hsg / 75;
418 msf -> frame = hsg % 75;
419 #ifdef DEBUG_CONV
420 if (msf -> min >= 70)
421 printk("optcd: Error hsg2msf address Minutes\n");
422 if (msf -> sec >= 60)
423 printk("optcd: Error hsg2msf address Seconds\n");
424 if (msf -> frame >= 75)
425 printk("optcd: Error hsg2msf address Frames\n");
426 #endif
427 msf -> min = bin2bcd(msf -> min);
428 msf -> sec = bin2bcd(msf -> sec);
429 msf -> frame = bin2bcd(msf -> frame);
430 }
431
432
433 inline static int bcd2bin(unsigned char bcd) {
434 return (bcd >> 4) * 10 + (bcd & 0x0f);
435 }
436
437
438 static long msf2hsg(struct msf *mp) {
439 #ifdef DEBUG_CONV
440 if (mp -> min >= 70)
441 printk("optcd: Error msf2hsg address Minutes\n");
442 if (mp -> sec >= 60)
443 printk("optcd: Error msf2hsg address Seconds\n");
444 if (mp -> frame >= 75)
445 printk("optcd: Error msf2hsg address Frames\n");
446 #endif
447 return bcd2bin(mp -> frame)
448 + bcd2bin(mp -> sec) * 75
449 + bcd2bin(mp -> min) * 4500
450 - 150;
451 }
452
453
454
455
456 static int optAudioStatus = CDROM_AUDIO_NO_STATUS;
457 static char optDiskChanged = 1;
458 static char optTocUpToDate = 0;
459 static struct opt_DiskInfo DiskInfo;
460 static struct opt_Toc Toc[MAX_TRACKS];
461
462
463 static int optGetStatus(void) {
464 int st;
465 if ((st = optCmd(COMIOCTLISTAT)) < 0)
466 return st;
467 if (st == 0xff)
468 return -ERR_IF_NOSTAT;
469 if (((st & ST_MODE_BITS) != ST_M_AUDIO) &&
470 (optAudioStatus == CDROM_AUDIO_PLAY)) {
471 optAudioStatus = CDROM_AUDIO_COMPLETED;
472 }
473 if (st & ST_DSK_CHG) {
474 optDiskChanged = 1;
475 optTocUpToDate = 0;
476 optAudioStatus = CDROM_AUDIO_NO_STATUS;
477 }
478 return st;
479 }
480
481
482
483
484
485 static int optGetQChannelInfo(struct opt_Toc *qp) {
486 int st;
487 #ifdef DEBUG_TOC
488 printk("optcd: starting optGetQChannelInfo\n");
489 #endif
490 if ((st = optGetStatus()) < 0)
491 return st;
492 if ((st = optCmd(COMSUBQ)) < 0)
493 return st;
494 if ((qp -> ctrl_addr = st = optGetData()), st < 0) return st;
495 if ((qp -> track = st = optGetData()), st < 0) return st;
496 if ((qp -> pointIndex = st = optGetData()), st < 0) return st;
497 if ((qp -> trackTime.min = st = optGetData()), st < 0) return st;
498 if ((qp -> trackTime.sec = st = optGetData()), st < 0) return st;
499 if ((qp -> trackTime.frame = st = optGetData()), st < 0) return st;
500 if ((st = optGetData()) < 0) return st;
501 if ((qp -> diskTime.min = st = optGetData()), st < 0) return st;
502 if ((qp -> diskTime.sec = st = optGetData()), st < 0) return st;
503 if ((qp -> diskTime.frame = st = optGetData()), st < 0) return st;
504 #ifdef DEBUG_TOC
505 printk("optcd: exiting optGetQChannelInfo\n");
506 #endif
507 return 0;
508 }
509
510 #define QINFO_FIRSTTRACK 0xa0
511 #define QINFO_LASTTRACK 0xa1
512 #define QINFO_DISKLENGTH 0xa2
513
514 static int optGetDiskInfo(void) {
515 int st, limit;
516 unsigned char test = 0;
517 struct opt_Toc qInfo;
518 #ifdef DEBUG_TOC
519 printk("optcd: starting optGetDiskInfo\n");
520 #endif
521 optDiskChanged = 0;
522 if ((st = optCmd(COMLEADIN)) < 0)
523 return st;
524 for (limit = 300; (limit > 0) && (test != 0x0f); limit--) {
525 if ((st = optGetQChannelInfo(&qInfo)) < 0)
526 return st;
527 switch (qInfo.pointIndex) {
528 case QINFO_FIRSTTRACK:
529 DiskInfo.first = bcd2bin(qInfo.diskTime.min);
530 #ifdef DEBUG_TOC
531 printk("optcd: got first: %d\n", DiskInfo.first);
532 #endif
533 test |= 0x01;
534 break;
535 case QINFO_LASTTRACK:
536 DiskInfo.last = bcd2bin(qInfo.diskTime.min);
537 #ifdef DEBUG_TOC
538 printk("optcd: got last: %d\n", DiskInfo.last);
539 #endif
540 test |= 0x02;
541 break;
542 case QINFO_DISKLENGTH:
543 DiskInfo.diskLength.min = qInfo.diskTime.min;
544 DiskInfo.diskLength.sec = qInfo.diskTime.sec-2;
545 DiskInfo.diskLength.frame = qInfo.diskTime.frame;
546 #ifdef DEBUG_TOC
547 printk("optcd: got length: %x:%x.%x\n",
548 DiskInfo.diskLength.min,
549 DiskInfo.diskLength.sec,
550 DiskInfo.diskLength.frame);
551 #endif
552 test |= 0x04;
553 break;
554 default:
555 if ((test & 0x01)
556 && (qInfo.pointIndex == DiskInfo.first)) {
557
558 DiskInfo.firstTrack.min = qInfo.diskTime.min;
559 DiskInfo.firstTrack.sec = qInfo.diskTime.sec;
560 DiskInfo.firstTrack.frame = qInfo.diskTime.frame;
561 #ifdef DEBUG_TOC
562 printk("optcd: got start: %x:%x.%x\n",
563 DiskInfo.firstTrack.min,
564 DiskInfo.firstTrack.sec,
565 DiskInfo.firstTrack.frame);
566 #endif
567 test |= 0x08;
568 }
569 }
570 }
571 #ifdef DEBUG_TOC
572 printk("optcd: exiting optGetDiskInfo\n");
573 #endif
574 if (test != 0x0f)
575 return -ERR_TOC_MISSINGINFO;
576 return 0;
577 }
578
579 static int optGetToc(void) {
580 int st, count, px, limit;
581 struct opt_Toc qInfo;
582 #ifdef DEBUG_TOC
583 int i;
584 printk("optcd: starting optGetToc\n");
585 #endif
586 for (count = 0; count < MAX_TRACKS; count++)
587 Toc[count].pointIndex = 0;
588 if ((st = optCmd(COMLEADIN)) < 0)
589 return st;
590 st = 0;
591 count = DiskInfo.last + 3;
592 for (limit = 300; (limit > 0) && (count > 0); limit--) {
593 if ((st = optGetQChannelInfo(&qInfo)) < 0)
594 break;
595 px = bcd2bin(qInfo.pointIndex);
596 if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
597 if (Toc[px].pointIndex == 0) {
598 Toc[px] = qInfo;
599 count--;
600 }
601 }
602 Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
603 #ifdef DEBUG_TOC
604 printk("optcd: exiting optGetToc\n");
605 for (i = 1; i <= DiskInfo.last + 1; i++)
606 printk("i = %3d ctl-adr = %02x track %2d px "
607 "%02x %02x:%02x.%02x %02x:%02x.%02x\n",
608 i, Toc[i].ctrl_addr,
609 Toc[i].track,
610 Toc[i].pointIndex,
611 Toc[i].trackTime.min,
612 Toc[i].trackTime.sec,
613 Toc[i].trackTime.frame,
614 Toc[i].diskTime.min,
615 Toc[i].diskTime.sec,
616 Toc[i].diskTime.frame);
617 for (i = 100; i < 103; i++)
618 printk("i = %3d ctl-adr = %02x track %2d px "
619 "%02x %02x:%02x.%02x %02x:%02x.%02x\n",
620 i, Toc[i].ctrl_addr,
621 Toc[i].track,
622 Toc[i].pointIndex,
623 Toc[i].trackTime.min,
624 Toc[i].trackTime.sec,
625 Toc[i].trackTime.frame,
626 Toc[i].diskTime.min,
627 Toc[i].diskTime.sec,
628 Toc[i].diskTime.frame);
629 #endif
630 return count ? -ERR_TOC_MISSINGENTRY : 0;
631 }
632
633 static int optUpdateToc(void) {
634 #ifdef DEBUG_TOC
635 printk("optcd: starting optUpdateToc\n");
636 #endif
637 if (optTocUpToDate)
638 return 0;
639 if (optGetDiskInfo() < 0)
640 return -EIO;
641 if (optGetToc() < 0)
642 return -EIO;
643 optTocUpToDate = 1;
644 #ifdef DEBUG_TOC
645 printk("optcd: exiting optUpdateToc\n");
646 #endif
647 return 0;
648 }
649
650
651
652
653 #define OPT_BUF_SIZ 16
654 #define OPT_BLOCKSIZE 2048
655 #define OPT_BLOCKSIZE_RAW 2336
656 #define OPT_BLOCKSIZE_ALL 2646
657 #define OPT_NOBUF -1
658
659
660 static char opt_buf[OPT_BLOCKSIZE*OPT_BUF_SIZ];
661 static volatile int opt_buf_bn[OPT_BUF_SIZ], opt_next_bn;
662 static volatile int opt_buf_in = 0, opt_buf_out = OPT_NOBUF;
663
664 inline static void opt_invalidate_buffers(void) {
665 int i;
666 #ifdef DEBUG_BUFFERS
667 printk("optcd: executing opt_invalidate_buffers\n");
668 #endif
669 for (i = 0; i < OPT_BUF_SIZ; i++)
670 opt_buf_bn[i] = OPT_NOBUF;
671 opt_buf_out = OPT_NOBUF;
672 }
673
674
675
676
677
678 static void opt_transfer(void) {
679 #if (defined DEBUG_BUFFERS) || (defined DEBUG_REQUEST)
680 printk("optcd: executing opt_transfer\n");
681 #endif
682 if (!CURRENT_VALID)
683 return;
684 while (CURRENT -> nr_sectors) {
685 int bn = CURRENT -> sector / 4;
686 int i, offs, nr_sectors;
687 for (i = 0; i < OPT_BUF_SIZ && opt_buf_bn[i] != bn; ++i);
688 #ifdef DEBUG_REQUEST
689 printk("optcd: found %d\n", i);
690 #endif
691 if (i >= OPT_BUF_SIZ) {
692 opt_buf_out = OPT_NOBUF;
693 break;
694 }
695 offs = (i * 4 + (CURRENT -> sector & 3)) * 512;
696 nr_sectors = 4 - (CURRENT -> sector & 3);
697 if (opt_buf_out != i) {
698 opt_buf_out = i;
699 if (opt_buf_bn[i] != bn) {
700 opt_buf_out = OPT_NOBUF;
701 continue;
702 }
703 }
704 if (nr_sectors > CURRENT -> nr_sectors)
705 nr_sectors = CURRENT -> nr_sectors;
706 memcpy(CURRENT -> buffer, opt_buf + offs, nr_sectors * 512);
707 CURRENT -> nr_sectors -= nr_sectors;
708 CURRENT -> sector += nr_sectors;
709 CURRENT -> buffer += nr_sectors * 512;
710 }
711 }
712
713
714
715
716 enum opt_state_e {
717 OPT_S_IDLE,
718 OPT_S_START,
719 OPT_S_READ,
720 OPT_S_DATA,
721 OPT_S_STOP,
722 OPT_S_STOPPING
723 };
724
725 static volatile enum opt_state_e opt_state = OPT_S_IDLE;
726 #ifdef DEBUG_STATE
727 static volatile enum opt_state_e opt_state_old = OPT_S_STOP;
728 static volatile int opt_st_old = 0;
729 static volatile long opt_state_n = 0;
730 #endif
731
732 static volatile int opt_transfer_is_active = 0;
733 static volatile int opt_error = 0;
734 static int optTries;
735
736 static void opt_poll(void) {
737 static int optTimeout;
738 static volatile int opt_read_count = 1;
739 int st = 0;
740 int loop_ctl = 1;
741 int skip = 0;
742
743 if (opt_error) {
744 printk("optcd: I/O error 0x%02x\n", opt_error);
745 opt_invalidate_buffers();
746 #ifdef WARN_IF_READ_FAILURE
747 if (optTries == 5)
748 printk("optcd: read block %d failed; audio disk?\n",
749 opt_next_bn);
750 #endif
751 if (!optTries--) {
752 printk("optcd: read block %d failed; Giving up\n",
753 opt_next_bn);
754 if (opt_transfer_is_active) {
755 optTries = 0;
756 loop_ctl = 0;
757 }
758 if (CURRENT_VALID)
759 end_request(0);
760 optTries = 5;
761 }
762 opt_error = 0;
763 opt_state = OPT_S_STOP;
764 }
765
766 while (loop_ctl)
767 {
768 loop_ctl = 0;
769
770 #ifdef DEBUG_STATE
771 if (opt_state == opt_state_old)
772 opt_state_n++;
773 else {
774 opt_state_old = opt_state;
775 if (++opt_state_n > 1)
776 printk("optcd: %ld times in previous state\n",
777 opt_state_n);
778 printk("optcd: state %d\n", opt_state);
779 opt_state_n = 0;
780 }
781 #endif
782 switch (opt_state) {
783 case OPT_S_IDLE:
784 return;
785 case OPT_S_START:
786 if (optSendCmd(COMDRVST))
787 return;
788 opt_state = OPT_S_READ;
789 optTimeout = 3000;
790 break;
791 case OPT_S_READ: {
792 struct opt_Play_msf msf;
793 if (!skip) {
794 if ((st = optStatus()) < 0)
795 break;
796 if (st & ST_DSK_CHG) {
797 optDiskChanged = 1;
798 optTocUpToDate = 0;
799 opt_invalidate_buffers();
800 }
801 }
802 skip = 0;
803 if ((st & ST_DOOR_OPEN) || (st & ST_DRVERR)) {
804 optDiskChanged = 1;
805 optTocUpToDate = 0;
806 printk((st & ST_DOOR_OPEN)
807 ? "optcd: door open\n"
808 : "optcd: disk removed\n");
809 if (opt_transfer_is_active) {
810 opt_state = OPT_S_START;
811 loop_ctl = 1;
812 break;
813 }
814 opt_state = OPT_S_IDLE;
815 while (CURRENT_VALID)
816 end_request(0);
817 return;
818 }
819 if (!CURRENT_VALID) {
820 opt_state = OPT_S_STOP;
821 loop_ctl = 1;
822 break;
823 }
824 opt_next_bn = CURRENT -> sector / 4;
825 hsg2msf(opt_next_bn, &msf.start);
826 opt_read_count = OPT_BUF_SIZ;
827 msf.end.min = 0;
828 msf.end.sec = 0;
829 msf.end.frame = opt_read_count;
830 #ifdef DEBUG_REQUEST
831 printk("optcd: reading %x:%x.%x %x:%x.%x\n",
832 msf.start.min,
833 msf.start.sec,
834 msf.start.frame,
835 msf.end.min,
836 msf.end.sec,
837 msf.end.frame);
838 printk("optcd: opt_next_bn:%d opt_buf_in:%d opt_buf_out:%d opt_buf_bn:%d\n",
839 opt_next_bn,
840 opt_buf_in,
841 opt_buf_out,
842 opt_buf_bn[opt_buf_in]);
843 #endif
844 optReadCmd(COMREAD, &msf);
845 opt_state = OPT_S_DATA;
846 optTimeout = READ_TIMEOUT;
847 break;
848 }
849 case OPT_S_DATA:
850 st = optFlags() & (FL_STEN|FL_DTEN);
851 #ifdef DEBUG_STATE
852 if (st != opt_st_old) {
853 opt_st_old = st;
854 printk("optcd: st:%x\n", st);
855 }
856 if (st == FL_STEN)
857 printk("timeout cnt: %d\n", optTimeout);
858 #endif
859 switch (st) {
860 case FL_DTEN:
861 #ifdef WARN_IF_READ_FAILURE
862 if (optTries == 5)
863 printk("optcd: read block %d failed; audio disk?\n",
864 opt_next_bn);
865 #endif
866 if (!optTries--) {
867 printk("optcd: read block %d failed; Giving up\n",
868 opt_next_bn);
869 if (opt_transfer_is_active) {
870 optTries = 0;
871 break;
872 }
873 if (CURRENT_VALID)
874 end_request(0);
875 optTries = 5;
876 }
877 opt_state = OPT_S_START;
878 optTimeout = READ_TIMEOUT;
879 loop_ctl = 1;
880 case (FL_STEN|FL_DTEN):
881 break;
882 default:
883 optTries = 5;
884 if (!CURRENT_VALID && opt_buf_in == opt_buf_out) {
885 opt_state = OPT_S_STOP;
886 loop_ctl = 1;
887 break;
888 }
889 if (opt_read_count<=0)
890 printk("optcd: warning - try to read 0 frames\n");
891 while (opt_read_count) {
892 opt_buf_bn[opt_buf_in] = OPT_NOBUF;
893 if (dten_low()) {
894 printk("read_count:%d CURRENT->nr_sectors:%ld opt_buf_in:%d\n",
895 opt_read_count,
896 CURRENT->nr_sectors,
897 opt_buf_in);
898 printk("opt_transfer_is_active:%x\n",
899 opt_transfer_is_active);
900 opt_read_count = 0;
901 opt_state = OPT_S_STOP;
902 loop_ctl = 1;
903 end_request(0);
904 break;
905 }
906 optReadData(opt_buf+OPT_BLOCKSIZE*opt_buf_in, OPT_BLOCKSIZE);
907 opt_read_count--;
908 #ifdef DEBUG_REQUEST
909 printk("OPT_S_DATA; ---I've read data- read_count: %d\n",
910 opt_read_count);
911 printk("opt_next_bn:%d opt_buf_in:%d opt_buf_out:%d opt_buf_bn:%d\n",
912 opt_next_bn,
913 opt_buf_in,
914 opt_buf_out,
915 opt_buf_bn[opt_buf_in]);
916 #endif
917 opt_buf_bn[opt_buf_in] = opt_next_bn++;
918 if (opt_buf_out == OPT_NOBUF)
919 opt_buf_out = opt_buf_in;
920 opt_buf_in = opt_buf_in + 1 ==
921 OPT_BUF_SIZ ? 0 : opt_buf_in + 1;
922 }
923 if (!opt_transfer_is_active) {
924 while (CURRENT_VALID) {
925 opt_transfer();
926 if (CURRENT -> nr_sectors == 0)
927 end_request(1);
928 else
929 break;
930 }
931 }
932
933 if (CURRENT_VALID
934 && (CURRENT -> sector / 4 < opt_next_bn ||
935 CURRENT -> sector / 4 >
936 opt_next_bn + OPT_BUF_SIZ)) {
937 opt_state = OPT_S_STOP;
938 loop_ctl = 1;
939 break;
940 }
941 optTimeout = READ_TIMEOUT;
942 if (opt_read_count == 0) {
943 opt_state = OPT_S_STOP;
944 loop_ctl = 1;
945 break;
946 }
947 }
948 break;
949 case OPT_S_STOP:
950 if (opt_read_count != 0)
951 printk("optcd: discard data=%x frames\n",
952 opt_read_count);
953 while (opt_read_count != 0) {
954 optFlushData();
955 opt_read_count--;
956 }
957 if (optSendCmd(COMDRVST))
958 return;
959 opt_state = OPT_S_STOPPING;
960 optTimeout = 1000;
961 break;
962 case OPT_S_STOPPING:
963 if ((st = optStatus()) < 0 && optTimeout)
964 break;
965 if ((st != -1) && (st & ST_DSK_CHG)) {
966 optDiskChanged = 1;
967 optTocUpToDate = 0;
968 opt_invalidate_buffers();
969 }
970 if (CURRENT_VALID) {
971 if (st != -1) {
972 opt_state = OPT_S_READ;
973 loop_ctl = 1;
974 skip = 1;
975 break;
976 } else {
977 opt_state = OPT_S_START;
978 optTimeout = 1;
979 }
980 } else {
981 opt_state = OPT_S_IDLE;
982 return;
983 }
984 break;
985 default:
986 printk("optcd: invalid state %d\n", opt_state);
987 return;
988 }
989 }
990
991 if (!optTimeout--) {
992 printk("optcd: timeout in state %d\n", opt_state);
993 opt_state = OPT_S_STOP;
994 if (optCmd(COMSTOP) < 0)
995 return;
996 }
997
998 SET_TIMER(opt_poll, 1);
999 }
1000
1001
1002 static void do_optcd_request(void) {
1003 #ifdef DEBUG_REQUEST
1004 printk("optcd: do_optcd_request(%ld+%ld)\n",
1005 CURRENT -> sector, CURRENT -> nr_sectors);
1006 #endif
1007 opt_transfer_is_active = 1;
1008 while (CURRENT_VALID) {
1009 if (CURRENT->bh) {
1010 if (!CURRENT->bh->b_lock)
1011 panic(DEVICE_NAME ": block not locked");
1012 }
1013 opt_transfer();
1014 if (CURRENT -> nr_sectors == 0) {
1015 end_request(1);
1016 } else {
1017 opt_buf_out = OPT_NOBUF;
1018 if (opt_state == OPT_S_IDLE) {
1019
1020 if (optUpdateToc() < 0) {
1021 while (CURRENT_VALID)
1022 end_request(0);
1023 break;
1024 }
1025
1026 opt_state = OPT_S_START;
1027 optTries = 5;
1028 SET_TIMER(opt_poll, 1);
1029 }
1030 break;
1031 }
1032 }
1033 opt_transfer_is_active = 0;
1034 #ifdef DEBUG_REQUEST
1035 printk("opt_next_bn:%d opt_buf_in:%d opt_buf_out:%d opt_buf_bn:%d\n",
1036 opt_next_bn, opt_buf_in, opt_buf_out, opt_buf_bn[opt_buf_in]);
1037 printk("optcd: do_optcd_request ends\n");
1038 #endif
1039 }
1040
1041
1042
1043
1044 static int opt_ioctl(struct inode *ip, struct file *fp,
1045 unsigned int cmd, unsigned long arg) {
1046 static struct opt_Play_msf opt_Play;
1047 int err;
1048 #ifdef DEBUG_VFS
1049 printk("optcd: starting opt_ioctl, command 0x%x\n", cmd);
1050 #endif
1051 if (!ip)
1052 return -EINVAL;
1053 if (optGetStatus() < 0)
1054 return -EIO;
1055 if ((err = optUpdateToc()) < 0)
1056 return err;
1057
1058 switch (cmd) {
1059 case CDROMPAUSE: {
1060 struct opt_Toc qInfo;
1061
1062 if (optAudioStatus != CDROM_AUDIO_PLAY)
1063 return -EINVAL;
1064 if (optGetQChannelInfo(&qInfo) < 0) {
1065
1066 optAudioStatus = CDROM_AUDIO_NO_STATUS;
1067 return 0;
1068 }
1069 opt_Play.start = qInfo.diskTime;
1070 if (optCmd(COMPAUSEON) < 0)
1071 return -EIO;
1072 optAudioStatus = CDROM_AUDIO_PAUSED;
1073 break;
1074 }
1075 case CDROMRESUME:
1076 if (optAudioStatus != CDROM_AUDIO_PAUSED)
1077 return -EINVAL;
1078 if (optPlayCmd(COMPLAY, &opt_Play) < 0) {
1079 optAudioStatus = CDROM_AUDIO_ERROR;
1080 return -EIO;
1081 }
1082 optAudioStatus = CDROM_AUDIO_PLAY;
1083 break;
1084 case CDROMPLAYMSF: {
1085 int st;
1086 struct cdrom_msf msf;
1087
1088 if ((st = verify_area(VERIFY_READ, (void *) arg, sizeof msf)))
1089 return st;
1090 memcpy_fromfs(&msf, (void *) arg, sizeof msf);
1091 opt_Play.start.min = bin2bcd(msf.cdmsf_min0);
1092 opt_Play.start.sec = bin2bcd(msf.cdmsf_sec0);
1093 opt_Play.start.frame = bin2bcd(msf.cdmsf_frame0);
1094 opt_Play.end.min = bin2bcd(msf.cdmsf_min1);
1095 opt_Play.end.sec = bin2bcd(msf.cdmsf_sec1);
1096 opt_Play.end.frame = bin2bcd(msf.cdmsf_frame1);
1097 if (optPlayCmd(COMPLAY, &opt_Play) < 0) {
1098 optAudioStatus = CDROM_AUDIO_ERROR;
1099 return -EIO;
1100 }
1101 optAudioStatus = CDROM_AUDIO_PLAY;
1102 break;
1103 }
1104 case CDROMPLAYTRKIND: {
1105 int st;
1106 struct cdrom_ti ti;
1107
1108 if ((st = verify_area(VERIFY_READ, (void *) arg, sizeof ti)))
1109 return st;
1110 memcpy_fromfs(&ti, (void *) arg, sizeof ti);
1111 if (ti.cdti_trk0 < DiskInfo.first
1112 || ti.cdti_trk0 > DiskInfo.last
1113 || ti.cdti_trk1 < ti.cdti_trk0)
1114 return -EINVAL;
1115 if (ti.cdti_trk1 > DiskInfo.last)
1116 ti.cdti_trk1 = DiskInfo.last;
1117 opt_Play.start = Toc[ti.cdti_trk0].diskTime;
1118 opt_Play.end = Toc[ti.cdti_trk1 + 1].diskTime;
1119 #ifdef DEBUG_VFS
1120 printk("optcd: play %02x:%02x.%02x to %02x:%02x.%02x\n",
1121 opt_Play.start.min,
1122 opt_Play.start.sec,
1123 opt_Play.start.frame,
1124 opt_Play.end.min,
1125 opt_Play.end.sec,
1126 opt_Play.end.frame);
1127 #endif
1128 if (optPlayCmd(COMPLAY, &opt_Play) < 0) {
1129 optAudioStatus = CDROM_AUDIO_ERROR;
1130 return -EIO;
1131 }
1132 optAudioStatus = CDROM_AUDIO_PLAY;
1133 break;
1134 }
1135 case CDROMREADTOCHDR: {
1136 int st;
1137 struct cdrom_tochdr tocHdr;
1138
1139 if ((st = verify_area(VERIFY_WRITE,(void *)arg,sizeof tocHdr)))
1140 return st;
1141 if (!optTocUpToDate)
1142 optGetDiskInfo();
1143 tocHdr.cdth_trk0 = DiskInfo.first;
1144 tocHdr.cdth_trk1 = DiskInfo.last;
1145 memcpy_tofs((void *) arg, &tocHdr, sizeof tocHdr);
1146 break;
1147 }
1148 case CDROMREADTOCENTRY: {
1149 int st;
1150 struct cdrom_tocentry entry;
1151 struct opt_Toc *tocPtr;
1152
1153 if ((st = verify_area(VERIFY_READ, (void *) arg, sizeof entry)))
1154 return st;
1155 if ((st = verify_area(VERIFY_WRITE, (void *) arg, sizeof entry)))
1156 return st;
1157 memcpy_fromfs(&entry, (void *) arg, sizeof entry);
1158 if (!optTocUpToDate)
1159 optGetDiskInfo();
1160 if (entry.cdte_track == CDROM_LEADOUT)
1161 tocPtr = &Toc[DiskInfo.last + 1];
1162 else if (entry.cdte_track > DiskInfo.last
1163 || entry.cdte_track < DiskInfo.first)
1164 return -EINVAL;
1165 else
1166 tocPtr = &Toc[entry.cdte_track];
1167 entry.cdte_adr = tocPtr -> ctrl_addr;
1168 entry.cdte_ctrl = tocPtr -> ctrl_addr >> 4;
1169 switch (entry.cdte_format) {
1170 case CDROM_LBA:
1171 entry.cdte_addr.lba = msf2hsg(&tocPtr -> diskTime);
1172 break;
1173 case CDROM_MSF:
1174 entry.cdte_addr.msf.minute =
1175 bcd2bin(tocPtr -> diskTime.min);
1176 entry.cdte_addr.msf.second =
1177 bcd2bin(tocPtr -> diskTime.sec);
1178 entry.cdte_addr.msf.frame =
1179 bcd2bin(tocPtr -> diskTime.frame);
1180 break;
1181 default:
1182 return -EINVAL;
1183 }
1184 memcpy_tofs((void *) arg, &entry, sizeof entry);
1185 break;
1186 }
1187 case CDROMSTOP:
1188 optCmd(COMSTOP);
1189 optAudioStatus = CDROM_AUDIO_NO_STATUS;
1190 break;
1191 case CDROMSTART:
1192 optCmd(COMCLOSE);
1193 break;
1194 case CDROMEJECT:
1195 optCmd(COMUNLOCK);
1196 optCmd(COMOPEN);
1197 break;
1198 case CDROMVOLCTRL: {
1199 int st;
1200 struct cdrom_volctrl volctrl;
1201
1202 if ((st = verify_area(VERIFY_READ, (void *) arg,
1203 sizeof(volctrl))))
1204 return st;
1205 memcpy_fromfs(&volctrl, (char *) arg, sizeof(volctrl));
1206 opt_Play.start.min = 0x10;
1207 opt_Play.start.sec = 0x32;
1208 opt_Play.start.frame = volctrl.channel0;
1209 opt_Play.end.min = volctrl.channel1;
1210 opt_Play.end.sec = volctrl.channel2;
1211 opt_Play.end.frame = volctrl.channel3;
1212 if (optPlayCmd(COMCHCTRL, &opt_Play) < 0)
1213 return -EIO;
1214 break;
1215 }
1216 case CDROMSUBCHNL: {
1217 int st;
1218 struct cdrom_subchnl subchnl;
1219 struct opt_Toc qInfo;
1220
1221 if ((st = verify_area(VERIFY_READ,
1222 (void *) arg, sizeof subchnl)))
1223 return st;
1224 if ((st = verify_area(VERIFY_WRITE,
1225 (void *) arg, sizeof subchnl)))
1226 return st;
1227 memcpy_fromfs(&subchnl, (void *) arg, sizeof subchnl);
1228 if (optGetQChannelInfo(&qInfo) < 0)
1229 return -EIO;
1230 subchnl.cdsc_audiostatus = optAudioStatus;
1231 subchnl.cdsc_adr = qInfo.ctrl_addr;
1232 subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4;
1233 subchnl.cdsc_trk = bcd2bin(qInfo.track);
1234 subchnl.cdsc_ind = bcd2bin(qInfo.pointIndex);
1235 switch (subchnl.cdsc_format) {
1236 case CDROM_LBA:
1237 subchnl.cdsc_absaddr.lba = msf2hsg(&qInfo.diskTime);
1238 subchnl.cdsc_reladdr.lba = msf2hsg(&qInfo.trackTime);
1239 break;
1240 case CDROM_MSF:
1241 subchnl.cdsc_absaddr.msf.minute =
1242 bcd2bin(qInfo.diskTime.min);
1243 subchnl.cdsc_absaddr.msf.second =
1244 bcd2bin(qInfo.diskTime.sec);
1245 subchnl.cdsc_absaddr.msf.frame =
1246 bcd2bin(qInfo.diskTime.frame);
1247 subchnl.cdsc_reladdr.msf.minute =
1248 bcd2bin(qInfo.trackTime.min);
1249 subchnl.cdsc_reladdr.msf.second =
1250 bcd2bin(qInfo.trackTime.sec);
1251 subchnl.cdsc_reladdr.msf.frame =
1252 bcd2bin(qInfo.trackTime.frame);
1253 break;
1254 default:
1255 return -EINVAL;
1256 }
1257 memcpy_tofs((void *) arg, &subchnl, sizeof subchnl);
1258 break;
1259 }
1260 case CDROMREADMODE1: {
1261 int st;
1262 struct cdrom_msf msf;
1263 char buf[OPT_BLOCKSIZE];
1264
1265 if ((st = verify_area(VERIFY_READ, (void *) arg, sizeof msf)))
1266 return st;
1267 if ((st = verify_area(VERIFY_WRITE,(void *)arg,OPT_BLOCKSIZE)))
1268 return st;
1269 memcpy_fromfs(&msf, (void *) arg, sizeof msf);
1270 opt_Play.start.min = bin2bcd(msf.cdmsf_min0);
1271 opt_Play.start.sec = bin2bcd(msf.cdmsf_sec0);
1272 opt_Play.start.frame = bin2bcd(msf.cdmsf_frame0);
1273 opt_Play.end.min = 0;
1274 opt_Play.end.sec = 0;
1275 opt_Play.end.frame = 1;
1276 st = optReadCmd(COMREAD, &opt_Play);
1277 #ifdef DEBUG_VFS
1278 printk("optcd: COMREAD status 0x%x\n", st);
1279 #endif
1280 sleep_dten_low();
1281 optReadData(buf, OPT_BLOCKSIZE);
1282 memcpy_tofs((void *) arg, &buf, OPT_BLOCKSIZE);
1283 break;
1284 }
1285 case CDROMMULTISESSION:
1286 return -EINVAL;
1287
1288 default:
1289 return -EINVAL;
1290 }
1291 #ifdef DEBUG_VFS
1292 printk("optcd: exiting opt_ioctl\n");
1293 #endif
1294 return 0;
1295 }
1296
1297 static int optPresent = 0;
1298 static int opt_open_count = 0;
1299
1300
1301 static int opt_open(struct inode *ip, struct file *fp) {
1302 #ifdef DEBUG_VFS
1303 printk("optcd: starting opt_open\n");
1304 #endif
1305 if (!optPresent)
1306 return -ENXIO;
1307 if (!opt_open_count && opt_state == OPT_S_IDLE) {
1308 int st;
1309 opt_invalidate_buffers();
1310 if ((st = optGetStatus()) < 0)
1311 return -EIO;
1312 if (st & ST_DOOR_OPEN) {
1313 optCmd(COMCLOSE);
1314 if ((st = optGetStatus()) < 0)
1315 return -EIO;
1316 }
1317 if (st & (ST_DOOR_OPEN|ST_DRVERR)) {
1318 printk("optcd: no disk or door open\n");
1319 return -EIO;
1320 }
1321 if (optUpdateToc() < 0)
1322 return -EIO;
1323 }
1324 opt_open_count++;
1325 MOD_INC_USE_COUNT;
1326 optCmd(COMLOCK);
1327 #ifdef DEBUG_VFS
1328 printk("optcd: exiting opt_open\n");
1329 #endif
1330 return 0;
1331 }
1332
1333
1334 static void opt_release(struct inode *ip, struct file *fp) {
1335 #ifdef DEBUG_VFS
1336 printk("optcd: executing opt_release\n");
1337 printk("inode: %p, inode -> i_rdev: 0x%x, file: %p\n",
1338 ip, ip -> i_rdev, fp);
1339 #endif
1340 if (!--opt_open_count) {
1341 opt_invalidate_buffers();
1342 sync_dev(ip -> i_rdev);
1343 invalidate_buffers(ip -> i_rdev);
1344 CLEAR_TIMER;
1345 optCmd(COMUNLOCK);
1346 }
1347 MOD_DEC_USE_COUNT;
1348 }
1349
1350
1351
1352
1353 static int version_ok(void) {
1354 char devname[100];
1355 int count, i, ch;
1356
1357 if (optCmd(COMVERSION) < 0)
1358 return 0;
1359 if ((count = optGetData()) < 0)
1360 return 0;
1361 for (i = 0, ch = -1; count > 0; count--) {
1362 if ((ch = optGetData()) < 0)
1363 break;
1364 if (i < 99)
1365 devname[i++] = ch;
1366 }
1367 devname[i] = '\0';
1368 if (ch < 0)
1369 return 0;
1370 printk("optcd: Device %s detected\n", devname);
1371 return ((devname[0] == 'D')
1372 && (devname[1] == 'O')
1373 && (devname[2] == 'L')
1374 && (devname[3] == 'P')
1375 && (devname[4] == 'H')
1376 && (devname[5] == 'I')
1377 && (devname[6] == 'N'));
1378 }
1379
1380
1381 static struct file_operations opt_fops = {
1382 NULL,
1383 block_read,
1384 block_write,
1385 NULL,
1386 NULL,
1387 opt_ioctl,
1388 NULL,
1389 opt_open,
1390 opt_release,
1391 NULL,
1392 NULL,
1393 NULL,
1394 NULL
1395 };
1396
1397
1398
1399 void optcd_setup(char *str, int *ints) {
1400 if (ints[0] > 0)
1401 optcd_port = ints[1];
1402 }
1403
1404 #ifndef MODULE
1405 #define RETURN_EIO return mem_start
1406 #else
1407 #define RETURN_EIO return -EIO
1408 #endif
1409
1410
1411
1412
1413 #ifndef MODULE
1414 unsigned long optcd_init(unsigned long mem_start, unsigned long mem_end) {
1415 #else
1416 int init_module(void) {
1417 #endif
1418 if (optcd_port <= 0) {
1419 printk("optcd: no Optics Storage CDROM Initialization\n");
1420 RETURN_EIO;
1421 }
1422 if (check_region(optcd_port, 4)) {
1423 printk("optcd: conflict, I/O port 0x%x already used\n",
1424 optcd_port);
1425 RETURN_EIO;
1426 }
1427
1428 if (!check_region(ISP16_DRIVE_SET_PORT, 5)) {
1429
1430
1431
1432
1433 if ( (isp16_type=isp16_detect()) < 0 )
1434 printk( "No ISP16 cdrom interface found.\n" );
1435 else {
1436 u_char expected_drive;
1437
1438 printk( "ISP16 cdrom interface (%s optional IDE) detected.\n",
1439 (isp16_type==2)?"with":"without" );
1440
1441 expected_drive = (isp16_type?ISP16_SANYO1:ISP16_SANYO0);
1442
1443 if ( isp16_config( optcd_port, ISP16_SONY, 0, 0 ) < 0 ) {
1444 printk( "ISP16 cdrom interface has not been properly configured.\n" );
1445 return(mem_start);
1446 }
1447 }
1448 }
1449
1450 if (!optResetDrive()) {
1451 printk("optcd: drive at 0x%x not ready\n", optcd_port);
1452 RETURN_EIO;
1453 }
1454 if (!version_ok()) {
1455 printk("optcd: unknown drive detected; aborting\n");
1456 RETURN_EIO;
1457 }
1458 if (optCmd(COMINITDOUBLE) < 0) {
1459 printk("optcd: cannot init double speed mode\n");
1460 RETURN_EIO;
1461 }
1462 if (register_blkdev(MAJOR_NR, "optcd", &opt_fops) != 0)
1463 {
1464 printk("optcd: unable to get major %d\n", MAJOR_NR);
1465 RETURN_EIO;
1466 }
1467 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1468 read_ahead[MAJOR_NR] = 4;
1469 request_region(optcd_port, 4, "optcd");
1470 optPresent = 1;
1471 printk("optcd: 8000 AT CDROM at 0x%x\n", optcd_port);
1472 #ifndef MODULE
1473 return mem_start;
1474 #else
1475 return 0;
1476 #endif
1477 }
1478
1479 #ifdef MODULE
1480 void cleanup_module(void) {
1481 if (MOD_IN_USE) {
1482 printk("optcd: module in use - can't remove it.\n");
1483 return;
1484 }
1485 if ((unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL)) {
1486 printk("optcd: what's that: can't unregister\n");
1487 return;
1488 }
1489 release_region(optcd_port, 4);
1490 printk("optcd: module released.\n");
1491 }
1492 #endif MODULE
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517 #define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p))
1518 #define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p))
1519
1520 static short
1521 isp16_detect(void)
1522 {
1523
1524 if ( !( isp16_with_ide__detect() < 0 ) )
1525 return(2);
1526 else
1527 return( isp16_no_ide__detect() );
1528 }
1529
1530 static short
1531 isp16_no_ide__detect(void)
1532 {
1533 u_char ctrl;
1534 u_char enable_cdrom;
1535 u_char io;
1536 short i = -1;
1537
1538 isp16_ctrl = ISP16_NO_IDE__CTRL;
1539 isp16_enable_cdrom_port = ISP16_NO_IDE__ENABLE_CDROM_PORT;
1540
1541
1542
1543
1544 ctrl = ISP16_IN( ISP16_CTRL_PORT ) & 0xFC;
1545 ISP16_OUT( ISP16_CTRL_PORT, ctrl );
1546
1547
1548 enable_cdrom = ISP16_IN( ISP16_NO_IDE__ENABLE_CDROM_PORT ) & 0x38;
1549
1550 if ( !(enable_cdrom & 0x20) ) {
1551
1552 io = ISP16_IN( ISP16_IO_SET_PORT ) & 0x03;
1553 if ( ((io&0x01)<<1) == (io&0x02) ) {
1554 if ( io == 0 ) {
1555 i = 0;
1556 enable_cdrom |= 0x20;
1557 }
1558 else {
1559 i = 1;
1560 enable_cdrom |= 0x28;
1561 }
1562 ISP16_OUT( ISP16_NO_IDE__ENABLE_CDROM_PORT, enable_cdrom );
1563 }
1564 else {
1565 ISP16_OUT( ISP16_CTRL_PORT, ctrl );
1566 return(i);
1567 }
1568 }
1569 else if ( enable_cdrom == 0x20 )
1570 i = 0;
1571 else if ( enable_cdrom == 0x28 )
1572 i = 1;
1573
1574 ISP16_OUT( ISP16_CTRL_PORT, ctrl );
1575
1576 return(i);
1577 }
1578
1579 static short
1580 isp16_with_ide__detect(void)
1581 {
1582 u_char ctrl;
1583 u_char tmp;
1584
1585 isp16_ctrl = ISP16_IDE__CTRL;
1586 isp16_enable_cdrom_port = ISP16_IDE__ENABLE_CDROM_PORT;
1587
1588
1589
1590
1591 ctrl = ISP16_IN( ISP16_CTRL_PORT );
1592
1593
1594 ISP16_OUT( ISP16_CTRL_PORT, 0 );
1595 tmp = ISP16_IN( ISP16_CTRL_PORT );
1596
1597 if ( tmp != 2 )
1598 return(-1);
1599
1600
1601 ISP16_OUT( ISP16_CTRL_PORT, ctrl );
1602
1603 return(2);
1604 }
1605
1606 static short
1607 isp16_config( int base, u_char drive_type, int irq, int dma )
1608 {
1609 u_char base_code;
1610 u_char irq_code;
1611 u_char dma_code;
1612 u_char i;
1613
1614 if ( (drive_type == ISP16_MITSUMI) && (dma != 0) )
1615 printk( "Mitsumi cdrom drive has no dma support.\n" );
1616
1617 switch (base) {
1618 case 0x340: base_code = ISP16_BASE_340; break;
1619 case 0x330: base_code = ISP16_BASE_330; break;
1620 case 0x360: base_code = ISP16_BASE_360; break;
1621 case 0x320: base_code = ISP16_BASE_320; break;
1622 default:
1623 printk( "Base address 0x%03X not supported by cdrom interface on ISP16.\n", base );
1624 return(-1);
1625 }
1626 switch (irq) {
1627 case 0: irq_code = ISP16_IRQ_X; break;
1628 case 5: irq_code = ISP16_IRQ_5;
1629 printk( "Irq 5 shouldn't be used by cdrom interface on ISP16,"
1630 " due to possible conflicts with the soundcard.\n");
1631 break;
1632 case 7: irq_code = ISP16_IRQ_7;
1633 printk( "Irq 7 shouldn't be used by cdrom interface on ISP16,"
1634 " due to possible conflicts with the soundcard.\n");
1635 break;
1636 case 3: irq_code = ISP16_IRQ_3; break;
1637 case 9: irq_code = ISP16_IRQ_9; break;
1638 case 10: irq_code = ISP16_IRQ_10; break;
1639 case 11: irq_code = ISP16_IRQ_11; break;
1640 default:
1641 printk( "Irq %d not supported by cdrom interface on ISP16.\n", irq );
1642 return(-1);
1643 }
1644 switch (dma) {
1645 case 0: dma_code = ISP16_DMA_X; break;
1646 case 1: printk( "Dma 1 cannot be used by cdrom interface on ISP16,"
1647 " due to conflict with the soundcard.\n");
1648 return(-1); break;
1649 case 3: dma_code = ISP16_DMA_3; break;
1650 case 5: dma_code = ISP16_DMA_5; break;
1651 case 6: dma_code = ISP16_DMA_6; break;
1652 case 7: dma_code = ISP16_DMA_7; break;
1653 default:
1654 printk( "Dma %d not supported by cdrom interface on ISP16.\n", dma );
1655 return(-1);
1656 }
1657
1658 if ( drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 &&
1659 drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 &&
1660 drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI &&
1661 drive_type != ISP16_DRIVE_X ) {
1662 printk( "Drive type (code 0x%02X) not supported by cdrom"
1663 " interface on ISP16.\n", drive_type );
1664 return(-1);
1665 }
1666
1667
1668 i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK;
1669 ISP16_OUT( ISP16_DRIVE_SET_PORT, i|drive_type );
1670
1671
1672 if ( isp16_type > 1 )
1673 ISP16_OUT( isp16_enable_cdrom_port, ISP16_ENABLE_CDROM );
1674
1675
1676 i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK;
1677 ISP16_OUT( ISP16_IO_SET_PORT, i|base_code|irq_code|dma_code );
1678
1679 return(0);
1680 }