OpenCBM
cbmformat.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 */
9 
10 #include "opencbm.h"
11 
12 #include <ctype.h>
13 #include <getopt.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 
18 #include "arch.h"
19 #include "libmisc.h"
20 
21 static unsigned char dskfrmt[] = {
22 #include "cbmformat.inc"
23 };
24 
25 static void help()
26 {
27  printf(
28 "Usage: cbmformat [OPTION]... DRIVE NAME,ID\n"
29 "Fast CBM-1541 disk formatter\n"
30 "\n"
31 " -h, --help display this help and exit\n"
32 " -V, --version display version information and exit\n"
33 " -@, --adapter=plugin:bus tell OpenCBM which backend plugin and bus to use\n"
34 "\n"
35 " -n, --no-bump do not bump drive head\n"
36 " -x, --extended format 40 track disk\n"
37 " -c, --clear clear (demagnetize) this disk.\n"
38 " this is highly recommended if this disk\n"
39 " is used for the first time.\n"
40 " -v, --verify verify each track after it is written\n"
41 " -o, --original fill sectors with the original pattern\n"
42 " (0x4b, 0x01...) instead of zeroes\n"
43 " -s, --status display drive status after formatting\n"
44 " -p, --progress display progress indicator\n"
45 "\n"
46 );
47 }
48 
49 static void hint(char *s)
50 {
51  fprintf(stderr, "Try `%s' -h for more information.\n", s);
52 }
53 
54 int ARCH_MAINDECL main(int argc, char *argv[])
55 {
56  int status = 0, id_ofs = 0, name_len, i;
57  CBM_FILE fd;
58  unsigned char drive, tracks = 35, bump = 1, orig = 0, show_progress = 0;
59  unsigned char verify = 0;
60  unsigned char demagnetize = 0;
61  char cmd[40], name[20], *arg;
62  int err = 0;
63  char *adapter = NULL;
64  int option;
65 
66  struct option longopts[] =
67  {
68  { "help" , no_argument , NULL, 'h' },
69  { "version" , no_argument , NULL, 'V' },
70  { "adapter" , required_argument, NULL, '@' },
71  { "no-bump" , no_argument , NULL, 'n' },
72  { "extended" , no_argument , NULL, 'x' },
73  { "original" , no_argument , NULL, 'o' },
74  { "status" , no_argument , NULL, 's' },
75  { "progress" , no_argument , NULL, 'p' },
76  { "verify" , no_argument , NULL, 'v' },
77  { "clear" , no_argument , NULL, 'c' },
78 
79  /* undocumented */
80  { "end-track" , required_argument, NULL, 't' },
81  { NULL , 0 , NULL, 0 }
82  };
83 
84  const char shortopts[] ="hVnxospvct:@:";
85  while((option = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1)
86  {
87  switch(option)
88  {
89  case 'n': bump = 0;
90  break;
91  case 'o': orig = 1;
92  break;
93  case 's': status = 1;
94  break;
95  case 'x': tracks = 40;
96  break;
97  case 'h': help();
98  return 0;
99  case 'V': printf("cbmformat %s\n", OPENCBM_VERSION);
100  return 0;
101  case 'p': show_progress = 1;
102  break;
103  case 'v': verify = 1;
104  break;
105  case 'c': demagnetize = 1;
106  break;
107  case 't': tracks = arch_atoc(optarg);
108  break;
109  case '@': if (adapter == NULL)
110  adapter = cbmlibmisc_strdup(optarg);
111  else
112  {
113  fprintf(stderr, "--adapter/-@ given more than once.");
114  hint(argv[0]);
115  return 1;
116  }
117  break;
118  default : hint(argv[0]);
119  return 1;
120  }
121  }
122 
123  if(optind + 2 != argc)
124  {
125  fprintf(stderr, "Usage: %s [OPTION]... DRIVE NAME,ID\n", argv[0]);
126  hint(argv[0]);
127  return 1;
128  }
129 
130  arg = argv[optind++];
131  drive = arch_atoc(arg);
132  if(drive < 8 || drive > 11)
133  {
134  fprintf(stderr, "Invalid drive number (%s)\n", arg);
135  return 1;
136  }
137 
138  arg = argv[optind++];
139  name_len = 0;
140  while(*arg)
141  {
142  unsigned char c;
143  c = (unsigned char) toupper(*arg);
144  if(c == ',')
145  {
146  if(id_ofs)
147  {
148  fprintf(stderr, "More than one `,' in disk name\n");
149  return 1;
150  }
151  id_ofs = name_len;
152  }
153  name[name_len++] = c;
154  if(name_len > 19)
155  {
156  fprintf(stderr, "Disk name too long\n");
157  return 1;
158  }
159  arg++;
160  }
161  name[name_len] = 0;
162 
163  if(cbm_driver_open_ex(&fd, adapter) == 0)
164  {
165  cbm_upload(fd, drive, 0x0500, dskfrmt, sizeof(dskfrmt));
166  sprintf(cmd, "M-E%c%c%c%c%c%c%c%c0:%s", 3, 5, tracks + 1,
167  orig, bump, show_progress, demagnetize, verify, name);
168  cbm_exec_command(fd, drive, cmd, 13+strlen(name));
169 
170  if(show_progress)
171  {
172  /* do some handshake */
174  for(i = 1; i <= tracks; i++)
175  {
176  cbm_iec_wait(fd, IEC_DATA, 1);
177  cbm_iec_set(fd, IEC_CLOCK);
178  cbm_iec_wait(fd, IEC_DATA, 0);
180 
181  printf("#");
182  fflush(stdout);
183  }
184  printf("\n");
185  }
186 
187  err = cbm_device_status(fd, drive, cmd, sizeof(cmd));
188 
189  if(err && status)
190  {
191  printf("%s\n", cmd);
192  }
193 
194  if(!err && (tracks > 35))
195  {
196  cbm_open(fd, drive, 2, "#", 1);
197  cbm_exec_command(fd, drive, "U1:2 0 18 0", 11);
198  cbm_exec_command(fd, drive, "B-P2 192", 8);
199  cbm_listen(fd, drive, 2);
200  while(tracks > 35)
201  {
202  cbm_raw_write(fd, "\021\377\377\001", 4);
203  tracks--;
204  }
205  cbm_unlisten(fd);
206  cbm_exec_command(fd, drive, "U2:2 0 18 0", 11);
207  cbm_close(fd, drive, 2);
208  }
209 
210  if(!err && status)
211  {
212  cbm_device_status(fd, drive, cmd, sizeof(cmd));
213  printf("%s\n", cmd);
214  }
215  cbm_driver_close(fd);
216  cbmlibmisc_strfree(adapter);
217  return 0;
218  }
219  else
220  {
221  arch_error(0, arch_get_errno(), "%s", cbm_get_driver_name_ex(adapter));
222  cbmlibmisc_strfree(adapter);
223  return 1;
224  }
225 }
char * cbmlibmisc_strdup(const char *const OldString)
Duplicate a given string.
Definition: libstring.c:84
int CBMAPIDECL cbm_listen(CBM_FILE HandleDevice, unsigned char DeviceAddress, unsigned char SecondaryAddress)
Send a LISTEN on the IEC serial bus.
Definition: cbm.c:945
void cbmlibmisc_strfree(const char *String)
Free a string.
Definition: libstring.c:172
int CBMAPIDECL cbm_device_status(CBM_FILE HandleDevice, unsigned char DeviceAddress, void *Buffer, size_t BufferLength)
Read the drive status from a floppy.
Definition: cbm.c:1525
int CBMAPIDECL cbm_close(CBM_FILE HandleDevice, unsigned char DeviceAddress, unsigned char SecondaryAddress)
Close a file on the IEC serial bus.
Definition: cbm.c:1072
const char *CBMAPIDECL cbm_get_driver_name_ex(char *Adapter)
Get the name of the driver for a specific parallel port, extended version.
Definition: cbm.c:583
int ARCH_MAINDECL main(int argc, char **argv)
Initialize the xum1541 device This function tries to find and identify the xum1541 device...
Definition: usbcfg.c:38
int CBMAPIDECL cbm_driver_open_ex(CBM_FILE *HandleDevice, char *Adapter)
Opens the driver, extended version.
Definition: cbm.c:683
#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_raw_write(CBM_FILE HandleDevice, const void *Buffer, size_t Count)
Write data to the IEC serial bus.
Definition: cbm.c:870
Definition: getopt.h:94
void CBMAPIDECL cbm_driver_close(CBM_FILE HandleDevice)
Closes the driver.
Definition: cbm.c:768
#define CBM_FILE
Definition: opencbm.h:87
int CBMAPIDECL cbm_unlisten(CBM_FILE HandleDevice)
Send an UNLISTEN on the IEC serial bus.
Definition: cbm.c:1100
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_open(CBM_FILE HandleDevice, unsigned char DeviceAddress, unsigned char SecondaryAddress, const void *Filename, size_t FilenameLength)
Open a file on the IEC serial bus.
Definition: cbm.c:1012
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
int CBMAPIDECL cbm_exec_command(CBM_FILE HandleDevice, unsigned char DeviceAddress, const void *Command, size_t Size)
Executes a command in the floppy drive.
Definition: cbm.c:1599
DLL interface for accessing the driver.
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 IEC_CLOCK
Definition: opencbm.h:98
Some functions for string handling.