bmake-ify mr_sas
[unleashed.git] / usr / src / uts / common / io / cpqary3 / cpqary3_ioctl.c
blob395a8f907f45c5ffa6c726c551b81e6f122f96ef
1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
13 * Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
17 * Supported IOCTLs :
18 * CPQARY3_IOCTL_DRIVER_INFO - to get driver details
19 * CPQARY3_IOCTL_CTLR_INFO - to get controller details
20 * CPQARY3_IOCTL_BMIC_PASS - to pass BMIC commands
21 * CPQARY3_IOCTL_SCSI_PASS - to pass SCSI commands
24 #include "cpqary3.h"
27 * Local Functions Declaration
30 static int32_t cpqary3_ioctl_send_bmiccmd(cpqary3_t *, cpqary3_bmic_pass_t *,
31 int);
32 static void cpqary3_ioctl_fil_bmic(CommandList_t *, cpqary3_bmic_pass_t *);
33 static void cpqary3_ioctl_fil_bmic_sas(CommandList_t *, cpqary3_bmic_pass_t *);
34 static int32_t cpqary3_ioctl_send_scsicmd(cpqary3_t *, cpqary3_scsi_pass_t *,
35 int);
36 static void cpqary3_ioctl_fil_scsi(CommandList_t *, cpqary3_scsi_pass_t *);
39 * Global Variables Definitions
42 cpqary3_driver_info_t gdriver_info = {0};
44 /* Function Definitions */
47 * Function : cpqary3_ioctl_driver_info
48 * Description : This routine will get major/ minor versions, Number of
49 * controllers detected & MAX Number of controllers
50 * supported
51 * Called By : cpqary3_ioctl
52 * Parameters : ioctl_reqp - address of the parameter sent from
53 * the application
54 * cpqary3p - address of the PerController structure
55 * mode - mode which comes from application
56 * Return Values: EFAULT on Failure, 0 on SUCCESS
58 int32_t
59 cpqary3_ioctl_driver_info(uintptr_t ioctl_reqp, int mode)
61 cpqary3_ioctl_request_t *request;
63 request = (cpqary3_ioctl_request_t *)
64 MEM_ZALLOC(sizeof (cpqary3_ioctl_request_t));
66 if (NULL == request)
67 return (FAILURE);
70 * First let us copyin the ioctl_reqp user buffer to request(kernel)
71 * memory. This is very much recomended before we access any of the
72 * fields.
74 if (ddi_copyin((void *)ioctl_reqp, (void *)request,
75 sizeof (cpqary3_ioctl_request_t), mode)) {
76 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
77 return (EFAULT);
81 * Fill up the global structure "gdriver_info" memory.
82 * Fill this structure with available info, which will be copied
83 * back later
86 (void) strcpy(gdriver_info.name, "cpqary3");
87 gdriver_info.version.minor = CPQARY3_MINOR_REV_NO;
88 gdriver_info.version.major = CPQARY3_MAJOR_REV_NO;
89 gdriver_info.version.dd = CPQARY3_REV_MONTH;
90 gdriver_info.version.mm = CPQARY3_REV_DATE;
91 gdriver_info.version.yyyy = CPQARY3_REV_YEAR;
92 gdriver_info.max_num_ctlr = MAX_CTLRS;
95 * First Copy out the driver_info structure
98 if (ddi_copyout((void *)&gdriver_info, (void *)(uintptr_t)request->argp,
99 sizeof (cpqary3_driver_info_t), mode)) {
100 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
101 return (EFAULT);
105 * Copy out the request structure back
108 if (ddi_copyout((void *)request, (void *)ioctl_reqp,
109 sizeof (cpqary3_ioctl_request_t), mode)) {
110 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
111 return (EFAULT);
114 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
117 * Everything looks fine. So return SUCCESS
120 return (SUCCESS);
124 * Function : cpqary3_ioctl_ctlr_info
125 * Description : This routine will get the controller related info, like
126 * board-id, subsystem-id, num of logical drives,
127 * slot number
128 * Called By : cpqary3_ioctl
129 * Parameters : ioctl_reqp - address of the parameter sent form the
130 * application
131 * cpqary3p - address of the PerController structure
132 * mode - mode which comes from application
133 * Return Values: EFAULT on Failure, 0 on SUCCESS
135 int32_t
136 cpqary3_ioctl_ctlr_info(uintptr_t ioctl_reqp, cpqary3_t *cpqary3p, int mode)
138 cpqary3_ioctl_request_t *request;
139 cpqary3_ctlr_info_t *ctlr_info;
141 request = (cpqary3_ioctl_request_t *)
142 MEM_ZALLOC(sizeof (cpqary3_ioctl_request_t));
144 if (NULL == request)
145 return (FAILURE);
148 * First let us copyin the buffer to kernel memory. This is very much
149 * recomended before we access any of the fields.
152 if (ddi_copyin((void *) ioctl_reqp, (void *)request,
153 sizeof (cpqary3_ioctl_request_t), mode)) {
154 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
155 return (EFAULT);
158 ctlr_info = (cpqary3_ctlr_info_t *)
159 MEM_ZALLOC(sizeof (cpqary3_ctlr_info_t));
161 if (NULL == ctlr_info) {
162 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
163 return (FAILURE);
167 * in the driver, board_id is actually subsystem_id
170 ctlr_info->subsystem_id = cpqary3p->board_id;
171 ctlr_info->bus = cpqary3p->bus;
172 ctlr_info->dev = cpqary3p->dev;
173 ctlr_info->fun = cpqary3p->fun;
174 ctlr_info->num_of_tgts = cpqary3p->num_of_targets;
175 ctlr_info->controller_instance = cpqary3p->instance;
178 * TODO: ctlr_info.slot_num has to be implemented
179 * state & board_id fields are kept for future implementation i
180 * if required!
184 * First Copy out the ctlr_info structure
187 if (ddi_copyout((void *)ctlr_info, (void *)(uintptr_t)request->argp,
188 sizeof (cpqary3_ctlr_info_t), mode)) {
189 MEM_SFREE(ctlr_info, sizeof (cpqary3_ctlr_info_t));
190 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
191 return (EFAULT);
195 * Copy out the request structure back
198 if (ddi_copyout((void *)request, (void *)ioctl_reqp,
199 sizeof (cpqary3_ioctl_request_t), mode)) {
200 MEM_SFREE(ctlr_info, sizeof (cpqary3_ctlr_info_t));
201 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
202 return (EFAULT);
205 MEM_SFREE(ctlr_info, sizeof (cpqary3_ctlr_info_t));
206 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
209 * Everything looks fine. So return SUCCESS
212 return (SUCCESS);
216 * Function : cpqary3_ioctl_bmic_pass
217 * Description : This routine will pass the BMIC commands to controller
218 * Called By : cpqary3_ioctl
219 * Parameters : ioctl_reqp - address of the parameter sent from the
220 * application
221 * cpqary3p - address of the PerController structure
222 * mode - mode which comes directly from application
223 * Return Values: EFAULT on Failure, 0 on SUCCESS
225 int32_t
226 cpqary3_ioctl_bmic_pass(uintptr_t ioctl_reqp, cpqary3_t *cpqary3p, int mode)
228 cpqary3_ioctl_request_t *request;
229 cpqary3_bmic_pass_t *bmic_pass;
230 int32_t retval = SUCCESS;
232 request = (cpqary3_ioctl_request_t *)
233 MEM_ZALLOC(sizeof (cpqary3_ioctl_request_t));
235 if (NULL == request)
236 return (FAILURE);
239 * First let us copyin the ioctl_reqp(user) buffer to request(kernel)
240 * memory. This is very much recommended before we access any of the
241 * fields.
244 if (ddi_copyin((void *)ioctl_reqp, (void *)request,
245 sizeof (cpqary3_ioctl_request_t), mode)) {
246 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
247 return (EFAULT);
250 bmic_pass = (cpqary3_bmic_pass_t *)
251 MEM_ZALLOC(sizeof (cpqary3_bmic_pass_t));
253 if (NULL == bmic_pass) {
254 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
255 return (FAILURE);
259 * Copy in "cpqary3_bmic_pass_t" structure from argp member
260 * of ioctl_reqp.
263 if (ddi_copyin((void *)(uintptr_t)request->argp, (void *)bmic_pass,
264 sizeof (cpqary3_bmic_pass_t), mode)) {
265 MEM_SFREE(bmic_pass, sizeof (cpqary3_bmic_pass_t));
266 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
267 return (EFAULT);
271 * Get the free command list, fill in the bmic command and send it
272 * to the controller. This will return 0 on success.
275 retval = cpqary3_ioctl_send_bmiccmd(cpqary3p, bmic_pass, mode);
278 * Now copy the bmic_pass (kernel) to the user argp
281 if (ddi_copyout((void *) bmic_pass, (void *)(uintptr_t)request->argp,
282 sizeof (cpqary3_bmic_pass_t), mode)) {
283 MEM_SFREE(bmic_pass, sizeof (cpqary3_bmic_pass_t));
284 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
285 retval = EFAULT; /* copyout failed */
289 * Now copy the request(kernel) to ioctl_reqp(user)
292 if (ddi_copyout((void *) request, (void *)ioctl_reqp,
293 sizeof (cpqary3_ioctl_request_t), mode)) {
294 MEM_SFREE(bmic_pass, sizeof (cpqary3_bmic_pass_t));
295 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
296 retval = EFAULT;
299 MEM_SFREE(bmic_pass, sizeof (cpqary3_bmic_pass_t));
300 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
302 return (retval);
306 * Function : cpqary3_ioctl_send_bmiccmd
307 * Description : This routine will get the free command,
308 * allocate memory and send it to controller.
309 * Called By : cpqary3_ioctl_bmic_pass
310 * Parameters : cpqary3_t - PerController structure
311 * cpqary3_bmic_pass_t - bmic structure
312 * mode - mode value sent from application
313 * Return Values: 0 on success
314 * FAILURE, EFAULT, ETIMEOUT based on the failure
317 uint32_t cpqary3_ioctl_wait_ms = 30000;
319 static int32_t
320 cpqary3_ioctl_send_bmiccmd(cpqary3_t *cpqary3p,
321 cpqary3_bmic_pass_t *bmic_pass, int mode)
323 cpqary3_cmdpvt_t *memp = NULL;
324 CommandList_t *cmdlist = NULL;
325 int8_t *databuf = NULL;
326 uint8_t retval = 0;
328 /* allocate a command with a dma buffer */
329 memp = cpqary3_synccmd_alloc(cpqary3p, bmic_pass->buf_len);
330 if (memp == NULL)
331 return (FAILURE);
333 /* Get the databuf when buf_len is greater than zero */
334 if (bmic_pass->buf_len > 0) {
335 databuf = memp->driverdata->sg;
338 cmdlist = memp->cmdlist_memaddr;
341 * If io_direction is CPQARY3_SCSI_OUT, we have to copy user buffer
342 * to databuf
345 if (bmic_pass->io_direction == CPQARY3_SCSI_OUT) {
346 /* Do a copyin when buf_len is greater than zero */
347 if (bmic_pass->buf_len > 0) {
348 if (ddi_copyin((void*)(uintptr_t)(bmic_pass->buf),
349 (void*)databuf, bmic_pass->buf_len, mode)) {
350 cpqary3_synccmd_free(cpqary3p, memp);
351 return (EFAULT);
357 * Now fill the command as per the BMIC
359 if (cpqary3p->bddef->bd_flags & SA_BD_SAS) {
360 cpqary3_ioctl_fil_bmic_sas(cmdlist, bmic_pass);
361 } else {
362 cpqary3_ioctl_fil_bmic(cmdlist, bmic_pass);
366 /* PERF */
368 memp->complete = cpqary3_synccmd_complete;
370 /* PERF */
372 /* send command to controller and wait for a reply */
373 if (cpqary3_synccmd_send(cpqary3p, memp, cpqary3_ioctl_wait_ms,
374 CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
375 cpqary3_synccmd_free(cpqary3p, memp);
376 return (ETIMEDOUT);
380 * Now the command is completed and copy the buffers back
381 * First copy the buffer databuf to bmic_pass.buf
382 * which is used as a buffer before passing the command to the
383 * controller.
386 if (bmic_pass->io_direction == CPQARY3_SCSI_IN) {
387 /* Do a copyout when buf_len is greater than zero */
388 if (bmic_pass->buf_len > 0) {
389 if (ddi_copyout((void *)databuf,
390 (void *)(uintptr_t)bmic_pass->buf,
391 bmic_pass->buf_len, mode)) {
392 retval = EFAULT;
398 * This is case where the command completes with error,
399 * Then tag would have set its 1st(10) bit.
402 if (cmdlist->Header.Tag.drvinfo_n_err == CPQARY3_SYNCCMD_FAILURE) {
403 bmic_pass->err_status = 1;
404 bcopy((caddr_t)memp->errorinfop, &bmic_pass->err_info,
405 sizeof (ErrorInfo_t));
406 switch (memp->errorinfop->CommandStatus) {
407 case CISS_CMD_DATA_OVERRUN :
408 case CISS_CMD_DATA_UNDERRUN :
409 case CISS_CMD_SUCCESS :
410 case CISS_CMD_TARGET_STATUS :
411 retval = SUCCESS;
412 break;
413 default :
414 retval = EIO;
415 break;
419 cpqary3_synccmd_free(cpqary3p, memp);
421 return (retval);
425 * Function : cpqary3_ioctl_fil_bmic
426 * Description : This routine will fill the cmdlist with BMIC details
427 * Called By : cpqary3_ioctl_send_bmiccmd
428 * Parameters : cmdlist - command packet
429 * bmic_pass - bmic structure
430 * Return Values: void
432 static void
433 cpqary3_ioctl_fil_bmic(CommandList_t *cmdlist,
434 cpqary3_bmic_pass_t *bmic_pass)
436 cmdlist->Header.SGTotal = 1;
437 cmdlist->Header.SGList = 1;
438 cmdlist->Request.CDBLen = bmic_pass->cmd_len;
439 cmdlist->Request.Timeout = bmic_pass->timeout;
440 cmdlist->Request.Type.Type = CISS_TYPE_CMD;
441 cmdlist->Request.Type.Attribute = CISS_ATTR_HEADOFQUEUE;
443 switch (bmic_pass->io_direction) {
444 case CPQARY3_SCSI_OUT:
445 cmdlist->Request.Type.Direction = CISS_XFER_WRITE;
446 break;
447 case CPQARY3_SCSI_IN:
448 cmdlist->Request.Type.Direction = CISS_XFER_READ;
449 break;
450 case CPQARY3_NODATA_XFER:
451 cmdlist->Request.Type.Direction = CISS_XFER_NONE;
452 break;
453 default:
454 cmdlist->Request.Type.Direction = CISS_XFER_RSVD;
455 break;
458 cmdlist ->Request.CDB[0] =
459 (bmic_pass->io_direction == CPQARY3_SCSI_IN) ? 0x26: 0x27;
460 cmdlist ->Request.CDB[1] = bmic_pass->unit_number; /* Unit Number */
463 * BMIC Detail - bytes 2[MSB] to 5[LSB]
466 cmdlist->Request.CDB[2] = (bmic_pass->blk_number >> 24) & 0xff;
467 cmdlist->Request.CDB[3] = (bmic_pass->blk_number >> 16) & 0xff;
468 cmdlist->Request.CDB[4] = (bmic_pass->blk_number >> 8) & 0xff;
469 cmdlist->Request.CDB[5] = bmic_pass->blk_number;
471 cmdlist->Request.CDB[6] = bmic_pass->cmd; /* BMIC Command */
473 /* Transfer Length - bytes 7[MSB] to 8[LSB] */
475 cmdlist->Request.CDB[7] = (bmic_pass->buf_len >> 8) & 0xff;
476 cmdlist->Request.CDB[8] = bmic_pass->buf_len & 0xff;
477 cmdlist->Request.CDB[9] = 0x00; /* Reserved */
480 * Copy the Lun address from the request
483 bcopy(&bmic_pass->lun_addr[0], &(cmdlist->Header.LUN),
484 sizeof (LUNAddr_t));
485 cmdlist->SG[0].Len = bmic_pass->buf_len;
489 * Function : cpqary3_ioctl_scsi_pass
490 * Description : This routine will pass the SCSI commands to controller
491 * Called By : cpqary3_ioctl
492 * Parameters : ioctl_reqp - address of the parameter sent
493 * from the application
494 * cpqary3p - Addess of the percontroller stucture
495 * mode - mode which comes directly from application
496 * Return Values: EFAULT on Failure, 0 on SUCCESS
498 int32_t
499 cpqary3_ioctl_scsi_pass(uintptr_t ioctl_reqp, cpqary3_t *cpqary3p, int mode)
501 cpqary3_ioctl_request_t *request;
502 cpqary3_scsi_pass_t *scsi_pass;
503 int32_t retval = SUCCESS;
505 request = (cpqary3_ioctl_request_t *)
506 MEM_ZALLOC(sizeof (cpqary3_ioctl_request_t));
508 if (NULL == request)
509 return (FAILURE);
512 * First let us copyin the ioctl_reqp(user) buffer to request(kernel)
513 * memory. * This is very much recommended before we access any of
514 * the fields.
517 if (ddi_copyin((void *)ioctl_reqp, (void *)request,
518 sizeof (cpqary3_ioctl_request_t), mode)) {
519 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
520 return (EFAULT);
523 scsi_pass = (cpqary3_scsi_pass_t *)
524 MEM_ZALLOC(sizeof (cpqary3_scsi_pass_t));
526 if (NULL == scsi_pass) {
527 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
528 return (FAILURE);
532 * Copy in "cpqary3_scsi_pass_t" structure from argp member
533 * of ioctl_reqp.
536 if (ddi_copyin((void *)(uintptr_t)request->argp, (void *)scsi_pass,
537 sizeof (cpqary3_scsi_pass_t), mode)) {
538 MEM_SFREE(scsi_pass, sizeof (cpqary3_scsi_pass_t));
539 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
540 return (EFAULT);
544 * Get the free command list, fill in the scsi command and send it
545 * to the controller. This will return 0 on success.
548 retval = cpqary3_ioctl_send_scsicmd(cpqary3p, scsi_pass, mode);
551 * Now copy the scsi_pass (kernel) to the user argp
554 if (ddi_copyout((void *)scsi_pass, (void *)(uintptr_t)request->argp,
555 sizeof (cpqary3_scsi_pass_t), mode)) {
556 MEM_SFREE(scsi_pass, sizeof (cpqary3_scsi_pass_t));
557 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
558 retval = EFAULT; /* copyout failed */
562 * Now copy the request(kernel) to ioctl_reqp(user)
565 if (ddi_copyout((void *)request, (void *)ioctl_reqp,
566 sizeof (cpqary3_ioctl_request_t), mode)) {
567 MEM_SFREE(scsi_pass, sizeof (cpqary3_scsi_pass_t));
568 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
569 retval = EFAULT;
572 MEM_SFREE(scsi_pass, sizeof (cpqary3_scsi_pass_t));
573 MEM_SFREE(request, sizeof (cpqary3_ioctl_request_t));
575 return (retval);
579 * Function : cpqary3_ioctl_send_scsiccmd
580 * Description : This routine will pass the SCSI commands to controller
581 * Called By : cpqary3_ioctl_scsi_pass
582 * Parameters : cpqary3_t - PerController structure,
583 * cpqary3_scsi_pass_t - scsi parameter
584 * mode - sent from the application
585 * Return Values: 0 on success
586 * FAILURE, EFAULT, ETIMEOUT based on the failure
588 static int32_t
589 cpqary3_ioctl_send_scsicmd(cpqary3_t *cpqary3p,
590 cpqary3_scsi_pass_t *scsi_pass, int mode)
592 cpqary3_cmdpvt_t *memp = NULL;
593 CommandList_t *cmdlist = NULL;
594 int8_t *databuf = NULL;
595 uint8_t retval = 0;
596 NoeBuffer *evt;
597 uint16_t drive = 0;
599 /* allocate a command with a dma buffer */
600 memp = cpqary3_synccmd_alloc(cpqary3p, scsi_pass->buf_len);
601 if (memp == NULL)
602 return (FAILURE);
604 /* Get the databuf when buf_len is greater than zero */
605 if (scsi_pass->buf_len > 0) {
606 databuf = memp->driverdata->sg;
609 cmdlist = memp->cmdlist_memaddr;
611 if (scsi_pass->io_direction == CPQARY3_SCSI_OUT) {
612 /* Do a copyin when buf_len is greater than zero */
613 if (scsi_pass->buf_len > 0) {
614 if (ddi_copyin((void*)(uintptr_t)(scsi_pass->buf),
615 (void*)databuf, scsi_pass->buf_len, mode)) {
616 cpqary3_synccmd_free(cpqary3p, memp);
617 return (EFAULT);
623 * Fill the scsi command
625 cpqary3_ioctl_fil_scsi(cmdlist, scsi_pass);
627 /* PERF */
628 memp->complete = cpqary3_synccmd_complete;
629 /* PERF */
631 /* send command to controller and wait for a reply */
632 if (cpqary3_synccmd_send(cpqary3p, memp, cpqary3_ioctl_wait_ms,
633 CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
634 cpqary3_synccmd_free(cpqary3p, memp);
635 return (ETIMEDOUT);
639 * If the command sent is NOE
640 * if the event class is CLASS_LOGICAL_DRIVE
641 * if the subcalls code is zero and if detail change is zero
642 * if the event specific data[3] is either 1 or 2 ie., if
643 * if the logical drive is failed set the target type to
644 * CPQARY3_TARGET_NONE
647 /* NOE */
648 if (cpqary3p->noe_support == 0 &&
649 cmdlist->Request.CDB[0] == 0x26 &&
650 cmdlist->Request.CDB[6] == BMIC_NOTIFY_ON_EVENT) {
652 evt = (NoeBuffer*)MEM2DRVPVT(memp)->sg;
654 if (evt->event_class_code == CLASS_LOGICAL_DRIVE &&
655 evt->event_subclass_code == SUB_CLASS_STATUS &&
656 evt->event_detail_code == DETAIL_CHANGE &&
657 evt->event_specific_data[3] == 1) {
658 /* LINTED: alignment */
659 drive = *(uint16_t *)(&evt->event_specific_data[0]);
660 drive = ((drive < CTLR_SCSI_ID) ?
661 drive : drive + CPQARY3_TGT_ALIGNMENT);
663 if (cpqary3p && cpqary3p->cpqary3_tgtp[drive]) {
664 cpqary3p->cpqary3_tgtp[drive]->type =
665 CPQARY3_TARGET_NONE;
671 * Now the command is completed and copy the buffers back
672 * First copy the buffer databuf to scsi_pass->buf
673 * which is used as a buffer before passing the command to the
674 * controller.
677 if (scsi_pass->io_direction == CPQARY3_SCSI_IN) {
678 if (scsi_pass->buf_len > 0) {
679 if (ddi_copyout((void *)databuf,
680 (void *)(uintptr_t)scsi_pass->buf,
681 scsi_pass->buf_len, mode)) {
682 retval = EFAULT;
688 * This is case where the command completes with error,
689 * Then tag would have set its 1st(10) bit.
692 if (cmdlist->Header.Tag.drvinfo_n_err == CPQARY3_SYNCCMD_FAILURE) {
693 scsi_pass->err_status = 1;
694 bcopy((caddr_t)memp->errorinfop, &scsi_pass->err_info,
695 sizeof (ErrorInfo_t));
696 switch (memp->errorinfop->CommandStatus) {
697 case CISS_CMD_DATA_OVERRUN:
698 case CISS_CMD_DATA_UNDERRUN:
699 case CISS_CMD_SUCCESS:
700 case CISS_CMD_TARGET_STATUS:
701 retval = SUCCESS;
702 break;
703 default:
704 retval = EIO;
705 break;
709 cpqary3_synccmd_free(cpqary3p, memp);
711 return (retval);
715 * Function : cpqary3_ioctl_fil_scsi_
716 * Description : This routine will fill the cmdlist with SCSI CDB
717 * Called By : cpqary3_ioctl_send_scsicmd
718 * Parameters : cmdlist - command packet
719 * cpqary3_scsi_pass_t - scsi parameter
720 * Return Values: void
722 static void
723 cpqary3_ioctl_fil_scsi(CommandList_t *cmdlist,
724 cpqary3_scsi_pass_t *scsi_pass)
726 cmdlist->Header.SGTotal = 1;
727 cmdlist->Header.SGList = 1;
728 cmdlist->Request.CDBLen = scsi_pass->cdb_len;
729 cmdlist->Request.Timeout = scsi_pass->timeout;
730 cmdlist->Request.Type.Type = CISS_TYPE_CMD;
731 cmdlist->Request.Type.Attribute = CISS_ATTR_HEADOFQUEUE;
733 switch (scsi_pass->io_direction) {
734 case CPQARY3_SCSI_OUT:
735 cmdlist->Request.Type.Direction = CISS_XFER_WRITE;
736 break;
737 case CPQARY3_SCSI_IN:
738 cmdlist->Request.Type.Direction = CISS_XFER_READ;
739 break;
740 case CPQARY3_NODATA_XFER:
741 cmdlist->Request.Type.Direction = CISS_XFER_NONE;
742 break;
743 default:
744 cmdlist->Request.Type.Direction = CISS_XFER_RSVD;
745 break;
749 * Copy the SCSI CDB as is
752 bcopy(&scsi_pass->cdb[0], &cmdlist->Request.CDB[0],
753 scsi_pass->cdb_len);
756 * Copy the Lun address from the request
759 bcopy(&scsi_pass->lun_addr[0], &(cmdlist->Header.LUN),
760 sizeof (LUNAddr_t));
762 cmdlist->SG[0].Len = scsi_pass->buf_len;
766 * Function : cpqary3_ioctl_fil_bmic_sas
767 * Description : This routine will fill the cmdlist with BMIC details
768 * Called By : cpqary3_ioctl_send_bmiccmd
769 * Parameters : cmdlist - command packet
770 * bmic_pass - bmic structure
771 * Return Values: void
773 static void
774 cpqary3_ioctl_fil_bmic_sas(CommandList_t *cmdlist,
775 cpqary3_bmic_pass_t *bmic_pass)
777 cmdlist->Header.SGTotal = 1;
778 cmdlist->Header.SGList = 1;
779 cmdlist->Request.CDBLen = bmic_pass->cmd_len;
780 cmdlist->Request.Timeout = bmic_pass->timeout;
781 cmdlist->Request.Type.Type = CISS_TYPE_CMD;
782 cmdlist->Request.Type.Attribute = CISS_ATTR_HEADOFQUEUE;
784 switch (bmic_pass->io_direction) {
785 case CPQARY3_SCSI_OUT:
786 cmdlist->Request.Type.Direction = CISS_XFER_WRITE;
787 break;
788 case CPQARY3_SCSI_IN:
789 cmdlist->Request.Type.Direction = CISS_XFER_READ;
790 break;
791 case CPQARY3_NODATA_XFER:
792 cmdlist->Request.Type.Direction = CISS_XFER_NONE;
793 break;
794 default:
795 cmdlist->Request.Type.Direction = CISS_XFER_RSVD;
796 break;
799 cmdlist->Request.CDB[0] =
800 (bmic_pass->io_direction == CPQARY3_SCSI_IN) ? 0x26: 0x27;
801 cmdlist->Request.CDB[1] = bmic_pass->unit_number; /* Unit Number */
804 * BMIC Detail - bytes 2[MSB] to 5[LSB]
807 cmdlist->Request.CDB[2] = (bmic_pass->blk_number >> 24) & 0xff;
808 cmdlist->Request.CDB[3] = (bmic_pass->blk_number >> 16) & 0xff;
809 cmdlist->Request.CDB[4] = (bmic_pass->blk_number >> 8) & 0xff;
810 cmdlist->Request.CDB[5] = bmic_pass->blk_number;
812 cmdlist->Request.CDB[6] = bmic_pass->cmd; /* BMIC Command */
814 /* Transfer Length - bytes 7[MSB] to 8[LSB] */
816 cmdlist->Request.CDB[7] = (bmic_pass->buf_len >> 8) & 0xff;
817 cmdlist->Request.CDB[8] = bmic_pass->buf_len & 0xff;
818 cmdlist->Request.CDB[9] = 0x00; /* Reserved */
820 /* Update CDB[2] = LSB bmix_index and CDB[9] = MSB bmic_index */
821 switch (bmic_pass->cmd) {
822 case HPSAS_ID_PHYSICAL_DRIVE:
823 case HPSAS_TAPE_INQUIRY:
824 case HPSAS_SENSE_MP_STAT:
825 case HPSAS_SET_MP_THRESHOLD:
826 case HPSAS_MP_PARAM_CONTROL:
827 case HPSAS_SENSE_DRV_ERR_LOG:
828 case HPSAS_SET_MP_VALUE:
829 cmdlist -> Request.CDB[2] = bmic_pass->bmic_index & 0xff;
830 cmdlist -> Request.CDB[9] = (bmic_pass->bmic_index >>8) & 0xff;
831 break;
833 case HPSAS_ID_LOG_DRIVE:
834 case HPSAS_SENSE_LOG_DRIVE:
835 case HPSAS_READ:
836 case HPSAS_WRITE:
837 case HPSAS_WRITE_THROUGH:
838 case HPSAS_SENSE_CONFIG:
839 case HPSAS_SET_CONFIG:
840 case HPSAS_BYPASS_VOL_STATE:
841 case HPSAS_CHANGE_CONFIG:
842 case HPSAS_SENSE_ORIG_CONFIG:
843 case HPSAS_LABEL_LOG_DRIVE:
844 /* Unit Number MSB */
845 cmdlist->Request.CDB[9] = (bmic_pass->unit_number >> 8) & 0xff;
846 break;
848 default:
849 break;
854 * Copy the Lun address from the request
857 bcopy(&bmic_pass->lun_addr[0], &(cmdlist->Header.LUN),
858 sizeof (LUNAddr_t));
860 cmdlist->SG[0].Len = bmic_pass->buf_len;