1 /*
2 www.freedo.org
3 The first working 3DO multiplayer emulator.
4
5 The FreeDO licensed under modified GNU LGPL, with following notes:
6
7 * The owners and original authors of the FreeDO have full right to
8 * develop closed source derivative work.
9
10 * Any non-commercial uses of the FreeDO sources or any knowledge
11 * obtained by studying or reverse engineering of the sources, or
12 * any other material published by FreeDO have to be accompanied
13 * with full credits.
14
15 * Any commercial uses of FreeDO sources or any knowledge obtained
16 * by studying or reverse engineering of the sources, or any other
17 * material published by FreeDO is strictly forbidden without
18 * owners approval.
19
20 The above notes are taking precedence over GNU LGPL in conflicting
21 situations.
22
23 Project authors:
24 * Alexander Troosh
25 * Maxim Grishin
26 * Allen Wright
27 * John Sammons
28 * Felix Lazarev
29 */
30
31 #include "inline.h"
32 #include "opera_cdrom.h"
33
34 #include <stdint.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #define MSF_BIAS_IN_SECONDS 2
39 #define MSF_BIAS_IN_FRAMES 150
40 #define FRAMES_PER_SECOND 75
41 #define SECONDS_PER_MINUTE 60
42
43 /* FIXME: should not be using globals */
44 opera_cdrom_get_size_cb_t CDROM_GET_SIZE;
45 opera_cdrom_set_sector_cb_t CDROM_SET_SECTOR;
46 opera_cdrom_read_sector_cb_t CDROM_READ_SECTOR;
47
48 static
49 INLINE
50 void
LBA2MSF(const uint32_t lba_,msf_t * msf_)51 LBA2MSF(const uint32_t lba_,
52 msf_t *msf_)
53 {
54 uint32_t mod;
55
56 mod = ((lba_ + MSF_BIAS_IN_FRAMES) % (SECONDS_PER_MINUTE * FRAMES_PER_SECOND));
57 msf_->minutes = ((lba_ + MSF_BIAS_IN_FRAMES) / (SECONDS_PER_MINUTE * FRAMES_PER_SECOND));
58 msf_->seconds = (mod / FRAMES_PER_SECOND);
59 msf_->frames = (mod % FRAMES_PER_SECOND);
60 }
61
62 static
63 INLINE
64 uint32_t
MSF2LBA(const msf_t * msf_)65 MSF2LBA(const msf_t *msf_)
66 {
67 uint32_t lba;
68
69 lba = ((msf_->minutes * SECONDS_PER_MINUTE * FRAMES_PER_SECOND) +
70 (msf_->seconds * FRAMES_PER_SECOND) +
71 (msf_->frames) -
72 (MSF_BIAS_IN_FRAMES));
73 if(lba < 0)
74 lba = 0;
75
76 return lba;
77 }
78
79 void
opera_cdrom_set_callbacks(opera_cdrom_get_size_cb_t get_size_,opera_cdrom_set_sector_cb_t set_sector_,opera_cdrom_read_sector_cb_t read_sector_)80 opera_cdrom_set_callbacks(opera_cdrom_get_size_cb_t get_size_,
81 opera_cdrom_set_sector_cb_t set_sector_,
82 opera_cdrom_read_sector_cb_t read_sector_)
83 {
84 CDROM_GET_SIZE = get_size_;
85 CDROM_SET_SECTOR = set_sector_;
86 CDROM_READ_SECTOR = read_sector_;
87 }
88
89 void
opera_cdrom_init(cdrom_device_t * cd_)90 opera_cdrom_init(cdrom_device_t *cd_)
91 {
92 uint32_t file_size_in_blocks;
93
94 cd_->current_sector = 0;
95 CDROM_SET_SECTOR(cd_->current_sector);
96 file_size_in_blocks = CDROM_GET_SIZE();
97
98 cd_->data_idx = 0;
99 cd_->xbus_status = 0;
100 cd_->poll = 0x0F;
101 cd_->xbus_status |= CDST_OK;
102
103 cd_->MEI_status = MEI_CDROM_no_error;
104
105 cd_->disc.track_first = 1;
106 cd_->disc.track_last = 1;
107
108 cd_->disc.disc_id = MEI_DISC_DA_OR_CDROM;
109
110 cd_->disc.msf_current.minutes = 0;
111 cd_->disc.msf_current.seconds = MSF_BIAS_IN_SECONDS;
112 cd_->disc.msf_current.frames = 0;
113
114 cd_->disc.disc_toc[1].CDCTL = CD_CTL_DATA_TRACK|CD_CTL_Q_NONE; /* |CD_CTL_COPY_PERMITTED; */
115 cd_->disc.disc_toc[1].track_number = 1;
116 cd_->disc.disc_toc[1].minutes = 0;
117 cd_->disc.disc_toc[1].seconds = MSF_BIAS_IN_SECONDS;
118 cd_->disc.disc_toc[1].frames = 0;
119
120 LBA2MSF(file_size_in_blocks + MSF_BIAS_IN_FRAMES,&cd_->disc.msf_total);
121 LBA2MSF(file_size_in_blocks,&cd_->disc.msf_session);
122
123 cd_->STATCYC = STATDELAY;
124 }
125
126 uint8_t
opera_cdrom_fifo_get_status(cdrom_device_t * cd_)127 opera_cdrom_fifo_get_status(cdrom_device_t *cd_)
128 {
129 uint8_t rv;
130
131 rv = 0;
132 if(cd_->status_len > 0)
133 {
134 rv = cd_->status[0];
135 cd_->status_len--;
136 if(cd_->status_len > 0)
137 memmove(cd_->status,cd_->status + 1,cd_->status_len);
138 else
139 cd_->poll &= ~POLST;
140 }
141
142 return rv;
143 }
144
145 void
opera_cdrom_do_cmd(cdrom_device_t * cd_)146 opera_cdrom_do_cmd(cdrom_device_t *cd_)
147 {
148 int i;
149
150 cd_->status_len = 0;
151
152 cd_->poll &= ~POLST;
153 cd_->poll &= ~POLDT;
154 cd_->xbus_status &= ~CDST_ERRO;
155 cd_->xbus_status &= ~CDST_RDY;
156
157 switch(cd_->cmd[0])
158 {
159 /*
160 seek
161 not used in opera
162 01 00 ll-bb-aa 00 00.
163 01 02 mm-ss-ff 00 00.
164 status 4 bytes
165 xx xx xx XS (xs = xbus status)
166 */
167 case CDROM_CMD_SEEK:
168 break;
169
170 /*
171 spin up
172 opera status request = 0
173 status 4 bytes
174 xx xx xx XS (XS = xbus status)
175 */
176 case CDROM_CMD_SPIN_UP:
177 if((cd_->xbus_status & CDST_TRAY) &&
178 (cd_->xbus_status & CDST_DISC))
179 {
180 cd_->xbus_status |= CDST_SPIN;
181 cd_->xbus_status |= CDST_RDY;
182 cd_->MEI_status = MEI_CDROM_no_error;
183 }
184 else
185 {
186 cd_->xbus_status |= CDST_ERRO;
187 cd_->xbus_status &= ~CDST_RDY;
188 cd_->MEI_status = MEI_CDROM_recv_ecc;
189 }
190
191 cd_->status_len = 2;
192 cd_->status[0] = CDROM_CMD_SPIN_UP;
193 cd_->status[1] = cd_->xbus_status;
194
195 cd_->poll |= POLST;
196 break;
197
198 /*
199 spin down
200 opera status request = 0 // not used in opera
201 status 4 bytes
202 xx xx xx XS (XS = xbus status)
203 */
204 case CDROM_CMD_SPIN_DOWN:
205 cd_->xbus_status |= CDST_RDY;
206 if((cd_->xbus_status & CDST_TRAY) &&
207 (cd_->xbus_status & CDST_DISC))
208 {
209 cd_->xbus_status &= ~CDST_SPIN;
210 cd_->MEI_status = MEI_CDROM_no_error;
211 }
212 else
213 {
214 cd_->xbus_status |= CDST_ERRO;
215 cd_->MEI_status = MEI_CDROM_recv_ecc;
216 }
217
218 cd_->status_len = 2;
219 cd_->status[0] = CDROM_CMD_SPIN_DOWN;
220 cd_->status[1] = cd_->xbus_status;
221
222 cd_->poll |= POLST;
223 break;
224
225 /*
226 diagnostics
227 not used in opera
228 04 00 ll-bb-aa 00 00.
229 04 02 mm-ss-ff 00 00.
230 status 4 bytes
231 xx S1 S2 XS
232 */
233 case CDROM_CMD_DIAGNOSTICS:
234 break;
235
236 /*
237 eject disc
238 opera status request = 0
239 status 4 bytes
240 xx xx xx XS
241 1b command of scsi
242 emulation ---
243 Execute EJECT command;
244 Check Sense, update PollRegister (if medium present)
245 */
246 case CDROM_CMD_EJECT_DISC:
247 cd_->xbus_status |= CDST_RDY;
248 cd_->xbus_status &= ~CDST_TRAY;
249 cd_->xbus_status &= ~CDST_DISC;
250 cd_->xbus_status &= ~CDST_SPIN;
251 cd_->xbus_status &= ~CDST_2X;
252 cd_->xbus_status &= ~CDST_ERRO;
253 cd_->MEI_status = MEI_CDROM_no_error;
254
255 cd_->status_len = 2;
256 cd_->status[0] = CDROM_CMD_EJECT_DISC;
257 cd_->status[1] = cd_->xbus_status;
258
259 cd_->poll |= POLST;
260 cd_->poll &= ~POLMA;
261 break;
262
263 /*
264 inject disc
265 opera status request = 0
266 status 4 bytes
267 xx xx xx XS
268 1b command of scsi
269 */
270 case CDROM_CMD_INJECT_DISC:
271 cd_->status_len = 2;
272 cd_->status[0] = CDROM_CMD_INJECT_DISC;
273 cd_->status[1] = cd_->xbus_status;
274
275 cd_->poll |= POLST;
276 break;
277
278 /*
279 abort !!!
280 opera status request = 31
281 status 4 bytes
282 xx xx xx XS
283 */
284 case CDROM_CMD_ABORT:
285 cd_->status_len = 33;
286 cd_->status[0] = CDROM_CMD_ABORT;
287 for(i = 1; i < 32; i++)
288 cd_->status[i] = 0;
289 cd_->status[32] = cd_->xbus_status;
290
291 cd_->xbus_status |= CDST_RDY;
292 cd_->MEI_status = MEI_CDROM_no_error;
293 break;
294
295 /*
296 mode set
297 09 MM nn 00 00 00 00 // 2048 or 2340 transfer size
298 to be checked -- wasn't called even once
299 2nd byte is type selector
300 MM = mode nn= value
301 opera status request = 0
302 status 4 bytes
303 xx xx xx XS
304 */
305 case CDROM_CMD_MODE_SET:
306 /* if((xbus_status&CDST_TRAY) && (xbus_status&CDST_disc)) */
307 /* { */
308 cd_->xbus_status |= CDST_RDY;
309 cd_->MEI_status = MEI_CDROM_no_error;
310
311 /* CDMode[cmd[1]] = cmd[2]; */
312 /* } */
313 /* else */
314 /* { */
315 /* xbus_status |= CDST_ERRO; */
316 /* xbus_status &= ~CDST_RDY; */
317 /* } */
318
319 cd_->status_len = 2;
320 cd_->status[0] = CDROM_CMD_MODE_SET;
321 cd_->status[1] = cd_->xbus_status;
322
323 cd_->poll |= POLST;
324 break;
325
326 /*
327 reset
328 not used in opera
329 status 4 bytes
330 xx xx xx XS
331 */
332 case CDROM_CMD_RESET:
333 break;
334
335 /*
336 flush
337 opera status request = 31
338 status 4 bytes
339 xx xx xx XS
340 returns data
341 flush all internal buffer
342 1+31+1
343 */
344 case CDROM_CMD_FLUSH:
345 cd_->xbus_status |= CDST_RDY;
346 cd_->status_len = 33;
347 cd_->status[0] = CDROM_CMD_FLUSH;
348 for(i = 1; i < 32; i++)
349 cd_->status[i] = 0;
350 cd_->status[32] = cd_->xbus_status;
351
352 /* cd_->xbus_status |= CDST_RDY; */
353 cd_->MEI_status = MEI_CDROM_no_error;
354 break;
355
356 /*
357 READ DATA
358 10 01 00 00 00 00 01
359 read 1 blocks from MSF = 1.0.0
360 10 xx-xx-xx fl nn-nn
361 00 01 02 03 04 05 06
362 reads nn blocks from xx
363 fl = 0 xx="msf" ?
364 fl = 1 xx="lba" ?
365 block = 2048 bytes
366 opera status request = 0
367 status 4 bytes
368 xx xx xx xbus_status
369 returns data
370 */
371 case CDROM_CMD_READ_DATA:
372 if((cd_->xbus_status & CDST_TRAY) &&
373 (cd_->xbus_status & CDST_DISC) &&
374 (cd_->xbus_status & CDST_SPIN))
375 {
376 cd_->xbus_status |= CDST_RDY;
377 cd_->status_len = 2;
378 cd_->status[0] = CDROM_CMD_READ_DATA;
379 cd_->status[1] = cd_->xbus_status;
380
381 cd_->disc.msf_current.minutes = cd_->cmd[1];
382 cd_->disc.msf_current.seconds = cd_->cmd[2];
383 cd_->disc.msf_current.frames = cd_->cmd[3];
384 cd_->current_sector = MSF2LBA(&cd_->disc.msf_current);
385 cd_->blocks_requested = ((cd_->cmd[5] << 8) + cd_->cmd[6]);
386
387 CDROM_SET_SECTOR(cd_->current_sector);
388 if(cd_->blocks_requested)
389 {
390 cd_->current_sector++;
391 CDROM_READ_SECTOR(cd_->data);
392 cd_->data_len = REQSIZE;
393 cd_->blocks_requested--;
394 }
395 else
396 {
397 cd_->data_len = 0;
398 }
399
400 cd_->MEI_status = MEI_CDROM_no_error;
401 cd_->poll |= (POLDT | POLST);
402 }
403 else
404 {
405 cd_->xbus_status |= CDST_ERRO;
406 cd_->xbus_status &= ~CDST_RDY;
407 cd_->status_len = 2;
408 cd_->status[0] = CDROM_CMD_READ_DATA;
409 cd_->status[1] = cd_->xbus_status;
410 cd_->MEI_status = MEI_CDROM_recv_ecc;
411 cd_->poll |= POLST;
412 }
413 break;
414
415 /*
416 data path check
417 opera status request = 2
418 MKE = 2
419 status 4 bytes
420 80 AA 55 XS
421 */
422 case CDROM_CMD_DATA_PATH_CHECK:
423 cd_->xbus_status |= CDST_RDY;
424 cd_->status_len = 4;
425 cd_->status[0] = CDROM_CMD_DATA_PATH_CHECK;
426 cd_->status[1] = 0xAA;
427 cd_->status[2] = 0x55;
428 cd_->status[3] = cd_->xbus_status;
429 cd_->MEI_status = MEI_CDROM_no_error;
430 cd_->poll |= POLST;
431 break;
432
433 /*
434 read error (get last status???)
435 opera status request = 8 ---- tests status req=9?????
436 MKE = 8!!!
437 00
438 11
439 22 Current status //MKE / Opera???
440 33
441 44
442 55
443 66
444 77
445 88 Current status //TEST
446 */
447 case CDROM_CMD_GET_LAST_STATUS:
448 cd_->xbus_status |= CDST_RDY;
449 cd_->status_len = 10;
450 cd_->status[0] = CDROM_CMD_GET_LAST_STATUS;
451 cd_->status[1] = cd_->MEI_status;
452 cd_->status[2] = cd_->MEI_status;
453 cd_->status[3] = cd_->MEI_status;
454 cd_->status[4] = cd_->MEI_status;
455 cd_->status[5] = cd_->MEI_status;
456 cd_->status[6] = cd_->MEI_status;
457 cd_->status[7] = cd_->MEI_status;
458 cd_->status[8] = cd_->MEI_status;
459 cd_->status[9] = cd_->xbus_status; /* 1 == disc present */
460 cd_->poll |= POLST;
461 break;
462
463 /*
464 read id
465 opera status request = 10
466 status 12 bytes (3 words)
467 MEI text + XS
468 00 M E I 1 01 00 00 00 00 00 XS
469 */
470 case CDROM_CMD_READ_ID:
471 cd_->xbus_status |= CDST_RDY;
472 cd_->status_len = 12;
473 cd_->status[0] = CDROM_CMD_READ_ID;
474 cd_->status[1] = 0x00; /* manufacture id */
475 cd_->status[2] = 0x10; /* 10 */
476 cd_->status[3] = 0x00; /* manufacture number */
477 cd_->status[4] = 0x01; /* 01 */
478 cd_->status[5] = 00;
479 cd_->status[6] = 00;
480 cd_->status[7] = 0; /* revision number */
481 cd_->status[8] = 0;
482 cd_->status[9] = 0x00; /* flag bytes */
483 cd_->status[10] = 0x00;
484 cd_->status[11] = cd_->xbus_status; /* device driver size */
485 cd_->MEI_status = MEI_CDROM_no_error;
486 cd_->poll |= POLST;
487 break;
488
489 /*
490 mode sense
491 not used in opera
492 84 mm 00 00 00 00 00.
493 status 4 bytes
494 xx S1 S2 XS
495 xx xx nn XS
496 */
497 case CDROM_CMD_MODE_SENSE:
498 if((cd_->xbus_status & CDST_TRAY) &&
499 (cd_->xbus_status & CDST_DISC))
500 {
501 cd_->xbus_status |= CDST_RDY;
502 }
503 else
504 {
505 cd_->xbus_status |= CDST_ERRO;
506 cd_->xbus_status &= ~CDST_RDY;
507 }
508
509 cd_->status_len = 4;
510 cd_->status[0] = 0x00;
511 cd_->status[1] = 0x00;
512 cd_->status[2] = 0x00;
513 cd_->status[3] = cd_->xbus_status;
514 cd_->poll |= POLST;
515 break;
516
517 /*
518 read capacity
519 status 8 bytes
520 opera status request = 6
521 cc cc cc cc cc cc cc XS
522 data?
523 00 85
524 11 mm total
525 22 ss total
526 33 ff total
527 44 ??
528 55 ??
529 66 ??
530 */
531 case CDROM_CMD_READ_CAPACITY:
532 if((cd_->xbus_status & CDST_TRAY) &&
533 (cd_->xbus_status & CDST_DISC) &&
534 (cd_->xbus_status & CDST_SPIN))
535 {
536 cd_->status_len = 8; //CMD+status+DRVSTAT
537 cd_->status[0] = CDROM_CMD_READ_CAPACITY;
538 cd_->status[1] = 0;
539 cd_->status[2] = cd_->disc.msf_total.minutes;
540 cd_->status[3] = cd_->disc.msf_total.seconds;
541 cd_->status[4] = cd_->disc.msf_total.frames;
542 cd_->status[5] = 0x00;
543 cd_->status[6] = 0x00;
544 cd_->xbus_status |= CDST_RDY;
545 cd_->status[7] = cd_->xbus_status;
546 cd_->MEI_status = MEI_CDROM_no_error;
547 cd_->poll |= POLST;
548 }
549 else
550 {
551 cd_->xbus_status |= CDST_ERRO;
552 cd_->xbus_status &= ~CDST_RDY;
553 cd_->status_len = 2; //CMD+status+DRVSTAT
554 cd_->status[0] = CDROM_CMD_READ_CAPACITY;
555 cd_->status[1] = cd_->xbus_status;
556 cd_->poll |= POLST;
557 cd_->MEI_status = MEI_CDROM_recv_ecc;
558 }
559 break;
560
561 /*
562 read header
563 not used in opera
564 86 00 ll-bb-aa 00 00.
565 86 02 mm-ss-ff 00 00.
566 status 8 bytes
567 data?
568 */
569 case CDROM_CMD_READ_HEADER:
570 break;
571
572 /*
573 read subq
574 opera status request = 10
575 87 fl 00 00 00 00 00
576 fl = 0 "lba"
577 fl = 1 "msf"
578
579 11 00 (if != 00 then break)
580 22 Subq_ctl_adr = swapnibles(_11_)
581 33 Subq_trk = but2bcd(_22_)
582 44 Subq_pnt_idx = byt2bcd(_33_)
583 55 mm run tot
584 66 ss run tot
585 77 ff run tot
586 88 mm run trk
587 99 ss run trk
588 aa ff run trk
589 */
590 case CDROM_CMD_READ_SUBQ:
591 if((cd_->xbus_status & CDST_TRAY) &&
592 (cd_->xbus_status & CDST_DISC) &&
593 (cd_->xbus_status & CDST_SPIN))
594 {
595 cd_->xbus_status |= CDST_RDY;
596 cd_->status_len = 12; /* CMD+status+DRVSTAT */
597 cd_->status[0] = CDROM_CMD_READ_SUBQ;
598 cd_->status[1] = 0; /* disc.msf_total.minutes; minutes */
599 cd_->status[2] = 0; /* disc.msf_total.seconds; seconds */
600 cd_->status[3] = 0; /* disc.msf_total.frames; frames */
601 cd_->status[4] = 0;
602 cd_->status[5] = 0;
603 cd_->status[6] = 0x0;
604 cd_->status[7] = 0x0;
605 cd_->status[8] = 0x0;
606 cd_->status[9] = 0x0;
607 cd_->status[10] = 0x0;
608 cd_->status[11] = cd_->xbus_status;
609 cd_->MEI_status = MEI_CDROM_no_error;
610 cd_->poll |= POLST;
611 }
612 else
613 {
614 cd_->xbus_status |= CDST_ERRO;
615 cd_->xbus_status &= ~CDST_RDY;
616 cd_->status_len = 2; /* CMD+status+DRVSTAT */
617 cd_->status[0] = CDROM_CMD_READ_SUBQ;
618 cd_->status[1] = cd_->xbus_status;
619 cd_->MEI_status = MEI_CDROM_recv_ecc;
620 cd_->poll |= POLST;
621 }
622 break;
623
624 /*
625 read upc
626 not used in opera
627 88 00 ll-bb-aa 00 00
628 88 02 mm-ss-ff 00 00
629 status 20(16) bytes
630 data?
631 */
632 case CDROM_CMD_READ_UPC:
633 break;
634
635 /*
636 read isrc
637 not used in opera
638 89 00 ll-bb-aa 00 00
639 89 02 mm-ss-ff 00 00
640 status 16(15) bytes
641 data?
642 */
643 case CDROM_CMD_READ_ISRC:
644 break;
645
646 /*
647 read disc code
648 ignore it yet...
649 opera status request = 10
650 8a 00 00 00 00 00 00
651 status 10 bytes
652 ????? which code???
653 */
654 case CDROM_CMD_READ_DISC_CODE:
655 if((cd_->xbus_status & CDST_TRAY) &&
656 (cd_->xbus_status & CDST_DISC) &&
657 (cd_->xbus_status & CDST_SPIN))
658 {
659 cd_->xbus_status |= CDST_RDY;
660 cd_->status_len = 12; /* CMD+status+DRVSTAT */
661 cd_->status[0] = CDROM_CMD_READ_DISC_CODE;
662 cd_->status[1] = 0; /* disc.msf_total.minutes; */
663 cd_->status[2] = 0; /* disc.msf_total.seconds; */
664 cd_->status[3] = 0; /* disc.msf_total.frames; */
665 cd_->status[4] = 0;
666 cd_->status[5] = 0;
667 cd_->status[6] = 0x00;
668 cd_->status[7] = 0x00;
669 cd_->status[8] = 0x00;
670 cd_->status[9] = 0x00;
671 cd_->status[10] = 0x00;
672 cd_->status[11] = cd_->xbus_status;
673 cd_->MEI_status = MEI_CDROM_no_error;
674 cd_->poll |= POLST;
675 }
676 else
677 {
678 cd_->xbus_status |= CDST_ERRO;
679 cd_->xbus_status &= ~CDST_RDY;
680 cd_->status_len = 2; /* CMD+status+DRVSTAT */
681 cd_->status[0] = CDROM_CMD_READ_DISC_CODE;
682 cd_->status[1] = cd_->xbus_status;
683 cd_->MEI_status = MEI_CDROM_recv_ecc;
684 cd_->poll |= POLST;
685 }
686 break;
687
688 /*
689 MKE !!!v the same
690 read disc information
691 opera status request = 6
692 8b 00 00 00 00 00 00
693 status 8(6) bytes
694 read the toc descritor
695 00 11 22 33 44 55 XS
696 00 = 8b // command code
697 11 = Disc ID // XA_BYTE
698 22 = 1st track#
699 33 = last track#
700 44 = minutes
701 55 = seconds
702 66 = frames
703 */
704 case CDROM_CMD_READ_DISC_INFO:
705 if((cd_->xbus_status & CDST_TRAY) &&
706 (cd_->xbus_status & CDST_DISC) &&
707 (cd_->xbus_status & CDST_SPIN))
708 {
709 cd_->xbus_status |= CDST_RDY;
710 cd_->status_len = 8;
711 cd_->status[0] = CDROM_CMD_READ_DISC_INFO;
712 cd_->status[1] = cd_->disc.disc_id;
713 cd_->status[2] = cd_->disc.track_first;
714 cd_->status[3] = cd_->disc.track_last;
715 cd_->status[4] = cd_->disc.msf_total.minutes;
716 cd_->status[5] = cd_->disc.msf_total.seconds;
717 cd_->status[6] = cd_->disc.msf_total.frames;
718 cd_->status[7] = cd_->xbus_status;
719 cd_->MEI_status = MEI_CDROM_no_error;
720 }
721 else
722 {
723 cd_->status_len = 2;
724 cd_->xbus_status |= CDST_ERRO;
725 cd_->status[0] = CDROM_CMD_READ_DISC_INFO;
726 cd_->status[1] = cd_->xbus_status;
727 cd_->MEI_status = MEI_CDROM_recv_ecc;
728 }
729
730 cd_->poll |= POLST;
731 break;
732
733 /*
734 read toc
735 MKE !!!v the same
736 opera status request = 8
737 8c fl nn 00 00 00 00 // reads nn entry
738 status 12(8) bytes
739 00 11 22 33 44 55 66 77 XS
740 00 = 8c
741 11 = reserved0; //NIX BYTE
742 22 = addressAndControl; //TOCENT_CTL_ADR=swapnibbles(11) ??? UPCCTLADR=_10_ | x02 (_11_ &F0 = _10_)
743 33 = trackNumber; //TOC_ENT NUMBER
744 44 = reserved3; //TOC_ENT FORMAT
745 55 = minutes; //TOC_ENT ADRESS == 0x00445566
746 66 = seconds;
747 77 = frames;
748 88 = reserved7;
749 */
750 case CDROM_CMD_READ_TOC:
751 if((cd_->xbus_status & CDST_TRAY) &&
752 (cd_->xbus_status & CDST_DISC) &&
753 (cd_->xbus_status & CDST_SPIN))
754 {
755 toc_entry_t *toc = &cd_->disc.disc_toc[cd_->cmd[2]];
756
757 cd_->xbus_status |= CDST_RDY;
758 cd_->status_len = 10; /* CMD+status+DRVSTAT */
759 cd_->status[0] = CDROM_CMD_READ_TOC;
760 cd_->status[1] = toc->res0;
761 cd_->status[2] = toc->CDCTL;
762 cd_->status[3] = toc->track_number;
763 cd_->status[4] = toc->res1;
764 cd_->status[5] = toc->minutes;
765 cd_->status[6] = toc->seconds;
766 cd_->status[7] = toc->frames;
767 cd_->status[8] = toc->res2;
768 cd_->status[9] = cd_->xbus_status;
769 cd_->MEI_status = MEI_CDROM_no_error;
770 }
771 else
772 {
773 cd_->status_len = 2;
774 cd_->xbus_status |= CDST_ERRO;
775 cd_->status[0] = CDROM_CMD_READ_TOC;
776 cd_->status[1] = cd_->xbus_status;
777 cd_->MEI_status = MEI_CDROM_recv_ecc;
778 }
779
780 cd_->poll |= POLST;
781 break;
782
783 /*
784 read session information
785 MKE !!!v the same
786 opera status request = 6
787 status 8(6)
788 00 11 22 33 44 55 XS ==
789 00 = 8d
790 11 = valid; // 0x80 = MULTISESS
791 22 = minutes;
792 33 = seconds;
793 44 = frames;
794 55 = rfu1; //ignore
795 66 = rfu2 //ignore
796 */
797 case CDROM_CMD_READ_SESSION_INFO:
798 if((cd_->xbus_status & CDST_TRAY) &&
799 (cd_->xbus_status & CDST_DISC))
800 {
801 cd_->xbus_status |= CDST_RDY;
802 cd_->status_len = 8; /* CMD+status+DRVSTAT */
803 cd_->status[0] = CDROM_CMD_READ_SESSION_INFO;
804 cd_->status[1] = 0x00;
805 cd_->status[2] = cd_->disc.msf_session.minutes;
806 cd_->status[3] = cd_->disc.msf_session.seconds;
807 cd_->status[4] = cd_->disc.msf_session.frames;
808 cd_->status[5] = 0x00;
809 cd_->status[6] = 0x00;
810 cd_->status[7] = cd_->xbus_status;
811 cd_->MEI_status = MEI_CDROM_no_error;
812 }
813 else
814 {
815 cd_->status_len = 2; //CMD+status+DRVSTAT
816 cd_->xbus_status |= CDST_ERRO;
817 cd_->status[0] = CDROM_CMD_READ_SESSION_INFO;
818 cd_->status[1] = cd_->xbus_status;
819 cd_->MEI_status = MEI_CDROM_recv_ecc;
820 }
821
822 cd_->poll |= POLST;
823 break;
824
825 /* read device driver */
826 case CDROM_CMD_READ_DEVICE_DRIVER:
827 break;
828
829 /* ????? */
830 case CDROM_CMD_UNKNOWN_0x93:
831 if((cd_->xbus_status & CDST_TRAY) &&
832 (cd_->xbus_status & CDST_DISC))
833 {
834 cd_->xbus_status |= CDST_RDY;
835 }
836 else
837 {
838 cd_->xbus_status |= CDST_ERRO;
839 cd_->xbus_status |= CDST_RDY;
840 }
841
842 cd_->status_len = 4;
843 cd_->status[0] = 0x0;
844 cd_->status[1] = 0x0;
845 cd_->status[2] = 0x0;
846 cd_->status[3] = cd_->xbus_status;
847
848 cd_->poll |= POLST;
849 break;
850
851 /* error: shouldn't happen */
852 default:
853 break;
854 }
855 }
856
857 void
opera_cdrom_send_cmd(cdrom_device_t * cd_,uint8_t val_)858 opera_cdrom_send_cmd(cdrom_device_t *cd_,
859 uint8_t val_)
860 {
861 if(cd_->cmd_idx < 7)
862 cd_->cmd[cd_->cmd_idx++] = (uint8_t)val_;
863
864 if((cd_->cmd_idx >= 7) || (cd_->cmd[0] == 0x08))
865 {
866 opera_cdrom_do_cmd(cd_);
867 cd_->cmd_idx = 0;
868 }
869 }
870
871 int
opera_cdrom_test_fiq(cdrom_device_t * cd_)872 opera_cdrom_test_fiq(cdrom_device_t *cd_)
873 {
874 return (((cd_->poll & POLST) && (cd_->poll & POLSTMASK)) ||
875 ((cd_->poll & POLDT) && (cd_->poll & POLDTMASK)));
876 }
877
878 void
opera_cdrom_set_poll(cdrom_device_t * cd_,uint32_t val_)879 opera_cdrom_set_poll(cdrom_device_t *cd_,
880 uint32_t val_)
881 {
882 cd_->poll = ((cd_->poll & 0xF0) | (val_ & 0x0F));
883 }
884
885 uint8_t
opera_cdrom_fifo_get_data(cdrom_device_t * cd_)886 opera_cdrom_fifo_get_data(cdrom_device_t *cd_)
887 {
888 uint8_t rv;
889
890 rv = 0;
891 if(cd_->data_len > 0)
892 {
893 rv = cd_->data[cd_->data_idx];
894 cd_->data_idx++;
895 cd_->data_len--;
896
897 if(cd_->data_len == 0)
898 {
899 cd_->data_idx = 0;
900 if(cd_->blocks_requested)
901 {
902 CDROM_SET_SECTOR(cd_->current_sector++);
903 CDROM_READ_SECTOR(cd_->data);
904 cd_->data_len = REQSIZE;
905 cd_->blocks_requested--;
906 }
907 else
908 {
909 cd_->poll &= ~POLDT;
910 cd_->blocks_requested = 0;
911 cd_->data_len = 0;
912 cd_->data_idx = 0;
913 }
914 }
915 }
916
917 return rv;
918 }
919