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>
7 * This is free software. You are permitted to use,
8 * redistribute, and modify it as specified in the file "COPYING".
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
17 #include <geekos/serial.h>
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>
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
46 #define IDE_DRIVE_0 0xa0
47 #define IDE_DRIVE_1 0xb0
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
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
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
76 /* Bits of Device Control Register */
77 #define IDE_DCR_NOINTERRUPT 0x02
78 #define IDE_DCR_RESET 0x04
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
86 /* Control register bits */
87 #define IDE_CONTROL_REGISTER 0x3F6
88 #define IDE_CONTROL_SOFTWARE_RESET 0x04
89 #define IDE_CONTROL_INT_DISABLE 0x02
91 #define LOW_BYTE(x) (x & 0xff)
92 #define HIGH_BYTE(x) ((x >> 8) & 0xff)
94 #define IDE_MAX_DRIVES 2
99 short num_SectorsPerTrack;
100 short num_BytesPerSector;
104 static int numDrives;
105 static ideDisk drives[IDE_MAX_DRIVES];
107 struct Thread_Queue s_ideWaitQueue;
108 struct Block_Request_List s_ideRequestQueue;
111 * return the number of logical blocks for a particular drive.
114 static int IDE_getNumBlocks(int driveNum)
116 if (driveNum < 0 || driveNum > IDE_MAX_DRIVES) {
117 return IDE_ERROR_BAD_DRIVE;
120 return (drives[driveNum].num_Heads *
121 drives[driveNum].num_SectorsPerTrack *
122 drives[driveNum].num_Cylinders);
126 * Read a block at the logical block number indicated.
128 static int IDE_Read(int driveNum, int blockNum, char *buffer)
137 if (driveNum < 0 || driveNum > (numDrives-1)) {
138 if (ideDebug) Print("ide: invalid drive %d\n", driveNum);
139 return IDE_ERROR_BAD_DRIVE;
142 if (blockNum < 0 || blockNum >= IDE_getNumBlocks(driveNum)) {
143 if (ideDebug) Print("ide: invalid block %d\n", blockNum);
144 return IDE_ERROR_INVALID_BLOCK;
147 if (Interrupts_Enabled()) {
148 Disable_Interrupts();
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;
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);
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));
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);
176 Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_READ_SECTORS);
178 if (ideDebug > 2) Print("About to wait for Read \n");
180 /* wait for the drive */
181 while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY);
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;
188 if (ideDebug > 2) Print("got buffer \n");
190 bufferW = (short *) buffer;
191 for (i=0; i < 256; i++) {
192 bufferW[i] = In_Word(IDE_DATA_REGISTER);
195 if (reEnable) Enable_Interrupts();
197 return IDE_ERROR_NO_ERROR;
201 * Write a block at the logical block number indicated.
203 static int IDE_Write(int driveNum, int blockNum, char *buffer)
212 if (driveNum < 0 || driveNum > (numDrives-1)) {
213 return IDE_ERROR_BAD_DRIVE;
216 if (blockNum < 0 || blockNum >= IDE_getNumBlocks(driveNum)) {
217 return IDE_ERROR_INVALID_BLOCK;
220 if (Interrupts_Enabled()) {
221 Disable_Interrupts();
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;
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);
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));
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);
249 Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_WRITE_SECTORS);
252 /* wait for the drive */
253 while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY);
255 bufferW = (short *) buffer;
256 for (i=0; i < 256; i++) {
257 Out_Word(IDE_DATA_REGISTER, bufferW[i]);
260 if (ideDebug) Print("About to wait for Write \n");
262 /* wait for the drive */
263 while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY);
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;
270 if (reEnable) Enable_Interrupts();
272 return IDE_ERROR_NO_ERROR;
275 static int IDE_Open(struct Block_Device *dev)
277 KASSERT(!dev->inUse);
281 static int IDE_Close(struct Block_Device *dev)
287 static int IDE_Get_Num_Blocks(struct Block_Device *dev)
289 return IDE_getNumBlocks(dev->unit);
292 static struct Block_Device_Ops s_ideDeviceOps = {
298 static void IDE_Request_Thread(ulong_t arg)
301 struct Block_Request *request;
304 /* Wait for a request to arrive */
305 request = Dequeue_Request(&s_ideRequestQueue, &s_ideWaitQueue);
308 if (request->type == BLOCK_READ)
309 rc = IDE_Read(request->dev->unit, request->blockNum, request->buf);
311 rc = IDE_Write(request->dev->unit, request->blockNum, request->buf);
313 /* Notify requesting thread of final status */
314 Notify_Request_Completion(request, rc == 0 ? COMPLETED : ERROR, rc);
318 static int readDriveConfig(int drive)
323 char devname[BLOCKDEV_MAX_NAME_LEN];
326 if (ideDebug) Print("ide: about to read drive config for drive #%d\n", drive);
329 Out_Byte(IDE_DRIVE_HEAD_REGISTER, (drive == 0) ? IDE_DRIVE_0 : IDE_DRIVE_1);
330 Print("Set head register\n");
332 Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_IDENTIFY_DRIVE);
334 Print ("identify drive\n");
336 while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY);
338 Print ("Status no longer busy\n");
340 status = In_Byte(IDE_STATUS_REGISTER);
342 Print ("Status is %x\n",status);
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);
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];
360 Print("Trying for ATAPI\n");
361 Out_Byte(IDE_FEATURE_REG, 0); /* disable dma & overlap */
362 Print("Out FEATURE REG\n");
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");
369 while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY);
370 Print("No longer busy\n");
372 status = In_Byte(IDE_STATUS_REGISTER);
374 Print("status is %x\n",status);
375 Print("ide: found atapi drive\n");
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);
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);
386 Print(" Error: could not create block device for %s\n", devname);
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");
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");
408 Print("Initializing IDE controller (0x1f0)...\n");
410 /* Reset the controller and drives */
411 Out_Byte(IDE_DEVICE_CONTROL_REGISTER, IDE_DCR_NOINTERRUPT | IDE_DCR_RESET);
413 Out_Byte(IDE_DEVICE_CONTROL_REGISTER, IDE_DCR_NOINTERRUPT);
416 * FIXME: This code doesn't work on Bochs 2.0.
417 * while ((In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_READY) == 0)
421 /* This code does work on Bochs 2.0. */
422 while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY)
425 if (ideDebug) Print("About to run drive Diagnosis\n");
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);
432 /* Probe and register drives */
433 if (readDriveConfig(0) == 0)
435 if (readDriveConfig(1) == 0)
437 if (ideDebug) Print("Found %d IDE drives\n", numDrives);
439 /* Start request thread */
441 Start_Kernel_Thread(IDE_Request_Thread, 0, PRIORITY_NORMAL, true);