/[projet1]/public/oric/hardware/cumulus/fw/179X.c
Defence Force logotype

Contents of /public/oric/hardware/cumulus/fw/179X.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 423 - (show annotations)
Mon Jan 24 12:19:33 2011 UTC (9 years, 2 months ago) by retromaster
File MIME type: text/plain
File size: 23474 byte(s)
Initial add of 18F46K20 firmware sources.
1 /* Cumulus 18F46K20 Firmware
2 * WD179X Simulation.
3 * Copyright 2010 Retromaster.
4 *
5 * This file is part of Cumulus Firmware.
6 *
7 * Cumulus Firmware is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License,
10 * or any later version.
11 *
12 * Cumulus Firmware is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Cumulus Firmware. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 /* TODO:
22 *
23 * 1. Verify flag for type I commands.
24 * 5. Motor step rate.
25 * 6. Interrupt request.
26 * 7. Old type DSK image.
27 * 8. Head load delay?
28 * 9. FM mode.
29 * 10. CRC Checks?
30 * 11. m Flag multiple operations check.
31 * 13. Type III.
32 */
33
34 #include "delays.h"
35
36 #include "global.h"
37
38 #include "179X.h"
39 #include "6610.h"
40 #include "sd-mmc.h"
41 #include "ui.h"
42
43 extern uint8_t fat32_sector_buffer[512];
44
45 #define WD179X_DEBUG
46 //#define WD179X_CRC_CHECK
47
48 #define WaitClockCycle Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop();
49
50 #pragma romdata
51 // DSK Signatures.
52 static rom char str_ORICDISK[] = "ORICDISK";
53 static rom char str_MFM_DISK[] = "MFM_DISK";
54
55 // Sector header.
56 static rom uint8_t sector_header[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xA1, 0xA1, 0xFB };
57
58 #include "CRC.h"
59
60 #pragma udata sector_buffer_section
61 static uint8_t sector_buffer[1024];
62
63 #pragma udata wd179x_data_section
64
65 static uint8_t command; // Command being currently executed.
66 static drive_state* drive; // Drive being currently accessed.
67 static uint8_t drive_changed; // Previous command was issued to another drive.
68
69 drive_state wd179x_drive[4];
70
71 #define CheckReadTrackEnd() if (drive->track_position == 6250) if (!image_track_seek()) { sd_io_error(); return 0; }
72 #define CheckWriteTrackEnd() if (drive->track_position == 6250) { if (!fat32_file_flush(&drive->image_file)) { sd_io_error(); return 0; } if (!image_track_seek()) { sd_io_error(); return 0; } }
73 #define TrackReadByte(X) if (!fat32_file_get_byte(&drive->image_file, (X))) { sd_io_error(); return 0; }
74 #define TrackWriteByte(X) if (!fat32_file_put_byte(&drive->image_file, (X))) { sd_io_error(); return 0; }
75
76 #pragma code
77 static void sd_io_error(void)
78 {
79 ui_set_status(ui_status_sd_io_error);
80 }
81
82 static void clear_busy_flag(void)
83 {
84 /* TRISD = 0x00; // MD output.
85 PORTD = 0x00;
86 PORTB = 0x06; // MFS = 0, MWE high, MOE high.
87 PORTB = 0x04; // MFS = 0, MWE low, MOE high.
88 WaitClockCycle;
89 PORTB = 0x06; // MFS = 0, MWE high, MOE high.
90 TRISD = 0xFF; // MD back to input.*/
91 }
92
93 static void generate_interrupt_request(void)
94 {
95 /*if (command == 0xD8)
96 PORTEbits.RE2 = 1;*/
97
98 PORTB = 0x16; // MFS = 2, MWE high, MOE high.
99 PORTB = 0x14; // MFS = 2, MWE low, MOE high.
100 WaitClockCycle;
101 PORTB = 0x16; // MFS = 2, MWE high, MOE high.
102
103 /*PORTEbits.RE2 = 0;*/
104 }
105
106 static void generate_data_request(void)
107 {
108 PORTB = 0x0E; // MFS = 1, MWE high, MOE high.
109 PORTB = 0x0C; // MFS = 1, MWE low, MOE high.
110 WaitClockCycle;
111 PORTB = 0x0E; // MFS = 1, MWE high, MOE high.
112 }
113
114 static void write_data_register(uint8_t data)
115 {
116 TRISD = 0x00; // MD output.
117 PORTD = data;
118 PORTB = 0x1E; // MFS = 3, MWE high, MOE high.
119 PORTB = 0x1C; // MFS = 3, MWE low, MOE high.
120 WaitClockCycle;
121 PORTB = 0x1E; // MFS = 3, MWE high, MOE high.
122 TRISD = 0xFF; // MD back to input.
123 }
124
125 static uint8_t read_data_register(void)
126 {
127 uint8_t data;
128
129 PORTB = 0x1A; // MFS = 3, MWE high, MOE low.
130 Nop();
131 data = PORTD;
132 PORTB = 0x1E; // MFS = 3, MWE high, MOE high.
133
134 return data;
135 }
136
137 static int8_t read_track_register(void)
138 {
139 int8_t track;
140
141 PORTB = 0x0A; // MFS = 1, MWE high, MOE low.
142 Nop();
143 track = PORTD;
144 PORTB = 0x0E; // MFS = 1, MWE high, MOE high.
145
146 return track;
147 }
148
149 static void write_track_register(uint8_t track)
150 {
151 TRISD = 0x00; // MD output.
152 PORTD = track;
153 PORTB = 0x2E; // MFS = 5, MWE high, MOE high.
154 PORTB = 0x2C; // MFS = 5, MWE low, MOE high.
155 WaitClockCycle;
156 PORTB = 0x2E; // MFS = 5, MWE high, MOE high.
157 TRISD = 0xFF; // MD back to input.
158 }
159
160 static uint8_t read_sector_register(void)
161 {
162 uint8_t sector;
163
164 PORTB = 0x12; // MFS = 2, MWE high, MOE low.
165 Nop();
166 sector = PORTD;
167 PORTB = 0x16; // MFS = 2, MWE high, MOE high.
168
169 return sector;
170 }
171
172 static void write_sector_register(uint8_t sector)
173 {
174 TRISD = 0x00; // MD output.
175 PORTD = sector;
176 PORTB = 0x06; // MFS = 0, MWE high, MOE high.
177 PORTB = 0x04; // MFS = 0, MWE low, MOE high.
178 WaitClockCycle;
179 PORTB = 0x06; // MFS = 0, MWE high, MOE high.
180 TRISD = 0xFF; // MD back to input.
181 }
182
183 static void write_status_register(uint8_t status)
184 {
185 #ifdef WD179X_DEBUG
186 //n6610_debug((const far rom char*) "Status: ", status);
187 #endif
188
189 TRISD = 0x00; // MD output.
190 PORTD = status;
191 PORTB = 0x26; // MFS = 4, MWE high, MOE high.
192 PORTB = 0x24; // MFS = 4, MWE low, MOE high.
193 WaitClockCycle;
194 PORTB = 0x26; // MFS = 4, MWE high, MOE high.
195 TRISD = 0xFF; // MD back to input.
196 }
197
198 static void wait_head_step(void)
199 {
200 //IMPLEMENTME!
201 }
202
203 static void head_step_out(void)
204 {
205 drive->track --;
206 if (drive->track < 0)
207 drive->track = 0;
208 if (drive->track == 0)
209 drive->type_I_status |= 0x04;
210
211 // Update display.
212 ui_update_track(drive);
213 }
214
215 static void head_step_in(void)
216 {
217 drive->track ++;
218 if (drive->track > 83) // Hard stop.
219 drive->track = 83;
220 drive->type_I_status &= 0xFB;
221
222 // Update display.
223 ui_update_track(drive);
224 }
225
226 static void step_out(void)
227 {
228 wait_head_step();
229 head_step_out();
230 write_status_register(drive->type_I_status);
231
232 // Update track register if requested.
233 if (command & 0x10)
234 {
235 int8_t track;
236
237 track = read_track_register();
238 track --;
239 if (track < 0)
240 track = 0;
241 write_track_register(track);
242 }
243 }
244
245 static void step_in(void)
246 {
247 wait_head_step();
248 head_step_in();
249 write_status_register(drive->type_I_status);
250
251 // Update track register if requested.
252 if (command & 0x10)
253 {
254 int8_t track;
255
256 track = read_track_register();
257 track ++; // No hard stop (?)
258 write_track_register(track);
259 }
260 }
261
262 static void restore(void)
263 {
264 ui_log_command((const far rom char*) "Restore", 0, 0, 0);
265
266 while (drive->track)
267 {
268 wait_head_step();
269 head_step_out();
270 write_status_register(drive->type_I_status);
271 }
272
273 write_track_register(0);
274 }
275
276 static void seek(void)
277 {
278 int8_t track;
279 int8_t data;
280
281 track = read_track_register();
282 data = read_data_register();
283
284 ui_log_command((const far rom char*) "Seek", track, data, 0);
285
286 do
287 {
288 wait_head_step();
289
290 track = read_track_register();
291 data = read_data_register();
292
293 if (track < data)
294 {
295 track ++;
296 head_step_in();
297 }
298 else if (track > data)
299 {
300 track --;
301 head_step_out();
302 }
303 write_track_register(track);
304 write_status_register(drive->type_I_status);
305 }
306 while (track != data);
307 }
308
309 static void wait_for_next_byte(void)
310 {
311 // Wait for ~32us.
312 /*Delay10TCYx(3);
313 Nop();
314 Nop();*/
315
316 Delay10TCYx(19);
317 }
318
319 static uint8_t sample_side(void)
320 {
321 uint8_t side_match;
322 side_match = 1;
323
324 // Sample side input.
325 if (PORTAbits.RA2 == 1)
326 {
327 if (drive->side == 0)
328 side_match = 0;
329 drive->side = 1;
330 }
331 else
332 {
333 if (drive->side == 1)
334 side_match = 0;
335 drive->side = 0;
336 }
337
338 return side_match;
339 }
340
341 static uint8_t needs_reseek(void)
342 {
343 if (!sample_side())
344 return 1;
345
346 if (drive_changed)
347 return 1;
348
349 return (fat32_sector_buffer_owner != &(drive->image_file));
350 }
351
352 static void sample_DSEL(void)
353 {
354 uint8_t drive_number;
355
356 /* Sample DSEL lines */
357 drive_number = 0;
358 if (PORTAbits.RA0 == 1)
359 drive_number ++;
360 if (PORTAbits.RA1 == 1)
361 drive_number += 2;
362
363 /* Find out if the drive has changed */
364 if (drive != 0)
365 drive_changed = (drive->number != drive_number);
366 else
367 drive_changed = 1;
368
369 /* Set active drive */
370 drive = &wd179x_drive[drive_number];
371 }
372
373 static uint8_t image_track_seek(void)
374 {
375 uint16_t block;
376
377 // Calculate starting block.
378 if (drive->image_geometry == IMAGE_GEO_TRACK_FIRST)
379 block = 1 + ((uint16_t) (drive->track + drive->side * drive->image_tracks)) * 25;
380 else
381 block = 1 + ((uint16_t) (drive->track * drive->image_sides + drive->side)) * 25;
382
383 drive->track_position = 0;
384 return fat32_file_seek(&drive->image_file, (((uint32_t) block) << 8));
385 }
386
387 static void handle_type_I(void)
388 {
389 // Set status for a type I command.
390 write_status_register(drive->type_I_status);
391
392 // Further decode command.
393 if (command & 0x40)
394 {
395 if (command & 0x02)
396 // Step-out.
397 step_out();
398 else
399 // Step-in.
400 step_in();
401 }
402 else if (command & 0x10)
403 seek();
404 else
405 restore();
406
407 // These commands cannot fail ATM.
408 ui_set_status(ui_status_ok);
409
410 // Seek in image file. //?
411 image_track_seek();
412
413 // IRQ.
414 generate_interrupt_request();
415 }
416
417 static uint8_t handle_read_sector(void)
418 {
419 uint8_t i;
420 uint16_t crc;
421 uint8_t* pos;
422 uint16_t cnt;
423 uint8_t* buf;
424 uint8_t byte;
425 uint8_t track;
426 uint8_t sector;
427 uint32_t lba;
428
429 // Update status?
430 //write_status_register(0x0);
431
432 // Read track and sector registers for verification.
433 track = read_track_register();
434 sector = read_sector_register();
435
436 if (needs_reseek())
437 if (!image_track_seek())
438 {
439 sd_io_error();
440 return 0;
441 }
442
443 ui_log_command((const far rom char*) "Read Sector", drive->side, track, sector);
444
445 if (drive->image_type == IMAGE_DSK_OLD)
446 {
447 /* IMPLEMENTME! */
448 }
449
450 if (drive->image_type == IMAGE_DSK_MFM)
451 {
452 // Due to the structure of DSK images, we can deal in 256 byte blocks.
453 uint8_t byte;
454 uint8_t idf;
455 uint8_t max_idf;
456 uint8_t df;
457 uint16_t length;
458 uint16_t bytes_left;
459
460 idf = 0;
461 max_idf = 0;
462 bytes_left = 6250;
463 while (1)
464 {
465 //n6610_debug_message((const far rom char*) "Searching ID Field");
466
467 idf = 0;
468 while (bytes_left)
469 {
470 CheckReadTrackEnd();
471 TrackReadByte(&byte);
472 bytes_left --;
473 drive->track_position ++;
474
475 if (idf > max_idf)
476 max_idf = idf;
477
478 if (idf < 3)
479 if (byte == 0xA1)
480 idf ++;
481 else
482 idf = 0;
483 else if (idf == 3)
484 if (byte == 0xFE)
485 idf ++;
486 else
487 idf = 0;
488 else if (idf == 4)
489 {
490 max_idf = byte;
491 if (byte == track)
492 idf ++;
493 else
494 idf = 0;
495 }
496 else if (idf == 5)
497 {
498 if (command & 0x02)
499 {
500 if (((command >> 3) & 0x01) == drive->side)
501 idf ++;
502 else
503 idf = 0;
504 }
505 else
506 idf ++;
507 }
508 else if (idf == 6)
509 {
510 if (byte == sector)
511 idf ++;
512 else
513 idf = 0;
514 }
515 else if (idf == 7)
516 {
517 if (byte < 4)
518 {
519 length = ((uint16_t) 128) << byte;
520 idf ++;
521
522 // We have a complete ID Field.
523 break;
524 }
525 else
526 idf = 0;
527 }
528 else
529 idf = 0;
530 }
531
532 if (idf != 8)
533 {
534 ui_set_status(ui_status_rnf);
535 ui_log_status(0x10);
536 write_status_register(0x10);
537 break;
538 }
539
540 df = 0;
541 i = 43;
542 while (bytes_left && i)
543 {
544 CheckReadTrackEnd();
545 TrackReadByte(&byte);
546 bytes_left --;
547 drive->track_position ++;
548
549 if (df < 3)
550 if (byte == 0xA1)
551 df ++;
552 else
553 df = 0;
554 else if (df == 3)
555 if (byte == 0xFB)
556 {
557 df ++;
558
559 // We have a complete Data Field Header.
560 break;
561 }
562 else
563 df = 0;
564 else
565 df = 0;
566 }
567
568 if (df != 4)
569 {
570 // Could not find a DAM within range, keep searching.
571 continue;
572 }
573
574 // Stream the whole data field out of the data bus.
575 pos = sector_buffer;
576 cnt = length;
577 crc = 0xE295; /* Initialize with A1A1A1FB */
578
579 while (cnt)
580 {
581 // Read data byte.
582 CheckReadTrackEnd();
583 TrackReadByte(&byte);
584
585 *pos = byte;
586 crc = (crc << 8) ^ crc_table[(crc >> 8) ^ byte];
587
588 pos ++;
589 cnt --;
590 drive->track_position ++;
591 }
592
593 pos = sector_buffer;
594 cnt = length;
595 while (cnt)
596 {
597 write_data_register(*pos);
598 generate_data_request();
599 wait_for_next_byte();
600 cnt --;
601 pos ++;
602 }
603
604 // Check CRC.
605 CheckReadTrackEnd();
606 TrackReadByte(&byte);
607 drive->track_position ++;
608
609 #ifdef WD179X_CHECK_CRC
610 if (byte != (crc >> 8))
611 {
612 ui_set_status(ui_status_crc_error);
613 ui_log_status(0x08);
614 write_status_register(0x08);
615 break;
616 }
617 #endif
618
619 CheckReadTrackEnd();
620 TrackReadByte(&byte);
621 drive->track_position ++;
622
623 #ifdef WD179X_CHECK_CRC
624 if (byte != (crc & 0xFF))
625 {
626 ui_set_status(ui_status_crc_error);
627 ui_log_status(0x08);
628 write_status_register(0x08);
629 break;
630 }
631 #endif
632
633 // Multiple sectors?
634 if (command & 0x10)
635 {
636 sector ++;
637 // Update sector register?
638 }
639 else
640 {
641 ui_set_status(ui_status_ok);
642 write_status_register(0x0);
643 break;
644 }
645
646 bytes_left = 6250;
647 }
648 }
649
650 return 1;
651 }
652
653 static uint8_t handle_write_sector(void)
654 {
655 uint8_t i;
656 uint16_t crc;
657 uint8_t* pos;
658 uint16_t cnt;
659 uint8_t* buf;
660 uint8_t byte;
661 uint8_t track;
662 uint8_t sector;
663 uint32_t lba;
664
665 /* Check for write protect */
666 if (drive->type_I_status & 0x40)
667 {
668 ui_set_status(ui_status_write_protect);
669 /* FIXME! */
670 ui_log_status(0x60);
671 write_status_register(0x60);
672 return 1;
673 }
674
675 // Read track and sector registers for verification.
676 track = read_track_register();
677 sector = read_sector_register();
678
679 if (needs_reseek())
680 if (!image_track_seek())
681 {
682 sd_io_error();
683 return 0;
684 }
685
686 ui_log_command((const far rom char*) "Write Sector", drive->side, track, sector);
687
688 if (drive->image_type == IMAGE_DSK_OLD)
689 {
690
691 }
692
693 if (drive->image_type == IMAGE_DSK_MFM)
694 {
695 // Due to the structure of DSK images, we can deal in 256 byte blocks.
696 uint8_t byte;
697 uint8_t idf;
698 uint8_t max_idf;
699 uint8_t df;
700 uint16_t length;
701 uint16_t bytes_left;
702
703 idf = 0;
704 max_idf = 0;
705 bytes_left = 6250;
706 while (1)
707 {
708 //n6610_debug_message((const far rom char*) "Searching ID Field");
709
710 idf = 0;
711 while (bytes_left)
712 {
713 CheckReadTrackEnd();
714 TrackReadByte(&byte);
715 bytes_left --;
716 drive->track_position ++;
717
718 if (idf > max_idf)
719 max_idf = idf;
720
721 if (idf < 3)
722 if (byte == 0xA1)
723 idf ++;
724 else
725 idf = 0;
726 else if (idf == 3)
727 if (byte == 0xFE)
728 idf ++;
729 else
730 idf = 0;
731 else if (idf == 4)
732 {
733 max_idf = byte;
734 if (byte == track)
735 idf ++;
736 else
737 idf = 0;
738 }
739 else if (idf == 5)
740 {
741 if (command & 0x02)
742 {
743 if (((command >> 3) & 0x01) == drive->side)
744 idf ++;
745 else
746 idf = 0;
747 }
748 else
749 idf ++;
750 }
751 else if (idf == 6)
752 {
753 if (byte == sector)
754 idf ++;
755 else
756 idf = 0;
757 }
758 else if (idf == 7)
759 {
760 if (byte < 4)
761 {
762 length = ((uint16_t) 128) << byte;
763 idf ++;
764
765 // We have a complete ID Field.
766 break;
767 }
768 else
769 idf = 0;
770 }
771 else
772 idf = 0;
773 }
774
775 if (idf != 8)
776 {
777 ui_set_status(ui_status_rnf);
778 ui_log_status(0x10);
779 write_status_register(0x10);
780 break;
781 }
782
783 n6610_set_font(FONT_6X8);
784
785 // Generate DRQ.
786 generate_data_request();
787
788 // Count off 22 bytes.
789 for (i = 0; i < 22; i ++)
790 {
791 // Advance.
792 CheckReadTrackEnd();
793 TrackReadByte(&byte);
794 drive->track_position ++;
795
796 wait_for_next_byte();
797 }
798
799 /* TODO: Check if DRQ's have been serviced */
800 // Buffer the data from the CPU and calculate CRC.
801 pos = sector_buffer;
802 cnt = length;
803 crc = 0xE295;
804 while (cnt)
805 {
806 *pos = byte = read_data_register();
807 crc = (crc << 8) ^ crc_table[(crc >> 8) ^ byte];
808 generate_data_request();
809 wait_for_next_byte();
810 cnt --;
811 pos ++;
812 }
813
814 /* At this point, we can actually signal end of command to the CPU.
815 * The actual write to SD Card may be deferred.
816 */
817
818 /* Write sector header to SD Card.
819 * 6 zero bytes followed by DAM.
820 */
821 for (i = 0; i < 10; i ++)
822 {
823 // Write
824 CheckWriteTrackEnd();
825 TrackWriteByte(sector_header[i]);
826 drive->track_position ++;
827 }
828
829 /* Now write data bytes to SD Card */
830 cnt = length;
831 pos = sector_buffer;
832 while (cnt)
833 {
834 // Write data byte.
835 CheckWriteTrackEnd();
836 TrackWriteByte(*pos);
837 pos ++;
838 cnt --;
839 drive->track_position ++;
840 }
841
842 // Write CRC bytes.
843 CheckWriteTrackEnd();
844 TrackWriteByte(crc >> 8);
845 drive->track_position ++;
846
847 CheckWriteTrackEnd();
848 TrackWriteByte(crc & 0xFF);
849 drive->track_position ++;
850
851 fat32_file_flush(&drive->image_file);
852
853 // Multiple sectors?
854 if (command & 0x10)
855 {
856 sector ++;
857 // Update sector register?
858 }
859 else
860 {
861 ui_set_status(ui_status_ok);
862 write_status_register(0x0);
863 break;
864 }
865
866 bytes_left = 6250;
867 }
868 }
869
870 return 1;
871 }
872
873 static uint8_t handle_type_II(void)
874 {
875 uint8_t result;
876
877 if (command & 0x20)
878 {
879 // Ready?
880 if (drive->type_I_status & 0x80)
881 {
882 ui_set_status(ui_status_not_ready);
883 ui_log_status(0x80);
884 write_status_register(0x80);
885 result = 1;
886 }
887 else if (!handle_write_sector())
888 result = 0;
889 else
890 result = 1;
891 }
892 else
893 {
894 // Ready?
895 if (drive->type_I_status & 0x80)
896 {
897 ui_set_status(ui_status_not_ready);
898 ui_log_status(0x80);
899 write_status_register(0x80);
900 result = 1;
901 }
902 else if (!handle_read_sector())
903 result = 0;
904 else
905 result = 1;
906 }
907
908 // IRQ.
909 generate_interrupt_request();
910 return result;
911 }
912
913 static uint8_t handle_read_address(void)
914 {
915 uint8_t i;
916 uint8_t byte;
917 uint8_t track;
918 uint32_t lba;
919
920 // Update status?
921 // write_status_register(0x0);
922 ui_log_command((const far rom char*) "Read Address", 0, 0, 0);
923
924 if (drive->image_type == IMAGE_DSK_OLD)
925 {
926
927 }
928
929 if (drive->image_type == IMAGE_DSK_MFM)
930 {
931 // Due to the structure of DSK images, we can deal in 256 byte blocks.
932 uint8_t byte;
933 uint8_t idf;
934 uint16_t length;
935 uint16_t side;
936 uint16_t block;
937 uint16_t bytes_left;
938
939 if (needs_reseek())
940 if (!image_track_seek())
941 {
942 sd_io_error();
943 return 0;
944 }
945
946 idf = 0;
947 bytes_left = 6250;
948 while (bytes_left)
949 {
950
951 CheckReadTrackEnd();
952 TrackReadByte(&byte);
953 bytes_left --;
954 drive->track_position ++;
955
956 if (idf < 3)
957 if (byte == 0xA1)
958 idf ++;
959 else
960 idf = 0;
961 else if (idf == 3)
962 if (byte == 0xFE)
963 {
964 idf ++;
965
966 // We have a complete IDAM.
967 break;
968 }
969 else
970 idf = 0;
971 }
972
973 if (idf != 4)
974 {
975 ui_set_status(ui_status_rnf);
976 ui_log_status(0x10);
977 write_status_register(0x10);
978 return 1;
979 }
980
981 // Stream the address field out of the data bus.
982 length = 6;
983 while (bytes_left && length)
984 {
985 // Read data byte.
986 CheckReadTrackEnd();
987 TrackReadByte(&byte);
988 bytes_left --;
989 length --;
990 drive->track_position ++;
991
992 if (length == 5)
993 track = byte;
994
995 write_data_register(byte);
996 generate_data_request();
997 wait_for_next_byte();
998 }
999
1000 //n6610_debug_message((const far rom char*) "Streaming Done");
1001 ui_log_command((const far rom char*) "Track", track, 0, 0);
1002
1003 ui_set_status(ui_status_ok);
1004 write_sector_register(track);
1005 write_status_register(0x0);
1006 }
1007
1008 return 1;
1009 }
1010
1011 static uint8_t handle_type_III(void)
1012 {
1013 uint8_t result;
1014
1015 if ((command & 0x30) == 0x00)
1016 {
1017 // Read Address.
1018
1019 // Ready?
1020 if (drive->type_I_status & 0x80)
1021 {
1022 ui_set_status(ui_status_not_ready);
1023 ui_log_status(0x80);
1024 write_status_register(0x80);
1025 result = 1;
1026 }
1027 else if (!handle_read_address())
1028 {
1029 // An SD Card error has occurred.
1030 // How to setup errors?
1031 result = 0;
1032 }
1033 else
1034 result = 1;
1035 }
1036
1037 // IRQ.
1038 generate_interrupt_request();
1039 return result;
1040 }
1041
1042 static void handle_type_IV(void)
1043 {
1044 //n6610_debug_message((const far rom char*) "Type IV");
1045 }
1046
1047 void wd179X_handle_command_request(void)
1048 {
1049 // Read the command register.
1050 PORTB = 0x02; // MFS = 0, MWE high, MOE low.
1051 Nop();
1052 command = PORTD;
1053 PORTB = 0x06; // MFS = 0, MWE high, MOE high.
1054
1055 // Clear command request.
1056 PORTB = 0x34; // MFS = 6, MWE low, MOE high.
1057 WaitClockCycle;
1058 PORTB = 0x36; // MFS = 6, MWE high, MOE high.
1059
1060 // Sample DSEL.
1061 sample_DSEL();
1062
1063 // Decode command type.
1064 if (command & 0x80)
1065 if (command & 0x40)
1066 if ((command & 0x30) == 0x10)
1067 handle_type_IV();
1068 else
1069 handle_type_III();
1070 else
1071 handle_type_II();
1072 else
1073 handle_type_I();
1074
1075 clear_busy_flag();
1076 }
1077
1078 uint8_t wd179x_mount_image(uint8_t d, fat32_dir_entry* image)
1079 {
1080 uint8_t i;
1081 uint32_t header_lba;
1082
1083 fat32_file_from_dir_entry(&wd179x_drive[d].image_file, image);
1084 header_lba = fat32_file_get_lba(&wd179x_drive[d].image_file, 0);
1085
1086 /* Read header sector into the sector buffer */
1087 if (!fat32_card_read(header_lba))
1088 {
1089 #ifdef WD179X_DEBUG
1090 n6610_debug_message((const far rom char*) "SD Card Read Error");
1091 #endif
1092
1093 return 0;
1094 }
1095
1096 /* Find out what kind of image it is */
1097 wd179x_drive[d].image_type = IMAGE_NONE;
1098 for (i = 0; i < 8; i ++)
1099 if (fat32_sector_buffer[i] != str_ORICDISK[i])
1100 break;
1101 if (i == 8)
1102 wd179x_drive[d].image_type = IMAGE_DSK_OLD;
1103
1104 for (i = 0; i < 8; i ++)
1105 if (fat32_sector_buffer[i] != str_MFM_DISK[i])
1106 break;
1107 if (i == 8)
1108 wd179x_drive[d].image_type = IMAGE_DSK_MFM;
1109
1110 if (wd179x_drive[d].image_type == IMAGE_NONE)
1111 return 0;
1112
1113 if (wd179x_drive[d].image_type == IMAGE_DSK_OLD)
1114 {
1115 // IMPLEMENTME!
1116 return 0;
1117 }
1118
1119 if (wd179x_drive[d].image_type == IMAGE_DSK_MFM)
1120 {
1121 wd179x_drive[d].image_sides = fat32_sector_buffer[8];
1122 wd179x_drive[d].image_tracks = fat32_sector_buffer[12];
1123 wd179x_drive[d].image_geometry = fat32_sector_buffer[16];
1124
1125 /* Sanity checks */
1126 if (wd179x_drive[d].image_sides > 2)
1127 return 0;
1128 if (wd179x_drive[d].image_geometry != 1 && wd179x_drive[d].image_geometry != 2)
1129 return 0;
1130 }
1131
1132 return 1;
1133 }
1134
1135 void wd179x_init(void)
1136 {
1137 uint8_t i;
1138
1139 // PORTD (MD) Input.
1140 TRISEbits.PSPMODE = 0; // PSP off.
1141 TRISD = 0xFF;
1142
1143 // nMCRQ Input, nMOE, nMWE, MFS Output (high)
1144 PORTB = 0xFF;
1145 TRISB = 0x01;
1146
1147 // DSEL, SSEL Input.
1148 TRISAbits.TRISA0 = 1;
1149 TRISAbits.TRISA1 = 1;
1150 TRISAbits.TRISA2 = 1;
1151
1152 // Init drive state.
1153 for (i = 0; i < 4; i ++)
1154 {
1155 wd179x_drive[i].number = i;
1156 wd179x_drive[i].image_type = IMAGE_NONE;
1157 wd179x_drive[i].track = 0;
1158 wd179x_drive[i].side = 0;
1159 wd179x_drive[i].type_I_status = 0x64; // No errors, ready, protected, head loaded, track 0.
1160 }
1161 drive = 0;
1162 drive_changed = 1;
1163 }
1164

  ViewVC Help
Powered by ViewVC 1.1.26