Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/cpqary3/cpqary3_ioctl.c
+++ new/usr/src/uts/common/io/cpqary3/cpqary3_ioctl.c
1 1 /*
2 2 * This file and its contents are supplied under the terms of the
3 3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 4 * You may only use this file in accordance with the terms of version
5 5 * 1.0 of the CDDL.
6 6 *
7 7 * A full copy of the text of the CDDL should have accompanied this
8 8 * source. A copy of the CDDL is also available via the Internet at
9 9 * http://www.illumos.org/license/CDDL.
10 10 */
11 11
12 12 /*
13 13 * Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
14 14 */
15 15
16 16 /*
17 17 * Supported IOCTLs :
18 18 * CPQARY3_IOCTL_DRIVER_INFO - to get driver details
19 19 * CPQARY3_IOCTL_CTLR_INFO - to get controller details
20 20 * CPQARY3_IOCTL_BMIC_PASS - to pass BMIC commands
21 21 * CPQARY3_IOCTL_SCSI_PASS - to pass SCSI commands
22 22 */
23 23
24 24 #include "cpqary3.h"
25 25
26 26 /*
27 27 * Local Functions Declaration
28 28 */
29 29
30 30 static int32_t cpqary3_ioctl_send_bmiccmd(cpqary3_t *, cpqary3_bmic_pass_t *,
31 31 int);
↓ open down ↓ |
31 lines elided |
↑ open up ↑ |
32 32 static void cpqary3_ioctl_fil_bmic(CommandList_t *, cpqary3_bmic_pass_t *);
33 33 static void cpqary3_ioctl_fil_bmic_sas(CommandList_t *, cpqary3_bmic_pass_t *);
34 34 static int32_t cpqary3_ioctl_send_scsicmd(cpqary3_t *, cpqary3_scsi_pass_t *,
35 35 int);
36 36 static void cpqary3_ioctl_fil_scsi(CommandList_t *, cpqary3_scsi_pass_t *);
37 37
38 38 /*
39 39 * Global Variables Definitions
40 40 */
41 41
42 -cpqary3_driver_info_t gdriver_info = {0};
42 +cpqary3_driver_info_t gdriver_info = {{0}};
43 43
44 44 /* Function Definitions */
45 45
46 46 /*
47 47 * Function : cpqary3_ioctl_driver_info
48 48 * Description : This routine will get major/ minor versions, Number of
49 49 * controllers detected & MAX Number of controllers
50 50 * supported
51 51 * Called By : cpqary3_ioctl
52 52 * Parameters : ioctl_reqp - address of the parameter sent from
53 53 * the application
54 54 * cpqary3p - address of the PerController structure
55 55 * mode - mode which comes from application
56 56 * Return Values: EFAULT on Failure, 0 on SUCCESS
57 57 */
58 58 int32_t
59 59 cpqary3_ioctl_driver_info(uintptr_t ioctl_reqp, int mode)
60 60 {
61 61 cpqary3_ioctl_request_t *request;
62 62
63 63 request = (cpqary3_ioctl_request_t *)
64 64 MEM_ZALLOC(sizeof (cpqary3_ioctl_request_t));
65 65
66 66 if (NULL == request)
67 67 return (FAILURE);
68 68
69 69 /*
70 70 * First let us copyin the ioctl_reqp user buffer to request(kernel)
71 71 * memory. This is very much recomended before we access any of the
72 72 * fields.
73 73 */
74 74 if (ddi_copyin((void *)ioctl_reqp, (void *)request,
75 75 sizeof (cpqary3_ioctl_request_t), mode)) {
76 76 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
77 77 return (EFAULT);
78 78 }
79 79
80 80 /*
81 81 * Fill up the global structure "gdriver_info" memory.
82 82 * Fill this structure with available info, which will be copied
83 83 * back later
84 84 */
85 85
86 86 (void) strcpy(gdriver_info.name, "cpqary3");
87 87 gdriver_info.version.minor = CPQARY3_MINOR_REV_NO;
88 88 gdriver_info.version.major = CPQARY3_MAJOR_REV_NO;
89 89 gdriver_info.version.dd = CPQARY3_REV_MONTH;
90 90 gdriver_info.version.mm = CPQARY3_REV_DATE;
91 91 gdriver_info.version.yyyy = CPQARY3_REV_YEAR;
92 92 gdriver_info.max_num_ctlr = MAX_CTLRS;
93 93
94 94 /*
95 95 * First Copy out the driver_info structure
96 96 */
97 97
98 98 if (ddi_copyout((void *)&gdriver_info, (void *)(uintptr_t)request->argp,
99 99 sizeof (cpqary3_driver_info_t), mode)) {
100 100 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
101 101 return (EFAULT);
102 102 }
103 103
104 104 /*
105 105 * Copy out the request structure back
106 106 */
107 107
108 108 if (ddi_copyout((void *)request, (void *)ioctl_reqp,
109 109 sizeof (cpqary3_ioctl_request_t), mode)) {
110 110 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
111 111 return (EFAULT);
112 112 }
113 113
114 114 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
115 115
116 116 /*
117 117 * Everything looks fine. So return SUCCESS
118 118 */
119 119
120 120 return (SUCCESS);
121 121 }
122 122
123 123 /*
124 124 * Function : cpqary3_ioctl_ctlr_info
125 125 * Description : This routine will get the controller related info, like
126 126 * board-id, subsystem-id, num of logical drives,
127 127 * slot number
128 128 * Called By : cpqary3_ioctl
129 129 * Parameters : ioctl_reqp - address of the parameter sent form the
130 130 * application
131 131 * cpqary3p - address of the PerController structure
132 132 * mode - mode which comes from application
133 133 * Return Values: EFAULT on Failure, 0 on SUCCESS
134 134 */
135 135 int32_t
136 136 cpqary3_ioctl_ctlr_info(uintptr_t ioctl_reqp, cpqary3_t *cpqary3p, int mode)
137 137 {
138 138 cpqary3_ioctl_request_t *request;
139 139 cpqary3_ctlr_info_t *ctlr_info;
140 140
141 141 request = (cpqary3_ioctl_request_t *)
142 142 MEM_ZALLOC(sizeof (cpqary3_ioctl_request_t));
143 143
144 144 if (NULL == request)
145 145 return (FAILURE);
146 146
147 147 /*
148 148 * First let us copyin the buffer to kernel memory. This is very much
149 149 * recomended before we access any of the fields.
150 150 */
151 151
152 152 if (ddi_copyin((void *) ioctl_reqp, (void *)request,
153 153 sizeof (cpqary3_ioctl_request_t), mode)) {
154 154 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
155 155 return (EFAULT);
156 156 }
157 157
158 158 ctlr_info = (cpqary3_ctlr_info_t *)
159 159 MEM_ZALLOC(sizeof (cpqary3_ctlr_info_t));
160 160
161 161 if (NULL == ctlr_info) {
162 162 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
163 163 return (FAILURE);
164 164 }
165 165
166 166 /*
167 167 * in the driver, board_id is actually subsystem_id
168 168 */
169 169
170 170 ctlr_info->subsystem_id = cpqary3p->board_id;
171 171 ctlr_info->bus = cpqary3p->bus;
172 172 ctlr_info->dev = cpqary3p->dev;
173 173 ctlr_info->fun = cpqary3p->fun;
174 174 ctlr_info->num_of_tgts = cpqary3p->num_of_targets;
175 175 ctlr_info->controller_instance = cpqary3p->instance;
176 176
177 177 /*
178 178 * TODO: ctlr_info.slot_num has to be implemented
179 179 * state & board_id fields are kept for future implementation i
180 180 * if required!
181 181 */
182 182
183 183 /*
184 184 * First Copy out the ctlr_info structure
185 185 */
186 186
187 187 if (ddi_copyout((void *)ctlr_info, (void *)(uintptr_t)request->argp,
188 188 sizeof (cpqary3_ctlr_info_t), mode)) {
189 189 MEM_SFREE(ctlr_info, sizeof (cpqary3_ctlr_info_t));
190 190 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
191 191 return (EFAULT);
192 192 }
193 193
194 194 /*
195 195 * Copy out the request structure back
196 196 */
197 197
198 198 if (ddi_copyout((void *)request, (void *)ioctl_reqp,
199 199 sizeof (cpqary3_ioctl_request_t), mode)) {
200 200 MEM_SFREE(ctlr_info, sizeof (cpqary3_ctlr_info_t));
201 201 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
202 202 return (EFAULT);
203 203 }
204 204
205 205 MEM_SFREE(ctlr_info, sizeof (cpqary3_ctlr_info_t));
206 206 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
207 207
208 208 /*
209 209 * Everything looks fine. So return SUCCESS
210 210 */
211 211
212 212 return (SUCCESS);
213 213 }
214 214
215 215 /*
216 216 * Function : cpqary3_ioctl_bmic_pass
217 217 * Description : This routine will pass the BMIC commands to controller
218 218 * Called By : cpqary3_ioctl
219 219 * Parameters : ioctl_reqp - address of the parameter sent from the
220 220 * application
221 221 * cpqary3p - address of the PerController structure
222 222 * mode - mode which comes directly from application
223 223 * Return Values: EFAULT on Failure, 0 on SUCCESS
224 224 */
225 225 int32_t
226 226 cpqary3_ioctl_bmic_pass(uintptr_t ioctl_reqp, cpqary3_t *cpqary3p, int mode)
227 227 {
228 228 cpqary3_ioctl_request_t *request;
229 229 cpqary3_bmic_pass_t *bmic_pass;
230 230 int32_t retval = SUCCESS;
231 231
232 232 request = (cpqary3_ioctl_request_t *)
233 233 MEM_ZALLOC(sizeof (cpqary3_ioctl_request_t));
234 234
235 235 if (NULL == request)
236 236 return (FAILURE);
237 237
238 238 /*
239 239 * First let us copyin the ioctl_reqp(user) buffer to request(kernel)
240 240 * memory. This is very much recommended before we access any of the
241 241 * fields.
242 242 */
243 243
244 244 if (ddi_copyin((void *)ioctl_reqp, (void *)request,
245 245 sizeof (cpqary3_ioctl_request_t), mode)) {
246 246 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
247 247 return (EFAULT);
248 248 }
249 249
250 250 bmic_pass = (cpqary3_bmic_pass_t *)
251 251 MEM_ZALLOC(sizeof (cpqary3_bmic_pass_t));
252 252
253 253 if (NULL == bmic_pass) {
254 254 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
255 255 return (FAILURE);
256 256 }
257 257
258 258 /*
259 259 * Copy in "cpqary3_bmic_pass_t" structure from argp member
260 260 * of ioctl_reqp.
261 261 */
262 262
263 263 if (ddi_copyin((void *)(uintptr_t)request->argp, (void *)bmic_pass,
264 264 sizeof (cpqary3_bmic_pass_t), mode)) {
265 265 MEM_SFREE(bmic_pass, sizeof (cpqary3_bmic_pass_t));
266 266 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
267 267 return (EFAULT);
268 268 }
269 269
270 270 /*
271 271 * Get the free command list, fill in the bmic command and send it
272 272 * to the controller. This will return 0 on success.
273 273 */
274 274
275 275 retval = cpqary3_ioctl_send_bmiccmd(cpqary3p, bmic_pass, mode);
276 276
277 277 /*
278 278 * Now copy the bmic_pass (kernel) to the user argp
279 279 */
280 280
281 281 if (ddi_copyout((void *) bmic_pass, (void *)(uintptr_t)request->argp,
282 282 sizeof (cpqary3_bmic_pass_t), mode)) {
283 283 MEM_SFREE(bmic_pass, sizeof (cpqary3_bmic_pass_t));
284 284 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
285 285 retval = EFAULT; /* copyout failed */
286 286 }
287 287
288 288 /*
289 289 * Now copy the request(kernel) to ioctl_reqp(user)
290 290 */
291 291
292 292 if (ddi_copyout((void *) request, (void *)ioctl_reqp,
293 293 sizeof (cpqary3_ioctl_request_t), mode)) {
294 294 MEM_SFREE(bmic_pass, sizeof (cpqary3_bmic_pass_t));
295 295 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
296 296 retval = EFAULT;
297 297 }
298 298
299 299 MEM_SFREE(bmic_pass, sizeof (cpqary3_bmic_pass_t));
300 300 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
301 301
302 302 return (retval);
303 303 }
304 304
305 305 /*
306 306 * Function : cpqary3_ioctl_send_bmiccmd
307 307 * Description : This routine will get the free command,
308 308 * allocate memory and send it to controller.
309 309 * Called By : cpqary3_ioctl_bmic_pass
310 310 * Parameters : cpqary3_t - PerController structure
311 311 * cpqary3_bmic_pass_t - bmic structure
312 312 * mode - mode value sent from application
313 313 * Return Values: 0 on success
314 314 * FAILURE, EFAULT, ETIMEOUT based on the failure
315 315 */
316 316
317 317 uint32_t cpqary3_ioctl_wait_ms = 30000;
318 318
319 319 static int32_t
320 320 cpqary3_ioctl_send_bmiccmd(cpqary3_t *cpqary3p,
321 321 cpqary3_bmic_pass_t *bmic_pass, int mode)
322 322 {
323 323 cpqary3_cmdpvt_t *memp = NULL;
324 324 CommandList_t *cmdlist = NULL;
325 325 int8_t *databuf = NULL;
326 326 uint8_t retval = 0;
327 327
328 328 /* allocate a command with a dma buffer */
329 329 memp = cpqary3_synccmd_alloc(cpqary3p, bmic_pass->buf_len);
330 330 if (memp == NULL)
331 331 return (FAILURE);
332 332
333 333 /* Get the databuf when buf_len is greater than zero */
334 334 if (bmic_pass->buf_len > 0) {
335 335 databuf = memp->driverdata->sg;
336 336 }
337 337
338 338 cmdlist = memp->cmdlist_memaddr;
339 339
340 340 /*
341 341 * If io_direction is CPQARY3_SCSI_OUT, we have to copy user buffer
342 342 * to databuf
343 343 */
344 344
345 345 if (bmic_pass->io_direction == CPQARY3_SCSI_OUT) {
346 346 /* Do a copyin when buf_len is greater than zero */
347 347 if (bmic_pass->buf_len > 0) {
348 348 if (ddi_copyin((void*)(uintptr_t)(bmic_pass->buf),
349 349 (void*)databuf, bmic_pass->buf_len, mode)) {
350 350 cpqary3_synccmd_free(cpqary3p, memp);
351 351 return (EFAULT);
352 352 }
353 353 }
354 354 }
355 355
356 356 /*
357 357 * Now fill the command as per the BMIC
358 358 */
359 359 if (cpqary3p->bddef->bd_flags & SA_BD_SAS) {
360 360 cpqary3_ioctl_fil_bmic_sas(cmdlist, bmic_pass);
361 361 } else {
362 362 cpqary3_ioctl_fil_bmic(cmdlist, bmic_pass);
363 363 }
364 364
365 365
366 366 /* PERF */
367 367
368 368 memp->complete = cpqary3_synccmd_complete;
369 369
370 370 /* PERF */
371 371
372 372 /* send command to controller and wait for a reply */
373 373 if (cpqary3_synccmd_send(cpqary3p, memp, cpqary3_ioctl_wait_ms,
374 374 CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
375 375 cpqary3_synccmd_free(cpqary3p, memp);
376 376 return (ETIMEDOUT);
377 377 }
378 378
379 379 /*
380 380 * Now the command is completed and copy the buffers back
381 381 * First copy the buffer databuf to bmic_pass.buf
382 382 * which is used as a buffer before passing the command to the
383 383 * controller.
384 384 */
385 385
386 386 if (bmic_pass->io_direction == CPQARY3_SCSI_IN) {
387 387 /* Do a copyout when buf_len is greater than zero */
388 388 if (bmic_pass->buf_len > 0) {
389 389 if (ddi_copyout((void *)databuf,
390 390 (void *)(uintptr_t)bmic_pass->buf,
391 391 bmic_pass->buf_len, mode)) {
392 392 retval = EFAULT;
393 393 }
394 394 }
395 395 }
396 396
397 397 /*
398 398 * This is case where the command completes with error,
399 399 * Then tag would have set its 1st(10) bit.
400 400 */
401 401
402 402 if (cmdlist->Header.Tag.drvinfo_n_err == CPQARY3_SYNCCMD_FAILURE) {
403 403 bmic_pass->err_status = 1;
404 404 bcopy((caddr_t)memp->errorinfop, &bmic_pass->err_info,
405 405 sizeof (ErrorInfo_t));
406 406 switch (memp->errorinfop->CommandStatus) {
407 407 case CISS_CMD_DATA_OVERRUN :
408 408 case CISS_CMD_DATA_UNDERRUN :
409 409 case CISS_CMD_SUCCESS :
410 410 case CISS_CMD_TARGET_STATUS :
411 411 retval = SUCCESS;
412 412 break;
413 413 default :
414 414 retval = EIO;
415 415 break;
416 416 }
417 417 }
418 418
419 419 cpqary3_synccmd_free(cpqary3p, memp);
420 420
421 421 return (retval);
422 422 }
423 423
424 424 /*
425 425 * Function : cpqary3_ioctl_fil_bmic
426 426 * Description : This routine will fill the cmdlist with BMIC details
427 427 * Called By : cpqary3_ioctl_send_bmiccmd
428 428 * Parameters : cmdlist - command packet
429 429 * bmic_pass - bmic structure
430 430 * Return Values: void
431 431 */
432 432 static void
433 433 cpqary3_ioctl_fil_bmic(CommandList_t *cmdlist,
434 434 cpqary3_bmic_pass_t *bmic_pass)
435 435 {
436 436 cmdlist->Header.SGTotal = 1;
437 437 cmdlist->Header.SGList = 1;
438 438 cmdlist->Request.CDBLen = bmic_pass->cmd_len;
439 439 cmdlist->Request.Timeout = bmic_pass->timeout;
440 440 cmdlist->Request.Type.Type = CISS_TYPE_CMD;
441 441 cmdlist->Request.Type.Attribute = CISS_ATTR_HEADOFQUEUE;
442 442
443 443 switch (bmic_pass->io_direction) {
444 444 case CPQARY3_SCSI_OUT:
445 445 cmdlist->Request.Type.Direction = CISS_XFER_WRITE;
446 446 break;
447 447 case CPQARY3_SCSI_IN:
448 448 cmdlist->Request.Type.Direction = CISS_XFER_READ;
449 449 break;
450 450 case CPQARY3_NODATA_XFER:
451 451 cmdlist->Request.Type.Direction = CISS_XFER_NONE;
452 452 break;
453 453 default:
454 454 cmdlist->Request.Type.Direction = CISS_XFER_RSVD;
455 455 break;
456 456 }
457 457
458 458 cmdlist ->Request.CDB[0] =
459 459 (bmic_pass->io_direction == CPQARY3_SCSI_IN) ? 0x26: 0x27;
460 460 cmdlist ->Request.CDB[1] = bmic_pass->unit_number; /* Unit Number */
461 461
462 462 /*
463 463 * BMIC Detail - bytes 2[MSB] to 5[LSB]
464 464 */
465 465
466 466 cmdlist->Request.CDB[2] = (bmic_pass->blk_number >> 24) & 0xff;
467 467 cmdlist->Request.CDB[3] = (bmic_pass->blk_number >> 16) & 0xff;
468 468 cmdlist->Request.CDB[4] = (bmic_pass->blk_number >> 8) & 0xff;
469 469 cmdlist->Request.CDB[5] = bmic_pass->blk_number;
470 470
471 471 cmdlist->Request.CDB[6] = bmic_pass->cmd; /* BMIC Command */
472 472
473 473 /* Transfer Length - bytes 7[MSB] to 8[LSB] */
474 474
475 475 cmdlist->Request.CDB[7] = (bmic_pass->buf_len >> 8) & 0xff;
476 476 cmdlist->Request.CDB[8] = bmic_pass->buf_len & 0xff;
477 477 cmdlist->Request.CDB[9] = 0x00; /* Reserved */
478 478
479 479 /*
480 480 * Copy the Lun address from the request
481 481 */
482 482
483 483 bcopy(&bmic_pass->lun_addr[0], &(cmdlist->Header.LUN),
484 484 sizeof (LUNAddr_t));
485 485 cmdlist->SG[0].Len = bmic_pass->buf_len;
486 486 }
487 487
488 488 /*
489 489 * Function : cpqary3_ioctl_scsi_pass
490 490 * Description : This routine will pass the SCSI commands to controller
491 491 * Called By : cpqary3_ioctl
492 492 * Parameters : ioctl_reqp - address of the parameter sent
493 493 * from the application
494 494 * cpqary3p - Addess of the percontroller stucture
495 495 * mode - mode which comes directly from application
496 496 * Return Values: EFAULT on Failure, 0 on SUCCESS
497 497 */
498 498 int32_t
499 499 cpqary3_ioctl_scsi_pass(uintptr_t ioctl_reqp, cpqary3_t *cpqary3p, int mode)
500 500 {
501 501 cpqary3_ioctl_request_t *request;
502 502 cpqary3_scsi_pass_t *scsi_pass;
503 503 int32_t retval = SUCCESS;
504 504
505 505 request = (cpqary3_ioctl_request_t *)
506 506 MEM_ZALLOC(sizeof (cpqary3_ioctl_request_t));
507 507
508 508 if (NULL == request)
509 509 return (FAILURE);
510 510
511 511 /*
512 512 * First let us copyin the ioctl_reqp(user) buffer to request(kernel)
513 513 * memory. * This is very much recommended before we access any of
514 514 * the fields.
515 515 */
516 516
517 517 if (ddi_copyin((void *)ioctl_reqp, (void *)request,
518 518 sizeof (cpqary3_ioctl_request_t), mode)) {
519 519 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
520 520 return (EFAULT);
521 521 }
522 522
523 523 scsi_pass = (cpqary3_scsi_pass_t *)
524 524 MEM_ZALLOC(sizeof (cpqary3_scsi_pass_t));
525 525
526 526 if (NULL == scsi_pass) {
527 527 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
528 528 return (FAILURE);
529 529 }
530 530
531 531 /*
532 532 * Copy in "cpqary3_scsi_pass_t" structure from argp member
533 533 * of ioctl_reqp.
534 534 */
535 535
536 536 if (ddi_copyin((void *)(uintptr_t)request->argp, (void *)scsi_pass,
537 537 sizeof (cpqary3_scsi_pass_t), mode)) {
538 538 MEM_SFREE(scsi_pass, sizeof (cpqary3_scsi_pass_t));
539 539 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
540 540 return (EFAULT);
541 541 }
542 542
543 543 /*
544 544 * Get the free command list, fill in the scsi command and send it
545 545 * to the controller. This will return 0 on success.
546 546 */
547 547
548 548 retval = cpqary3_ioctl_send_scsicmd(cpqary3p, scsi_pass, mode);
549 549
550 550 /*
551 551 * Now copy the scsi_pass (kernel) to the user argp
552 552 */
553 553
554 554 if (ddi_copyout((void *)scsi_pass, (void *)(uintptr_t)request->argp,
555 555 sizeof (cpqary3_scsi_pass_t), mode)) {
556 556 MEM_SFREE(scsi_pass, sizeof (cpqary3_scsi_pass_t));
557 557 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
558 558 retval = EFAULT; /* copyout failed */
559 559 }
560 560
561 561 /*
562 562 * Now copy the request(kernel) to ioctl_reqp(user)
563 563 */
564 564
565 565 if (ddi_copyout((void *)request, (void *)ioctl_reqp,
566 566 sizeof (cpqary3_ioctl_request_t), mode)) {
567 567 MEM_SFREE(scsi_pass, sizeof (cpqary3_scsi_pass_t));
568 568 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
569 569 retval = EFAULT;
570 570 }
571 571
572 572 MEM_SFREE(scsi_pass, sizeof (cpqary3_scsi_pass_t));
573 573 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
574 574
575 575 return (retval);
576 576 }
577 577
578 578 /*
579 579 * Function : cpqary3_ioctl_send_scsiccmd
580 580 * Description : This routine will pass the SCSI commands to controller
581 581 * Called By : cpqary3_ioctl_scsi_pass
582 582 * Parameters : cpqary3_t - PerController structure,
583 583 * cpqary3_scsi_pass_t - scsi parameter
584 584 * mode - sent from the application
585 585 * Return Values: 0 on success
586 586 * FAILURE, EFAULT, ETIMEOUT based on the failure
587 587 */
588 588 static int32_t
589 589 cpqary3_ioctl_send_scsicmd(cpqary3_t *cpqary3p,
590 590 cpqary3_scsi_pass_t *scsi_pass, int mode)
591 591 {
592 592 cpqary3_cmdpvt_t *memp = NULL;
593 593 CommandList_t *cmdlist = NULL;
594 594 int8_t *databuf = NULL;
595 595 uint8_t retval = 0;
596 596 NoeBuffer *evt;
597 597 uint16_t drive = 0;
598 598
599 599 /* allocate a command with a dma buffer */
600 600 memp = cpqary3_synccmd_alloc(cpqary3p, scsi_pass->buf_len);
601 601 if (memp == NULL)
602 602 return (FAILURE);
603 603
604 604 /* Get the databuf when buf_len is greater than zero */
605 605 if (scsi_pass->buf_len > 0) {
606 606 databuf = memp->driverdata->sg;
607 607 }
608 608
609 609 cmdlist = memp->cmdlist_memaddr;
610 610
611 611 if (scsi_pass->io_direction == CPQARY3_SCSI_OUT) {
612 612 /* Do a copyin when buf_len is greater than zero */
613 613 if (scsi_pass->buf_len > 0) {
614 614 if (ddi_copyin((void*)(uintptr_t)(scsi_pass->buf),
615 615 (void*)databuf, scsi_pass->buf_len, mode)) {
616 616 cpqary3_synccmd_free(cpqary3p, memp);
617 617 return (EFAULT);
618 618 }
619 619 }
620 620 }
621 621
622 622 /*
623 623 * Fill the scsi command
624 624 */
625 625 cpqary3_ioctl_fil_scsi(cmdlist, scsi_pass);
626 626
627 627 /* PERF */
628 628 memp->complete = cpqary3_synccmd_complete;
629 629 /* PERF */
630 630
631 631 /* send command to controller and wait for a reply */
632 632 if (cpqary3_synccmd_send(cpqary3p, memp, cpqary3_ioctl_wait_ms,
633 633 CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
634 634 cpqary3_synccmd_free(cpqary3p, memp);
635 635 return (ETIMEDOUT);
636 636 }
637 637
638 638 /*
639 639 * If the command sent is NOE
640 640 * if the event class is CLASS_LOGICAL_DRIVE
641 641 * if the subcalls code is zero and if detail change is zero
642 642 * if the event specific data[3] is either 1 or 2 ie., if
643 643 * if the logical drive is failed set the target type to
644 644 * CPQARY3_TARGET_NONE
645 645 */
646 646
647 647 /* NOE */
648 648 if (cpqary3p->noe_support == 0 &&
649 649 cmdlist->Request.CDB[0] == 0x26 &&
650 650 cmdlist->Request.CDB[6] == BMIC_NOTIFY_ON_EVENT) {
651 651
652 652 evt = (NoeBuffer*)MEM2DRVPVT(memp)->sg;
653 653
654 654 if (evt->event_class_code == CLASS_LOGICAL_DRIVE &&
655 655 evt->event_subclass_code == SUB_CLASS_STATUS &&
656 656 evt->event_detail_code == DETAIL_CHANGE &&
657 657 evt->event_specific_data[3] == 1) {
658 658 /* LINTED: alignment */
659 659 drive = *(uint16_t *)(&evt->event_specific_data[0]);
660 660 drive = ((drive < CTLR_SCSI_ID) ?
661 661 drive : drive + CPQARY3_TGT_ALIGNMENT);
662 662
663 663 if (cpqary3p && cpqary3p->cpqary3_tgtp[drive]) {
664 664 cpqary3p->cpqary3_tgtp[drive]->type =
665 665 CPQARY3_TARGET_NONE;
666 666 }
667 667 }
668 668 }
669 669
670 670 /*
671 671 * Now the command is completed and copy the buffers back
672 672 * First copy the buffer databuf to scsi_pass->buf
673 673 * which is used as a buffer before passing the command to the
674 674 * controller.
675 675 */
676 676
677 677 if (scsi_pass->io_direction == CPQARY3_SCSI_IN) {
678 678 if (scsi_pass->buf_len > 0) {
679 679 if (ddi_copyout((void *)databuf,
680 680 (void *)(uintptr_t)scsi_pass->buf,
681 681 scsi_pass->buf_len, mode)) {
682 682 retval = EFAULT;
683 683 }
684 684 }
685 685 }
686 686
687 687 /*
688 688 * This is case where the command completes with error,
689 689 * Then tag would have set its 1st(10) bit.
690 690 */
691 691
692 692 if (cmdlist->Header.Tag.drvinfo_n_err == CPQARY3_SYNCCMD_FAILURE) {
693 693 scsi_pass->err_status = 1;
694 694 bcopy((caddr_t)memp->errorinfop, &scsi_pass->err_info,
695 695 sizeof (ErrorInfo_t));
696 696 switch (memp->errorinfop->CommandStatus) {
697 697 case CISS_CMD_DATA_OVERRUN:
698 698 case CISS_CMD_DATA_UNDERRUN:
699 699 case CISS_CMD_SUCCESS:
700 700 case CISS_CMD_TARGET_STATUS:
701 701 retval = SUCCESS;
702 702 break;
703 703 default:
704 704 retval = EIO;
705 705 break;
706 706 }
707 707 }
708 708
709 709 cpqary3_synccmd_free(cpqary3p, memp);
710 710
711 711 return (retval);
712 712 }
713 713
714 714 /*
715 715 * Function : cpqary3_ioctl_fil_scsi_
716 716 * Description : This routine will fill the cmdlist with SCSI CDB
717 717 * Called By : cpqary3_ioctl_send_scsicmd
718 718 * Parameters : cmdlist - command packet
719 719 * cpqary3_scsi_pass_t - scsi parameter
720 720 * Return Values: void
721 721 */
722 722 static void
723 723 cpqary3_ioctl_fil_scsi(CommandList_t *cmdlist,
724 724 cpqary3_scsi_pass_t *scsi_pass)
725 725 {
726 726 cmdlist->Header.SGTotal = 1;
727 727 cmdlist->Header.SGList = 1;
728 728 cmdlist->Request.CDBLen = scsi_pass->cdb_len;
729 729 cmdlist->Request.Timeout = scsi_pass->timeout;
730 730 cmdlist->Request.Type.Type = CISS_TYPE_CMD;
731 731 cmdlist->Request.Type.Attribute = CISS_ATTR_HEADOFQUEUE;
732 732
733 733 switch (scsi_pass->io_direction) {
734 734 case CPQARY3_SCSI_OUT:
735 735 cmdlist->Request.Type.Direction = CISS_XFER_WRITE;
736 736 break;
737 737 case CPQARY3_SCSI_IN:
738 738 cmdlist->Request.Type.Direction = CISS_XFER_READ;
739 739 break;
740 740 case CPQARY3_NODATA_XFER:
741 741 cmdlist->Request.Type.Direction = CISS_XFER_NONE;
742 742 break;
743 743 default:
744 744 cmdlist->Request.Type.Direction = CISS_XFER_RSVD;
745 745 break;
746 746 }
747 747
748 748 /*
749 749 * Copy the SCSI CDB as is
750 750 */
751 751
752 752 bcopy(&scsi_pass->cdb[0], &cmdlist->Request.CDB[0],
753 753 scsi_pass->cdb_len);
754 754
755 755 /*
756 756 * Copy the Lun address from the request
757 757 */
758 758
759 759 bcopy(&scsi_pass->lun_addr[0], &(cmdlist->Header.LUN),
760 760 sizeof (LUNAddr_t));
761 761
762 762 cmdlist->SG[0].Len = scsi_pass->buf_len;
763 763 }
764 764
765 765 /*
766 766 * Function : cpqary3_ioctl_fil_bmic_sas
767 767 * Description : This routine will fill the cmdlist with BMIC details
768 768 * Called By : cpqary3_ioctl_send_bmiccmd
769 769 * Parameters : cmdlist - command packet
770 770 * bmic_pass - bmic structure
771 771 * Return Values: void
772 772 */
773 773 static void
774 774 cpqary3_ioctl_fil_bmic_sas(CommandList_t *cmdlist,
775 775 cpqary3_bmic_pass_t *bmic_pass)
776 776 {
777 777 cmdlist->Header.SGTotal = 1;
778 778 cmdlist->Header.SGList = 1;
779 779 cmdlist->Request.CDBLen = bmic_pass->cmd_len;
780 780 cmdlist->Request.Timeout = bmic_pass->timeout;
781 781 cmdlist->Request.Type.Type = CISS_TYPE_CMD;
782 782 cmdlist->Request.Type.Attribute = CISS_ATTR_HEADOFQUEUE;
783 783
784 784 switch (bmic_pass->io_direction) {
785 785 case CPQARY3_SCSI_OUT:
786 786 cmdlist->Request.Type.Direction = CISS_XFER_WRITE;
787 787 break;
788 788 case CPQARY3_SCSI_IN:
789 789 cmdlist->Request.Type.Direction = CISS_XFER_READ;
790 790 break;
791 791 case CPQARY3_NODATA_XFER:
792 792 cmdlist->Request.Type.Direction = CISS_XFER_NONE;
793 793 break;
794 794 default:
795 795 cmdlist->Request.Type.Direction = CISS_XFER_RSVD;
796 796 break;
797 797 }
798 798
799 799 cmdlist->Request.CDB[0] =
800 800 (bmic_pass->io_direction == CPQARY3_SCSI_IN) ? 0x26: 0x27;
801 801 cmdlist->Request.CDB[1] = bmic_pass->unit_number; /* Unit Number */
802 802
803 803 /*
804 804 * BMIC Detail - bytes 2[MSB] to 5[LSB]
805 805 */
806 806
807 807 cmdlist->Request.CDB[2] = (bmic_pass->blk_number >> 24) & 0xff;
808 808 cmdlist->Request.CDB[3] = (bmic_pass->blk_number >> 16) & 0xff;
809 809 cmdlist->Request.CDB[4] = (bmic_pass->blk_number >> 8) & 0xff;
810 810 cmdlist->Request.CDB[5] = bmic_pass->blk_number;
811 811
812 812 cmdlist->Request.CDB[6] = bmic_pass->cmd; /* BMIC Command */
813 813
814 814 /* Transfer Length - bytes 7[MSB] to 8[LSB] */
815 815
816 816 cmdlist->Request.CDB[7] = (bmic_pass->buf_len >> 8) & 0xff;
817 817 cmdlist->Request.CDB[8] = bmic_pass->buf_len & 0xff;
818 818 cmdlist->Request.CDB[9] = 0x00; /* Reserved */
819 819
820 820 /* Update CDB[2] = LSB bmix_index and CDB[9] = MSB bmic_index */
821 821 switch (bmic_pass->cmd) {
822 822 case HPSAS_ID_PHYSICAL_DRIVE:
823 823 case HPSAS_TAPE_INQUIRY:
824 824 case HPSAS_SENSE_MP_STAT:
825 825 case HPSAS_SET_MP_THRESHOLD:
826 826 case HPSAS_MP_PARAM_CONTROL:
827 827 case HPSAS_SENSE_DRV_ERR_LOG:
828 828 case HPSAS_SET_MP_VALUE:
829 829 cmdlist -> Request.CDB[2] = bmic_pass->bmic_index & 0xff;
830 830 cmdlist -> Request.CDB[9] = (bmic_pass->bmic_index >>8) & 0xff;
831 831 break;
832 832
833 833 case HPSAS_ID_LOG_DRIVE:
834 834 case HPSAS_SENSE_LOG_DRIVE:
835 835 case HPSAS_READ:
836 836 case HPSAS_WRITE:
837 837 case HPSAS_WRITE_THROUGH:
838 838 case HPSAS_SENSE_CONFIG:
839 839 case HPSAS_SET_CONFIG:
840 840 case HPSAS_BYPASS_VOL_STATE:
841 841 case HPSAS_CHANGE_CONFIG:
842 842 case HPSAS_SENSE_ORIG_CONFIG:
843 843 case HPSAS_LABEL_LOG_DRIVE:
844 844 /* Unit Number MSB */
845 845 cmdlist->Request.CDB[9] = (bmic_pass->unit_number >> 8) & 0xff;
846 846 break;
847 847
848 848 default:
849 849 break;
850 850 }
851 851
852 852
853 853 /*
854 854 * Copy the Lun address from the request
855 855 */
856 856
857 857 bcopy(&bmic_pass->lun_addr[0], &(cmdlist->Header.LUN),
858 858 sizeof (LUNAddr_t));
859 859
860 860 cmdlist->SG[0].Len = bmic_pass->buf_len;
861 861 }
↓ open down ↓ |
809 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX