📄 main.cc
字号:
//IDE bus master controler & slave device //Note that you should comment endian_fix() in io.h before using it//Rita <RitaShen@cse.unsw.edu.au>#include <stdio.h>#include <string.h>#include <unistd.h>#include <assert.hh>#include <checkpoint.hh>#include <device.hh>#include <inttypes.hh>#include <module.hh>#include <serial.hh>#include <simarg.hh>#include <sulima.hh>#include <sys/stat.h>#include "ide.hh"// Serialization information.//SerialType<IDE> IDE::type( "IDE", "Generic IDE Controller");// Runtime constructor.IDE::IDE(const SimArgs& args) //since I am a device, so do nothing here, wait for driver// : Module(args), PCIDevice(32, PCI_VENDOR_ID_DEC_IDE, PCI_DEVICE_ID_DEC_IDE, PCI_CLASS_IDE), file_name(0), data(0) { /*the 256 16-bit words are stored by 128 32-bit words, RitaShen*/ dev_words[31]=0x00000101; dev_words[41]=0x00004000; dev_words[30]=0x0000400; //64M IDE if (args.length() > 2) throw Error("IDE device: Too many arguments to \"sim::install IDE\"."); define("fileName", conf.file_name); define("size", conf.size); define("readLatency", conf.read_latency, 150); define("writeLatency", conf.write_latency, 150);}// Serialized constructor.IDE::IDE(Checkpoint& cp) : Module(cp), PCIDevice(32, PCI_VENDOR_ID_DEC_IDE, PCI_DEVICE_ID_DEC_IDE, PCI_CLASS_IDE), file_name(0), data(0) { define("fileName", conf.file_name, file_name); cp >> conf.size >> conf.read_latency >> conf.write_latency >> '\n'; define("size", conf.size); define("readLatency", conf.read_latency, conf.read_latency); define("writeLatency", conf.write_latency, conf.write_latency); reset(false);}IDE::~IDE(){ delete file_name; delete data;}// Module interface.voidIDE::reset(bool warm){}// Serialization interface.voidIDE::checkpoint(Checkpoint& cp, bool parent) const{}voidIDE::init(Bus *b, InterruptSink *intc, UInt64 base_address, UInt64 size, int base_irq){ bus = b; intctrl = intc; irq=base_irq; bar[0] = base_address | 1; bar[1] = (base_address+8) | 1; bar[2] = (base_address+10) | 1; bar[3] = (base_address+18) | 1; bar[4] = (base_address+20) | 1; bar[5] = 0;}voidIDE::io_poll(){}ClockValueIDE::read(UInt64 addr, UInt64* buf, int size) //what's size for?? //{ unsigned int reg; reg= addr & 0xff; UInt32 val; switch (reg){ case 0: //for 256 device words dide_data.data=dev_words[words_counter]; words_counter=words_counter+1; if (words_counter<128) dide_devcon.r.nien=1; else {dide_stat.r.drq=0; dide_devcon.r.nien=0; }; val=dide_data.data; break; case 1: /* error Register and feature */ val = dide_err.data; break; case 2: /* Sec_Count */ val =dide_sectorcount.data; break; case 3: /* LBA_Low_Byte */ val = dide_lbal.data; break; case 4: /* LBA_Mid_Byte */ val = dide_lbam.data; break; case 5: /* LBA_High_Byte */ val = dide_lbah.data; break; case 6: /* Device regi */ val = dide_dev.data; break; case 7: val = dide_stat.data; break; case 8: val = dide_astat.data; break; case 20: /*bus master command regi*/ val = bmide_comm.data; break; case 22: /*bus master status regi*/ val = bmide_stat.data; break; case 24: /*bus master PRD regi*/ val = bmide_dtpr.data; break; default: log("IDE device Read unimplemented register %d\n", reg); val = 0; break; } *buf = val; return 0; // ignore latency}ClockValue IDE::write(UInt64 addr, const UInt64* buf, int size){ unsigned int reg = addr & 0xff; UInt32 val; val= *buf; switch (reg) { case 0: /* data regi */ dide_data.data=val; break; case 1: /* error regi & feature Register */ dide_feature.data= val; break; case 2: /*Sec_Count*/ dide_sectorcount.data=val; break; case 4: /* LBA_Mid_Byte Register */ dide_lbam.data = val; break; case 3: /*LBA_Low_Byte*/ dide_lbal.data=val; break; case 5: /* LBA_High_Byte */ dide_lbah.data = val; break; case 6: /* device regi */ dide_dev.data= val; break; case 7: /* command Register & status Regi*/ dide_comm.data= val; do_command(val); break; case 8: /* for alternate status & device control */ dide_devcon.data = val; break; case 20: /*bus master command regi*/ bmide_comm.data = val; break; case 22: /*bus master status, write 1 to clear Interrupr and error */ if (val & 0x04) clear_interrupt(); bmide_stat.data = val & 0xf9; break; case 24: /*bus master PRD regi*/ bmide_dtpr.data =val; break; default: log("IDE device: Write unimplemented register %d %x\n", reg, val); break; } return 0; // ignore latency}void IDE::do_command(UInt16 code){ dide_stat.r.drdy=0; // not ready for a new command, // switch(code) { case 0x90: //EDD dide_stat.r.bsy=1; dide_err.r.icrc=0; dide_dev.r.dev=0; dide_sectorcount.data=0x01; dide_lbam.data=00; dide_lbal.data=00; dide_lbah.data=00; dide_dev.data=00; dide_astat.data|=0x0d; dide_stat.r.bsy=0; break; case 0xec: //Identify Device, not much thing to do here dide_stat.r.bsy=1; words_counter=0; dide_stat.r.drq=1; dide_stat.r.bsy=0; break; case 0xef: //set features dide_stat.r.bsy=1; dide_stat.r.drdy=1; features.com[features.c++]=dide_feature.data; features.subcom[features.c++]=dide_sectorcount.data; dide_stat.r.bsy=0; dide_stat.r.drq=0; break; case 0xc8: //read DMA case 0xca: //write DMA if (dide_err.r.abrt){ if(dide_devcon.r.nien==0 && bmide_stat.r.interrupt==1) dide_stat.r.bsy=dide_stat.r.drq=0; else{ dide_stat.r.bsy=dide_stat.r.drq=0; dide_stat.r.drdy=1; } } else { dide_stat.r.bsy = 1; dide_stat.r.drq = 0; dide_devcon.r.nien=1; dma_transfer(); dide_stat.r.bsy=0; dide_stat.r.drq=1; dide_devcon.r.nien=0; }; break; default: log("IDE device: Write unimplemented command %d", code); break; //DRDY=1, device is ready to receive commands // dide_comm.data=0x40; } set_interrupt(); }void IDE::set_interrupt() { if(dide_devcon.r.nien==0) { dide_devcon.r.nien=1; bmide_stat.r.interrupt=1; intctrl->deliver_interrupt(irq); }}void IDE::clear_interrupt(){ intctrl->clear_interrupt(irq); dide_devcon.r.nien=0;}void IDE::dma_transfer(){ UInt64 temp, taddr, maddr, foffset, dma_data; UInt64 mbytes=0, sbytes, sector_count, i; UInt32 fdata; int eot =0; bmide_stat.r.active=1; bmide_stat.r.interrupt=0; //read the DMA PDR mem adress form the table taddr = bmide_dtpr.data; if (dide_sectorcount.data==0) sector_count = 256; else sector_count = dide_sectorcount.data; sbytes = sector_count * 512; //get sector base address from LBA registers and the offset which sector is mapped to// temp=(dide_lbah.data<<16) | (dide_lbam.data<<8) | (dide_lbal.data); foffset = temp*512; FILE* fp; if ((fp= fopen(conf.file_name, "rb+")) == NULL) { printf("can not open file\n"); exit(0); }; fseek(fp, foffset, 0); while (eot!=1) { bus->read(taddr, &temp, 4); maddr=idedma_descriptor.r.mem_paddr=temp; taddr = taddr + 4; bus->read(taddr, &temp, 4); mbytes = idedma_descriptor.r.mbyte_count= temp & 0x0000ffff; taddr = taddr + 4; eot = idedma_descriptor.r.eot= (temp & 0x80000000) >> 31; if (!bmide_comm.r.read_write) { for (i=0; i< (mbytes/4); i++) { bus->read(maddr, &temp, 4); fdata = temp; fwrite(&fdata, sizeof(fdata), 1, fp); maddr = maddr + 4; }; } else { for (i=0; i<(mbytes/8); i++) { fread(&fdata, sizeof(fdata), 1, fp); dma_data = (UInt64)fdata; fread(&fdata, sizeof(fdata), 1, fp); dma_data = (dma_data << 32) | (UInt64)fdata; bus->write(maddr, &dma_data, 8); maddr = maddr + 8; }; }; }; if (fclose(fp)!=0) printf("errors in closing file!\n" ); if (sbytes | mbytes==0) { bmide_stat.r.active=0; bmide_stat.r.interrupt=1; }; if (sbytes==0 && mbytes!=0) { bmide_stat.r.active=1; bmide_stat.r.interrupt=1; }; if (sbytes!=0 && mbytes==0) { bmide_stat.r.error=1; bmide_stat.r.active=0; bmide_stat.r.interrupt=0; dide_err.r.abrt=1; };}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -