scsi.h 4.7 KB
Newer Older
G
Gerd Hoffmann 已提交
1 2
#ifndef QEMU_HW_SCSI_H
#define QEMU_HW_SCSI_H
G
Gerd Hoffmann 已提交
3 4

#include "qdev.h"
5
#include "block.h"
6
#include "block_int.h"
G
Gerd Hoffmann 已提交
7

8 9
#define MAX_SCSI_DEVS	255

10 11
#define SCSI_CMD_BUF_SIZE     16

G
Gerd Hoffmann 已提交
12 13 14 15 16 17 18
/* scsi-disk.c */
enum scsi_reason {
    SCSI_REASON_DONE, /* Command complete.  */
    SCSI_REASON_DATA  /* Transfer complete, more data required.  */
};

typedef struct SCSIBus SCSIBus;
P
Paolo Bonzini 已提交
19
typedef struct SCSIBusOps SCSIBusOps;
G
Gerd Hoffmann 已提交
20 21
typedef struct SCSIDevice SCSIDevice;
typedef struct SCSIDeviceInfo SCSIDeviceInfo;
22
typedef struct SCSIRequest SCSIRequest;
G
Gerd Hoffmann 已提交
23

G
Gerd Hoffmann 已提交
24 25 26 27 28 29
enum SCSIXferMode {
    SCSI_XFER_NONE,      /*  TEST_UNIT_READY, ...            */
    SCSI_XFER_FROM_DEV,  /*  READ, INQUIRY, MODE_SENSE, ...  */
    SCSI_XFER_TO_DEV,    /*  WRITE, MODE_SELECT, ...         */
};

30 31 32 33 34 35
typedef struct SCSISense {
    uint8_t key;
    uint8_t asc;
    uint8_t ascq;
} SCSISense;

36
struct SCSIRequest {
37 38
    SCSIBus           *bus;
    SCSIDevice        *dev;
P
Paolo Bonzini 已提交
39
    uint32_t          refcount;
40
    uint32_t          tag;
41
    uint32_t          lun;
G
Gerd Hoffmann 已提交
42
    uint32_t          status;
43 44 45
    struct {
        uint8_t buf[SCSI_CMD_BUF_SIZE];
        int len;
46 47
        size_t xfer;
        uint64_t lba;
G
Gerd Hoffmann 已提交
48
        enum SCSIXferMode mode;
49
    } cmd;
50
    BlockDriverAIOCB  *aiocb;
51
    bool enqueued;
52
    QTAILQ_ENTRY(SCSIRequest) next;
53
};
54

G
Gerd Hoffmann 已提交
55 56 57 58
struct SCSIDevice
{
    DeviceState qdev;
    uint32_t id;
59
    BlockConf conf;
G
Gerd Hoffmann 已提交
60
    SCSIDeviceInfo *info;
61
    QTAILQ_HEAD(, SCSIRequest) requests;
62
    int blocksize;
63
    int type;
G
Gerd Hoffmann 已提交
64 65 66 67 68 69 70 71 72 73 74 75
};

/* cdrom.c */
int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);

/* scsi-bus.c */
typedef int (*scsi_qdev_initfn)(SCSIDevice *dev);
struct SCSIDeviceInfo {
    DeviceInfo qdev;
    scsi_qdev_initfn init;
    void (*destroy)(SCSIDevice *s);
76
    SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun);
P
Paolo Bonzini 已提交
77
    void (*free_req)(SCSIRequest *req);
78 79 80 81 82
    int32_t (*send_command)(SCSIRequest *req, uint8_t *buf);
    void (*read_data)(SCSIRequest *req);
    int (*write_data)(SCSIRequest *req);
    void (*cancel_io)(SCSIRequest *req);
    uint8_t *(*get_buf)(SCSIRequest *req);
G
Gerd Hoffmann 已提交
83 84
};

P
Paolo Bonzini 已提交
85
struct SCSIBusOps {
86
    void (*complete)(SCSIRequest *req, int reason, uint32_t arg);
P
Paolo Bonzini 已提交
87
    void (*cancel)(SCSIRequest *req);
P
Paolo Bonzini 已提交
88 89
};

G
Gerd Hoffmann 已提交
90 91 92 93 94
struct SCSIBus {
    BusState qbus;
    int busnr;

    int tcq, ndev;
P
Paolo Bonzini 已提交
95
    const SCSIBusOps *ops;
G
Gerd Hoffmann 已提交
96

97
    SCSIDevice *devs[MAX_SCSI_DEVS];
G
Gerd Hoffmann 已提交
98 99 100
};

void scsi_bus_new(SCSIBus *bus, DeviceState *host, int tcq, int ndev,
P
Paolo Bonzini 已提交
101
                  const SCSIBusOps *ops);
G
Gerd Hoffmann 已提交
102 103 104 105 106 107 108
void scsi_qdev_register(SCSIDeviceInfo *info);

static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
{
    return DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
}

109 110
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
                                      int unit, bool removable);
111
int scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
G
Gerd Hoffmann 已提交
112

113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
/*
 * Predefined sense codes
 */

/* No sense data available */
extern const struct SCSISense sense_code_NO_SENSE;
/* LUN not ready, Manual intervention required */
extern const struct SCSISense sense_code_LUN_NOT_READY;
/* LUN not ready, Medium not present */
extern const struct SCSISense sense_code_NO_MEDIUM;
/* Hardware error, internal target failure */
extern const struct SCSISense sense_code_TARGET_FAILURE;
/* Illegal request, invalid command operation code */
extern const struct SCSISense sense_code_INVALID_OPCODE;
/* Illegal request, LBA out of range */
extern const struct SCSISense sense_code_LBA_OUT_OF_RANGE;
/* Illegal request, Invalid field in CDB */
extern const struct SCSISense sense_code_INVALID_FIELD;
/* Illegal request, LUN not supported */
extern const struct SCSISense sense_code_LUN_NOT_SUPPORTED;
/* Command aborted, I/O process terminated */
extern const struct SCSISense sense_code_IO_ERROR;
/* Command aborted, I_T Nexus loss occurred */
extern const struct SCSISense sense_code_I_T_NEXUS_LOSS;
/* Command aborted, Logical Unit failure */
extern const struct SCSISense sense_code_LUN_FAILURE;

#define SENSE_CODE(x) sense_code_ ## x

int scsi_build_sense(SCSISense sense, uint8_t *buf, int len, int fixed);
int scsi_sense_valid(SCSISense sense);

145
SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun);
P
Paolo Bonzini 已提交
146
SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun);
147
int32_t scsi_req_enqueue(SCSIRequest *req, uint8_t *buf);
148
void scsi_req_free(SCSIRequest *req);
P
Paolo Bonzini 已提交
149 150
SCSIRequest *scsi_req_ref(SCSIRequest *req);
void scsi_req_unref(SCSIRequest *req);
151

152
int scsi_req_parse(SCSIRequest *req, uint8_t *buf);
G
Gerd Hoffmann 已提交
153
void scsi_req_print(SCSIRequest *req);
P
Paolo Bonzini 已提交
154
void scsi_req_data(SCSIRequest *req, int len);
G
Gerd Hoffmann 已提交
155
void scsi_req_complete(SCSIRequest *req);
P
Paolo Bonzini 已提交
156
void scsi_req_abort(SCSIRequest *req, int status);
P
Paolo Bonzini 已提交
157
void scsi_req_cancel(SCSIRequest *req);
P
Paolo Bonzini 已提交
158
void scsi_device_purge_requests(SCSIDevice *sdev);
159

G
Gerd Hoffmann 已提交
160
#endif