📄 ata_ide_drive.c
字号:
#include "ide_bus.h"#include "ata_ide_drive.h"#include <kernel/dev/arch/i386/ide/ide_bus.h>#include <kernel/heap.h>#include <kernel/debug.h>#include <kernel/lock.h>#define CB_DC_HD15 0x08 // bit should always be set to one#define CB_DC_NIEN 0x02 // disable interrupts#define CB_DH_DEV0 0xa0 // select device 0#define CB_DH_DEV1 0xb0 // select device 1#define DH_DRV1 0x1#define DH_LBA 0x400// Most mandtory and optional ATA commands (from ATA-3),#define CMD_CFA_ERASE_SECTORS 0xC0#define CMD_CFA_REQUEST_EXT_ERR_CODE 0x03#define CMD_CFA_TRANSLATE_SECTOR 0x87#define CMD_CFA_WRITE_MULTIPLE_WO_ERASE 0xCD#define CMD_CFA_WRITE_SECTORS_WO_ERASE 0x38#define CMD_CHECK_POWER_MODE1 0xE5#define CMD_CHECK_POWER_MODE2 0x98#define CMD_DEVICE_RESET 0x08#define CMD_EXECUTE_DEVICE_DIAGNOSTIC 0x90#define CMD_FLUSH_CACHE 0xE7#define CMD_FORMAT_TRACK 0x50#define CMD_IDENTIFY_DEVICE 0xEC#define CMD_IDENTIFY_DEVICE_PACKET 0xA1#define CMD_IDENTIFY_PACKET_DEVICE 0xA1#define CMD_IDLE1 0xE3#define CMD_IDLE2 0x97#define CMD_IDLE_IMMEDIATE1 0xE1#define CMD_IDLE_IMMEDIATE2 0x95#define CMD_INITIALIZE_DRIVE_PARAMETERS 0x91#define CMD_INITIALIZE_DEVICE_PARAMETERS 0x91#define CMD_NOP 0x00#define CMD_PACKET 0xA0#define CMD_READ_BUFFER 0xE4#define CMD_READ_DMA 0xC8#define CMD_READ_DMA_QUEUED 0xC7#define CMD_READ_MULTIPLE 0xC4#define CMD_READ_SECTORS 0x20#define CMD_READ_VERIFY_SECTORS 0x40#define CMD_RECALIBRATE 0x10#define CMD_SEEK 0x70#define CMD_SET_FEATURES 0xEF#define CMD_SET_MULTIPLE_MODE 0xC6#define CMD_SLEEP1 0xE6#define CMD_SLEEP2 0x99#define CMD_STANDBY1 0xE2#define CMD_STANDBY2 0x96#define CMD_STANDBY_IMMEDIATE1 0xE0#define CMD_STANDBY_IMMEDIATE2 0x94#define CMD_WRITE_BUFFER 0xE8#define CMD_WRITE_DMA 0xCA#define CMD_WRITE_DMA_QUEUED 0xCC#define CMD_WRITE_MULTIPLE 0xC5#define CMD_WRITE_SECTORS 0x30#define CMD_WRITE_VERIFY 0x3C#define CB_STAT_BSY 0x80 // busy#define CB_STAT_RDY 0x40 // ready#define CB_STAT_DF 0x20 // device fault#define CB_STAT_WFT 0x20 // write fault (old name)#define CB_STAT_SKC 0x10 // seek complete#define CB_STAT_SERV 0x10 // service#define CB_STAT_DRQ 0x08 // data request#define CB_STAT_CORR 0x04 // corrected#define CB_STAT_IDX 0x02 // index#define CB_STAT_ERR 0x01 // error (ATA)#define CB_STAT_CHK 0x01 // check (ATAPI)#define NO_ERR 0#define ERR_EXPIRED_TIME_OUT -1#define ERR_DISK_BUSY -2#define ERR_HARDWARE_ERROR -3#define ERR_DRQ_NOT_SET -4#define ERR_TRANSMIT_BUFFER_NOT_EMPTY -5#define ERR_DEVICE_FAULT -6#define DRIVE_SUPPORT_LBA 0x0200#define IDE_TRACE 1#if IDE_TRACE#define TRACE(x) dprintf x#else#define TRACE(x)#endif#define STATUS_WAITING_INTR 1#define STATUS_IDLE 2typedef struct s_ata_command{ int cmd; int fr; int sc; int cyl; int head; int sect; uint8 *output; int numSect; int multiCnt; bool read; bool useInterrupt;}ata_command;typedef struct{ ide_bus *attached_bus; void *attached_bus_cookie; int position; bool lba_supported; long sector_count; uint16 bytes_per_sector; ide_drive_info device_info; int status; ata_command *active_command; mutex interrupt_mutex;}ata_drive_cookie;static void ide_reg_poll(ide_bus *bus, void *b_cookie){ uint8 status; while(1) { status = bus->get_alt_status(b_cookie); // poll for not busy if ( ( status & CB_STAT_BSY ) == 0 ) break; }}static int convert_error(int error){ if(error & CB_STAT_BSY) return ERR_DISK_BUSY; if(error & CB_STAT_DF) return ERR_DEVICE_FAULT; if(error & CB_STAT_ERR) return ERR_HARDWARE_ERROR; return 0;}static void signal_interrupt(void *b_cookie,void *drive_cookie){ ata_drive_cookie *cookie = drive_cookie; TRACE(("in signal interrupt status is %d\n",cookie->status)); if(cookie->status == STATUS_WAITING_INTR) { TRACE(("unlock mutex\n")); mutex_unlock(&cookie->interrupt_mutex); }}int execute_command( ide_bus *bus, void *b_cookie,ata_drive_cookie *drive_cookie,ata_command *command){ unsigned char devHead; unsigned char devCtrl; unsigned char cylLow; unsigned char cylHigh; unsigned char status; unsigned int wordCnt; int i; uint16 *buffer = (uint16*)command->output; int error_code; if(command->useInterrupt==true) devCtrl = CB_DC_HD15; else devCtrl = CB_DC_HD15 | CB_DC_NIEN; devHead = drive_cookie->position ? CB_DH_DEV1 : CB_DH_DEV0; devHead = devHead | ( command->head & 0x4f ); cylLow = command->cyl & 0x00ff; cylHigh = ( command->cyl & 0xff00 ) >> 8; // these commands transfer only 1 sector if (( command->cmd == CMD_IDENTIFY_DEVICE )|| ( command->cmd == CMD_IDENTIFY_DEVICE_PACKET )|| ( command->cmd == CMD_READ_BUFFER )|| ( command->cmd == CMD_WRITE_BUFFER)) command->numSect = 1; // only Read Multiple uses multiCnt if ( (command->cmd != CMD_READ_MULTIPLE ) && ( command->cmd != CMD_WRITE_MULTIPLE ) && ( command->cmd != CMD_CFA_WRITE_MULTIPLE_WO_ERASE )) command->multiCnt = 1; if(command->useInterrupt) { drive_cookie->active_command = command; drive_cookie->status = STATUS_WAITING_INTR; } if ( bus->select_drive( b_cookie,drive_cookie->position) ) { return ERR_EXPIRED_TIME_OUT; } bus->write_register(b_cookie, CB_DC, devCtrl ); bus->write_register(b_cookie, CB_FR, command->fr ); bus->write_register(b_cookie, CB_SC, command->sc ); bus->write_register(b_cookie, CB_SN, command->sect ); bus->write_register(b_cookie, CB_CL, cylLow ); bus->write_register(b_cookie, CB_CH, cylHigh ); bus->write_register(b_cookie, CB_DH, devHead ); bus->write_register(b_cookie, CB_CMD, command->cmd ); if(command->useInterrupt) { TRACE(("locking interrupt mutex\n")); mutex_lock(&drive_cookie->interrupt_mutex); TRACE(("entering wait loop\n")); } else { bus->delay_on_bus(b_cookie); } while ( 1 ) { if(command->read) { if(command->useInterrupt) { mutex_lock(&drive_cookie->interrupt_mutex); mutex_unlock(&drive_cookie->interrupt_mutex); } else ide_reg_poll(bus,b_cookie); } status = bus->get_alt_status(b_cookie); if ( ( status & ( CB_STAT_BSY | CB_STAT_DRQ ) ) == CB_STAT_DRQ ) { wordCnt = command->multiCnt ? command->multiCnt : 1; if ( wordCnt > command->numSect ) wordCnt = command->numSect; wordCnt = wordCnt * 256; bus->transfer_buffer( b_cookie,CB_DATA, buffer, wordCnt ,command->read); bus->delay_on_bus(b_cookie); command->numSect = command->numSect - ( command->multiCnt ? command->multiCnt : 1 ); buffer+=wordCnt; } if(!command->read) { if(command->useInterrupt) { mutex_lock(&drive_cookie->interrupt_mutex); mutex_unlock(&drive_cookie->interrupt_mutex); } else ide_reg_poll(bus,b_cookie); status = bus->get_alt_status(b_cookie); } error_code = convert_error(status); if(error_code!=0) return error_code; if ( ( status & CB_STAT_DRQ ) == 0 ) { return ERR_DRQ_NOT_SET; } if ( command->numSect < 1 ) { status = bus->get_alt_status(b_cookie); error_code = convert_error(status); if(error_code!=0) return error_code; if( status & CB_STAT_DRQ) { return ERR_TRANSMIT_BUFFER_NOT_EMPTY; } break; // go to READ_DONE } } drive_cookie->status = STATUS_IDLE; return NO_ERR;}int execute_command_dma( ide_bus *bus, void *b_cookie,ata_drive_cookie *drive_cookie, ata_command *command){ unsigned char devHead; unsigned char devCtrl; unsigned char cylLow; unsigned char cylHigh; unsigned char status; int ns; unsigned long lw1, lw2; int doTwo; // setup register values dprintf("entering execute_command_dma %X %X %X %X %X\n",bus,b_cookie,drive_cookie,command,command->output); devCtrl = 0; devHead = drive_cookie->position ? CB_DH_DEV1 : CB_DH_DEV0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -