1 /***************************************************************************
2 * *
3 * LIBDSK: General floppy and diskimage access library *
4 * Copyright (C) 2005 John Elliott <seasip.webmaster@gmail.com> *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of the GNU Library General Public *
8 * License as published by the Free Software Foundation; either *
9 * version 2 of the License, or (at your option) any later version. *
10 * *
11 * This library is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14 * Library General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU Library General Public *
17 * License along with this library; if not, write to the Free *
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, *
19 * MA 02111-1307, USA *
20 * *
21 ***************************************************************************/
22
23 #include "drvi.h"
24
25 /* PASSES is the number of times a sector header is seen before we deduce
26 * that all the sectors on the disc have been seen by the scan. Higher
27 * values of PASSES may make for more accurate results but slower scans. */
28 #define PASSES 3
29
dsk_ptrackids(DSK_PDRIVER self,const DSK_GEOMETRY * geom,dsk_pcyl_t cylinder,dsk_phead_t head,dsk_psect_t * count,DSK_FORMAT ** results)30 LDPUBLIC32 dsk_err_t LDPUBLIC16 dsk_ptrackids(DSK_PDRIVER self,
31 const DSK_GEOMETRY *geom,
32 dsk_pcyl_t cylinder, dsk_phead_t head,
33 dsk_psect_t *count, DSK_FORMAT **results)
34 {
35 dsk_err_t err;
36 DRV_CLASS *dc;
37 DSK_FORMAT fmt;
38 DSK_GEOMETRY gtemp;
39
40 if (!self || !geom || !self->dr_class || !count || !results)
41 return DSK_ERR_BADPTR;
42
43 dc = self->dr_class;
44
45 if (dc->dc_trackids)
46 {
47 err = (dc->dc_trackids)(self,geom,cylinder,head,count,results);
48 if (err != DSK_ERR_NOTIMPL) return err;
49 }
50 if (dc->dc_secid)
51 {
52 /* The driver doesn't provide a 'bulk' sector ID function, but we can
53 * try to get at it one sector at a time. */
54
55 /* This is a big buffer and may need to be made static for DOS versions */
56 DSK_FORMAT headers[256];
57 unsigned char found[256];
58 int lcount = 0;
59
60 dsk_psect_t sector = 0;
61 memcpy(>emp, geom, sizeof(gtemp));
62
63 /* Start by forcing a read error. We set sector size to 256
64 * i) because with any luck, the floppy we're scanning won't have 256-byte
65 * sectors.
66 * ii) because the buffer we're using is only 256 bytes long. */
67 gtemp.dg_secsize = 256;
68 do
69 {
70 err = dsk_pread(self,>emp,found,cylinder,head,
71 sector++);
72 }
73 while (err == DSK_ERR_OK);
74 /* After the read error, we should be right after the index hole. So read
75 * off the sector IDs in order. But in case we miss one, go around a few
76 * times. */
77
78 memset(found, 0, sizeof(found));
79 for (;;)
80 {
81 err = (dc->dc_secid)(self,geom,cylinder,head,&fmt);
82 if (err) return err;
83 if (!found[fmt.fmt_sector & 0xFF])
84 {
85 memcpy(&headers[lcount], &fmt, sizeof(fmt));
86 ++lcount;
87 }
88 found[fmt.fmt_sector & 0xFF]++;
89 if (found[fmt.fmt_sector] > PASSES) break;
90 }
91 if (!lcount) return DSK_ERR_NOADDR; /* Track blank */
92
93 *count = lcount;
94 *results = dsk_malloc( lcount * sizeof(DSK_FORMAT) );
95 if (!(*results)) return DSK_ERR_NOMEM;
96 memcpy(*results, headers, lcount * sizeof(DSK_FORMAT)) ;
97 return DSK_ERR_OK;
98 }
99 return DSK_ERR_NOTIMPL;
100 }
101
102
dsk_ltrackids(DSK_PDRIVER self,const DSK_GEOMETRY * geom,dsk_ltrack_t track,dsk_psect_t * count,DSK_FORMAT ** result)103 LDPUBLIC32 dsk_err_t LDPUBLIC16 dsk_ltrackids(DSK_PDRIVER self,
104 const DSK_GEOMETRY *geom,
105 dsk_ltrack_t track,
106 dsk_psect_t *count, DSK_FORMAT **result)
107 {
108 dsk_err_t e;
109 dsk_pcyl_t cyl;
110 dsk_psect_t sec;
111
112 e = dg_lt2pt(geom, track, &cyl, &sec);
113 if (e) return e;
114 return dsk_ptrackids(self, geom, cyl, sec, count, result);
115
116 }
117
118