Revision 9af99d98 hw/scsi-disk.c
b/hw/scsi-disk.c | ||
---|---|---|
55 | 55 |
uint32_t sector_count; |
56 | 56 |
struct iovec iov; |
57 | 57 |
QEMUIOVector qiov; |
58 |
struct SCSIDiskReq *next; |
|
59 | 58 |
uint32_t status; |
60 | 59 |
} SCSIDiskReq; |
61 | 60 |
|
... | ... | |
63 | 62 |
{ |
64 | 63 |
SCSIDevice qdev; |
65 | 64 |
DriveInfo *dinfo; |
66 |
SCSIDiskReq *requests; |
|
67 | 65 |
/* The qemu block layer uses a fixed 512 byte sector size. |
68 | 66 |
This is the number of 512 byte blocks in a single scsi sector. */ |
69 | 67 |
int cluster_size; |
... | ... | |
73 | 71 |
QEMUBH *bh; |
74 | 72 |
}; |
75 | 73 |
|
76 |
/* Global pool of SCSIRequest structures. */ |
|
77 |
static SCSIDiskReq *free_requests = NULL; |
|
78 |
|
|
79 | 74 |
static SCSIDiskReq *scsi_new_request(SCSIDevice *d, uint32_t tag) |
80 | 75 |
{ |
81 |
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d); |
|
82 | 76 |
SCSIDiskReq *r; |
83 | 77 |
|
84 |
if (free_requests) { |
|
85 |
r = free_requests; |
|
86 |
free_requests = r->next; |
|
87 |
} else { |
|
88 |
r = qemu_malloc(sizeof(SCSIDiskReq)); |
|
89 |
r->iov.iov_base = qemu_memalign(512, SCSI_DMA_BUF_SIZE); |
|
90 |
} |
|
78 |
r = qemu_mallocz(sizeof(SCSIDiskReq)); |
|
79 |
r->iov.iov_base = qemu_memalign(512, SCSI_DMA_BUF_SIZE); |
|
91 | 80 |
r->req.bus = scsi_bus_from_device(d); |
92 | 81 |
r->req.dev = d; |
93 | 82 |
r->req.tag = tag; |
94 |
r->sector_count = 0; |
|
95 |
r->iov.iov_len = 0; |
|
96 |
r->req.aiocb = NULL; |
|
97 |
r->status = 0; |
|
98 | 83 |
|
99 |
r->next = s->requests; |
|
100 |
s->requests = r; |
|
84 |
QTAILQ_INSERT_TAIL(&d->requests, &r->req, next); |
|
101 | 85 |
return r; |
102 | 86 |
} |
103 | 87 |
|
104 | 88 |
static void scsi_remove_request(SCSIDiskReq *r) |
105 | 89 |
{ |
106 |
SCSIDiskReq *last; |
|
107 |
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); |
|
108 |
|
|
109 |
if (s->requests == r) { |
|
110 |
s->requests = r->next; |
|
111 |
} else { |
|
112 |
last = s->requests; |
|
113 |
while (last && last->next != r) |
|
114 |
last = last->next; |
|
115 |
if (last) { |
|
116 |
last->next = r->next; |
|
117 |
} else { |
|
118 |
BADF("Orphaned request\n"); |
|
119 |
} |
|
120 |
} |
|
121 |
r->next = free_requests; |
|
122 |
free_requests = r; |
|
90 |
qemu_free(r->iov.iov_base); |
|
91 |
QTAILQ_REMOVE(&r->req.dev->requests, &r->req, next); |
|
92 |
qemu_free(r); |
|
123 | 93 |
} |
124 | 94 |
|
125 | 95 |
static SCSIDiskReq *scsi_find_request(SCSIDiskState *s, uint32_t tag) |
126 | 96 |
{ |
127 |
SCSIDiskReq *r; |
|
128 |
|
|
129 |
r = s->requests; |
|
130 |
while (r && r->req.tag != tag) |
|
131 |
r = r->next; |
|
97 |
SCSIRequest *req; |
|
132 | 98 |
|
133 |
return r; |
|
99 |
QTAILQ_FOREACH(req, &s->qdev.requests, next) { |
|
100 |
if (req->tag == tag) { |
|
101 |
return DO_UPCAST(SCSIDiskReq, req, req); |
|
102 |
} |
|
103 |
} |
|
104 |
return NULL; |
|
134 | 105 |
} |
135 | 106 |
|
136 | 107 |
/* Helper function for command completion. */ |
... | ... | |
310 | 281 |
static void scsi_dma_restart_bh(void *opaque) |
311 | 282 |
{ |
312 | 283 |
SCSIDiskState *s = opaque; |
313 |
SCSIDiskReq *r = s->requests; |
|
284 |
SCSIRequest *req; |
|
285 |
SCSIDiskReq *r; |
|
314 | 286 |
|
315 | 287 |
qemu_bh_delete(s->bh); |
316 | 288 |
s->bh = NULL; |
317 | 289 |
|
318 |
while (r) { |
|
290 |
QTAILQ_FOREACH(req, &s->qdev.requests, next) { |
|
291 |
r = DO_UPCAST(SCSIDiskReq, req, req); |
|
319 | 292 |
if (r->status & SCSI_REQ_STATUS_RETRY) { |
320 | 293 |
r->status &= ~SCSI_REQ_STATUS_RETRY; |
321 | 294 |
scsi_write_request(r); |
322 | 295 |
} |
323 |
r = r->next; |
|
324 | 296 |
} |
325 | 297 |
} |
326 | 298 |
|
... | ... | |
959 | 931 |
static void scsi_destroy(SCSIDevice *dev) |
960 | 932 |
{ |
961 | 933 |
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); |
934 |
SCSIDiskReq *r; |
|
962 | 935 |
|
936 |
while (!QTAILQ_EMPTY(&s->qdev.requests)) { |
|
937 |
r = DO_UPCAST(SCSIDiskReq, req, QTAILQ_FIRST(&s->qdev.requests)); |
|
938 |
scsi_remove_request(r); |
|
939 |
} |
|
963 | 940 |
drive_uninit(s->dinfo); |
964 | 941 |
} |
965 | 942 |
|
Also available in: Unified diff