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