Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Release 1.0
[palacios.git] / geekos / src / geekos / ide.c
1 /*
2  * ATA (aka IDE) driver.
3  * Copyright (c) 2003, Jeffrey K. Hollingsworth <hollings@cs.umd.edu>
4  * Copyright (c) 2003,2004 David H. Hovemeyer <daveho@cs.umd.edu>
5  * $Revision: 1.1 $
6  *
7  * This is free software.  You are permitted to use,
8  * redistribute, and modify it as specified in the file "COPYING".
9  */
10
11 /*
12  * NOTES:
13  * 12/22/03 - Converted to use new block device layer with queued requests
14  *  1/20/04 - Changed probing of drives to work on Bochs 2.0 with 2 drives
15  */
16
17 #include <geekos/serial.h>
18
19 #include <geekos/ktypes.h>
20 #include <geekos/kassert.h>
21 #include <geekos/errno.h>
22 #include <geekos/malloc.h>
23 #include <geekos/string.h>
24 #include <geekos/io.h>
25 #include <geekos/int.h>
26 #include <geekos/screen.h>
27 #include <geekos/timer.h>
28 #include <geekos/kthread.h>
29 #include <geekos/blockdev.h>
30 #include <geekos/ide.h>
31
32 /* Registers */
33 #define IDE_DATA_REGISTER               0x1f0
34 #define IDE_ERROR_REGISTER              0x1f1
35 #define IDE_FEATURE_REG                 IDE_ERROR_REGISTER
36 #define IDE_SECTOR_COUNT_REGISTER       0x1f2
37 #define IDE_SECTOR_NUMBER_REGISTER      0x1f3
38 #define IDE_CYLINDER_LOW_REGISTER       0x1f4
39 #define IDE_CYLINDER_HIGH_REGISTER      0x1f5
40 #define IDE_DRIVE_HEAD_REGISTER         0x1f6
41 #define IDE_STATUS_REGISTER             0x1f7
42 #define IDE_COMMAND_REGISTER            0x1f7
43 #define IDE_DEVICE_CONTROL_REGISTER     0x3F6
44
45 /* Drives */
46 #define IDE_DRIVE_0                     0xa0
47 #define IDE_DRIVE_1                     0xb0
48
49 /* Commands */
50 #define IDE_COMMAND_IDENTIFY_DRIVE      0xEC
51 #define IDE_COMMAND_SEEK                0x70
52 #define IDE_COMMAND_READ_SECTORS        0x21
53 #define IDE_COMMAND_READ_BUFFER         0xE4
54 #define IDE_COMMAND_WRITE_SECTORS       0x30
55 #define IDE_COMMAND_WRITE_BUFFER        0xE8
56 #define IDE_COMMAND_DIAGNOSTIC          0x90
57 #define IDE_COMMAND_ATAPI_IDENT_DRIVE   0xA1
58
59 /* Results words from Identify Drive Request */
60 #define IDE_INDENTIFY_NUM_CYLINDERS     0x01
61 #define IDE_INDENTIFY_NUM_HEADS         0x03
62 #define IDE_INDENTIFY_NUM_BYTES_TRACK   0x04
63 #define IDE_INDENTIFY_NUM_BYTES_SECTOR  0x05
64 #define IDE_INDENTIFY_NUM_SECTORS_TRACK 0x06
65
66 /* bits of Status Register */
67 #define IDE_STATUS_DRIVE_BUSY           0x80
68 #define IDE_STATUS_DRIVE_READY          0x40
69 #define IDE_STATUS_DRIVE_WRITE_FAULT    0x20
70 #define IDE_STATUS_DRIVE_SEEK_COMPLETE  0x10
71 #define IDE_STATUS_DRIVE_DATA_REQUEST   0x08
72 #define IDE_STATUS_DRIVE_CORRECTED_DATA 0x04
73 #define IDE_STATUS_DRIVE_INDEX          0x02
74 #define IDE_STATUS_DRIVE_ERROR          0x01
75
76 /* Bits of Device Control Register */
77 #define IDE_DCR_NOINTERRUPT             0x02
78 #define IDE_DCR_RESET                   0x04
79
80 /* Return codes from various IDE_* functions */
81 #define IDE_ERROR_NO_ERROR      0
82 #define IDE_ERROR_BAD_DRIVE     -1
83 #define IDE_ERROR_INVALID_BLOCK -2
84 #define IDE_ERROR_DRIVE_ERROR   -3
85
86 /* Control register bits */
87 #define IDE_CONTROL_REGISTER            0x3F6
88 #define IDE_CONTROL_SOFTWARE_RESET      0x04
89 #define IDE_CONTROL_INT_DISABLE         0x02
90
91 #define LOW_BYTE(x)     (x & 0xff)
92 #define HIGH_BYTE(x)    ((x >> 8) & 0xff)
93
94 #define IDE_MAX_DRIVES                  2
95
96 typedef struct {
97     short num_Cylinders;
98     short num_Heads;
99     short num_SectorsPerTrack;
100     short num_BytesPerSector;
101 } ideDisk;
102
103 int ideDebug = 99;
104 static int numDrives;
105 static ideDisk drives[IDE_MAX_DRIVES];
106
107 struct Thread_Queue s_ideWaitQueue;
108 struct Block_Request_List s_ideRequestQueue;
109
110 /*
111  * return the number of logical blocks for a particular drive.
112  *
113  */
114 static int IDE_getNumBlocks(int driveNum)
115 {
116     if (driveNum < 0 || driveNum > IDE_MAX_DRIVES) {
117         return IDE_ERROR_BAD_DRIVE;
118     }
119
120     return (drives[driveNum].num_Heads * 
121             drives[driveNum].num_SectorsPerTrack *
122             drives[driveNum].num_Cylinders);
123 }
124
125 /*
126  * Read a block at the logical block number indicated.
127  */
128 static int IDE_Read(int driveNum, int blockNum, char *buffer)
129 {
130     int i;
131     int head;
132     int sector;
133     int cylinder;
134     short *bufferW;
135     int reEnable = 0;
136
137     if (driveNum < 0 || driveNum > (numDrives-1)) {
138         if (ideDebug) Print("ide: invalid drive %d\n", driveNum);
139         return IDE_ERROR_BAD_DRIVE;
140     }
141
142     if (blockNum < 0 || blockNum >= IDE_getNumBlocks(driveNum)) {
143         if (ideDebug) Print("ide: invalid block %d\n", blockNum);
144         return IDE_ERROR_INVALID_BLOCK;
145     }
146
147     if (Interrupts_Enabled()) {
148         Disable_Interrupts();
149         reEnable = 1;
150     }
151
152     /* now compute the head, cylinder, and sector */
153     sector = blockNum % drives[driveNum].num_SectorsPerTrack + 1;
154     cylinder = blockNum / (drives[driveNum].num_Heads * 
155         drives[driveNum].num_SectorsPerTrack);
156     head = (blockNum / drives[driveNum].num_SectorsPerTrack) % 
157         drives[driveNum].num_Heads;
158
159     if (ideDebug >= 2) {
160         Print ("request to read block %d\n", blockNum);
161         Print ("    head %d\n", head);
162         Print ("    cylinder %d\n", cylinder);
163         Print ("    sector %d\n", sector);
164     }
165
166     Out_Byte(IDE_SECTOR_COUNT_REGISTER, 1);
167     Out_Byte(IDE_SECTOR_NUMBER_REGISTER, sector);
168     Out_Byte(IDE_CYLINDER_LOW_REGISTER, LOW_BYTE(cylinder));
169     Out_Byte(IDE_CYLINDER_HIGH_REGISTER, HIGH_BYTE(cylinder));
170     if (driveNum == 0) {
171         Out_Byte(IDE_DRIVE_HEAD_REGISTER, IDE_DRIVE_0 | head);
172     } else if (driveNum == 1) {
173         Out_Byte(IDE_DRIVE_HEAD_REGISTER, IDE_DRIVE_1 | head);
174     }
175
176     Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_READ_SECTORS);
177
178     if (ideDebug > 2) Print("About to wait for Read \n");
179
180     /* wait for the drive */
181     while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY);
182
183     if (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_ERROR) {
184         Print("ERROR: Got Read %d\n", In_Byte(IDE_STATUS_REGISTER));
185         return IDE_ERROR_DRIVE_ERROR;
186     }
187
188     if (ideDebug > 2) Print("got buffer \n");
189
190     bufferW = (short *) buffer;
191     for (i=0; i < 256; i++) {
192         bufferW[i] = In_Word(IDE_DATA_REGISTER);
193     }
194
195     if (reEnable) Enable_Interrupts();
196
197     return IDE_ERROR_NO_ERROR;
198 }
199
200 /*
201  * Write a block at the logical block number indicated.
202  */
203 static int IDE_Write(int driveNum, int blockNum, char *buffer)
204 {
205     int i;
206     int head;
207     int sector;
208     int cylinder;
209     short *bufferW;
210     int reEnable = 0;
211
212     if (driveNum < 0 || driveNum > (numDrives-1)) {
213         return IDE_ERROR_BAD_DRIVE;
214     }
215
216     if (blockNum < 0 || blockNum >= IDE_getNumBlocks(driveNum)) {
217         return IDE_ERROR_INVALID_BLOCK;
218     }
219
220     if (Interrupts_Enabled()) {
221         Disable_Interrupts();
222         reEnable = 1;
223     }
224
225     /* now compute the head, cylinder, and sector */
226     sector = blockNum % drives[driveNum].num_SectorsPerTrack + 1;
227     cylinder = blockNum / (drives[driveNum].num_Heads * 
228         drives[driveNum].num_SectorsPerTrack);
229     head = (blockNum / drives[driveNum].num_SectorsPerTrack) % 
230         drives[driveNum].num_Heads;
231
232     if (ideDebug) {
233         Print ("request to write block %d\n", blockNum);
234         Print ("    head %d\n", head);
235         Print ("    cylinder %d\n", cylinder);
236         Print ("    sector %d\n", sector);
237     }
238
239     Out_Byte(IDE_SECTOR_COUNT_REGISTER, 1);
240     Out_Byte(IDE_SECTOR_NUMBER_REGISTER, sector);
241     Out_Byte(IDE_CYLINDER_LOW_REGISTER, LOW_BYTE(cylinder));
242     Out_Byte(IDE_CYLINDER_HIGH_REGISTER, HIGH_BYTE(cylinder));
243     if (driveNum == 0) {
244         Out_Byte(IDE_DRIVE_HEAD_REGISTER, IDE_DRIVE_0 | head);
245     } else if (driveNum == 1) {
246         Out_Byte(IDE_DRIVE_HEAD_REGISTER, IDE_DRIVE_1 | head);
247     }
248
249     Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_WRITE_SECTORS);
250
251
252     /* wait for the drive */
253     while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY);
254
255     bufferW = (short *) buffer;
256     for (i=0; i < 256; i++) {
257         Out_Word(IDE_DATA_REGISTER, bufferW[i]);
258     }
259
260     if (ideDebug) Print("About to wait for Write \n");
261
262     /* wait for the drive */
263     while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY);
264
265     if (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_ERROR) {
266         Print("ERROR: Got Read %d\n", In_Byte(IDE_STATUS_REGISTER));
267         return IDE_ERROR_DRIVE_ERROR;
268     }
269
270     if (reEnable) Enable_Interrupts();
271
272     return IDE_ERROR_NO_ERROR;
273 }
274
275 static int IDE_Open(struct Block_Device *dev)
276 {
277     KASSERT(!dev->inUse);
278     return 0;
279 }
280
281 static int IDE_Close(struct Block_Device *dev)
282 {
283     KASSERT(dev->inUse);
284     return 0;
285 }
286
287 static int IDE_Get_Num_Blocks(struct Block_Device *dev)
288 {
289     return IDE_getNumBlocks(dev->unit);
290 }
291
292 static struct Block_Device_Ops s_ideDeviceOps = {
293     IDE_Open,
294     IDE_Close,
295     IDE_Get_Num_Blocks,
296 };
297
298 static void IDE_Request_Thread(ulong_t arg)
299 {
300     for (;;) {
301         struct Block_Request *request;
302         int rc;
303
304         /* Wait for a request to arrive */
305         request = Dequeue_Request(&s_ideRequestQueue, &s_ideWaitQueue);
306
307         /* Do the I/O */
308         if (request->type == BLOCK_READ)
309             rc = IDE_Read(request->dev->unit, request->blockNum, request->buf);
310         else
311             rc = IDE_Write(request->dev->unit, request->blockNum, request->buf);
312
313         /* Notify requesting thread of final status */
314         Notify_Request_Completion(request, rc == 0 ? COMPLETED : ERROR, rc);
315     }
316 }
317
318 static int readDriveConfig(int drive)
319 {
320     int i;
321     int status;
322     short info[256];
323     char devname[BLOCKDEV_MAX_NAME_LEN];
324     int rc;
325
326     if (ideDebug) Print("ide: about to read drive config for drive #%d\n", drive);
327  
328
329     Out_Byte(IDE_DRIVE_HEAD_REGISTER, (drive == 0) ? IDE_DRIVE_0 : IDE_DRIVE_1);
330     Print("Set head register\n");
331
332     Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_IDENTIFY_DRIVE);
333
334     Print ("identify drive\n");
335
336     while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY);
337
338     Print ("Status no longer busy\n");
339
340     status = In_Byte(IDE_STATUS_REGISTER);
341
342     Print ("Status is %x\n",status);
343     /*
344      * simulate failure
345      * status = 0x50;
346      */
347     if ((status & IDE_STATUS_DRIVE_DATA_REQUEST)) {
348       Print("ide: probe found ATA drive\n");
349       /* drive responded to ATA probe */
350       for (i=0; i < 256; i++) {
351         info[i] = In_Word(IDE_DATA_REGISTER);
352       }
353       
354       drives[drive].num_Cylinders = info[IDE_INDENTIFY_NUM_CYLINDERS];
355       drives[drive].num_Heads = info[IDE_INDENTIFY_NUM_HEADS];
356       drives[drive].num_SectorsPerTrack = info[IDE_INDENTIFY_NUM_SECTORS_TRACK];
357       drives[drive].num_BytesPerSector = info[IDE_INDENTIFY_NUM_BYTES_SECTOR];
358     } else {
359        /* try for ATAPI */
360       Print("Trying for ATAPI\n");
361       Out_Byte(IDE_FEATURE_REG, 0);              /* disable dma & overlap */
362       Print("Out FEATURE REG\n");
363       
364       Out_Byte(IDE_DRIVE_HEAD_REGISTER, (drive == 0) ? IDE_DRIVE_0 : IDE_DRIVE_1);
365       Print("Out Head Select\n");
366       Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_ATAPI_IDENT_DRIVE);
367       Print("Out Ident drive\n");
368
369       while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY);
370       Print("No longer busy\n");
371
372       status = In_Byte(IDE_STATUS_REGISTER);
373       
374       Print("status is %x\n",status);
375       Print("ide: found atapi drive\n");
376       return -1;
377     }
378     
379     Print("    ide%d: cyl=%d, heads=%d, sectors=%d\n", drive, drives[drive].num_Cylinders,
380           drives[drive].num_Heads, drives[drive].num_SectorsPerTrack);
381     
382     /* Register the drive as a block device */
383     snprintf(devname, sizeof(devname), "ide%d", drive);
384     rc = Register_Block_Device(devname, &s_ideDeviceOps, drive, 0, &s_ideWaitQueue, &s_ideRequestQueue);
385     if (rc != 0)
386         Print("  Error: could not create block device for %s\n", devname);
387
388     return 0;
389 }
390
391
392 void Init_IDE(void)
393 {
394     int errorCode;
395
396     // Check to see if controller 0 is present
397     Out_Byte(0x1f3,0x88);
398     if (In_Byte(0x1f3)==0x88) { 
399       Print("IDE Controller 0 is present\n");
400     }
401
402     // Check to see if controller 1 is present
403     Out_Byte(0x173,0x88);
404     if (In_Byte(0x173)==0x88) { 
405       Print("IDE Controller 1 is present\n");
406     }
407
408     Print("Initializing IDE controller (0x1f0)...\n");
409
410     /* Reset the controller and drives */
411     Out_Byte(IDE_DEVICE_CONTROL_REGISTER, IDE_DCR_NOINTERRUPT | IDE_DCR_RESET);
412     Micro_Delay(100);
413     Out_Byte(IDE_DEVICE_CONTROL_REGISTER, IDE_DCR_NOINTERRUPT);
414
415 /*
416  * FIXME: This code doesn't work on Bochs 2.0.
417  *    while ((In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_READY) == 0)
418  *      ;
419  */
420
421     /* This code does work on Bochs 2.0. */
422     while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY)
423         ;
424
425     if (ideDebug) Print("About to run drive Diagnosis\n");
426
427     Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_DIAGNOSTIC);
428     while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY);
429     errorCode = In_Byte(IDE_ERROR_REGISTER);
430     if (ideDebug) Print("ide: ide error register = %x\n", errorCode);
431
432     /* Probe and register drives */
433     if (readDriveConfig(0) == 0)
434         ++numDrives;
435     if (readDriveConfig(1) == 0)
436         ++numDrives;
437     if (ideDebug) Print("Found %d IDE drives\n", numDrives);
438
439     /* Start request thread */
440     if (numDrives > 0)
441         Start_Kernel_Thread(IDE_Request_Thread, 0, PRIORITY_NORMAL, true);
442 }