提交 42550fde 编写于 作者: T ths

SCSI emulation improvements, by Chuck Brazie.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2265 c046a42c-6fe2-441c-8c8c-71466251a162
上级 62ee0211
...@@ -688,23 +688,21 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device, ...@@ -688,23 +688,21 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
if (i440fx_state) { if (i440fx_state) {
i440fx_init_memory_mappings(i440fx_state); i440fx_init_memory_mappings(i440fx_state);
} }
#if 0
/* ??? Need to figure out some way for the user to
specify SCSI devices. */
if (pci_enabled) { if (pci_enabled) {
void *scsi; void *scsi;
BlockDriverState *bdrv;
if (scsi_hba_lsi > 0) {
scsi = lsi_scsi_init(pci_bus, -1); if (!(scsi = lsi_scsi_init(pci_bus, -1))) {
bdrv = bdrv_new("scsidisk"); exit(1);
bdrv_open(bdrv, "scsi_disk.img", 0); }
lsi_scsi_attach(scsi, bdrv, -1); for(i = 0; i < MAX_SCSI_DISKS; i++) {
bdrv = bdrv_new("scsicd"); if (scsi_disks_info[i].adapter == SCSI_LSI_53C895A &&
bdrv_open(bdrv, "scsi_cd.iso", 0); scsi_disks_info[i].device_type != SCSI_NONE) {
bdrv_set_type_hint(bdrv, BDRV_TYPE_CDROM); lsi_scsi_attach(scsi, bs_scsi_table[i], scsi_disks_info[i].id);
lsi_scsi_attach(scsi, bdrv, -1); }
}
}
} }
#endif
} }
static void pc_init_pci(int ram_size, int vga_ram_size, int boot_device, static void pc_init_pci(int ram_size, int vga_ram_size, int boot_device,
......
...@@ -223,10 +223,16 @@ using @file{/dev/cdrom} as filename (@pxref{host_drives}). ...@@ -223,10 +223,16 @@ using @file{/dev/cdrom} as filename (@pxref{host_drives}).
Boot on floppy (a), hard disk (c) or CD-ROM (d). Hard disk boot is Boot on floppy (a), hard disk (c) or CD-ROM (d). Hard disk boot is
the default. the default.
@item -disk ide,img=file[,hdx=a..dd][,type=disk|cdrom]
Use @var{file} as the IDE disk/CD-ROM image. The defaults are: hdx=a,type=disk
@item -disk scsi,img=file[,sdx=a..g][,type=disk|cdrom][,id=n]
Use @var{file} as the SCSI disk/CD-ROM image. The defaults are: sdx=a,type=disk,id='auto assign'
@item -snapshot @item -snapshot
Write to temporary files instead of disk image files. In this case, Write to temporary files instead of disk image files. In this case,
the raw disk image you use is not written back. You can however force the raw disk image you use is not written back. You can however force
the write back by pressing @key{C-a s} (@pxref{disk_images}). the write back by pressing @key{C-a s} (@pxref{disk_images}).
@item -no-fd-bootchk @item -no-fd-bootchk
Disable boot signature checking for floppy disks in Bochs BIOS. It may Disable boot signature checking for floppy disks in Bochs BIOS. It may
......
...@@ -109,6 +109,8 @@ ...@@ -109,6 +109,8 @@
/* XXX: use a two level table to limit memory usage */ /* XXX: use a two level table to limit memory usage */
#define MAX_IOPORTS 65536 #define MAX_IOPORTS 65536
#define DISK_OPTIONS_SIZE 256
const char *bios_dir = CONFIG_QEMU_SHAREDIR; const char *bios_dir = CONFIG_QEMU_SHAREDIR;
char phys_ram_file[1024]; char phys_ram_file[1024];
void *ioport_opaque[MAX_IOPORTS]; void *ioport_opaque[MAX_IOPORTS];
...@@ -119,6 +121,9 @@ IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; ...@@ -119,6 +121,9 @@ IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
BlockDriverState *bs_table[MAX_DISKS + 1], *fd_table[MAX_FD]; BlockDriverState *bs_table[MAX_DISKS + 1], *fd_table[MAX_FD];
/* point to the block driver where the snapshots are managed */ /* point to the block driver where the snapshots are managed */
BlockDriverState *bs_snapshots; BlockDriverState *bs_snapshots;
BlockDriverState *bs_scsi_table[MAX_SCSI_DISKS];
SCSIDiskInfo scsi_disks_info[MAX_SCSI_DISKS];
int scsi_hba_lsi; /* Count of scsi disks/cdrom using this lsi adapter */
int vga_ram_size; int vga_ram_size;
int bios_size; int bios_size;
static DisplayState display_state; static DisplayState display_state;
...@@ -3814,7 +3819,172 @@ void do_info_network(void) ...@@ -3814,7 +3819,172 @@ void do_info_network(void)
term_printf(" %s\n", vc->info_str); term_printf(" %s\n", vc->info_str);
} }
} }
/* Parse IDE and SCSI disk options */
static int disk_options_init(int num_ide_disks,
char ide_disk_options[][DISK_OPTIONS_SIZE],
int snapshot,
int num_scsi_disks,
char scsi_disk_options[][DISK_OPTIONS_SIZE],
int cdrom_index,
int cyls,
int heads,
int secs,
int translation)
{
char buf[256];
char dev_name[64];
int id, i, j;
int cdrom_device;
int ide_cdrom_created = 0;
int scsi_index;
scsi_host_adapters temp_adapter;
/* Process any IDE disks/cdroms */
for (i=0; i< num_ide_disks; i++) {
for (j=0; j<MAX_DISKS; j++) {
if (ide_disk_options[j][0] == '\0')
continue;
if (get_param_value(buf, sizeof(buf),"type",ide_disk_options[j])) {
if (!strcmp(buf, "disk")) {
cdrom_device = 0;
} else if (!strcmp(buf, "cdrom")) {
cdrom_device = 1;
ide_cdrom_created = 1;
} else {
fprintf(stderr, "qemu: invalid IDE disk type= value: %s\n", buf);
return -1;
}
} else {
cdrom_device = 0;
}
if (cdrom_device) {
snprintf(dev_name, sizeof(dev_name), "cdrom%c", i);
} else {
snprintf(dev_name, sizeof(dev_name), "hd%c", i + 'a');
}
if (!(get_param_value(buf, sizeof(buf),"img",ide_disk_options[j]))) {
fprintf(stderr, "qemu: missing IDE disk img= value.\n");
return -1;
}
if (!(bs_table[i] = bdrv_new(dev_name))) {
fprintf(stderr, "qemu: unable to create new block device for:%s\n",dev_name);
return -1;
}
if (cdrom_device) {
bdrv_set_type_hint(bs_table[i], BDRV_TYPE_CDROM);
}
if (bdrv_open(bs_table[i], buf, snapshot ? BDRV_O_SNAPSHOT : 0) < 0) {
fprintf(stderr, "qemu: could not open hard disk image: '%s'\n",
buf);
return -1;
}
if (i == 0 && cyls != 0) {
bdrv_set_geometry_hint(bs_table[i], cyls, heads, secs);
bdrv_set_translation_hint(bs_table[i], translation);
}
ide_disk_options[j][0] = '\0';
if (i == cdrom_index) {
cdrom_index = -1;
}
break; /* finished with this IDE device*/
}
}
if (cdrom_index >= 0 && (!ide_cdrom_created)) {
bs_table[cdrom_index] = bdrv_new("cdrom");
bdrv_set_type_hint(bs_table[cdrom_index], BDRV_TYPE_CDROM);
}
for(i = 0; i < num_scsi_disks; i++) {
temp_adapter = SCSI_LSI_53C895A;
scsi_hba_lsi++;
/*Check for sdx= parameter */
if (get_param_value(buf, sizeof(buf), "sdx", scsi_disk_options[i])) {
if (buf[0] >= 'a' && buf[0] <= 'g') {
scsi_index = buf[0] - 'a';
} else{
fprintf(stderr, "qemu: sdx= option for SCSI must be one letter from a-g. %s \n",buf);
exit(1);
}
} else {
scsi_index = 0;
}
/* Check for SCSI id specified. */
if (get_param_value(buf, sizeof(buf),"id",scsi_disk_options[i])) {
id = strtol(buf, NULL, 0);
if (id < 0 || id > 6) {
fprintf(stderr, "qemu: SCSI id must be from 0-6: %d\n", id);
return -1;
}
/* Check if id already used */
for(j = 0; j < MAX_SCSI_DISKS; j++) {
if (scsi_disks_info[j].device_type != SCSI_NONE &&
j != i &&
scsi_disks_info[j].adapter == temp_adapter &&
scsi_disks_info[j].id == id ) {
fprintf(stderr, "qemu: SCSI id already used: %u\n", id);
return -1;
}
}
} else {
id = -1;
}
scsi_disks_info[i].adapter = temp_adapter;
scsi_disks_info[i].id = id;
if (get_param_value(buf, sizeof(buf),"type",scsi_disk_options[i])) {
if (!strcmp(buf, "disk")) {
cdrom_device = 0;
} else if (!strcmp(buf, "cdrom")) {
cdrom_device = 1;
} else {
fprintf(stderr, "qemu: invalid SCSI disk type= value: %s\n", buf);
return -1;
}
} else {
cdrom_device = 0;
}
if (cdrom_device) {
snprintf(dev_name, sizeof(buf), "cdrom%c", scsi_index);
scsi_disks_info[scsi_index].device_type = SCSI_CDROM;
} else {
snprintf(dev_name, sizeof(buf), "sd%c", scsi_index + 'a');
scsi_disks_info[scsi_index].device_type = SCSI_DISK;
}
if (!(bs_scsi_table[scsi_index] = bdrv_new(dev_name))) {
fprintf(stderr, "qemu: unable to create new block device for:%s\n",dev_name);
return -1;
}
/* Get image filename from options and then try to open it */
if (get_param_value(buf, sizeof(buf),"img",scsi_disk_options[i])) {
if (bdrv_open(bs_scsi_table[scsi_index], buf, 0) < 0) {
fprintf(stderr, "qemu: could not open SCSI disk image img='%s'\n",buf);
return -1;
}
} else {
fprintf(stderr, "qemu: SCSI disk image not specified for sd%c \n", i + 'a');
return -1;
}
}
return 0;
}
/***********************************************************/ /***********************************************************/
/* USB devices */ /* USB devices */
...@@ -5923,6 +6093,10 @@ void help(void) ...@@ -5923,6 +6093,10 @@ void help(void)
"-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n" "-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n"
"-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)\n" "-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
"-boot [a|c|d] boot on floppy (a), hard disk (c) or CD-ROM (d)\n" "-boot [a|c|d] boot on floppy (a), hard disk (c) or CD-ROM (d)\n"
"-disk ide,img=file[,hdx=a..dd][,type=disk|cdrom] \n"
" defaults are: hdx=a,type=disk \n"
"-disk scsi,img=file[,sdx=a..g][,type=disk|cdrom][,id=n] \n"
" defaults are: sdx=a,type=disk,id='auto assign' \n"
"-snapshot write to temporary files instead of disk image files\n" "-snapshot write to temporary files instead of disk image files\n"
#ifdef CONFIG_SDL #ifdef CONFIG_SDL
"-no-quit disable SDL window close capability\n" "-no-quit disable SDL window close capability\n"
...@@ -6103,6 +6277,7 @@ enum { ...@@ -6103,6 +6277,7 @@ enum {
QEMU_OPTION_no_acpi, QEMU_OPTION_no_acpi,
QEMU_OPTION_no_reboot, QEMU_OPTION_no_reboot,
QEMU_OPTION_daemonize, QEMU_OPTION_daemonize,
QEMU_OPTION_disk,
}; };
typedef struct QEMUOption { typedef struct QEMUOption {
...@@ -6177,6 +6352,7 @@ const QEMUOption qemu_options[] = { ...@@ -6177,6 +6352,7 @@ const QEMUOption qemu_options[] = {
{ "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice }, { "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
{ "smp", HAS_ARG, QEMU_OPTION_smp }, { "smp", HAS_ARG, QEMU_OPTION_smp },
{ "vnc", HAS_ARG, QEMU_OPTION_vnc }, { "vnc", HAS_ARG, QEMU_OPTION_vnc },
{ "disk", HAS_ARG, QEMU_OPTION_disk },
/* temporary options */ /* temporary options */
{ "usb", 0, QEMU_OPTION_usb }, { "usb", 0, QEMU_OPTION_usb },
...@@ -6395,7 +6571,11 @@ int main(int argc, char **argv) ...@@ -6395,7 +6571,11 @@ int main(int argc, char **argv)
int i, cdrom_index; int i, cdrom_index;
int snapshot, linux_boot; int snapshot, linux_boot;
const char *initrd_filename; const char *initrd_filename;
const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD]; const char *fd_filename[MAX_FD];
char scsi_options[MAX_SCSI_DISKS] [DISK_OPTIONS_SIZE];
char ide_options[MAX_DISKS] [DISK_OPTIONS_SIZE];
int num_ide_disks;
int num_scsi_disks;
const char *kernel_filename, *kernel_cmdline; const char *kernel_filename, *kernel_cmdline;
DisplayState *ds = &display_state; DisplayState *ds = &display_state;
int cyls, heads, secs, translation; int cyls, heads, secs, translation;
...@@ -6450,10 +6630,19 @@ int main(int argc, char **argv) ...@@ -6450,10 +6630,19 @@ int main(int argc, char **argv)
register_machines(); register_machines();
machine = first_machine; machine = first_machine;
initrd_filename = NULL; initrd_filename = NULL;
for(i = 0; i < MAX_SCSI_DISKS; i++) {
scsi_disks_info[i].device_type = SCSI_NONE;
bs_scsi_table[i] = NULL;
}
num_ide_disks = 0;
num_scsi_disks = 0;
for(i = 0; i < MAX_FD; i++) for(i = 0; i < MAX_FD; i++)
fd_filename[i] = NULL; fd_filename[i] = NULL;
for(i = 0; i < MAX_DISKS; i++) for(i = 0; i < MAX_DISKS; i++) {
hd_filename[i] = NULL; ide_options[i][0] = '\0';
}
ram_size = DEFAULT_RAM_SIZE * 1024 * 1024; ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
vga_ram_size = VGA_RAM_SIZE; vga_ram_size = VGA_RAM_SIZE;
bios_size = BIOS_SIZE; bios_size = BIOS_SIZE;
...@@ -6497,7 +6686,16 @@ int main(int argc, char **argv) ...@@ -6497,7 +6686,16 @@ int main(int argc, char **argv)
break; break;
r = argv[optind]; r = argv[optind];
if (r[0] != '-') { if (r[0] != '-') {
hd_filename[0] = argv[optind++];
/* Build new disk IDE syntax string */
pstrcpy(ide_options[0],
14,
"hdx=a,img=");
/*Add on image filename */
pstrcpy(&(ide_options[0][13]),
sizeof(ide_options[0])-13,
argv[optind++]);
num_ide_disks++;
} else { } else {
const QEMUOption *popt; const QEMUOption *popt;
...@@ -6547,10 +6745,75 @@ int main(int argc, char **argv) ...@@ -6547,10 +6745,75 @@ int main(int argc, char **argv)
case QEMU_OPTION_hdd: case QEMU_OPTION_hdd:
{ {
int hd_index; int hd_index;
const char newIDE_DiskSyntax [][10] = {
"hdx=a,img=", "hdx=b,img=", "hdx=c,img=", "hdx=d,img=" };
hd_index = popt->index - QEMU_OPTION_hda; hd_index = popt->index - QEMU_OPTION_hda;
hd_filename[hd_index] = optarg; if (num_ide_disks >= MAX_DISKS){
if (hd_index == cdrom_index) fprintf(stderr, "qemu: too many IDE disks defined.\n");
cdrom_index = -1; exit(1);
}
/* Build new disk IDE syntax string */
pstrcpy(ide_options[hd_index],
11,
newIDE_DiskSyntax[hd_index]);
/* Add on image filename */
pstrcpy(&(ide_options[hd_index][10]),
sizeof(ide_options[0])-10,
optarg);
num_ide_disks++;
}
break;
case QEMU_OPTION_disk: /*Combined IDE and SCSI, for disk and CDROM */
{
const char *p_input_char;
char *p_output_string;
char device[64];
int disk_index;
p_input_char = optarg;
p_output_string = device;
while (*p_input_char != '\0' && *p_input_char != ',') {
if ((p_output_string - device) < sizeof(device) - 1)
*p_output_string++ = *p_input_char;
p_input_char++;
}
*p_output_string = '\0';
if (*p_input_char == ',')
p_input_char++;
if (!strcmp(device, "scsi")) {
if (num_scsi_disks >= MAX_SCSI_DISKS) {
fprintf(stderr, "qemu: too many SCSI disks defined.\n");
exit(1);
}
pstrcpy(scsi_options[num_scsi_disks],
sizeof(scsi_options[0]),
p_input_char);
num_scsi_disks++;
} else if (!strcmp(device,"ide")) {
if (num_ide_disks >= MAX_DISKS) {
fprintf(stderr, "qemu: too many IDE disks/cdroms defined.\n");
exit(1);
}
disk_index = 0; /* default is hda */
if (get_param_value(device, sizeof(device),"hdx",p_input_char)) {
if (device[0] >= 'a' && device[0] <= 'd') {
disk_index = device[0] - 'a';
} else {
fprintf(stderr, "qemu: invalid IDE disk hdx= value: %s\n", device);
return -1;
}
}
else disk_index=0;
pstrcpy(ide_options[disk_index],
sizeof(ide_options[0]),
p_input_char);
num_ide_disks++;
} else {
fprintf(stderr, "qemu: -disk option must specify IDE or SCSI: %s \n",device);
exit(1);
}
} }
break; break;
case QEMU_OPTION_snapshot: case QEMU_OPTION_snapshot:
...@@ -6604,8 +6867,22 @@ int main(int argc, char **argv) ...@@ -6604,8 +6867,22 @@ int main(int argc, char **argv)
kernel_cmdline = optarg; kernel_cmdline = optarg;
break; break;
case QEMU_OPTION_cdrom: case QEMU_OPTION_cdrom:
if (cdrom_index >= 0) { {
hd_filename[cdrom_index] = optarg; char buf[24];
if (num_ide_disks >= MAX_DISKS) {
fprintf(stderr, "qemu: too many IDE disks/cdroms defined.\n");
exit(1);
}
snprintf(buf, sizeof(buf), "type=cdrom,hdx=%c,img=", cdrom_index + 'a');
/* Build new disk IDE syntax string */
pstrcpy(ide_options[cdrom_index],
25,
buf);
/* Add on image filename */
pstrcpy(&(ide_options[cdrom_index][24]),
sizeof(ide_options[0])-24,
optarg);
num_ide_disks++;
} }
break; break;
case QEMU_OPTION_boot: case QEMU_OPTION_boot:
...@@ -6893,20 +7170,11 @@ int main(int argc, char **argv) ...@@ -6893,20 +7170,11 @@ int main(int argc, char **argv)
kqemu_allowed = 0; kqemu_allowed = 0;
#endif #endif
linux_boot = (kernel_filename != NULL); linux_boot = (kernel_filename != NULL);
if (!linux_boot && if (!linux_boot &&
hd_filename[0] == '\0' && num_ide_disks == 0 &&
(cdrom_index >= 0 && hd_filename[cdrom_index] == '\0') &&
fd_filename[0] == '\0') fd_filename[0] == '\0')
help(); help();
/* boot to cd by default if no hard disk */
if (hd_filename[0] == '\0' && boot_device == 'c') {
if (fd_filename[0] != '\0')
boot_device = 'a';
else
boot_device = 'd';
}
setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(stdout, NULL, _IOLBF, 0);
...@@ -6942,31 +7210,22 @@ int main(int argc, char **argv) ...@@ -6942,31 +7210,22 @@ int main(int argc, char **argv)
exit(1); exit(1);
} }
/* we always create the cdrom drive, even if no disk is there */
bdrv_init(); bdrv_init();
if (cdrom_index >= 0) {
bs_table[cdrom_index] = bdrv_new("cdrom"); /* open the virtual block devices, disks or CDRoms */
bdrv_set_type_hint(bs_table[cdrom_index], BDRV_TYPE_CDROM); if (disk_options_init(num_ide_disks,ide_options,snapshot,
num_scsi_disks,scsi_options,
cdrom_index,
cyls, heads, secs, translation)){
exit(1);
} }
/* open the virtual block devices */ /* boot to floppy or default cd if no hard disk */
for(i = 0; i < MAX_DISKS; i++) { if (num_ide_disks == 0 && boot_device == 'c') {
if (hd_filename[i]) { if (fd_filename[0] != '\0')
if (!bs_table[i]) { boot_device = 'a';
char buf[64]; else
snprintf(buf, sizeof(buf), "hd%c", i + 'a'); boot_device = 'd';
bs_table[i] = bdrv_new(buf);
}
if (bdrv_open(bs_table[i], hd_filename[i], snapshot ? BDRV_O_SNAPSHOT : 0) < 0) {
fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
hd_filename[i]);
exit(1);
}
if (i == 0 && cyls != 0) {
bdrv_set_geometry_hint(bs_table[i], cyls, heads, secs);
bdrv_set_translation_hint(bs_table[i], translation);
}
}
} }
/* we always create at least one floppy disk */ /* we always create at least one floppy disk */
......
...@@ -1222,9 +1222,30 @@ int scsi_write_data(SCSIDevice *s, uint32_t tag); ...@@ -1222,9 +1222,30 @@ int scsi_write_data(SCSIDevice *s, uint32_t tag);
void scsi_cancel_io(SCSIDevice *s, uint32_t tag); void scsi_cancel_io(SCSIDevice *s, uint32_t tag);
uint8_t *scsi_get_buf(SCSIDevice *s, uint32_t tag); uint8_t *scsi_get_buf(SCSIDevice *s, uint32_t tag);
enum scsi_host_adapters {
SCSI_LSI_53C895A
};
enum scsi_devices {
SCSI_CDROM,
SCSI_DISK,
SCSI_NONE
};
typedef enum scsi_host_adapters scsi_host_adapters;
typedef enum scsi_devices scsi_devices;
typedef struct SCSIDiskInfo {
scsi_host_adapters adapter;
int id;
scsi_devices device_type;
} SCSIDiskInfo;
#define MAX_SCSI_DISKS 7
extern BlockDriverState *bs_scsi_table[MAX_SCSI_DISKS];
extern SCSIDiskInfo scsi_disks_info[MAX_SCSI_DISKS];
/* lsi53c895a.c */ /* lsi53c895a.c */
void lsi_scsi_attach(void *opaque, BlockDriverState *bd, int id); void lsi_scsi_attach(void *opaque, BlockDriverState *bd, int id);
void *lsi_scsi_init(PCIBus *bus, int devfn); void *lsi_scsi_init(PCIBus *bus, int devfn);
extern int scsi_hba_lsi; // Count of scsi disks/cdrom using this lsi adapter
/* integratorcp.c */ /* integratorcp.c */
extern QEMUMachine integratorcp926_machine; extern QEMUMachine integratorcp926_machine;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册