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