UbixOS  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));
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 
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) {
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);
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) {
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();
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);
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