OpenCBM
libd64copy/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 "d64copy_int.h"
13 
14 #include <stdlib.h>
15 
16 #include "arch.h"
17 
18 #include "opencbm-plugin.h"
19 
21 
23 
24 static const unsigned char s1_drive_prog[] = {
25 #include "s1.inc"
26 };
27 
28 static CBM_FILE fd_cbm;
29 static int two_sided;
30 
31 static int s1_write_byte_nohs(CBM_FILE fd, unsigned char c)
32 {
33  int b, i;
34  for(i=7; ; i--) {
35  SETSTATEDEBUG(DebugBitCount=i);
36  b=(c >> i) & 1;
37  SETSTATEDEBUG((void)0);
38  if(b) cbm_iec_set(fd, IEC_DATA); else cbm_iec_release(fd, IEC_DATA);
39  SETSTATEDEBUG((void)0);
41  SETSTATEDEBUG((void)0);
42 #ifndef USE_CBM_IEC_WAIT
43  while(!cbm_iec_get(fd, IEC_CLOCK));
44 #else
45  cbm_iec_wait(fd, IEC_CLOCK, 1);
46 #endif
47  SETSTATEDEBUG((void)0);
48  if(b) cbm_iec_release(fd, IEC_DATA); else cbm_iec_set(fd, IEC_DATA);
49  SETSTATEDEBUG((void)0);
50 #ifndef USE_CBM_IEC_WAIT
51  while(cbm_iec_get(fd, IEC_CLOCK));
52 #else
53  cbm_iec_wait(fd, IEC_CLOCK, 0);
54 #endif
55  SETSTATEDEBUG((void)0);
57  SETSTATEDEBUG((void)0);
59  SETSTATEDEBUG((void)0);
60 
61  if(i<=0) return 0;
62  SETSTATEDEBUG((void)0);
63 
64 #ifndef USE_CBM_IEC_WAIT
65  while(!cbm_iec_get(fd, IEC_DATA));
66 #else
67  cbm_iec_wait(fd, IEC_DATA, 1);
68 #endif
69  }
70  SETSTATEDEBUG((void)0);
71 }
72 
73 static int s1_write_byte(CBM_FILE fd, unsigned char c)
74 {
75  SETSTATEDEBUG((void)0);
76  s1_write_byte_nohs(fd, c);
77  SETSTATEDEBUG((void)0);
78 #ifndef USE_CBM_IEC_WAIT
79  while(!cbm_iec_get(fd, IEC_DATA));
80 #else
81  cbm_iec_wait(fd, IEC_DATA, 1);
82 #endif
83  SETSTATEDEBUG(DebugBitCount=-1);
84  return 0;
85 }
86 
87 /* write_n redirects USB writes to the external reader if required */
88 static void write_n(const unsigned char *data, int size)
89 {
90  int i;
91 
93  {
94  opencbm_plugin_s1_write_n(fd_cbm, data, size);
95  return;
96  }
97 
98  for(i=0;i<size;i++)
99  s1_write_byte(fd_cbm, *data++);
100 }
101 
102 static int s1_read_byte(CBM_FILE fd, unsigned char *c)
103 {
104  int b=0, i;
105  *c = 0;
106  for(i=7; i>=0; i--) {
107  SETSTATEDEBUG(DebugBitCount=i);
108 #ifndef USE_CBM_IEC_WAIT
109  while(cbm_iec_get(fd, IEC_DATA));
110 #else
111  cbm_iec_wait(fd, IEC_DATA, 0);
112 #endif
113  SETSTATEDEBUG((void)0);
115  SETSTATEDEBUG((void)0);
116  b = cbm_iec_get(fd, IEC_CLOCK);
117  SETSTATEDEBUG((void)0);
118  *c = (*c >> 1) | (b ? 0x80 : 0);
119  cbm_iec_set(fd, IEC_DATA);
120  SETSTATEDEBUG((void)0);
121 #ifndef USE_CBM_IEC_WAIT
122  while(b == cbm_iec_get(fd, IEC_CLOCK));
123 #else
124  cbm_iec_wait(fd, IEC_CLOCK, !b);
125 #endif
126  SETSTATEDEBUG((void)0);
128  SETSTATEDEBUG((void)0);
129 #ifndef USE_CBM_IEC_WAIT
130  while(!cbm_iec_get(fd, IEC_DATA));
131 #else
132  cbm_iec_wait(fd, IEC_DATA, 1);
133 #endif
134  SETSTATEDEBUG((void)0);
135  cbm_iec_set(fd, IEC_CLOCK);
136  }
137  SETSTATEDEBUG(DebugBitCount=-1);
138  return 0;
139 }
140 
141 /* read_n redirects USB reads to the external reader if required */
142 static void read_n(unsigned char *data, int size)
143 {
144  int i;
145 
147  {
148  opencbm_plugin_s1_read_n(fd_cbm, data, size);
149  return;
150  }
151 
152  for(i=0;i<size;i++)
153  s1_read_byte(fd_cbm, data++);
154 }
155 
156 static int read_block(unsigned char tr, unsigned char se, unsigned char *block)
157 {
158  unsigned char status;
159 
160  SETSTATEDEBUG((void)0);
161  write_n(&tr, 1);
162  SETSTATEDEBUG((void)0);
163  write_n(&se, 1);
164  SETSTATEDEBUG((void)0);
165 #ifndef USE_CBM_IEC_WAIT
166  arch_usleep(20000);
167 #endif
168  SETSTATEDEBUG((void)0);
169  read_n(&status, 1);
170  SETSTATEDEBUG(DebugByteCount=0);
171  // removed from loop: SETSTATEDEBUG(DebugByteCount++);
172  read_n(block, 256);
173  SETSTATEDEBUG(DebugByteCount=-1);
174  cbm_iec_release(fd_cbm, IEC_DATA);
175  SETSTATEDEBUG((void)0);
176  return status;
177 }
178 
179 static int write_block(unsigned char tr, unsigned char se, const unsigned char *blk, int size, int read_status)
180 {
181  unsigned char status;
182  SETSTATEDEBUG((void)0);
183  write_n(&tr, 1);
184  SETSTATEDEBUG((void)0);
185  write_n(&se, 1);
186  SETSTATEDEBUG(DebugByteCount=0);
187 
188  // removed from loop: SETSTATEDEBUG(DebugByteCount++);
189  write_n(blk, size);
190  SETSTATEDEBUG(DebugByteCount=-1);
191 #ifndef USE_CBM_IEC_WAIT
192  if(size == BLOCKSIZE) {
193  SETSTATEDEBUG((void)0);
194  arch_usleep(20000);
195  }
196 #endif
197  SETSTATEDEBUG((void)0);
198  read_n(&status, 1);
199  SETSTATEDEBUG((void)0);
200  cbm_iec_release(fd_cbm, IEC_DATA);
201  SETSTATEDEBUG((void)0);
202 
203  return status;
204 }
205 
206 static int open_disk(CBM_FILE fd, d64copy_settings *settings,
207  const void *arg, int for_writing,
208  turbo_start start, d64copy_message_cb message_cb)
209 {
210  unsigned char d = (unsigned char)(ULONG_PTR)arg;
211 
212  fd_cbm = fd;
213  two_sided = settings->two_sided;
214 
215  opencbm_plugin_s1_read_n = cbm_get_plugin_function_address("opencbm_plugin_s1_read_n");
216 
217  opencbm_plugin_s1_write_n = cbm_get_plugin_function_address("opencbm_plugin_s1_write_n");
218 
219  SETSTATEDEBUG((void)0);
220  cbm_upload(fd_cbm, d, 0x700, s1_drive_prog, sizeof(s1_drive_prog));
221  SETSTATEDEBUG((void)0);
222  start(fd, d);
223  SETSTATEDEBUG((void)0);
224  while(!cbm_iec_get(fd_cbm, IEC_DATA));
225  SETSTATEDEBUG((void)0);
226  return 0;
227 }
228 
229 static void close_disk(void)
230 {
231  SETSTATEDEBUG((void)0);
232  s1_write_byte(fd_cbm, 0);
233  SETSTATEDEBUG((void)0);
234  s1_write_byte_nohs(fd_cbm, 0);
235  SETSTATEDEBUG((void)0);
236  arch_usleep(100);
237  SETSTATEDEBUG(DebugBitCount=-1);
238 
240 
242 }
243 
244 static int send_track_map(unsigned char tr, const char *trackmap, unsigned char count)
245 {
246  int i, size;
247  unsigned char *data;
248  SETSTATEDEBUG((void)0);
249  size = d64copy_sector_count(two_sided, tr);
250  data = malloc(size+2);
251 
252  data[0] = tr;
253  data[1] = count;
254 
255  /* build track map */
256  for(i = 0; i < size; i++)
257  data[2+i] = !NEED_SECTOR(trackmap[i]);
258  SETSTATEDEBUG((void)0);
259  write_n(data, size+2);
260  free(data);
261  SETSTATEDEBUG((void)0);
262  return 0;
263 }
264 
265 static int read_gcr_block(unsigned char *se, unsigned char *gcrbuf)
266 {
267  unsigned char s;
268 
269  SETSTATEDEBUG((void)0);
270  read_n(&s, 1);
271  SETSTATEDEBUG((void)0);
272  *se = s;
273  read_n(&s, 1);
274  SETSTATEDEBUG((void)0);
275 
276  if(s) {
277  return s;
278  }
279 
280  SETSTATEDEBUG(DebugByteCount=0);
281  read_n(gcrbuf, GCRBUFSIZE);
282  SETSTATEDEBUG(DebugByteCount=-1);
283  return 0;
284 }
285 
286 DECLARE_TRANSFER_FUNCS_EX(s1_transfer, 1, 1);
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
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
DLL interface for accessing the driver.
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
#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