ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/cwcbm/common.c
Revision: 1.1
Committed: 2004-01-07T16:53:58Z (20 years, 2 months ago) by cebix
Content type: text/plain
Branch: MAIN
Log Message:
- better argument parsing
- drive type (40/80 tracks) selectable with command line option
- works with Catweasel PCI MK3

File Contents

# Content
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 /* 1541 crystal frequency (16 MHz) */
12 #define CRYSTAL_FREQ 16000000
13
14 /* 1541 RPM */
15 #define NOMINAL_RPM 300
16
17 /* Catweasel frequency (7 MHz) */
18 #define CW_FREQ 7080500.0
19
20 /* Bit rate for each speed zone */
21 const int bps[4] = {
22 CRYSTAL_FREQ / 16 / 4, CRYSTAL_FREQ / 15 / 4,
23 CRYSTAL_FREQ / 14 / 4, CRYSTAL_FREQ / 13 / 4
24 };
25
26 /* Standard speeds for tracks */
27 const int std_speed[NUM_TRACKS + 1] = {
28 0,
29 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
30 2, 2, 2, 2, 2, 2, 2,
31 1, 1, 1, 1, 1, 1,
32 0, 0, 0, 0, 0
33 };
34
35 /* Number of sectors per track, for all tracks */
36 const int num_sectors[NUM_TRACKS + 1] = {
37 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
45 /* Command line arguments */
46 int drive_num = 0;
47 int drive_rpm = 360;
48 int drive_40tracks = 0;
49 const char *file_name;
50
51
52 /* Catweasel controller struct */
53 catweasel_contr c;
54
55
56 /* Clock table (nominal number of Catweasel clocks per inter-flux-change gap) */
57 int clock_table[4] = {0, 0, 0, 0};
58
59 /* Threshold table */
60 int thresh_table[3] = {0, 0, 0};
61
62
63 /* Track buffer */
64 unsigned char track_buf[MAX_SECTORS * SECTOR_SIZE];
65
66
67 /* Delay specified number of milliseconds */
68 void msdelay(int ms)
69 {
70 usleep(ms * 1000);
71 }
72
73
74 /* Set speed zone and tables */
75 static void set_zone(int track)
76 {
77 int zone = std_speed[track];
78 clock_table[0] = 0;
79 clock_table[1] = CW_FREQ * NOMINAL_RPM * 1 / (bps[zone] * drive_rpm);
80 clock_table[2] = CW_FREQ * NOMINAL_RPM * 2 / (bps[zone] * drive_rpm);
81 clock_table[3] = CW_FREQ * NOMINAL_RPM * 3 / (bps[zone] * drive_rpm);
82 thresh_table[0] = (clock_table[0] + clock_table[1]) / 2;
83 thresh_table[1] = (clock_table[1] + clock_table[2]) / 2;
84 thresh_table[2] = (clock_table[2] + clock_table[3]) / 2;
85 }
86
87
88 /* Seek to given CBM track (1..35) and select correct side and speed zone */
89 void seek_to(int drive, int track)
90 {
91 // Set speed zone and tables
92 set_zone(track);
93
94 // Seek to track
95 catweasel_seek(c.drives + drive, (track - 1) * (drive_40tracks ? 1 : 2));
96 msdelay(20);
97 }
98
99
100 /* Print usage information */
101 static void usage(const char *prgname)
102 {
103 fprintf(stderr,
104 "Reads/writes CBM formatted disks with the Catweasel controller\n\n"
105 "Usage: %s <options> <file>\n\n"
106 "Options:\n"
107 " -h | --help this text\n"
108 " -p | --port n Catweasel I/O port address (hex, required)\n"
109 " -d | --drive n drive number (0 or 1)\n"
110 " -4 | --40tracks assume 300RPM 40-track drive\n",
111 prgname
112 );
113 exit(1);
114 }
115
116
117 /* Parse command line arguments */
118 void parse_args(int argc, char **argv)
119 {
120 static struct option long_opts[] = {
121 {"help", 0, 0, 'h'},
122 {"port", 1, 0, 'p'},
123 {"drive", 1, 0, 'd'},
124 {"40tracks", 0, 0, '4'},
125 {NULL, 0, 0, 0}
126 };
127
128 // Init Catweasel struct
129 memset(&c, 0, sizeof(c));
130 c.msdelay = msdelay;
131
132 // Parse arguments
133 for (;;) {
134 int ch;
135 if ((ch = getopt_long(argc, argv, "hp:d:4", long_opts, NULL)) == -1)
136 break;
137
138 switch (ch) {
139 case 0: /* Long option */
140 break;
141 case 'p':
142 c.iobase = strtol(optarg, NULL, 16);
143 break;
144 case 'd':
145 drive_num = atoi(optarg);
146 if (drive_num < 0 || drive_num > 1)
147 usage(argv[0]);
148 break;
149 case '4':
150 drive_rpm = 300;
151 drive_40tracks = 1;
152 break;
153 case 'h':
154 default:
155 usage(argv[0]);
156 break;
157 }
158 }
159
160 if (optind >= argc)
161 usage(argv[0]);
162 else
163 file_name = argv[optind];
164
165 // Check for consistency
166 if (c.iobase == 0)
167 usage(argv[0]);
168
169 // Set Catweasel type
170 if (c.iobase < 0x1000)
171 c.type = CATWEASEL_TYPE_MK1;
172 else
173 c.type = CATWEASEL_TYPE_MK3;
174 }
175
176
177 /* Obtain access to I/O ports */
178 void ioport_access(void)
179 {
180 if ((c.type == CATWEASEL_TYPE_MK1 && ioperm(c.iobase, 8, 1) == -1)
181 || (c.type == CATWEASEL_TYPE_MK3 && iopl(3) == -1)) {
182 fprintf(stderr, "No access to I/O ports\n");
183 exit(1);
184 }
185 setuid(getuid());
186 }
187
188
189 /* Start drive */
190 void start_drive(int drive)
191 {
192 catweasel_select(&c, drive == 0, drive == 1);
193 catweasel_set_motor(c.drives + drive, 1);
194 msdelay(500);
195 catweasel_seek(c.drives + drive, 0);
196 msdelay(20);
197 }
198
199
200 /* Stop drive */
201 void stop_drive(int drive)
202 {
203 catweasel_set_motor(c.drives + drive, 0);
204 catweasel_select(&c, 0, 0);
205 }