--- qemu/hw/ide/internal.h 2018/04/24 18:30:52 1.1.1.4 +++ qemu/hw/ide/internal.h 2018/04/24 19:02:18 1.1.1.6 @@ -8,6 +8,8 @@ */ #include #include "block_int.h" +#include "iorange.h" +#include "dma.h" /* debug IDE devices */ //#define DEBUG_IDE @@ -19,7 +21,8 @@ typedef struct IDEBus IDEBus; 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 @@ -59,7 +62,11 @@ typedef struct BMDMAState BMDMAState; */ #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 @@ -187,6 +194,9 @@ typedef struct BMDMAState BMDMAState; #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 @@ -366,6 +376,25 @@ typedef enum { IDE_HD, IDE_CD, IDE_CFATA 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; @@ -401,6 +430,7 @@ struct IDEState { BlockDriverState *bs; char version[9]; /* ATAPI specific */ + struct unreported_events events; uint8_t sense_key; uint8_t asc; uint8_t cdrom_changed; @@ -432,25 +462,48 @@ struct IDEState { 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 { @@ -470,52 +523,29 @@ struct IDEDeviceInfo { #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; - - 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); } } @@ -538,10 +568,7 @@ void ide_bus_reset(IDEBus *bus); 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); @@ -556,15 +583,33 @@ uint32_t ide_data_readw(void *opaque, ui void ide_data_writel(void *opaque, uint32_t addr, uint32_t val); uint32_t ide_data_readl(void *opaque, uint32_t addr); -int ide_init_drive(IDEState *s, BlockDriverState *bs, +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 */