1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 2001 Jens Axboe <axboe@suse.de>
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun #include <linux/compat.h>
6*4882a593Smuzhiyun #include <linux/kernel.h>
7*4882a593Smuzhiyun #include <linux/errno.h>
8*4882a593Smuzhiyun #include <linux/string.h>
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/blkdev.h>
11*4882a593Smuzhiyun #include <linux/capability.h>
12*4882a593Smuzhiyun #include <linux/completion.h>
13*4882a593Smuzhiyun #include <linux/cdrom.h>
14*4882a593Smuzhiyun #include <linux/ratelimit.h>
15*4882a593Smuzhiyun #include <linux/slab.h>
16*4882a593Smuzhiyun #include <linux/times.h>
17*4882a593Smuzhiyun #include <linux/uio.h>
18*4882a593Smuzhiyun #include <linux/uaccess.h>
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun #include <scsi/scsi.h>
21*4882a593Smuzhiyun #include <scsi/scsi_ioctl.h>
22*4882a593Smuzhiyun #include <scsi/scsi_cmnd.h>
23*4882a593Smuzhiyun #include <scsi/sg.h>
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun struct blk_cmd_filter {
26*4882a593Smuzhiyun unsigned long read_ok[BLK_SCSI_CMD_PER_LONG];
27*4882a593Smuzhiyun unsigned long write_ok[BLK_SCSI_CMD_PER_LONG];
28*4882a593Smuzhiyun };
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun static struct blk_cmd_filter blk_default_cmd_filter;
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun /* Command group 3 is reserved and should never be used. */
33*4882a593Smuzhiyun const unsigned char scsi_command_size_tbl[8] =
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun 6, 10, 10, 12,
36*4882a593Smuzhiyun 16, 12, 10, 10
37*4882a593Smuzhiyun };
38*4882a593Smuzhiyun EXPORT_SYMBOL(scsi_command_size_tbl);
39*4882a593Smuzhiyun
sg_get_version(int __user * p)40*4882a593Smuzhiyun static int sg_get_version(int __user *p)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun static const int sg_version_num = 30527;
43*4882a593Smuzhiyun return put_user(sg_version_num, p);
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun
scsi_get_idlun(struct request_queue * q,int __user * p)46*4882a593Smuzhiyun static int scsi_get_idlun(struct request_queue *q, int __user *p)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun return put_user(0, p);
49*4882a593Smuzhiyun }
50*4882a593Smuzhiyun
scsi_get_bus(struct request_queue * q,int __user * p)51*4882a593Smuzhiyun static int scsi_get_bus(struct request_queue *q, int __user *p)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun return put_user(0, p);
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun
sg_get_timeout(struct request_queue * q)56*4882a593Smuzhiyun static int sg_get_timeout(struct request_queue *q)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun return jiffies_to_clock_t(q->sg_timeout);
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun
sg_set_timeout(struct request_queue * q,int __user * p)61*4882a593Smuzhiyun static int sg_set_timeout(struct request_queue *q, int __user *p)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun int timeout, err = get_user(timeout, p);
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun if (!err)
66*4882a593Smuzhiyun q->sg_timeout = clock_t_to_jiffies(timeout);
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun return err;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun
max_sectors_bytes(struct request_queue * q)71*4882a593Smuzhiyun static int max_sectors_bytes(struct request_queue *q)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun unsigned int max_sectors = queue_max_sectors(q);
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun max_sectors = min_t(unsigned int, max_sectors, INT_MAX >> 9);
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun return max_sectors << 9;
78*4882a593Smuzhiyun }
79*4882a593Smuzhiyun
sg_get_reserved_size(struct request_queue * q,int __user * p)80*4882a593Smuzhiyun static int sg_get_reserved_size(struct request_queue *q, int __user *p)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun int val = min_t(int, q->sg_reserved_size, max_sectors_bytes(q));
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun return put_user(val, p);
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun
sg_set_reserved_size(struct request_queue * q,int __user * p)87*4882a593Smuzhiyun static int sg_set_reserved_size(struct request_queue *q, int __user *p)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun int size, err = get_user(size, p);
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun if (err)
92*4882a593Smuzhiyun return err;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun if (size < 0)
95*4882a593Smuzhiyun return -EINVAL;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun q->sg_reserved_size = min(size, max_sectors_bytes(q));
98*4882a593Smuzhiyun return 0;
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun /*
102*4882a593Smuzhiyun * will always return that we are ATAPI even for a real SCSI drive, I'm not
103*4882a593Smuzhiyun * so sure this is worth doing anything about (why would you care??)
104*4882a593Smuzhiyun */
sg_emulated_host(struct request_queue * q,int __user * p)105*4882a593Smuzhiyun static int sg_emulated_host(struct request_queue *q, int __user *p)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun return put_user(1, p);
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun
blk_set_cmd_filter_defaults(struct blk_cmd_filter * filter)110*4882a593Smuzhiyun static void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun /* Basic read-only commands */
113*4882a593Smuzhiyun __set_bit(TEST_UNIT_READY, filter->read_ok);
114*4882a593Smuzhiyun __set_bit(REQUEST_SENSE, filter->read_ok);
115*4882a593Smuzhiyun __set_bit(READ_6, filter->read_ok);
116*4882a593Smuzhiyun __set_bit(READ_10, filter->read_ok);
117*4882a593Smuzhiyun __set_bit(READ_12, filter->read_ok);
118*4882a593Smuzhiyun __set_bit(READ_16, filter->read_ok);
119*4882a593Smuzhiyun __set_bit(READ_BUFFER, filter->read_ok);
120*4882a593Smuzhiyun __set_bit(READ_DEFECT_DATA, filter->read_ok);
121*4882a593Smuzhiyun __set_bit(READ_CAPACITY, filter->read_ok);
122*4882a593Smuzhiyun __set_bit(READ_LONG, filter->read_ok);
123*4882a593Smuzhiyun __set_bit(INQUIRY, filter->read_ok);
124*4882a593Smuzhiyun __set_bit(MODE_SENSE, filter->read_ok);
125*4882a593Smuzhiyun __set_bit(MODE_SENSE_10, filter->read_ok);
126*4882a593Smuzhiyun __set_bit(LOG_SENSE, filter->read_ok);
127*4882a593Smuzhiyun __set_bit(START_STOP, filter->read_ok);
128*4882a593Smuzhiyun __set_bit(GPCMD_VERIFY_10, filter->read_ok);
129*4882a593Smuzhiyun __set_bit(VERIFY_16, filter->read_ok);
130*4882a593Smuzhiyun __set_bit(REPORT_LUNS, filter->read_ok);
131*4882a593Smuzhiyun __set_bit(SERVICE_ACTION_IN_16, filter->read_ok);
132*4882a593Smuzhiyun __set_bit(RECEIVE_DIAGNOSTIC, filter->read_ok);
133*4882a593Smuzhiyun __set_bit(MAINTENANCE_IN, filter->read_ok);
134*4882a593Smuzhiyun __set_bit(GPCMD_READ_BUFFER_CAPACITY, filter->read_ok);
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun /* Audio CD commands */
137*4882a593Smuzhiyun __set_bit(GPCMD_PLAY_CD, filter->read_ok);
138*4882a593Smuzhiyun __set_bit(GPCMD_PLAY_AUDIO_10, filter->read_ok);
139*4882a593Smuzhiyun __set_bit(GPCMD_PLAY_AUDIO_MSF, filter->read_ok);
140*4882a593Smuzhiyun __set_bit(GPCMD_PLAY_AUDIO_TI, filter->read_ok);
141*4882a593Smuzhiyun __set_bit(GPCMD_PAUSE_RESUME, filter->read_ok);
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun /* CD/DVD data reading */
144*4882a593Smuzhiyun __set_bit(GPCMD_READ_CD, filter->read_ok);
145*4882a593Smuzhiyun __set_bit(GPCMD_READ_CD_MSF, filter->read_ok);
146*4882a593Smuzhiyun __set_bit(GPCMD_READ_DISC_INFO, filter->read_ok);
147*4882a593Smuzhiyun __set_bit(GPCMD_READ_CDVD_CAPACITY, filter->read_ok);
148*4882a593Smuzhiyun __set_bit(GPCMD_READ_DVD_STRUCTURE, filter->read_ok);
149*4882a593Smuzhiyun __set_bit(GPCMD_READ_HEADER, filter->read_ok);
150*4882a593Smuzhiyun __set_bit(GPCMD_READ_TRACK_RZONE_INFO, filter->read_ok);
151*4882a593Smuzhiyun __set_bit(GPCMD_READ_SUBCHANNEL, filter->read_ok);
152*4882a593Smuzhiyun __set_bit(GPCMD_READ_TOC_PMA_ATIP, filter->read_ok);
153*4882a593Smuzhiyun __set_bit(GPCMD_REPORT_KEY, filter->read_ok);
154*4882a593Smuzhiyun __set_bit(GPCMD_SCAN, filter->read_ok);
155*4882a593Smuzhiyun __set_bit(GPCMD_GET_CONFIGURATION, filter->read_ok);
156*4882a593Smuzhiyun __set_bit(GPCMD_READ_FORMAT_CAPACITIES, filter->read_ok);
157*4882a593Smuzhiyun __set_bit(GPCMD_GET_EVENT_STATUS_NOTIFICATION, filter->read_ok);
158*4882a593Smuzhiyun __set_bit(GPCMD_GET_PERFORMANCE, filter->read_ok);
159*4882a593Smuzhiyun __set_bit(GPCMD_SEEK, filter->read_ok);
160*4882a593Smuzhiyun __set_bit(GPCMD_STOP_PLAY_SCAN, filter->read_ok);
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun /* Basic writing commands */
163*4882a593Smuzhiyun __set_bit(WRITE_6, filter->write_ok);
164*4882a593Smuzhiyun __set_bit(WRITE_10, filter->write_ok);
165*4882a593Smuzhiyun __set_bit(WRITE_VERIFY, filter->write_ok);
166*4882a593Smuzhiyun __set_bit(WRITE_12, filter->write_ok);
167*4882a593Smuzhiyun __set_bit(WRITE_VERIFY_12, filter->write_ok);
168*4882a593Smuzhiyun __set_bit(WRITE_16, filter->write_ok);
169*4882a593Smuzhiyun __set_bit(WRITE_LONG, filter->write_ok);
170*4882a593Smuzhiyun __set_bit(WRITE_LONG_2, filter->write_ok);
171*4882a593Smuzhiyun __set_bit(WRITE_SAME, filter->write_ok);
172*4882a593Smuzhiyun __set_bit(WRITE_SAME_16, filter->write_ok);
173*4882a593Smuzhiyun __set_bit(WRITE_SAME_32, filter->write_ok);
174*4882a593Smuzhiyun __set_bit(ERASE, filter->write_ok);
175*4882a593Smuzhiyun __set_bit(GPCMD_MODE_SELECT_10, filter->write_ok);
176*4882a593Smuzhiyun __set_bit(MODE_SELECT, filter->write_ok);
177*4882a593Smuzhiyun __set_bit(LOG_SELECT, filter->write_ok);
178*4882a593Smuzhiyun __set_bit(GPCMD_BLANK, filter->write_ok);
179*4882a593Smuzhiyun __set_bit(GPCMD_CLOSE_TRACK, filter->write_ok);
180*4882a593Smuzhiyun __set_bit(GPCMD_FLUSH_CACHE, filter->write_ok);
181*4882a593Smuzhiyun __set_bit(GPCMD_FORMAT_UNIT, filter->write_ok);
182*4882a593Smuzhiyun __set_bit(GPCMD_REPAIR_RZONE_TRACK, filter->write_ok);
183*4882a593Smuzhiyun __set_bit(GPCMD_RESERVE_RZONE_TRACK, filter->write_ok);
184*4882a593Smuzhiyun __set_bit(GPCMD_SEND_DVD_STRUCTURE, filter->write_ok);
185*4882a593Smuzhiyun __set_bit(GPCMD_SEND_EVENT, filter->write_ok);
186*4882a593Smuzhiyun __set_bit(GPCMD_SEND_KEY, filter->write_ok);
187*4882a593Smuzhiyun __set_bit(GPCMD_SEND_OPC, filter->write_ok);
188*4882a593Smuzhiyun __set_bit(GPCMD_SEND_CUE_SHEET, filter->write_ok);
189*4882a593Smuzhiyun __set_bit(GPCMD_SET_SPEED, filter->write_ok);
190*4882a593Smuzhiyun __set_bit(GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, filter->write_ok);
191*4882a593Smuzhiyun __set_bit(GPCMD_LOAD_UNLOAD, filter->write_ok);
192*4882a593Smuzhiyun __set_bit(GPCMD_SET_STREAMING, filter->write_ok);
193*4882a593Smuzhiyun __set_bit(GPCMD_SET_READ_AHEAD, filter->write_ok);
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun /* ZBC Commands */
196*4882a593Smuzhiyun __set_bit(ZBC_OUT, filter->write_ok);
197*4882a593Smuzhiyun __set_bit(ZBC_IN, filter->read_ok);
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun
blk_verify_command(unsigned char * cmd,fmode_t mode)200*4882a593Smuzhiyun int blk_verify_command(unsigned char *cmd, fmode_t mode)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun struct blk_cmd_filter *filter = &blk_default_cmd_filter;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun /* root can do any command. */
205*4882a593Smuzhiyun if (capable(CAP_SYS_RAWIO))
206*4882a593Smuzhiyun return 0;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun /* Anybody who can open the device can do a read-safe command */
209*4882a593Smuzhiyun if (test_bit(cmd[0], filter->read_ok))
210*4882a593Smuzhiyun return 0;
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun /* Write-safe commands require a writable open */
213*4882a593Smuzhiyun if (test_bit(cmd[0], filter->write_ok) && (mode & FMODE_WRITE))
214*4882a593Smuzhiyun return 0;
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun return -EPERM;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun EXPORT_SYMBOL(blk_verify_command);
219*4882a593Smuzhiyun
blk_fill_sghdr_rq(struct request_queue * q,struct request * rq,struct sg_io_hdr * hdr,fmode_t mode)220*4882a593Smuzhiyun static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
221*4882a593Smuzhiyun struct sg_io_hdr *hdr, fmode_t mode)
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun struct scsi_request *req = scsi_req(rq);
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun if (copy_from_user(req->cmd, hdr->cmdp, hdr->cmd_len))
226*4882a593Smuzhiyun return -EFAULT;
227*4882a593Smuzhiyun if (blk_verify_command(req->cmd, mode))
228*4882a593Smuzhiyun return -EPERM;
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun /*
231*4882a593Smuzhiyun * fill in request structure
232*4882a593Smuzhiyun */
233*4882a593Smuzhiyun req->cmd_len = hdr->cmd_len;
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun rq->timeout = msecs_to_jiffies(hdr->timeout);
236*4882a593Smuzhiyun if (!rq->timeout)
237*4882a593Smuzhiyun rq->timeout = q->sg_timeout;
238*4882a593Smuzhiyun if (!rq->timeout)
239*4882a593Smuzhiyun rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
240*4882a593Smuzhiyun if (rq->timeout < BLK_MIN_SG_TIMEOUT)
241*4882a593Smuzhiyun rq->timeout = BLK_MIN_SG_TIMEOUT;
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun return 0;
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun
blk_complete_sghdr_rq(struct request * rq,struct sg_io_hdr * hdr,struct bio * bio)246*4882a593Smuzhiyun static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
247*4882a593Smuzhiyun struct bio *bio)
248*4882a593Smuzhiyun {
249*4882a593Smuzhiyun struct scsi_request *req = scsi_req(rq);
250*4882a593Smuzhiyun int r, ret = 0;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun /*
253*4882a593Smuzhiyun * fill in all the output members
254*4882a593Smuzhiyun */
255*4882a593Smuzhiyun hdr->status = req->result & 0xff;
256*4882a593Smuzhiyun hdr->masked_status = status_byte(req->result);
257*4882a593Smuzhiyun hdr->msg_status = msg_byte(req->result);
258*4882a593Smuzhiyun hdr->host_status = host_byte(req->result);
259*4882a593Smuzhiyun hdr->driver_status = driver_byte(req->result);
260*4882a593Smuzhiyun hdr->info = 0;
261*4882a593Smuzhiyun if (hdr->masked_status || hdr->host_status || hdr->driver_status)
262*4882a593Smuzhiyun hdr->info |= SG_INFO_CHECK;
263*4882a593Smuzhiyun hdr->resid = req->resid_len;
264*4882a593Smuzhiyun hdr->sb_len_wr = 0;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun if (req->sense_len && hdr->sbp) {
267*4882a593Smuzhiyun int len = min((unsigned int) hdr->mx_sb_len, req->sense_len);
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun if (!copy_to_user(hdr->sbp, req->sense, len))
270*4882a593Smuzhiyun hdr->sb_len_wr = len;
271*4882a593Smuzhiyun else
272*4882a593Smuzhiyun ret = -EFAULT;
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun r = blk_rq_unmap_user(bio);
276*4882a593Smuzhiyun if (!ret)
277*4882a593Smuzhiyun ret = r;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun return ret;
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun
sg_io(struct request_queue * q,struct gendisk * bd_disk,struct sg_io_hdr * hdr,fmode_t mode)282*4882a593Smuzhiyun static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
283*4882a593Smuzhiyun struct sg_io_hdr *hdr, fmode_t mode)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun unsigned long start_time;
286*4882a593Smuzhiyun ssize_t ret = 0;
287*4882a593Smuzhiyun int writing = 0;
288*4882a593Smuzhiyun int at_head = 0;
289*4882a593Smuzhiyun struct request *rq;
290*4882a593Smuzhiyun struct scsi_request *req;
291*4882a593Smuzhiyun struct bio *bio;
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun if (hdr->interface_id != 'S')
294*4882a593Smuzhiyun return -EINVAL;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun if (hdr->dxfer_len > (queue_max_hw_sectors(q) << 9))
297*4882a593Smuzhiyun return -EIO;
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun if (hdr->dxfer_len)
300*4882a593Smuzhiyun switch (hdr->dxfer_direction) {
301*4882a593Smuzhiyun default:
302*4882a593Smuzhiyun return -EINVAL;
303*4882a593Smuzhiyun case SG_DXFER_TO_DEV:
304*4882a593Smuzhiyun writing = 1;
305*4882a593Smuzhiyun break;
306*4882a593Smuzhiyun case SG_DXFER_TO_FROM_DEV:
307*4882a593Smuzhiyun case SG_DXFER_FROM_DEV:
308*4882a593Smuzhiyun break;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun if (hdr->flags & SG_FLAG_Q_AT_HEAD)
311*4882a593Smuzhiyun at_head = 1;
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun ret = -ENOMEM;
314*4882a593Smuzhiyun rq = blk_get_request(q, writing ? REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN, 0);
315*4882a593Smuzhiyun if (IS_ERR(rq))
316*4882a593Smuzhiyun return PTR_ERR(rq);
317*4882a593Smuzhiyun req = scsi_req(rq);
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun if (hdr->cmd_len > BLK_MAX_CDB) {
320*4882a593Smuzhiyun req->cmd = kzalloc(hdr->cmd_len, GFP_KERNEL);
321*4882a593Smuzhiyun if (!req->cmd)
322*4882a593Smuzhiyun goto out_put_request;
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun ret = blk_fill_sghdr_rq(q, rq, hdr, mode);
326*4882a593Smuzhiyun if (ret < 0)
327*4882a593Smuzhiyun goto out_free_cdb;
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun ret = 0;
330*4882a593Smuzhiyun if (hdr->iovec_count) {
331*4882a593Smuzhiyun struct iov_iter i;
332*4882a593Smuzhiyun struct iovec *iov = NULL;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun ret = import_iovec(rq_data_dir(rq), hdr->dxferp,
335*4882a593Smuzhiyun hdr->iovec_count, 0, &iov, &i);
336*4882a593Smuzhiyun if (ret < 0)
337*4882a593Smuzhiyun goto out_free_cdb;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun /* SG_IO howto says that the shorter of the two wins */
340*4882a593Smuzhiyun iov_iter_truncate(&i, hdr->dxfer_len);
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun ret = blk_rq_map_user_iov(q, rq, NULL, &i, GFP_KERNEL);
343*4882a593Smuzhiyun kfree(iov);
344*4882a593Smuzhiyun } else if (hdr->dxfer_len)
345*4882a593Smuzhiyun ret = blk_rq_map_user(q, rq, NULL, hdr->dxferp, hdr->dxfer_len,
346*4882a593Smuzhiyun GFP_KERNEL);
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun if (ret)
349*4882a593Smuzhiyun goto out_free_cdb;
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun bio = rq->bio;
352*4882a593Smuzhiyun req->retries = 0;
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun start_time = jiffies;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun /* ignore return value. All information is passed back to caller
357*4882a593Smuzhiyun * (if he doesn't check that is his problem).
358*4882a593Smuzhiyun * N.B. a non-zero SCSI status is _not_ necessarily an error.
359*4882a593Smuzhiyun */
360*4882a593Smuzhiyun blk_execute_rq(q, bd_disk, rq, at_head);
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun hdr->duration = jiffies_to_msecs(jiffies - start_time);
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun ret = blk_complete_sghdr_rq(rq, hdr, bio);
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun out_free_cdb:
367*4882a593Smuzhiyun scsi_req_free_cmd(req);
368*4882a593Smuzhiyun out_put_request:
369*4882a593Smuzhiyun blk_put_request(rq);
370*4882a593Smuzhiyun return ret;
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun /**
374*4882a593Smuzhiyun * sg_scsi_ioctl -- handle deprecated SCSI_IOCTL_SEND_COMMAND ioctl
375*4882a593Smuzhiyun * @q: request queue to send scsi commands down
376*4882a593Smuzhiyun * @disk: gendisk to operate on (option)
377*4882a593Smuzhiyun * @mode: mode used to open the file through which the ioctl has been
378*4882a593Smuzhiyun * submitted
379*4882a593Smuzhiyun * @sic: userspace structure describing the command to perform
380*4882a593Smuzhiyun *
381*4882a593Smuzhiyun * Send down the scsi command described by @sic to the device below
382*4882a593Smuzhiyun * the request queue @q. If @file is non-NULL it's used to perform
383*4882a593Smuzhiyun * fine-grained permission checks that allow users to send down
384*4882a593Smuzhiyun * non-destructive SCSI commands. If the caller has a struct gendisk
385*4882a593Smuzhiyun * available it should be passed in as @disk to allow the low level
386*4882a593Smuzhiyun * driver to use the information contained in it. A non-NULL @disk
387*4882a593Smuzhiyun * is only allowed if the caller knows that the low level driver doesn't
388*4882a593Smuzhiyun * need it (e.g. in the scsi subsystem).
389*4882a593Smuzhiyun *
390*4882a593Smuzhiyun * Notes:
391*4882a593Smuzhiyun * - This interface is deprecated - users should use the SG_IO
392*4882a593Smuzhiyun * interface instead, as this is a more flexible approach to
393*4882a593Smuzhiyun * performing SCSI commands on a device.
394*4882a593Smuzhiyun * - The SCSI command length is determined by examining the 1st byte
395*4882a593Smuzhiyun * of the given command. There is no way to override this.
396*4882a593Smuzhiyun * - Data transfers are limited to PAGE_SIZE
397*4882a593Smuzhiyun * - The length (x + y) must be at least OMAX_SB_LEN bytes long to
398*4882a593Smuzhiyun * accommodate the sense buffer when an error occurs.
399*4882a593Smuzhiyun * The sense buffer is truncated to OMAX_SB_LEN (16) bytes so that
400*4882a593Smuzhiyun * old code will not be surprised.
401*4882a593Smuzhiyun * - If a Unix error occurs (e.g. ENOMEM) then the user will receive
402*4882a593Smuzhiyun * a negative return and the Unix error code in 'errno'.
403*4882a593Smuzhiyun * If the SCSI command succeeds then 0 is returned.
404*4882a593Smuzhiyun * Positive numbers returned are the compacted SCSI error codes (4
405*4882a593Smuzhiyun * bytes in one int) where the lowest byte is the SCSI status.
406*4882a593Smuzhiyun */
sg_scsi_ioctl(struct request_queue * q,struct gendisk * disk,fmode_t mode,struct scsi_ioctl_command __user * sic)407*4882a593Smuzhiyun int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
408*4882a593Smuzhiyun struct scsi_ioctl_command __user *sic)
409*4882a593Smuzhiyun {
410*4882a593Smuzhiyun enum { OMAX_SB_LEN = 16 }; /* For backward compatibility */
411*4882a593Smuzhiyun struct request *rq;
412*4882a593Smuzhiyun struct scsi_request *req;
413*4882a593Smuzhiyun int err;
414*4882a593Smuzhiyun unsigned int in_len, out_len, bytes, opcode, cmdlen;
415*4882a593Smuzhiyun char *buffer = NULL;
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun if (!sic)
418*4882a593Smuzhiyun return -EINVAL;
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun /*
421*4882a593Smuzhiyun * get in an out lengths, verify they don't exceed a page worth of data
422*4882a593Smuzhiyun */
423*4882a593Smuzhiyun if (get_user(in_len, &sic->inlen))
424*4882a593Smuzhiyun return -EFAULT;
425*4882a593Smuzhiyun if (get_user(out_len, &sic->outlen))
426*4882a593Smuzhiyun return -EFAULT;
427*4882a593Smuzhiyun if (in_len > PAGE_SIZE || out_len > PAGE_SIZE)
428*4882a593Smuzhiyun return -EINVAL;
429*4882a593Smuzhiyun if (get_user(opcode, sic->data))
430*4882a593Smuzhiyun return -EFAULT;
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun bytes = max(in_len, out_len);
433*4882a593Smuzhiyun if (bytes) {
434*4882a593Smuzhiyun buffer = kzalloc(bytes, q->bounce_gfp | GFP_USER| __GFP_NOWARN);
435*4882a593Smuzhiyun if (!buffer)
436*4882a593Smuzhiyun return -ENOMEM;
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun rq = blk_get_request(q, in_len ? REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN, 0);
441*4882a593Smuzhiyun if (IS_ERR(rq)) {
442*4882a593Smuzhiyun err = PTR_ERR(rq);
443*4882a593Smuzhiyun goto error_free_buffer;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun req = scsi_req(rq);
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun cmdlen = COMMAND_SIZE(opcode);
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun /*
450*4882a593Smuzhiyun * get command and data to send to device, if any
451*4882a593Smuzhiyun */
452*4882a593Smuzhiyun err = -EFAULT;
453*4882a593Smuzhiyun req->cmd_len = cmdlen;
454*4882a593Smuzhiyun if (copy_from_user(req->cmd, sic->data, cmdlen))
455*4882a593Smuzhiyun goto error;
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
458*4882a593Smuzhiyun goto error;
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun err = blk_verify_command(req->cmd, mode);
461*4882a593Smuzhiyun if (err)
462*4882a593Smuzhiyun goto error;
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun /* default. possible overriden later */
465*4882a593Smuzhiyun req->retries = 5;
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun switch (opcode) {
468*4882a593Smuzhiyun case SEND_DIAGNOSTIC:
469*4882a593Smuzhiyun case FORMAT_UNIT:
470*4882a593Smuzhiyun rq->timeout = FORMAT_UNIT_TIMEOUT;
471*4882a593Smuzhiyun req->retries = 1;
472*4882a593Smuzhiyun break;
473*4882a593Smuzhiyun case START_STOP:
474*4882a593Smuzhiyun rq->timeout = START_STOP_TIMEOUT;
475*4882a593Smuzhiyun break;
476*4882a593Smuzhiyun case MOVE_MEDIUM:
477*4882a593Smuzhiyun rq->timeout = MOVE_MEDIUM_TIMEOUT;
478*4882a593Smuzhiyun break;
479*4882a593Smuzhiyun case READ_ELEMENT_STATUS:
480*4882a593Smuzhiyun rq->timeout = READ_ELEMENT_STATUS_TIMEOUT;
481*4882a593Smuzhiyun break;
482*4882a593Smuzhiyun case READ_DEFECT_DATA:
483*4882a593Smuzhiyun rq->timeout = READ_DEFECT_DATA_TIMEOUT;
484*4882a593Smuzhiyun req->retries = 1;
485*4882a593Smuzhiyun break;
486*4882a593Smuzhiyun default:
487*4882a593Smuzhiyun rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
488*4882a593Smuzhiyun break;
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun if (bytes && blk_rq_map_kern(q, rq, buffer, bytes, GFP_NOIO)) {
492*4882a593Smuzhiyun err = DRIVER_ERROR << 24;
493*4882a593Smuzhiyun goto error;
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun blk_execute_rq(q, disk, rq, 0);
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun err = req->result & 0xff; /* only 8 bit SCSI status */
499*4882a593Smuzhiyun if (err) {
500*4882a593Smuzhiyun if (req->sense_len && req->sense) {
501*4882a593Smuzhiyun bytes = (OMAX_SB_LEN > req->sense_len) ?
502*4882a593Smuzhiyun req->sense_len : OMAX_SB_LEN;
503*4882a593Smuzhiyun if (copy_to_user(sic->data, req->sense, bytes))
504*4882a593Smuzhiyun err = -EFAULT;
505*4882a593Smuzhiyun }
506*4882a593Smuzhiyun } else {
507*4882a593Smuzhiyun if (copy_to_user(sic->data, buffer, out_len))
508*4882a593Smuzhiyun err = -EFAULT;
509*4882a593Smuzhiyun }
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun error:
512*4882a593Smuzhiyun blk_put_request(rq);
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun error_free_buffer:
515*4882a593Smuzhiyun kfree(buffer);
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun return err;
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(sg_scsi_ioctl);
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun /* Send basic block requests */
__blk_send_generic(struct request_queue * q,struct gendisk * bd_disk,int cmd,int data)522*4882a593Smuzhiyun static int __blk_send_generic(struct request_queue *q, struct gendisk *bd_disk,
523*4882a593Smuzhiyun int cmd, int data)
524*4882a593Smuzhiyun {
525*4882a593Smuzhiyun struct request *rq;
526*4882a593Smuzhiyun int err;
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun rq = blk_get_request(q, REQ_OP_SCSI_OUT, 0);
529*4882a593Smuzhiyun if (IS_ERR(rq))
530*4882a593Smuzhiyun return PTR_ERR(rq);
531*4882a593Smuzhiyun rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
532*4882a593Smuzhiyun scsi_req(rq)->cmd[0] = cmd;
533*4882a593Smuzhiyun scsi_req(rq)->cmd[4] = data;
534*4882a593Smuzhiyun scsi_req(rq)->cmd_len = 6;
535*4882a593Smuzhiyun blk_execute_rq(q, bd_disk, rq, 0);
536*4882a593Smuzhiyun err = scsi_req(rq)->result ? -EIO : 0;
537*4882a593Smuzhiyun blk_put_request(rq);
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun return err;
540*4882a593Smuzhiyun }
541*4882a593Smuzhiyun
blk_send_start_stop(struct request_queue * q,struct gendisk * bd_disk,int data)542*4882a593Smuzhiyun static inline int blk_send_start_stop(struct request_queue *q,
543*4882a593Smuzhiyun struct gendisk *bd_disk, int data)
544*4882a593Smuzhiyun {
545*4882a593Smuzhiyun return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data);
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun
put_sg_io_hdr(const struct sg_io_hdr * hdr,void __user * argp)548*4882a593Smuzhiyun int put_sg_io_hdr(const struct sg_io_hdr *hdr, void __user *argp)
549*4882a593Smuzhiyun {
550*4882a593Smuzhiyun #ifdef CONFIG_COMPAT
551*4882a593Smuzhiyun if (in_compat_syscall()) {
552*4882a593Smuzhiyun struct compat_sg_io_hdr hdr32 = {
553*4882a593Smuzhiyun .interface_id = hdr->interface_id,
554*4882a593Smuzhiyun .dxfer_direction = hdr->dxfer_direction,
555*4882a593Smuzhiyun .cmd_len = hdr->cmd_len,
556*4882a593Smuzhiyun .mx_sb_len = hdr->mx_sb_len,
557*4882a593Smuzhiyun .iovec_count = hdr->iovec_count,
558*4882a593Smuzhiyun .dxfer_len = hdr->dxfer_len,
559*4882a593Smuzhiyun .dxferp = (uintptr_t)hdr->dxferp,
560*4882a593Smuzhiyun .cmdp = (uintptr_t)hdr->cmdp,
561*4882a593Smuzhiyun .sbp = (uintptr_t)hdr->sbp,
562*4882a593Smuzhiyun .timeout = hdr->timeout,
563*4882a593Smuzhiyun .flags = hdr->flags,
564*4882a593Smuzhiyun .pack_id = hdr->pack_id,
565*4882a593Smuzhiyun .usr_ptr = (uintptr_t)hdr->usr_ptr,
566*4882a593Smuzhiyun .status = hdr->status,
567*4882a593Smuzhiyun .masked_status = hdr->masked_status,
568*4882a593Smuzhiyun .msg_status = hdr->msg_status,
569*4882a593Smuzhiyun .sb_len_wr = hdr->sb_len_wr,
570*4882a593Smuzhiyun .host_status = hdr->host_status,
571*4882a593Smuzhiyun .driver_status = hdr->driver_status,
572*4882a593Smuzhiyun .resid = hdr->resid,
573*4882a593Smuzhiyun .duration = hdr->duration,
574*4882a593Smuzhiyun .info = hdr->info,
575*4882a593Smuzhiyun };
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun if (copy_to_user(argp, &hdr32, sizeof(hdr32)))
578*4882a593Smuzhiyun return -EFAULT;
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun return 0;
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun #endif
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun if (copy_to_user(argp, hdr, sizeof(*hdr)))
585*4882a593Smuzhiyun return -EFAULT;
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun return 0;
588*4882a593Smuzhiyun }
589*4882a593Smuzhiyun EXPORT_SYMBOL(put_sg_io_hdr);
590*4882a593Smuzhiyun
get_sg_io_hdr(struct sg_io_hdr * hdr,const void __user * argp)591*4882a593Smuzhiyun int get_sg_io_hdr(struct sg_io_hdr *hdr, const void __user *argp)
592*4882a593Smuzhiyun {
593*4882a593Smuzhiyun #ifdef CONFIG_COMPAT
594*4882a593Smuzhiyun struct compat_sg_io_hdr hdr32;
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun if (in_compat_syscall()) {
597*4882a593Smuzhiyun if (copy_from_user(&hdr32, argp, sizeof(hdr32)))
598*4882a593Smuzhiyun return -EFAULT;
599*4882a593Smuzhiyun
600*4882a593Smuzhiyun *hdr = (struct sg_io_hdr) {
601*4882a593Smuzhiyun .interface_id = hdr32.interface_id,
602*4882a593Smuzhiyun .dxfer_direction = hdr32.dxfer_direction,
603*4882a593Smuzhiyun .cmd_len = hdr32.cmd_len,
604*4882a593Smuzhiyun .mx_sb_len = hdr32.mx_sb_len,
605*4882a593Smuzhiyun .iovec_count = hdr32.iovec_count,
606*4882a593Smuzhiyun .dxfer_len = hdr32.dxfer_len,
607*4882a593Smuzhiyun .dxferp = compat_ptr(hdr32.dxferp),
608*4882a593Smuzhiyun .cmdp = compat_ptr(hdr32.cmdp),
609*4882a593Smuzhiyun .sbp = compat_ptr(hdr32.sbp),
610*4882a593Smuzhiyun .timeout = hdr32.timeout,
611*4882a593Smuzhiyun .flags = hdr32.flags,
612*4882a593Smuzhiyun .pack_id = hdr32.pack_id,
613*4882a593Smuzhiyun .usr_ptr = compat_ptr(hdr32.usr_ptr),
614*4882a593Smuzhiyun .status = hdr32.status,
615*4882a593Smuzhiyun .masked_status = hdr32.masked_status,
616*4882a593Smuzhiyun .msg_status = hdr32.msg_status,
617*4882a593Smuzhiyun .sb_len_wr = hdr32.sb_len_wr,
618*4882a593Smuzhiyun .host_status = hdr32.host_status,
619*4882a593Smuzhiyun .driver_status = hdr32.driver_status,
620*4882a593Smuzhiyun .resid = hdr32.resid,
621*4882a593Smuzhiyun .duration = hdr32.duration,
622*4882a593Smuzhiyun .info = hdr32.info,
623*4882a593Smuzhiyun };
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun return 0;
626*4882a593Smuzhiyun }
627*4882a593Smuzhiyun #endif
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun if (copy_from_user(hdr, argp, sizeof(*hdr)))
630*4882a593Smuzhiyun return -EFAULT;
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun return 0;
633*4882a593Smuzhiyun }
634*4882a593Smuzhiyun EXPORT_SYMBOL(get_sg_io_hdr);
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun #ifdef CONFIG_COMPAT
637*4882a593Smuzhiyun struct compat_cdrom_generic_command {
638*4882a593Smuzhiyun unsigned char cmd[CDROM_PACKET_SIZE];
639*4882a593Smuzhiyun compat_caddr_t buffer;
640*4882a593Smuzhiyun compat_uint_t buflen;
641*4882a593Smuzhiyun compat_int_t stat;
642*4882a593Smuzhiyun compat_caddr_t sense;
643*4882a593Smuzhiyun unsigned char data_direction;
644*4882a593Smuzhiyun unsigned char pad[3];
645*4882a593Smuzhiyun compat_int_t quiet;
646*4882a593Smuzhiyun compat_int_t timeout;
647*4882a593Smuzhiyun compat_caddr_t unused;
648*4882a593Smuzhiyun };
649*4882a593Smuzhiyun #endif
650*4882a593Smuzhiyun
scsi_get_cdrom_generic_arg(struct cdrom_generic_command * cgc,const void __user * arg)651*4882a593Smuzhiyun static int scsi_get_cdrom_generic_arg(struct cdrom_generic_command *cgc,
652*4882a593Smuzhiyun const void __user *arg)
653*4882a593Smuzhiyun {
654*4882a593Smuzhiyun #ifdef CONFIG_COMPAT
655*4882a593Smuzhiyun if (in_compat_syscall()) {
656*4882a593Smuzhiyun struct compat_cdrom_generic_command cgc32;
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun if (copy_from_user(&cgc32, arg, sizeof(cgc32)))
659*4882a593Smuzhiyun return -EFAULT;
660*4882a593Smuzhiyun
661*4882a593Smuzhiyun *cgc = (struct cdrom_generic_command) {
662*4882a593Smuzhiyun .buffer = compat_ptr(cgc32.buffer),
663*4882a593Smuzhiyun .buflen = cgc32.buflen,
664*4882a593Smuzhiyun .stat = cgc32.stat,
665*4882a593Smuzhiyun .sense = compat_ptr(cgc32.sense),
666*4882a593Smuzhiyun .data_direction = cgc32.data_direction,
667*4882a593Smuzhiyun .quiet = cgc32.quiet,
668*4882a593Smuzhiyun .timeout = cgc32.timeout,
669*4882a593Smuzhiyun .unused = compat_ptr(cgc32.unused),
670*4882a593Smuzhiyun };
671*4882a593Smuzhiyun memcpy(&cgc->cmd, &cgc32.cmd, CDROM_PACKET_SIZE);
672*4882a593Smuzhiyun return 0;
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun #endif
675*4882a593Smuzhiyun if (copy_from_user(cgc, arg, sizeof(*cgc)))
676*4882a593Smuzhiyun return -EFAULT;
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun return 0;
679*4882a593Smuzhiyun }
680*4882a593Smuzhiyun
scsi_put_cdrom_generic_arg(const struct cdrom_generic_command * cgc,void __user * arg)681*4882a593Smuzhiyun static int scsi_put_cdrom_generic_arg(const struct cdrom_generic_command *cgc,
682*4882a593Smuzhiyun void __user *arg)
683*4882a593Smuzhiyun {
684*4882a593Smuzhiyun #ifdef CONFIG_COMPAT
685*4882a593Smuzhiyun if (in_compat_syscall()) {
686*4882a593Smuzhiyun struct compat_cdrom_generic_command cgc32 = {
687*4882a593Smuzhiyun .buffer = (uintptr_t)(cgc->buffer),
688*4882a593Smuzhiyun .buflen = cgc->buflen,
689*4882a593Smuzhiyun .stat = cgc->stat,
690*4882a593Smuzhiyun .sense = (uintptr_t)(cgc->sense),
691*4882a593Smuzhiyun .data_direction = cgc->data_direction,
692*4882a593Smuzhiyun .quiet = cgc->quiet,
693*4882a593Smuzhiyun .timeout = cgc->timeout,
694*4882a593Smuzhiyun .unused = (uintptr_t)(cgc->unused),
695*4882a593Smuzhiyun };
696*4882a593Smuzhiyun memcpy(&cgc32.cmd, &cgc->cmd, CDROM_PACKET_SIZE);
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun if (copy_to_user(arg, &cgc32, sizeof(cgc32)))
699*4882a593Smuzhiyun return -EFAULT;
700*4882a593Smuzhiyun
701*4882a593Smuzhiyun return 0;
702*4882a593Smuzhiyun }
703*4882a593Smuzhiyun #endif
704*4882a593Smuzhiyun if (copy_to_user(arg, cgc, sizeof(*cgc)))
705*4882a593Smuzhiyun return -EFAULT;
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun return 0;
708*4882a593Smuzhiyun }
709*4882a593Smuzhiyun
scsi_cdrom_send_packet(struct request_queue * q,struct gendisk * bd_disk,fmode_t mode,void __user * arg)710*4882a593Smuzhiyun static int scsi_cdrom_send_packet(struct request_queue *q,
711*4882a593Smuzhiyun struct gendisk *bd_disk,
712*4882a593Smuzhiyun fmode_t mode, void __user *arg)
713*4882a593Smuzhiyun {
714*4882a593Smuzhiyun struct cdrom_generic_command cgc;
715*4882a593Smuzhiyun struct sg_io_hdr hdr;
716*4882a593Smuzhiyun int err;
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun err = scsi_get_cdrom_generic_arg(&cgc, arg);
719*4882a593Smuzhiyun if (err)
720*4882a593Smuzhiyun return err;
721*4882a593Smuzhiyun
722*4882a593Smuzhiyun cgc.timeout = clock_t_to_jiffies(cgc.timeout);
723*4882a593Smuzhiyun memset(&hdr, 0, sizeof(hdr));
724*4882a593Smuzhiyun hdr.interface_id = 'S';
725*4882a593Smuzhiyun hdr.cmd_len = sizeof(cgc.cmd);
726*4882a593Smuzhiyun hdr.dxfer_len = cgc.buflen;
727*4882a593Smuzhiyun switch (cgc.data_direction) {
728*4882a593Smuzhiyun case CGC_DATA_UNKNOWN:
729*4882a593Smuzhiyun hdr.dxfer_direction = SG_DXFER_UNKNOWN;
730*4882a593Smuzhiyun break;
731*4882a593Smuzhiyun case CGC_DATA_WRITE:
732*4882a593Smuzhiyun hdr.dxfer_direction = SG_DXFER_TO_DEV;
733*4882a593Smuzhiyun break;
734*4882a593Smuzhiyun case CGC_DATA_READ:
735*4882a593Smuzhiyun hdr.dxfer_direction = SG_DXFER_FROM_DEV;
736*4882a593Smuzhiyun break;
737*4882a593Smuzhiyun case CGC_DATA_NONE:
738*4882a593Smuzhiyun hdr.dxfer_direction = SG_DXFER_NONE;
739*4882a593Smuzhiyun break;
740*4882a593Smuzhiyun default:
741*4882a593Smuzhiyun return -EINVAL;
742*4882a593Smuzhiyun }
743*4882a593Smuzhiyun
744*4882a593Smuzhiyun hdr.dxferp = cgc.buffer;
745*4882a593Smuzhiyun hdr.sbp = cgc.sense;
746*4882a593Smuzhiyun if (hdr.sbp)
747*4882a593Smuzhiyun hdr.mx_sb_len = sizeof(struct request_sense);
748*4882a593Smuzhiyun hdr.timeout = jiffies_to_msecs(cgc.timeout);
749*4882a593Smuzhiyun hdr.cmdp = ((struct cdrom_generic_command __user*) arg)->cmd;
750*4882a593Smuzhiyun hdr.cmd_len = sizeof(cgc.cmd);
751*4882a593Smuzhiyun
752*4882a593Smuzhiyun err = sg_io(q, bd_disk, &hdr, mode);
753*4882a593Smuzhiyun if (err == -EFAULT)
754*4882a593Smuzhiyun return -EFAULT;
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun if (hdr.status)
757*4882a593Smuzhiyun return -EIO;
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun cgc.stat = err;
760*4882a593Smuzhiyun cgc.buflen = hdr.resid;
761*4882a593Smuzhiyun if (scsi_put_cdrom_generic_arg(&cgc, arg))
762*4882a593Smuzhiyun return -EFAULT;
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun return err;
765*4882a593Smuzhiyun }
766*4882a593Smuzhiyun
scsi_cmd_ioctl(struct request_queue * q,struct gendisk * bd_disk,fmode_t mode,unsigned int cmd,void __user * arg)767*4882a593Smuzhiyun int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mode,
768*4882a593Smuzhiyun unsigned int cmd, void __user *arg)
769*4882a593Smuzhiyun {
770*4882a593Smuzhiyun int err;
771*4882a593Smuzhiyun
772*4882a593Smuzhiyun if (!q)
773*4882a593Smuzhiyun return -ENXIO;
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun switch (cmd) {
776*4882a593Smuzhiyun /*
777*4882a593Smuzhiyun * new sgv3 interface
778*4882a593Smuzhiyun */
779*4882a593Smuzhiyun case SG_GET_VERSION_NUM:
780*4882a593Smuzhiyun err = sg_get_version(arg);
781*4882a593Smuzhiyun break;
782*4882a593Smuzhiyun case SCSI_IOCTL_GET_IDLUN:
783*4882a593Smuzhiyun err = scsi_get_idlun(q, arg);
784*4882a593Smuzhiyun break;
785*4882a593Smuzhiyun case SCSI_IOCTL_GET_BUS_NUMBER:
786*4882a593Smuzhiyun err = scsi_get_bus(q, arg);
787*4882a593Smuzhiyun break;
788*4882a593Smuzhiyun case SG_SET_TIMEOUT:
789*4882a593Smuzhiyun err = sg_set_timeout(q, arg);
790*4882a593Smuzhiyun break;
791*4882a593Smuzhiyun case SG_GET_TIMEOUT:
792*4882a593Smuzhiyun err = sg_get_timeout(q);
793*4882a593Smuzhiyun break;
794*4882a593Smuzhiyun case SG_GET_RESERVED_SIZE:
795*4882a593Smuzhiyun err = sg_get_reserved_size(q, arg);
796*4882a593Smuzhiyun break;
797*4882a593Smuzhiyun case SG_SET_RESERVED_SIZE:
798*4882a593Smuzhiyun err = sg_set_reserved_size(q, arg);
799*4882a593Smuzhiyun break;
800*4882a593Smuzhiyun case SG_EMULATED_HOST:
801*4882a593Smuzhiyun err = sg_emulated_host(q, arg);
802*4882a593Smuzhiyun break;
803*4882a593Smuzhiyun case SG_IO: {
804*4882a593Smuzhiyun struct sg_io_hdr hdr;
805*4882a593Smuzhiyun
806*4882a593Smuzhiyun err = get_sg_io_hdr(&hdr, arg);
807*4882a593Smuzhiyun if (err)
808*4882a593Smuzhiyun break;
809*4882a593Smuzhiyun err = sg_io(q, bd_disk, &hdr, mode);
810*4882a593Smuzhiyun if (err == -EFAULT)
811*4882a593Smuzhiyun break;
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun if (put_sg_io_hdr(&hdr, arg))
814*4882a593Smuzhiyun err = -EFAULT;
815*4882a593Smuzhiyun break;
816*4882a593Smuzhiyun }
817*4882a593Smuzhiyun case CDROM_SEND_PACKET:
818*4882a593Smuzhiyun err = scsi_cdrom_send_packet(q, bd_disk, mode, arg);
819*4882a593Smuzhiyun break;
820*4882a593Smuzhiyun
821*4882a593Smuzhiyun /*
822*4882a593Smuzhiyun * old junk scsi send command ioctl
823*4882a593Smuzhiyun */
824*4882a593Smuzhiyun case SCSI_IOCTL_SEND_COMMAND:
825*4882a593Smuzhiyun printk(KERN_WARNING "program %s is using a deprecated SCSI ioctl, please convert it to SG_IO\n", current->comm);
826*4882a593Smuzhiyun err = -EINVAL;
827*4882a593Smuzhiyun if (!arg)
828*4882a593Smuzhiyun break;
829*4882a593Smuzhiyun
830*4882a593Smuzhiyun err = sg_scsi_ioctl(q, bd_disk, mode, arg);
831*4882a593Smuzhiyun break;
832*4882a593Smuzhiyun case CDROMCLOSETRAY:
833*4882a593Smuzhiyun err = blk_send_start_stop(q, bd_disk, 0x03);
834*4882a593Smuzhiyun break;
835*4882a593Smuzhiyun case CDROMEJECT:
836*4882a593Smuzhiyun err = blk_send_start_stop(q, bd_disk, 0x02);
837*4882a593Smuzhiyun break;
838*4882a593Smuzhiyun default:
839*4882a593Smuzhiyun err = -ENOTTY;
840*4882a593Smuzhiyun }
841*4882a593Smuzhiyun
842*4882a593Smuzhiyun return err;
843*4882a593Smuzhiyun }
844*4882a593Smuzhiyun EXPORT_SYMBOL(scsi_cmd_ioctl);
845*4882a593Smuzhiyun
scsi_verify_blk_ioctl(struct block_device * bd,unsigned int cmd)846*4882a593Smuzhiyun int scsi_verify_blk_ioctl(struct block_device *bd, unsigned int cmd)
847*4882a593Smuzhiyun {
848*4882a593Smuzhiyun if (bd && !bdev_is_partition(bd))
849*4882a593Smuzhiyun return 0;
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun if (capable(CAP_SYS_RAWIO))
852*4882a593Smuzhiyun return 0;
853*4882a593Smuzhiyun
854*4882a593Smuzhiyun return -ENOIOCTLCMD;
855*4882a593Smuzhiyun }
856*4882a593Smuzhiyun EXPORT_SYMBOL(scsi_verify_blk_ioctl);
857*4882a593Smuzhiyun
scsi_cmd_blk_ioctl(struct block_device * bd,fmode_t mode,unsigned int cmd,void __user * arg)858*4882a593Smuzhiyun int scsi_cmd_blk_ioctl(struct block_device *bd, fmode_t mode,
859*4882a593Smuzhiyun unsigned int cmd, void __user *arg)
860*4882a593Smuzhiyun {
861*4882a593Smuzhiyun int ret;
862*4882a593Smuzhiyun
863*4882a593Smuzhiyun ret = scsi_verify_blk_ioctl(bd, cmd);
864*4882a593Smuzhiyun if (ret < 0)
865*4882a593Smuzhiyun return ret;
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun return scsi_cmd_ioctl(bd->bd_disk->queue, bd->bd_disk, mode, cmd, arg);
868*4882a593Smuzhiyun }
869*4882a593Smuzhiyun EXPORT_SYMBOL(scsi_cmd_blk_ioctl);
870*4882a593Smuzhiyun
871*4882a593Smuzhiyun /**
872*4882a593Smuzhiyun * scsi_req_init - initialize certain fields of a scsi_request structure
873*4882a593Smuzhiyun * @req: Pointer to a scsi_request structure.
874*4882a593Smuzhiyun * Initializes .__cmd[], .cmd, .cmd_len and .sense_len but no other members
875*4882a593Smuzhiyun * of struct scsi_request.
876*4882a593Smuzhiyun */
scsi_req_init(struct scsi_request * req)877*4882a593Smuzhiyun void scsi_req_init(struct scsi_request *req)
878*4882a593Smuzhiyun {
879*4882a593Smuzhiyun memset(req->__cmd, 0, sizeof(req->__cmd));
880*4882a593Smuzhiyun req->cmd = req->__cmd;
881*4882a593Smuzhiyun req->cmd_len = BLK_MAX_CDB;
882*4882a593Smuzhiyun req->sense_len = 0;
883*4882a593Smuzhiyun }
884*4882a593Smuzhiyun EXPORT_SYMBOL(scsi_req_init);
885*4882a593Smuzhiyun
blk_scsi_ioctl_init(void)886*4882a593Smuzhiyun static int __init blk_scsi_ioctl_init(void)
887*4882a593Smuzhiyun {
888*4882a593Smuzhiyun blk_set_cmd_filter_defaults(&blk_default_cmd_filter);
889*4882a593Smuzhiyun return 0;
890*4882a593Smuzhiyun }
891*4882a593Smuzhiyun fs_initcall(blk_scsi_ioctl_init);
892