2 * Xen SCSI backend driver
4 * Copyright (c) 2008, FUJITSU Limited
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version 2
8 * as published by the Free Software Foundation; or, when distributed
9 * separately from the Linux kernel or incorporated into other
10 * software packages, subject to the following license:
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this source file (the "Software"), to deal in the Software without
14 * restriction, including without limitation the rights to use, copy, modify,
15 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
16 * and to permit persons to whom the Software is furnished to do so, subject to
17 * the following conditions:
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
32 * Patched to support >2TB drives + allow tape & autoloader operations
33 * 2010, Samuel Kvasnica, IMS Nanofabrication AG
36 #include <scsi/scsi.h>
37 #include <scsi/scsi_cmnd.h>
38 #include <scsi/scsi_device.h>
41 /* Following SCSI commands are not defined in scsi/scsi.h */
42 #define EXTENDED_COPY 0x83 /* EXTENDED COPY command */
43 #define REPORT_ALIASES 0xa3 /* REPORT ALIASES command */
44 #define CHANGE_ALIASES 0xa4 /* CHANGE ALIASES command */
45 #define SET_PRIORITY 0xa4 /* SET PRIORITY command */
49 The bitmap in order to control emulation.
50 (Bit 3 to 7 are reserved for future use.)
52 #define VSCSIIF_NEED_CMD_EXEC 0x01 /* If this bit is set, cmd exec */
54 #define VSCSIIF_NEED_EMULATE_REQBUF 0x02 /* If this bit is set, need */
55 /* emulation reqest buff before */
57 #define VSCSIIF_NEED_EMULATE_RSPBUF 0x04 /* If this bit is set, need */
58 /* emulation resp buff after */
61 /* Additional Sense Code (ASC) used */
62 #define NO_ADDITIONAL_SENSE 0x0
63 #define LOGICAL_UNIT_NOT_READY 0x4
64 #define UNRECOVERED_READ_ERR 0x11
65 #define PARAMETER_LIST_LENGTH_ERR 0x1a
66 #define INVALID_OPCODE 0x20
67 #define ADDR_OUT_OF_RANGE 0x21
68 #define INVALID_FIELD_IN_CDB 0x24
69 #define INVALID_FIELD_IN_PARAM_LIST 0x26
70 #define POWERON_RESET 0x29
71 #define SAVING_PARAMS_UNSUP 0x39
72 #define THRESHOLD_EXCEEDED 0x5d
73 #define LOW_POWER_COND_ON 0x5e
77 /* Number os SCSI op_code */
78 #define VSCSI_MAX_SCSI_OP_CODE 256
79 static unsigned char bitmap[VSCSI_MAX_SCSI_OP_CODE];
81 #define NO_EMULATE(cmd) \
82 bitmap[cmd] = VSCSIIF_NEED_CMD_EXEC; \
83 pre_function[cmd] = NULL; \
84 post_function[cmd] = NULL
89 Emulation routines for each SCSI op_code.
91 static void (*pre_function[VSCSI_MAX_SCSI_OP_CODE])(pending_req_t *, void *);
92 static void (*post_function[VSCSI_MAX_SCSI_OP_CODE])(pending_req_t *, void *);
95 static const int check_condition_result =
96 (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
98 static void scsiback_mk_sense_buffer(uint8_t *data, uint8_t key,
99 uint8_t asc, uint8_t asq)
101 data[0] = 0x70; /* fixed, current */
103 data[7] = 0xa; /* implies 18 byte sense buffer */
108 static void resp_not_supported_cmd(pending_req_t *pending_req, void *data)
110 scsiback_mk_sense_buffer(pending_req->sense_buffer, ILLEGAL_REQUEST,
112 pending_req->resid = 0;
113 pending_req->rslt = check_condition_result;
117 static int __copy_to_sg(struct scatterlist *sgl, unsigned int nr_sg,
118 void *buf, unsigned int buflen)
120 struct scatterlist *sg;
123 unsigned int from_rest = buflen;
124 unsigned int to_capa;
125 unsigned int copy_size = 0;
129 for_each_sg (sgl, sg, nr_sg, i) {
130 if (sg_page(sg) == NULL) {
131 pr_warning("%s: inconsistent length field in "
132 "scatterlist\n", __FUNCTION__);
136 to_capa = sg->length;
137 copy_size = min_t(unsigned int, to_capa, from_rest);
139 pfn = page_to_pfn(sg_page(sg));
140 to = pfn_to_kaddr(pfn) + (sg->offset);
141 memcpy(to, from, copy_size);
143 from_rest -= copy_size;
144 if (from_rest == 0) {
151 pr_warning("%s: no space in scatterlist\n", __FUNCTION__);
155 static int __maybe_unused __copy_from_sg(struct scatterlist *sgl,
156 unsigned int nr_sg, void *buf,
159 struct scatterlist *sg;
162 unsigned int from_rest;
163 unsigned int to_capa = buflen;
164 unsigned int copy_size;
168 for_each_sg (sgl, sg, nr_sg, i) {
169 if (sg_page(sg) == NULL) {
170 pr_warning("%s: inconsistent length field in "
171 "scatterlist\n", __FUNCTION__);
175 from_rest = sg->length;
176 if ((from_rest > 0) && (to_capa < from_rest)) {
177 pr_warning("%s: no space in destination buffer\n",
181 copy_size = from_rest;
183 pfn = page_to_pfn(sg_page(sg));
184 from = pfn_to_kaddr(pfn) + (sg->offset);
185 memcpy(to, from, copy_size);
187 to_capa -= copy_size;
194 static int __nr_luns_under_host(struct vscsibk_info *info)
196 struct v2p_entry *entry;
197 struct list_head *head = &(info->v2p_entry_lists);
201 spin_lock_irqsave(&info->v2p_lock, flags);
202 list_for_each_entry(entry, head, l) {
205 spin_unlock_irqrestore(&info->v2p_lock, flags);
211 /* REPORT LUNS Define*/
212 #define VSCSI_REPORT_LUNS_HEADER 8
213 #define VSCSI_REPORT_LUNS_RETRY 3
215 /* quoted scsi_debug.c/resp_report_luns() */
216 static void __report_luns(pending_req_t *pending_req, void *data)
218 struct vscsibk_info *info = pending_req->info;
219 unsigned int channel = pending_req->v_chn;
220 unsigned int target = pending_req->v_tgt;
221 unsigned int nr_seg = pending_req->nr_segments;
222 unsigned char *cmd = (unsigned char *)pending_req->cmnd;
224 unsigned char *buff = NULL;
225 unsigned char alloc_len;
226 unsigned int alloc_luns = 0;
227 unsigned int req_bufflen = 0;
228 unsigned int actual_len = 0;
229 unsigned int retry_cnt = 0;
230 int select_report = (int)cmd[2];
231 int i, lun_cnt = 0, lun, upper, err = 0;
233 struct v2p_entry *entry;
234 struct list_head *head = &(info->v2p_entry_lists);
237 struct scsi_lun *one_lun;
239 req_bufflen = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
240 if ((req_bufflen < 4) || (select_report != 0))
243 alloc_luns = __nr_luns_under_host(info);
244 alloc_len = sizeof(struct scsi_lun) * alloc_luns
245 + VSCSI_REPORT_LUNS_HEADER;
247 if ((buff = kzalloc(alloc_len, GFP_KERNEL)) == NULL) {
248 pr_err("scsiback:%s kmalloc err\n", __FUNCTION__);
252 one_lun = (struct scsi_lun *) &buff[8];
253 spin_lock_irqsave(&info->v2p_lock, flags);
254 list_for_each_entry(entry, head, l) {
255 if ((entry->v.chn == channel) &&
256 (entry->v.tgt == target)) {
259 if (lun_cnt >= alloc_luns) {
260 spin_unlock_irqrestore(&info->v2p_lock,
263 if (retry_cnt < VSCSI_REPORT_LUNS_RETRY) {
274 upper = (lun >> 8) & 0x3f;
276 one_lun[lun_cnt].scsi_lun[0] = upper;
277 one_lun[lun_cnt].scsi_lun[1] = lun & 0xff;
282 spin_unlock_irqrestore(&info->v2p_lock, flags);
284 buff[2] = ((sizeof(struct scsi_lun) * lun_cnt) >> 8) & 0xff;
285 buff[3] = (sizeof(struct scsi_lun) * lun_cnt) & 0xff;
287 actual_len = lun_cnt * sizeof(struct scsi_lun)
288 + VSCSI_REPORT_LUNS_HEADER;
290 for (i = 0; i < nr_seg; i++)
291 req_bufflen += pending_req->sgl[i].length;
293 err = __copy_to_sg(pending_req->sgl, nr_seg, buff,
294 min(req_bufflen, actual_len));
298 memset(pending_req->sense_buffer, 0, VSCSIIF_SENSE_BUFFERSIZE);
299 pending_req->rslt = 0x00;
300 pending_req->resid = req_bufflen - min(req_bufflen, actual_len);
306 scsiback_mk_sense_buffer(pending_req->sense_buffer, ILLEGAL_REQUEST,
307 INVALID_FIELD_IN_CDB, 0);
308 pending_req->rslt = check_condition_result;
309 pending_req->resid = 0;
317 int __pre_do_emulation(pending_req_t *pending_req, void *data)
319 uint8_t op_code = pending_req->cmnd[0];
321 if ((bitmap[op_code] & VSCSIIF_NEED_EMULATE_REQBUF) &&
322 pre_function[op_code] != NULL) {
323 pre_function[op_code](pending_req, data);
327 0: no need for native driver call, so should return immediately.
328 1: non emulation or should call native driver
329 after modifing the request buffer.
331 return !!(bitmap[op_code] & VSCSIIF_NEED_CMD_EXEC);
334 void scsiback_rsp_emulation(pending_req_t *pending_req)
336 uint8_t op_code = pending_req->cmnd[0];
338 if ((bitmap[op_code] & VSCSIIF_NEED_EMULATE_RSPBUF) &&
339 post_function[op_code] != NULL) {
340 post_function[op_code](pending_req, NULL);
347 void scsiback_req_emulation_or_cmdexec(pending_req_t *pending_req)
349 if (__pre_do_emulation(pending_req, NULL)) {
350 scsiback_cmd_exec(pending_req);
353 scsiback_fast_flush_area(pending_req);
354 scsiback_do_resp_with_sense(pending_req->sense_buffer,
355 pending_req->rslt, pending_req->resid, pending_req);
361 Following are not customizable functions.
363 void scsiback_emulation_init(void)
367 /* Initialize to default state */
368 for (i = 0; i < VSCSI_MAX_SCSI_OP_CODE; i++) {
369 bitmap[i] = (VSCSIIF_NEED_EMULATE_REQBUF |
370 VSCSIIF_NEED_EMULATE_RSPBUF);
371 pre_function[i] = resp_not_supported_cmd;
372 post_function[i] = NULL;
374 - no need for pre-emulation
375 - no need for post-emulation
381 Register appropriate functions below as you need.
382 (See scsi/scsi.h for definition of SCSI op_code.)
386 Following commands do not require emulation.
388 NO_EMULATE(TEST_UNIT_READY); /*0x00*/ /* sd,st */
389 NO_EMULATE(REZERO_UNIT); /*0x01*/ /* st */
390 NO_EMULATE(REQUEST_SENSE); /*0x03*/
391 NO_EMULATE(FORMAT_UNIT); /*0x04*/
392 NO_EMULATE(READ_BLOCK_LIMITS); /*0x05*/ /* st */
393 /*NO_EMULATE(REASSIGN_BLOCKS); *//*0x07*/
394 NO_EMULATE(INITIALIZE_ELEMENT_STATUS); /*0x07*/ /* ch */
395 NO_EMULATE(READ_6); /*0x08*/ /* sd,st */
396 NO_EMULATE(WRITE_6); /*0x0a*/ /* sd,st */
397 NO_EMULATE(SEEK_6); /*0x0b*/
398 /*NO_EMULATE(READ_REVERSE); *//*0x0f*/
399 NO_EMULATE(WRITE_FILEMARKS); /*0x10*/ /* st */
400 NO_EMULATE(SPACE); /*0x11*/ /* st */
401 NO_EMULATE(INQUIRY); /*0x12*/
402 /*NO_EMULATE(RECOVER_BUFFERED_DATA); *//*0x14*/
403 NO_EMULATE(MODE_SELECT); /*0x15*/ /* st */
404 NO_EMULATE(RESERVE); /*0x16*/
405 NO_EMULATE(RELEASE); /*0x17*/
406 /*NO_EMULATE(COPY); *//*0x18*/
407 NO_EMULATE(ERASE); /*0x19*/ /* st */
408 NO_EMULATE(MODE_SENSE); /*0x1a*/ /* st */
409 NO_EMULATE(START_STOP); /*0x1b*/ /* sd,st */
410 NO_EMULATE(RECEIVE_DIAGNOSTIC); /*0x1c*/
411 NO_EMULATE(SEND_DIAGNOSTIC); /*0x1d*/
412 NO_EMULATE(ALLOW_MEDIUM_REMOVAL); /*0x1e*/
414 /*NO_EMULATE(SET_WINDOW); *//*0x24*/
415 NO_EMULATE(READ_CAPACITY); /*0x25*/ /* sd */
416 NO_EMULATE(READ_10); /*0x28*/ /* sd */
417 NO_EMULATE(WRITE_10); /*0x2a*/ /* sd */
418 NO_EMULATE(SEEK_10); /*0x2b*/ /* st */
419 NO_EMULATE(POSITION_TO_ELEMENT); /*0x2b*/ /* ch */
420 /*NO_EMULATE(WRITE_VERIFY); *//*0x2e*/
421 /*NO_EMULATE(VERIFY); *//*0x2f*/
422 /*NO_EMULATE(SEARCH_HIGH); *//*0x30*/
423 /*NO_EMULATE(SEARCH_EQUAL); *//*0x31*/
424 /*NO_EMULATE(SEARCH_LOW); *//*0x32*/
425 NO_EMULATE(SET_LIMITS); /*0x33*/
426 NO_EMULATE(PRE_FETCH); /*0x34*/ /* st! */
427 NO_EMULATE(READ_POSITION); /*0x34*/ /* st */
428 NO_EMULATE(SYNCHRONIZE_CACHE); /*0x35*/ /* sd */
429 NO_EMULATE(LOCK_UNLOCK_CACHE); /*0x36*/
430 NO_EMULATE(READ_DEFECT_DATA); /*0x37*/
431 NO_EMULATE(MEDIUM_SCAN); /*0x38*/
432 /*NO_EMULATE(COMPARE); *//*0x39*/
433 /*NO_EMULATE(COPY_VERIFY); *//*0x3a*/
434 NO_EMULATE(WRITE_BUFFER); /*0x3b*/
435 NO_EMULATE(READ_BUFFER); /*0x3c*/ /* osst */
436 /*NO_EMULATE(UPDATE_BLOCK); *//*0x3d*/
437 /*NO_EMULATE(READ_LONG); *//*0x3e*/
438 /*NO_EMULATE(WRITE_LONG); *//*0x3f*/
439 /*NO_EMULATE(CHANGE_DEFINITION); *//*0x40*/
440 /*NO_EMULATE(WRITE_SAME); *//*0x41*/
441 NO_EMULATE(READ_TOC); /*0x43*/ /* sr */
442 NO_EMULATE(LOG_SELECT); /*0x4c*/
443 NO_EMULATE(LOG_SENSE); /*0x4d*/ /* st! */
444 /*NO_EMULATE(MODE_SELECT_10); *//*0x55*/
445 /*NO_EMULATE(RESERVE_10); *//*0x56*/
446 /*NO_EMULATE(RELEASE_10); *//*0x57*/
447 NO_EMULATE(MODE_SENSE_10); /*0x5a*/ /* scsi_lib */
448 /*NO_EMULATE(PERSISTENT_RESERVE_IN); *//*0x5e*/
449 /*NO_EMULATE(PERSISTENT_RESERVE_OUT); *//*0x5f*/
450 /* REPORT_LUNS *//*0xa0*//*Full emulaiton*/
451 #ifdef MAINTENANCE_IN
452 NO_EMULATE(MAINTENANCE_IN); /*0xa3*/ /* IFT alua */
453 NO_EMULATE(MAINTENANCE_OUT); /*0xa4*/ /* IFT alua */
455 NO_EMULATE(MOVE_MEDIUM); /*0xa5*/ /* ch */
456 NO_EMULATE(EXCHANGE_MEDIUM); /*0xa6*/ /* ch */
457 /*NO_EMULATE(READ_12); *//*0xa8*/
458 /*NO_EMULATE(WRITE_12); *//*0xaa*/
459 /*NO_EMULATE(WRITE_VERIFY_12); *//*0xae*/
460 /*NO_EMULATE(SEARCH_HIGH_12); *//*0xb0*/
461 /*NO_EMULATE(SEARCH_EQUAL_12); *//*0xb1*/
462 /*NO_EMULATE(SEARCH_LOW_12); *//*0xb2*/
463 NO_EMULATE(READ_ELEMENT_STATUS); /*0xb8*/ /* ch */
464 NO_EMULATE(SEND_VOLUME_TAG); /*0xb6*/ /* ch */
465 /*NO_EMULATE(WRITE_LONG_2); *//*0xea*/
466 NO_EMULATE(READ_16); /*0x88*/ /* sd >2TB */
467 NO_EMULATE(WRITE_16); /*0x8a*/ /* sd >2TB */
468 NO_EMULATE(VERIFY_16); /*0x8f*/
469 NO_EMULATE(SERVICE_ACTION_IN); /*0x9e*/ /* sd >2TB */
471 /* st: QFA_REQUEST_BLOCK, QFA_SEEK_BLOCK might be needed ? */
473 Following commands require emulation.
475 pre_function[REPORT_LUNS] = __report_luns;
476 bitmap[REPORT_LUNS] = (VSCSIIF_NEED_EMULATE_REQBUF |
477 VSCSIIF_NEED_EMULATE_RSPBUF);