UbixOS V2 2.0

fdc.c
Go to the documentation of this file.
1 /*-
2 * Copyright (c) 2002-2018 The UbixOS Project.
3 * All rights reserved.
4 *
5 * This was developed by Christopher W. Olsen for the UbixOS Project.
6 *
7 * Redistribution and use in source and binary forms, with or without modification, are permitted
8 * provided that the following conditions are met:
9 *
10 * 1) Redistributions of source code must retain the above copyright notice, this list of
11 * conditions, the following disclaimer and the list of authors.
12 * 2) Redistributions in binary form must reproduce the above copyright notice, this list of
13 * conditions, the following disclaimer and the list of authors in the documentation and/or
14 * other materials provided with the distribution.
15 * 3) Neither the name of the UbixOS Project nor the names of its contributors may be used to
16 * endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <isa/fdc.h>
30 #include <isa/8259.h>
31 #include <sys/video.h>
32 #include <sys/gdt.h>
33 #include <sys/idt.h>
34 #include <ubixos/spinlock.h>
35 #include <sys/io.h>
36 #include <sys/dma.h>
37 #include <sys/device.h>
38 #include <lib/kprintf.h>
39 #include <lib/kmalloc.h>
40 #include <devfs/devfs.h>
41
42 static struct spinLock fdcSpinLock = SPIN_LOCK_INITIALIZER;
43
44 static volatile bool done = FALSE;
45 static drvGeom geometry = { dg144Heads, dg144Tracks, dg144Spt };
46 static bool diskChange = FALSE;
47 static bool motor = FALSE;
48 static volatile Int8 fdcTrack = 0xff;
49 static Int8 sr0 = 0;
50 static volatile int timeOut = 0;
51 static Int8 statSize = 0;
52 static Int8 status[7] = { 0 };
53
54 unsigned long tbaddr = 0x80000L;
55
56 int fdcInit2(struct device_node *dev) {
57 dev->devInfo->size = (1024 * 1450);
58 return (0x0);
59 }
60
61 int fdc_init() {
62 struct device_interface *devInfo = (struct device_interface *) kmalloc(sizeof(struct device_interface));
63 setVector(floppyIsr, mVec + 6, (dInt + dPresent));
64 irqEnable(6);
65 reset();
66 devInfo->major = 0x0;
67 devInfo->init = (void *) &fdcInit2;
68 devInfo->read = fdcRead;
69 devInfo->write = fdcWrite;
70 devInfo->reset = (void *) reset;
71
72 device_add(0, 'c', devInfo);
73 devfs_makeNode("fd0", 'b', 0x0, 0x0);
74 return (0x0);
75 }
76
77 asm(
78 ".globl floppyIsr \n"
79 "floppyIsr: \n"
80 " pusha \n"
81 " push %ss \n"
82 " push %ds \n"
83 " push %es \n"
84 " push %fs \n"
85 " push %gs \n"
86 " call floppyIsrhndlr \n"
87 " pop %gs \n"
88 " pop %fs \n"
89 " pop %es \n"
90 " pop %ds \n"
91 " pop %ss \n"
92 " popa \n"
93 " iret \n"
94 );
95
96 void floppyIsrhndlr() {
97 done = TRUE;
98 outportByte(0x20, 0x20);
99 }
100
101 void sendByte(int Int8) {
102 volatile int msr;
103 int tmo;
104 for (tmo = 0; tmo < 128; tmo++) {
105 msr = inportByte(fdcMsr);
106 if ((msr & 0xc0) == 0x80) {
107 outportByte(fdcData, Int8);
108 return;
109 }
110 inportByte(0x80);
111 }
112 }
113
114 int getByte() {
115 volatile int msr;
116 int tmo;
117 for (tmo = 0; tmo < 128; tmo++) {
118 msr = inportByte(fdcMsr);
119 if ((msr & 0xd0) == 0xd0) {
120 return inportByte(fdcData);
121 }
122 inportByte(0x80);
123 }
124 return (-1);
125 }
126
127 bool fdcRw(int block, unsigned char *blockBuffer, bool read, unsigned long numSectors) {
128 int head = 0x0, track = 0x0, sector = 0x0, tries = 0x0, copyCount = 0x0;
129 unsigned char *p_tbaddr = (unsigned char *) 0x80000;
130 unsigned char *p_blockbuff = blockBuffer;
131 //kprintf("Block: [%i]\n",block);
132 block2Hts(block, &head, &track, &sector);
133 motorOn();
134 if (!read && blockBuffer) {
135 /* copy data from data buffer into track buffer */
136 for (copyCount = 0; copyCount < (numSectors * 512); copyCount++) {
137 *p_tbaddr = *p_blockbuff;
138 p_blockbuff++;
139 p_tbaddr++;
140 }
141 }
142 for (tries = 0; tries < 3; tries++) {
143 if (inportByte(fdcDir) & 0x80) {
144 diskChange = TRUE;
145 seek(1); /* clear "disk change" status */
146 recalibrate();
147 motorOff();
148 kprint("FDC: Disk change detected. Trying again.\n");
149 return fdcRw(block, blockBuffer, read, numSectors);
150 }
151 if (!seek(track)) {
152 motorOff();
153 kprintf("FDC: Error seeking to track [%i]\n", block);
154 return FALSE;
155 }
156 outportByte(fdcCcr, 0);
157 if (read) {
158 dmaXfer(2, tbaddr, numSectors * 512, FALSE);
159 sendByte(cmdRead);
160 }
161 else {
162 dmaXfer(2, tbaddr, numSectors * 512, TRUE);
163 sendByte(cmdWrite);
164 }
165 sendByte(head << 2);
166 sendByte(track);
167 sendByte(head);
168 sendByte(sector);
169 sendByte(2); /* 512 Int8s/sector */
170 sendByte(geometry.spt);
171 if (geometry.spt == dg144Spt) {
172 sendByte(dg144Gap3rw); /* gap 3 size for 1.44M read/write */
173 }
174 else {
175 sendByte(dg168Gap3rw); /* gap 3 size for 1.68M read/write */
176 }
177 sendByte(0xff); /* DTL = unused */
178 if (!waitFdc(TRUE)) {
179 kprint("Timed out, trying operation again after reset()\n");
180 reset();
181 return fdcRw(block, blockBuffer, read, numSectors);
182 }
183 if ((status[0] & 0xc0) == 0)
184 break; /* worked! outta here! */
185 recalibrate(); /* oops, try again... */
186 }
187 motorOff();
188 if (read && blockBuffer) {
189 p_blockbuff = blockBuffer;
190 p_tbaddr = (unsigned char *) 0x80000;
191 for (copyCount = 0x0; copyCount < (numSectors * 512); copyCount++) {
192 *p_blockbuff = *p_tbaddr;
193 p_blockbuff++;
194 p_tbaddr++;
195 }
196 }
197 return (tries != 3);
198 }
199
200 void block2Hts(int block, int *head, int *track, int *sector) {
201 *head = (block % (geometry.spt * geometry.heads)) / (geometry.spt);
202 *track = block / (geometry.spt * geometry.heads);
203 *sector = block % geometry.spt + 1;
204 }
205
206 void motorOn(void) {
207 if (motor == FALSE) {
208 outportByte(fdcDor, 0x1c);
209 motor = TRUE;
210 }
211 }
212
213 void motorOff(void) {
214 if (motor == TRUE) {
215 //outportByte(fdcDor,0x0);
216 //outportByte(fdcDor,0x0C);
217 motor = FALSE;
218 }
219 }
220
221 bool seek(int track) {
222 if (fdcTrack == track) {
223 return (TRUE);
224 }
225 sendByte(cmdSeek);
226 sendByte(0);
227 sendByte(track);
228 if (!waitFdc(TRUE)) {
229 kprintf("wait fdc failed\n");
230 return (FALSE);
231 }
232 if ((sr0 != 0x20) || (fdcTrack != track)) {
233 return (FALSE);
234 }
235 else {
236 return (TRUE);
237 }
238 }
239
240 bool readBlock(int block, Int8 *blockBuffer, unsigned long numSectors) {
241 int result = 0x0, loop = 0x0;
242 if (numSectors > 1) {
243 for (loop = 0; loop < numSectors; loop++) {
244 result = fdcRw(block + loop, blockBuffer + (loop * 512), TRUE, 1);
245 }
246 return result;
247 }
248 return fdcRw(block, blockBuffer, TRUE, numSectors);
249 }
250
251 bool writeBlock(int block, Int8 *blockBuffer, unsigned long numSectors) {
252 return fdcRw(block, blockBuffer, FALSE, numSectors);
253 }
254
255 bool waitFdc(bool sensei) {
256 timeOut = 50000;
257 while (!done && timeOut)
258 ;
259 statSize = 0;
260 while ((statSize < 7) && (inportByte(fdcMsr) & (1 << 4))) {
261 status[(int) statSize++] = getByte();
262 }
263 if (sensei) {
264 sendByte(cmdSensei);
265 sr0 = getByte();
266 fdcTrack = getByte();
267 }
268 done = FALSE;
269 if (!timeOut) {
270 if (inportByte(fdcDir) & 0x80) {
271 diskChange = TRUE;
272 }
273 return (FALSE);
274 }
275 else {
276 return (TRUE);
277 }
278 }
279
280 void recalibrate(void) {
281 motorOn();
282 sendByte(cmdRecal);
283 sendByte(0);
284 waitFdc(TRUE);
285 motorOff();
286 }
287
288 void reset(void) {
289 outportByte(fdcDor, 0);
290 motor = FALSE;
291 outportByte(fdcDor, 0x0c);
292 done = TRUE;
293 waitFdc(TRUE);
294 sendByte(cmdSpecify);
295 sendByte(0xdf);
296 sendByte(0x02);
297 seek(1);
298 recalibrate();
299 diskChange = FALSE;
300 return;
301 }
302
303 void fdcRead(void *info, void *baseAddr, uInt32 startSector, uInt32 sectorCount) {
304 spinLock(&fdcSpinLock);
305 readBlock(startSector, baseAddr, sectorCount);
306 spinUnlock(&fdcSpinLock);
307 return;
308 }
309 void fdcWrite(void *info, void *baseAddr, uInt32 startSector, uInt32 sectorCount) {
310 writeBlock(startSector, baseAddr, sectorCount);
311 return;
312 }
313
314 /***
315
316 $Log: fdc.c,v $
317 Revision 1.1.1.1 2006/06/01 12:46:12 reddawg
318 ubix2
319
320 Revision 1.2 2005/10/12 00:13:37 reddawg
321 Removed
322
323 Revision 1.1.1.1 2005/09/26 17:24:01 reddawg
324 no message
325
326 Revision 1.24 2004/09/07 21:54:38 reddawg
327 ok reverted back to old scheduling for now....
328
329 Revision 1.23 2004/09/06 15:13:25 reddawg
330 Last commit before FreeBSD 6.0
331
332 Revision 1.22 2004/08/21 20:06:28 reddawg
333 ok check out exec.c
334
335 Revision 1.21 2004/08/15 16:47:49 reddawg
336 Fixed
337
338 Revision 1.20 2004/08/15 00:33:02 reddawg
339 Wow the ide driver works again
340
341 Revision 1.19 2004/08/01 20:40:45 reddawg
342 Net related fixes
343
344 Revision 1.18 2004/07/29 21:32:16 reddawg
345 My quick lunchs breaks worth of updates....
346
347 Revision 1.17 2004/07/27 08:03:36 reddawg
348 chg: stopped push all these extra registers I can't find a good reason as to why I was doing it
349
350 Revision 1.16 2004/07/22 17:32:25 reddawg
351 I broke it hopefully
352
353 Revision 1.15 2004/07/21 10:02:09 reddawg
354 devfs: renamed functions
355 device system: renamed functions
356 fdc: fixed a few potential bugs and cleaned up some unused variables
357 strol: fixed definition
358 endtask: made it print out freepage debug info
359 kmalloc: fixed a huge memory leak we had some unhandled descriptor insertion so some descriptors were lost
360 ld: fixed a pointer conversion
361 file: cleaned up a few unused variables
362 sched: broke task deletion
363 kprintf: fixed ogPrintf definition
364
365 Revision 1.14 2004/07/17 02:38:31 reddawg
366 Fixed a few problems
367
368 Revision 1.13 2004/07/14 12:42:46 reddawg
369 fdc: fdcInit to fdc_init
370 Changed Startup Routines
371
372 Revision 1.12 2004/06/04 10:19:42 reddawg
373 notes: we compile again, thank g-d anyways i was about to cry
374
375 Revision 1.11 2004/05/20 22:51:09 reddawg
376 Cleaned Up Warnings
377
378 Revision 1.10 2004/05/19 23:36:52 reddawg
379 Bug Fixes
380
381 Revision 1.9 2004/05/19 15:31:27 reddawg
382 Fixed up the rest of the references
383
384 Revision 1.8 2004/05/19 15:26:33 reddawg
385 Fixed reference issues due to changes in driver subsystem
386
387 Revision 1.7 2004/05/10 02:23:24 reddawg
388 Minor Changes To Source Code To Prepare It For Open Source Release
389
390 Revision 1.6 2004/04/30 14:16:04 reddawg
391 Fixed all the datatypes to be consistant uInt8,uInt16,uInt32,Int8,Int16,Int32
392
393 Revision 1.5 2004/04/29 15:29:20 reddawg
394 Fixed All Running Issues
395
396 Revision 1.4 2004/04/28 02:22:54 reddawg
397 This is a fiarly large commit but we are starting to use new driver model
398 all around
399
400 Revision 1.3 2004/04/26 22:22:33 reddawg
401 DevFS now uses correct size of device
402
403 Revision 1.2 2004/04/22 21:20:05 reddawg
404 FDC now adds drives to the devfs
405
406 Revision 1.1.1.1 2004/04/15 12:07:09 reddawg
407 UbixOS v1.0
408
409 Revision 1.6 2004/04/13 16:36:33 reddawg
410 Changed our copyright, it is all now under a BSD-Style license
411
412 END
413 ***/
414
8259.h
floppyIsr
void floppyIsr()
dmaXfer
void dmaXfer(uInt8 channel, uInt32 address, uInt length, uInt8 read)
fdcCcr
#define fdcCcr
Definition: fdc.h:44
spinlock.h
device_interface
Definition: device.h:47
gdt.h
recalibrate
void recalibrate(void)
Definition: fdc.c:280
uInt32
unsigned long int uInt32
Definition: objgfx30.h:49
fdc.h
dPresent
#define dPresent
Definition: gdt.h:54
TRUE
Definition: types.h:82
motorOff
void motorOff(void)
Definition: fdc.c:213
fdcMsr
#define fdcMsr
Definition: fdc.h:41
Int8
signed char Int8
Definition: objgfx30.h:43
idt.h
dg144Spt
#define dg144Spt
Definition: fdc.h:57
video.h
fdcWrite
void fdcWrite(void *info, void *baseAddr, uInt32 startSector, uInt32 sectorCount)
Definition: fdc.c:309
outportByte
void outportByte(unsigned int, unsigned char)
outputut one byte to specified port
Definition: io.c:72
FALSE
Definition: types.h:82
cmdRecal
#define cmdRecal
Definition: fdc.h:52
spinUnlock
void spinUnlock(spinLock_t *lock)
Definition: spinlock.c:36
block2Hts
void block2Hts(int block, int *head, int *track, int *sector)
Definition: fdc.c:200
floppyIsrhndlr
void floppyIsrhndlr()
Definition: fdc.c:96
SPIN_LOCK_INITIALIZER
#define SPIN_LOCK_INITIALIZER
Definition: spinlock.h:36
device_add
int device_add(int, char, struct device_interface *)
Definition: device.c:49
motorOn
void motorOn(void)
Definition: fdc.c:206
device_interface::size
uInt32 size
Definition: device.h:49
spinLock
void spinLock(spinLock_t *lock)
Definition: spinlock.c:55
inportByte
unsigned char inportByte(unsigned int)
input one byte from specified port
Definition: io.c:38
readBlock
bool readBlock(int block, Int8 *blockBuffer, unsigned long numSectors)
Definition: fdc.c:240
tbaddr
unsigned long tbaddr
Definition: fdc.c:54
reset
void reset(void)
Definition: fdc.c:288
writeBlock
bool writeBlock(int block, Int8 *blockBuffer, unsigned long numSectors)
Definition: fdc.c:251
kprintf.h
fdcRead
void fdcRead(void *info, void *baseAddr, uInt32 startSector, uInt32 sectorCount)
Definition: fdc.c:303
seek
bool seek(int track)
Definition: fdc.c:221
device_node
Definition: device.h:34
DrvGeom::spt
Int8 spt
Definition: fdc.h:63
fdc_init
int fdc_init()
Definition: fdc.c:61
DrvGeom
Definition: fdc.h:34
getByte
int getByte()
Definition: fdc.c:114
DrvGeom::heads
Int8 heads
Definition: fdc.h:61
device_interface::init
int(* init)(void *)
Definition: device.h:55
device_interface::reset
void(* reset)(void *)
Definition: device.h:54
cmdSensei
#define cmdSensei
Definition: fdc.h:51
fdcDor
#define fdcDor
Definition: fdc.h:45
devfs_makeNode
int devfs_makeNode(char *name, uInt8 type, uInt16 major, uInt16 minor)
Definition: devfs.c:174
device_interface::write
int(* write)(void *, void *, uInt32, uInt32)
Definition: device.h:53
read
int read(struct thread *td, struct read_args *uap)
Definition: gen_calls.c:100
sendByte
void sendByte(int Int8)
Definition: fdc.c:101
fdcDir
#define fdcDir
Definition: fdc.h:43
device_interface::read
int(* read)(void *, void *, uInt32, uInt32)
Definition: device.h:52
devfs.h
device.h
dg168Gap3rw
#define dg168Gap3rw
Definition: fdc.h:59
dInt
#define dInt
Definition: gdt.h:43
cmdSeek
#define cmdSeek
Definition: fdc.h:50
dg144Tracks
#define dg144Tracks
Definition: fdc.h:56
mVec
#define mVec
Definition: 8259.h:41
cmdSpecify
#define cmdSpecify
Definition: fdc.h:53
device_interface::info
void * info
Definition: device.h:51
cmdRead
#define cmdRead
Definition: fdc.h:49
kmalloc
void * kmalloc(uInt32 len)
Definition: kmalloc.c:241
spinLock
Definition: spinlock.h:41
setVector
void setVector(void *handler, unsigned char interrupt, unsigned short controlMajor)
Definition: idt.c:208
io.h
irqEnable
void irqEnable(uInt16 irqNo)
L
#define L
Definition: types.h:155
device_node::devInfo
struct device_interface * devInfo
Definition: device.h:37
fdcInit2
int fdcInit2(struct device_node *dev)
Definition: fdc.c:56
kprintf
int kprintf(const char *,...)
Definition: kprintf.c:259
fdcRw
bool fdcRw(int block, unsigned char *blockBuffer, bool read, unsigned long numSectors)
Definition: fdc.c:127
dg144Heads
#define dg144Heads
Definition: fdc.h:55
device_interface::major
int major
Definition: device.h:50
fdcData
#define fdcData
Definition: fdc.h:42
kmalloc.h
kprint
void kprint(char *string)
Definition: video.c:58
dma.h
waitFdc
bool waitFdc(bool sensei)
Definition: fdc.c:255
dg144Gap3rw
#define dg144Gap3rw
Definition: fdc.h:58
cmdWrite
#define cmdWrite
Definition: fdc.h:48