This patch adds the SCSI support for the target PC. It allows to initalize SCSI interface in the PC init machine.
it adds a new interface type "scsi" to "-disk" interface. "-disk file,if=scsi,bus=0,unit=6" allows to connect the disk image file to the bus 0 with the unit id 6. if there is no SCSI disk, the SCSI interface is not created. It also defines the default interface type to "scsi" for targets "realview", "SS-5", "SS-10", "versatilepb", "versatileab" to keep old behavior, where "-hda" is a SCSI disk. -- hw/esp.c | 4 +- hw/pc.c | 30 ++++++++------- hw/realview.c | 6 +-- hw/sun4m.c | 6 +-- hw/versatilepb.c | 6 +-- monitor.c | 7 +++ vl.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++------ vl.h | 9 ++++ 8 files changed, 139 insertions(+), 37 deletions(-) Index: qemu/hw/pc.c =================================================================== --- qemu.orig/hw/pc.c 2007-10-31 14:13:20.000000000 +0100 +++ qemu/hw/pc.c 2007-10-31 14:23:52.000000000 +0100 @@ -927,23 +927,25 @@ if (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) { - void *scsi; - BlockDriverState *bdrv; + void *scsi[SCSI_MAX_BUS]; + int max_bus = -1; + + for (i = 0; i < MAX_SCSI_DISKS; i++) + if (sd_table[i]) + max_bus = i / SCSI_MAX_DEVS + 1; + + for (i = 0; i < max_bus; i++) + scsi[i] = lsi_scsi_init(pci_bus, -1); - scsi = lsi_scsi_init(pci_bus, -1); - bdrv = bdrv_new("scsidisk"); - bdrv_open(bdrv, "scsi_disk.img", 0); - lsi_scsi_attach(scsi, bdrv, -1); - bdrv = bdrv_new("scsicd"); - bdrv_open(bdrv, "scsi_cd.iso", 0); - bdrv_set_type_hint(bdrv, BDRV_TYPE_CDROM); - lsi_scsi_attach(scsi, bdrv, -1); + for (i = 0; i < MAX_SCSI_DISKS; i++) { + if (sd_table[i]) { + lsi_scsi_attach(scsi[i / SCSI_MAX_DEVS], + sd_table[i], i % SCSI_MAX_DEVS); + } + } } -#endif } static void pc_init_pci(int ram_size, int vga_ram_size, const char *boot_device, Index: qemu/hw/realview.c =================================================================== --- qemu.orig/hw/realview.c 2007-10-31 14:12:40.000000000 +0100 +++ qemu/hw/realview.c 2007-10-31 14:23:52.000000000 +0100 @@ -65,9 +65,9 @@ usb_ohci_init_pci(pci_bus, 3, -1); } scsi_hba = lsi_scsi_init(pci_bus, -1); - for (n = 0; n < MAX_DISKS; n++) { - if (bs_table[n]) { - lsi_scsi_attach(scsi_hba, bs_table[n], n); + for (n = 0; n < SCSI_MAX_DEVS; n++) { + if (sd_table[n]) { + lsi_scsi_attach(scsi_hba, sd_table[n], n); } } for(n = 0; n < nb_nics; n++) { Index: qemu/hw/versatilepb.c =================================================================== --- qemu.orig/hw/versatilepb.c 2007-10-31 14:12:40.000000000 +0100 +++ qemu/hw/versatilepb.c 2007-10-31 14:23:52.000000000 +0100 @@ -199,9 +199,9 @@ usb_ohci_init_pci(pci_bus, 3, -1); } scsi_hba = lsi_scsi_init(pci_bus, -1); - for (n = 0; n < MAX_DISKS; n++) { - if (bs_table[n]) { - lsi_scsi_attach(scsi_hba, bs_table[n], n); + for (n = 0; n < SCSI_MAX_DEVS; n++) { + if (sd_table[n]) { + lsi_scsi_attach(scsi_hba, sd_table[n], n); } } Index: qemu/vl.c =================================================================== --- qemu.orig/vl.c 2007-10-31 14:18:25.000000000 +0100 +++ qemu/vl.c 2007-10-31 14:23:52.000000000 +0100 @@ -152,6 +152,7 @@ /* Note: bs_table[MAX_IDE_DISKS] is a dummy block driver if none available to store the VM snapshots */ BlockDriverState *bs_table[MAX_IDE_DISKS + 1], *fd_table[MAX_FD]; +BlockDriverState *sd_table[MAX_SCSI_DISKS + 1]; BlockDriverState *pflash_table[MAX_PFLASH]; BlockDriverState *sd_bdrv; BlockDriverState *mtd_bdrv; @@ -1752,6 +1753,10 @@ if (bs_table[i]) bdrv_commit(bs_table[i]); } + for (i = 0; i < MAX_SCSI_DISKS; i++) { + if (sd_table[i]) + bdrv_commit(sd_table[i]); + } if (mtd_bdrv) bdrv_commit(mtd_bdrv); } @@ -4714,7 +4719,7 @@ #define CDROM_ALIAS ",index=2,media=cdrom" #endif -static int disk_init(const char *str, int snapshot) +static int disk_init(const char *str, int snapshot, QEMUMachine *machine) { char buf[16]; enum { IF_IDE, IF_SCSI } interface; @@ -4739,7 +4744,16 @@ unit_id = -1; disk_index = -1; translation = BIOS_ATA_TRANSLATION_AUTO; - interface = IF_IDE; + + if (!strcmp(machine->name, "realview") || + !strcmp(machine->name, "SS-5") || + !strcmp(machine->name, "SS-10") || + !strcmp(machine->name, "versatilepb") || + !strcmp(machine->name, "versatileab")) { + interface = IF_SCSI; + } else { + interface = IF_IDE; + } media = MEDIA_DISK; /* extract parameters */ @@ -4899,8 +4913,59 @@ } break; case IF_SCSI: - /* TODO */ - break; + + if (bus_id >= SCSI_MAX_BUS) { + fprintf(stderr, "qemu: bus id too big\n"); + return -1; + } + + if (unit_id >= SCSI_MAX_DEVS) { + fprintf(stderr, "qemu: unit id too big\n"); + return -1; + } + + if (bus_id != -1 && unit_id != -1) + disk_index = bus_id * SCSI_MAX_DEVS + unit_id; + else { + if (bus_id != -1) + disk_index = bus_id * SCSI_MAX_DEVS; + else + disk_index = 0; + while (sd_table[disk_index] && disk_index < SCSI_MAX_DEVS) + disk_index++; + } + if (disk_index >= MAX_SCSI_DISKS) { + fprintf(stderr, "qemu: too many disks\n"); + return -1; + } + + if (!sd_table[disk_index]) { + switch(media) { + case MEDIA_DISK: + snprintf(buf, sizeof(buf), "sd%c", disk_index + 'a'); + sd_table[disk_index] = bdrv_new(buf); + break; + case MEDIA_CDROM: + snprintf(buf, sizeof(buf), "sr%c", disk_index + '0'); + sd_table[disk_index] = bdrv_new(buf); + bdrv_set_type_hint(sd_table[disk_index], BDRV_TYPE_CDROM); + break; + } + + if (file[0] && bdrv_open(sd_table[disk_index], file, + snapshot ? BDRV_O_SNAPSHOT : 0) < 0) { + fprintf(stderr, "qemu: could not open hard disk image '%s'\n", + file); + return -1; + } + + if (cyls != 0) { + bdrv_set_geometry_hint(sd_table[disk_index], + cyls, heads, secs); + bdrv_set_translation_hint(sd_table[disk_index], translation); + } + } + break; } return 0; } @@ -5693,6 +5758,11 @@ if (bdrv_can_snapshot(bs)) goto ok; } + for(i = 0; i <= MAX_SCSI_DISKS; i++) { + bs = sd_table[i]; + if (bdrv_can_snapshot(bs)) + goto ok; + } return NULL; ok: bs_snapshots = bs; @@ -5797,8 +5867,11 @@ /* create the snapshots */ - for(i = 0; i < MAX_IDE_DISKS; i++) { - bs1 = bs_table[i]; + for(i = 0; i < MAX_IDE_DISKS + MAX_SCSI_DISKS; i++) { + if (i < MAX_IDE_DISKS) + bs1 = bs_table[i]; + else + bs1 = sd_table[i - MAX_IDE_DISKS]; if (bdrv_has_snapshot(bs1)) { if (must_delete) { ret = bdrv_snapshot_delete(bs1, old_sn->id_str); @@ -5840,8 +5913,11 @@ saved_vm_running = vm_running; vm_stop(0); - for(i = 0; i <= MAX_IDE_DISKS; i++) { - bs1 = bs_table[i]; + for(i = 0; i <= MAX_IDE_DISKS + MAX_SCSI_DISKS; i++) { + if (i < MAX_IDE_DISKS) + bs1 = bs_table[i]; + else + bs1 = sd_table[i - MAX_IDE_DISKS]; if (bdrv_has_snapshot(bs1)) { ret = bdrv_snapshot_goto(bs1, name); if (ret < 0) { @@ -5901,8 +5977,11 @@ return; } - for(i = 0; i <= MAX_IDE_DISKS; i++) { - bs1 = bs_table[i]; + for(i = 0; i <= MAX_IDE_DISKS + MAX_SCSI_DISKS; i++) { + if (i < MAX_IDE_DISKS) + bs1 = bs_table[i]; + else + bs1 = sd_table[i - MAX_IDE_DISKS]; if (bdrv_has_snapshot(bs1)) { ret = bdrv_snapshot_delete(bs1, name); if (ret < 0) { @@ -5937,6 +6016,13 @@ term_printf(" %s", bdrv_get_device_name(bs1)); } } + for(i = 0; i <= MAX_SCSI_DISKS; i++) { + bs1 = sd_table[i]; + if (bdrv_has_snapshot(bs1)) { + if (bs == bs1) + term_printf(" %s", bdrv_get_device_name(bs1)); + } + } term_printf("\n"); nb_sns = bdrv_snapshot_list(bs, &sn_tab); @@ -8523,7 +8609,7 @@ /* open the virtual block devices */ for(i = 0; i < nb_disks; i++) - if (disk_init(disks[i], snapshot) == -1) + if (disk_init(disks[i], snapshot, machine) == -1) exit(1); /* we always create at least one floppy disk */ Index: qemu/vl.h =================================================================== --- qemu.orig/vl.h 2007-10-31 14:13:20.000000000 +0100 +++ qemu/vl.h 2007-10-31 14:23:52.000000000 +0100 @@ -983,14 +983,21 @@ /* x_keymap.c */ extern uint8_t _translate_keycode(const int key); +/* lsi53c895a.c */ + +#define SCSI_MAX_DEVS 7 +#define SCSI_MAX_BUS 4 +#define MAX_SCSI_DISKS (SCSI_MAX_BUS * SCSI_MAX_DEVS) + /* ide.c */ #define MAX_IDE_BUS 2 #define MAX_IDE_DEVS 2 #define MAX_IDE_DISKS (MAX_IDE_BUS * MAX_IDE_DEVS) -#define MAX_DISKS (MAX_IDE_DISKS) +#define MAX_DISKS (MAX_IDE_DISKS + MAX_SCSI_DISKS) extern BlockDriverState *bs_table[MAX_IDE_DISKS + 1]; +extern BlockDriverState *sd_table[MAX_SCSI_DISKS + 1]; extern BlockDriverState *sd_bdrv; extern BlockDriverState *mtd_bdrv; Index: qemu/hw/sun4m.c =================================================================== --- qemu.orig/hw/sun4m.c 2007-10-31 14:12:40.000000000 +0100 +++ qemu/hw/sun4m.c 2007-10-31 14:23:52.000000000 +0100 @@ -394,9 +394,9 @@ main_esp = esp_init(bs_table, hwdef->esp_base, espdma, *espdma_irq, esp_reset); - for (i = 0; i < MAX_DISKS; i++) { - if (bs_table[i]) { - esp_scsi_attach(main_esp, bs_table[i], i); + for (i = 0; i < MAX_SCSI_DISKS; i++) { + if (sd_table[i]) { + esp_scsi_attach(main_esp, sd_table[i], i); } } Index: qemu/monitor.c =================================================================== --- qemu.orig/monitor.c 2007-10-31 14:13:20.000000000 +0100 +++ qemu/monitor.c 2007-10-31 14:23:52.000000000 +0100 @@ -211,6 +211,13 @@ bdrv_commit(bs_table[i]); } } + for (i = 0; i < MAX_SCSI_DISKS; i++) { + if (sd_table[i]) { + if (all_devices || + !strcmp(bdrv_get_device_name(sd_table[i]), device)) + bdrv_commit(sd_table[i]); + } + } if (mtd_bdrv) if (all_devices || !strcmp(bdrv_get_device_name(mtd_bdrv), device)) bdrv_commit(mtd_bdrv); Index: qemu/hw/esp.c =================================================================== --- qemu.orig/hw/esp.c 2007-10-31 14:12:18.000000000 +0100 +++ qemu/hw/esp.c 2007-10-31 14:23:52.000000000 +0100 @@ -60,7 +60,7 @@ uint8_t ti_buf[TI_BUFSZ]; int sense; int dma; - SCSIDevice *scsi_dev[MAX_DISKS]; + SCSIDevice *scsi_dev[SCSI_MAX_DEVS]; SCSIDevice *current_dev; uint8_t cmdbuf[TI_BUFSZ]; int cmdlen; @@ -122,7 +122,7 @@ s->async_len = 0; } - if (target >= MAX_DISKS || !s->scsi_dev[target]) { + if (target >= SCSI_MAX_DEVS || !s->scsi_dev[target]) { // No such drive s->rregs[4] = STAT_IN; s->rregs[5] = INTR_DC;