OpenCBM
detectxp1541.c
Go to the documentation of this file.
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 2005 Spiro Trikaliotis
8  * Based on code by Wolfgang Moser
9  *
10 */
11 
22 #define DBG_USERMODE
23 
25 #define DBG_PROGNAME "OPENCBM.DLL"
26 
27 #include "debug.h"
28 
29 #include <stdlib.h>
30 
32 #define DLL
33 #include "opencbm.h"
34 #include "archlib.h"
35 
36 #include "arch.h"
37 
38 
65 static int
66 pia_to_inputmode(CBM_FILE HandleDevice, unsigned char Drive, unsigned int PiaAddress)
67 {
68  int ret = -1;
69  unsigned char byteval = 0x00;
70 
71  FUNC_ENTER();
72 
73  if (cbm_upload(HandleDevice, Drive, PiaAddress + 2, &byteval, 1) == 1)
74  ret = 0;
75  else
76  ret = 1;
77 
78  FUNC_LEAVE_INT(ret);
79 }
80 
109 static int
110 output_pia(CBM_FILE HandleDevice, unsigned char Drive, unsigned int PiaAddress, unsigned char Value)
111 {
112  int ret = -1;
113 
114  FUNC_ENTER();
115 
116  do {
117  unsigned char byteval = 0xff;
118 
119  /*
120  * Set the PIA port to output
121  */
122  if (cbm_upload(HandleDevice, Drive, PiaAddress + 2, &byteval, 1) != 1)
123  break;
124 
125  /*
126  * Output the value via the PIA port
127  */
128  if (cbm_upload(HandleDevice, Drive, PiaAddress , &Value, 1) != 1)
129  break;
130 
131  /*
132  * Give the drive time to be able to execute this command
133  */
134  arch_usleep(10000);
135 
136  /*
137  * Read back the value. Hopefully, it is exactly what we just have written.
138  */
139  ret = cbm_pp_read(HandleDevice) != Value;
140 
141  if (ret)
142  {
143  /*
144  * The test was unsuccessfull. To make sure the PIA
145  * is not stuck at output mode, set it back to input mode.
146  */
147  pia_to_inputmode(HandleDevice, Drive, PiaAddress);
148  }
149 
150  } while (0);
151 
152  FUNC_LEAVE_INT(ret);
153 }
154 
186 int CBMAPIDECL
187 cbm_identify_xp1541(CBM_FILE HandleDevice, unsigned char DeviceAddress,
188  enum cbm_device_type_e *CbmDeviceType,
189  enum cbm_cable_type_e *CableType)
190 {
191  int ret = 0;
192  enum cbm_device_type_e localDummyDeviceType = cbm_dt_unknown;
193 
194  FUNC_ENTER();
195 
196  do
197  {
198  unsigned int piaAddress;
199  int value;
200 
201  if (!CableType)
202  {
203  /*
204  * We do not have a possibility to send back the
205  * cable type: This is an error!
206  */
207  DBG_ASSERT(("CableType is NULL", 0));
208  ret = 1;
209  break;
210  }
211 
212  *CableType = cbm_ct_none;
213 
214  /*
215  * If needed, determine the type of the drive
216  */
217  if (!CbmDeviceType)
218  CbmDeviceType = &localDummyDeviceType;
219 
220  if (*CbmDeviceType == cbm_dt_unknown)
221  {
222  ret = cbm_identify(HandleDevice, DeviceAddress,
223  CbmDeviceType, NULL);
224  }
225 
226  if (ret)
227  {
228  /*
229  * We could not even determine the device type;
230  * we do not dare trying to determine the cable
231  * type, as writing into wrong locations can
232  * make the drive hang.
233  */
234  *CableType = cbm_ct_unknown;
235  break;
236  }
237 
238  /*
239  * Now that we know the drive type, use this to find the PIA/VIA/CIA address
240  */
241  switch (*CbmDeviceType)
242  {
243  case cbm_dt_cbm1541:
244  piaAddress = 0x1801;
245  break;
246 
247  case cbm_dt_cbm1570:
248  case cbm_dt_cbm1571:
249  piaAddress = 0x4001;
250  break;
251 
252  default:
253  piaAddress = 0;
254  break;
255  }
256 
257  /*
258  * If we do not have a PIA address, we do not know where a parallel
259  * cable could be located. This, report "no parallel cable".
260  */
261  if (piaAddress == 0)
262  break;
263 
264  /*
265  * Set parallel port into input mode.
266  * This prevents us (PC) and the drive driving the lines simultaneously.
267  */
268  value = cbm_pp_read(HandleDevice);
269  DBG_PRINT((DBG_PREFIX "Setting Parport into input mode", value));
270 
271  /*
272  * Try to write some patterns and check if we see them:
273  */
274  if (output_pia(HandleDevice, DeviceAddress, piaAddress, 0x55))
275  break;
276 
277  if (output_pia(HandleDevice, DeviceAddress, piaAddress, 0xAA))
278  break;
279 
280  /*
281  * Ok, it has worked: We have a parallel cable.
282  */
283  *CableType = cbm_ct_xp1541;
284 
285  /*
286  * Set PIA back to input mode.
287  * Again, this prevents PC and drive driving the lines simultaneously
288  * (in the future).
289  */
290  if (piaAddress)
291  {
292  pia_to_inputmode(HandleDevice, DeviceAddress, piaAddress);
293  }
294 
295  } while (0);
296 
297  FUNC_LEAVE_INT(ret);
298 }
int CBMAPIDECL cbm_identify_xp1541(CBM_FILE HandleDevice, unsigned char DeviceAddress, enum cbm_device_type_e *CbmDeviceType, enum cbm_cable_type_e *CableType)
Identify the cable connected to a specific floppy drive.
Definition: detectxp1541.c:187
#define FUNC_LEAVE_INT(_xxx)
Definition: debug.h:358
Define makros for debugging purposes.
#define CBMAPIDECL
Definition: opencbm.h:85
unsigned char CBMAPIDECL cbm_pp_read(CBM_FILE HandleDevice)
Read a byte from a XP1541/XP1571 cable.
Definition: cbm.c:1244
#define CBM_FILE
Definition: opencbm.h:87
#define DBG_ASSERT(_xxx)
Definition: debug.h:401
#define FUNC_ENTER()
Definition: debug.h:347
cbm_device_type_e
Definition: opencbm.h:114
int CBMAPIDECL cbm_identify(CBM_FILE HandleDevice, unsigned char DeviceAddress, enum cbm_device_type_e *CbmDeviceType, const char **CbmDeviceString)
Identify the connected floppy drive.
Definition: detect.c:66
#define DBG_PREFIX
Definition: debug.h:320
DLL interface for accessing the driver.
cbm_cable_type_e
Definition: opencbm.h:132
Define makros and functions which account for differences between the different architectures.
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 DBG_PRINT(_xxx)
Definition: debug.h:403