1174604Sscottl/* 2174604Sscottl * Copyright (c) HighPoint Technologies, Inc. 3174604Sscottl * All rights reserved. 4174604Sscottl * 5174604Sscottl * Redistribution and use in source and binary forms, with or without 6174604Sscottl * modification, are permitted provided that the following conditions 7174604Sscottl * are met: 8174604Sscottl * 1. Redistributions of source code must retain the above copyright 9174604Sscottl * notice, this list of conditions and the following disclaimer. 10174604Sscottl * 2. Redistributions in binary form must reproduce the above copyright 11174604Sscottl * notice, this list of conditions and the following disclaimer in the 12174604Sscottl * documentation and/or other materials provided with the distribution. 13174604Sscottl * 14174604Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15174604Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16174604Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17174604Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18174604Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19174604Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20174604Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21174604Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22174604Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23174604Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24174604Sscottl * SUCH DAMAGE. 25174604Sscottl */ 26227912Smarius 27227912Smarius#include <sys/cdefs.h> 28227912Smarius__FBSDID("$FreeBSD$"); 29227912Smarius 30174604Sscottl#include <dev/hptrr/hptrr_config.h> 31176018Sscottl/* $Id: osm_bsd.c,v 1.27 2007/11/22 07:35:49 gmm Exp $ 32174604Sscottl * 33174604Sscottl * HighPoint RAID Driver for FreeBSD 34174604Sscottl * Copyright (C) 2005 HighPoint Technologies, Inc. All Rights Reserved. 35174604Sscottl */ 36174604Sscottl#include <dev/hptrr/os_bsd.h> 37174604Sscottl#include <dev/hptrr/hptintf.h> 38174604Sscottl 39237178Seadlerstatic int attach_generic = 0; 40199043SmavTUNABLE_INT("hw.hptrr.attach_generic", &attach_generic); 41199043Smav 42174604Sscottlstatic int hpt_probe(device_t dev) 43174604Sscottl{ 44174604Sscottl PCI_ID pci_id; 45174604Sscottl HIM *him; 46174604Sscottl int i; 47174604Sscottl PHBA hba; 48174604Sscottl 49199043Smav /* Some of supported chips are used not only by HPT. */ 50199043Smav if (pci_get_vendor(dev) != 0x1103 && !attach_generic) 51199043Smav return (ENXIO); 52174604Sscottl for (him = him_list; him; him = him->next) { 53174604Sscottl for (i=0; him->get_supported_device_id(i, &pci_id); i++) { 54174604Sscottl if ((pci_get_vendor(dev) == pci_id.vid) && 55174604Sscottl (pci_get_device(dev) == pci_id.did)){ 56174604Sscottl KdPrint(("hpt_probe: adapter at PCI %d:%d:%d, IRQ %d", 57174604Sscottl pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev), pci_get_irq(dev) 58174604Sscottl )); 59174604Sscottl device_set_desc(dev, him->name); 60174604Sscottl hba = (PHBA)device_get_softc(dev); 61174604Sscottl memset(hba, 0, sizeof(HBA)); 62174604Sscottl hba->ext_type = EXT_TYPE_HBA; 63174604Sscottl hba->ldm_adapter.him = him; 64174604Sscottl return 0; 65174604Sscottl } 66174604Sscottl } 67174604Sscottl } 68174604Sscottl 69174604Sscottl return (ENXIO); 70174604Sscottl} 71174604Sscottl 72174604Sscottlstatic int hpt_attach(device_t dev) 73174604Sscottl{ 74174604Sscottl PHBA hba = (PHBA)device_get_softc(dev); 75174604Sscottl HIM *him = hba->ldm_adapter.him; 76174604Sscottl PCI_ID pci_id; 77174604Sscottl HPT_UINT size; 78174604Sscottl PVBUS vbus; 79174604Sscottl PVBUS_EXT vbus_ext; 80174604Sscottl 81174604Sscottl KdPrint(("hpt_attach(%d/%d/%d)", pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev))); 82174604Sscottl 83174604Sscottl#if __FreeBSD_version >=440000 84174604Sscottl pci_enable_busmaster(dev); 85174604Sscottl#endif 86174604Sscottl 87174604Sscottl pci_id.vid = pci_get_vendor(dev); 88174604Sscottl pci_id.did = pci_get_device(dev); 89174604Sscottl pci_id.rev = pci_get_revid(dev); 90174604Sscottl 91174604Sscottl size = him->get_adapter_size(&pci_id); 92174604Sscottl hba->ldm_adapter.him_handle = malloc(size, M_DEVBUF, M_WAITOK); 93174604Sscottl if (!hba->ldm_adapter.him_handle) 94174604Sscottl return ENXIO; 95174604Sscottl 96174604Sscottl hba->pcidev = dev; 97174604Sscottl hba->pciaddr.tree = 0; 98174604Sscottl hba->pciaddr.bus = pci_get_bus(dev); 99174604Sscottl hba->pciaddr.device = pci_get_slot(dev); 100174604Sscottl hba->pciaddr.function = pci_get_function(dev); 101174604Sscottl 102174604Sscottl if (!him->create_adapter(&pci_id, hba->pciaddr, hba->ldm_adapter.him_handle, hba)) { 103174604Sscottl free(hba->ldm_adapter.him_handle, M_DEVBUF); 104174604Sscottl return -1; 105174604Sscottl } 106174604Sscottl 107174604Sscottl os_printk("adapter at PCI %d:%d:%d, IRQ %d", 108174604Sscottl hba->pciaddr.bus, hba->pciaddr.device, hba->pciaddr.function, pci_get_irq(dev)); 109174604Sscottl 110174604Sscottl if (!ldm_register_adapter(&hba->ldm_adapter)) { 111174604Sscottl size = ldm_get_vbus_size(); 112174604Sscottl vbus_ext = malloc(sizeof(VBUS_EXT) + size, M_DEVBUF, M_WAITOK); 113174604Sscottl if (!vbus_ext) { 114174604Sscottl free(hba->ldm_adapter.him_handle, M_DEVBUF); 115174604Sscottl return -1; 116174604Sscottl } 117174604Sscottl memset(vbus_ext, 0, sizeof(VBUS_EXT)); 118174604Sscottl vbus_ext->ext_type = EXT_TYPE_VBUS; 119174604Sscottl ldm_create_vbus((PVBUS)vbus_ext->vbus, vbus_ext); 120174604Sscottl ldm_register_adapter(&hba->ldm_adapter); 121174604Sscottl } 122174604Sscottl 123174604Sscottl ldm_for_each_vbus(vbus, vbus_ext) { 124174604Sscottl if (hba->ldm_adapter.vbus==vbus) { 125174604Sscottl hba->vbus_ext = vbus_ext; 126174604Sscottl hba->next = vbus_ext->hba_list; 127174604Sscottl vbus_ext->hba_list = hba; 128174604Sscottl break; 129174604Sscottl } 130174604Sscottl } 131174604Sscottl return 0; 132174604Sscottl} 133174604Sscottl 134174604Sscottl/* 135174604Sscottl * Maybe we'd better to use the bus_dmamem_alloc to alloc DMA memory, 136174604Sscottl * but there are some problems currently (alignment, etc). 137174604Sscottl */ 138174604Sscottlstatic __inline void *__get_free_pages(int order) 139174604Sscottl{ 140174604Sscottl /* don't use low memory - other devices may get starved */ 141174604Sscottl return contigmalloc(PAGE_SIZE<<order, 142174604Sscottl M_DEVBUF, M_WAITOK, BUS_SPACE_MAXADDR_24BIT, BUS_SPACE_MAXADDR, PAGE_SIZE, 0); 143174604Sscottl} 144174604Sscottl 145174604Sscottlstatic __inline void free_pages(void *p, int order) 146174604Sscottl{ 147174604Sscottl contigfree(p, PAGE_SIZE<<order, M_DEVBUF); 148174604Sscottl} 149174604Sscottl 150174604Sscottlstatic int hpt_alloc_mem(PVBUS_EXT vbus_ext) 151174604Sscottl{ 152174604Sscottl PHBA hba; 153174604Sscottl struct freelist *f; 154174604Sscottl HPT_UINT i; 155174604Sscottl void **p; 156174604Sscottl 157174604Sscottl for (hba = vbus_ext->hba_list; hba; hba = hba->next) 158174604Sscottl hba->ldm_adapter.him->get_meminfo(hba->ldm_adapter.him_handle); 159174604Sscottl 160174604Sscottl ldm_get_mem_info((PVBUS)vbus_ext->vbus, 0); 161174604Sscottl 162174604Sscottl for (f=vbus_ext->freelist_head; f; f=f->next) { 163174604Sscottl KdPrint(("%s: %d*%d=%d bytes", 164174604Sscottl f->tag, f->count, f->size, f->count*f->size)); 165174604Sscottl for (i=0; i<f->count; i++) { 166174604Sscottl p = (void **)malloc(f->size, M_DEVBUF, M_WAITOK); 167174604Sscottl if (!p) return (ENXIO); 168174604Sscottl *p = f->head; 169174604Sscottl f->head = p; 170174604Sscottl } 171174604Sscottl } 172174604Sscottl 173174604Sscottl for (f=vbus_ext->freelist_dma_head; f; f=f->next) { 174174604Sscottl int order, size, j; 175174604Sscottl 176174604Sscottl HPT_ASSERT((f->size & (f->alignment-1))==0); 177174604Sscottl 178250032Ssbruno for (order=0, size=PAGE_SIZE; size<f->size; order++, size<<=1) 179250032Ssbruno ; 180174604Sscottl 181174604Sscottl KdPrint(("%s: %d*%d=%d bytes, order %d", 182174604Sscottl f->tag, f->count, f->size, f->count*f->size, order)); 183174604Sscottl HPT_ASSERT(f->alignment<=PAGE_SIZE); 184174604Sscottl 185174604Sscottl for (i=0; i<f->count;) { 186174604Sscottl p = (void **)__get_free_pages(order); 187174604Sscottl if (!p) return -1; 188174604Sscottl for (j = size/f->size; j && i<f->count; i++,j--) { 189174604Sscottl *p = f->head; 190174604Sscottl *(BUS_ADDRESS *)(p+1) = (BUS_ADDRESS)vtophys(p); 191174604Sscottl f->head = p; 192174604Sscottl p = (void **)((unsigned long)p + f->size); 193174604Sscottl } 194174604Sscottl } 195174604Sscottl } 196174604Sscottl 197174604Sscottl HPT_ASSERT(PAGE_SIZE==DMAPOOL_PAGE_SIZE); 198174604Sscottl 199174604Sscottl for (i=0; i<os_max_cache_pages; i++) { 200174604Sscottl p = (void **)__get_free_pages(0); 201174604Sscottl if (!p) return -1; 202174604Sscottl HPT_ASSERT(((HPT_UPTR)p & (DMAPOOL_PAGE_SIZE-1))==0); 203174604Sscottl dmapool_put_page((PVBUS)vbus_ext->vbus, p, (BUS_ADDRESS)vtophys(p)); 204174604Sscottl } 205174604Sscottl 206174604Sscottl return 0; 207174604Sscottl} 208174604Sscottl 209174604Sscottlstatic void hpt_free_mem(PVBUS_EXT vbus_ext) 210174604Sscottl{ 211174604Sscottl struct freelist *f; 212174604Sscottl void *p; 213174604Sscottl int i; 214174604Sscottl BUS_ADDRESS bus; 215174604Sscottl 216174604Sscottl for (f=vbus_ext->freelist_head; f; f=f->next) { 217176939Sscottl#if DBG 218174604Sscottl if (f->count!=f->reserved_count) { 219174604Sscottl KdPrint(("memory leak for freelist %s (%d/%d)", f->tag, f->count, f->reserved_count)); 220174604Sscottl } 221174604Sscottl#endif 222174604Sscottl while ((p=freelist_get(f))) 223174604Sscottl free(p, M_DEVBUF); 224174604Sscottl } 225174604Sscottl 226174604Sscottl for (i=0; i<os_max_cache_pages; i++) { 227174604Sscottl p = dmapool_get_page((PVBUS)vbus_ext->vbus, &bus); 228174604Sscottl HPT_ASSERT(p); 229174604Sscottl free_pages(p, 0); 230174604Sscottl } 231174604Sscottl 232174604Sscottl for (f=vbus_ext->freelist_dma_head; f; f=f->next) { 233174604Sscottl int order, size; 234176939Sscottl#if DBG 235174604Sscottl if (f->count!=f->reserved_count) { 236174604Sscottl KdPrint(("memory leak for dma freelist %s (%d/%d)", f->tag, f->count, f->reserved_count)); 237174604Sscottl } 238174604Sscottl#endif 239174604Sscottl for (order=0, size=PAGE_SIZE; size<f->size; order++, size<<=1) ; 240174604Sscottl 241174604Sscottl while ((p=freelist_get_dma(f, &bus))) { 242174604Sscottl if (order) 243174604Sscottl free_pages(p, order); 244174604Sscottl else { 245174604Sscottl /* can't free immediately since other blocks in this page may still be in the list */ 246174604Sscottl if (((HPT_UPTR)p & (PAGE_SIZE-1))==0) 247174604Sscottl dmapool_put_page((PVBUS)vbus_ext->vbus, p, bus); 248174604Sscottl } 249174604Sscottl } 250174604Sscottl } 251174604Sscottl 252174604Sscottl while ((p = dmapool_get_page((PVBUS)vbus_ext->vbus, &bus))) 253174604Sscottl free_pages(p, 0); 254174604Sscottl} 255174604Sscottl 256174604Sscottlstatic int hpt_init_vbus(PVBUS_EXT vbus_ext) 257174604Sscottl{ 258174604Sscottl PHBA hba; 259174604Sscottl 260174604Sscottl for (hba = vbus_ext->hba_list; hba; hba = hba->next) 261174604Sscottl if (!hba->ldm_adapter.him->initialize(hba->ldm_adapter.him_handle)) { 262174604Sscottl KdPrint(("fail to initialize %p", hba)); 263174604Sscottl return -1; 264174604Sscottl } 265174604Sscottl 266174604Sscottl ldm_initialize_vbus((PVBUS)vbus_ext->vbus, &vbus_ext->hba_list->ldm_adapter); 267174604Sscottl return 0; 268174604Sscottl} 269174604Sscottl 270174604Sscottlstatic void hpt_flush_done(PCOMMAND pCmd) 271174604Sscottl{ 272174604Sscottl PVDEV vd = pCmd->target; 273174604Sscottl 274176018Sscottl if (mIsArray(vd->type) && vd->u.array.transform && vd!=vd->u.array.transform->target) { 275174604Sscottl vd = vd->u.array.transform->target; 276174604Sscottl HPT_ASSERT(vd); 277174604Sscottl pCmd->target = vd; 278174604Sscottl pCmd->Result = RETURN_PENDING; 279174604Sscottl vdev_queue_cmd(pCmd); 280174604Sscottl return; 281174604Sscottl } 282174604Sscottl 283174604Sscottl *(int *)pCmd->priv = 1; 284174604Sscottl wakeup(pCmd); 285174604Sscottl} 286174604Sscottl 287174604Sscottl/* 288174604Sscottl * flush a vdev (without retry). 289174604Sscottl */ 290174604Sscottlstatic int hpt_flush_vdev(PVBUS_EXT vbus_ext, PVDEV vd) 291174604Sscottl{ 292174604Sscottl PCOMMAND pCmd; 293174604Sscottl int result = 0, done; 294174604Sscottl HPT_UINT count; 295174604Sscottl 296174604Sscottl KdPrint(("flusing dev %p", vd)); 297174604Sscottl 298174604Sscottl hpt_lock_vbus(vbus_ext); 299174604Sscottl 300176018Sscottl if (mIsArray(vd->type) && vd->u.array.transform) 301174604Sscottl count = MAX(vd->u.array.transform->source->cmds_per_request, 302174604Sscottl vd->u.array.transform->target->cmds_per_request); 303174604Sscottl else 304174604Sscottl count = vd->cmds_per_request; 305174604Sscottl 306174604Sscottl pCmd = ldm_alloc_cmds(vd->vbus, count); 307174604Sscottl 308174604Sscottl if (!pCmd) { 309174604Sscottl hpt_unlock_vbus(vbus_ext); 310174604Sscottl return -1; 311174604Sscottl } 312174604Sscottl 313174604Sscottl pCmd->type = CMD_TYPE_FLUSH; 314174604Sscottl pCmd->flags.hard_flush = 1; 315174604Sscottl pCmd->target = vd; 316174604Sscottl pCmd->done = hpt_flush_done; 317174604Sscottl done = 0; 318174604Sscottl pCmd->priv = &done; 319174604Sscottl 320174604Sscottl ldm_queue_cmd(pCmd); 321174604Sscottl 322174604Sscottl if (!done) { 323174604Sscottl while (hpt_sleep(vbus_ext, pCmd, PPAUSE, "hptfls", HPT_OSM_TIMEOUT)) { 324174604Sscottl ldm_reset_vbus(vd->vbus); 325174604Sscottl } 326174604Sscottl } 327174604Sscottl 328174604Sscottl KdPrint(("flush result %d", pCmd->Result)); 329174604Sscottl 330174604Sscottl if (pCmd->Result!=RETURN_SUCCESS) 331174604Sscottl result = -1; 332174604Sscottl 333174604Sscottl ldm_free_cmds(pCmd); 334174604Sscottl 335174604Sscottl hpt_unlock_vbus(vbus_ext); 336174604Sscottl 337174604Sscottl return result; 338174604Sscottl} 339174604Sscottl 340174604Sscottlstatic void hpt_stop_tasks(PVBUS_EXT vbus_ext); 341174604Sscottlstatic void hpt_shutdown_vbus(PVBUS_EXT vbus_ext, int howto) 342174604Sscottl{ 343174604Sscottl PVBUS vbus = (PVBUS)vbus_ext->vbus; 344174604Sscottl PHBA hba; 345174604Sscottl int i; 346174604Sscottl 347174604Sscottl KdPrint(("hpt_shutdown_vbus")); 348174604Sscottl 349174604Sscottl /* stop all ctl tasks and disable the worker taskqueue */ 350174604Sscottl hpt_stop_tasks(vbus_ext); 351174604Sscottl vbus_ext->worker.ta_context = 0; 352174604Sscottl 353174604Sscottl /* flush devices */ 354174604Sscottl for (i=0; i<osm_max_targets; i++) { 355174604Sscottl PVDEV vd = ldm_find_target(vbus, i); 356174604Sscottl if (vd) { 357174604Sscottl /* retry once */ 358174604Sscottl if (hpt_flush_vdev(vbus_ext, vd)) 359174604Sscottl hpt_flush_vdev(vbus_ext, vd); 360174604Sscottl } 361174604Sscottl } 362174604Sscottl 363174604Sscottl hpt_lock_vbus(vbus_ext); 364174604Sscottl ldm_shutdown(vbus); 365174604Sscottl hpt_unlock_vbus(vbus_ext); 366174604Sscottl 367174604Sscottl ldm_release_vbus(vbus); 368174604Sscottl 369174604Sscottl for (hba=vbus_ext->hba_list; hba; hba=hba->next) 370174604Sscottl bus_teardown_intr(hba->pcidev, hba->irq_res, hba->irq_handle); 371174604Sscottl 372174604Sscottl hpt_free_mem(vbus_ext); 373174604Sscottl 374174604Sscottl while ((hba=vbus_ext->hba_list)) { 375174604Sscottl vbus_ext->hba_list = hba->next; 376174604Sscottl free(hba->ldm_adapter.him_handle, M_DEVBUF); 377174604Sscottl } 378174604Sscottl 379174604Sscottl free(vbus_ext, M_DEVBUF); 380174604Sscottl KdPrint(("hpt_shutdown_vbus done")); 381174604Sscottl} 382174604Sscottl 383174604Sscottlstatic void __hpt_do_tasks(PVBUS_EXT vbus_ext) 384174604Sscottl{ 385174604Sscottl OSM_TASK *tasks; 386174604Sscottl 387174604Sscottl tasks = vbus_ext->tasks; 388174604Sscottl vbus_ext->tasks = 0; 389174604Sscottl 390174604Sscottl while (tasks) { 391174604Sscottl OSM_TASK *t = tasks; 392174604Sscottl tasks = t->next; 393174604Sscottl t->next = 0; 394174604Sscottl t->func(vbus_ext->vbus, t->data); 395174604Sscottl } 396174604Sscottl} 397174604Sscottl 398174604Sscottlstatic void hpt_do_tasks(PVBUS_EXT vbus_ext, int pending) 399174604Sscottl{ 400174604Sscottl if(vbus_ext){ 401174604Sscottl hpt_lock_vbus(vbus_ext); 402174604Sscottl __hpt_do_tasks(vbus_ext); 403174604Sscottl hpt_unlock_vbus(vbus_ext); 404174604Sscottl } 405174604Sscottl} 406174604Sscottl 407174604Sscottlstatic void hpt_action(struct cam_sim *sim, union ccb *ccb); 408174604Sscottlstatic void hpt_poll(struct cam_sim *sim); 409174604Sscottlstatic void hpt_async(void * callback_arg, u_int32_t code, struct cam_path * path, void * arg); 410174604Sscottlstatic void hpt_pci_intr(void *arg); 411174604Sscottl 412174604Sscottlstatic __inline POS_CMDEXT cmdext_get(PVBUS_EXT vbus_ext) 413174604Sscottl{ 414174604Sscottl POS_CMDEXT p = vbus_ext->cmdext_list; 415174604Sscottl if (p) 416174604Sscottl vbus_ext->cmdext_list = p->next; 417174604Sscottl return p; 418174604Sscottl} 419174604Sscottl 420174604Sscottlstatic __inline void cmdext_put(POS_CMDEXT p) 421174604Sscottl{ 422174604Sscottl p->next = p->vbus_ext->cmdext_list; 423174604Sscottl p->vbus_ext->cmdext_list = p; 424174604Sscottl} 425174604Sscottl 426174604Sscottlstatic void hpt_timeout(void *arg) 427174604Sscottl{ 428174604Sscottl PCOMMAND pCmd = (PCOMMAND)arg; 429174604Sscottl POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv; 430174604Sscottl 431174604Sscottl KdPrint(("pCmd %p timeout", pCmd)); 432174604Sscottl 433174604Sscottl ldm_reset_vbus((PVBUS)ext->vbus_ext->vbus); 434174604Sscottl} 435174604Sscottl 436174604Sscottlstatic void os_cmddone(PCOMMAND pCmd) 437174604Sscottl{ 438174604Sscottl POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv; 439174604Sscottl union ccb *ccb = ext->ccb; 440174604Sscottl 441174604Sscottl KdPrint(("os_cmddone(%p, %d)", pCmd, pCmd->Result)); 442174604Sscottl 443255871Sscottl untimeout(hpt_timeout, pCmd, ext->timeout_ch); 444174604Sscottl 445174604Sscottl switch(pCmd->Result) { 446174604Sscottl case RETURN_SUCCESS: 447174604Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 448174604Sscottl break; 449174604Sscottl case RETURN_BAD_DEVICE: 450174604Sscottl ccb->ccb_h.status = CAM_DEV_NOT_THERE; 451174604Sscottl break; 452174604Sscottl case RETURN_DEVICE_BUSY: 453174604Sscottl ccb->ccb_h.status = CAM_BUSY; 454174604Sscottl break; 455174604Sscottl case RETURN_INVALID_REQUEST: 456174604Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 457174604Sscottl break; 458174604Sscottl case RETURN_SELECTION_TIMEOUT: 459174604Sscottl ccb->ccb_h.status = CAM_SEL_TIMEOUT; 460174604Sscottl break; 461174604Sscottl case RETURN_RETRY: 462174604Sscottl ccb->ccb_h.status = CAM_BUSY; 463174604Sscottl break; 464174604Sscottl default: 465174604Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 466174604Sscottl break; 467174604Sscottl } 468174604Sscottl 469174604Sscottl if (pCmd->flags.data_in) { 470174604Sscottl bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, BUS_DMASYNC_POSTREAD); 471174604Sscottl } 472174604Sscottl else if (pCmd->flags.data_out) { 473174604Sscottl bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, BUS_DMASYNC_POSTWRITE); 474174604Sscottl } 475174604Sscottl 476174604Sscottl bus_dmamap_unload(ext->vbus_ext->io_dmat, ext->dma_map); 477174604Sscottl 478174604Sscottl cmdext_put(ext); 479174604Sscottl ldm_free_cmds(pCmd); 480174604Sscottl xpt_done(ccb); 481174604Sscottl} 482174604Sscottl 483174604Sscottlstatic int os_buildsgl(PCOMMAND pCmd, PSG pSg, int logical) 484174604Sscottl{ 485174604Sscottl 486174604Sscottl /* since we have provided physical sg, nobody will ask us to build physical sg */ 487174604Sscottl HPT_ASSERT(0); 488174604Sscottl return FALSE; 489174604Sscottl} 490174604Sscottl 491174604Sscottlstatic void hpt_io_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 492174604Sscottl{ 493174604Sscottl PCOMMAND pCmd = (PCOMMAND)arg; 494174604Sscottl POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv; 495174604Sscottl PSG psg = pCmd->psg; 496174604Sscottl int idx; 497174604Sscottl 498174604Sscottl HPT_ASSERT(pCmd->flags.physical_sg); 499174604Sscottl 500246713Skib if (error) 501174604Sscottl panic("busdma error"); 502174604Sscottl 503174604Sscottl HPT_ASSERT(nsegs<=os_max_sg_descriptors); 504174604Sscottl 505246713Skib if (nsegs != 0) { 506246713Skib for (idx = 0; idx < nsegs; idx++, psg++) { 507246713Skib psg->addr.bus = segs[idx].ds_addr; 508246713Skib psg->size = segs[idx].ds_len; 509246713Skib psg->eot = 0; 510246713Skib } 511246713Skib psg[-1].eot = 1; 512246713Skib 513246713Skib if (pCmd->flags.data_in) { 514246713Skib bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, 515246713Skib BUS_DMASYNC_PREREAD); 516246713Skib } 517246713Skib else if (pCmd->flags.data_out) { 518246713Skib bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, 519246713Skib BUS_DMASYNC_PREWRITE); 520246713Skib } 521174604Sscottl } 522255871Sscottl ext->timeout_ch = timeout(hpt_timeout, pCmd, HPT_OSM_TIMEOUT); 523174604Sscottl ldm_queue_cmd(pCmd); 524174604Sscottl} 525174604Sscottl 526174604Sscottlstatic void hpt_scsi_io(PVBUS_EXT vbus_ext, union ccb *ccb) 527174604Sscottl{ 528174604Sscottl PVBUS vbus = (PVBUS)vbus_ext->vbus; 529174604Sscottl PVDEV vd; 530174604Sscottl PCOMMAND pCmd; 531174604Sscottl POS_CMDEXT ext; 532174604Sscottl HPT_U8 *cdb; 533174604Sscottl 534174604Sscottl if (ccb->ccb_h.flags & CAM_CDB_POINTER) 535174604Sscottl cdb = ccb->csio.cdb_io.cdb_ptr; 536174604Sscottl else 537174604Sscottl cdb = ccb->csio.cdb_io.cdb_bytes; 538174604Sscottl 539174604Sscottl KdPrint(("hpt_scsi_io: ccb %x id %d lun %d cdb %x-%x-%x", 540174604Sscottl ccb, 541174604Sscottl ccb->ccb_h.target_id, ccb->ccb_h.target_lun, 542174604Sscottl *(HPT_U32 *)&cdb[0], *(HPT_U32 *)&cdb[4], *(HPT_U32 *)&cdb[8] 543174604Sscottl )); 544174604Sscottl 545174604Sscottl /* ccb->ccb_h.path_id is not our bus id - don't check it */ 546174604Sscottl if (ccb->ccb_h.target_lun != 0 || 547174604Sscottl ccb->ccb_h.target_id >= osm_max_targets || 548174604Sscottl (ccb->ccb_h.flags & CAM_CDB_PHYS)) 549174604Sscottl { 550174604Sscottl ccb->ccb_h.status = CAM_TID_INVALID; 551174604Sscottl xpt_done(ccb); 552174604Sscottl return; 553174604Sscottl } 554174604Sscottl 555174604Sscottl vd = ldm_find_target(vbus, ccb->ccb_h.target_id); 556174604Sscottl 557174604Sscottl if (!vd) { 558174604Sscottl ccb->ccb_h.status = CAM_TID_INVALID; 559174604Sscottl xpt_done(ccb); 560174604Sscottl return; 561174604Sscottl } 562174604Sscottl 563174604Sscottl switch (cdb[0]) { 564174604Sscottl case TEST_UNIT_READY: 565174604Sscottl case START_STOP_UNIT: 566174604Sscottl case SYNCHRONIZE_CACHE: 567174604Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 568174604Sscottl break; 569174604Sscottl 570174604Sscottl case INQUIRY: 571174604Sscottl { 572174604Sscottl PINQUIRYDATA inquiryData; 573174604Sscottl memset(ccb->csio.data_ptr, 0, ccb->csio.dxfer_len); 574174604Sscottl inquiryData = (PINQUIRYDATA)ccb->csio.data_ptr; 575174604Sscottl 576174604Sscottl inquiryData->AdditionalLength = 31; 577174604Sscottl inquiryData->CommandQueue = 1; 578174604Sscottl memcpy(&inquiryData->VendorId, "HPT ", 8); 579174604Sscottl memcpy(&inquiryData->ProductId, "DISK 0_0 ", 16); 580174604Sscottl 581174604Sscottl if (vd->target_id / 10) { 582174604Sscottl inquiryData->ProductId[7] = (vd->target_id % 100) / 10 + '0'; 583174604Sscottl inquiryData->ProductId[8] = (vd->target_id % 100) % 10 + '0'; 584174604Sscottl } 585174604Sscottl else 586174604Sscottl inquiryData->ProductId[7] = (vd->target_id % 100) % 10 + '0'; 587174604Sscottl 588174604Sscottl memcpy(&inquiryData->ProductRevisionLevel, "4.00", 4); 589174604Sscottl 590174604Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 591174604Sscottl } 592174604Sscottl break; 593174604Sscottl 594174604Sscottl case READ_CAPACITY: 595174604Sscottl { 596174604Sscottl HPT_U8 *rbuf = ccb->csio.data_ptr; 597174604Sscottl HPT_U32 cap; 598174604Sscottl 599174604Sscottl if (vd->capacity>0xfffffffful) 600174604Sscottl cap = 0xfffffffful; 601174604Sscottl else 602174604Sscottl cap = vd->capacity - 1; 603174604Sscottl 604174604Sscottl rbuf[0] = (HPT_U8)(cap>>24); 605174604Sscottl rbuf[1] = (HPT_U8)(cap>>16); 606174604Sscottl rbuf[2] = (HPT_U8)(cap>>8); 607174604Sscottl rbuf[3] = (HPT_U8)cap; 608174604Sscottl rbuf[4] = 0; 609174604Sscottl rbuf[5] = 0; 610174604Sscottl rbuf[6] = 2; 611174604Sscottl rbuf[7] = 0; 612174604Sscottl 613174604Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 614174604Sscottl break; 615174604Sscottl } 616174604Sscottl 617174604Sscottl case SERVICE_ACTION_IN: 618174604Sscottl { 619174604Sscottl HPT_U8 *rbuf = ccb->csio.data_ptr; 620174604Sscottl HPT_U64 cap = vd->capacity - 1; 621174604Sscottl 622174604Sscottl rbuf[0] = (HPT_U8)(cap>>56); 623174604Sscottl rbuf[1] = (HPT_U8)(cap>>48); 624174604Sscottl rbuf[2] = (HPT_U8)(cap>>40); 625174604Sscottl rbuf[3] = (HPT_U8)(cap>>32); 626174604Sscottl rbuf[4] = (HPT_U8)(cap>>24); 627174604Sscottl rbuf[5] = (HPT_U8)(cap>>16); 628174604Sscottl rbuf[6] = (HPT_U8)(cap>>8); 629174604Sscottl rbuf[7] = (HPT_U8)cap; 630174604Sscottl rbuf[8] = 0; 631174604Sscottl rbuf[9] = 0; 632174604Sscottl rbuf[10] = 2; 633174604Sscottl rbuf[11] = 0; 634174604Sscottl 635174604Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 636174604Sscottl break; 637174604Sscottl } 638174604Sscottl 639174604Sscottl case READ_6: 640174604Sscottl case READ_10: 641174604Sscottl case READ_16: 642174604Sscottl case WRITE_6: 643174604Sscottl case WRITE_10: 644174604Sscottl case WRITE_16: 645174604Sscottl case 0x13: 646174604Sscottl case 0x2f: 647174604Sscottl { 648246713Skib int error; 649246713Skib 650174604Sscottl pCmd = ldm_alloc_cmds(vbus, vd->cmds_per_request); 651174604Sscottl if(!pCmd){ 652174604Sscottl KdPrint(("Failed to allocate command!")); 653174604Sscottl ccb->ccb_h.status = CAM_BUSY; 654174604Sscottl break; 655174604Sscottl } 656174604Sscottl 657174604Sscottl switch (cdb[0]) { 658174604Sscottl case READ_6: 659174604Sscottl case WRITE_6: 660174604Sscottl case 0x13: 661174604Sscottl pCmd->uCmd.Ide.Lba = ((HPT_U32)cdb[1] << 16) | ((HPT_U32)cdb[2] << 8) | (HPT_U32)cdb[3]; 662174604Sscottl pCmd->uCmd.Ide.nSectors = (HPT_U16) cdb[4]; 663174604Sscottl break; 664174604Sscottl case READ_16: 665174604Sscottl case WRITE_16: 666174604Sscottl { 667174604Sscottl HPT_U64 block = 668174604Sscottl ((HPT_U64)cdb[2]<<56) | 669174604Sscottl ((HPT_U64)cdb[3]<<48) | 670174604Sscottl ((HPT_U64)cdb[4]<<40) | 671174604Sscottl ((HPT_U64)cdb[5]<<32) | 672174604Sscottl ((HPT_U64)cdb[6]<<24) | 673174604Sscottl ((HPT_U64)cdb[7]<<16) | 674174604Sscottl ((HPT_U64)cdb[8]<<8) | 675174604Sscottl ((HPT_U64)cdb[9]); 676174604Sscottl pCmd->uCmd.Ide.Lba = block; 677174604Sscottl pCmd->uCmd.Ide.nSectors = (HPT_U16)cdb[13] | ((HPT_U16)cdb[12]<<8); 678174604Sscottl break; 679174604Sscottl } 680174604Sscottl 681174604Sscottl default: 682174604Sscottl pCmd->uCmd.Ide.Lba = (HPT_U32)cdb[5] | ((HPT_U32)cdb[4] << 8) | ((HPT_U32)cdb[3] << 16) | ((HPT_U32)cdb[2] << 24); 683174604Sscottl pCmd->uCmd.Ide.nSectors = (HPT_U16) cdb[8] | ((HPT_U16)cdb[7]<<8); 684174604Sscottl break; 685174604Sscottl } 686174604Sscottl 687174604Sscottl switch (cdb[0]) { 688174604Sscottl case READ_6: 689174604Sscottl case READ_10: 690174604Sscottl case READ_16: 691174604Sscottl pCmd->flags.data_in = 1; 692174604Sscottl break; 693174604Sscottl case WRITE_6: 694174604Sscottl case WRITE_10: 695174604Sscottl case WRITE_16: 696174604Sscottl pCmd->flags.data_out = 1; 697174604Sscottl break; 698174604Sscottl } 699174604Sscottl pCmd->priv = ext = cmdext_get(vbus_ext); 700174604Sscottl HPT_ASSERT(ext); 701174604Sscottl ext->ccb = ccb; 702174604Sscottl pCmd->target = vd; 703174604Sscottl pCmd->done = os_cmddone; 704174604Sscottl pCmd->buildsgl = os_buildsgl; 705174604Sscottl pCmd->psg = ext->psg; 706246713Skib pCmd->flags.physical_sg = 1; 707246713Skib error = bus_dmamap_load_ccb(vbus_ext->io_dmat, 708246713Skib ext->dma_map, 709246713Skib ccb, 710246713Skib hpt_io_dmamap_callback, pCmd, 711246713Skib BUS_DMA_WAITOK 712174604Sscottl ); 713246713Skib KdPrint(("bus_dmamap_load return %d", error)); 714246713Skib if (error && error!=EINPROGRESS) { 715246713Skib os_printk("bus_dmamap_load error %d", error); 716246713Skib cmdext_put(ext); 717246713Skib ldm_free_cmds(pCmd); 718246713Skib ccb->ccb_h.status = CAM_REQ_CMP_ERR; 719246713Skib xpt_done(ccb); 720174604Sscottl } 721174604Sscottl return; 722174604Sscottl } 723174604Sscottl 724174604Sscottl default: 725174604Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 726174604Sscottl break; 727174604Sscottl } 728174604Sscottl 729174604Sscottl xpt_done(ccb); 730174604Sscottl return; 731174604Sscottl} 732174604Sscottl 733174604Sscottlstatic void hpt_action(struct cam_sim *sim, union ccb *ccb) 734174604Sscottl{ 735174604Sscottl PVBUS_EXT vbus_ext = (PVBUS_EXT)cam_sim_softc(sim); 736174604Sscottl 737174604Sscottl KdPrint(("hpt_action(fn=%d, id=%d)", ccb->ccb_h.func_code, ccb->ccb_h.target_id)); 738174604Sscottl 739174604Sscottl switch (ccb->ccb_h.func_code) { 740174604Sscottl 741174604Sscottl case XPT_SCSI_IO: 742174604Sscottl hpt_lock_vbus(vbus_ext); 743174604Sscottl hpt_scsi_io(vbus_ext, ccb); 744174604Sscottl hpt_unlock_vbus(vbus_ext); 745174604Sscottl return; 746174604Sscottl 747174604Sscottl case XPT_RESET_BUS: 748174604Sscottl hpt_lock_vbus(vbus_ext); 749174604Sscottl ldm_reset_vbus((PVBUS)vbus_ext->vbus); 750174604Sscottl hpt_unlock_vbus(vbus_ext); 751174604Sscottl break; 752174604Sscottl 753174604Sscottl case XPT_GET_TRAN_SETTINGS: 754174604Sscottl case XPT_SET_TRAN_SETTINGS: 755174604Sscottl ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 756174604Sscottl break; 757174604Sscottl 758174604Sscottl case XPT_CALC_GEOMETRY: 759227912Smarius#if __FreeBSD_version >= 500000 760227912Smarius cam_calc_geometry(&ccb->ccg, 1); 761227912Smarius#else 762174604Sscottl ccb->ccg.heads = 255; 763174604Sscottl ccb->ccg.secs_per_track = 63; 764174604Sscottl ccb->ccg.cylinders = ccb->ccg.volume_size / (ccb->ccg.heads * ccb->ccg.secs_per_track); 765174604Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 766227912Smarius#endif 767174604Sscottl break; 768174604Sscottl 769174604Sscottl case XPT_PATH_INQ: 770174604Sscottl { 771174604Sscottl struct ccb_pathinq *cpi = &ccb->cpi; 772174604Sscottl 773174604Sscottl cpi->version_num = 1; 774174604Sscottl cpi->hba_inquiry = PI_SDTR_ABLE; 775174604Sscottl cpi->target_sprt = 0; 776174604Sscottl cpi->hba_misc = PIM_NOBUSRESET; 777174604Sscottl cpi->hba_eng_cnt = 0; 778174604Sscottl cpi->max_target = osm_max_targets; 779174604Sscottl cpi->max_lun = 0; 780174604Sscottl cpi->unit_number = cam_sim_unit(sim); 781174604Sscottl cpi->bus_id = cam_sim_bus(sim); 782174604Sscottl cpi->initiator_id = osm_max_targets; 783174604Sscottl cpi->base_transfer_speed = 3300; 784174604Sscottl 785174604Sscottl strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 786174604Sscottl strncpy(cpi->hba_vid, "HPT ", HBA_IDLEN); 787174604Sscottl strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 788196415Skensmith cpi->transport = XPORT_SPI; 789196415Skensmith cpi->transport_version = 2; 790196415Skensmith cpi->protocol = PROTO_SCSI; 791196415Skensmith cpi->protocol_version = SCSI_REV_2; 792174604Sscottl cpi->ccb_h.status = CAM_REQ_CMP; 793174604Sscottl break; 794174604Sscottl } 795174604Sscottl 796174604Sscottl default: 797174604Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 798174604Sscottl break; 799174604Sscottl } 800174604Sscottl 801174604Sscottl xpt_done(ccb); 802174604Sscottl return; 803174604Sscottl} 804174604Sscottl 805174604Sscottlstatic void hpt_pci_intr(void *arg) 806174604Sscottl{ 807174604Sscottl PVBUS_EXT vbus_ext = (PVBUS_EXT)arg; 808174604Sscottl hpt_lock_vbus(vbus_ext); 809174604Sscottl ldm_intr((PVBUS)vbus_ext->vbus); 810174604Sscottl hpt_unlock_vbus(vbus_ext); 811174604Sscottl} 812174604Sscottl 813174604Sscottlstatic void hpt_poll(struct cam_sim *sim) 814174604Sscottl{ 815174604Sscottl hpt_pci_intr(cam_sim_softc(sim)); 816174604Sscottl} 817174604Sscottl 818174604Sscottlstatic void hpt_async(void * callback_arg, u_int32_t code, struct cam_path * path, void * arg) 819174604Sscottl{ 820174604Sscottl KdPrint(("hpt_async")); 821174604Sscottl} 822174604Sscottl 823174604Sscottlstatic int hpt_shutdown(device_t dev) 824174604Sscottl{ 825174604Sscottl KdPrint(("hpt_shutdown(dev=%p)", dev)); 826174604Sscottl return 0; 827174604Sscottl} 828174604Sscottl 829174604Sscottlstatic int hpt_detach(device_t dev) 830174604Sscottl{ 831174604Sscottl /* we don't allow the driver to be unloaded. */ 832174604Sscottl return EBUSY; 833174604Sscottl} 834174604Sscottl 835174604Sscottlstatic void hpt_ioctl_done(struct _IOCTL_ARG *arg) 836174604Sscottl{ 837174604Sscottl arg->ioctl_cmnd = 0; 838174604Sscottl wakeup(arg); 839174604Sscottl} 840174604Sscottl 841174604Sscottlstatic void __hpt_do_ioctl(PVBUS_EXT vbus_ext, IOCTL_ARG *ioctl_args) 842174604Sscottl{ 843174604Sscottl ioctl_args->result = -1; 844174604Sscottl ioctl_args->done = hpt_ioctl_done; 845174604Sscottl ioctl_args->ioctl_cmnd = (void *)1; 846174604Sscottl 847174604Sscottl hpt_lock_vbus(vbus_ext); 848174604Sscottl ldm_ioctl((PVBUS)vbus_ext->vbus, ioctl_args); 849174604Sscottl 850174604Sscottl while (ioctl_args->ioctl_cmnd) { 851174604Sscottl if (hpt_sleep(vbus_ext, ioctl_args, PPAUSE, "hptctl", HPT_OSM_TIMEOUT)==0) 852174604Sscottl break; 853174604Sscottl ldm_reset_vbus((PVBUS)vbus_ext->vbus); 854174604Sscottl __hpt_do_tasks(vbus_ext); 855174604Sscottl } 856174604Sscottl 857174604Sscottl /* KdPrint(("ioctl %x result %d", ioctl_args->dwIoControlCode, ioctl_args->result)); */ 858174604Sscottl 859174604Sscottl hpt_unlock_vbus(vbus_ext); 860174604Sscottl} 861174604Sscottl 862174604Sscottlstatic void hpt_do_ioctl(IOCTL_ARG *ioctl_args) 863174604Sscottl{ 864174604Sscottl PVBUS vbus; 865174604Sscottl PVBUS_EXT vbus_ext; 866174604Sscottl 867174604Sscottl ldm_for_each_vbus(vbus, vbus_ext) { 868174604Sscottl __hpt_do_ioctl(vbus_ext, ioctl_args); 869174604Sscottl if (ioctl_args->result!=HPT_IOCTL_RESULT_WRONG_VBUS) 870174604Sscottl return; 871174604Sscottl } 872174604Sscottl} 873174604Sscottl 874174604Sscottl#define HPT_DO_IOCTL(code, inbuf, insize, outbuf, outsize) ({\ 875174604Sscottl IOCTL_ARG arg;\ 876174604Sscottl arg.dwIoControlCode = code;\ 877174604Sscottl arg.lpInBuffer = inbuf;\ 878174604Sscottl arg.lpOutBuffer = outbuf;\ 879174604Sscottl arg.nInBufferSize = insize;\ 880174604Sscottl arg.nOutBufferSize = outsize;\ 881174604Sscottl arg.lpBytesReturned = 0;\ 882174604Sscottl hpt_do_ioctl(&arg);\ 883174604Sscottl arg.result;\ 884174604Sscottl}) 885174604Sscottl 886174604Sscottl#define DEVICEID_VALID(id) ((id) && ((HPT_U32)(id)!=0xffffffff)) 887174604Sscottl 888174604Sscottlstatic int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount) 889174604Sscottl{ 890174604Sscottl int i; 891174604Sscottl HPT_U32 count = nMaxCount-1; 892174604Sscottl 893174604Sscottl if (HPT_DO_IOCTL(HPT_IOCTL_GET_LOGICAL_DEVICES, 894174604Sscottl &count, sizeof(HPT_U32), pIds, sizeof(DEVICEID)*nMaxCount)) 895174604Sscottl return -1; 896174604Sscottl 897174604Sscottl nMaxCount = (int)pIds[0]; 898174604Sscottl for (i=0; i<nMaxCount; i++) pIds[i] = pIds[i+1]; 899174604Sscottl return nMaxCount; 900174604Sscottl} 901174604Sscottl 902174604Sscottlstatic int hpt_get_device_info_v3(DEVICEID id, PLOGICAL_DEVICE_INFO_V3 pInfo) 903174604Sscottl{ 904174604Sscottl return HPT_DO_IOCTL(HPT_IOCTL_GET_DEVICE_INFO_V3, 905174604Sscottl &id, sizeof(DEVICEID), pInfo, sizeof(LOGICAL_DEVICE_INFO_V3)); 906174604Sscottl} 907174604Sscottl 908174604Sscottl/* not belong to this file logically, but we want to use ioctl interface */ 909174604Sscottlstatic int __hpt_stop_tasks(PVBUS_EXT vbus_ext, DEVICEID id) 910174604Sscottl{ 911174604Sscottl LOGICAL_DEVICE_INFO_V3 devinfo; 912174604Sscottl int i, result; 913174604Sscottl DEVICEID param[2] = { id, 0 }; 914174604Sscottl 915174604Sscottl if (hpt_get_device_info_v3(id, &devinfo)) 916174604Sscottl return -1; 917174604Sscottl 918174604Sscottl if (devinfo.Type!=LDT_ARRAY) 919174604Sscottl return -1; 920174604Sscottl 921174604Sscottl if (devinfo.u.array.Flags & ARRAY_FLAG_REBUILDING) 922174604Sscottl param[1] = AS_REBUILD_ABORT; 923174604Sscottl else if (devinfo.u.array.Flags & ARRAY_FLAG_VERIFYING) 924174604Sscottl param[1] = AS_VERIFY_ABORT; 925174604Sscottl else if (devinfo.u.array.Flags & ARRAY_FLAG_INITIALIZING) 926174604Sscottl param[1] = AS_INITIALIZE_ABORT; 927174604Sscottl else if (devinfo.u.array.Flags & ARRAY_FLAG_TRANSFORMING) 928174604Sscottl param[1] = AS_TRANSFORM_ABORT; 929174604Sscottl else 930174604Sscottl return -1; 931174604Sscottl 932174604Sscottl KdPrint(("SET_ARRAY_STATE(%x, %d)", param[0], param[1])); 933174604Sscottl result = HPT_DO_IOCTL(HPT_IOCTL_SET_ARRAY_STATE, 934174604Sscottl param, sizeof(param), 0, 0); 935174604Sscottl 936174604Sscottl for (i=0; i<devinfo.u.array.nDisk; i++) 937174604Sscottl if (DEVICEID_VALID(devinfo.u.array.Members[i])) 938174604Sscottl __hpt_stop_tasks(vbus_ext, devinfo.u.array.Members[i]); 939174604Sscottl 940174604Sscottl return result; 941174604Sscottl} 942174604Sscottl 943174604Sscottlstatic void hpt_stop_tasks(PVBUS_EXT vbus_ext) 944174604Sscottl{ 945174604Sscottl DEVICEID ids[32]; 946174604Sscottl int i, count; 947174604Sscottl 948174604Sscottl count = hpt_get_logical_devices((DEVICEID *)&ids, sizeof(ids)/sizeof(ids[0])); 949174604Sscottl 950174604Sscottl for (i=0; i<count; i++) 951174604Sscottl __hpt_stop_tasks(vbus_ext, ids[i]); 952174604Sscottl} 953174604Sscottl 954174604Sscottlstatic d_open_t hpt_open; 955174604Sscottlstatic d_close_t hpt_close; 956174604Sscottlstatic d_ioctl_t hpt_ioctl; 957174604Sscottlstatic int hpt_rescan_bus(void); 958174604Sscottl 959174604Sscottlstatic struct cdevsw hpt_cdevsw = { 960174604Sscottl .d_open = hpt_open, 961174604Sscottl .d_close = hpt_close, 962174604Sscottl .d_ioctl = hpt_ioctl, 963174604Sscottl .d_name = driver_name, 964174604Sscottl#if __FreeBSD_version>=503000 965174604Sscottl .d_version = D_VERSION, 966174604Sscottl#endif 967174604Sscottl#if (__FreeBSD_version>=503000 && __FreeBSD_version<600034) 968174604Sscottl .d_flags = D_NEEDGIANT, 969174604Sscottl#endif 970174604Sscottl#if __FreeBSD_version<600034 971174604Sscottl#if __FreeBSD_version>501000 972174604Sscottl .d_maj = MAJOR_AUTO, 973174604Sscottl#else 974174604Sscottl .d_maj = HPT_DEV_MAJOR, 975174604Sscottl#endif 976174604Sscottl#endif 977174604Sscottl}; 978174604Sscottl 979174604Sscottlstatic struct intr_config_hook hpt_ich; 980174604Sscottl 981174604Sscottl/* 982174604Sscottl * hpt_final_init will be called after all hpt_attach. 983174604Sscottl */ 984174604Sscottlstatic void hpt_final_init(void *dummy) 985174604Sscottl{ 986174604Sscottl int i; 987174604Sscottl PVBUS_EXT vbus_ext; 988174604Sscottl PVBUS vbus; 989174604Sscottl PHBA hba; 990174604Sscottl 991174604Sscottl /* Clear the config hook */ 992174604Sscottl config_intrhook_disestablish(&hpt_ich); 993174604Sscottl 994174604Sscottl /* allocate memory */ 995174604Sscottl i = 0; 996174604Sscottl ldm_for_each_vbus(vbus, vbus_ext) { 997174604Sscottl if (hpt_alloc_mem(vbus_ext)) { 998174604Sscottl os_printk("out of memory"); 999174604Sscottl return; 1000174604Sscottl } 1001174604Sscottl i++; 1002174604Sscottl } 1003174604Sscottl 1004174604Sscottl if (!i) { 1005175363Ssobomax if (bootverbose) 1006175363Ssobomax os_printk("no controller detected."); 1007174604Sscottl return; 1008174604Sscottl } 1009174604Sscottl 1010174604Sscottl /* initializing hardware */ 1011174604Sscottl ldm_for_each_vbus(vbus, vbus_ext) { 1012174604Sscottl /* make timer available here */ 1013174604Sscottl callout_handle_init(&vbus_ext->timer); 1014174604Sscottl if (hpt_init_vbus(vbus_ext)) { 1015174604Sscottl os_printk("fail to initialize hardware"); 1016174604Sscottl break; /* FIXME */ 1017174604Sscottl } 1018174604Sscottl } 1019174604Sscottl 1020174604Sscottl /* register CAM interface */ 1021174604Sscottl ldm_for_each_vbus(vbus, vbus_ext) { 1022174604Sscottl struct cam_devq *devq; 1023174604Sscottl struct ccb_setasync ccb; 1024174604Sscottl 1025174604Sscottl#if (__FreeBSD_version >= 500000) 1026174604Sscottl mtx_init(&vbus_ext->lock, "hptsleeplock", NULL, MTX_DEF); 1027174604Sscottl#endif 1028174604Sscottl if (bus_dma_tag_create(NULL,/* parent */ 1029174604Sscottl 4, /* alignment */ 1030174604Sscottl BUS_SPACE_MAXADDR_32BIT+1, /* boundary */ 1031174604Sscottl BUS_SPACE_MAXADDR, /* lowaddr */ 1032174604Sscottl BUS_SPACE_MAXADDR, /* highaddr */ 1033174604Sscottl NULL, NULL, /* filter, filterarg */ 1034174604Sscottl PAGE_SIZE * (os_max_sg_descriptors-1), /* maxsize */ 1035174604Sscottl os_max_sg_descriptors, /* nsegments */ 1036174604Sscottl 0x10000, /* maxsegsize */ 1037174604Sscottl BUS_DMA_WAITOK, /* flags */ 1038174604Sscottl#if __FreeBSD_version>502000 1039174604Sscottl busdma_lock_mutex, /* lockfunc */ 1040174604Sscottl &vbus_ext->lock, /* lockfuncarg */ 1041174604Sscottl#endif 1042174604Sscottl &vbus_ext->io_dmat /* tag */)) 1043174604Sscottl { 1044174604Sscottl return ; 1045174604Sscottl } 1046174604Sscottl 1047174604Sscottl for (i=0; i<os_max_queue_comm; i++) { 1048174604Sscottl POS_CMDEXT ext = (POS_CMDEXT)malloc(sizeof(OS_CMDEXT), M_DEVBUF, M_WAITOK); 1049174604Sscottl if (!ext) { 1050174604Sscottl os_printk("Can't alloc cmdext(%d)", i); 1051174604Sscottl return ; 1052174604Sscottl } 1053174604Sscottl ext->vbus_ext = vbus_ext; 1054174604Sscottl ext->next = vbus_ext->cmdext_list; 1055174604Sscottl vbus_ext->cmdext_list = ext; 1056174604Sscottl 1057174604Sscottl if (bus_dmamap_create(vbus_ext->io_dmat, 0, &ext->dma_map)) { 1058174604Sscottl os_printk("Can't create dma map(%d)", i); 1059174604Sscottl return ; 1060174604Sscottl } 1061255871Sscottl callout_handle_init(&ext->timeout_ch); 1062174604Sscottl } 1063174604Sscottl 1064174604Sscottl if ((devq = cam_simq_alloc(os_max_queue_comm)) == NULL) { 1065174604Sscottl os_printk("cam_simq_alloc failed"); 1066174604Sscottl return ; 1067174604Sscottl } 1068174604Sscottl 1069174604Sscottl#if __FreeBSD_version > 700025 1070174604Sscottl vbus_ext->sim = cam_sim_alloc(hpt_action, hpt_poll, driver_name, 1071174604Sscottl vbus_ext, 0, &Giant, os_max_queue_comm, /*tagged*/8, devq); 1072174604Sscottl#else 1073174604Sscottl vbus_ext->sim = cam_sim_alloc(hpt_action, hpt_poll, driver_name, 1074174604Sscottl vbus_ext, 0, os_max_queue_comm, /*tagged*/8, devq); 1075174604Sscottl#endif 1076174604Sscottl 1077174604Sscottl if (!vbus_ext->sim) { 1078174604Sscottl os_printk("cam_sim_alloc failed"); 1079174604Sscottl cam_simq_free(devq); 1080174604Sscottl return ; 1081174604Sscottl } 1082174604Sscottl 1083174604Sscottl#if __FreeBSD_version > 700044 1084174604Sscottl if (xpt_bus_register(vbus_ext->sim, NULL, 0) != CAM_SUCCESS) { 1085174604Sscottl#else 1086174604Sscottl if (xpt_bus_register(vbus_ext->sim, 0) != CAM_SUCCESS) { 1087174604Sscottl#endif 1088174604Sscottl os_printk("xpt_bus_register failed"); 1089174604Sscottl cam_sim_free(vbus_ext->sim, /*free devq*/ TRUE); 1090174604Sscottl vbus_ext->sim = NULL; 1091174604Sscottl return ; 1092174604Sscottl } 1093174604Sscottl 1094174604Sscottl if (xpt_create_path(&vbus_ext->path, /*periph */ NULL, 1095174604Sscottl cam_sim_path(vbus_ext->sim), CAM_TARGET_WILDCARD, 1096174604Sscottl CAM_LUN_WILDCARD) != CAM_REQ_CMP) 1097174604Sscottl { 1098174604Sscottl os_printk("xpt_create_path failed"); 1099174604Sscottl xpt_bus_deregister(cam_sim_path(vbus_ext->sim)); 1100174604Sscottl cam_sim_free(vbus_ext->sim, /*free_devq*/TRUE); 1101174604Sscottl vbus_ext->sim = NULL; 1102174604Sscottl return ; 1103174604Sscottl } 1104174604Sscottl 1105174604Sscottl xpt_setup_ccb(&ccb.ccb_h, vbus_ext->path, /*priority*/5); 1106174604Sscottl ccb.ccb_h.func_code = XPT_SASYNC_CB; 1107174604Sscottl ccb.event_enable = AC_LOST_DEVICE; 1108174604Sscottl ccb.callback = hpt_async; 1109174604Sscottl ccb.callback_arg = vbus_ext; 1110174604Sscottl xpt_action((union ccb *)&ccb); 1111174604Sscottl 1112174604Sscottl for (hba = vbus_ext->hba_list; hba; hba = hba->next) { 1113174604Sscottl int rid = 0; 1114174604Sscottl if ((hba->irq_res = bus_alloc_resource(hba->pcidev, 1115174604Sscottl SYS_RES_IRQ, &rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) 1116174604Sscottl { 1117174604Sscottl os_printk("can't allocate interrupt"); 1118174604Sscottl return ; 1119174604Sscottl } 1120174604Sscottl 1121174604Sscottl if (bus_setup_intr(hba->pcidev, hba->irq_res, INTR_TYPE_CAM, 1122174604Sscottl#if __FreeBSD_version > 700025 1123174604Sscottl NULL, hpt_pci_intr, vbus_ext, &hba->irq_handle)) 1124174604Sscottl#else 1125174604Sscottl hpt_pci_intr, vbus_ext, &hba->irq_handle)) 1126174604Sscottl#endif 1127174604Sscottl { 1128174604Sscottl os_printk("can't set up interrupt"); 1129174604Sscottl return ; 1130174604Sscottl } 1131174604Sscottl hba->ldm_adapter.him->intr_control(hba->ldm_adapter.him_handle, HPT_TRUE); 1132174604Sscottl } 1133174604Sscottl 1134174604Sscottl vbus_ext->shutdown_eh = EVENTHANDLER_REGISTER(shutdown_final, 1135174604Sscottl hpt_shutdown_vbus, vbus_ext, SHUTDOWN_PRI_DEFAULT); 1136174604Sscottl if (!vbus_ext->shutdown_eh) 1137174604Sscottl os_printk("Shutdown event registration failed"); 1138174604Sscottl } 1139174604Sscottl 1140174604Sscottl ldm_for_each_vbus(vbus, vbus_ext) { 1141174604Sscottl TASK_INIT(&vbus_ext->worker, 0, (task_fn_t *)hpt_do_tasks, vbus_ext); 1142174604Sscottl if (vbus_ext->tasks) 1143174604Sscottl TASK_ENQUEUE(&vbus_ext->worker); 1144174604Sscottl } 1145174604Sscottl 1146174604Sscottl make_dev(&hpt_cdevsw, DRIVER_MINOR, UID_ROOT, GID_OPERATOR, 1147213780Srpaulo S_IRUSR | S_IWUSR, "%s", driver_name); 1148174604Sscottl} 1149174604Sscottl 1150174604Sscottl#if defined(KLD_MODULE) && (__FreeBSD_version >= 503000) 1151174604Sscottl 1152174604Sscottltypedef struct driverlink *driverlink_t; 1153174604Sscottlstruct driverlink { 1154174604Sscottl kobj_class_t driver; 1155174604Sscottl TAILQ_ENTRY(driverlink) link; /* list of drivers in devclass */ 1156174604Sscottl}; 1157174604Sscottl 1158174604Sscottltypedef TAILQ_HEAD(driver_list, driverlink) driver_list_t; 1159174604Sscottl 1160174604Sscottlstruct devclass { 1161174604Sscottl TAILQ_ENTRY(devclass) link; 1162174604Sscottl devclass_t parent; /* parent in devclass hierarchy */ 1163174604Sscottl driver_list_t drivers; /* bus devclasses store drivers for bus */ 1164174604Sscottl char *name; 1165174604Sscottl device_t *devices; /* array of devices indexed by unit */ 1166174604Sscottl int maxunit; /* size of devices array */ 1167174604Sscottl}; 1168174604Sscottl 1169174604Sscottlstatic void override_kernel_driver(void) 1170174604Sscottl{ 1171174604Sscottl driverlink_t dl, dlfirst; 1172174604Sscottl driver_t *tmpdriver; 1173174604Sscottl devclass_t dc = devclass_find("pci"); 1174174604Sscottl 1175174604Sscottl if (dc){ 1176174604Sscottl dlfirst = TAILQ_FIRST(&dc->drivers); 1177174604Sscottl for (dl = dlfirst; dl; dl = TAILQ_NEXT(dl, link)) { 1178174604Sscottl if(strcmp(dl->driver->name, driver_name) == 0) { 1179174604Sscottl tmpdriver=dl->driver; 1180174604Sscottl dl->driver=dlfirst->driver; 1181174604Sscottl dlfirst->driver=tmpdriver; 1182174604Sscottl break; 1183174604Sscottl } 1184174604Sscottl } 1185174604Sscottl } 1186174604Sscottl} 1187174604Sscottl 1188174604Sscottl#else 1189174604Sscottl#define override_kernel_driver() 1190174604Sscottl#endif 1191174604Sscottl 1192174604Sscottlstatic void hpt_init(void *dummy) 1193174604Sscottl{ 1194175363Ssobomax if (bootverbose) 1195175363Ssobomax os_printk("%s %s", driver_name_long, driver_ver); 1196174604Sscottl 1197174604Sscottl override_kernel_driver(); 1198174604Sscottl init_config(); 1199174604Sscottl 1200174604Sscottl hpt_ich.ich_func = hpt_final_init; 1201174604Sscottl hpt_ich.ich_arg = NULL; 1202174604Sscottl if (config_intrhook_establish(&hpt_ich) != 0) { 1203174604Sscottl printf("%s: cannot establish configuration hook\n", 1204174604Sscottl driver_name_long); 1205174604Sscottl } 1206174604Sscottl 1207174604Sscottl} 1208174604SscottlSYSINIT(hptinit, SI_SUB_CONFIGURE, SI_ORDER_FIRST, hpt_init, NULL); 1209174604Sscottl 1210174604Sscottl/* 1211174604Sscottl * CAM driver interface 1212174604Sscottl */ 1213174604Sscottlstatic device_method_t driver_methods[] = { 1214174604Sscottl /* Device interface */ 1215174604Sscottl DEVMETHOD(device_probe, hpt_probe), 1216174604Sscottl DEVMETHOD(device_attach, hpt_attach), 1217174604Sscottl DEVMETHOD(device_detach, hpt_detach), 1218174604Sscottl DEVMETHOD(device_shutdown, hpt_shutdown), 1219227912Smarius DEVMETHOD_END 1220174604Sscottl}; 1221174604Sscottl 1222174604Sscottlstatic driver_t hpt_pci_driver = { 1223174604Sscottl driver_name, 1224174604Sscottl driver_methods, 1225174604Sscottl sizeof(HBA) 1226174604Sscottl}; 1227174604Sscottl 1228174604Sscottlstatic devclass_t hpt_devclass; 1229174604Sscottl 1230174604Sscottl#ifndef TARGETNAME 1231174604Sscottl#error "no TARGETNAME found" 1232174604Sscottl#endif 1233174604Sscottl 1234174604Sscottl/* use this to make TARGETNAME be expanded */ 1235174604Sscottl#define __DRIVER_MODULE(p1, p2, p3, p4, p5, p6) DRIVER_MODULE(p1, p2, p3, p4, p5, p6) 1236174604Sscottl#define __MODULE_VERSION(p1, p2) MODULE_VERSION(p1, p2) 1237174604Sscottl#define __MODULE_DEPEND(p1, p2, p3, p4, p5) MODULE_DEPEND(p1, p2, p3, p4, p5) 1238174604Sscottl__DRIVER_MODULE(TARGETNAME, pci, hpt_pci_driver, hpt_devclass, 0, 0); 1239174604Sscottl__MODULE_VERSION(TARGETNAME, 1); 1240174604Sscottl__MODULE_DEPEND(TARGETNAME, cam, 1, 1, 1); 1241174604Sscottl 1242174604Sscottl#if __FreeBSD_version>503000 1243174604Sscottltypedef struct cdev * ioctl_dev_t; 1244174604Sscottl#else 1245174604Sscottltypedef dev_t ioctl_dev_t; 1246174604Sscottl#endif 1247174604Sscottl 1248174604Sscottl#if __FreeBSD_version >= 500000 1249174604Sscottltypedef struct thread * ioctl_thread_t; 1250174604Sscottl#else 1251174604Sscottltypedef struct proc * ioctl_thread_t; 1252174604Sscottl#endif 1253174604Sscottl 1254174604Sscottlstatic int hpt_open(ioctl_dev_t dev, int flags, int devtype, ioctl_thread_t td) 1255174604Sscottl{ 1256174604Sscottl return 0; 1257174604Sscottl} 1258174604Sscottl 1259174604Sscottlstatic int hpt_close(ioctl_dev_t dev, int flags, int devtype, ioctl_thread_t td) 1260174604Sscottl{ 1261174604Sscottl return 0; 1262174604Sscottl} 1263174604Sscottl 1264174604Sscottlstatic int hpt_ioctl(ioctl_dev_t dev, u_long cmd, caddr_t data, int fflag, ioctl_thread_t td) 1265174604Sscottl{ 1266174604Sscottl PHPT_IOCTL_PARAM piop=(PHPT_IOCTL_PARAM)data; 1267174604Sscottl IOCTL_ARG ioctl_args; 1268174604Sscottl HPT_U32 bytesReturned; 1269174604Sscottl 1270174604Sscottl switch (cmd){ 1271174604Sscottl case HPT_DO_IOCONTROL: 1272174604Sscottl { 1273174604Sscottl if (piop->Magic == HPT_IOCTL_MAGIC || piop->Magic == HPT_IOCTL_MAGIC32) { 1274174604Sscottl KdPrint(("ioctl=%x in=%p len=%d out=%p len=%d\n", 1275174604Sscottl piop->dwIoControlCode, 1276174604Sscottl piop->lpInBuffer, 1277174604Sscottl piop->nInBufferSize, 1278174604Sscottl piop->lpOutBuffer, 1279174604Sscottl piop->nOutBufferSize)); 1280174604Sscottl 1281174604Sscottl memset(&ioctl_args, 0, sizeof(ioctl_args)); 1282174604Sscottl 1283174604Sscottl ioctl_args.dwIoControlCode = piop->dwIoControlCode; 1284174604Sscottl ioctl_args.nInBufferSize = piop->nInBufferSize; 1285174604Sscottl ioctl_args.nOutBufferSize = piop->nOutBufferSize; 1286174604Sscottl ioctl_args.lpBytesReturned = &bytesReturned; 1287174604Sscottl 1288174604Sscottl if (ioctl_args.nInBufferSize) { 1289174604Sscottl ioctl_args.lpInBuffer = malloc(ioctl_args.nInBufferSize, M_DEVBUF, M_WAITOK); 1290174604Sscottl if (!ioctl_args.lpInBuffer) 1291174604Sscottl goto invalid; 1292174604Sscottl if (copyin((void*)piop->lpInBuffer, 1293174604Sscottl ioctl_args.lpInBuffer, piop->nInBufferSize)) 1294174604Sscottl goto invalid; 1295174604Sscottl } 1296174604Sscottl 1297174604Sscottl if (ioctl_args.nOutBufferSize) { 1298174604Sscottl ioctl_args.lpOutBuffer = malloc(ioctl_args.nOutBufferSize, M_DEVBUF, M_WAITOK); 1299174604Sscottl if (!ioctl_args.lpOutBuffer) 1300174604Sscottl goto invalid; 1301174604Sscottl } 1302174604Sscottl 1303174604Sscottl#if (__FreeBSD_version >= 500000) 1304174604Sscottl mtx_lock(&Giant); 1305174604Sscottl#endif 1306174604Sscottl 1307174604Sscottl hpt_do_ioctl(&ioctl_args); 1308174604Sscottl 1309174604Sscottl#if (__FreeBSD_version >= 500000) 1310174604Sscottl mtx_unlock(&Giant); 1311174604Sscottl#endif 1312174604Sscottl 1313174604Sscottl if (ioctl_args.result==HPT_IOCTL_RESULT_OK) { 1314174604Sscottl if (piop->nOutBufferSize) { 1315174604Sscottl if (copyout(ioctl_args.lpOutBuffer, 1316174604Sscottl (void*)piop->lpOutBuffer, piop->nOutBufferSize)) 1317174604Sscottl goto invalid; 1318174604Sscottl } 1319174604Sscottl if (piop->lpBytesReturned) { 1320174604Sscottl if (copyout(&bytesReturned, 1321174604Sscottl (void*)piop->lpBytesReturned, sizeof(HPT_U32))) 1322174604Sscottl goto invalid; 1323174604Sscottl } 1324174604Sscottl if (ioctl_args.lpInBuffer) free(ioctl_args.lpInBuffer, M_DEVBUF); 1325174604Sscottl if (ioctl_args.lpOutBuffer) free(ioctl_args.lpOutBuffer, M_DEVBUF); 1326174604Sscottl return 0; 1327174604Sscottl } 1328174604Sscottlinvalid: 1329174604Sscottl if (ioctl_args.lpInBuffer) free(ioctl_args.lpInBuffer, M_DEVBUF); 1330174604Sscottl if (ioctl_args.lpOutBuffer) free(ioctl_args.lpOutBuffer, M_DEVBUF); 1331174604Sscottl return EFAULT; 1332174604Sscottl } 1333174604Sscottl return EFAULT; 1334174604Sscottl } 1335174604Sscottl 1336174604Sscottl case HPT_SCAN_BUS: 1337174604Sscottl { 1338174604Sscottl return hpt_rescan_bus(); 1339174604Sscottl } 1340174604Sscottl default: 1341174604Sscottl KdPrint(("invalid command!")); 1342174604Sscottl return EFAULT; 1343174604Sscottl } 1344174604Sscottl 1345174604Sscottl} 1346174604Sscottl 1347174604Sscottlstatic int hpt_rescan_bus(void) 1348174604Sscottl{ 1349174604Sscottl union ccb *ccb; 1350174604Sscottl PVBUS vbus; 1351174604Sscottl PVBUS_EXT vbus_ext; 1352174604Sscottl 1353174604Sscottl#if (__FreeBSD_version >= 500000) 1354174604Sscottl mtx_lock(&Giant); 1355174604Sscottl#endif 1356174604Sscottl 1357174604Sscottl ldm_for_each_vbus(vbus, vbus_ext) { 1358203108Smav if ((ccb = xpt_alloc_ccb()) == NULL) 1359203108Smav return(ENOMEM); 1360249468Smav if (xpt_create_path(&ccb->ccb_h.path, NULL, 1361203108Smav cam_sim_path(vbus_ext->sim), 1362203108Smav CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 1363203108Smav xpt_free_ccb(ccb); 1364174604Sscottl return(EIO); 1365203108Smav } 1366203108Smav xpt_rescan(ccb); 1367174604Sscottl } 1368174604Sscottl 1369174604Sscottl#if (__FreeBSD_version >= 500000) 1370174604Sscottl mtx_unlock(&Giant); 1371174604Sscottl#endif 1372174604Sscottl 1373174604Sscottl return(0); 1374174604Sscottl} 1375