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, 3 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

# 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     /* 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     }