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