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