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
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.
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
27 * Local Functions Declaration
30 static int32_t cpqary3_ioctl_send_bmiccmd(cpqary3_t
*, cpqary3_bmic_pass_t
*,
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
*,
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
51 * Called By : cpqary3_ioctl
52 * Parameters : ioctl_reqp - address of the parameter sent from
54 * cpqary3p - address of the PerController structure
55 * mode - mode which comes from application
56 * Return Values: EFAULT on Failure, 0 on SUCCESS
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
));
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
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
));
81 * Fill up the global structure "gdriver_info" memory.
82 * Fill this structure with available info, which will be copied
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
));
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
));
114 MEM_SFREE(request
, sizeof (cpqary3_ioctl_request_t
));
117 * Everything looks fine. So 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,
128 * Called By : cpqary3_ioctl
129 * Parameters : ioctl_reqp - address of the parameter sent form the
131 * cpqary3p - address of the PerController structure
132 * mode - mode which comes from application
133 * Return Values: EFAULT on Failure, 0 on SUCCESS
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
));
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
));
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
));
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
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
));
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
));
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
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
221 * cpqary3p - address of the PerController structure
222 * mode - mode which comes directly from application
223 * Return Values: EFAULT on Failure, 0 on SUCCESS
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
));
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
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
));
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
));
259 * Copy in "cpqary3_bmic_pass_t" structure from argp member
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
));
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
));
299 MEM_SFREE(bmic_pass
, sizeof (cpqary3_bmic_pass_t
));
300 MEM_SFREE(request
, sizeof (cpqary3_ioctl_request_t
));
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;
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
;
328 /* allocate a command with a dma buffer */
329 memp
= cpqary3_synccmd_alloc(cpqary3p
, bmic_pass
->buf_len
);
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
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
);
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
);
362 cpqary3_ioctl_fil_bmic(cmdlist
, bmic_pass
);
368 memp
->complete
= cpqary3_synccmd_complete
;
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
);
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
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
)) {
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
:
419 cpqary3_synccmd_free(cpqary3p
, memp
);
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
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
;
447 case CPQARY3_SCSI_IN
:
448 cmdlist
->Request
.Type
.Direction
= CISS_XFER_READ
;
450 case CPQARY3_NODATA_XFER
:
451 cmdlist
->Request
.Type
.Direction
= CISS_XFER_NONE
;
454 cmdlist
->Request
.Type
.Direction
= CISS_XFER_RSVD
;
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
),
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
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
));
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
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
));
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
));
532 * Copy in "cpqary3_scsi_pass_t" structure from argp member
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
));
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
));
572 MEM_SFREE(scsi_pass
, sizeof (cpqary3_scsi_pass_t
));
573 MEM_SFREE(request
, sizeof (cpqary3_ioctl_request_t
));
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
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
;
599 /* allocate a command with a dma buffer */
600 memp
= cpqary3_synccmd_alloc(cpqary3p
, scsi_pass
->buf_len
);
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
);
623 * Fill the scsi command
625 cpqary3_ioctl_fil_scsi(cmdlist
, scsi_pass
);
628 memp
->complete
= cpqary3_synccmd_complete
;
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
);
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
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
=
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
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
)) {
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
:
709 cpqary3_synccmd_free(cpqary3p
, memp
);
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
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
;
737 case CPQARY3_SCSI_IN
:
738 cmdlist
->Request
.Type
.Direction
= CISS_XFER_READ
;
740 case CPQARY3_NODATA_XFER
:
741 cmdlist
->Request
.Type
.Direction
= CISS_XFER_NONE
;
744 cmdlist
->Request
.Type
.Direction
= CISS_XFER_RSVD
;
749 * Copy the SCSI CDB as is
752 bcopy(&scsi_pass
->cdb
[0], &cmdlist
->Request
.CDB
[0],
756 * Copy the Lun address from the request
759 bcopy(&scsi_pass
->lun_addr
[0], &(cmdlist
->Header
.LUN
),
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
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
;
788 case CPQARY3_SCSI_IN
:
789 cmdlist
->Request
.Type
.Direction
= CISS_XFER_READ
;
791 case CPQARY3_NODATA_XFER
:
792 cmdlist
->Request
.Type
.Direction
= CISS_XFER_NONE
;
795 cmdlist
->Request
.Type
.Direction
= CISS_XFER_RSVD
;
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;
833 case HPSAS_ID_LOG_DRIVE
:
834 case HPSAS_SENSE_LOG_DRIVE
:
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;
854 * Copy the Lun address from the request
857 bcopy(&bmic_pass
->lun_addr
[0], &(cmdlist
->Header
.LUN
),
860 cmdlist
->SG
[0].Len
= bmic_pass
->buf_len
;