Commit | Line | Data |
---|---|---|
a6a4e5d4 PH |
1 | #include <stdio.h> |
2 | #include <unistd.h> | |
3 | #include <stdlib.h> | |
4 | #include <stdint.h> | |
5 | #include <fcntl.h> | |
6 | #include <string.h> | |
7 | #include <errno.h> | |
8 | #include <getopt.h> | |
9 | ||
10 | #include "speed8.h" | |
11 | #include "link.h" | |
12 | #include "rk05.h" | |
13 | #include "memory.h" | |
14 | #include "log.h" | |
15 | ||
16 | #define PORT "/dev/ttyUSB0" | |
17 | ||
18 | int fd; | |
19 | ||
20 | static const struct option longopts[]={ | |
21 | {"help",0,NULL,'h'}, | |
22 | {"read",0,NULL,'r'}, | |
23 | {"write",0,NULL,'w'}, | |
24 | {"verbose",0,NULL,'v'}, | |
25 | {"port",1,NULL,'p'}, | |
26 | {"drive",1,NULL,'d'}, | |
27 | {"quiet",0,NULL,'q'}, | |
28 | {"loglevel",1,NULL,'l'}, | |
29 | {"verify",0,NULL,'V'}, | |
30 | {NULL} | |
31 | }; | |
32 | ||
33 | static const char optstring[]="hrwvp:d:l:qV"; | |
34 | ||
35 | static void help(void){ | |
36 | fprintf(stderr, "\ | |
37 | \n\ | |
38 | Usage: rktool {-r|-w} [-v] [-V] [-h] [-d<unit_number>] [-l<loglevel>] <imagefile>\n\ | |
39 | \n\ | |
40 | This tool will help you to backup restore RK05 media on a PDP8 running speed8.\n\ | |
41 | \n\ | |
42 | Options:\n\ | |
43 | \n\ | |
44 | -r, --read Read disk (default if nothing specified)\n\ | |
45 | -w, --write Write disk\n\ | |
46 | -d, --drive= Select drive number 0-3 (defaults to 0)\n\ | |
47 | -p, --port= Serial port to use (defaults to /dev/ttyUSB0)\n\ | |
48 | -V, --verify Verify after read or write\n\ | |
49 | -v, --verbose Be verbose\n\ | |
50 | -q, --quiet Be quiet, opposite of -v\n\ | |
51 | -l, --loglevel= Set loglevel for debugging purposes\n\ | |
52 | -h, --help Display this help and exit\n\ | |
53 | \n\ | |
54 | "); | |
55 | exit(100); | |
56 | } | |
57 | ||
58 | static char defaultport[]=PORT; | |
59 | ||
60 | int main(int argc, char ** argv){ | |
61 | int res; | |
62 | int e; | |
63 | ||
64 | int drive=0; | |
65 | #define READ 0 | |
66 | #define WRITE 1 | |
67 | int action=READ; | |
68 | char * port=defaultport; | |
69 | char * file=NULL; | |
70 | int verify=0; | |
71 | char opt; | |
72 | ||
73 | opterr=1; | |
74 | opt=getopt_long(argc,argv,optstring,longopts,NULL); | |
75 | ||
76 | while(opt>0){ | |
77 | switch(opt){ | |
78 | case 'v': | |
79 | loglevel++; | |
80 | break; | |
81 | case 'h': | |
82 | help(); | |
83 | break; | |
84 | case 'r': | |
85 | action=READ; | |
86 | break; | |
87 | case 'w': | |
88 | action=WRITE; | |
89 | break; | |
90 | case 'p': | |
91 | if (!optarg) { | |
92 | error("-p needs an argument!\n"); | |
93 | exit(1); | |
94 | } | |
95 | port=optarg; | |
96 | break; | |
97 | case 'd': | |
98 | if (!optarg) { | |
99 | error("-d needs an argument!\n"); | |
100 | exit(1); | |
101 | } | |
102 | drive=strtol(optarg, NULL, 0); | |
103 | break; | |
104 | case 'q': | |
105 | loglevel=LL_QUIET; | |
106 | break; | |
107 | case 'l': | |
108 | if (!optarg) { | |
109 | error("-l needs an argument!\n"); | |
110 | exit(1); | |
111 | } | |
112 | loglevel=strtol(optarg,NULL,0); | |
113 | break; | |
114 | case 'V': | |
115 | verify=1; | |
116 | break; | |
117 | case '?': | |
118 | help(); | |
119 | break; | |
120 | } | |
121 | opt=getopt_long(argc,argv,optstring,longopts,NULL); | |
122 | } | |
123 | ||
124 | file=argv[optind]; | |
125 | ||
126 | if (!file) { | |
127 | fprintf(stderr,"Error: No file specified!\n"); | |
128 | help(); | |
129 | } | |
130 | ||
131 | debug("Opening port \"%s\".\n",port); | |
132 | debug("Image file: %s\n", file); | |
133 | debug("Flushing first\n"); | |
134 | ||
135 | res=link_flush(port); | |
136 | ||
137 | if (res <0){ | |
138 | ERROR perror("While initializing link"); | |
139 | return -1; | |
140 | } | |
141 | debug("Opening for real now\n"); | |
142 | res=link_open(port); | |
143 | if (res <0){ | |
144 | ERROR perror("While initializing link"); | |
145 | return -1; | |
146 | } | |
147 | ||
148 | if (action==WRITE){ | |
149 | uint16_t origin[RK05_DISKSIZE]; | |
150 | uint16_t readback[RK05_DISKSIZE]; | |
151 | ||
152 | int fd=open(file,O_RDONLY); | |
153 | if (fd<0){ | |
154 | ERROR perror("While opening file"); | |
155 | exit(2); | |
156 | } | |
157 | res=read(fd,(char*)origin,sizeof(origin)); | |
158 | WARN if (res<RK05_DISKSIZE*2) | |
159 | warn("Read only %i bytes! Hope, that's ok.\n",res); | |
160 | close(fd); | |
161 | ||
162 | res=rk05_write_disk(drive,origin); | |
163 | if(res<0){ | |
164 | ERROR perror("While writing disk image"); | |
165 | exit(3); | |
166 | } | |
167 | ||
168 | if (verify){ | |
169 | info("Reading back image.\n"); | |
170 | res=rk05_read_disk(drive,readback); | |
171 | if(res<0){ | |
172 | ERROR perror("While reading disk image"); | |
173 | exit(3); | |
174 | } | |
175 | int i; | |
176 | e=0; | |
177 | int cylinder,side,sector,word; | |
178 | for (cylinder=0; cylinder<RK05_CYLINDERS;cylinder++) | |
179 | for (side=0; side<1; side++) | |
180 | for (sector=0; sector<16; sector++) | |
181 | for (word=0; word<256; word++){ | |
182 | i=cylinder*2*16*256+side*16*256+sector*256+word; | |
183 | if (readback[i]!=origin[i]){ | |
184 | error("Verify mismatch! Cylinder %i, Side %i, Sector %i, Word %i\n", | |
185 | cylinder,side,sector,word); | |
186 | e++; | |
187 | } | |
188 | } | |
189 | if (e) { | |
190 | error("Found %i verify errors!\n",e); | |
191 | exit(3); | |
192 | } | |
193 | } // verify | |
194 | } // WRITE | |
195 | ||
196 | if (action==READ){ | |
197 | ||
198 | uint16_t target[RK05_DISKSIZE]; | |
199 | uint16_t target2[RK05_DISKSIZE]; | |
200 | ||
201 | info("Reading drive %i\n",drive); | |
202 | res=0; | |
203 | res=rk05_read_disk(drive,target); | |
204 | if(res<0){ | |
205 | ERROR perror("While reading disk image"); | |
206 | exit(3); | |
207 | } | |
208 | if (verify){ | |
209 | e=0; | |
210 | info("Reading again\n"); | |
211 | res=rk05_read_disk(drive,target2); | |
212 | if(res<0){ | |
213 | ERROR perror("While reading disk image"); | |
214 | exit(3); | |
215 | } | |
216 | int i; | |
217 | for (i=0; i<RK05_DISKSIZE ;i++){ | |
218 | debug("verify: %i\n",i); | |
219 | if (target[i]!=target2[i]){ | |
220 | error("Verify mismatch! Cylinder %i, Side %i, Sector %i, Word %i\n", | |
221 | i>>13,(i>>12)&1,(i>>8)&15,i&256); | |
222 | e++; | |
223 | } | |
224 | } | |
225 | } | |
226 | int fd=open(file,O_WRONLY|O_CREAT|O_TRUNC,0640); | |
227 | if (fd<0){ | |
228 | ERROR perror("While opening file"); | |
229 | exit(2); | |
230 | } | |
231 | debug("File \"%s\" opened.\n",file); | |
232 | res=write(fd,target,sizeof(target)); | |
233 | if (res!=sizeof(target)){ | |
234 | ERROR perror ("While writing file to disk"); | |
235 | exit(1); | |
236 | } | |
237 | ||
238 | } | |
239 | ||
240 | link_close(); | |
241 | link_flush(file); | |
242 | if (e) { | |
243 | error("Found %i verify errors!\n",e); | |
244 | exit(5); | |
245 | } | |
246 | return 0; | |
247 | } |