ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/cwcbm/common.c
Revision: 1.2
Committed: 2004-01-10T14:05:59Z (20 years, 2 months ago) by cebix
Content type: text/plain
Branch: MAIN
Changes since 1.1: +163 -45 lines
Log Message:
added support for 8050 and 8250 formats

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * common.c - Common parts of readcbm and writecbm
3     *
4     * Written in 2003-2004 by Christian Bauer <Christian.Bauer@uni-mainz.de>
5     */
6    
7     #include "catweasel.h"
8     #include "common.h"
9    
10    
11 cebix 1.2 /* Effective crystal frequencies */
12     #define CRYSTAL_FREQ_1541 4000000 // 4 MHz
13     #define CRYSTAL_FREQ_8050 6000000 // 6 MHz
14 cebix 1.1
15 cebix 1.2 /* CBM drive RPM */
16 cebix 1.1 #define NOMINAL_RPM 300
17    
18     /* Catweasel frequency (7 MHz) */
19     #define CW_FREQ 7080500.0
20    
21 cebix 1.2
22     /* 1541 disk format */
23     static const int bps_1541[4] = {
24     CRYSTAL_FREQ_1541 / 16, CRYSTAL_FREQ_1541 / 15,
25     CRYSTAL_FREQ_1541 / 14, CRYSTAL_FREQ_1541 / 13
26 cebix 1.1 };
27    
28 cebix 1.2 static const int std_speed_1541[36] = {
29 cebix 1.1 0,
30     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
31     2, 2, 2, 2, 2, 2, 2,
32     1, 1, 1, 1, 1, 1,
33     0, 0, 0, 0, 0
34     };
35    
36 cebix 1.2 static const int num_sectors_1541[36] = {
37 cebix 1.1 0,
38     21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
39     19,19,19,19,19,19,19,
40     18,18,18,18,18,18,
41     17,17,17,17,17
42     };
43    
44 cebix 1.2 static const struct format_t format_1541 = {
45     1, // sides
46     35, // tracks_per_side
47     bps_1541, // bps
48     std_speed_1541, // std_speed
49     num_sectors_1541 // num_sectors
50     };
51    
52     /* 8050 disk format */
53     static const int bps_8050[4] = {
54     CRYSTAL_FREQ_8050 / 16, CRYSTAL_FREQ_8050 / 15,
55     CRYSTAL_FREQ_8050 / 14, CRYSTAL_FREQ_8050 / 13
56     };
57    
58     static const int std_speed_8050[78] = {
59     0,
60     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
61     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
62     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
63     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
64     };
65    
66     static const int num_sectors_8050[78] = {
67     0,
68     29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
69     27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
70     25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
71     23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23
72     };
73    
74     static const struct format_t format_8050 = {
75     1, // sides
76     77, // tracks_per_side
77     bps_8050, // bps
78     std_speed_8050, // std_speed
79     num_sectors_8050 // num_sectors
80     };
81    
82     /* 8250 disk format */
83     static const int std_speed_8250[155] = {
84     0,
85     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
86     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
87     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
88     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
89     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
90     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
91     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
92     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
93     };
94    
95     static const int num_sectors_8250[155] = {
96     0,
97     29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
98     27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
99     25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
100     23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
101     29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
102     27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
103     25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
104     23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23
105     };
106    
107     static const struct format_t format_8250 = {
108     2, // sides
109     77, // tracks_per_side
110     bps_8050, // bps
111     std_speed_8250, // std_speed
112     num_sectors_8250 // num_sectors
113     };
114    
115     /* Selected format */
116     const struct format_t *format = NULL;
117    
118 cebix 1.1
119     /* Command line arguments */
120     int drive_num = 0;
121     int drive_rpm = 360;
122     int drive_40tracks = 0;
123 cebix 1.2 int steps_per_track = 1;
124 cebix 1.1 const char *file_name;
125    
126    
127     /* Catweasel controller struct */
128     catweasel_contr c;
129    
130    
131     /* Clock table (nominal number of Catweasel clocks per inter-flux-change gap) */
132     int clock_table[4] = {0, 0, 0, 0};
133    
134     /* Threshold table */
135     int thresh_table[3] = {0, 0, 0};
136    
137    
138     /* Track buffer */
139     unsigned char track_buf[MAX_SECTORS * SECTOR_SIZE];
140    
141    
142     /* Print usage information */
143     static void usage(const char *prgname)
144     {
145     fprintf(stderr,
146     "Reads/writes CBM formatted disks with the Catweasel controller\n\n"
147     "Usage: %s <options> <file>\n\n"
148     "Options:\n"
149     " -h | --help this text\n"
150     " -p | --port n Catweasel I/O port address (hex, required)\n"
151     " -d | --drive n drive number (0 or 1)\n"
152 cebix 1.2 " -f | --format n disk format type (1541, 8050, or 8250)\n"
153 cebix 1.1 " -4 | --40tracks assume 300RPM 40-track drive\n",
154     prgname
155     );
156     exit(1);
157     }
158    
159    
160     /* Parse command line arguments */
161     void parse_args(int argc, char **argv)
162     {
163     static struct option long_opts[] = {
164     {"help", 0, 0, 'h'},
165     {"port", 1, 0, 'p'},
166     {"drive", 1, 0, 'd'},
167 cebix 1.2 {"format", 1, 0, 'f'},
168 cebix 1.1 {"40tracks", 0, 0, '4'},
169     {NULL, 0, 0, 0}
170     };
171    
172 cebix 1.2 int format_type = 0;
173    
174 cebix 1.1 // Init Catweasel struct
175     memset(&c, 0, sizeof(c));
176     c.msdelay = msdelay;
177    
178     // Parse arguments
179     for (;;) {
180     int ch;
181 cebix 1.2 if ((ch = getopt_long(argc, argv, "hp:d:f:4", long_opts, NULL)) == -1)
182 cebix 1.1 break;
183    
184     switch (ch) {
185     case 0: /* Long option */
186     break;
187     case 'p':
188     c.iobase = strtol(optarg, NULL, 16);
189     break;
190     case 'd':
191     drive_num = atoi(optarg);
192     if (drive_num < 0 || drive_num > 1)
193     usage(argv[0]);
194     break;
195 cebix 1.2 case 'f':
196     format_type = atoi(optarg);
197     if (format_type == 1541 || format_type == 8050 || format_type == 8250)
198     select_format(format_type);
199     else
200     usage(argv[0]);
201     break;
202 cebix 1.1 case '4':
203     drive_rpm = 300;
204     drive_40tracks = 1;
205     break;
206     case 'h':
207     default:
208     usage(argv[0]);
209     break;
210     }
211     }
212    
213     if (optind >= argc)
214     usage(argv[0]);
215     else
216     file_name = argv[optind];
217    
218     // Check for consistency
219     if (c.iobase == 0)
220     usage(argv[0]);
221 cebix 1.2 if (format_type == 0)
222     select_format(1541);
223     if (format->tracks_per_side >= 40 && drive_40tracks) {
224     fprintf(stderr, "Can't use 80 track disk format on 40 track drive\n");
225     exit(1);
226     }
227     if (format->tracks_per_side < 40 && !drive_40tracks)
228     steps_per_track = 2; // double step
229 cebix 1.1
230     // Set Catweasel type
231     if (c.iobase < 0x1000)
232     c.type = CATWEASEL_TYPE_MK1;
233     else
234     c.type = CATWEASEL_TYPE_MK3;
235     }
236    
237    
238     /* Obtain access to I/O ports */
239     void ioport_access(void)
240     {
241     if ((c.type == CATWEASEL_TYPE_MK1 && ioperm(c.iobase, 8, 1) == -1)
242     || (c.type == CATWEASEL_TYPE_MK3 && iopl(3) == -1)) {
243     fprintf(stderr, "No access to I/O ports\n");
244     exit(1);
245     }
246     setuid(getuid());
247 cebix 1.2 }
248    
249    
250     /* Delay specified number of milliseconds */
251     void msdelay(int ms)
252     {
253     usleep(ms * 1000);
254     }
255    
256    
257     /* Select disk format */
258     void select_format(int type)
259     {
260     switch (type) {
261     case 1541:
262     format = &format_1541;
263     break;
264     case 8050:
265     format = &format_8050;
266     break;
267     case 8250:
268     format = &format_8250;
269     break;
270     default:
271     fprintf(stderr, "Invalid disk format type\n");
272     exit(1);
273     }
274     }
275    
276    
277     /* Set speed zone and tables */
278     static void set_zone(int track)
279     {
280     int zone = format->std_speed[track];
281     int bps = format->bps[zone];
282     clock_table[0] = 0;
283     clock_table[1] = CW_FREQ * NOMINAL_RPM * 1 / (bps * drive_rpm);
284     clock_table[2] = CW_FREQ * NOMINAL_RPM * 2 / (bps * drive_rpm);
285     clock_table[3] = CW_FREQ * NOMINAL_RPM * 3 / (bps * drive_rpm);
286     thresh_table[0] = (clock_table[0] + clock_table[1]) / 2;
287     thresh_table[1] = (clock_table[1] + clock_table[2]) / 2;
288     thresh_table[2] = (clock_table[2] + clock_table[3]) / 2;
289     }
290    
291    
292     /* Seek to given CBM track (1..35) and select correct side and speed zone */
293     void seek_to(int drive, int track)
294     {
295     // Set speed zone and tables
296     set_zone(track);
297    
298     // Seek to track
299     int cw_track = ((track - 1) % format->tracks_per_side) * steps_per_track;
300     //cw_track -= 3;
301     //if (cw_track < 0) cw_track = 0;
302     catweasel_seek(c.drives + drive, cw_track);
303     msdelay(20);
304 cebix 1.1 }
305    
306    
307     /* Start drive */
308     void start_drive(int drive)
309     {
310     catweasel_select(&c, drive == 0, drive == 1);
311     catweasel_set_motor(c.drives + drive, 1);
312     msdelay(500);
313     catweasel_seek(c.drives + drive, 0);
314     msdelay(20);
315     }
316    
317    
318     /* Stop drive */
319     void stop_drive(int drive)
320     {
321     catweasel_set_motor(c.drives + drive, 0);
322     catweasel_select(&c, 0, 0);
323     }