summaryrefslogtreecommitdiff
path: root/sys/src/boot/pc/devfloppy.h
blob: 1d9a76a855a11340c82f10d467605e406255f731 (plain)
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
typedef	struct FController FController;
typedef	struct FDrive FDrive;
typedef struct FType FType;

static void floppyintr(Ureg*);
static int floppyon(FDrive*);
static void floppyoff(FDrive*);
static void floppysetdef(FDrive*);

/*
 *  a floppy drive
 */
struct FDrive
{
	FType	*t;		/* floppy type */
	int	dt;		/* drive type */
	int	dev;

	ulong	lasttouched;	/* time last touched */
	int	cyl;		/* current arm position */
	int	confused;	/* needs to be recalibrated */
	int	offset;		/* current offset */
	int	vers;
	int	maxtries;

	int	tcyl;		/* target cylinder */
	int	thead;		/* target head */
	int	tsec;		/* target sector */
	long	len;		/* size of xfer */

	uchar	*cache;		/* track cache */
	int	ccyl;
	int	chead;

//	Rendez	r;		/* waiting here for motor to spin up */
	void	*aux;
};

/*
 *  controller for 4 floppys
 */
struct FController
{
//	QLock;			/* exclusive access to the contoller */

	int	ndrive;
	FDrive	*d;		/* the floppy drives */
	FDrive	*selected;
	int	rate;		/* current rate selected */
	uchar	cmd[14];	/* command */
	int	ncmd;		/* # command bytes */
	uchar	stat[14];	/* command status */
	int	nstat;		/* # status bytes */
	int	confused;	/* controler needs to be reset */
//	Rendez	r;		/* wait here for command termination */
	int	motor;		/* bit mask of spinning disks */
//	Rendez	kr;		/* for motor watcher */
};

/*
 *  floppy types (all MFM encoding)
 */
struct FType
{
	char	*name;
	int	dt;		/* compatible drive type */
	int	bytes;		/* bytes/sector */
	int	sectors;	/* sectors/track */
	int	heads;		/* number of heads */
	int	steps;		/* steps per cylinder */
	int	tracks;		/* tracks/disk */
	int	gpl;		/* intersector gap length for read/write */	
	int	fgpl;		/* intersector gap length for format */
	int	rate;		/* rate code */

	/*
	 *  these depend on previous entries and are set filled in
	 *  by floppyinit
	 */
	int	bcode;		/* coded version of bytes for the controller */
	long	cap;		/* drive capacity in bytes */
	long	tsize;		/* track size in bytes */
};
/* bits in the registers */
enum
{
	/* status registers a & b */
	Psra=		0x3f0,
	Psrb=		0x3f1,

	/* digital output register */
	Pdor=		0x3f2,
	Fintena=	0x8,	/* enable floppy interrupt */
	Fena=		0x4,	/* 0 == reset controller */

	/* main status register */
	Pmsr=		0x3f4,
	Fready=		0x80,	/* ready to be touched */
	Ffrom=		0x40,	/* data from controller */
	Ffloppybusy=	0x10,	/* operation not over */

	/* data register */
	Pfdata=		0x3f5,
	Frecal=		0x07,	/* recalibrate cmd */
	Fseek=		0x0f,	/* seek cmd */
	Fsense=		0x08,	/* sense cmd */
	Fread=		0x66,	/* read cmd */
	Freadid=	0x4a,	/* read track id */
	Fspec=		0x03,	/* set hold times */
	Fwrite=		0x45,	/* write cmd */
	Fformat=	0x4d,	/* format cmd */
	Fmulti=		0x80,	/* or'd with Fread or Fwrite for multi-head */
	Fdumpreg=	0x0e,	/* dump internal registers */

	/* digital input register */
	Pdir=		0x3F7,	/* disk changed port (read only) */
	Pdsr=		0x3F7,	/* data rate select port (write only) */
	Fchange=	0x80,	/* disk has changed */

	/* status 0 byte */
	Drivemask=	3<<0,
	Seekend=	1<<5,
	Codemask=	(3<<6)|(3<<3),
	Cmdexec=	1<<6,

	/* status 1 byte */
	Overrun=	0x10,
};

/*
 *  types of drive (from PC equipment byte)
 */
enum
{
	Tnone=		0,
	T360kb=		1,
	T1200kb=	2,
	T720kb=		3,
	T1440kb=	4,
};

static void
pcfloppyintr(Ureg *ur, void *a)
{
	USED(a);

	floppyintr(ur);
}

void
floppysetup0(FController *fl)
{
	uchar equip;

	/*
	 * Read nvram for types of floppies 0 & 1.
	 * Always try floppy 0.
	 */
	equip = nvramread(0x10);
	fl->ndrive = 1;

	if(equip & 0xf)
		fl->ndrive++;

	/*
	 * Allocate the drive storage.
	 * There's always one.
	 */
	fl->d = xalloc(fl->ndrive*sizeof(FDrive));
	fl->d[0].dt = (equip >> 4) & 0xf;
	if(fl->d[0].dt == Tnone)
		fl->d[0].dt = T1440kb;

	if(fl->ndrive == 2)
		fl->d[1].dt = equip & 0xf;
}

void
floppysetup1(FController*)
{
//	intrenable(VectorFLOPPY, pcfloppyintr, fl, BUSUNKNOWN);
	setvec(VectorFLOPPY, pcfloppyintr, 0);
}


static vlong pcfloppyseek(FDrive*, vlong);
FController	fl;

vlong
floppyseek(Fs *fs, vlong off)
{
	FDrive *dp;

	dp = &fl.d[fs->dev];
	return pcfloppyseek(dp, off);
}