📄 ata_ide_drive.c
字号:
devHead = devHead | ( command->head & 0x4f ); cylLow = command->cyl & 0x00ff; cylHigh = ( command->cyl & 0xff00 ) >> 8; // Quit now if the command is incorrect. if ( ( command->cmd != CMD_READ_DMA) && ( command->cmd != CMD_WRITE_DMA) ) { return -1; } // set up the dma transfer(s) ns = command->sc; if ( ! ns ) ns = 256; drive_cookie->active_command = command; doTwo = bus->setup_dma(b_cookie,command->cmd == CMD_WRITE_DMA, ns * 512L, command->output); if ( bus->select_drive( b_cookie,drive_cookie->position) ) { return ERR_EXPIRED_TIME_OUT; } // Set up all the registers except the command register. 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 ); drive_cookie->status = STATUS_WAITING_INTR; bus->delay_on_bus(b_cookie); bus->start_dma( b_cookie); dprintf("first lock\n"); mutex_lock(&drive_cookie->interrupt_mutex); dprintf("second lock\n"); mutex_lock(&drive_cookie->interrupt_mutex); mutex_unlock(&drive_cookie->interrupt_mutex); return bus->finish_dma(b_cookie);}static 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;}int ide_identify_device (ide_bus *bus, void *b_cookie,ata_drive_cookie *drive_cookie,int bus_pos){ int ret; uint8 *buffer; ata_command command; buffer = (uint8*)&drive_cookie->device_info; TRACE(("executing command\n")); command.cmd = CMD_IDENTIFY_DEVICE; command.fr = 1; command.sc = 0; command.cyl = 0; command.head = 0; command.sect = 0; command.output = buffer; command.numSect = 1; command.multiCnt = 0; command.read = true; command.useInterrupt = false; ret = execute_command( bus,b_cookie,drive_cookie,&command); TRACE(("executing command %d\n",ret)); if(ret<0) return -1; ide_string_conv(drive_cookie->device_info.model,40); drive_cookie->sector_count = drive_cookie->device_info.cyls*drive_cookie->device_info.heads*drive_cookie->device_info.sectors; drive_cookie->bytes_per_sector = 512; drive_cookie->lba_supported = drive_cookie->device_info.capabilities & DRIVE_SUPPORT_LBA; TRACE( ("ide: disk at bus %d, device %d %s\n", bus_pos, drive_cookie->position,drive_cookie->device_info.model)); TRACE(("ide/%d/%d: %dMB; %d cyl, %d head, %d sec, %d bytes/sec (LBA=%d)\n",bus_pos, drive_cookie->position, drive_cookie->sector_count * drive_cookie->bytes_per_sector / 1024, drive_cookie->device_info.cyls, drive_cookie->device_info.heads, drive_cookie->device_info.sectors, drive_cookie->bytes_per_sector, drive_cookie->lba_supported )); return 0;}static void *init_drive(ide_bus *bus,void *b_cookie,int channel,int drive){ uint8 sc,sn,ch,cl,st; unsigned char devCtrl = CB_DC_HD15 | CB_DC_NIEN ; void *ret = NULL; bus->write_register(b_cookie,CB_DC,devCtrl); bus->select_drive(b_cookie,drive); bus->delay_on_bus(b_cookie); bus->write_register( b_cookie,CB_SC, 0x55 ); bus->write_register( b_cookie,CB_SN, 0xaa ); bus->write_register( b_cookie,CB_SC, 0xaa ); bus->write_register( b_cookie,CB_SN, 0x55 ); bus->write_register( b_cookie,CB_SC, 0x55 ); bus->write_register( b_cookie,CB_SN, 0xaa ); sc = bus->read_register( b_cookie,CB_SC ); sn = bus->read_register( b_cookie,CB_SN ); if(sc!=0x55 && sn!=0xaa) { return NULL; } bus->select_drive(b_cookie,drive); bus->delay_on_bus(b_cookie); bus->reset_bus( b_cookie,drive); bus->select_drive(b_cookie,drive); bus->delay_on_bus(b_cookie); sc = bus->read_register( b_cookie,CB_SC ); sn = bus->read_register( b_cookie,CB_SN ); if ( ( sc == 0x01 ) && ( sn == 0x01 ) ) { ret = NULL; cl = bus->read_register( b_cookie,CB_CL ); ch = bus->read_register( b_cookie,CB_CH ); st = bus->read_register( b_cookie,CB_STAT ); if ( ( cl == 0x14 ) && ( ch == 0xeb ) ) ret = NULL; else if ( ( cl == 0x00 ) && ( ch == 0x00 ) && ( st != 0x00 ) ) { ata_drive_cookie *cookie = kmalloc(sizeof(ata_drive_cookie)); cookie->attached_bus = bus; cookie->attached_bus_cookie = b_cookie; cookie->position = drive; mutex_init(&cookie->interrupt_mutex,"test"); if(ide_identify_device(bus,b_cookie,cookie,channel)==0) ret = cookie; else ret = NULL; } } return ret;}void ide_btochs(uint32 block, ata_drive_cookie *dev, int *cylinder, int *head, int *sect){ uint32 sav_block = block; *sect = (block % dev->device_info.sectors) + 1; block /= dev->device_info.sectors; *head = (block % dev->device_info.heads) | (dev->position ? DH_DRV1 : 0); block /= dev->device_info.heads; *cylinder = block & 0xFFFF; TRACE(("ide_btochs: block %d -> cyl %d head %d sect %d\n", sav_block, *cylinder, *head, *sect));}void ide_btolba(uint32 block, ata_drive_cookie *dev, int *cylinder,int *head, int *sect){ uint32 sav_block = block; *sect = block & 0xFF; *cylinder = (block >> 8) & 0xFFFF; *head = ((block >> 24) & 0xF) | ( dev->position ? DH_DRV1: 0) | DH_LBA; TRACE(("ide_btolba: block %d -> cyl %d head %d sect %d\n", sav_block, *cylinder, *head, *sect));}static int read_block(void *b_cookie,void *d_cookie,long block,void *buffer,size_t size){ ata_drive_cookie *drive_cookie = d_cookie; ide_bus *bus = drive_cookie->attached_bus; int cyl, head, sect; ata_command command; TRACE(("in read_blocks %x\n",block)); if(drive_cookie->lba_supported==1) ide_btolba(block, drive_cookie, &cyl, &head, §); else ide_btochs(block, drive_cookie, &cyl, &head, §); TRACE(("about to read from %d %d %d\n",cyl,head,sect)); command.fr = 0; command.sc = size; command.cyl = cyl; command.head = head; command.sect = sect; command.output = buffer; command.numSect = size; command.multiCnt = 2; command.read = true; command.useInterrupt = true; if(drive_cookie->attached_bus->support_dma(b_cookie)==true) { TRACE(("Will use DMA to transfer data\n")); command.cmd = CMD_READ_DMA; return execute_command_dma( bus,b_cookie,drive_cookie,&command); } else { TRACE(("Will use PIO to transfer data\n")); command.cmd = CMD_READ_SECTORS; return execute_command( bus,b_cookie,drive_cookie,&command); }}static int write_block(void *b_cookie,void *d_cookie,long block,const void *buffer,size_t size){ ata_drive_cookie *drive_cookie = d_cookie; ide_bus *bus = drive_cookie->attached_bus; int cyl, head, sect; ata_command command; if(drive_cookie->lba_supported==1) ide_btolba(block, drive_cookie, &cyl, &head, §); else ide_btochs(block, drive_cookie, &cyl, &head, §); command.fr = 0; command.sc = size; command.cyl = cyl; command.head = head; command.sect = sect; command.output = buffer; command.numSect = size; command.multiCnt = 2; command.read = false; command.useInterrupt = true; if(drive_cookie->attached_bus->support_dma(b_cookie)==true) { command.cmd = CMD_WRITE_DMA; return execute_command_dma( bus,b_cookie,drive_cookie,&command); } else { command.cmd = CMD_WRITE_SECTORS; return execute_command( bus,b_cookie,drive_cookie,&command); }}static uint16 get_bytes_per_sector(void *d_cookie){ ata_drive_cookie *cookie = d_cookie; return cookie->bytes_per_sector;}static int ioctl(void *b_cookie,void *d_cookie,int command,void *buffer,size_t size){ ata_drive_cookie *cookie = d_cookie; int retCode; switch(command) { case 10000: { /*if(size!=sizeof(device_information)) { retCode = -1; } else { device_information *ret = (device_information*)buffer; ret->bytes_per_sector = cookie->bytes_per_sector; ret->sectors = cookie->sector_count; ret->heads = cookie->device_info.heads; ret->cylinders = cookie->device_info.cyls; retCode = 0; }*/ break; } default: { retCode = -1; } } return retCode;}ide_drive ata_ide_drive ={ "ATA_DRIVE", &init_drive, &read_block, &write_block, &get_bytes_per_sector, &ioctl, &signal_interrupt, NULL};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -