📄 dev_pcmcia_disk.c
字号:
d->ata_status = ATA_STATUS_RDY|ATA_STATUS_DSC; }}/* Handle an ATA command */static void ata_handle_cmd(struct pcmcia_disk_data *d){#if DEBUG_ATA vm_log(d->vm,d->dev.name,"ATA command 0x%2.2x\n",(u_int)d->ata_cmd);#endif d->data_pos = 0; switch(d->ata_cmd) { case ATA_CMD_IDENT_DEVICE: ata_identify_device(d); d->ata_cmd_callback = ata_cmd_ident_device_callback; d->ata_status = ATA_STATUS_RDY|ATA_STATUS_DSC|ATA_STATUS_DRQ; break; case ATA_CMD_READ_SECTOR: d->sect_remaining = d->sect_count; if (!d->sect_remaining) d->sect_remaining = 256; ata_set_sect_pos(d); disk_read_sector(d,d->sect_pos,d->data_buffer); d->ata_cmd_callback = ata_cmd_read_callback; d->ata_status = ATA_STATUS_RDY|ATA_STATUS_DSC|ATA_STATUS_DRQ; break; case ATA_CMD_WRITE_SECTOR: d->sect_remaining = d->sect_count; if (!d->sect_remaining) d->sect_remaining = 256; ata_set_sect_pos(d); d->ata_cmd_callback = ata_cmd_write_callback; d->ata_status = ATA_STATUS_RDY|ATA_STATUS_DSC|ATA_STATUS_DRQ; break; default: vm_log(d->vm,d->dev.name,"unhandled ATA command 0x%2.2x\n", (u_int)d->ata_cmd); }}/* * dev_pcmcia_disk_access_0() */void *dev_pcmcia_disk_access_0(cpu_mips_t *cpu,struct vdevice *dev, m_uint32_t offset,u_int op_size,u_int op_type, m_uint64_t *data){ struct pcmcia_disk_data *d = dev->priv_data; /* Compute the good internal offset */ offset = (offset >> 1) ^ 1; #if DEBUG_ACCESS if (op_type == MTS_READ) { cpu_log(cpu,d->dev.name, "reading offset 0x%5.5x at pc=0x%llx (size=%u)\n", offset,cpu->pc,op_size); } else { cpu_log(cpu,d->dev.name, "writing offset 0x%5.5x, data=0x%llx at pc=0x%llx (size=%u)\n", offset,*data,cpu->pc,op_size); }#endif /* Card Information Structure */ if (offset < sizeof(cis_table)) { if (op_type == MTS_READ) *data = cis_table[offset]; return NULL; } switch(offset) { case 0x102: /* Pin Replacement Register */ if (op_type == MTS_READ) *data = 0x22; break; case 0x80001: /* Sector Count + Sector no */ if (op_type == MTS_READ) { *data = (d->sect_no << 8) + d->sect_count; } else { d->sect_no = *data >> 8; d->sect_count = *data & 0xFF; } break; case 0x80002: /* Cylinder Low + Cylinder High */ if (op_type == MTS_READ) { *data = (d->cyl_high << 8) + d->cyl_low; } else { d->cyl_high = *data >> 8; d->cyl_low = *data & 0xFF; } break; case 0x80003: /* Select Card/Head + Status/Command register */ if (op_type == MTS_READ) *data = (d->ata_status << 8) + d->head; else { d->ata_cmd = *data >> 8; d->head = *data; ata_handle_cmd(d); } break; default: /* Data buffer access ? */ if ((offset >= d->data_offset) && (offset < d->data_offset + (SECTOR_SIZE/2))) { if (op_type == MTS_READ) { *data = d->data_buffer[(d->data_pos << 1)]; *data += d->data_buffer[(d->data_pos << 1)+1] << 8; } else { d->data_buffer[(d->data_pos << 1)] = *data & 0xFF; d->data_buffer[(d->data_pos << 1)+1] = *data >> 8; } d->data_pos++; /* Buffer complete: call the callback function */ if (d->data_pos == (SECTOR_SIZE/2)) { d->data_pos = 0; if (d->ata_cmd_callback) d->ata_cmd_callback(d); } } } return NULL;}/* * dev_pcmcia_disk_access_1() */void *dev_pcmcia_disk_access_1(cpu_mips_t *cpu,struct vdevice *dev, m_uint32_t offset,u_int op_size,u_int op_type, m_uint64_t *data){ struct pcmcia_disk_data *d = dev->priv_data; /* Compute the good internal offset */ offset = (offset >> 1) ^ 1; #if DEBUG_ACCESS if (op_type == MTS_READ) { cpu_log(cpu,d->dev.name, "reading offset 0x%5.5x at pc=0x%llx (size=%u)\n", offset,cpu->pc,op_size); } else { cpu_log(cpu,d->dev.name, "writing offset 0x%5.5x, data=0x%llx at pc=0x%llx (size=%u)\n", offset,*data,cpu->pc,op_size); }#endif switch(offset) { case 0x02: /* Sector Count + Sector no */ if (op_type == MTS_READ) { *data = (d->sect_no << 8) + d->sect_count; } else { d->sect_no = *data >> 8; d->sect_count = *data & 0xFF; } break; case 0x04: /* Cylinder Low + Cylinder High */ if (op_type == MTS_READ) { *data = (d->cyl_high << 8) + d->cyl_low; } else { d->cyl_high = *data >> 8; d->cyl_low = *data & 0xFF; } break; case 0x06: /* Select Card/Head + Status/Command register */ if (op_type == MTS_READ) *data = (d->ata_status << 8) + d->head; else { d->ata_cmd = *data >> 8; d->head = *data & 0xFF; ata_handle_cmd(d); } break; case 0x08: if (op_type == MTS_READ) { *data = d->data_buffer[(d->data_pos << 1)]; *data += d->data_buffer[(d->data_pos << 1)+1] << 8; } else { d->data_buffer[(d->data_pos << 1)] = *data & 0xFF; d->data_buffer[(d->data_pos << 1)+1] = *data >> 8; } d->data_pos++; /* Buffer complete: call the callback function */ if (d->data_pos == (SECTOR_SIZE/2)) { d->data_pos = 0; if (d->ata_cmd_callback) d->ata_cmd_callback(d); } break; case 0x0E: break; } return NULL;}/* Shutdown a PCMCIA disk device */void dev_pcmcia_disk_shutdown(vm_instance_t *vm,struct pcmcia_disk_data *d){ if (d != NULL) { /* Remove the device */ dev_remove(vm,&d->dev); /* Close disk file */ if (d->fd != -1) close(d->fd); /* Free filename */ free(d->filename); /* Free the structure itself */ free(d); }}/* Initialize a PCMCIA disk */vm_obj_t *dev_pcmcia_disk_init(vm_instance_t *vm,char *name, m_uint64_t paddr,m_uint32_t len, u_int disk_size,int mode){ struct pcmcia_disk_data *d; m_uint32_t tot_sect; /* allocate the private data structure */ if (!(d = malloc(sizeof(*d)))) { fprintf(stderr,"PCMCIA: unable to create disk device '%s'.\n",name); return NULL; } memset(d,0,sizeof(*d)); vm_object_init(&d->vm_obj); d->vm = vm; d->vm_obj.name = name; d->vm_obj.data = d; d->vm_obj.shutdown = (vm_shutdown_t)dev_pcmcia_disk_shutdown; d->fd = -1; if (!(d->filename = vm_build_filename(vm,name))) { fprintf(stderr,"PCMCIA: unable to create filename.\n"); goto err_filename; } /* Data buffer offset in mapped memory */ d->data_offset = 0x80200; d->ata_status = ATA_STATUS_RDY|ATA_STATUS_DSC; /* Compute the number of cylinders given a disk size in Mb */ tot_sect = ((m_uint64_t)disk_size * 1048576) / SECTOR_SIZE; d->nr_heads = DISK_NR_HEADS; d->sects_per_track = DISK_SECTS_PER_TRACK; d->nr_cylinders = tot_sect / (d->nr_heads * d->sects_per_track); vm_log(vm,name,"C/H/S settings = %u/%u/%u\n", d->nr_cylinders,d->nr_heads,d->sects_per_track); /* Create the disk file */ if (disk_create(d) == -1) goto err_disk_create; dev_init(&d->dev); d->dev.name = name; d->dev.priv_data = d; d->dev.phys_addr = paddr; d->dev.phys_len = len; d->dev.flags = VDEVICE_FLAG_CACHING; if (mode == 0) d->dev.handler = dev_pcmcia_disk_access_0; else d->dev.handler = dev_pcmcia_disk_access_1; /* Map this device to the VM */ vm_bind_device(vm,&d->dev); vm_object_add(vm,&d->vm_obj); return(&d->vm_obj); err_disk_create: free(d->filename); err_filename: free(d); return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -