1 /*
2  *  KCemu -- The emulator for the KC85 homecomputer series and much more.
3  *  Copyright (C) 1997-2010 Torsten Paul
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License along
16  *  with this program; if not, write to the Free Software Foundation, Inc.,
17  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #include <ctype.h>
21 
22 #include "kc/system.h"
23 
24 #include "kc/fdc4.h"
25 #include "kc/z80_fdc.h"
26 
27 #include "libdbg/dbg.h"
28 
FDC4(void)29 FDC4::FDC4(void)
30 {
31   fdc_z80->register_ic(this);
32 }
33 
~FDC4(void)34 FDC4::~FDC4(void)
35 {
36   fdc_z80->unregister_ic(this);
37 }
38 
39 long long
get_counter()40 FDC4::get_counter()
41 {
42   return fdc_z80->get_counter();
43 }
44 
45 void
add_callback(unsigned long long offset,Callback * cb,void * data)46 FDC4::add_callback(unsigned long long offset, Callback *cb, void *data)
47 {
48   fdc_z80->add_callback(offset, cb, data);
49 }
50 
51 byte_t
in(word_t addr)52 FDC4::in(word_t addr)
53 {
54   byte_t val = 0;
55 
56   word_t pc = fdc_z80->getPC();
57 
58   switch (addr & 0xff)
59     {
60     case 0xf0: // D004 (KC85/4)
61       /* CS-FDC (Chipselect) */
62       val = get_msr();
63       DBG(2, form("KCemu/FDC/in_F0",
64                   "FDC::in(): %04xh addr = %04x, val = %02x [%c]\n",
65                   pc, addr, val, isprint(val) ? val : '.'));
66       break;
67     case 0xf1: // D004 (KC85/4)
68       val = in_data(addr);
69       DBG(2, form("KCemu/FDC/in_F1",
70                   "FDC::in(): %04xh addr = %04x, val = %02x [%c]\n",
71                   pc, addr, val, isprint(val) ? val : '.'));
72       break;
73     case 0xf2: // D004 (KC85/4)
74       /* DAK-FDC (DMA-Acknowledge) */
75       val = read_byte();
76       DBG(2, form("KCemu/FDC/in_F2",
77                   "FDC::in(): %04xh addr = %04x, val = %02x [%c]\n",
78                   pc, addr, val, isprint(val) ? val : '.'));
79       break;
80     case 0xf4: // D004 (KC85/4)
81       /*
82        *  Input-Gate:
83        *
84        *  Bit 7   DRQ (DMA-Request)
85        *  Bit 6   INT (Interrupt)
86        *  Bit 5   RDY (Drive-Ready)
87        *  Bit 4   IDX (Index - Spuranfang)
88        */
89       val = get_input_gate();
90       DBG(2, form("KCemu/FDC/in_F4",
91                   "FDC::in(): %04xh addr = %04x, val = %02x [%c]\n",
92                   pc, addr, val, isprint(val) ? val : '.'));
93       break;
94     case 0xf6: // D004 (KC85/4)
95       /* Select-Latch */
96       val = 0x00;
97       DBG(2, form("KCemu/FDC/in_F6",
98                   "FDC::in(): %04xh addr = %04x, val = %02x [%c]\n",
99                   pc, addr, val, isprint(val) ? val : '.'));
100       break;
101     case 0xf8: // D004 (KC85/4)
102       /* TC-FDC (Terminalcount) - End of DMA Transfer */
103       val = 0x00;
104       DBG(2, form("KCemu/FDC/in_F8",
105                   "FDC::in(): %04xh addr = %04x, val = %02x [%c]\n",
106                   pc, addr, val, isprint(val) ? val : '.'));
107       break;
108     }
109 
110   DBG(2, form("KCemu/FDC/in",
111               "FDC::in(): %04xh  addr = %04x, val = %02x\n",
112               pc, addr, val));
113 
114   return val;
115 }
116 
117 void
out(word_t addr,byte_t val)118 FDC4::out(word_t addr, byte_t val)
119 {
120   word_t pc = fdc_z80->getPC();
121 
122   DBG(2, form("KCemu/FDC/out",
123               "FDC::out(): %04xh (I=%02x): addr = %04x, val = %02x [%c]\n",
124               pc, fdc_z80->getI(), addr, val, isprint(val) ? val : '.'));
125 
126   switch (addr & 0xff)
127     {
128     case 0xf1: // D004 (KC85/4)
129       DBG(2, form("KCemu/FDC/out_F1",
130                   "FDC::out(): %04xh addr = %04x, val = %02x [%c]\n",
131                   pc, addr, val, isprint(val) ? val : '.'));
132       out_data(addr, val);
133       break;
134     case 0xf2: // D004 (KC85/4)
135       DBG(2, form("KCemu/FDC/out_F2",
136                   "FDC::out(): %04xh addr = %04x, val = %02x [%c]\n",
137                   pc, addr, val, isprint(val) ? val : '.'));
138       write_byte(val);
139       break;
140     case 0xf6: // D004 (KC85/4)
141       DBG(2, form("KCemu/FDC/out_F6",
142                   "FDC::out(): %04xh addr = %04x, val = %02x [%c]\n",
143                   pc, addr, val, isprint(val) ? val : '.'));
144       drive_select(val & 0x0f);
145       break;
146     case 0xf8: // D004 (KC85/4)
147       DBG(2, form("KCemu/FDC/out_F8",
148                   "FDC::out(): %04xh Terminal Count %02x\n",
149                   pc, val));
150 
151       set_state(FDC_STATE_RESULT);
152       set_input_gate(0x40, 0x00);
153       break;
154     default:
155       DBG(2, form("KCemu/FDC/out_unhandled",
156                   "FDC::out(): %04xh addr = %04x, val = %02x [%c]\n",
157                   pc, addr, val, isprint(val) ? val : '.'));
158       break;
159     }
160 }
161