]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/smartpqi/smartpqi_cam.c
pmic: rockchip: Split the clocks part in its own file
[FreeBSD/FreeBSD.git] / sys / dev / smartpqi / smartpqi_cam.c
1 /*-
2  * Copyright 2016-2021 Microchip Technology, Inc. and/or its subsidiaries.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25
26 /* $FreeBSD$ */
27 /*
28  * CAM interface for smartpqi driver
29  */
30
31 #include "smartpqi_includes.h"
32
33 /*
34  * Set cam sim properties of the smartpqi adapter.
35  */
36 static void
37 update_sim_properties(struct cam_sim *sim, struct ccb_pathinq *cpi)
38 {
39
40         pqisrc_softstate_t *softs = (struct pqisrc_softstate *)
41                                         cam_sim_softc(sim);
42
43         device_t dev = softs->os_specific.pqi_dev;
44
45         DBG_FUNC("IN\n");
46
47         cpi->version_num = 1;
48         cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
49         cpi->target_sprt = 0;
50         cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED;
51         cpi->hba_eng_cnt = 0;
52         cpi->max_lun = PQI_MAX_MULTILUN;
53         cpi->max_target = 1088;
54         cpi->maxio = (softs->pqi_cap.max_sg_elem - 1) * PAGE_SIZE;
55         cpi->initiator_id = 255;
56         strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
57         strlcpy(cpi->hba_vid, "Microsemi", HBA_IDLEN);
58         strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
59         cpi->unit_number = cam_sim_unit(sim);
60         cpi->bus_id = cam_sim_bus(sim);
61         cpi->base_transfer_speed = 1200000; /* Base bus speed in KB/sec */
62         cpi->protocol = PROTO_SCSI;
63         cpi->protocol_version = SCSI_REV_SPC4;
64         cpi->transport = XPORT_SPI;
65         cpi->transport_version = 2;
66         cpi->ccb_h.status = CAM_REQ_CMP;
67         cpi->hba_vendor = pci_get_vendor(dev);
68         cpi->hba_device = pci_get_device(dev);
69         cpi->hba_subvendor = pci_get_subvendor(dev);
70         cpi->hba_subdevice = pci_get_subdevice(dev);
71
72
73         DBG_FUNC("OUT\n");
74 }
75
76 /*
77  * Get transport settings of the smartpqi adapter 
78  */
79 static void
80 get_transport_settings(struct pqisrc_softstate *softs,
81                 struct ccb_trans_settings *cts)
82 {
83         struct ccb_trans_settings_scsi  *scsi = &cts->proto_specific.scsi;
84         struct ccb_trans_settings_sas   *sas = &cts->xport_specific.sas;
85         struct ccb_trans_settings_spi   *spi = &cts->xport_specific.spi;
86
87         DBG_FUNC("IN\n");
88         
89         cts->protocol = PROTO_SCSI;
90         cts->protocol_version = SCSI_REV_SPC4;
91         cts->transport = XPORT_SPI;
92         cts->transport_version = 2;
93         spi->valid = CTS_SPI_VALID_DISC;
94         spi->flags = CTS_SPI_FLAGS_DISC_ENB;
95         scsi->valid = CTS_SCSI_VALID_TQ;
96         scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
97         sas->valid = CTS_SAS_VALID_SPEED;
98         cts->ccb_h.status = CAM_REQ_CMP;
99
100         DBG_FUNC("OUT\n");
101 }
102
103 /*
104  *  Add the target to CAM layer and rescan, when a new device is found
105  */
106 void
107 os_add_device(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
108 {
109         union ccb *ccb;
110
111         DBG_FUNC("IN\n");
112
113         if(softs->os_specific.sim_registered) { 
114                 if ((ccb = xpt_alloc_ccb_nowait()) == NULL) {
115                         DBG_ERR("rescan failed (can't allocate CCB)\n");
116                         return;
117                 }
118
119                 if (xpt_create_path(&ccb->ccb_h.path, NULL,
120                         cam_sim_path(softs->os_specific.sim),
121                         device->target, device->lun) != CAM_REQ_CMP) {
122                         DBG_ERR("rescan failed (can't create path)\n");
123                         xpt_free_ccb(ccb);
124                         return;
125                 }
126                 xpt_rescan(ccb);
127         }
128
129         DBG_FUNC("OUT\n");
130 }
131
132 /*
133  * Remove the device from CAM layer when deleted or hot removed
134  */
135 void
136 os_remove_device(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
137 {
138         struct cam_path *tmppath;
139
140         DBG_FUNC("IN\n");
141         
142         if(softs->os_specific.sim_registered) {
143                 if (xpt_create_path(&tmppath, NULL, 
144                         cam_sim_path(softs->os_specific.sim),
145                         device->target, device->lun) != CAM_REQ_CMP) {
146                         DBG_ERR("unable to create path for async event");
147                         return;
148                 }
149                 xpt_async(AC_LOST_DEVICE, tmppath, NULL);
150                 xpt_free_path(tmppath);
151                 softs->device_list[device->target][device->lun] = NULL;
152                 pqisrc_free_device(softs, device);
153         }
154
155         DBG_FUNC("OUT\n");
156
157 }
158
159 /*
160  * Function to release the frozen simq
161  */
162 static void
163 pqi_release_camq(rcb_t *rcb)
164 {
165         pqisrc_softstate_t *softs;
166         struct ccb_scsiio *csio;
167
168         csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio;
169         softs = rcb->softs;
170
171         DBG_FUNC("IN\n");
172
173         if (softs->os_specific.pqi_flags & PQI_FLAG_BUSY) {
174                 softs->os_specific.pqi_flags &= ~PQI_FLAG_BUSY;
175                 if (csio->ccb_h.status & CAM_RELEASE_SIMQ)
176                         xpt_release_simq(xpt_path_sim(csio->ccb_h.path), 0);
177                 else
178                         csio->ccb_h.status |= CAM_RELEASE_SIMQ;
179         }
180
181         DBG_FUNC("OUT\n");
182 }
183
184 static void
185 pqi_synch_request(rcb_t *rcb)
186 {
187         pqisrc_softstate_t *softs = rcb->softs;
188
189         DBG_IO("IN rcb = %p\n", rcb);
190
191         if (!(rcb->cm_flags & PQI_CMD_MAPPED))
192                 return;
193
194         if (rcb->bcount != 0 ) {
195                 if (rcb->data_dir == SOP_DATA_DIR_FROM_DEVICE)
196                         bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat,
197                                         rcb->cm_datamap,
198                                         BUS_DMASYNC_POSTREAD);
199                 if (rcb->data_dir == SOP_DATA_DIR_TO_DEVICE)
200                         bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat,
201                                         rcb->cm_datamap,
202                                         BUS_DMASYNC_POSTWRITE);
203                 bus_dmamap_unload(softs->os_specific.pqi_buffer_dmat,
204                                         rcb->cm_datamap);
205         }
206         rcb->cm_flags &= ~PQI_CMD_MAPPED;
207
208         if(rcb->sgt && rcb->nseg)
209                 os_mem_free(rcb->softs, (void*)rcb->sgt,
210                                 rcb->nseg*sizeof(sgt_t));
211
212         DBG_IO("OUT\n");
213 }
214
215 /*
216  * Function to dma-unmap the completed request
217  */
218 static inline void
219 pqi_unmap_request(rcb_t *rcb)
220 {
221         DBG_IO("IN rcb = %p\n", rcb);
222
223         pqi_synch_request(rcb);
224         pqisrc_put_tag(&rcb->softs->taglist, rcb->tag);
225
226         DBG_IO("OUT\n");
227 }
228
229 /*
230  * Construct meaningful LD name for volume here.
231  */
232 static void
233 smartpqi_fix_ld_inquiry(pqisrc_softstate_t *softs, struct ccb_scsiio *csio)
234 {
235         struct scsi_inquiry_data *inq = NULL;
236         uint8_t *cdb = NULL;
237         pqi_scsi_dev_t *device = NULL;
238
239         DBG_FUNC("IN\n");
240
241         if (pqisrc_ctrl_offline(softs))
242                 return;
243
244         cdb = (csio->ccb_h.flags & CAM_CDB_POINTER) ?
245                 (uint8_t *)csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes;
246         if(cdb[0] == INQUIRY &&
247                 (cdb[1] & SI_EVPD) == 0 &&
248                 (csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN &&
249                 csio->dxfer_len >= SHORT_INQUIRY_LENGTH) {
250
251                 inq = (struct scsi_inquiry_data *)csio->data_ptr;
252
253                 device = softs->device_list[csio->ccb_h.target_id][csio->ccb_h.target_lun];
254
255                 /* Let the disks be probed and dealt with via CAM. Only for LD
256                   let it fall through and inquiry be tweaked */
257                 if (!device || !pqisrc_is_logical_device(device) ||
258                                 (device->devtype != DISK_DEVICE) ||
259                                 pqisrc_is_external_raid_device(device)) {
260                         return;
261                 }
262
263                 strncpy(inq->vendor, device->vendor,
264                                 SID_VENDOR_SIZE);
265                 strncpy(inq->product,
266                                 pqisrc_raidlevel_to_string(device->raid_level),
267                                 SID_PRODUCT_SIZE);
268                 strncpy(inq->revision, device->volume_offline?"OFF":"OK",
269                                 SID_REVISION_SIZE);
270         }
271
272         DBG_FUNC("OUT\n");
273 }
274
275 static void
276 pqi_complete_scsi_io(struct ccb_scsiio *csio, rcb_t *rcb)
277 {
278         uint32_t release_tag;
279         pqisrc_softstate_t *softs = rcb->softs;
280
281         DBG_IO("IN scsi io = %p\n", csio);
282
283         pqi_synch_request(rcb);
284         smartpqi_fix_ld_inquiry(rcb->softs, csio);
285         pqi_release_camq(rcb);
286         release_tag = rcb->tag;
287         os_reset_rcb(rcb);
288         pqisrc_put_tag(&softs->taglist, release_tag);
289         xpt_done((union ccb *)csio);
290
291         DBG_FUNC("OUT\n");
292 }
293
294 /*
295  * Handle completion of a command - pass results back through the CCB
296  */
297 void
298 os_io_response_success(rcb_t *rcb)
299 {
300         struct ccb_scsiio *csio;
301
302         DBG_IO("IN rcb = %p\n", rcb);
303
304         if (rcb == NULL)
305                 panic("rcb is null");
306
307         csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio;
308
309         if (csio == NULL)
310                 panic("csio is null");
311
312         rcb->status = REQUEST_SUCCESS;
313         csio->ccb_h.status = CAM_REQ_CMP;
314
315         pqi_complete_scsi_io(csio, rcb);
316
317         DBG_IO("OUT\n");
318 }
319
320 static void
321 copy_sense_data_to_csio(struct ccb_scsiio *csio,
322                 uint8_t *sense_data, uint16_t sense_data_len)
323 {
324         DBG_IO("IN csio = %p\n", csio);
325
326         memset(&csio->sense_data, 0, csio->sense_len);
327
328         sense_data_len = (sense_data_len > csio->sense_len) ?
329                 csio->sense_len : sense_data_len;
330
331         if (sense_data)
332                 memcpy(&csio->sense_data, sense_data, sense_data_len);
333
334         if (csio->sense_len > sense_data_len)
335                 csio->sense_resid = csio->sense_len - sense_data_len;
336         else
337                 csio->sense_resid = 0;
338
339         DBG_IO("OUT\n");
340 }
341
342 /*
343  * Error response handling for raid IO
344  */
345 void
346 os_raid_response_error(rcb_t *rcb, raid_path_error_info_elem_t *err_info)
347 {
348         struct ccb_scsiio *csio;
349         pqisrc_softstate_t *softs;
350
351         DBG_IO("IN\n");
352
353         csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio;
354
355         if (csio == NULL)
356                 panic("csio is null");
357
358         softs = rcb->softs;
359
360         csio->ccb_h.status = CAM_REQ_CMP_ERR;
361
362         if (!err_info || !rcb->dvp) {
363                 DBG_ERR("couldn't be accessed! error info = %p, rcb->dvp = %p\n",
364                                 err_info, rcb->dvp);
365                 goto error_out;
366         }
367
368         csio->scsi_status = err_info->status;
369
370         if (csio->ccb_h.func_code == XPT_SCSI_IO) {
371                 /*
372                  * Handle specific SCSI status values.
373                  */
374                 switch(csio->scsi_status) {
375                         case PQI_RAID_STATUS_QUEUE_FULL:
376                                 csio->ccb_h.status = CAM_REQ_CMP;
377                                 DBG_ERR("Queue Full error\n");
378                                 break;
379                                 /* check condition, sense data included */
380                         case PQI_RAID_STATUS_CHECK_CONDITION:
381                                 {
382                                         uint16_t sense_data_len =
383                                                 LE_16(err_info->sense_data_len);
384                                         uint8_t *sense_data = NULL;
385                                         if (sense_data_len)
386                                                 sense_data = err_info->data;
387                                         copy_sense_data_to_csio(csio, sense_data, sense_data_len);
388                                         csio->ccb_h.status = CAM_SCSI_STATUS_ERROR
389                                                         | CAM_AUTOSNS_VALID
390                                                         | CAM_REQ_CMP_ERR;
391
392                                 }
393                                 break;
394
395                         case PQI_RAID_DATA_IN_OUT_UNDERFLOW:
396                                 {
397                                         uint32_t resid = 0;
398                                         resid = rcb->bcount-err_info->data_out_transferred;
399                                         csio->resid  = resid;
400                                         csio->ccb_h.status = CAM_REQ_CMP;
401                                 }
402                                 break;
403                         default:
404                                 csio->ccb_h.status = CAM_REQ_CMP;
405                                 break;
406                 }
407         }
408
409 error_out:
410         pqi_complete_scsi_io(csio, rcb);
411
412         DBG_IO("OUT\n");
413 }
414
415 /*
416  * Error response handling for aio.
417  */
418 void
419 os_aio_response_error(rcb_t *rcb, aio_path_error_info_elem_t *err_info)
420 {
421         struct ccb_scsiio *csio;
422         pqisrc_softstate_t *softs;
423
424         DBG_IO("IN\n");
425
426         if (rcb == NULL)
427                 panic("rcb is null");
428
429         rcb->status = REQUEST_SUCCESS;
430         csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio;
431         if (csio == NULL)
432                 panic("csio is null");
433
434         softs = rcb->softs;
435
436         if (!err_info || !rcb->dvp) {
437                 csio->ccb_h.status = CAM_REQ_CMP_ERR;
438                 DBG_ERR("couldn't be accessed! error info = %p, rcb->dvp = %p\n",
439                                 err_info, rcb->dvp);
440                 goto error_out;
441         }
442
443         switch (err_info->service_resp) {
444                 case PQI_AIO_SERV_RESPONSE_COMPLETE:
445                         csio->ccb_h.status = err_info->status;
446                         break;
447                 case PQI_AIO_SERV_RESPONSE_FAILURE:
448                         switch(err_info->status) {
449                                 case PQI_AIO_STATUS_IO_ABORTED:
450                                         csio->ccb_h.status = CAM_REQ_ABORTED;
451                                         DBG_WARN_BTL(rcb->dvp, "IO aborted\n");
452                                         break;
453                                 case PQI_AIO_STATUS_UNDERRUN:
454                                         csio->ccb_h.status = CAM_REQ_CMP;
455                                         csio->resid =
456                                                 LE_32(err_info->resd_count);
457                                         break;
458                                 case PQI_AIO_STATUS_OVERRUN:
459                                         csio->ccb_h.status = CAM_REQ_CMP;
460                                         break;
461                                 case PQI_AIO_STATUS_AIO_PATH_DISABLED:
462                                         DBG_WARN_BTL(rcb->dvp,"AIO Path Disabled\n");
463                                         /* Timed out TMF response comes here */
464                                         if (rcb->tm_req) {
465                                                 rcb->req_pending = false;
466                                                 rcb->status = REQUEST_SUCCESS;
467                                                 DBG_ERR("AIO Disabled for TMF\n");
468                                                 return;
469                                         }
470                                         rcb->dvp->aio_enabled = false;
471                                         rcb->dvp->offload_enabled = false;
472                                         csio->ccb_h.status |= CAM_REQUEUE_REQ;
473                                         break;
474                                 case PQI_AIO_STATUS_IO_ERROR:
475                                 case PQI_AIO_STATUS_IO_NO_DEVICE:
476                                 case PQI_AIO_STATUS_INVALID_DEVICE:
477                                 default:
478                                         DBG_WARN_BTL(rcb->dvp,"IO Error/Invalid/No device\n");
479                                         csio->ccb_h.status |=
480                                                 CAM_SCSI_STATUS_ERROR;
481                                         break;
482                         }
483                         break;
484                 case PQI_AIO_SERV_RESPONSE_TMF_COMPLETE:
485                 case PQI_AIO_SERV_RESPONSE_TMF_SUCCEEDED:
486                         DBG_ERR("PQI_AIO_SERV_RESPONSE_TMF %s\n",
487                                 (err_info->service_resp == PQI_AIO_SERV_RESPONSE_TMF_COMPLETE) ? "COMPLETE" : "SUCCEEDED");
488                         rcb->status = REQUEST_SUCCESS;
489                         rcb->req_pending = false;
490                         return;
491                 case PQI_AIO_SERV_RESPONSE_TMF_REJECTED:
492                 case PQI_AIO_SERV_RESPONSE_TMF_INCORRECT_LUN:
493                         DBG_ERR("PQI_AIO_SERV_RESPONSE_TMF %s\n",
494                                 (err_info->service_resp == PQI_AIO_SERV_RESPONSE_TMF_REJECTED) ? "REJECTED" : "INCORRECT LUN");
495                         rcb->status = REQUEST_FAILED;
496                         rcb->req_pending = false;
497                         return;
498                 default:
499                         DBG_WARN_BTL(rcb->dvp,"Scsi Status Error\n");
500                         csio->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
501                         break;
502         }
503
504         if(err_info->data_pres == DATA_PRESENT_SENSE_DATA ) {
505                 csio->scsi_status = PQI_AIO_STATUS_CHECK_CONDITION;
506                 uint8_t *sense_data = NULL;
507                 unsigned sense_data_len = LE_16(err_info->data_len);
508                 if (sense_data_len)
509                         sense_data = err_info->data;
510                 DBG_ERR_BTL(rcb->dvp, "SCSI_STATUS_CHECK_COND  sense size %u\n",
511                         sense_data_len);
512                 copy_sense_data_to_csio(csio, sense_data, sense_data_len);
513                 csio->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
514         }
515
516 error_out:
517         pqi_complete_scsi_io(csio, rcb);
518         DBG_IO("OUT\n");
519 }
520
521 static void
522 pqi_freeze_ccb(union ccb *ccb)
523 {
524         if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
525                 ccb->ccb_h.status |= CAM_DEV_QFRZN;
526                 xpt_freeze_devq(ccb->ccb_h.path, 1);
527         }
528 }
529
530 /*
531  * Command-mapping helper function - populate this command's s/g table.
532  */
533 static void
534 pqi_request_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
535 {
536         rcb_t *rcb = (rcb_t *)arg;
537         pqisrc_softstate_t *softs = rcb->softs;
538         union ccb *ccb;
539
540         if (error || nseg > softs->pqi_cap.max_sg_elem) {
541                 DBG_ERR_BTL(rcb->dvp, "map failed err = %d or nseg(%d) > sgelem(%d)\n",
542                         error, nseg, softs->pqi_cap.max_sg_elem);
543                 goto error_io;
544         }
545
546         rcb->sgt = os_mem_alloc(softs, nseg * sizeof(sgt_t));
547
548         if (!rcb->sgt) {
549                 DBG_ERR_BTL(rcb->dvp, "os_mem_alloc() failed; nseg = %d\n", nseg);
550                 goto error_io;
551         }
552
553         rcb->nseg = nseg;
554         for (int i = 0; i < nseg; i++) {
555                 rcb->sgt[i].addr = segs[i].ds_addr;
556                 rcb->sgt[i].len = segs[i].ds_len;
557                 rcb->sgt[i].flags = 0;
558         }
559
560         if (rcb->data_dir == SOP_DATA_DIR_FROM_DEVICE)
561                 bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat,
562                         rcb->cm_datamap, BUS_DMASYNC_PREREAD);
563         if (rcb->data_dir == SOP_DATA_DIR_TO_DEVICE)
564                 bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat,
565                         rcb->cm_datamap, BUS_DMASYNC_PREWRITE);
566
567         /* Call IO functions depending on pd or ld */
568         rcb->status = REQUEST_PENDING;
569
570         error = pqisrc_build_send_io(softs, rcb);
571
572         if (error) {
573                 rcb->req_pending = false;
574                 DBG_ERR_BTL(rcb->dvp, "Build IO failed, error = %d\n", error);
575         } else {
576                 /* Successfully IO was submitted to the device. */
577                 return;
578         }
579
580 error_io:
581         ccb = rcb->cm_ccb;
582         ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
583         pqi_freeze_ccb(ccb);
584         pqi_unmap_request(rcb);
585         xpt_done(ccb);
586         return;
587 }
588
589 /*
590  * Function to dma-map the request buffer
591  */
592 static int
593 pqi_map_request(rcb_t *rcb)
594 {
595         pqisrc_softstate_t *softs = rcb->softs;
596         int bsd_status = BSD_SUCCESS;
597         union ccb *ccb = rcb->cm_ccb;
598
599         DBG_FUNC("IN\n");
600
601         /* check that mapping is necessary */
602         if (rcb->cm_flags & PQI_CMD_MAPPED)
603                 return BSD_SUCCESS;
604
605         rcb->cm_flags |= PQI_CMD_MAPPED;
606
607         if (rcb->bcount) {
608                 bsd_status = bus_dmamap_load_ccb(softs->os_specific.pqi_buffer_dmat,
609                         rcb->cm_datamap, ccb, pqi_request_map_helper, rcb, 0);
610                 if (bsd_status != BSD_SUCCESS && bsd_status != EINPROGRESS) {
611                         DBG_ERR_BTL(rcb->dvp, "bus_dmamap_load_ccb failed, return status = %d transfer length = %d\n",
612                                         bsd_status, rcb->bcount);
613                         return bsd_status;
614                 }
615         } else {
616                 /*
617                  * Set up the command to go to the controller.  If there are no
618                  * data buffers associated with the command then it can bypass
619                  * busdma.
620                  */
621                 /* Call IO functions depending on pd or ld */
622                 rcb->status = REQUEST_PENDING;
623
624                 if (pqisrc_build_send_io(softs, rcb) != PQI_STATUS_SUCCESS) {
625                         bsd_status = EIO;
626                 }
627         }
628
629         DBG_FUNC("OUT error = %d\n", bsd_status);
630
631         return bsd_status;
632 }
633
634 /*
635  * Function to clear the request control block
636  */
637 void
638 os_reset_rcb(rcb_t *rcb)
639 {
640         rcb->error_info = NULL;
641         rcb->req = NULL;
642         rcb->status = -1;
643         rcb->tag = INVALID_ELEM;
644         rcb->dvp = NULL;
645         rcb->cdbp = NULL;
646         rcb->softs = NULL;
647         rcb->cm_flags = 0;
648         rcb->cm_data = NULL;
649         rcb->bcount = 0;
650         rcb->nseg = 0;
651         rcb->sgt = NULL;
652         rcb->cm_ccb = NULL;
653         rcb->encrypt_enable = false;
654         rcb->ioaccel_handle = 0;
655         rcb->resp_qid = 0;
656         rcb->req_pending = false;
657         rcb->tm_req = false;
658 }
659
660 /*
661  * Callback function for the lun rescan
662  */
663 static void
664 smartpqi_lunrescan_cb(struct cam_periph *periph, union ccb *ccb)
665 {
666         xpt_free_path(ccb->ccb_h.path);
667         xpt_free_ccb(ccb);
668 }
669
670
671 /*
672  * Function to rescan the lun
673  */
674 static void
675 smartpqi_lun_rescan(struct pqisrc_softstate *softs, int target,
676                         int lun)
677 {
678         union ccb *ccb = NULL;
679         cam_status status = 0;
680         struct cam_path *path = NULL;
681
682         DBG_FUNC("IN\n");
683
684         ccb = xpt_alloc_ccb_nowait();
685         if (ccb == NULL) {
686                 DBG_ERR("Unable to alloc ccb for lun rescan\n");
687                 return;
688         }
689
690         status = xpt_create_path(&path, NULL,
691                                 cam_sim_path(softs->os_specific.sim), target, lun);
692         if (status != CAM_REQ_CMP) {
693                 DBG_ERR("xpt_create_path status(%d) != CAM_REQ_CMP \n",
694                                  status);
695                 xpt_free_ccb(ccb);
696                 return;
697         }
698
699         bzero(ccb, sizeof(union ccb));
700         xpt_setup_ccb(&ccb->ccb_h, path, 5);
701         ccb->ccb_h.func_code = XPT_SCAN_LUN;
702         ccb->ccb_h.cbfcnp = smartpqi_lunrescan_cb;
703         ccb->crcn.flags = CAM_FLAG_NONE;
704
705         xpt_action(ccb);
706
707         DBG_FUNC("OUT\n");
708 }
709
710 /*
711  * Function to rescan the lun under each target
712  */
713 void
714 smartpqi_target_rescan(struct pqisrc_softstate *softs)
715 {
716         int target = 0, lun = 0;
717
718         DBG_FUNC("IN\n");
719
720         for(target = 0; target < PQI_MAX_DEVICES; target++){
721                 for(lun = 0; lun < PQI_MAX_MULTILUN; lun++){
722                         if(softs->device_list[target][lun]){
723                                 smartpqi_lun_rescan(softs, target, lun);
724                         }
725                 }
726         }
727
728         DBG_FUNC("OUT\n");
729 }
730
731 /*
732  * Set the mode of tagged command queueing for the current task.
733  */
734 uint8_t
735 os_get_task_attr(rcb_t *rcb)
736 {
737         union ccb *ccb = rcb->cm_ccb;
738         uint8_t tag_action = SOP_TASK_ATTRIBUTE_SIMPLE;
739
740         switch(ccb->csio.tag_action) {
741         case MSG_HEAD_OF_Q_TAG:
742                 tag_action = SOP_TASK_ATTRIBUTE_HEAD_OF_QUEUE;
743                 break;
744         case MSG_ORDERED_Q_TAG:
745                 tag_action = SOP_TASK_ATTRIBUTE_ORDERED;
746                 break;
747         case MSG_SIMPLE_Q_TAG:
748         default:
749                 tag_action = SOP_TASK_ATTRIBUTE_SIMPLE;
750                 break;
751         }
752         return tag_action;
753 }
754
755 /*
756  * Complete all outstanding commands
757  */
758 void
759 os_complete_outstanding_cmds_nodevice(pqisrc_softstate_t *softs)
760 {
761         int tag = 0;
762         pqi_scsi_dev_t  *dvp = NULL;
763
764         DBG_FUNC("IN\n");
765
766         for (tag = 1; tag <= softs->max_outstanding_io; tag++) {
767                 rcb_t *prcb = &softs->rcb[tag];
768                 dvp = prcb->dvp;
769                 if(prcb->req_pending && prcb->cm_ccb ) {
770                         prcb->req_pending = false;
771                         prcb->cm_ccb->ccb_h.status = CAM_REQ_ABORTED | CAM_REQ_CMP;
772                         pqi_complete_scsi_io(&prcb->cm_ccb->csio, prcb);
773                         if (dvp)
774                                 pqisrc_decrement_device_active_io(softs, dvp);
775
776                 }
777         }
778
779         DBG_FUNC("OUT\n");
780 }
781
782 /*
783  * IO handling functionality entry point
784  */
785 static int
786 pqisrc_io_start(struct cam_sim *sim, union ccb *ccb)
787 {
788         rcb_t *rcb;
789         uint32_t tag, no_transfer = 0;
790         pqisrc_softstate_t *softs = (struct pqisrc_softstate *)
791                                         cam_sim_softc(sim);
792         int32_t error;
793         pqi_scsi_dev_t *dvp;
794
795         DBG_FUNC("IN\n");
796
797         if (softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun] == NULL) {
798                 ccb->ccb_h.status = CAM_DEV_NOT_THERE;
799                 DBG_INFO("Device  = %d not there\n", ccb->ccb_h.target_id);
800                 return ENXIO;
801         }
802
803         dvp = softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun];
804         /* Check  controller state */
805         if (IN_PQI_RESET(softs)) {
806                 ccb->ccb_h.status = CAM_SCSI_BUS_RESET
807                                         | CAM_BUSY | CAM_REQ_INPROG;
808                 DBG_WARN("Device  = %d BUSY/IN_RESET\n", ccb->ccb_h.target_id);
809                 return ENXIO;
810         }
811         /* Check device state */
812         if (pqisrc_ctrl_offline(softs) || DEV_GONE(dvp)) {
813                 ccb->ccb_h.status = CAM_DEV_NOT_THERE | CAM_REQ_CMP;
814                 DBG_WARN("Device  = %d GONE/OFFLINE\n", ccb->ccb_h.target_id);
815                 return ENXIO;
816         }
817         /* Check device reset */
818         if (DEVICE_RESET(dvp)) {
819                 ccb->ccb_h.status = CAM_SCSI_BUSY | CAM_REQ_INPROG | CAM_BUSY;
820                 DBG_WARN("Device %d reset returned busy\n", ccb->ccb_h.target_id);
821                 return EBUSY;
822         }
823
824         if (dvp->expose_device == false) {
825                 ccb->ccb_h.status = CAM_DEV_NOT_THERE;
826                 DBG_INFO("Device  = %d not exposed\n", ccb->ccb_h.target_id);
827                 return ENXIO;
828         }
829
830         tag = pqisrc_get_tag(&softs->taglist);
831         if (tag == INVALID_ELEM) {
832                 DBG_ERR("Get Tag failed\n");
833                 xpt_freeze_simq(softs->os_specific.sim, 1);
834                 softs->os_specific.pqi_flags |= PQI_FLAG_BUSY;
835                 ccb->ccb_h.status |= (CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ);
836                 return EIO;
837         }
838
839         DBG_IO("tag = %d &softs->taglist : %p\n", tag, &softs->taglist);
840
841         rcb = &softs->rcb[tag];
842         os_reset_rcb(rcb);
843         rcb->tag = tag;
844         rcb->softs = softs;
845         rcb->cmdlen = ccb->csio.cdb_len;
846         ccb->ccb_h.sim_priv.entries[0].ptr = rcb;
847
848         switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
849                 case CAM_DIR_IN:
850                         rcb->data_dir = SOP_DATA_DIR_FROM_DEVICE;
851                         break;
852                 case CAM_DIR_OUT:
853                         rcb->data_dir = SOP_DATA_DIR_TO_DEVICE;
854                         break;
855                 case CAM_DIR_NONE:
856                         no_transfer = 1;
857                         break;
858                 default:
859                         DBG_ERR("Unknown Dir\n");
860                         break;
861         }
862         rcb->cm_ccb = ccb;
863         rcb->dvp = softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun];
864
865         if (!no_transfer) {
866                 rcb->cm_data = (void *)ccb->csio.data_ptr;
867                 rcb->bcount = ccb->csio.dxfer_len;
868         } else {
869                 rcb->cm_data = NULL;
870                 rcb->bcount = 0;
871         }
872         /*
873          * Submit the request to the adapter.
874          *
875          * Note that this may fail if we're unable to map the request (and
876          * if we ever learn a transport layer other than simple, may fail
877          * if the adapter rejects the command).
878          */
879         if ((error = pqi_map_request(rcb)) != BSD_SUCCESS) {
880                 xpt_freeze_simq(softs->os_specific.sim, 1);
881                 if (error == EINPROGRESS) {
882                         /* Release simq in the completion */
883                         softs->os_specific.pqi_flags |= PQI_FLAG_BUSY;
884                         error = BSD_SUCCESS;
885                 } else {
886                         rcb->req_pending = false;
887                         ccb->ccb_h.status |= CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ;
888                         DBG_WARN("Requeue req error = %d target = %d\n", error,
889                                 ccb->ccb_h.target_id);
890                         pqi_unmap_request(rcb);
891                         error = EIO;
892                 }
893         }
894
895         DBG_FUNC("OUT error = %d\n", error);
896
897         return error;
898 }
899
900 static inline int
901 pqi_tmf_status_to_bsd_tmf_status(int pqi_status, rcb_t *rcb)
902 {
903         if (PQI_STATUS_SUCCESS == pqi_status &&
904                         REQUEST_SUCCESS == rcb->status)
905                 return BSD_SUCCESS;
906         else
907                 return EIO;
908 }
909
910 /*
911  * Abort a task, task management functionality
912  */
913 static int
914 pqisrc_scsi_abort_task(pqisrc_softstate_t *softs,  union ccb *ccb)
915 {
916         struct ccb_hdr *ccb_h = &ccb->ccb_h;
917         rcb_t *rcb = NULL;
918         rcb_t *prcb = ccb->ccb_h.sim_priv.entries[0].ptr;
919         uint32_t tag;
920         int rval;
921
922         DBG_FUNC("IN\n");
923
924         tag = pqisrc_get_tag(&softs->taglist);
925         rcb = &softs->rcb[tag];
926         rcb->tag = tag;
927
928         if (!rcb->dvp) {
929                 DBG_ERR("dvp is null, tmf type : 0x%x\n", ccb_h->func_code);
930                 rval = ENXIO;
931                 goto error_tmf;
932         }
933
934         rcb->tm_req = true;
935
936         rval = pqisrc_send_tmf(softs, rcb->dvp, rcb, prcb,
937                 SOP_TASK_MANAGEMENT_FUNCTION_ABORT_TASK);
938
939         if ((rval = pqi_tmf_status_to_bsd_tmf_status(rval, rcb)) == BSD_SUCCESS)
940                 ccb->ccb_h.status = CAM_REQ_ABORTED;
941
942 error_tmf:
943         os_reset_rcb(rcb);
944         pqisrc_put_tag(&softs->taglist, tag);
945
946         DBG_FUNC("OUT rval = %d\n", rval);
947
948         return rval;
949 }
950
951 /*
952  * Abort a taskset, task management functionality
953  */
954 static int
955 pqisrc_scsi_abort_task_set(pqisrc_softstate_t *softs, union ccb *ccb)
956 {
957         struct ccb_hdr *ccb_h = &ccb->ccb_h;
958         rcb_t *rcb = NULL;
959         uint32_t tag;
960         int rval;
961
962         DBG_FUNC("IN\n");
963
964         tag = pqisrc_get_tag(&softs->taglist);
965         rcb = &softs->rcb[tag];
966         rcb->tag = tag;
967
968         if (!rcb->dvp) {
969                 DBG_ERR("dvp is null, tmf type : 0x%x\n", ccb_h->func_code);
970                 rval = ENXIO;
971                 goto error_tmf;
972         }
973
974         rcb->tm_req = true;
975
976         rval = pqisrc_send_tmf(softs, rcb->dvp, rcb, NULL,
977                         SOP_TASK_MANAGEMENT_FUNCTION_ABORT_TASK_SET);
978
979         rval = pqi_tmf_status_to_bsd_tmf_status(rval, rcb);
980
981 error_tmf:
982         os_reset_rcb(rcb);
983         pqisrc_put_tag(&softs->taglist, tag);
984
985         DBG_FUNC("OUT rval = %d\n", rval);
986
987         return rval;
988 }
989
990 /*
991  * Target reset task management functionality
992  */
993 static int
994 pqisrc_target_reset( pqisrc_softstate_t *softs,  union ccb *ccb)
995 {
996         struct ccb_hdr  *ccb_h = &ccb->ccb_h;
997         pqi_scsi_dev_t *devp = softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun];
998         rcb_t *rcb = NULL;
999         uint32_t tag;
1000         int rval;
1001
1002         DBG_FUNC("IN\n");
1003
1004         if (devp == NULL) {
1005                 DBG_ERR("bad target %d, tmf type : 0x%x\n", ccb_h->target_id, ccb_h->func_code);
1006                 return ENXIO;
1007         }
1008
1009         tag = pqisrc_get_tag(&softs->taglist);
1010         rcb = &softs->rcb[tag];
1011         rcb->tag = tag;
1012
1013         devp->reset_in_progress = true;
1014
1015         rcb->tm_req = true;
1016
1017         rval = pqisrc_send_tmf(softs, devp, rcb, NULL,
1018                 SOP_TASK_MANAGEMENT_LUN_RESET);
1019
1020         rval = pqi_tmf_status_to_bsd_tmf_status(rval, rcb);
1021         devp->reset_in_progress = false;
1022
1023         os_reset_rcb(rcb);
1024         pqisrc_put_tag(&softs->taglist, tag);
1025
1026         DBG_FUNC("OUT rval = %d\n", rval);
1027
1028         return rval;
1029
1030 }
1031
1032 /*
1033  * cam entry point of the smartpqi module.
1034  */
1035 static void
1036 smartpqi_cam_action(struct cam_sim *sim, union ccb *ccb)
1037 {
1038         struct pqisrc_softstate *softs = cam_sim_softc(sim);
1039         struct ccb_hdr  *ccb_h = &ccb->ccb_h;
1040
1041         DBG_FUNC("IN\n");
1042
1043         switch (ccb_h->func_code) {
1044                 case XPT_SCSI_IO:
1045                 {
1046                         if(!pqisrc_io_start(sim, ccb)) {
1047                                 return;
1048                         }
1049                         break;
1050                 }
1051                 case XPT_CALC_GEOMETRY:
1052                 {
1053                         struct ccb_calc_geometry *ccg;
1054                         ccg = &ccb->ccg;
1055                         if (ccg->block_size == 0) {
1056                                 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1057                                 ccb->ccb_h.status |= CAM_REQ_INVALID;
1058                                 break;
1059                         }
1060                         cam_calc_geometry(ccg, /* extended */ 1);
1061                         ccb->ccb_h.status = CAM_REQ_CMP;
1062                         break;
1063                 }
1064                 case XPT_PATH_INQ:
1065                 {
1066                         update_sim_properties(sim, &ccb->cpi);
1067                         ccb->ccb_h.status = CAM_REQ_CMP;
1068                         break;
1069                 }
1070                 case XPT_GET_TRAN_SETTINGS:
1071                         get_transport_settings(softs, &ccb->cts);
1072                         ccb->ccb_h.status = CAM_REQ_CMP;
1073                         break;
1074                 case XPT_ABORT:
1075                         if(pqisrc_scsi_abort_task(softs,  ccb)) {
1076                                 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1077                                 xpt_done(ccb);
1078                                 DBG_ERR("Abort task failed on %d\n",
1079                                         ccb->ccb_h.target_id);
1080                                 return;
1081                         }
1082                         break;
1083                 case XPT_TERM_IO:
1084                         if (pqisrc_scsi_abort_task_set(softs,  ccb)) {
1085                                 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1086                                 DBG_ERR("Abort task set failed on %d\n",
1087                                         ccb->ccb_h.target_id);
1088                                 xpt_done(ccb);
1089                                 return;
1090                         }
1091                         break;
1092                 case XPT_RESET_DEV:
1093                         if(pqisrc_target_reset(softs,  ccb)) {
1094                                 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1095                                 DBG_ERR("Target reset failed on %d\n",
1096                                         ccb->ccb_h.target_id);
1097                                 xpt_done(ccb);
1098                                 return;
1099                         } else {
1100                                 ccb->ccb_h.status = CAM_REQ_CMP;
1101                         }
1102                         break;
1103                 case XPT_RESET_BUS:
1104                         ccb->ccb_h.status = CAM_REQ_CMP;
1105                         break;
1106                 case XPT_SET_TRAN_SETTINGS:
1107                         ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1108                         return;
1109                 default:
1110                         DBG_WARN("UNSUPPORTED FUNC CODE\n");
1111                         ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1112                         break;
1113         }
1114         xpt_done(ccb);
1115
1116         DBG_FUNC("OUT\n");
1117 }
1118
1119 /*
1120  * Function to poll the response, when interrupts are unavailable
1121  * This also serves supporting crash dump.
1122  */
1123 static void
1124 smartpqi_poll(struct cam_sim *sim)
1125 {
1126         struct pqisrc_softstate *softs = cam_sim_softc(sim);
1127         int i;
1128
1129         for (i = 1; i < softs->intr_count; i++ )
1130                 pqisrc_process_response_queue(softs, i);
1131 }
1132
1133 /*
1134  * Function to adjust the queue depth of a device
1135  */
1136 void
1137 smartpqi_adjust_queue_depth(struct cam_path *path, uint32_t queue_depth)
1138 {
1139         struct ccb_relsim crs;
1140
1141         DBG_INFO("IN\n");
1142
1143         memset(&crs, 0, sizeof(crs));
1144         xpt_setup_ccb(&crs.ccb_h, path, 5);
1145         crs.ccb_h.func_code = XPT_REL_SIMQ;
1146         crs.ccb_h.flags = CAM_DEV_QFREEZE;
1147         crs.release_flags = RELSIM_ADJUST_OPENINGS;
1148         crs.openings = queue_depth;
1149         xpt_action((union ccb *)&crs);
1150         if(crs.ccb_h.status != CAM_REQ_CMP) {
1151                 printf("XPT_REL_SIMQ failed stat=%d\n", crs.ccb_h.status);
1152         }
1153
1154         DBG_INFO("OUT\n");
1155 }
1156
1157 /*
1158  * Function to register async callback for setting queue depth
1159  */
1160 static void
1161 smartpqi_async(void *callback_arg, u_int32_t code,
1162                 struct cam_path *path, void *arg)
1163 {
1164         struct pqisrc_softstate *softs;
1165         softs = (struct pqisrc_softstate*)callback_arg;
1166
1167         DBG_FUNC("IN\n");
1168
1169         switch (code) {
1170                 case AC_FOUND_DEVICE:
1171                 {
1172                         struct ccb_getdev *cgd;
1173                         cgd = (struct ccb_getdev *)arg;
1174                         if (cgd == NULL) {
1175                                 break;
1176                         }
1177                         uint32_t t_id = cgd->ccb_h.target_id;
1178
1179                         if (t_id <= (PQI_CTLR_INDEX - 1)) {
1180                                 if (softs != NULL) {
1181                                         pqi_scsi_dev_t *dvp = softs->device_list[t_id][cgd->ccb_h.target_lun];
1182                                         if (dvp == NULL) {
1183                                                 DBG_ERR("Target is null, target id=%d\n", t_id);
1184                                                 break;
1185                                         }
1186                                         smartpqi_adjust_queue_depth(path,
1187                                                         dvp->queue_depth);
1188                                 }
1189                         }
1190                         break;
1191                 }
1192                 default:
1193                         break;
1194         }
1195
1196         DBG_FUNC("OUT\n");
1197 }
1198
1199 /*
1200  * Function to register sim with CAM layer for smartpqi driver
1201  */
1202 int
1203 register_sim(struct pqisrc_softstate *softs, int card_index)
1204 {
1205         int max_transactions;
1206         union ccb   *ccb = NULL;
1207         int error;
1208         struct ccb_setasync csa;
1209         struct cam_sim *sim;
1210
1211         DBG_FUNC("IN\n");
1212
1213         max_transactions = softs->max_io_for_scsi_ml;
1214         softs->os_specific.devq = cam_simq_alloc(max_transactions);
1215         if (softs->os_specific.devq == NULL) {
1216                 DBG_ERR("cam_simq_alloc failed txns = %d\n",
1217                         max_transactions);
1218                 return ENOMEM;
1219         }
1220
1221         sim = cam_sim_alloc(smartpqi_cam_action, \
1222                                 smartpqi_poll, "smartpqi", softs, \
1223                                 card_index, &softs->os_specific.cam_lock, \
1224                                 1, max_transactions, softs->os_specific.devq);
1225         if (sim == NULL) {
1226                 DBG_ERR("cam_sim_alloc failed txns = %d\n",
1227                         max_transactions);
1228                 cam_simq_free(softs->os_specific.devq);
1229                 return ENOMEM;
1230         }
1231
1232         softs->os_specific.sim = sim;
1233         mtx_lock(&softs->os_specific.cam_lock);
1234         error = xpt_bus_register(sim, softs->os_specific.pqi_dev, 0);
1235         if (error != CAM_SUCCESS) {
1236                 DBG_ERR("xpt_bus_register failed errno %d\n", error);
1237                 cam_sim_free(softs->os_specific.sim, FALSE);
1238                 cam_simq_free(softs->os_specific.devq);
1239                 mtx_unlock(&softs->os_specific.cam_lock);
1240                 return ENXIO;
1241         }
1242
1243         softs->os_specific.sim_registered = TRUE;
1244         ccb = xpt_alloc_ccb_nowait();
1245         if (ccb == NULL) {
1246                 DBG_ERR("xpt_create_path failed\n");
1247                 return ENXIO;
1248         }
1249
1250         if (xpt_create_path(&ccb->ccb_h.path, NULL,
1251                         cam_sim_path(softs->os_specific.sim),
1252                         CAM_TARGET_WILDCARD,
1253                         CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1254                 DBG_ERR("xpt_create_path failed\n");
1255                 xpt_free_ccb(ccb);
1256                 xpt_bus_deregister(cam_sim_path(softs->os_specific.sim));
1257                 cam_sim_free(softs->os_specific.sim, TRUE);
1258                 mtx_unlock(&softs->os_specific.cam_lock);
1259                 return ENXIO;
1260         }
1261         /*
1262          * Callback to set the queue depth per target which is 
1263          * derived from the FW.
1264          */
1265         softs->os_specific.path = ccb->ccb_h.path;
1266         memset(&csa, 0, sizeof(csa));
1267         xpt_setup_ccb(&csa.ccb_h, softs->os_specific.path, 5);
1268         csa.ccb_h.func_code = XPT_SASYNC_CB;
1269         csa.event_enable = AC_FOUND_DEVICE;
1270         csa.callback = smartpqi_async;
1271         csa.callback_arg = softs;
1272         xpt_action((union ccb *)&csa);
1273         if (csa.ccb_h.status != CAM_REQ_CMP) {
1274                 DBG_ERR("Unable to register smartpqi_aysnc handler: %d!\n", 
1275                         csa.ccb_h.status);
1276         }
1277
1278         mtx_unlock(&softs->os_specific.cam_lock);
1279         DBG_INFO("OUT\n");
1280
1281         return BSD_SUCCESS;
1282 }
1283
1284 /*
1285  * Function to deregister smartpqi sim from cam layer
1286  */
1287 void
1288 deregister_sim(struct pqisrc_softstate *softs)
1289 {
1290         struct ccb_setasync csa;
1291         
1292         DBG_FUNC("IN\n");
1293
1294         if (softs->os_specific.mtx_init) {
1295                 mtx_lock(&softs->os_specific.cam_lock);
1296         }
1297
1298
1299         memset(&csa, 0, sizeof(csa));
1300         xpt_setup_ccb(&csa.ccb_h, softs->os_specific.path, 5);
1301         csa.ccb_h.func_code = XPT_SASYNC_CB;
1302         csa.event_enable = 0;
1303         csa.callback = smartpqi_async;
1304         csa.callback_arg = softs;
1305         xpt_action((union ccb *)&csa);
1306         xpt_free_path(softs->os_specific.path);
1307
1308         if (softs->os_specific.sim) {
1309                 xpt_release_simq(softs->os_specific.sim, 0);
1310                 xpt_bus_deregister(cam_sim_path(softs->os_specific.sim));
1311                 softs->os_specific.sim_registered = FALSE;
1312                 cam_sim_free(softs->os_specific.sim, FALSE);
1313                 softs->os_specific.sim = NULL;
1314         }
1315
1316         if (softs->os_specific.mtx_init) {
1317                 mtx_unlock(&softs->os_specific.cam_lock);
1318         }
1319         if (softs->os_specific.devq != NULL) {
1320                 cam_simq_free(softs->os_specific.devq);
1321         }
1322         if (softs->os_specific.mtx_init) {
1323                 mtx_destroy(&softs->os_specific.cam_lock);
1324                 softs->os_specific.mtx_init = FALSE;
1325         }
1326
1327         mtx_destroy(&softs->os_specific.map_lock);
1328
1329         DBG_FUNC("OUT\n");
1330 }
1331
1332 void
1333 os_rescan_target(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
1334 {
1335        struct cam_path *tmppath;
1336
1337        DBG_FUNC("IN\n");
1338
1339        if(softs->os_specific.sim_registered) {
1340                if (xpt_create_path(&tmppath, NULL,
1341                        cam_sim_path(softs->os_specific.sim),
1342                        device->target, device->lun) != CAM_REQ_CMP) {
1343                        DBG_ERR("unable to create path for async event!!! Bus: %d Target: %d Lun: %d\n",
1344                                device->bus, device->target, device->lun);
1345                        return;
1346                }
1347                xpt_async(AC_INQ_CHANGED, tmppath, NULL);
1348                xpt_free_path(tmppath);
1349        }
1350
1351        device->scsi_rescan = false;
1352
1353        DBG_FUNC("OUT\n");
1354 }