/*
* QEMU IDE disk and CD-ROM Emulator
- *
+ *
* Copyright (c) 2003 Fabrice Bellard
* Copyright (c) 2006 Openedhand Ltd.
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
#define WIN_WRITEDMA_ONCE 0xCB /* 28-Bit - without retries */
#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers */
#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */
-#define WIN_GETMEDIASTATUS 0xDA
+#define WIN_GETMEDIASTATUS 0xDA
#define WIN_ACKMEDIACHANGE 0xDB /* ATA-1, ATA-2 vendor */
#define WIN_POSTBOOT 0xDC
#define WIN_PREBOOT 0xDD
#define GPCMD_VERIFY_10 0x2f
#define GPCMD_WRITE_10 0x2a
#define GPCMD_WRITE_AND_VERIFY_10 0x2e
-/* This is listed as optional in ATAPI 2.6, but is (curiously)
+/* This is listed as optional in ATAPI 2.6, but is (curiously)
* missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji
* Table 377 as an MMC command for SCSi devices though... Most ATAPI
* drives support it. */
#define GPCMD_SET_SPEED 0xbb
-/* This seems to be a SCSI specific CD-ROM opcode
+/* This seems to be a SCSI specific CD-ROM opcode
* to play data at track/index */
#define GPCMD_PLAYAUDIO_TI 0x48
/*
/* set for lba48 access */
uint8_t lba48;
/* depends on bit 4 in select, only meaningful for drive 0 */
- struct IDEState *cur_drive;
+ struct IDEState *cur_drive;
BlockDriverState *bs;
/* ATAPI specific */
uint8_t sense_key;
uint8_t cmd;
uint8_t status;
uint32_t addr;
-
+
struct PCIIDEState *pci_dev;
/* current transfer state */
uint32_t cur_addr;
memset(s->io_buffer, 0, 512);
p = (uint16_t *)s->io_buffer;
put_le16(p + 0, 0x0040);
- put_le16(p + 1, s->cylinders);
+ put_le16(p + 1, s->cylinders);
put_le16(p + 3, s->heads);
put_le16(p + 4, 512 * s->sectors); /* XXX: retired, remove ? */
put_le16(p + 5, 512); /* XXX: retired, remove ? */
- put_le16(p + 6, s->sectors);
+ put_le16(p + 6, s->sectors);
snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);
padstr((uint8_t *)(p + 10), buf, 20); /* serial number */
put_le16(p + 20, 3); /* XXX: retired, remove ? */
put_le16(p + 22, 4); /* ecc bytes */
padstr((uint8_t *)(p + 23), QEMU_VERSION, 8); /* firmware version */
padstr((uint8_t *)(p + 27), "QEMU HARDDISK", 40); /* model */
-#if MAX_MULT_SECTORS > 1
+#if MAX_MULT_SECTORS > 1
put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);
#endif
put_le16(p + 48, 1); /* dword I/O */
}
/* prepare data transfer and tell what to do after */
-static void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
+static void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
EndTransferFunc *end_transfer_func)
{
s->end_transfer_func = end_transfer_func;
for(;;) {
l = s->io_buffer_size - s->io_buffer_index;
- if (l <= 0)
+ if (l <= 0)
break;
if (bm->cur_prd_len == 0) {
/* end of table (with a fail safe of one page) */
l = bm->cur_prd_len;
if (l > 0) {
if (is_write) {
- cpu_physical_memory_write(bm->cur_prd_addr,
+ cpu_physical_memory_write(bm->cur_prd_addr,
s->io_buffer + s->io_buffer_index, l);
} else {
- cpu_physical_memory_read(bm->cur_prd_addr,
+ cpu_physical_memory_read(bm->cur_prd_addr,
s->io_buffer + s->io_buffer_index, l);
}
bm->cur_prd_addr += l;
#ifdef DEBUG_AIO
printf("aio_read: sector_num=%lld n=%d\n", sector_num, n);
#endif
- bm->aiocb = bdrv_aio_read(s->bs, sector_num, s->io_buffer, n,
+ bm->aiocb = bdrv_aio_read(s->bs, sector_num, s->io_buffer, n,
ide_read_dma_cb, bm);
}
ide_transfer_start(s, s->io_buffer, 512 * n1, ide_sector_write);
}
ide_set_sector(s, sector_num + n);
-
+
bm->aiocb = bdrv_aio_write(s->bs, sector_num, s->io_buffer, n,
ide_sector_write_aio_cb, bm);
}
#ifdef DEBUG_AIO
printf("aio_write: sector_num=%lld n=%d\n", sector_num, n);
#endif
- bm->aiocb = bdrv_aio_write(s->bs, sector_num, s->io_buffer, n,
+ bm->aiocb = bdrv_aio_write(s->bs, sector_num, s->io_buffer, n,
ide_write_dma_cb, bm);
}
memset(buf, 0, 288);
}
-static int cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf,
+static int cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf,
int sector_size)
{
int ret;
{
/* XXX: handle more errors */
if (ret == -ENOMEDIUM) {
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
+ ide_atapi_cmd_error(s, SENSE_NOT_READY,
ASC_MEDIUM_NOT_PRESENT);
} else {
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
ASC_LOGICAL_BLOCK_OOR);
}
}
{
int byte_count_limit, size, ret;
#ifdef DEBUG_IDE_ATAPI
- printf("reply: tx_size=%d elem_tx_size=%d index=%d\n",
+ printf("reply: tx_size=%d elem_tx_size=%d index=%d\n",
s->packet_transfer_size,
s->elementary_transfer_size,
s->io_buffer_index);
size = s->cd_sector_size - s->io_buffer_index;
if (size > s->elementary_transfer_size)
size = s->elementary_transfer_size;
- ide_transfer_start(s, s->io_buffer + s->io_buffer_index,
+ ide_transfer_start(s, s->io_buffer + s->io_buffer_index,
size, ide_atapi_cmd_reply_end);
s->packet_transfer_size -= size;
s->elementary_transfer_size -= size;
if (size > (s->cd_sector_size - s->io_buffer_index))
size = (s->cd_sector_size - s->io_buffer_index);
}
- ide_transfer_start(s, s->io_buffer + s->io_buffer_index,
+ ide_transfer_start(s, s->io_buffer + s->io_buffer_index,
size, ide_atapi_cmd_reply_end);
s->packet_transfer_size -= size;
s->elementary_transfer_size -= size;
bm->aiocb = NULL;
return;
}
-
+
s->io_buffer_index = 0;
if (s->cd_sector_size == 2352) {
n = 1;
#ifdef DEBUG_AIO
printf("aio_read_cd: lba=%u n=%d\n", s->lba, n);
#endif
- bm->aiocb = bdrv_aio_read(s->bs, (int64_t)s->lba << 2,
- s->io_buffer + data_offset, n * 4,
+ bm->aiocb = bdrv_aio_read(s->bs, (int64_t)s->lba << 2,
+ s->io_buffer + data_offset, n * 4,
ide_atapi_cmd_read_dma_cb, bm);
if (!bm->aiocb) {
/* Note: media not present is the most likely case */
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
+ ide_atapi_cmd_error(s, SENSE_NOT_READY,
ASC_MEDIUM_NOT_PRESENT);
goto eot;
}
ide_dma_start(s, ide_atapi_cmd_read_dma_cb);
}
-static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors,
+static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors,
int sector_size)
{
#ifdef DEBUG_IDE_ATAPI
if (bdrv_is_inserted(s->bs)) {
ide_atapi_cmd_ok(s);
} else {
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
+ ide_atapi_cmd_error(s, SENSE_NOT_READY,
ASC_MEDIUM_NOT_PRESENT);
}
break;
buf[9] = 0x12;
buf[10] = 0x08;
buf[11] = 0x00;
-
+
buf[12] = 0x70;
buf[13] = 3 << 5;
buf[14] = (1 << 0) | (1 << 3) | (1 << 5);
goto error_cmd;
default:
case 3: /* saved values */
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
break;
}
bdrv_set_locked(s->bs, packet[4] & 1);
ide_atapi_cmd_ok(s);
} else {
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
+ ide_atapi_cmd_error(s, SENSE_NOT_READY,
ASC_MEDIUM_NOT_PRESENT);
}
break;
ide_atapi_cmd_read(s, lba, nb_sectors, 2352);
break;
default:
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
ASC_INV_FIELD_IN_CMD_PACKET);
break;
}
bdrv_get_geometry(s->bs, &total_sectors);
total_sectors >>= 2;
if (total_sectors <= 0) {
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
+ ide_atapi_cmd_error(s, SENSE_NOT_READY,
ASC_MEDIUM_NOT_PRESENT);
break;
}
lba = ube32_to_cpu(packet + 2);
if (lba >= total_sectors) {
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
ASC_LOGICAL_BLOCK_OOR);
break;
}
int start, eject;
start = packet[4] & 1;
eject = (packet[4] >> 1) & 1;
-
+
if (eject && !start) {
/* eject the disk */
bdrv_eject(s->bs, 1);
bdrv_get_geometry(s->bs, &total_sectors);
total_sectors >>= 2;
if (total_sectors <= 0) {
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
+ ide_atapi_cmd_error(s, SENSE_NOT_READY,
ASC_MEDIUM_NOT_PRESENT);
break;
}
break;
default:
error_cmd:
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
ASC_INV_FIELD_IN_CMD_PACKET);
break;
}
bdrv_get_geometry(s->bs, &total_sectors);
total_sectors >>= 2;
if (total_sectors <= 0) {
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
+ ide_atapi_cmd_error(s, SENSE_NOT_READY,
ASC_MEDIUM_NOT_PRESENT);
break;
}
break;
}
default:
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
ASC_ILLEGAL_OPCODE);
break;
}
#endif
s = ide_if->cur_drive;
/* ignore commands to non existant slave */
- if (s != ide_if && !s->bs)
+ if (s != ide_if && !s->bs)
break;
switch(val) {
lba48 = 1;
case WIN_READ:
case WIN_READ_ONCE:
- if (!s->bs)
+ if (!s->bs)
goto abort_cmd;
ide_cmd_lba48_transform(s, lba48);
s->req_nb_sectors = 1;
lba48 = 1;
case WIN_READDMA:
case WIN_READDMA_ONCE:
- if (!s->bs)
+ if (!s->bs)
goto abort_cmd;
ide_cmd_lba48_transform(s, lba48);
ide_sector_read_dma(s);
lba48 = 1;
case WIN_WRITEDMA:
case WIN_WRITEDMA_ONCE:
- if (!s->bs)
+ if (!s->bs)
goto abort_cmd;
ide_cmd_lba48_transform(s, lba48);
ide_sector_write_dma(s);
s->status = READY_STAT;
s->atapi_dma = s->feature & 1;
s->nsector = 1;
- ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE,
+ ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE,
ide_atapi_cmd);
break;
/* CF-ATA commands */
IDEState *s = ((IDEState *)opaque)->cur_drive;
uint8_t *p;
int ret;
-
+
p = s->data_ptr;
ret = cpu_to_le32(*(uint32_t *)p);
p += 4;
} __attribute__((packed));
/* try to guess the disk logical geometry from the MSDOS partition table. Return 0 if OK, -1 if could not guess */
-static int guess_disk_lchs(IDEState *s,
+static int guess_disk_lchs(IDEState *s,
int *pcylinders, int *pheads, int *psectors)
{
uint8_t buf[512];
*psectors = sectors;
*pcylinders = cylinders;
#if 0
- printf("guessed geometry: LCHS=%d %d %d\n",
+ printf("guessed geometry: LCHS=%d %d %d\n",
cylinders, heads, sectors);
#endif
return 0;
}
s->drive_serial = drive_serial++;
s->irq = irq;
- s->sector_write_timer = qemu_new_timer(vm_clock,
+ s->sector_write_timer = qemu_new_timer(vm_clock,
ide_sector_write_timer_cb, s);
ide_reset(s);
}
register_ioport_read(iobase2, 1, 1, ide_status_read, ide_state);
register_ioport_write(iobase2, 1, 1, ide_cmd_write, ide_state);
}
-
+
/* data ports */
register_ioport_write(iobase, 2, 2, ide_data_writew, ide_state);
register_ioport_read(iobase, 2, 2, ide_data_readw, ide_state);
ide_state = qemu_mallocz(sizeof(IDEState) * 2);
if (!ide_state)
return;
-
+
ide_init2(ide_state, hd0, hd1, irq);
ide_init_ioport(ide_state, iobase, iobase2);
}
static void cmd646_update_irq(PCIIDEState *d);
-static void ide_map(PCIDevice *pci_dev, int region_num,
+static void ide_map(PCIDevice *pci_dev, int region_num,
uint32_t addr, uint32_t size, int type)
{
PCIIDEState *d = (PCIIDEState *)pci_dev;
BMDMAState *bm = opaque;
PCIIDEState *pci_dev;
uint32_t val;
-
+
switch(addr & 3) {
- case 0:
+ case 0:
val = bm->cmd;
break;
case 1:
case 1:
pci_dev = bm->pci_dev;
if (pci_dev->type == IDE_TYPE_CMD646) {
- pci_dev->dev.config[MRDMODE] =
+ pci_dev->dev.config[MRDMODE] =
(pci_dev->dev.config[MRDMODE] & ~0x30) | (val & 0x30);
cmd646_update_irq(pci_dev);
}
bm->cur_addr = bm->addr;
}
-static void bmdma_map(PCIDevice *pci_dev, int region_num,
+static void bmdma_map(PCIDevice *pci_dev, int region_num,
uint32_t addr, uint32_t size, int type)
{
PCIIDEState *d = (PCIIDEState *)pci_dev;
int i;
qemu_irq *irq;
- d = (PCIIDEState *)pci_register_device(bus, "CMD646 IDE",
+ d = (PCIIDEState *)pci_register_device(bus, "CMD646 IDE",
sizeof(PCIIDEState),
- -1,
+ -1,
NULL, NULL);
d->type = IDE_TYPE_CMD646;
pci_conf = d->dev.config;
pci_conf[0x03] = 0x06;
pci_conf[0x08] = 0x07; // IDE controller revision
- pci_conf[0x09] = 0x8f;
+ pci_conf[0x09] = 0x8f;
pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
pci_conf[0x0e] = 0x00; // header_type
-
+
if (secondary_ide_enabled) {
/* XXX: if not enabled, really disable the seconday IDE controller */
pci_conf[0x51] = 0x80; /* enable IDE1 */
}
- pci_register_io_region((PCIDevice *)d, 0, 0x8,
+ pci_register_io_region((PCIDevice *)d, 0, 0x8,
PCI_ADDRESS_SPACE_IO, ide_map);
- pci_register_io_region((PCIDevice *)d, 1, 0x4,
+ pci_register_io_region((PCIDevice *)d, 1, 0x4,
PCI_ADDRESS_SPACE_IO, ide_map);
- pci_register_io_region((PCIDevice *)d, 2, 0x8,
+ pci_register_io_region((PCIDevice *)d, 2, 0x8,
PCI_ADDRESS_SPACE_IO, ide_map);
- pci_register_io_region((PCIDevice *)d, 3, 0x4,
+ pci_register_io_region((PCIDevice *)d, 3, 0x4,
PCI_ADDRESS_SPACE_IO, ide_map);
- pci_register_io_region((PCIDevice *)d, 4, 0x10,
+ pci_register_io_region((PCIDevice *)d, 4, 0x10,
PCI_ADDRESS_SPACE_IO, bmdma_map);
pci_conf[0x3d] = 0x01; // interrupt on pin 1
-
+
for(i = 0; i < 4; i++)
d->ide_if[i].pci_dev = (PCIDevice *)d;
{
PCIIDEState *d;
uint8_t *pci_conf;
-
+
/* register a function 1 of PIIX3 */
- d = (PCIIDEState *)pci_register_device(bus, "PIIX3 IDE",
+ d = (PCIIDEState *)pci_register_device(bus, "PIIX3 IDE",
sizeof(PCIIDEState),
devfn,
NULL, NULL);
piix3_reset(d);
- pci_register_io_region((PCIDevice *)d, 4, 0x10,
+ pci_register_io_region((PCIDevice *)d, 4, 0x10,
PCI_ADDRESS_SPACE_IO, bmdma_map);
ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], pic[14]);
static void pmac_ide_writeb (void *opaque,
target_phys_addr_t addr, uint32_t val)
{
- addr = (addr & 0xFFF) >> 4;
+ addr = (addr & 0xFFF) >> 4;
switch (addr) {
case 1 ... 7:
ide_ioport_write(opaque, addr, val);
static void pmac_ide_writew (void *opaque,
target_phys_addr_t addr, uint32_t val)
{
- addr = (addr & 0xFFF) >> 4;
+ addr = (addr & 0xFFF) >> 4;
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap16(val);
#endif
{
uint16_t retval;
- addr = (addr & 0xFFF) >> 4;
+ addr = (addr & 0xFFF) >> 4;
if (addr == 0) {
retval = ide_data_readw(opaque, 0);
} else {
static void pmac_ide_writel (void *opaque,
target_phys_addr_t addr, uint32_t val)
{
- addr = (addr & 0xFFF) >> 4;
+ addr = (addr & 0xFFF) >> 4;
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
{
uint32_t retval;
- addr = (addr & 0xFFF) >> 4;
+ addr = (addr & 0xFFF) >> 4;
if (addr == 0) {
retval = ide_data_readl(opaque, 0);
} else {
ide_if = qemu_mallocz(sizeof(IDEState) * 2);
ide_init2(&ide_if[0], hd_table[0], hd_table[1], irq);
-
+
pmac_ide_memory = cpu_register_io_memory(0, pmac_ide_read,
pmac_ide_write, &ide_if[0]);
return pmac_ide_memory;