/* * 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)); Out_Byte(IDE_DRIVE_HEAD_REGISTER, IDE_DRIVE(driveNum) | 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 readDriveConfig(int drive) { int i; int status; short info[256]; char devname[BLOCKDEV_MAX_NAME_LEN]; int rc; if (ideDebug > 1) Print("ide: about to read drive config for drive #%d\n", drive); Out_Byte(IDE_DRIVE_HEAD_REGISTER, IDE_DRIVE(drive)); Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_IDENTIFY_DRIVE); while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY); status = In_Byte(IDE_STATUS_REGISTER); /* * 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 */ Out_Byte(IDE_FEATURE_REG, 0); /* disable dma & overlap */ Out_Byte(IDE_DRIVE_HEAD_REGISTER, IDE_DRIVE(drive)); Out_Byte(IDE_COMMAND_REGISTER, IDE_COMMAND_ATAPI_IDENT_DRIVE); while (In_Byte(IDE_STATUS_REGISTER) & IDE_STATUS_DRIVE_BUSY); status = In_Byte(IDE_STATUS_REGISTER); Print("status is %x\n", status); if ((status & IDE_STATUS_DRIVE_DATA_REQUEST)) { Print("ide: found atapi drive\n"); } else { Print("ide: found no drive %d\n", drive); } 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; }
/* * 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; } /* 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, cylinder %d, sector %d\n", head, cylinder, sector); // Print (" cylinder %d\n", cylinder); // Print (" sector %d\n", sector); } #ifndef NS_INTERRUPTABLE_NO_GLOBAL_LOCK reEnable = Begin_Int_Atomic(); #endif 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)); Out_Byte(IDE_DRIVE_HEAD_REGISTER, IDE_DRIVE(driveNum) | 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(ideDebug > 2) Print("read buffer \n"); #ifndef NS_INTERRUPTABLE_NO_GLOBAL_LOCK End_Int_Atomic(reEnable); #endif return IDE_ERROR_NO_ERROR; }