📄 pci_ide_bus.c
字号:
#include "ide_bus.h"#include "pci_ide_bus.h"#include "ide_drive.h"#include <kernel/arch/cpu.h>#include <kernel/debug.h>#include <kernel/heap.h>#include <kernel/vfs.h>#include <kernel/sem.h>#include <kernel/int.h>#include <kernel/vm.h>#include <kernel/bus/bus.h>#include <kernel/bus/pci/pci_bus.h>#include <nulibc/string.h>#include <nulibc/stdarg.h>#define CB_DC_HD15 0x08 // bit should always be set to one#define CB_DC_SRST 0x04 // soft reset#define CB_DC_NIEN 0x02 // disable interrupts#define CB_DH_DEV0 0xa0 // select device 0#define CB_DH_DEV1 0xb0 // select device 1#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 DMA_SEL5 0x01#define DMA_SEL6 0x02#define DMA_SEL7 0x03#define DMA_TC5 0x02#define DMA_TC6 0x04#define DMA_TC7 0x08#define DMA_MODE_DEMAND 0x00 // modeByte bits for various dma modes#define DMA_MODE_BLOCK 0x80#define DMA_MODE_SINGLE 0x40#define DMA_MODE_MEMR 0x08 // modeByte memory read or write#define DMA_MODE_MEMW 0x04#define DMA_MASK_ENABLE 0x00 // bits for enable/disable#define DMA_MASK_DISABLE 0x04#define BM_COMMAND_REG 0 // offset to command reg#define BM_CR_MASK_READ 0x00 // read from memory#define BM_CR_MASK_WRITE 0x08 // write to memory#define BM_CR_MASK_START 0x01 // start transfer#define BM_CR_MASK_STOP 0x00 // stop transfer#define BM_STATUS_REG 2 // offset to status reg#define BM_SR_MASK_SIMPLEX 0x80 // simplex only#define BM_SR_MASK_DRV1 0x40 // drive 1 can do dma#define BM_SR_MASK_DRV0 0x20 // drive 0 can do dma#define BM_SR_MASK_INT 0x04 // INTRQ signal asserted#define BM_SR_MASK_ERR 0x02 // error#define BM_SR_MASK_ACT 0x01 // active#define BM_PRD_ADDR_LOW 4 // offset to prd addr reg low 16 bits#define BM_PRD_ADDR_HIGH 6 // offset to prd addr reg high 16 bitstypedef struct{ uint32 address; uint16 count; uint8 reserved_1; uint8 reserved_2 : 7; uint8 eot : 1;}prd_entry;typedef struct{ int base_reg; int status_reg; ide_drive *drives[2]; void *drive_cookie[2]; unsigned int pio_reg_addrs[10]; region_id prd_region_id; int channel; bool dma_supported; sem_id bus_semaphore; int io_port; int irq; bool busMasterActivated; uint32 *prd_buf_address; addr_t prd_phy_address; uint8 stat_reg; uint8 rw_control; uint8 *raw_buffer; uint8 *mapped_address; uint8 *current_dma; uint32 current_dma_length;}pci_bus_cookie;//#define IDE_TRACE 0uint32 *tmp_buffer = (uint32*)0x80000;#if IDE_TRACE#define TRACE(x) dprintf x#else#define TRACE(x)#endifstatic int ide_interrupt_handler(void* data){ TRACE(("in ide interrupt handler %p\n",data)); pci_bus_cookie *cookie = data; TRACE(("drive = %p drive_cookie=%p\n",cookie->drives[0],cookie->drive_cookie[0])); TRACE(("drive = %p drive_cookie=%p\n",cookie->drives[1],cookie->drive_cookie[1])); if(cookie->drives[0]!=NULL) { if ( ( in8( cookie->io_port + BM_STATUS_REG )& BM_SR_MASK_INT )) // done yet ? cookie->drives[0]->signal_interrupt(cookie,cookie->drive_cookie[0]); } if(cookie->drives[1]!=NULL) { if ( ( in8( cookie->io_port + BM_STATUS_REG )& BM_SR_MASK_INT )) // done yet ? cookie->drives[1]->signal_interrupt(cookie,cookie->drive_cookie[1]); } return INT_RESCHEDULE;}extern void init_ide_struct(int bus,int device,int partition_id);static int ide_raw_init(pci_bus_cookie *cookie){ cookie->pio_reg_addrs[ CB_DATA ] = cookie->base_reg + 0; // 0 cookie->pio_reg_addrs[ CB_FR ] = cookie->base_reg + 1; // 1 cookie->pio_reg_addrs[ CB_SC ] = cookie->base_reg + 2; // 2 cookie->pio_reg_addrs[ CB_SN ] = cookie->base_reg + 3; // 3 cookie->pio_reg_addrs[ CB_CL ] = cookie->base_reg + 4; // 4 cookie->pio_reg_addrs[ CB_CH ] = cookie->base_reg + 5; // 5 cookie->pio_reg_addrs[ CB_DH ] = cookie->base_reg + 6; // 6 cookie->pio_reg_addrs[ CB_CMD ] = cookie->base_reg + 7; // 7 cookie->pio_reg_addrs[ CB_DC ] = cookie->status_reg + 6; // 8 cookie->pio_reg_addrs[ CB_DA ] = cookie->status_reg + 7; // 9 return 0;}#define _INTEL_VENDORID 0x8086#define _82371AB_DEVICE_ID 0x7111static int pci_init(pci_bus_cookie *cookie){ id_list *vendor_ids; id_list *device_ids; int err; device dev; int i,j; int fd; struct pci_cfg cfg; int pp; vendor_ids = kmalloc(sizeof(id_list) + sizeof(uint32)); vendor_ids->num_ids = 1; vendor_ids->id[0] = _INTEL_VENDORID; device_ids = kmalloc(sizeof(id_list) + sizeof(uint32)); device_ids->num_ids = 1; device_ids->id[0] = _82371AB_DEVICE_ID; err = bus_find_device(1, vendor_ids, device_ids, &dev); if(err < 0) { TRACE(("unable to pci find controller\n")); err = -1; goto err; } fd = sys_open(dev.dev_path,STREAM_TYPE_DEVICE,0); sys_ioctl(fd, PCI_DUMP_CFG, NULL, 0); sys_ioctl(fd, PCI_GET_CFG, &cfg, sizeof(struct pci_cfg)); sys_close(fd); cookie->io_port = dev.base[4]; cookie->busMasterActivated = /*(buffer[0x9] & 0x80)!=0*/true; if(cookie->channel==0) { cookie->irq = 0x14; cookie->base_reg = 0x1F0; cookie->status_reg = 0x200 + cookie->base_reg; } else { cookie->irq = 0x15; cookie->base_reg = 0x170; cookie->status_reg = 0x200 + cookie->base_reg; } TRACE(("pci_init:irq=%X\n",cfg.irq)); TRACE(("pci_init:header=%X\n",cfg.header_type)); TRACE(("pci_init: found device at '%s'\n", dev.dev_path)); for(i=0; i<MAX_DEV_IO_RANGES; i++) { TRACE(("pci_init: found device at base '%X'\n", dev.base[i])); } TRACE(("pci_init: found device at irq '%X'\n", dev.irq));err: kfree(vendor_ids); kfree(device_ids); return err;}static uint8 read_register(void *cookie,int reg);static int init_dma(pci_bus_cookie *cookie){ addr_t temp; uint8 val = in8(cookie->io_port + BM_STATUS_REG ); TRACE(("entering init_dma status = %d\n",val)); if (!( val &( BM_SR_MASK_DRV1 | BM_SR_MASK_DRV0 ))) { TRACE(("BM_STATUS is wrong %d\n",val)); return -1; } cookie->prd_region_id = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "ide_prd_buf", (void **)&cookie->prd_buf_address, REGION_ADDR_ANY_ADDRESS, 4096, REGION_WIRING_WIRED_CONTIG, LOCK_KERNEL|LOCK_RW); cookie->stat_reg = in8( cookie->io_port + + BM_STATUS_REG ); cookie->stat_reg = cookie->stat_reg & 0xe0; memset(cookie->prd_buf_address, 0, 4096); vm_get_page_mapping(vm_get_kernel_aspace_id(), (addr_t)cookie->prd_buf_address, &cookie->prd_phy_address); cookie->raw_buffer = (uint8*)0x80000; vm_map_physical_memory(vm_get_kernel_aspace_id(), "test", (void *)&cookie->mapped_address, REGION_ADDR_ANY_ADDRESS,0x10000, LOCK_RW|LOCK_KERNEL, (addr_t)cookie->raw_buffer); TRACE(("mapped address is %X\n",cookie->mapped_address)); return 0;}static int init(int channel){ char temp[64]; pci_bus_cookie *current_cookie = kmalloc(sizeof(pci_bus_cookie)); current_cookie->channel = channel; pci_init(current_cookie); //return -1; bus_cookies[channel] = current_cookie; current_cookie->dma_supported = true; sprintf(temp, "pci_ide_sem%d", channel); current_cookie->bus_semaphore = sem_create(1, temp); if(current_cookie->bus_semaphore < 0) { kfree(current_cookie); return -1; } TRACE(("trying to discover devices on channel %d\n",channel)); if(channel==0) { current_cookie->base_reg = 0x1f0; current_cookie->status_reg = 0x3f0; } else { current_cookie->base_reg = 0x170; current_cookie->status_reg = 0x370; } if(ide_raw_init(current_cookie)==0) { int current_drive; init_dma(current_cookie); for(current_drive=0;current_drive<2;current_drive++) { int i = 0; current_cookie->drives[current_drive] = NULL; TRACE(("trying to discover device %d/%d\n",channel,current_drive)); while(ide_drives[i]!=NULL) { void *drive_cookie = ide_drives[i]->init_drive(&pci_bus,current_cookie,channel,current_drive); if(drive_cookie!=NULL) { TRACE(("trying to discover device %d/%d is a %s\n",channel,current_drive,ide_drives[i]->device_name)); current_cookie->drives[current_drive] = ide_drives[i]; current_cookie->drive_cookie[current_drive] = drive_cookie; init_ide_struct(channel,current_drive,-1); TRACE(("done discovering device\n")); TRACE(("Cookie for interrupt is %p\n",current_cookie));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -