1 /*
2  * realdevice.c - Real device access.
3  *
4  * Written by
5  *  Andreas Boose <viceteam@t-online.de>
6  *  Michael Klein <nip@c64.org>
7  *
8  * This file is part of VICE, the Versatile Commodore Emulator.
9  * See README for copyright notice.
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24  *  02111-1307  USA.
25  *
26  */
27 
28 #include "vice.h"
29 
30 #ifdef HAVE_OPENCBM
31 
32 #include <stdio.h>
33 
34 #include "opencbmlib.h"
35 
36 #include "log.h"
37 #include "realdevice.h"
38 #include "serial.h"
39 #include "types.h"
40 #include "vsync.h"
41 
42 /*#define DEBUG_RD*/
43 
44 
45 static log_t realdevice_log = LOG_DEFAULT;
46 
47 static unsigned int realdevice_available = 0;
48 
49 static unsigned int realdevice_enabled = 0;
50 
51 static CBM_FILE realdevice_fd;
52 
53 static opencbmlib_t opencbmlib;
54 
55 
realdevice_open(unsigned int device,uint8_t secondary,void (* st_func)(uint8_t))56 void realdevice_open(unsigned int device, uint8_t secondary, void (*st_func)(uint8_t))
57 {
58     vsync_suspend_speed_eval();
59 
60     (*opencbmlib.p_cbm_open)(realdevice_fd, (uint8_t)(device & 0x0f),
61                              (uint8_t)(secondary & 0x0f),
62                              NULL, 0);
63 
64 #ifdef DEBUG_RD
65     log_debug("OPEN DEVICE %i SECONDARY %i", device & 0x0f, secondary & 0x0f);
66 #endif
67 }
68 
realdevice_close(unsigned int device,uint8_t secondary,void (* st_func)(uint8_t))69 void realdevice_close(unsigned int device, uint8_t secondary, void (*st_func)(uint8_t))
70 {
71     vsync_suspend_speed_eval();
72 
73     (*opencbmlib.p_cbm_close)(realdevice_fd, (uint8_t)(device & 0x0f),
74                               (uint8_t)(secondary & 0x0f));
75 
76 #ifdef DEBUG_RD
77     log_debug("CLOSE DEVICE %i SECONDARY %i", device & 0x0f, secondary & 0x0f);
78 #endif
79 }
80 
realdevice_listen(unsigned int device,uint8_t secondary,void (* st_func)(uint8_t))81 void realdevice_listen(unsigned int device, uint8_t secondary, void (*st_func)(uint8_t))
82 {
83     vsync_suspend_speed_eval();
84 
85     (*opencbmlib.p_cbm_listen)(realdevice_fd, (uint8_t)(device & 0x0f),
86                                (uint8_t)(secondary & 0x0f));
87 #ifdef DEBUG_RD
88     log_debug("LISTEN DEVICE %i SECONDARY %i", device & 0x0f,
89               secondary & 0x0f);
90 #endif
91 }
92 
realdevice_talk(unsigned int device,uint8_t secondary,void (* st_func)(uint8_t))93 void realdevice_talk(unsigned int device, uint8_t secondary, void (*st_func)(uint8_t))
94 {
95     vsync_suspend_speed_eval();
96 
97     (*opencbmlib.p_cbm_talk)(realdevice_fd, (uint8_t)(device & 0x0f),
98                              (uint8_t)(secondary & 0x0f));
99 #ifdef DEBUG_RD
100     log_debug("TALK DEVICE %i SECONDARY %i", device & 0x0f,
101               secondary & 0x0f);
102 #endif
103 }
104 
realdevice_unlisten(void (* st_func)(uint8_t))105 void realdevice_unlisten(void (*st_func)(uint8_t))
106 {
107     vsync_suspend_speed_eval();
108 
109     (*opencbmlib.p_cbm_unlisten)(realdevice_fd);
110 #ifdef DEBUG_RD
111     log_debug("UNLISTEN");
112 #endif
113 }
114 
realdevice_untalk(void (* st_func)(uint8_t))115 void realdevice_untalk(void (*st_func)(uint8_t))
116 {
117     vsync_suspend_speed_eval();
118 
119     (*opencbmlib.p_cbm_untalk)(realdevice_fd);
120 #ifdef DEBUG_RD
121     log_debug("UNTALK");
122 #endif
123 }
124 
realdevice_write(uint8_t data,void (* st_func)(uint8_t))125 void realdevice_write(uint8_t data, void (*st_func)(uint8_t))
126 {
127     uint8_t st;
128 
129 #ifdef DEBUG_RD
130     uint8_t mydata = data;
131 #endif
132 
133     vsync_suspend_speed_eval();
134 
135     st = ((*opencbmlib.p_cbm_raw_write)(realdevice_fd, &data, 1) == 1)
136          ? 0 : 0x83;
137 
138 #ifdef DEBUG_RD
139     log_debug("WRITE DATA %02x ST %02x", mydata, st);
140 #endif
141 
142     st_func(st);
143 }
144 
realdevice_read(void (* st_func)(uint8_t))145 uint8_t realdevice_read(void (*st_func)(uint8_t))
146 {
147     uint8_t st, data;
148 
149     vsync_suspend_speed_eval();
150 
151     st = ((*opencbmlib.p_cbm_raw_read)(realdevice_fd, &data, 1) == 1) ? 0 : 2;
152 
153 #ifdef DEBUG_RD
154     log_debug("READ %02x ST %02x", data, st);
155 #endif
156 
157     if ((*opencbmlib.p_cbm_get_eoi)(realdevice_fd)) {
158         st |= 0x40;
159     }
160 
161 #ifdef DEBUG_RD
162     log_debug("READ NEWST %02x", st);
163 #endif
164 
165     st_func(st);
166 
167     return data;
168 }
169 
realdevice_init(void)170 void realdevice_init(void)
171 {
172     realdevice_log = log_open("Real Device");
173 #ifdef DEBUG_RD
174     log_debug("realdevice_init()");
175 #endif
176 
177     if (opencbmlib_open(&opencbmlib) >= 0) {
178         realdevice_available = 1;
179     }
180 }
181 
realdevice_reset(void)182 void realdevice_reset(void)
183 {
184 #ifdef DEBUG_RD
185     log_debug("realdevice_reset()");
186 #endif
187     if (realdevice_enabled) {
188         (*opencbmlib.p_cbm_reset)(realdevice_fd);
189     }
190 }
191 
realdevice_enable(void)192 int realdevice_enable(void)
193 {
194 #ifdef DEBUG_RD
195     log_debug("realdevice_enable()");
196 #endif
197     if (realdevice_available == 0 &&
198             opencbmlib_open(&opencbmlib) >= 0) {
199         realdevice_available = 1;
200     }
201 
202     if (realdevice_available == 0) {
203         log_message(realdevice_log, "Real device access is not available!");
204         return -1;
205     }
206 
207     if (realdevice_enabled == 0) {
208 #ifdef DEBUG_RD
209         log_debug("realdevice_enable: calling cbm_driver_open");
210 #endif
211         if ((*opencbmlib.p_cbm_driver_open)(&realdevice_fd, 0) != 0) {
212             log_message(realdevice_log,
213                         "Cannot open %s, realdevice not available!",
214                         (*opencbmlib.p_cbm_get_driver_name)(0));
215             return -1;
216         }
217 
218         log_message(realdevice_log, "%s opened.",
219                     (*opencbmlib.p_cbm_get_driver_name)(0));
220     }
221 
222 #ifdef DEBUG_RD
223     log_debug("realdevice_enable: realdevice_enabled++");
224 #endif
225     realdevice_enabled++;
226 
227     return 0;
228 }
229 
realdevice_disable(void)230 void realdevice_disable(void)
231 {
232 #ifdef DEBUG_RD
233     log_debug("realdevice_disable()");
234 #endif
235     if (realdevice_enabled > 0) {
236         realdevice_enabled--;
237 
238         if (realdevice_enabled == 0) {
239             (*opencbmlib.p_cbm_driver_close)(realdevice_fd);
240 
241             log_message(realdevice_log, "%s closed.",
242                         (*opencbmlib.p_cbm_get_driver_name)(0));
243 
244             opencbmlib_close();
245             realdevice_available = 0;
246         }
247     }
248 }
249 #endif
250