📄 ide_raw.c
字号:
return ERR_DISK_BUSY; if(status & CB_STAT_DF) return ERR_DEVICE_FAULT; if(status & CB_STAT_ERR) return ERR_HARDWARE_ERROR; if((status & CB_STAT_DRQ) == 0) return ERR_DRQ_NOT_SET; } return NO_ERR;}static int reg_pio_data_out( int bus, int dev, int cmd, int fr, int sc, unsigned int cyl, int head, int sect, const uint8 *output, unsigned int numSect, unsigned int multiCnt ){ unsigned char devHead; unsigned char devCtrl; unsigned char cylLow; unsigned char cylHigh; unsigned char status; uint16 *buffer = (uint16*)output; devCtrl = CB_DC_HD15 | CB_DC_NIEN; devHead = dev ? CB_DH_DEV1 : CB_DH_DEV0; devHead = devHead | (head & 0x4f); cylLow = cyl & 0x00ff; cylHigh = (cyl & 0xff00) >> 8; if (cmd == CMD_WRITE_BUFFER) numSect = 1; // only Write Multiple and CFA Write Multiple W/O Erase uses multCnt if ((cmd != CMD_WRITE_MULTIPLE) && (cmd != CMD_CFA_WRITE_MULTIPLE_WO_ERASE)) multiCnt = 1; // select the drive if (ide_select_device(bus, dev) != NO_ERR) return ERR_TIMEOUT; // set up the registers pio_outbyte(CB_DC, devCtrl); pio_outbyte(CB_FR, fr); pio_outbyte(CB_SC, sc); pio_outbyte(CB_SN, sect); pio_outbyte(CB_CL, cylLow); pio_outbyte(CB_CH, cylHigh); pio_outbyte(CB_DH, devHead); // Start the command. The drive should immediately set BUSY status. pio_outbyte(CB_CMD, cmd); DELAY400NS; if (ide_wait_busy() == false) return ERR_TIMEOUT; status = pio_inbyte(CB_STAT); while (1) { if ((status & (CB_STAT_BSY | CB_STAT_DRQ)) == CB_STAT_DRQ) { unsigned int wordCnt = multiCnt > numSect ? numSect : multiCnt; wordCnt = wordCnt * 256; pio_rep_outword(CB_DATA, buffer, wordCnt); DELAY400NS; numSect = numSect - multiCnt; buffer += wordCnt; } // check all possible fault conditions if(status & CB_STAT_BSY) return ERR_DISK_BUSY; if(status & CB_STAT_DF) return ERR_DEVICE_FAULT; if(status & CB_STAT_ERR) return ERR_HARDWARE_ERROR; if ((status & CB_STAT_DRQ) == 0) return ERR_DRQ_NOT_SET; ide_delay(bus, dev); // ensure drive isn't still busy ide_reg_poll(); if(numSect < 1 && status & (CB_STAT_BSY | CB_STAT_DF | CB_STAT_ERR)) { dprintf("status = 0x%x\n", status); return ERR_BUFFER_NOT_EMPTY; } } return NO_ERR;}static void ide_btochs(uint32 block, ide_device *dev, int *cylinder, int *head, int *sect){ *sect = (block % dev->hardware_device.sectors) + 1; block /= dev->hardware_device.sectors; *head = (block % dev->hardware_device.heads) | (dev->device ? 1 : 0); block /= dev->hardware_device.heads; *cylinder = block & 0xFFFF;// dprintf("ide_btochs: block %d -> cyl %d head %d sect %d\n", block, *cylinder, *head, *sect);}static void ide_btolba(uint32 block, ide_device *dev, int *cylinder, int *head, int *sect){ *sect = block & 0xFF; *cylinder = (block >> 8) & 0xFFFF; *head = ((block >> 24) & 0xF) | (dev->device ? 1: 0) | CB_DH_LBA;// dprintf("ide_btolba: block %d -> cyl %d head %d sect %d\n", block, *cylinder, *head, *sect);}int ide_read_block(ide_device *device, char *data, uint32 block, uint8 numSectors){ int cyl, head, sect; if(device->lba_supported) ide_btolba(block, device, &cyl, &head, §); else ide_btochs(block, device, &cyl, &head, §); return reg_pio_data_in(device->bus, device->device, CMD_READ_SECTORS, 0, numSectors, cyl, head, sect, data, numSectors, 2);}int ide_write_block(ide_device *device, const char *data, uint32 block, uint8 numSectors){ int cyl, head, sect; if(device->lba_supported) ide_btolba(block, device, &cyl, &head, §); else ide_btochs(block, device, &cyl, &head, §); return reg_pio_data_out(device->bus, device->device, CMD_WRITE_SECTORS, 0, numSectors, cyl, head, sect, data, numSectors, 2);}void ide_string_conv (char *str, int len){ unsigned int i; int j; for (i=0; i<len/sizeof(unsigned short); i++) { char c = str[i*2+1]; str[i*2+1] = str[i*2]; str[i*2] = c; } str[len - 1] = 0; for (j=len-1; j>=0 && str[j]==' '; j--) str[j] = 0;}// ide_reset() - execute a software resetbool ide_reset (int bus, int device){ unsigned char devCtrl = CB_DC_HD15 | CB_DC_NIEN; // Set and then reset the soft reset bit in the Device // Control register. This causes device 0 be selected pio_outbyte(CB_DC, devCtrl | CB_DC_SRST); DELAY400NS; pio_outbyte(CB_DC, devCtrl); DELAY400NS; return (ide_wait_busy() ? true : false);}bool ide_identify_device(int bus, int device){ ide_device* ide = &devices[(bus*2) + device]; uint8* buffer; int rc; // Store specs for device ide->bus = bus; ide->device = device; // Do an IDENTIFY DEVICE command buffer = (uint8*)&ide->hardware_device; rc = reg_pio_data_in(bus, device, CMD_IDENTIFY_DEVICE, 1, 0, 0, 0, 0, buffer, 1, 0); if (rc == NO_ERR) { // If command was ok, lets assume ATA device ide->device_type = ATA_DEVICE; // Convert the model string to ASCIIZ ide_string_conv(ide->hardware_device.model, 40); // Get copy over interesting data ide->sector_count = ide->hardware_device.cyls * ide->hardware_device.heads * ide->hardware_device.sectors; ide->bytes_per_sector = 512; ide->lba_supported = ide->hardware_device.capabilities & DRIVE_SUPPORT_LBA; ide->start_block = 0; ide->end_block = ide->sector_count + ide->start_block; // Give some debugging output to show what was found dprintf ("ide: disk at bus %d, device %d %s\n", bus, device, ide->hardware_device.model); dprintf ("ide/%d/%d: %dMB; %d cyl, %d head, %d sec, %d bytes/sec (LBA=%d)\n", bus, device, ide->sector_count * ide->bytes_per_sector / (1024*1024), ide->hardware_device.cyls, ide->hardware_device.heads, ide->hardware_device.sectors, ide->bytes_per_sector, ide->lba_supported ); } else { // Something went wrong, let's forget about this device ide->device_type = NO_DEVICE; } return (rc == NO_ERROR) ? true : false;}// Set the pio base addressesvoid ide_raw_init(int base1, int base2){ unsigned int pio_base_addr1 = base1; unsigned int pio_base_addr2 = base2; pio_reg_addrs[CB_DATA] = pio_base_addr1 + 0; // 0 pio_reg_addrs[CB_FR ] = pio_base_addr1 + 1; // 1 pio_reg_addrs[CB_SC ] = pio_base_addr1 + 2; // 2 pio_reg_addrs[CB_SN ] = pio_base_addr1 + 3; // 3 pio_reg_addrs[CB_CL ] = pio_base_addr1 + 4; // 4 pio_reg_addrs[CB_CH ] = pio_base_addr1 + 5; // 5 pio_reg_addrs[CB_DH ] = pio_base_addr1 + 6; // 6 pio_reg_addrs[CB_CMD ] = pio_base_addr1 + 7; // 7 pio_reg_addrs[CB_DC ] = pio_base_addr2 + 6; // 8 pio_reg_addrs[CB_DA ] = pio_base_addr2 + 7; // 9}static char getHexChar(uint8 value){ if(value < 10) return value + '0'; return 'A' + (value - 10);}static void dumpHexLine(uint8 *buffer, int numberPerLine){ uint8 *copy = buffer; int i; for(i=0; i<numberPerLine; i++) { uint8 value1 = getHexChar(((*copy) >> 4)); uint8 value2 = getHexChar(((*copy) & 0xF)); dprintf("%c%c ", value1, value2); copy++; } copy = buffer; for(i=0; i<numberPerLine; i++) { if(*copy >= ' ' && *copy <= 'Z') dprintf("%c", *copy); else dprintf("."); copy++; } dprintf("\n");}static void dumpHexBuffer(uint8 *buffer, int size){ int numberPerLine = 8; int numberOfLines = size / numberPerLine; int i, j; for(i=0; i<numberOfLines; i++) { dprintf("%d ", i*numberPerLine); dumpHexLine(buffer, numberPerLine); buffer += numberPerLine; }}static bool ide_get_partition_info(ide_device *device, tPartition *partition, uint32 position){ char buffer[512]; uint8* partitionBuffer = buffer; // Try to read partition table if (ide_read_block(device, buffer, position, 1) != 0) { dprintf("unable to read partition table\n"); return false; } // Check partition table signature if (partitionBuffer[PART_MAGIC_OFFSET] != PARTITION_MAGIC1 || partitionBuffer[PART_MAGIC_OFFSET+1] != PARTITION_MAGIC2) { dprintf("partition table magic is incorrect\n"); return false; } memcpy(partition, partitionBuffer + PARTITION_OFFSET, sizeof(tPartition) * NUM_PARTITIONS); return true;}bool ide_get_partitions(ide_device *device){ int i; memset(&device->partitions, 0, sizeof(tPartition) * 2 * NUM_PARTITIONS); if(ide_get_partition_info(device, device->partitions, 0) == false) return false; dprintf("Primary Partition Table\n"); for (i = 0; i < NUM_PARTITIONS; i++) { dprintf(" %d: flags:%x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n", i, device->partitions[i].boot_flags, device->partitions[i].partition_type, device->partitions[i].starting_head, device->partitions[i].starting_sector, device->partitions[i].starting_cylinder, device->partitions[i].ending_head, device->partitions[i].ending_sector, device->partitions[i].ending_cylinder, device->partitions[i].starting_block, device->partitions[i].sector_count); } if(device->partitions[1].partition_type == PTDosExtended) { int extOffset = device->partitions[1].starting_block; if(ide_get_partition_info(device, &device->partitions[4], extOffset) == false) return false; dprintf("Extended Partition Table\n"); for (i=4; i<4+NUM_PARTITIONS; i++) { device->partitions[i].starting_block += extOffset; dprintf(" %d: flags:%x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n", i, device->partitions[i].boot_flags, device->partitions[i].partition_type, device->partitions[i].starting_head, device->partitions[i].starting_sector, device->partitions[i].starting_cylinder, device->partitions[i].ending_head, device->partitions[i].ending_sector, device->partitions[i].ending_cylinder, device->partitions[i].starting_block, device->partitions[i].sector_count); } } return true;}// These two functions are called from ide_ioctl in ide.c. They are far from// tested, and mostly just a C conversion of a DEBUG script presented on// http://www.satwerk.de/ufd552.htm// This should be tweaked some more before actual release!int ide_get_accoustic(ide_device *device, int8* level_ptr){ return ERR_UNIMPLEMENTED;}int ide_set_accoustic(ide_device *device, int8 level){ pio_outbyte(CB_DH, (device->device == 1) ? CB_DH_DEV1 : CB_DH_DEV0); pio_outbyte(CB_CMD, CMD_SET_ACCOUSTIC_LEVEL); pio_outbyte(CB_SC, level); pio_outbyte(CB_STAT, 0xEF); return NO_ERROR;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -