source: vital-to8-sdk/sap/lfloppy.c @ 1

Last change on this file since 1 was 1, checked in by svn, 5 years ago

Import initial

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.