OpenCBM
libcbmcopy/s2.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 "arch.h"
17 
18 #include "opencbm-plugin.h"
19 
21 
23 
24 
25 static const unsigned char s2r15x1[] = {
26 #include "s2r.inc"
27 };
28 
29 static const unsigned char s2w15x1[] = {
30 #include "s2w.inc"
31 };
32 
33 static const unsigned char s2r1581[] = {
34 #include "s2r-1581.inc"
35 };
36 
37 static const unsigned char s2w1581[] = {
38 #include "s2w-1581.inc"
39 };
40 
41 static struct drive_prog
42 {
43  const unsigned char *prog;
44  size_t size;
45 } drive_progs[] =
46 {
47  { s2r15x1, sizeof(s2r15x1) },
48  { s2w15x1, sizeof(s2w15x1) },
49  { s2r1581, sizeof(s2r1581) },
50  { s2w1581, sizeof(s2w1581) }
51 };
52 
53 static int write_byte(CBM_FILE,unsigned char);
54 static unsigned char read_byte(CBM_FILE);
55 
76 static int write_blk(CBM_FILE HandleDevice, const void *Buffer, unsigned char Count, cbmcopy_message_cb msg_cb)
77 {
79  {
80 #ifdef LIBCBMCOPY_DEBUG
81  msg_cb( sev_debug, "send byte count: %d", Count );
82 #endif
83  SETSTATEDEBUG((void)0);
84  if ( (Buffer == NULL) || (opencbm_plugin_s2_write_n( HandleDevice, &Count, 1 ) != 1) )
85  {
86  return -1;
87  }
88  SETSTATEDEBUG((void)0);
89 
90  if( Count == 0xff )
91  {
92  Count--;
93  }
94 
95 #ifdef LIBCBMCOPY_DEBUG
96  msg_cb( sev_debug, "send block data" );
97 #endif
98  return opencbm_plugin_s2_write_n( HandleDevice, Buffer, Count );
99  }
100  else
101  {
102  SETSTATEDEBUG((void)0);
103  /* call generic byte oriented block handler */
104  return write_block_generic(HandleDevice, Buffer, Count, &write_byte, msg_cb);
105  }
106 }
107 
127 static int read_blk(CBM_FILE HandleDevice, void *Buffer, size_t Count, cbmcopy_message_cb msg_cb)
128 {
129  unsigned char c;
130  int rv = 0;
131 
133  {
134  SETSTATEDEBUG((void)0);
135  /* get the number of bytes that need to be transferred for this block */
136  if( opencbm_plugin_s2_read_n(HandleDevice, &c, 1) != 1 )
137  {
138  return -1;
139  }
140 #ifdef LIBCBMCOPY_DEBUG
141  msg_cb( sev_debug, "received byte count: %d", c );
142 #endif
143  SETSTATEDEBUG((void)0);
144  rv = c;
145 
146  if( c == 0xff )
147  {
148  /* this is a flag that further bytes are following, so get a full block of 254 bytes */
149  c--;
150  }
151  if( (Buffer == NULL) || (c > Count) )
152  {
153  /* If the block size if greater than the available buffer, return with
154  * a fatal error since the turbo handlers always need to transfer a
155  * complete block. If there is no buffer allocated at all, fail also.
156  */
157  return -1;
158  }
159 #ifdef LIBCBMCOPY_DEBUG
160  msg_cb( sev_debug, "receive block data (%d)", c );
161 #endif
162  return (opencbm_plugin_s2_read_n(HandleDevice, Buffer, c) != c )? -1 : rv;
163  /* (drive is busy now) */
164  }
165  else
166  {
167  /* call generic byte oriented block handler */
168  return read_block_generic(HandleDevice, Buffer, Count, &read_byte, msg_cb);
169  }
170 }
171 
172 static int write_byte(CBM_FILE fd, unsigned char c)
173 {
174  int i;
175  SETSTATEDEBUG((void)0);
176  for(i=4; i>0; i--) {
177  SETSTATEDEBUG(DebugBitCount=i*2);
178  c & 1 ? cbm_iec_set(fd, IEC_DATA) : cbm_iec_release(fd, IEC_DATA);
179  c >>= 1;
180  SETSTATEDEBUG((void)0);
182  SETSTATEDEBUG((void)0);
183 #ifndef USE_CBM_IEC_WAIT
184  while(cbm_iec_get(fd, IEC_CLOCK));
185 #else
186  cbm_iec_wait(fd, IEC_CLOCK, 0);
187 #endif
188  SETSTATEDEBUG(DebugBitCount--);
189  c & 1 ? cbm_iec_set(fd, IEC_DATA) : cbm_iec_release(fd, IEC_DATA);
190  c >>= 1;
191  SETSTATEDEBUG((void)0);
192  cbm_iec_set(fd, IEC_ATN);
193  SETSTATEDEBUG((void)0);
194 #ifndef USE_CBM_IEC_WAIT
195  while(!cbm_iec_get(fd, IEC_CLOCK));
196 #else
197  cbm_iec_wait(fd, IEC_CLOCK, 1);
198 #endif
199  }
200  SETSTATEDEBUG(DebugBitCount=-1);
202  SETSTATEDEBUG((void)0);
203  return 0;
204 }
205 
206 static unsigned char read_byte(CBM_FILE fd)
207 {
208  int i;
209  unsigned char c;
210  SETSTATEDEBUG((void)0);
211  c = 0;
212  for(i=4; i>0; i--) {
213  SETSTATEDEBUG(DebugBitCount=i*2);
214 #ifndef USE_CBM_IEC_WAIT
215  while(cbm_iec_get(fd, IEC_CLOCK));
216  c = (c>>1) | (cbm_iec_get(fd, IEC_DATA) ? 0x80 : 0);
217 #else
218  c = (c>>1) | ((cbm_iec_wait(fd, IEC_CLOCK, 0) & IEC_DATA) ? 0x80 : 0 );
219 #endif
220  SETSTATEDEBUG((void)0);
222  SETSTATEDEBUG(DebugBitCount--);
223 #ifndef USE_CBM_IEC_WAIT
224  while(!cbm_iec_get(fd,IEC_CLOCK));
225  c = (c>>1) | (cbm_iec_get(fd, IEC_DATA) ? 0x80 : 0);
226 #else
227  c = (c>>1) | ((cbm_iec_wait(fd, IEC_CLOCK, 1) & IEC_DATA) ? 0x80 : 0 );
228 #endif
229  SETSTATEDEBUG((void)0);
230  cbm_iec_set(fd, IEC_ATN);
231  }
232 
233  SETSTATEDEBUG(DebugBitCount=-1);
234  return c;
235 }
236 
237 static int check_error(CBM_FILE fd, int write)
238 {
239  int error;
240 
241  SETSTATEDEBUG((void)0);
243  SETSTATEDEBUG((void)0);
244  cbm_iec_wait(fd, IEC_CLOCK, 0);
245  SETSTATEDEBUG((void)0);
246  error = cbm_iec_get(fd, IEC_DATA) == 0;
247  if(!error)
248  {
249  SETSTATEDEBUG((void)0);
250  cbm_iec_set(fd, IEC_DATA);
251  SETSTATEDEBUG((void)0);
252  cbm_iec_set(fd, IEC_ATN);
253  SETSTATEDEBUG((void)0);
254  if(!write)
255  {
256  cbm_iec_wait(fd, IEC_CLOCK, 1);
257  SETSTATEDEBUG((void)0);
259  }
260  }
261 
262  SETSTATEDEBUG((void)0);
263  return error;
264 }
265 
266 static int upload_turbo(CBM_FILE fd, unsigned char drive,
267  enum cbm_device_type_e drive_type, int write)
268 {
269  const struct drive_prog *p;
270  int dt;
271 
272  opencbm_plugin_s2_read_n = cbm_get_plugin_function_address("opencbm_plugin_s2_read_n");
273 
274  opencbm_plugin_s2_write_n = cbm_get_plugin_function_address("opencbm_plugin_s2_write_n");
275 
276  dt = (drive_type == cbm_dt_cbm1581);
277  p = &drive_progs[dt * 2 + (write != 0)];
278 
279  SETSTATEDEBUG((void)0);
280  cbm_upload(fd, drive, 0x680, p->prog, p->size);
281  SETSTATEDEBUG((void)0);
282  return 0;
283 }
284 
285 static int start_turbo(CBM_FILE fd, int write)
286 {
287  SETSTATEDEBUG((void)0);
289  SETSTATEDEBUG((void)0);
290  cbm_iec_wait(fd, IEC_CLOCK, 1);
291  SETSTATEDEBUG((void)0);
292  cbm_iec_set(fd, IEC_ATN);
293  SETSTATEDEBUG((void)0);
294  arch_usleep(20000);
295  SETSTATEDEBUG((void)0);
296  return 0;
297 }
298 
299 static void exit_turbo(CBM_FILE fd, int write)
300 {
301  SETSTATEDEBUG((void)0);
303  SETSTATEDEBUG((void)0);
305  SETSTATEDEBUG((void)0);
306  cbm_iec_set(fd, IEC_CLOCK);
307  SETSTATEDEBUG((void)0);
308  arch_usleep(20000);
309  SETSTATEDEBUG((void)0);
310 // cbm_iec_wait(fd, IEC_DATA, 0);
311  SETSTATEDEBUG((void)0);
312 
314 
316 }
317 
318 DECLARE_TRANSFER_FUNCS(s2_transfer);
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
#define IEC_ATN
Definition: opencbm.h:99
void CBMAPIDECL cbm_iec_release(CBM_FILE HandleDevice, int Line)
Deactivate a line on the IEC serial bus.
Definition: cbm.c:1372
int CBMAPIDECL opencbm_plugin_s2_read_n_t(CBM_FILE HandleDevice, unsigned char *data, unsigned int size)
read a block of data from the OpenCBM backend with protocol serial-2
Definition: cbmctrl.c:1340
int CBMAPIDECL opencbm_plugin_s2_read_n(CBM_FILE HandleDevice, unsigned char *data, unsigned int size)
Read data with serial2 protocol.
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.
int CBMAPIDECL opencbm_plugin_s2_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-2
Define makros and functions which account for differences between the different architectures.
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
int CBMAPIDECL opencbm_plugin_s2_write_n(CBM_FILE HandleDevice, const unsigned char *data, unsigned int size)
Write data with serial2 protocol.
#define IEC_CLOCK
Definition: opencbm.h:98