* non-internal declarations are in hw/ide.h
*/
#include <hw/ide.h>
+#include "block_int.h"
+#include "iorange.h"
+#include "dma.h"
/* debug IDE devices */
//#define DEBUG_IDE
typedef struct IDEDevice IDEDevice;
typedef struct IDEDeviceInfo IDEDeviceInfo;
typedef struct IDEState IDEState;
-typedef struct BMDMAState BMDMAState;
+typedef struct IDEDMA IDEDMA;
+typedef struct IDEDMAOps IDEDMAOps;
/* Bits of HD_STATUS */
#define ERR_STAT 0x01
*/
#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */
/*
- * 0x04->0x07 Reserved
+ * 0x04->0x05 Reserved
+ */
+#define WIN_DSM 0x06
+/*
+ * 0x07 Reserved
*/
#define WIN_SRST 0x08 /* ATAPI soft reset command */
#define WIN_DEVICE_RESET 0x08
#define IDE_DMA_BUF_SECTORS 256
+/* feature values for Data Set Management */
+#define DSM_TRIM 0x01
+
#if (IDE_DMA_BUF_SECTORS < MAX_MULT_SECTORS)
#error "IDE_DMA_BUF_SECTORS must be bigger or equal to MAX_MULT_SECTORS"
#endif
#define SMART_DISABLE 0xd9
#define SMART_STATUS 0xda
+typedef enum { IDE_HD, IDE_CD, IDE_CFATA } IDEDriveKind;
+
typedef void EndTransferFunc(IDEState *);
+typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockDriverCompletionFunc *);
+typedef int DMAFunc(IDEDMA *);
+typedef int DMAIntFunc(IDEDMA *, int);
+typedef void DMARestartFunc(void *, int, int);
+
+struct unreported_events {
+ bool eject_request;
+ bool new_media;
+};
+
+enum ide_dma_cmd {
+ IDE_DMA_READ,
+ IDE_DMA_WRITE,
+ IDE_DMA_TRIM,
+};
+
+#define ide_cmd_is_read(s) \
+ ((s)->dma_cmd == IDE_DMA_READ)
+
/* NOTE: IDEState represents in fact one drive */
struct IDEState {
IDEBus *bus;
uint8_t unit;
/* ide config */
- int is_cdrom;
- int is_cf;
+ IDEDriveKind drive_kind;
int cylinders, heads, sectors;
int64_t nb_sectors;
int mult_sectors;
/* set for lba48 access */
uint8_t lba48;
BlockDriverState *bs;
+ char version[9];
/* ATAPI specific */
+ struct unreported_events events;
uint8_t sense_key;
uint8_t asc;
uint8_t cdrom_changed;
int lba;
int cd_sector_size;
int atapi_dma; /* true if dma is requested for the packet cmd */
+ BlockAcctCookie acct;
/* ATA DMA state */
int io_buffer_size;
QEMUSGList sg;
uint8_t *data_ptr;
uint8_t *data_end;
uint8_t *io_buffer;
+ /* PIO save/restore */
+ int32_t io_buffer_total_len;
+ int cur_io_buffer_offset;
+ int cur_io_buffer_len;
+ uint8_t end_transfer_fn_idx;
QEMUTimer *sector_write_timer; /* only used for win2k install hack */
uint32_t irq_count; /* counts IRQs when using win2k install hack */
/* CF-ATA extended error */
uint32_t mdata_size;
uint8_t *mdata_storage;
int media_changed;
- /* for pmac */
- int is_read;
+ enum ide_dma_cmd dma_cmd;
/* SMART */
uint8_t smart_enabled;
uint8_t smart_autosave;
int smart_errors;
uint8_t smart_selftest_count;
uint8_t *smart_selftest_data;
+ /* AHCI */
+ int ncq_queues;
+};
+
+struct IDEDMAOps {
+ DMAStartFunc *start_dma;
+ DMAFunc *start_transfer;
+ DMAIntFunc *prepare_buf;
+ DMAIntFunc *rw_buf;
+ DMAIntFunc *set_unit;
+ DMAIntFunc *add_status;
+ DMAFunc *set_inactive;
+ DMARestartFunc *restart_cb;
+ DMAFunc *reset;
+};
+
+struct IDEDMA {
+ const struct IDEDMAOps *ops;
+ struct iovec iov;
+ QEMUIOVector qiov;
+ BlockDriverAIOCB *aiocb;
};
struct IDEBus {
BusState qbus;
IDEDevice *master;
IDEDevice *slave;
- BMDMAState *bmdma;
IDEState ifs[2];
+ int bus_id;
+ IDEDMA *dma;
uint8_t unit;
uint8_t cmd;
qemu_irq irq;
+
+ int error_status;
};
struct IDEDevice {
DeviceState qdev;
uint32_t unit;
- DriveInfo *dinfo;
+ BlockConf conf;
+ char *version;
+ char *serial;
};
typedef int (*ide_qdev_initfn)(IDEDevice *dev);
struct IDEDeviceInfo {
DeviceInfo qdev;
ide_qdev_initfn init;
- uint32_t unit;
- DriveInfo *drive;
};
#define BM_STATUS_DMAING 0x01
#define BM_STATUS_ERROR 0x02
#define BM_STATUS_INT 0x04
+
+/* FIXME These are not status register bits */
#define BM_STATUS_DMA_RETRY 0x08
#define BM_STATUS_PIO_RETRY 0x10
-#define BM_STATUS_RETRY_READ 0x20
+#define BM_STATUS_RETRY_READ 0x20
+#define BM_STATUS_RETRY_FLUSH 0x40
+#define BM_STATUS_RETRY_TRIM 0x80
+
+#define BM_MIGRATION_COMPAT_STATUS_BITS \
+ (BM_STATUS_DMA_RETRY | BM_STATUS_PIO_RETRY | \
+ BM_STATUS_RETRY_READ | BM_STATUS_RETRY_FLUSH)
#define BM_CMD_START 0x01
#define BM_CMD_READ 0x08
-struct BMDMAState {
- uint8_t cmd;
- uint8_t status;
- uint32_t addr;
-
- struct PCIIDEState *pci_dev;
- IDEBus *bus;
- /* current transfer state */
- uint32_t cur_addr;
- uint32_t cur_prd_last;
- uint32_t cur_prd_addr;
- uint32_t cur_prd_len;
- uint8_t unit;
- BlockDriverCompletionFunc *dma_cb;
- BlockDriverAIOCB *aiocb;
- struct iovec iov;
- QEMUIOVector qiov;
- int64_t sector_num;
- uint32_t nsector;
- QEMUBH *bh;
-};
-
static inline IDEState *idebus_active_if(IDEBus *bus)
{
return bus->ifs + bus->unit;
}
-static inline IDEState *bmdma_active_if(BMDMAState *bmdma)
-{
- assert(bmdma->unit != (uint8_t)-1);
- return bmdma->bus->ifs + bmdma->unit;
-}
-
static inline void ide_set_irq(IDEBus *bus)
{
- BMDMAState *bm = bus->bmdma;
if (!(bus->cmd & IDE_CMD_DISABLE_IRQ)) {
- if (bm) {
- bm->status |= BM_STATUS_INT;
- }
qemu_irq_raise(bus->irq);
}
}
int64_t ide_get_sector(IDEState *s);
void ide_set_sector(IDEState *s, int64_t sector_num);
-void ide_dma_cancel(BMDMAState *bm);
-void ide_dma_restart_cb(void *opaque, int running, int reason);
void ide_dma_error(IDEState *s);
-void ide_dma_reset(BMDMAState *bm);
void ide_atapi_cmd_ok(IDEState *s);
void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc);
void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
uint32_t ide_data_readl(void *opaque, uint32_t addr);
-void ide_init_drive(IDEState *s, DriveInfo *dinfo);
-void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
- qemu_irq irq);
+int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
+ const char *version, const char *serial);
+void ide_init2(IDEBus *bus, qemu_irq irq);
+void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
+ DriveInfo *hd1, qemu_irq irq);
void ide_init_ioport(IDEBus *bus, int iobase, int iobase2);
+void ide_exec_cmd(IDEBus *bus, uint32_t val);
+void ide_dma_cb(void *opaque, int ret);
+void ide_sector_write(IDEState *s);
+void ide_sector_read(IDEState *s);
+void ide_flush_cache(IDEState *s);
+
+void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
+ EndTransferFunc *end_transfer_func);
+void ide_transfer_stop(IDEState *s);
+void ide_set_inactive(IDEState *s);
+BlockDriverAIOCB *ide_issue_trim(BlockDriverState *bs,
+ int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+ BlockDriverCompletionFunc *cb, void *opaque);
+
+/* hw/ide/atapi.c */
+void ide_atapi_cmd(IDEState *s);
+void ide_atapi_cmd_reply_end(IDEState *s);
+
/* hw/ide/qdev.c */
-void ide_bus_new(IDEBus *idebus, DeviceState *dev);
+void ide_bus_new(IDEBus *idebus, DeviceState *dev, int bus_id);
IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive);
#endif /* HW_IDE_INTERNAL_H */