12 /* Commands for the RK8E controller */
13 #define RK_CM_READ 00000
14 #define RK_CM_SEEK_ONLY 03000
15 #define RK_CM_WRITE 04000
16 #define RK_CM_TRANS256 00000
17 #define RK_CM_TRANS128 00100
19 static char * bars(int width
, int max
, int current
){
20 static char buffer
[100];
21 if (width
>80) width
=80;
25 float current_f
=current
;
26 float step
=width_f
/max_f
;
27 float dots
=step
*current_f
;
28 int actual
=round(dots
);
31 for (i
=0; i
<width
; i
++){
32 if (i
<actual
) buffer
[i
+1]='*';
35 int perc
=round((current_f
/max_f
)*100);
36 sprintf(buffer
+width
+2," %3i%%",perc
);
40 int rk05_write_sector(uint8_t drive
, uint16_t disk_address
, uint16_t mem_address
){
42 debug("rk05_write_sector(): Drive %i, DA: %05o, CA: %04o\n",drive
,disk_address
, mem_address
);
43 if ((disk_address
>=203*2*16*256)||(mem_address
>4095)||(drive
>3)) {
44 debug("rk05_write_sector(): Invalid parameters!\n");
50 cb
[2]=mem_address
; // Current address
51 cb
[3]=RK_CM_WRITE
|(drive
&3)<<1
52 | ((disk_address
>>12)&1)
55 cb
[4]=disk_address
&07777;
56 return link_write(cb
,5);
59 int rk05_read_sector(uint8_t drive
, uint16_t disk_address
, uint16_t mem_address
){
60 debug("rk05_read_sector(): Drive %i, DA: %05o, CA: %04o\n",drive
,disk_address
, mem_address
);
62 if ((disk_address
>=RK05_TRACKS
*16)||(mem_address
>4095)||(drive
>3)) {
63 debug("rk05_read_sector(): Invalid parameters!\n");
69 cb
[2]=mem_address
; // Current address
70 cb
[3]=RK_CM_READ
|(drive
&3)<<1
71 | ((disk_address
>>12)&1)
73 cb
[4]=disk_address
&07777;
78 int rk05_write_track(uint8_t drive
, uint16_t track
){
80 uint16_t sector
=track
*16+0;
81 debug("rk05_write_track(): Drive %i, Track: %i\n",drive
,track
);
82 if ((drive
>3)||(track
>=RK05_TRACKS
)){
83 debug("rk05_write_track(): Invalid parameters!\n");
92 return link_write(cb
,4);
95 int rk05_read_track(uint8_t drive
, uint16_t track
){
97 uint16_t sector
=track
*16+0;
98 debug("rk05_read_track(): Drive %i, Track: %i\n",drive
,track
);
99 if ((drive
>3)||(track
>=RK05_TRACKS
)){
100 debug("rk05_read_track(): Invalid parameters!\n");
105 cb
[1]=CMD_RK_R_TRACK
;
109 return link_write(cb
,4);
112 int rk05_status(uint16_t * status
){
115 debug("rk05_status()\n");
118 res
=link_write(cb
,2);
119 if (res
<0) return res
;
121 if (res
<0) return res
;
122 if (status
) *status
=cb
[0];
123 debug("rk05_status(): %04o\n",cb
[0]);
127 int rk05_recalibrate(uint8_t drive
){
129 debug("rk05_recalibrate(): Drive: %i\n",drive
);
131 debug("rk05_recalibrate(): Invalid drive!\n");
136 cb
[1]=CMD_RK_RECAL0
+ 0100*drive
;
137 return link_write(cb
,2);
141 int order1
[16]={0, 2, 4, 6, 8, 10, 12, 14, 1,3,5,7,9,11,13,15};
142 int order2
[16]={0, 3, 6, 9, 12, 15, 1, 4, 7,10,13,2,5,8,11,14};
143 int order3
[16]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
144 int order4
[16]={0,4,8,12,1,5,9,13,2,6,10,14,3,7,11,15};
146 int rk05_read_disk(uint8_t disk
, uint16_t * target
){
154 res
=rk05_recalibrate(disk
);
155 if (res
<0) return res
;
156 res
=rk05_status(&status
);
157 if (res
<0) return res
;
158 if (status
!= RK05_STATUS_OK
){
159 err("Status error while recalibrating!\n");
160 ERROR
rk05_perror(status
);
165 for (track
=0; track
<RK05_TRACKS
; track
++){
166 info("\rReading drive %i: CYL: %3i, SIDE: %i %s",
167 disk
, track
/2, track
%2,bars(70,RK05_TRACKS
-1,track
));
168 res
=rk05_read_track(disk
, track
);
169 if (res
<0) return res
;
170 res
=rk05_status(&status
);
171 if (res
<0) return res
;
173 if (status
!= RK05_STATUS_OK
){
175 info("\nAn error occured!\n");
176 INFO
rk05_perror(status
);
177 warning("Reading of track %i failed. Will try individual sectors now.\n", track
);
178 res
=rk05_recalibrate(disk
);
179 if (res
<0) return res
;
180 res
=rk05_status(&status
);
181 if (res
<0) return res
;
182 for (sector
=0; sector
<16; sector
++){
185 debug("Reading sector %i with %i tries left\n",sector
,retries
);
186 res
=rk05_read_sector(disk
,track
*16+order2
[sector
],order2
[sector
]*0400);
187 if (res
<0) return res
;
188 res
=rk05_status(&status
);
189 if (res
<0) return res
;
190 if (status
!= RK05_STATUS_OK
){
192 warning("Error on sector %i, will retry %i times.\n",sector
, retries
);
193 INFO
rk05_perror(status
);
194 res
=rk05_recalibrate(disk
);
195 if (res
<0) return res
;
196 res
=rk05_status(&status
);
197 if (res
<0) return res
;
205 err("Failed to read track %i. Giving up.\n",track
);
209 warning("Now it succeeded.\n");
212 res
=get_buffer(target
+(4096*track
));
213 if(res
<0) return res
;
216 debug("rk05_read_disk():Success\n");
220 int rk05_write_disk(uint8_t disk
, uint16_t * target
){
228 res
=rk05_recalibrate(disk
);
229 if (res
<0) return res
;
230 res
=rk05_status(&status
);
231 if (res
<0) return res
;
232 if (status
!= RK05_STATUS_OK
){
233 err("Status error while recalibrating!\n");
234 ERROR
rk05_perror(status
);
238 for (track
=0; track
<RK05_TRACKS
; track
++){
239 info("\rWriting drive %i: CYL: %3i, SIDE: %i %s", disk
, track
/2, track
%2, bars(70,RK05_TRACKS
-1,track
));
240 res
=put_buffer(target
+(4096*track
));
241 if (res
<0) return res
;
242 res
=rk05_write_track(disk
,track
);
243 if (res
<0) return res
;
244 res
=rk05_status(&status
);
245 if (res
<0) return res
;
247 if (status
!= RK05_STATUS_OK
){
249 info ("\nAn error occured!\n");
250 INFO
rk05_perror(status
);
251 warning("Writing of track %i failed. Will try individual sectors now.\n", track
);
252 res
=rk05_recalibrate(disk
);
253 if (res
<0) return res
;
254 res
=rk05_status(&status
);
255 if (res
<0) return res
;
256 for (sector
=0; sector
<16; sector
++){
259 debug("Writing sector %i with %i tries left\n",order2
[sector
],retries
);
260 res
=rk05_write_sector(disk
,track
*16+order2
[sector
],order2
[sector
]*0400);
261 if (res
<0) return res
;
262 res
=rk05_status(&status
);
263 if (res
<0) return res
;
264 if (status
!= RK05_STATUS_OK
){
266 warning("Error on sector %i, will retry %i times.\n",order2
[sector
], retries
);
267 INFO
rk05_perror(status
);
268 res
=rk05_recalibrate(disk
);
269 if (res
<0) return res
;
270 res
=rk05_status(&status
);
271 if (res
<0) return res
;
279 err("Failed to write track %i. Giving up.\n",track
);
283 warning("Now it succeeded.\n");
288 debug("rk05_write_disk():Success\n");
292 void rk05_perror(uint16_t status
){
293 fprintf(stderr
, "Status: %s\n",(status
&04000?"Done":"Busy"));
294 if (status
& 02000) fprintf(stderr
,"Head in motion.\n");
295 if (status
& 00400) fprintf(stderr
,"Seek fail\n");
296 if (status
& 00200) fprintf(stderr
,"File not ready\n");
297 if (status
& 00100) fprintf(stderr
,"Control busy\n");
298 if (status
& 00040) fprintf(stderr
,"Timing error");
299 if (status
& 00020) printf("Write lock error\n");
300 if (status
& 00010) fprintf(stderr
,"Parity error\n");
301 if (status
& 00004) fprintf(stderr
,"Data request late\n");
302 if (status
& 00002) fprintf(stderr
,"Drive status error\n");
303 if (status
& 00001) fprintf(stderr
,"Cylinder address error\n");