X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=misc%2Ftest_vm%2Fsrc%2Fgeekos%2Fide.c;fp=misc%2Ftest_vm%2Fsrc%2Fgeekos%2Fide.c;h=0000000000000000000000000000000000000000;hp=22b02c2ff6b36b805cfa6399784311e6c4ecc6c5;hb=a70930549d1b741704dd7af4e6bb0e89f6f8a519;hpb=afb634a80f946634454a5d067a92aa600227bd93 diff --git a/misc/test_vm/src/geekos/ide.c b/misc/test_vm/src/geekos/ide.c deleted file mode 100644 index 22b02c2..0000000 --- a/misc/test_vm/src/geekos/ide.c +++ /dev/null @@ -1,442 +0,0 @@ -/* - * ATA (aka IDE) driver. - * Copyright (c) 2003, Jeffrey K. Hollingsworth - * Copyright (c) 2003,2004 David H. Hovemeyer - * $Revision: 1.1 $ - * - * This is free software. You are permitted to use, - * redistribute, and modify it as specified in the file "COPYING". - */ - -/* - * NOTES: - * 12/22/03 - Converted to use new block device layer with queued requests - * 1/20/04 - Changed probing of drives to work on Bochs 2.0 with 2 drives - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Registers */ -#define IDE_DATA_REGISTER 0x1f0 -#define IDE_ERROR_REGISTER 0x1f1 -#define IDE_FEATURE_REG IDE_ERROR_REGISTER -#define IDE_SECTOR_COUNT_REGISTER 0x1f2 -#define IDE_SECTOR_NUMBER_REGISTER 0x1f3 -#define IDE_CYLINDER_LOW_REGISTER 0x1f4 -#define IDE_CYLINDER_HIGH_REGISTER 0x1f5 -#define IDE_DRIVE_HEAD_REGISTER 0x1f6 -#define IDE_STATUS_REGISTER 0x1f7 -#define IDE_COMMAND_REGISTER 0x1f7 -#define IDE_DEVICE_CONTROL_REGISTER 0x3F6 - -/* Drives */ -#define IDE_DRIVE_0 0xa0 -#define IDE_DRIVE_1 0xb0 - -/* Commands */ -#define IDE_COMMAND_IDENTIFY_DRIVE 0xEC -#define IDE_COMMAND_SEEK 0x70 -#define IDE_COMMAND_READ_SECTORS 0x21 -#define IDE_COMMAND_READ_BUFFER 0xE4 -#define IDE_COMMAND_WRITE_SECTORS 0x30 -#define IDE_COMMAND_WRITE_BUFFER 0xE8 -#define IDE_COMMAND_DIAGNOSTIC 0x90 -#define IDE_COMMAND_ATAPI_IDENT_DRIVE 0xA1 - -/* Results words from Identify Drive Request */ -#define IDE_INDENTIFY_NUM_CYLINDERS 0x01 -#define IDE_INDENTIFY_NUM_HEADS 0x03 -#define IDE_INDENTIFY_NUM_BYTES_TRACK 0x04 -#define IDE_INDENTIFY_NUM_BYTES_SECTOR 0x05 -#define IDE_INDENTIFY_NUM_SECTORS_TRACK 0x06 - -/* bits of Status Register */ -#define IDE_STATUS_DRIVE_BUSY 0x80 -#define IDE_STATUS_DRIVE_READY 0x40 -#define IDE_STATUS_DRIVE_WRITE_FAULT 0x20 -#define IDE_STATUS_DRIVE_SEEK_COMPLETE 0x10 -#define IDE_STATUS_DRIVE_DATA_REQUEST 0x08 -#define IDE_STATUS_DRIVE_CORRECTED_DATA 0x04 -#define IDE_STATUS_DRIVE_INDEX 0x02 -#define IDE_STATUS_DRIVE_ERROR 0x01 - -/* Bits of Device Control Register */ -#define IDE_DCR_NOINTERRUPT 0x02 -#define IDE_DCR_RESET 0x04 - -/* Return codes from various IDE_* functions */ -#define IDE_ERROR_NO_ERROR 0 -#define IDE_ERROR_BAD_DRIVE -1 -#define IDE_ERROR_INVALID_BLOCK -2 -#define IDE_ERROR_DRIVE_ERROR -3 - -/* Control register bits */ -#define IDE_CONTROL_REGISTER 0x3F6 -#define IDE_CONTROL_SOFTWARE_RESET 0x04 -#define IDE_CONTROL_INT_DISABLE 0x02 - -#define LOW_BYTE(x) (x & 0xff) -#define HIGH_BYTE(x) ((x >> 8) & 0xff) - -#define IDE_MAX_DRIVES 2 - -typedef struct { - short num_Cylinders; - short num_Heads; - short num_SectorsPerTrack; - short num_BytesPerSector; -} ideDisk; - -int ideDebug = 99; -static int numDrives; -static ideDisk drives[IDE_MAX_DRIVES]; - -struct Thread_Queue s_ideWaitQueue; -struct Block_Request_List s_ideRequestQueue; - -/* - * return the number of logical blocks for a particular drive. - * - */ -static int IDE_getNumBlocks(int driveNum) -{ - if (driveNum < 0 || driveNum > IDE_MAX_DRIVES) { - return IDE_ERROR_BAD_DRIVE; - } - - return (drives[driveNum].num_Heads * - drives[driveNum].num_SectorsPerTrack * - drives[driveNum].num_Cylinders); -} - -/* - * Read a block at the logical block number indicated. - */ -static int IDE_Read(int driveNum, int blockNum, char *buffer) -{ - int i; - int head; - int sector; - int cylinder; - short *bufferW; - int reEnable = 0; - - if (driveNum < 0 || driveNum > (numDrives-1)) { - if (ideDebug) Print("ide: invalid drive %d\n", driveNum); - return IDE_ERROR_BAD_DRIVE; - } - - if (blockNum < 0 || blockNum >= IDE_getNumBlocks(driveNum)) { - if (ideDebug) Print("ide: invalid block %d\n", blockNum); - return IDE_ERROR_INVALID_BLOCK; - } - - if (Interrupts_Enabled()) { - Disable_Interrupts(); - reEnable = 1; - } - - /* now compute the head, cylinder, and sector */ - sector = blockNum % drives[driveNum].num_SectorsPerTrack + 1; - cylinder = blockNum / (drives[driveNum].num_Heads * - drives[driveNum].num_SectorsPerTrack); - head = (blockNum / drives[driveNum].num_SectorsPerTrack) % - drives[driveNum].num_Heads; - - if (ideDebug >= 2) { - Print ("request to read block %d\n", blockNum); - Print (" head %d\n", head); - Print (" cylinder %d\n", cylinder); - Print (" sector %d\n", sector); - } - - Out_Byte(IDE_SECTOR_COUNT_REGISTER, 1); - Out_Byte(IDE_SECTOR_NUMBER_REGISTER, sector); - Out_Byte(IDE_CYLINDER_LOW_REGISTER, LOW_BYTE(cylinder)); - Out_Byte(IDE_CYLINDER_HIGH_REGISTER, HIGH_BYTE(cylinder)); - if (driveNum == 0) { - Out_Byte(IDE_DRIVE_HEAD_REGISTER, IDE_DRIVE_0 | head); - } else if (driveNum == 1) { - Out_Byte(IDE_DRIVE_HEAD_REGISTER, IDE_DRIVE_1 | head); - } - - Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_READ_SECTORS); - - if (ideDebug > 2) Print("About to wait for Read \n"); - - /* wait for the drive */ - while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY); - - if (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_ERROR) { - Print("ERROR: Got Read %d\n", In_Byte(IDE_STATUS_REGISTER)); - return IDE_ERROR_DRIVE_ERROR; - } - - if (ideDebug > 2) Print("got buffer \n"); - - bufferW = (short *) buffer; - for (i=0; i < 256; i++) { - bufferW[i] = In_Word(IDE_DATA_REGISTER); - } - - if (reEnable) Enable_Interrupts(); - - return IDE_ERROR_NO_ERROR; -} - -/* - * Write a block at the logical block number indicated. - */ -static int IDE_Write(int driveNum, int blockNum, char *buffer) -{ - int i; - int head; - int sector; - int cylinder; - short *bufferW; - int reEnable = 0; - - if (driveNum < 0 || driveNum > (numDrives-1)) { - return IDE_ERROR_BAD_DRIVE; - } - - if (blockNum < 0 || blockNum >= IDE_getNumBlocks(driveNum)) { - return IDE_ERROR_INVALID_BLOCK; - } - - if (Interrupts_Enabled()) { - Disable_Interrupts(); - reEnable = 1; - } - - /* now compute the head, cylinder, and sector */ - sector = blockNum % drives[driveNum].num_SectorsPerTrack + 1; - cylinder = blockNum / (drives[driveNum].num_Heads * - drives[driveNum].num_SectorsPerTrack); - head = (blockNum / drives[driveNum].num_SectorsPerTrack) % - drives[driveNum].num_Heads; - - if (ideDebug) { - Print ("request to write block %d\n", blockNum); - Print (" head %d\n", head); - Print (" cylinder %d\n", cylinder); - Print (" sector %d\n", sector); - } - - Out_Byte(IDE_SECTOR_COUNT_REGISTER, 1); - Out_Byte(IDE_SECTOR_NUMBER_REGISTER, sector); - Out_Byte(IDE_CYLINDER_LOW_REGISTER, LOW_BYTE(cylinder)); - Out_Byte(IDE_CYLINDER_HIGH_REGISTER, HIGH_BYTE(cylinder)); - if (driveNum == 0) { - Out_Byte(IDE_DRIVE_HEAD_REGISTER, IDE_DRIVE_0 | head); - } else if (driveNum == 1) { - Out_Byte(IDE_DRIVE_HEAD_REGISTER, IDE_DRIVE_1 | head); - } - - Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_WRITE_SECTORS); - - - /* wait for the drive */ - while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY); - - bufferW = (short *) buffer; - for (i=0; i < 256; i++) { - Out_Word(IDE_DATA_REGISTER, bufferW[i]); - } - - if (ideDebug) Print("About to wait for Write \n"); - - /* wait for the drive */ - while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY); - - if (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_ERROR) { - Print("ERROR: Got Read %d\n", In_Byte(IDE_STATUS_REGISTER)); - return IDE_ERROR_DRIVE_ERROR; - } - - if (reEnable) Enable_Interrupts(); - - return IDE_ERROR_NO_ERROR; -} - -static int IDE_Open(struct Block_Device *dev) -{ - KASSERT(!dev->inUse); - return 0; -} - -static int IDE_Close(struct Block_Device *dev) -{ - KASSERT(dev->inUse); - return 0; -} - -static int IDE_Get_Num_Blocks(struct Block_Device *dev) -{ - return IDE_getNumBlocks(dev->unit); -} - -static struct Block_Device_Ops s_ideDeviceOps = { - IDE_Open, - IDE_Close, - IDE_Get_Num_Blocks, -}; - -static void IDE_Request_Thread(ulong_t arg) -{ - for (;;) { - struct Block_Request *request; - int rc; - - /* Wait for a request to arrive */ - request = Dequeue_Request(&s_ideRequestQueue, &s_ideWaitQueue); - - /* Do the I/O */ - if (request->type == BLOCK_READ) - rc = IDE_Read(request->dev->unit, request->blockNum, request->buf); - else - rc = IDE_Write(request->dev->unit, request->blockNum, request->buf); - - /* Notify requesting thread of final status */ - Notify_Request_Completion(request, rc == 0 ? COMPLETED : ERROR, rc); - } -} - -static int readDriveConfig(int drive) -{ - int i; - int status; - short info[256]; - char devname[BLOCKDEV_MAX_NAME_LEN]; - int rc; - - if (ideDebug) Print("ide: about to read drive config for drive #%d\n", drive); - - - Out_Byte(IDE_DRIVE_HEAD_REGISTER, (drive == 0) ? IDE_DRIVE_0 : IDE_DRIVE_1); - Print("Set head register\n"); - - Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_IDENTIFY_DRIVE); - - Print ("identify drive\n"); - - while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY); - - Print ("Status no longer busy\n"); - - status = In_Byte(IDE_STATUS_REGISTER); - - Print ("Status is %x\n",status); - /* - * simulate failure - * status = 0x50; - */ - if ((status & IDE_STATUS_DRIVE_DATA_REQUEST)) { - Print("ide: probe found ATA drive\n"); - /* drive responded to ATA probe */ - for (i=0; i < 256; i++) { - info[i] = In_Word(IDE_DATA_REGISTER); - } - - drives[drive].num_Cylinders = info[IDE_INDENTIFY_NUM_CYLINDERS]; - drives[drive].num_Heads = info[IDE_INDENTIFY_NUM_HEADS]; - drives[drive].num_SectorsPerTrack = info[IDE_INDENTIFY_NUM_SECTORS_TRACK]; - drives[drive].num_BytesPerSector = info[IDE_INDENTIFY_NUM_BYTES_SECTOR]; - } else { - /* try for ATAPI */ - Print("Trying for ATAPI\n"); - Out_Byte(IDE_FEATURE_REG, 0); /* disable dma & overlap */ - Print("Out FEATURE REG\n"); - - Out_Byte(IDE_DRIVE_HEAD_REGISTER, (drive == 0) ? IDE_DRIVE_0 : IDE_DRIVE_1); - Print("Out Head Select\n"); - Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_ATAPI_IDENT_DRIVE); - Print("Out Ident drive\n"); - - while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY); - Print("No longer busy\n"); - - status = In_Byte(IDE_STATUS_REGISTER); - - Print("status is %x\n",status); - Print("ide: found atapi drive\n"); - return -1; - } - - Print(" ide%d: cyl=%d, heads=%d, sectors=%d\n", drive, drives[drive].num_Cylinders, - drives[drive].num_Heads, drives[drive].num_SectorsPerTrack); - - /* Register the drive as a block device */ - snprintf(devname, sizeof(devname), "ide%d", drive); - rc = Register_Block_Device(devname, &s_ideDeviceOps, drive, 0, &s_ideWaitQueue, &s_ideRequestQueue); - if (rc != 0) - Print(" Error: could not create block device for %s\n", devname); - - return 0; -} - - -void Init_IDE(void) -{ - int errorCode; - - // Check to see if controller 0 is present - Out_Byte(0x1f3,0x88); - if (In_Byte(0x1f3)==0x88) { - Print("IDE Controller 0 is present\n"); - } - - // Check to see if controller 1 is present - Out_Byte(0x173,0x88); - if (In_Byte(0x173)==0x88) { - Print("IDE Controller 1 is present\n"); - } - - Print("Initializing IDE controller (0x1f0)...\n"); - - /* Reset the controller and drives */ - Out_Byte(IDE_DEVICE_CONTROL_REGISTER, IDE_DCR_NOINTERRUPT | IDE_DCR_RESET); - Micro_Delay(100); - Out_Byte(IDE_DEVICE_CONTROL_REGISTER, IDE_DCR_NOINTERRUPT); - -/* - * FIXME: This code doesn't work on Bochs 2.0. - * while ((In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_READY) == 0) - * ; - */ - - /* This code does work on Bochs 2.0. */ - while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY) - ; - - if (ideDebug) Print("About to run drive Diagnosis\n"); - - Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_DIAGNOSTIC); - while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY); - errorCode = In_Byte(IDE_ERROR_REGISTER); - if (ideDebug) Print("ide: ide error register = %x\n", errorCode); - - /* Probe and register drives */ - if (readDriveConfig(0) == 0) - ++numDrives; - if (readDriveConfig(1) == 0) - ++numDrives; - if (ideDebug) Print("Found %d IDE drives\n", numDrives); - - /* Start request thread */ - if (numDrives > 0) - Start_Kernel_Thread(IDE_Request_Thread, 0, PRIORITY_NORMAL, true); -}