forked from lipro-cpm4l/cpmtools
-
Notifications
You must be signed in to change notification settings - Fork 1
/
device_libdsk.c
135 lines (126 loc) · 3.56 KB
/
device_libdsk.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/* #includes */ /*{{{C}}}*//*{{{*/
#include "config.h"
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "device.h"
#ifdef USE_DMALLOC
#include <dmalloc.h>
#endif
/*}}}*/
static const char *lookupFormat(DSK_GEOMETRY *geom, const char *name)
{
dsk_format_t fmt = FMT_180K;
const char *fname;
while (dg_stdformat(NULL, fmt, &fname, NULL) == DSK_ERR_OK)
{
if (!strcmp(name, fname))
{
dg_stdformat(geom, fmt, &fname, NULL);
return NULL;
}
++fmt;
}
return "Unrecognised LibDsk geometry specification";
}
/* Device_open -- Open an image file */ /*{{{*/
const char *Device_open(struct Device *this, const char *filename, int mode, const char *deviceOpts)
{
char *format;
char driverName[80];
const char *boo;
dsk_err_t e;
/* Assume driver name & format name both fit in 80 characters, rather than
* malloccing the exact size */
if (deviceOpts == NULL)
{
e = dsk_open(&this->dev, filename, NULL, NULL);
format = NULL;
}
else
{
strncpy(driverName, deviceOpts, 79);
driverName[79] = 0;
format = strchr(driverName, ',');
if (format)
{
*format = 0;
++format;
}
e = dsk_open(&this->dev, filename, driverName, NULL);
}
this->opened = 0;
if (e) return dsk_strerror(e);
this->opened = 1;
if (format)
{
boo = lookupFormat(&this->geom, format);
if (boo) return boo;
}
else
{
dsk_getgeom(this->dev, &this->geom);
}
return NULL;
}
/*}}}*/
/* Device_setGeometry -- Set disk geometry */ /*{{{*/
const char *Device_setGeometry(struct Device *this, int secLength, int sectrk, int tracks, off_t offset, const char *libdskGeometry)
{
char *boo;
this->secLength=secLength;
this->sectrk=sectrk;
this->tracks=tracks;
/* Must be an even multiple of sector size */
assert(offset%secLength==0);
this->offset=offset;
/* If a geometry is named in diskdefs, use it */
if (libdskGeometry && libdskGeometry[0])
{
return lookupFormat(&this->geom, libdskGeometry);
}
this->geom.dg_secsize = secLength;
this->geom.dg_sectors = sectrk;
/* Did the autoprobe guess right about the number of sectors & cylinders? */
if (this->geom.dg_cylinders * this->geom.dg_heads == tracks) return NULL;
/* Otherwise we guess: <= 43 tracks: single-sided. Else double. This
* fails for 80-track single-sided if there are any such beasts */
if (tracks <= 43)
{
this->geom.dg_cylinders = tracks;
this->geom.dg_heads = 1;
}
else
{
this->geom.dg_cylinders = tracks/2;
this->geom.dg_heads = 2;
}
return NULL;
}
/*}}}*/
/* Device_close -- Close an image file */ /*{{{*/
const char *Device_close(struct Device *this)
{
dsk_err_t e;
this->opened=0;
e = dsk_close(&this->dev);
return (e?dsk_strerror(e):(const char*)0);
}
/*}}}*/
/* Device_readSector -- read a physical sector */ /*{{{*/
const char *Device_readSector(const struct Device *this, int track, int sector, char *buf)
{
dsk_err_t e;
e = dsk_lread(this->dev, &this->geom, buf, (track * this->sectrk) + sector + this->offset/this->secLength);
return (e?dsk_strerror(e):(const char*)0);
}
/*}}}*/
/* Device_writeSector -- write physical sector */ /*{{{*/
const char *Device_writeSector(const struct Device *this, int track, int sector, const char *buf)
{
dsk_err_t e;
e = dsk_lwrite(this->dev, &this->geom, buf, (track * this->sectrk) + sector + this->offset/this->secLength);
return (e?dsk_strerror(e):(const char*)0);
}
/*}}}*/