1 // license:GPL-2.0+
2 // copyright-holders:Raphael Nabet
3 /*
4 990_dk.c: emulation of a TI FD800 'Diablo' floppy disk controller
5 controller, for use with any TI990 system (and possibly any system which
6 implements the CRU bus).
7
8 This floppy disk controller supports IBM-format 8" SSSD and DSSD floppies.
9
10 Raphael Nabet 2003
11
12 Rewritten as class
13 Michael Zapf 2014
14
15 TODO: Make it work
16 */
17
18 #include "emu.h"
19
20 #include "990_dk.h"
21
22 /* status bits */
23 enum
24 {
25 status_OP_complete = 1 << 0,
26 status_XFER_ready = 1 << 1,
27 status_drv_not_ready= 1 << 2,
28 status_dat_chk_err = 1 << 3,
29 status_seek_err = 1 << 4,
30 status_invalid_cmd = 1 << 5,
31 status_no_addr_mark = 1 << 6,
32 status_equ_chk_err = 1 << 7,
33 status_ID_chk_err = 1 << 8,
34 status_ID_not_found = 1 << 9,
35 status_ctlr_busy = 1 << 10,
36 status_write_prot = 1 << 11,
37 status_del_sector = 1 << 12,
38 status_interrupt = 1 << 15,
39
40 status_unit_shift = 13
41 };
42
43 DEFINE_DEVICE_TYPE(TI99X_FD800, fd800_legacy_device, "ti99x_fd800", "TI FD800 Diablo floppy disk controller")
44
fd800_legacy_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)45 fd800_legacy_device::fd800_legacy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
46 : device_t(mconfig, TI99X_FD800, tag, owner, clock),
47 m_recv_buf(0), m_stat_reg(0), m_xmit_buf(0), m_cmd_reg(0), m_interrupt_f_f(0),
48 m_int_line(*this), m_buf_pos(0), m_buf_mode(), m_unit(0), m_sector(0)
49 {
50 }
51
set_interrupt_line()52 void fd800_legacy_device::set_interrupt_line()
53 {
54 if ((m_stat_reg & status_interrupt) && ! m_interrupt_f_f)
55 m_int_line(ASSERT_LINE);
56 else
57 m_int_line(CLEAR_LINE);
58 }
59
60
61 #if 0
62 void fd800_legacy_device::unload_proc(device_image_interface &image)
63 {
64 int unit = floppy_get_drive(&image.device());
65
66 m_drv[unit].log_cylinder[0] = m_drv[unit].log_cylinder[1] = -1;
67 }
68
69
70 void fd800_machine_init(void (*interrupt_callback)(running_machine &machine, int state))
71 {
72 int i;
73
74 m_machine = &machine;
75 m_interrupt_callback = interrupt_callback;
76
77 m_stat_reg = 0;
78 m_interrupt_f_f = 1;
79
80 m_buf_pos = 0;
81 m_buf_mode = bm_off;
82
83 for (i=0; i<MAX_FLOPPIES; i++)
84 {
85 m_drv[i].img = dynamic_cast<device_image_interface *>(floppy_get_device(machine, i));
86 m_drv[i].phys_cylinder = -1;
87 m_drv[i].log_cylinder[0] = m_drv[i].log_cylinder[1] = -1;
88 m_drv[i].seclen = 64;
89 floppy_install_unload_proc(&m_drv[i].img->device(), unload_proc);
90 }
91
92 set_interrupt_line();
93 }
94 #endif
95
96 /*
97 Read the first id field that can be found on the floppy disk.
98
99 unit: floppy drive index
100 head: selected head
101 cylinder_id: cylinder ID read
102 sector_id: sector ID read
103
104 Return true if an ID was found
105 */
read_id(int unit,int head,int * cylinder_id,int * sector_id)106 int fd800_legacy_device::read_id(int unit, int head, int *cylinder_id, int *sector_id)
107 {
108 //uint8_t revolution_count;*/
109 // chrn_id id;
110
111 //revolution_count = 0;*/
112
113 /*while (revolution_count < 2)*/
114 /*{*/
115 /* if (m_drv[unit].img->floppy_drive_get_next_id(head, &id))
116 {
117 if (cylinder_id)
118 *cylinder_id = id.C;
119 if (sector_id)
120 *sector_id = id.R;
121 return true;
122 }
123 }*/
124
125 return false;
126 }
127
128 /*
129 Find a sector by id.
130
131 unit: floppy drive index
132 head: selected head
133 sector: sector ID to search
134 data_id: data ID to be used when calling sector read/write functions
135
136 Return true if the given sector ID was found
137 */
find_sector(int unit,int head,int sector,int * data_id)138 int fd800_legacy_device::find_sector(int unit, int head, int sector, int *data_id)
139 {
140 /* uint8_t revolution_count;
141 chrn_id id;
142
143 revolution_count = 0;
144
145 while (revolution_count < 2)
146 {
147 if (m_drv[unit].img->floppy_drive_get_next_id(head, &id))
148 {
149 // compare id
150 if ((id.R == sector) && (id.N == 0))
151 {
152 *data_id = id.data_id;
153 // get ddam status
154 // w->ddam = id.flags & ID_FLAG_DELETED_DATA;
155 return true;
156 }
157 }
158 }
159 */
160 return false;
161 }
162
163 /*
164 Perform seek command
165
166 unit: floppy drive index
167 cylinder: track to seek for
168 head: head for which the seek is performed
169
170 Return false if the seek was successful
171 */
do_seek(int unit,int cylinder,int head)172 int fd800_legacy_device::do_seek(int unit, int cylinder, int head)
173 {
174 /* int retries;
175
176 if (cylinder > 76)
177 {
178 m_stat_reg |= status_invalid_cmd;
179 return true;
180 }
181
182 if (m_drv[unit].img == nullptr || !m_drv[unit].img->exists())
183 {
184 m_stat_reg |= status_drv_not_ready;
185 return true;
186 }
187
188 if (m_drv[unit].log_cylinder[head] == -1)
189 {
190 if (!read_id(unit, head, &m_drv[unit].log_cylinder[head], nullptr))
191 {
192 m_stat_reg |= status_ID_not_found;
193 return true;
194 }
195 }
196
197 if (m_drv[unit].log_cylinder[head] == cylinder)
198 {
199
200 return false;
201 }
202 for (retries=0; retries<10; retries++)
203 {
204 m_drv[unit].img->floppy_drive_seek(cylinder-m_drv[unit].log_cylinder[head]);
205
206 if (m_drv[unit].phys_cylinder != -1)
207 m_drv[unit].phys_cylinder += cylinder-m_drv[unit].log_cylinder[head];
208
209 if (!read_id(unit, head, &m_drv[unit].log_cylinder[head], nullptr))
210 {
211 m_drv[unit].log_cylinder[head] = -1;
212 m_stat_reg |= status_ID_not_found;
213 return true;
214 }
215
216 if (m_drv[unit].log_cylinder[head] == cylinder)
217 {
218
219 return false;
220 }
221 }
222
223 m_stat_reg |= status_seek_err;
224 */
225 return true;
226 }
227
228 /*
229 Perform restore command
230
231 unit: floppy drive index
232
233 Return false if the restore was successful
234 */
do_restore(int unit)235 int fd800_legacy_device::do_restore(int unit)
236 {
237 int seek_complete = 0;
238 /* int seek_count = 0;
239
240 if (!m_drv[unit].img->exists())
241 {
242 m_stat_reg |= status_drv_not_ready;
243 return true;
244 }
245
246
247 while (!(seek_complete = !m_drv[unit].img->floppy_tk00_r()) && (seek_count < 76))
248 {
249 m_drv[unit].img->floppy_drive_seek(-1);
250 seek_count++;
251 }
252 if (! seek_complete)
253 {
254 m_drv[unit].phys_cylinder = -1;
255 m_stat_reg |= status_seek_err;
256 }
257 else
258 {
259 m_drv[unit].phys_cylinder = 0;
260
261 }
262 */
263 return ! seek_complete;
264 }
265
266 /*
267 Perform a read operation for one sector
268 */
do_read()269 void fd800_legacy_device::do_read()
270 {
271 /* int data_id;
272
273 if ((m_sector == 0) || (m_sector > 26))
274 {
275 m_stat_reg |= status_invalid_cmd;
276 return;
277 }
278
279 if (!find_sector(m_unit, m_head, m_sector, &data_id))
280 {
281 m_stat_reg |= status_ID_not_found;
282 return;
283 }
284
285 m_drv[m_unit].img->floppy_drive_read_sector_data(m_head, data_id, m_buf, 128);
286 m_buf_pos = 0;
287 m_buf_mode = bm_read;
288 m_recv_buf = (m_buf[m_buf_pos<<1] << 8) | m_buf[(m_buf_pos<<1)+1];
289
290 m_stat_reg |= status_XFER_ready;
291 m_stat_reg |= status_OP_complete;
292 */
293 }
294
295 /*
296 Perform a write operation for one sector
297 */
do_write()298 void fd800_legacy_device::do_write()
299 {
300 /* int data_id;
301
302 if (m_drv[m_unit].seclen < 64)
303 memset(m_buf+(m_drv[m_unit].seclen<<1), 0, (64-m_drv[m_unit].seclen)<<1);
304
305 if (!find_sector(m_unit, m_head, m_sector, &data_id))
306 {
307 m_stat_reg |= status_ID_not_found;
308 return;
309 }
310
311 m_drv[m_unit].img->floppy_drive_write_sector_data(m_head, data_id, m_buf, 128, m_ddam);
312 m_buf_pos = 0;
313 m_buf_mode = bm_write;
314
315 m_stat_reg |= status_XFER_ready;
316 m_stat_reg |= status_OP_complete;
317 */
318 }
319
320 /*
321 Execute a fdc command
322 */
do_cmd()323 void fd800_legacy_device::do_cmd()
324 {
325 /*
326 int unit;
327 int cylinder;
328 int head;
329 int seclen;
330 int sector;
331
332
333 if (m_buf_mode != bm_off)
334 { // All commands in the midst of read or write are interpreted as Stop
335 unit = (m_cmd_reg >> 10) & 3;
336
337 // reset status
338 m_stat_reg = unit << status_unit_shift;
339
340 m_buf_pos = 0;
341 m_buf_mode = bm_off;
342
343 m_stat_reg |= status_OP_complete;
344
345 m_stat_reg |= status_interrupt;
346 set_interrupt_line();
347
348 return;
349 }
350
351 switch (m_cmd_reg >> 12)
352 {
353 case 0: // select
354 // bits 16-25: 0s
355 // bits 26-27: unit number (0-3)
356 unit = (m_cmd_reg >> 10) & 3;
357
358 // reset status
359 m_stat_reg = unit << status_unit_shift;
360
361 if (!m_drv[unit].img->exists())
362 m_stat_reg |= status_drv_not_ready; // right???
363 else if (m_drv[unit].img->is_readonly())
364 m_stat_reg |= status_write_prot;
365 else
366 m_stat_reg |= status_OP_complete;
367
368 m_stat_reg |= status_interrupt;
369 set_interrupt_line();
370 break;
371
372 case 1: // seek
373 bits 16-22: cylinder number (0-76)
374 bits 23-24: 0s
375 bits 25: head number (1=upper)
376 bits 26-27: unit number (0-3)
377 unit = (m_cmd_reg >> 10) & 3;
378 head = (m_cmd_reg >> 9) & 1;
379 cylinder = m_cmd_reg & 0x7f;
380
381 // reset status
382 m_stat_reg = unit << status_unit_shift;
383
384 if (!do_seek(unit, cylinder, head))
385 m_stat_reg |= status_OP_complete;
386
387 m_stat_reg |= status_interrupt;
388 set_interrupt_line();
389 break;
390
391 case 2: // restore
392 bits 16-25: 0s
393 bits 26-27: unit number (0-3)
394 unit = (m_cmd_reg >> 10) & 3;
395
396 // reset status
397 m_stat_reg = unit << status_unit_shift;
398
399 if (!do_restore(unit))
400 m_stat_reg |= status_OP_complete;
401
402 m_stat_reg |= status_interrupt;
403 set_interrupt_line();
404 break;
405
406 case 3: // sector length
407 bits 16-22: sector word count (0-64)
408 bits 23-25: 0s
409 bits 26-27: unit number (0-3)
410 unit = (m_cmd_reg >> 10) & 3;
411 seclen = m_cmd_reg & 0x7f;
412
413 // reset status
414 m_stat_reg = unit << status_unit_shift;
415
416 if ((seclen > 64) || (seclen == 0))
417 {
418 m_stat_reg |= status_invalid_cmd;
419 }
420 else
421 {
422 m_drv[unit].seclen = seclen;
423 m_stat_reg |= status_OP_complete;
424 }
425
426 m_stat_reg |= status_interrupt;
427 set_interrupt_line();
428 break;
429
430 case 4: // read
431 bits 16-20: sector number (1-26)
432 bits 21-23: 0s
433 bit 24: no sequential sectoring (1=active)
434 bit 25: head number (1=upper)
435 bits 26-27: unit number (0-3)
436 unit = (m_cmd_reg >> 10) & 3;
437 head = (m_cmd_reg >> 9) & 1;
438 //non_seq_mode = (m_cmd_reg >> 8) & 1;
439 sector = m_cmd_reg & 0x1f;
440
441 m_unit = unit;
442 m_head = head;
443 m_sector = sector;
444 //m_non_seq_mode = non_seq_mode;
445
446 // reset status
447 m_stat_reg = unit << status_unit_shift;
448
449 do_read();
450
451 m_stat_reg |= status_interrupt;
452 set_interrupt_line();
453 break;
454
455 case 5: // read ID
456 bits 16-24: 0s
457 bit 25: head number (1=upper)
458 bits 26-27: unit number (0-3)
459 unit = (m_cmd_reg >> 10) & 3;
460 head = (m_cmd_reg >> 9) & 1;
461
462 // reset status
463 m_stat_reg = unit << status_unit_shift;
464
465 if (!read_id(unit, head, &cylinder, §or))
466 {
467 m_stat_reg |= status_ID_not_found;
468 }
469 else
470 {
471 m_recv_buf = (cylinder << 8) | sector;
472 m_stat_reg |= status_OP_complete;
473 }
474
475 m_stat_reg |= status_interrupt;
476 set_interrupt_line();
477 break;
478
479 case 6: // read unformatted
480 bits 16-20: sector number (1-26)
481 bits 21-24: 0s
482 bit 25: head number (1=upper)
483 bits 26-27: unit number (0-3)
484 // ...
485 break;
486
487 case 7: // write
488 bits 16-20: sector number (1-26)
489 bits 21-24: 0s
490 bit 25: head number (1=upper)
491 bits 26-27: unit number (0-3)
492 unit = (m_cmd_reg >> 10) & 3;
493 head = (m_cmd_reg >> 9) & 1;
494 sector = m_cmd_reg & 0x1f;
495
496 // reset status
497 m_stat_reg = unit << status_unit_shift;
498
499 if ((m_sector == 0) || (m_sector > 26))
500 {
501 m_stat_reg |= status_invalid_cmd;
502 }
503 else
504 {
505 m_unit = unit;
506 m_head = head;
507 m_sector = sector;
508 m_ddam = 0;
509
510 m_buf_pos = 0;
511 m_buf_mode = bm_write;
512 m_stat_reg |= status_XFER_ready;
513 m_stat_reg |= status_OP_complete; // right???
514 }
515
516 m_stat_reg |= status_interrupt;
517 set_interrupt_line();
518 break;
519
520 case 8: // write delete
521 bits 16-20: sector number (1-26)
522 bits 21-24: 0s
523 bit 25: head number (1=upper)
524 bits 26-27: unit number (0-3)
525 unit = (m_cmd_reg >> 10) & 3;
526 head = (m_cmd_reg >> 9) & 1;
527 sector = m_cmd_reg & 0x1f;
528
529 // reset status
530 m_stat_reg = unit << status_unit_shift;
531
532 if ((m_sector == 0) || (m_sector > 26))
533 {
534 m_stat_reg |= status_invalid_cmd;
535 }
536 else
537 {
538 m_unit = unit;
539 m_head = head;
540 m_sector = sector;
541 m_ddam = 1;
542
543 m_buf_pos = 0;
544 m_buf_mode = bm_write;
545 m_stat_reg |= status_XFER_ready;
546 m_stat_reg |= status_OP_complete; // right???
547 }
548
549 m_stat_reg |= status_interrupt;
550 set_interrupt_line();
551 break;
552
553 case 9: // format track
554 bits 16-23: track ID (0-255, normally current cylinder index, or 255 for bad track)
555 bit 24: verify only (1 - verify, 0 - format & verify)
556 bit 25: head number (1=upper)
557 bits 26-27: unit number (0-3)
558 // ...
559 break;
560
561 case 10: // load int mask
562 bit 16: bad mask for interrupt (0 = unmask or enable interrupt)
563 bits 17-27: 0s
564 m_interrupt_f_f = m_cmd_reg & 1;
565 set_interrupt_line();
566 break;
567
568 case 11: // stop
569 bits 16-25: 0s
570 bits 26-27: unit number (0-3)
571 unit = (m_cmd_reg >> 10) & 3;
572
573 // reset status
574 m_stat_reg = unit << status_unit_shift;
575
576 m_stat_reg |= status_OP_complete;
577
578 m_stat_reg |= status_interrupt;
579 set_interrupt_line();
580 break;
581
582 case 12: // step head
583 bits 16-22: track number (0-76)
584 bits 23-25: 0s
585 bits 26-27: unit number (0-3)
586 unit = (m_cmd_reg >> 10) & 3;
587 cylinder = m_cmd_reg & 0x7f;
588
589 if (cylinder > 76)
590 {
591 m_stat_reg |= status_invalid_cmd;
592 }
593 else if ((m_drv[unit].phys_cylinder != -1) || (!do_restore(unit)))
594 {
595 m_drv[unit].img->floppy_drive_seek(cylinder-m_drv[unit].phys_cylinder);
596 m_stat_reg |= status_OP_complete;
597 }
598
599 m_stat_reg |= status_interrupt;
600 set_interrupt_line();
601 break;
602
603 case 13: // maintenance commands
604 bits 16-23: according to extended command code
605 bits 24-27: extended command code (0-7)
606 switch ((m_cmd_reg >> 8) & 15)
607 {
608 case 0: // reset
609 bits 16-23: 0s
610 // ...
611 break;
612 case 1: // retry inhibit
613 bits 16-23: 0s
614 // ...
615 break;
616 case 2: // LED test
617 bit 16: 1
618 bits 17-19: 0s
619 bit 20: LED #2 enable
620 bit 21: LED #3 enable
621 bit 22: LED #4 enable
622 bit 23: enable LEDs
623 // ...
624 break;
625 case 3: // program error (a.k.a. invalid command)
626 bits 16-23: 0s
627 // ...
628 break;
629 case 4: // memory read
630 bits 16-20: controller memory address (shifted left by 8 to generate 9900 address)
631 bits 21-23: 0s
632 // ...
633 break;
634 case 5: // RAM load
635 bit 16: 0
636 bits 17-23: RAM offset (shifted left by 1 and offset by >1800 to generate 9900 address)
637 // ...
638 break;
639 case 6: // RAM run
640 bit 16: 0
641 bits 17-23: RAM offset (shifted left by 1 and offset by >1800 to generate 9900 address)
642 // ...
643 break;
644 case 7: // power up simulation
645 bits 16-23: 0s
646 // ...
647 break;
648 }
649 // ...
650 break;
651
652 case 14: // IPL
653 bits 16-22: track number (0-76)
654 bit 23: 0
655 bit 24: no sequential sectoring (1=active)
656 bit 25: head number (1=upper)
657 bits 26-27: unit number (0-3)
658 unit = (m_cmd_reg >> 10) & 3;
659 head = (m_cmd_reg >> 9) & 1;
660 //non_seq_mode = (m_cmd_reg >> 8) & 1;
661 cylinder = m_cmd_reg & 0x7f;
662
663 if (!do_seek(unit, cylinder, head))
664 {
665 m_unit = unit;
666 m_head = head;
667 m_sector = 1;
668 //m_non_seq_mode = non_seq_mode;
669
670 do_read();
671 }
672
673 m_stat_reg |= status_interrupt;
674 set_interrupt_line();
675 break;
676
677 case 15: // Clear Status port
678 bits 16-27: 0s
679 m_stat_reg = 0;
680 set_interrupt_line();
681 break;
682 }
683 */
684 }
685
686 /*
687 read one CRU bit
688
689 0-15: receive buffer
690 16-31: status:
691 16: OP complete (1 -> complete???)
692 17: Xfer ready (XFER) (1 -> ready???)
693 18: drive not ready
694 19: data check error
695 20: seek error/??????
696 21 invalid command/??????
697 22: no address mark found/??????
698 23: equipment check error/??????
699 24: ID check error
700 25: ID not found
701 26: Controller busy (CTLBSY) (0 -> controller is ready)
702 27: write protect
703 28: deleted sector detected
704 29: unit LSB
705 30: unit MSB
706 31: Interrupt (CBUSY???) (1 -> controller is ready)
707 */
cru_r(offs_t offset)708 uint8_t fd800_legacy_device::cru_r(offs_t offset)
709 {
710 int reply = 0;
711
712 offset &= 31;
713 if (offset < 16)
714 {
715 // receive buffer
716 reply = BIT(m_recv_buf, offset);
717 }
718 else
719 {
720 // status register
721 reply = BIT(m_stat_reg, offset - 16);
722 }
723
724 return reply;
725 }
726
727 /*
728 write one CRU bit
729
730 0-15: controller data word (transmit buffer)
731 16-31: controller command word (command register)
732 16-23: parameter value
733 24: flag bit/extended command code
734 25: head select/extended command code
735 26: FD unit number LSB/extended command code
736 27: FD unit number MSB/extended command code
737 28-31: command code
738 */
cru_w(offs_t offset,uint8_t data)739 void fd800_legacy_device::cru_w(offs_t offset, uint8_t data)
740 {
741 switch (offset)
742 {
743 case 0:
744 case 1:
745 case 2:
746 case 3:
747 case 4:
748 case 5:
749 case 6:
750 case 7:
751 case 8:
752 case 9:
753 case 10:
754 case 11:
755 case 12:
756 case 13:
757 case 14:
758 case 15:
759 // transmit buffer
760 if (data)
761 m_xmit_buf |= 1 << offset;
762 else
763 m_xmit_buf &= ~(1 << offset);
764 if (offset == 15)
765 {
766 switch (m_buf_mode)
767 {
768 case bm_off:
769 break;
770 case bm_read:
771 m_buf_pos++;
772 if (m_buf_pos == m_drv[m_unit].seclen)
773 { // end of sector
774 if (m_sector == 26)
775 { // end of track -> end command (right???)
776 m_stat_reg &= ~status_XFER_ready;
777 m_stat_reg |= status_OP_complete;
778 m_stat_reg |= status_interrupt;
779 m_buf_mode = bm_off;
780 set_interrupt_line();
781 }
782 else
783 { // read next sector
784 m_sector++;
785 m_stat_reg &= ~status_XFER_ready | status_OP_complete | status_interrupt;
786 do_read();
787 m_stat_reg |= status_interrupt;
788 set_interrupt_line();
789 }
790 }
791 else
792 m_recv_buf = (m_buf[m_buf_pos<<1] << 8) | m_buf[(m_buf_pos<<1)+1];
793 break;
794
795 case bm_write:
796 m_buf[m_buf_pos<<1] = m_xmit_buf >> 8;
797 m_buf[(m_buf_pos<<1)+1] = m_xmit_buf & 0xff;
798 m_buf_pos++;
799 if (m_buf_pos == m_drv[m_unit].seclen)
800 { // end of sector
801 do_write();
802 if (m_sector == 26)
803 {
804 // end of track -> end command (right???)
805 m_stat_reg &= ~status_XFER_ready;
806 m_stat_reg |= status_OP_complete;
807 m_stat_reg |= status_interrupt;
808 m_buf_mode = bm_off;
809 set_interrupt_line();
810 }
811 else
812 { // increment to next sector
813 m_sector++;
814 m_stat_reg |= status_interrupt;
815 set_interrupt_line();
816 }
817 }
818 break;
819 }
820 }
821 break;
822
823 case 16:
824 case 17:
825 case 18:
826 case 19:
827 case 20:
828 case 21:
829 case 22:
830 case 23:
831 case 24:
832 case 25:
833 case 26:
834 case 27:
835 case 28:
836 case 29:
837 case 30:
838 case 31:
839 // command register
840 if (data)
841 m_cmd_reg |= 1 << (offset-16);
842 else
843 m_cmd_reg &= ~(1 << (offset-16));
844 if (offset == 31)
845 do_cmd();
846 break;
847 }
848 }
849
850 #if 0
851 LEGACY_FLOPPY_OPTIONS_START(fd800)
852 // SSSD 8"
853 LEGACY_FLOPPY_OPTION(fd800, "dsk", "TI990 8\" SSSD disk image", basicdsk_identify_default, basicdsk_construct_default, nullptr,
854 HEADS([1])
855 TRACKS([77])
856 SECTORS([26])
857 SECTOR_LENGTH([128])
858 FIRST_SECTOR_ID([1]))
859
860 // DSSD 8"
861 LEGACY_FLOPPY_OPTION(fd800, "dsk", "TI990 8\" DSSD disk image", basicdsk_identify_default, basicdsk_construct_default, nullptr,
862 HEADS([2])
863 TRACKS([77])
864 SECTORS([26])
865 SECTOR_LENGTH([128])
866 FIRST_SECTOR_ID([1]))
867 LEGACY_FLOPPY_OPTIONS_END
868 #endif
869
device_start()870 void fd800_legacy_device::device_start()
871 {
872 logerror("fd800: start\n");
873 m_int_line.resolve();
874
875 for (auto & elem : m_drv)
876 {
877 // m_drv[i].img = floppy_get_device(machine(), i);
878 elem.phys_cylinder = -1;
879 elem.log_cylinder[0] = elem.log_cylinder[1] = -1;
880 elem.seclen = 64;
881 }
882 }
883
device_reset()884 void fd800_legacy_device::device_reset()
885 {
886 logerror("fd800: reset\n");
887 m_stat_reg = 0;
888 m_interrupt_f_f = 1;
889
890 m_buf_pos = 0;
891 m_buf_mode = bm_off;
892 }
893