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(&gtemp, 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,&gtemp,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