OpenCBM
libcbmcopy/s1.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version
5  * 2 of the License, or (at your option) any later version.
6  *
7  * Copyright 1999 Michael Klein <michael(dot)klein(at)puffin(dot)lb(dot)shuttle(dot)de>
8  * Copyright 2008 Spiro Trikaliotis
9 */
10 
11 #include "opencbm.h"
12 #include "cbmcopy_int.h"
13 
14 #include <stdlib.h>
15 
16 #include "opencbm-plugin.h"
17 
19 
21 
22 static const unsigned char s1r15x1[] = {
23 #include "s1r.inc"
24 };
25 
26 static const unsigned char s1w15x1[] = {
27 #include "s1w.inc"
28 };
29 
30 static const unsigned char s1r1581[] = {
31 #include "s1r-1581.inc"
32 };
33 
34 static const unsigned char s1w1581[] = {
35 #include "s1w-1581.inc"
36 };
37 
38 static struct drive_prog
39 {
40  const unsigned char *prog;
41  size_t size;
42 } drive_progs[] =
43 {
44  { s1r15x1, sizeof(s1r15x1) },
45  { s1w15x1, sizeof(s1w15x1) },
46  { s1r1581, sizeof(s1r1581) },
47  { s1w1581, sizeof(s1w1581) }
48 };
49 
50 static int write_byte(CBM_FILE,unsigned char);
51 static unsigned char read_byte(CBM_FILE);
52 
73 static int write_blk(CBM_FILE HandleDevice, const void *Buffer, unsigned char Count, cbmcopy_message_cb msg_cb)
74 {
76  {
77 #ifdef LIBCBMCOPY_DEBUG
78  msg_cb( sev_debug, "send byte count: %d", Count );
79 #endif
80  SETSTATEDEBUG((void)0);
81  if ( (Buffer == NULL) || (opencbm_plugin_s1_write_n( HandleDevice, &Count, 1 ) != 1) )
82  {
83  return -1;
84  }
85  SETSTATEDEBUG((void)0);
86 
87  if( Count == 0xff )
88  {
89  Count--;
90  }
91 
92 #ifdef LIBCBMCOPY_DEBUG
93  msg_cb( sev_debug, "send block data" );
94 #endif
95  return opencbm_plugin_s1_write_n( HandleDevice, Buffer, Count );
96  }
97  else
98  {
99  SETSTATEDEBUG((void)0);
100  /* call generic byte oriented block handler */
101  return write_block_generic(HandleDevice, Buffer, Count, &write_byte, msg_cb);
102  }
103 }
104 
124 static int read_blk(CBM_FILE HandleDevice, void *Buffer, size_t Count, cbmcopy_message_cb msg_cb)
125 {
126  unsigned char c;
127  int rv = 0;
128 
130  {
131  SETSTATEDEBUG((void)0);
132  /* get the number of bytes that need to be transferred for this block */
133  if( opencbm_plugin_s1_read_n(HandleDevice, &c, 1) != 1 )
134  {
135  return -1;
136  }
137 #ifdef LIBCBMCOPY_DEBUG
138  msg_cb( sev_debug, "received byte count: %d", c );
139 #endif
140  SETSTATEDEBUG((void)0);
141  rv = c;
142 
143  if( c == 0xff )
144  {
145  /* this is a flag that further bytes are following, so get a full block of 254 bytes */
146  c--;
147  }
148  if( (Buffer == NULL) || (c > Count) )
149  {
150  /* If the block size if greater than the available buffer, return with
151  * a fatal error since the turbo handlers always need to transfer a
152  * complete block. If there is no buffer allocated at all, fail also.
153  */
154  return -1;
155  }
156 #ifdef LIBCBMCOPY_DEBUG
157  msg_cb( sev_debug, "receive block data (%d)", c );
158 #endif
159  return (opencbm_plugin_s1_read_n(HandleDevice, Buffer, c) != c )? -1 : rv;
160  /* (drive is busy now) */
161  }
162  else
163  {
164  /* call generic byte oriented block handler */
165  return read_block_generic(HandleDevice, Buffer, Count, &read_byte, msg_cb);
166  }
167 }
168 
169 static int write_byte(CBM_FILE fd, unsigned char c)
170 {
171  int b, i;
172  SETSTATEDEBUG((void)0);
173  for(i=7; i>=0; i--) {
174  b=(c >> i) & 1;
175  SETSTATEDEBUG(DebugBitCount=i);
176  if(b) cbm_iec_set(fd, IEC_DATA); else cbm_iec_release(fd, IEC_DATA);
177  SETSTATEDEBUG((void)0);
179  SETSTATEDEBUG((void)0);
180 #ifndef USE_CBM_IEC_WAIT
181  while(!cbm_iec_get(fd, IEC_CLOCK));
182 #else
183  cbm_iec_wait(fd, IEC_CLOCK, 1);
184 #endif
185  SETSTATEDEBUG((void)0);
186  if(b) cbm_iec_release(fd, IEC_DATA); else cbm_iec_set(fd, IEC_DATA);
187  SETSTATEDEBUG((void)0);
188 #ifndef USE_CBM_IEC_WAIT
189  while(cbm_iec_get(fd, IEC_CLOCK));
190 #else
191  cbm_iec_wait(fd, IEC_CLOCK, 0);
192 #endif
193  SETSTATEDEBUG((void)0);
195  SETSTATEDEBUG((void)0);
196  cbm_iec_set(fd, IEC_CLOCK);
197  SETSTATEDEBUG((void)0);
198 #ifndef USE_CBM_IEC_WAIT
199  while(!cbm_iec_get(fd, IEC_DATA));
200 #else
201  cbm_iec_wait(fd, IEC_DATA, 1);
202 #endif
203  }
204  SETSTATEDEBUG(DebugBitCount=-1);
205  return 0;
206 }
207 
208 static unsigned char read_byte(CBM_FILE fd)
209 {
210  int b=0, i;
211  unsigned char c;
212  SETSTATEDEBUG((void)0);
213  c = 0;
214  for(i=7; i>=0; i--) {
215  SETSTATEDEBUG(DebugBitCount=i);
216 #ifndef USE_CBM_IEC_WAIT
217  while(cbm_iec_get(fd, IEC_DATA));
218 #else
219  cbm_iec_wait(fd, IEC_DATA, 0);
220 #endif
221  SETSTATEDEBUG((void)0);
223  SETSTATEDEBUG((void)0);
224  b = cbm_iec_get(fd, IEC_CLOCK);
225  c = (c >> 1) | (b ? 0x80 : 0);
226  SETSTATEDEBUG((void)0);
227  cbm_iec_set(fd, IEC_DATA);
228  SETSTATEDEBUG((void)0);
229 #ifndef USE_CBM_IEC_WAIT
230  while(b == cbm_iec_get(fd, IEC_CLOCK));
231 #else
232  cbm_iec_wait(fd, IEC_CLOCK, !b);
233 #endif
234  SETSTATEDEBUG((void)0);
236  SETSTATEDEBUG((void)0);
237 #ifndef USE_CBM_IEC_WAIT
238  while(!cbm_iec_get(fd, IEC_DATA));
239 #else
240  cbm_iec_wait(fd, IEC_DATA, 1);
241 #endif
242  SETSTATEDEBUG((void)0);
243  cbm_iec_set(fd, IEC_CLOCK);
244  }
245  SETSTATEDEBUG(DebugBitCount=-1);
246  return c;
247 }
248 
249 static int check_error(CBM_FILE fd, int write)
250 {
251  int error;
252 
253  SETSTATEDEBUG((void)0);
255  SETSTATEDEBUG((void)0);
256  cbm_iec_wait(fd, IEC_DATA, 0);
257  SETSTATEDEBUG((void)0);
258  error = cbm_iec_get(fd, IEC_CLOCK) == 0;
259 
260  if(!error)
261  {
262  SETSTATEDEBUG((void)0);
263  cbm_iec_set(fd, IEC_DATA);
264  SETSTATEDEBUG((void)0);
265  cbm_iec_wait(fd, IEC_CLOCK, 0);
266  SETSTATEDEBUG((void)0);
268  if(write)
269  {
270  SETSTATEDEBUG((void)0);
271  cbm_iec_set(fd, IEC_CLOCK);
272  }
273  else
274  {
275  SETSTATEDEBUG((void)0);
276  cbm_iec_wait(fd, IEC_DATA, 1);
277  SETSTATEDEBUG((void)0);
278  cbm_iec_set(fd, IEC_CLOCK);
279  }
280  SETSTATEDEBUG((void)0);
281  }
282  SETSTATEDEBUG((void)0);
283  return error;
284 }
285 
286 static int upload_turbo(CBM_FILE fd, unsigned char drive,
287  enum cbm_device_type_e drive_type, int write)
288 {
289  const struct drive_prog *p;
290  int dt;
291 
292  opencbm_plugin_s1_read_n = cbm_get_plugin_function_address("opencbm_plugin_s1_read_n");
293  opencbm_plugin_s1_write_n = cbm_get_plugin_function_address("opencbm_plugin_s1_write_n");
294 
295  dt = (drive_type == cbm_dt_cbm1581);
296  p = &drive_progs[dt * 2 + (write != 0)];
297 
298  SETSTATEDEBUG((void)0);
299  cbm_upload(fd, drive, 0x680, p->prog, p->size);
300  SETSTATEDEBUG((void)0);
301  return 0;
302 }
303 
304 static int start_turbo(CBM_FILE fd, int write)
305 {
306  if(write)
307  {
308  SETSTATEDEBUG((void)0);
309  cbm_iec_wait(fd, IEC_DATA, 1);
310  }
311  else
312  {
313  SETSTATEDEBUG((void)0);
315  SETSTATEDEBUG((void)0);
316  cbm_iec_wait(fd, IEC_DATA, 1);
317  SETSTATEDEBUG((void)0);
318  cbm_iec_set(fd, IEC_CLOCK);
319  }
320  SETSTATEDEBUG((void)0);
321  return 0;
322 }
323 
324 static void exit_turbo(CBM_FILE fd, int write)
325 {
326  SETSTATEDEBUG((void)0);
327 // cbm_iec_wait(fd, IEC_DATA, 0);
328  SETSTATEDEBUG((void)0);
329 
331 
333 }
334 
335 DECLARE_TRANSFER_FUNCS(s1_transfer);
int CBMAPIDECL opencbm_plugin_s1_write_n(CBM_FILE HandleDevice, const unsigned char *data, unsigned int size)
Write data with serial1 protocol.
int CBMAPIDECL opencbm_plugin_s1_read_n_t(CBM_FILE HandleDevice, unsigned char *data, unsigned int size)
read a block of data from the OpenCBM backend with protocol serial-1
Plugin DLL interface.
#define IEC_DATA
Definition: opencbm.h:97
void CBMAPIDECL cbm_iec_set(CBM_FILE HandleDevice, int Line)
Activate a line on the IEC serial bus.
Definition: cbm.c:1341
int CBMAPIDECL cbm_iec_get(CBM_FILE HandleDevice, int Line)
Get the (logical) state of a line on the IEC serial bus.
Definition: cbm.c:1477
#define CBM_FILE
Definition: opencbm.h:87
void CBMAPIDECL cbm_iec_release(CBM_FILE HandleDevice, int Line)
Deactivate a line on the IEC serial bus.
Definition: cbm.c:1372
Definition: cbmctrl.c:1340
int CBMAPIDECL cbm_iec_wait(CBM_FILE HandleDevice, int Line, int State)
Wait for a line to have a specific state.
Definition: cbm.c:1448
cbm_device_type_e
Definition: opencbm.h:114
DLL interface for accessing the driver.
void *CBMAPIDECL cbm_get_plugin_function_address(const char *Functionname)
Get the function pointer for a function in a plugin.
Definition: cbm.c:2449
int CBMAPIDECL cbm_upload(CBM_FILE HandleDevice, unsigned char DeviceAddress, int DriveMemAddress, const void *Program, size_t Size)
Upload a program into a floppy's drive memory.
Definition: upload.c:133
#define IEC_CLOCK
Definition: opencbm.h:98
int CBMAPIDECL opencbm_plugin_s1_read_n(CBM_FILE HandleDevice, unsigned char *data, unsigned int size)
Read data with serial1 protocol.
int CBMAPIDECL opencbm_plugin_s1_write_n_t(CBM_FILE HandleDevice, const unsigned char *data, unsigned int size)
write a block of data to the OpenCBM backend with protocol serial-1