source: thomson/tools/sap/lfloppy.c@ 134f1c4

main
Last change on this file since 134f1c4 was 134f1c4, checked in by Adrien Destugues <pulkomandy@…>, 12 years ago

Add sapfs (Vital Motion modified code...)

git-svn-id: svn://localhost/thomson@21 85ae3b6b-dc8f-4344-a89d-598714f2e4e5

  • Property mode set to 100644
File size: 8.5 KB
Line 
1/* Lecture des disquettes Thomson sous Linux
2 * Version 2.1
3 * Copyright (C) 2000-2003 Eric Botcazou
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20
21#ifndef SCAN_DEPEND
22 #include <stdio.h>
23 #include <fcntl.h>
24 #include <unistd.h>
25 #include <sys/ioctl.h>
26 #include <linux/fd.h>
27 #include <linux/fdreg.h>
28#endif
29
30#include "floppy.h"
31
32
33#define DISK_RETRY 4
34#define RETRY2 10
35
36static int rw_flag;
37static int fd[2] = {-1, -1};
38static int drive_type[2];
39
40#define IS_5_INCHES(drive) ((drive_type[drive]>0) && (drive_type[drive]<3))
41
42#define SET_NO_MULTITRACK(lval) (lval &= ~0x80)
43#define SET_NO_MFM(lval) (lval &= ~0x40)
44
45
46
47/* ResetDrive:
48 * Réinitialise le lecteur de disquettes.
49 */
50static void ResetDrive(int drive, int density)
51{
52 struct floppy_struct fd_prm;
53
54 fd_prm.head = (density == 1 ? 1 : 2); /* nr of heads */
55 fd_prm.track = (IS_5_INCHES(drive) ? 40 : 80); /* nr of tracks */
56 fd_prm.sect = (density == 1 ? 4 : 8); /* sectors per track (512-byte sector) */
57 fd_prm.size = fd_prm.head * fd_prm.track * fd_prm.sect; /* nr of sectors total */
58 fd_prm.stretch = 0;
59 fd_prm.gap = 0x1B;
60 fd_prm.rate = (density == 1 ? 0xB1 : 0x3A); /* cf /usr/include/linux/fd.h */
61 fd_prm.spec1 = 0xDF;
62 fd_prm.fmt_gap = 0x2C;
63
64 ioctl(fd[drive], FDSETPRM, &fd_prm);
65}
66
67
68
69/* OpenDrive:
70 * Obtient le descripteur de fichier pour le lecteur de disquettes.
71 */
72static int OpenDrive(int drive, int density)
73{
74 char dev_str[16];
75
76 snprintf(dev_str, sizeof(dev_str), "/dev/fd%d", drive);
77
78 if (rw_flag) {
79 if ((fd[drive]=open(dev_str, O_RDWR | O_NDELAY))>=0)
80 goto success;
81 }
82 else {
83 if ((fd[drive]=open(dev_str, O_RDONLY | O_NDELAY))>=0)
84 goto success;
85 }
86
87 return 0;
88
89 success:
90 ResetDrive(drive, density);
91 return 1;
92}
93
94
95
96/* ExecCommand:
97 * Exécute la commande spécifiée via l'appel ioctl() FDRAWCMD.
98 */
99static int ExecCommand2(int drive, int density, struct floppy_raw_cmd *fd_cmd);
100
101static int ExecCommand(int drive,int density, struct floppy_raw_cmd *fd_cmd) {
102 int i,ret;
103 for (i=0;i<RETRY2;i++) {
104 if ((ret=ExecCommand2(drive,density,fd_cmd))==0) return 0;
105 ResetDrive(drive,density);
106}
107return ret;
108}
109
110static int ExecCommand2(int drive, int density, struct floppy_raw_cmd *fd_cmd)
111{
112 int i, ret = 0;
113
114 if (fd[drive]<0 && !OpenDrive(drive, density))
115 return 0x10; /* lecteur non prêt */
116
117 for (i=0; i<DISK_RETRY; i++) {
118 ret=ioctl(fd[drive], FDRAWCMD, fd_cmd);
119
120 if (ret >= 0)
121 break;
122
123 ResetDrive(drive, density);
124 }
125
126 if (ret<0)
127 return 0x10; /* lecteur non prêt */
128
129#ifdef DEBUG
130 printf("fd_cmd reply: ");
131 for (i=0; i<3; i++)
132 printf("ST%d=%02x ", i, fd_cmd->reply[i]);
133 printf("\n");
134#endif
135
136 switch (fd_cmd->reply[1]) { /* ST1 */
137
138 case 0x01: /* Missing Address Mark */
139 return 0x04; /* erreur sur l'adresse */
140
141 case 0x02: /* Write Protected */
142 return 0x01; /* disk protégé en écriture */
143
144 case 0x04: /* No Data - unreadable */
145 return 0x08; /* erreur sur les données */
146
147 case 0x20: /* CRC error in data or addr */
148 if (fd_cmd->reply[2]==0x20)
149 return 0x08; /* erreur sur les données */
150 else
151 return 0x04; /* erreur sur l'adresse */
152
153 default:
154 return 0; /* OK */
155 }
156}
157
158
159
160/* FloppyReadSector:
161 * Lit le secteur spécifié sur la disquette.
162 */
163int FloppyReadSector(int drive, int density, int track, int sector, int nsects, unsigned char data[])
164{
165 struct floppy_raw_cmd fd_cmd;
166 int pc_drive = drive/2;
167
168 /* paramètres de commande */
169 fd_cmd.flags = FD_RAW_READ | FD_RAW_INTR | FD_RAW_NEED_SEEK;
170 fd_cmd.data = data;
171 fd_cmd.length = (density == 1 ? 128 : 256)*nsects; /* buffer length */
172 fd_cmd.rate = IS_5_INCHES(pc_drive) ? 1 : 2;
173 fd_cmd.track = IS_5_INCHES(pc_drive) ? track*2 : track; /* physical cylinder */
174
175 fd_cmd.cmd[0] = FD_READ;
176 fd_cmd.cmd[1] = (drive%2) << 2; /* physical head */
177 fd_cmd.cmd[2] = track; /* logical cylinder */
178 fd_cmd.cmd[3] = 0; /* logical head */
179 fd_cmd.cmd[4] = sector;
180 fd_cmd.cmd[5] = density - 1; /* sector size = 128*2^n */
181 fd_cmd.cmd[6] = 16; /* num sectors */
182 fd_cmd.cmd[7] = 0x1B; /* gap */
183 fd_cmd.cmd[8] = 0xFF;
184 fd_cmd.cmd_count = 9;
185
186 SET_NO_MULTITRACK(fd_cmd.cmd[0]);
187
188 if (density == 1)
189 SET_NO_MFM(fd_cmd.cmd[0]); /* FM coding */
190
191 return ExecCommand(pc_drive, density, &fd_cmd);
192}
193
194
195
196/* FloppyWriteSector:
197 * Ecrit le secteur spécifié sur la disquette.
198 */
199int FloppyWriteSector(int drive, int density, int track, int sector, int nsects, const unsigned char data[])
200{
201 struct floppy_raw_cmd fd_cmd;
202 int pc_drive = drive/2;
203
204 /* paramètres de commande */
205 fd_cmd.flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_NEED_SEEK;
206 fd_cmd.data = (unsigned char *)data;
207 fd_cmd.length = (density == 1 ? 128 : 256)*nsects; /* buffer length */
208 fd_cmd.rate = IS_5_INCHES(pc_drive) ? 1 : 2;
209 fd_cmd.track = IS_5_INCHES(pc_drive) ? track*2 : track; /* physical cylinder */
210
211 fd_cmd.cmd[0] = FD_WRITE;
212 fd_cmd.cmd[1] = (drive%2) << 2; /* physical head */
213 fd_cmd.cmd[2] = track; /* logical cylinder */
214 fd_cmd.cmd[3] = 0; /* logical head */
215 fd_cmd.cmd[4] = sector;
216 fd_cmd.cmd[5] = density - 1; /* sector size = 128*2^n */
217 fd_cmd.cmd[6] = 16; /* num sectors */
218 fd_cmd.cmd[7] = 0x1B; /* gap */
219 fd_cmd.cmd[8] = 0xFF;
220 fd_cmd.cmd_count = 9;
221
222 SET_NO_MULTITRACK(fd_cmd.cmd[0]);
223
224 if (density == 1)
225 SET_NO_MFM(fd_cmd.cmd[0]); /* FM coding */
226
227 return ExecCommand(pc_drive, density, &fd_cmd);
228}
229
230
231
232/* FloppyFormatTrack:
233 * Formate la piste en utilisant la table des headers spécifiée.
234 */
235int FloppyFormatTrack(int drive, int density, int track, const unsigned char header_table[])
236{
237 struct floppy_raw_cmd fd_cmd;
238 int pc_drive = drive/2;
239
240 /* paramètres de commande */
241 fd_cmd.flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_NEED_SEEK;
242 fd_cmd.data = (unsigned char *)header_table;
243 fd_cmd.length = 64;
244 fd_cmd.rate = IS_5_INCHES(pc_drive) ? 1 : 2;
245 fd_cmd.track = IS_5_INCHES(pc_drive) ? track*2 : track; /* physical cylinder */
246
247 fd_cmd.cmd[0] = FD_FORMAT;
248 fd_cmd.cmd[1] = (drive%2) << 2;
249 fd_cmd.cmd[2] = density - 1; /* sector size = 128*2^n */
250 fd_cmd.cmd[3] = 16; /* num sectors */
251 fd_cmd.cmd[4] = 0x2C;
252 fd_cmd.cmd[5] = 0xE5; /* filler_byte */
253 fd_cmd.cmd_count = 6;
254
255 SET_NO_MULTITRACK(fd_cmd.cmd[0]); /* nop */
256
257 if (density == 1)
258 SET_NO_MFM(fd_cmd.cmd[0]); /* FM coding */
259
260 return ExecCommand(pc_drive, density, &fd_cmd);
261}
262
263
264
265/* FloppyInit:
266 * Initialise le module de lecture de disquettes.
267 */
268int FloppyInit(struct floppy_info *fi, int enable_write_support)
269{
270 struct floppy_drive_params fd_params;
271 char dev_str[16];
272 int i, num_drives = 0;
273
274 for (i=0; i<2; i++) {
275 /* get drive type */
276 snprintf(dev_str, sizeof(dev_str), "/dev/fd%d", i);
277
278 if ((fd[i]=open(dev_str, O_RDONLY | O_NDELAY))<0) {
279 drive_type[i] = 0;
280 fi->drive_type[2*i] = 0;
281 fi->drive_type[2*i+1] = 0;
282 }
283 else {
284 ioctl(fd[i], FDGETDRVPRM, &fd_params);
285 close(fd[i]);
286 fd[i] = -1;
287
288 if (fd_params.cmos > 6) {
289 drive_type[i] = 0;
290 fi->drive_type[2*i] = 0;
291 fi->drive_type[2*i+1] = 0;
292 }
293 else {
294 drive_type[i] = fd_params.cmos;
295 fi->drive_type[2*i] = fd_params.cmos;
296 fi->drive_type[2*i+1] = fd_params.cmos;
297 }
298
299 num_drives++;
300 }
301 }
302
303 fi->num_drives = num_drives;
304 fi->fm_support = 1;
305 fi->write_support = enable_write_support;
306
307 rw_flag = enable_write_support;
308
309 return num_drives;
310}
311
312
313
314/* FloppyExit:
315 * Met au repos le module de lecture de disquettes.
316 */
317void FloppyExit(void)
318{
319 int i;
320
321 for (i=0; i<2; i++) {
322 if (fd[i] >= 0) {
323 close(fd[i]);
324 fd[i] = -1;
325 }
326 }
327}
328
Note: See TracBrowser for help on using the repository browser.