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; 64267457Sdelphij return (BUS_PROBE_DEFAULT); 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{ 485267457Sdelphij POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv; 486267457Sdelphij union ccb *ccb = ext->ccb; 487174604Sscottl 488267457Sdelphij if (logical) { 489267457Sdelphij os_set_sgptr(pSg, (HPT_U8 *)ccb->csio.data_ptr); 490267457Sdelphij pSg->size = ccb->csio.dxfer_len; 491267457Sdelphij pSg->eot = 1; 492267457Sdelphij return TRUE; 493267457Sdelphij } 494267457Sdelphij 495174604Sscottl /* since we have provided physical sg, nobody will ask us to build physical sg */ 496174604Sscottl HPT_ASSERT(0); 497174604Sscottl return FALSE; 498174604Sscottl} 499174604Sscottl 500174604Sscottlstatic void hpt_io_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 501174604Sscottl{ 502174604Sscottl PCOMMAND pCmd = (PCOMMAND)arg; 503174604Sscottl POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv; 504174604Sscottl PSG psg = pCmd->psg; 505174604Sscottl int idx; 506174604Sscottl 507174604Sscottl HPT_ASSERT(pCmd->flags.physical_sg); 508174604Sscottl 509246713Skib if (error) 510174604Sscottl panic("busdma error"); 511174604Sscottl 512174604Sscottl HPT_ASSERT(nsegs<=os_max_sg_descriptors); 513174604Sscottl 514246713Skib if (nsegs != 0) { 515246713Skib for (idx = 0; idx < nsegs; idx++, psg++) { 516246713Skib psg->addr.bus = segs[idx].ds_addr; 517246713Skib psg->size = segs[idx].ds_len; 518246713Skib psg->eot = 0; 519246713Skib } 520246713Skib psg[-1].eot = 1; 521246713Skib 522246713Skib if (pCmd->flags.data_in) { 523246713Skib bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, 524246713Skib BUS_DMASYNC_PREREAD); 525246713Skib } 526246713Skib else if (pCmd->flags.data_out) { 527246713Skib bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, 528246713Skib BUS_DMASYNC_PREWRITE); 529246713Skib } 530174604Sscottl } 531255871Sscottl ext->timeout_ch = timeout(hpt_timeout, pCmd, HPT_OSM_TIMEOUT); 532174604Sscottl ldm_queue_cmd(pCmd); 533174604Sscottl} 534174604Sscottl 535174604Sscottlstatic void hpt_scsi_io(PVBUS_EXT vbus_ext, union ccb *ccb) 536174604Sscottl{ 537174604Sscottl PVBUS vbus = (PVBUS)vbus_ext->vbus; 538174604Sscottl PVDEV vd; 539174604Sscottl PCOMMAND pCmd; 540174604Sscottl POS_CMDEXT ext; 541174604Sscottl HPT_U8 *cdb; 542174604Sscottl 543174604Sscottl if (ccb->ccb_h.flags & CAM_CDB_POINTER) 544174604Sscottl cdb = ccb->csio.cdb_io.cdb_ptr; 545174604Sscottl else 546174604Sscottl cdb = ccb->csio.cdb_io.cdb_bytes; 547174604Sscottl 548174604Sscottl KdPrint(("hpt_scsi_io: ccb %x id %d lun %d cdb %x-%x-%x", 549174604Sscottl ccb, 550174604Sscottl ccb->ccb_h.target_id, ccb->ccb_h.target_lun, 551174604Sscottl *(HPT_U32 *)&cdb[0], *(HPT_U32 *)&cdb[4], *(HPT_U32 *)&cdb[8] 552174604Sscottl )); 553174604Sscottl 554174604Sscottl /* ccb->ccb_h.path_id is not our bus id - don't check it */ 555174604Sscottl if (ccb->ccb_h.target_lun != 0 || 556174604Sscottl ccb->ccb_h.target_id >= osm_max_targets || 557174604Sscottl (ccb->ccb_h.flags & CAM_CDB_PHYS)) 558174604Sscottl { 559174604Sscottl ccb->ccb_h.status = CAM_TID_INVALID; 560174604Sscottl xpt_done(ccb); 561174604Sscottl return; 562174604Sscottl } 563174604Sscottl 564174604Sscottl vd = ldm_find_target(vbus, ccb->ccb_h.target_id); 565174604Sscottl 566174604Sscottl if (!vd) { 567267457Sdelphij ccb->ccb_h.status = CAM_SEL_TIMEOUT; 568174604Sscottl xpt_done(ccb); 569174604Sscottl return; 570174604Sscottl } 571174604Sscottl 572174604Sscottl switch (cdb[0]) { 573174604Sscottl case TEST_UNIT_READY: 574174604Sscottl case START_STOP_UNIT: 575174604Sscottl case SYNCHRONIZE_CACHE: 576174604Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 577174604Sscottl break; 578174604Sscottl 579174604Sscottl case INQUIRY: 580174604Sscottl { 581174604Sscottl PINQUIRYDATA inquiryData; 582174604Sscottl memset(ccb->csio.data_ptr, 0, ccb->csio.dxfer_len); 583174604Sscottl inquiryData = (PINQUIRYDATA)ccb->csio.data_ptr; 584174604Sscottl 585174604Sscottl inquiryData->AdditionalLength = 31; 586174604Sscottl inquiryData->CommandQueue = 1; 587174604Sscottl memcpy(&inquiryData->VendorId, "HPT ", 8); 588174604Sscottl memcpy(&inquiryData->ProductId, "DISK 0_0 ", 16); 589174604Sscottl 590174604Sscottl if (vd->target_id / 10) { 591174604Sscottl inquiryData->ProductId[7] = (vd->target_id % 100) / 10 + '0'; 592174604Sscottl inquiryData->ProductId[8] = (vd->target_id % 100) % 10 + '0'; 593174604Sscottl } 594174604Sscottl else 595174604Sscottl inquiryData->ProductId[7] = (vd->target_id % 100) % 10 + '0'; 596174604Sscottl 597174604Sscottl memcpy(&inquiryData->ProductRevisionLevel, "4.00", 4); 598174604Sscottl 599174604Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 600174604Sscottl } 601174604Sscottl break; 602174604Sscottl 603174604Sscottl case READ_CAPACITY: 604174604Sscottl { 605174604Sscottl HPT_U8 *rbuf = ccb->csio.data_ptr; 606174604Sscottl HPT_U32 cap; 607174604Sscottl 608174604Sscottl if (vd->capacity>0xfffffffful) 609174604Sscottl cap = 0xfffffffful; 610174604Sscottl else 611174604Sscottl cap = vd->capacity - 1; 612174604Sscottl 613174604Sscottl rbuf[0] = (HPT_U8)(cap>>24); 614174604Sscottl rbuf[1] = (HPT_U8)(cap>>16); 615174604Sscottl rbuf[2] = (HPT_U8)(cap>>8); 616174604Sscottl rbuf[3] = (HPT_U8)cap; 617174604Sscottl rbuf[4] = 0; 618174604Sscottl rbuf[5] = 0; 619174604Sscottl rbuf[6] = 2; 620174604Sscottl rbuf[7] = 0; 621174604Sscottl 622174604Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 623174604Sscottl break; 624174604Sscottl } 625174604Sscottl 626174604Sscottl case SERVICE_ACTION_IN: 627174604Sscottl { 628174604Sscottl HPT_U8 *rbuf = ccb->csio.data_ptr; 629174604Sscottl HPT_U64 cap = vd->capacity - 1; 630174604Sscottl 631174604Sscottl rbuf[0] = (HPT_U8)(cap>>56); 632174604Sscottl rbuf[1] = (HPT_U8)(cap>>48); 633174604Sscottl rbuf[2] = (HPT_U8)(cap>>40); 634174604Sscottl rbuf[3] = (HPT_U8)(cap>>32); 635174604Sscottl rbuf[4] = (HPT_U8)(cap>>24); 636174604Sscottl rbuf[5] = (HPT_U8)(cap>>16); 637174604Sscottl rbuf[6] = (HPT_U8)(cap>>8); 638174604Sscottl rbuf[7] = (HPT_U8)cap; 639174604Sscottl rbuf[8] = 0; 640174604Sscottl rbuf[9] = 0; 641174604Sscottl rbuf[10] = 2; 642174604Sscottl rbuf[11] = 0; 643174604Sscottl 644174604Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 645174604Sscottl break; 646174604Sscottl } 647174604Sscottl 648174604Sscottl case READ_6: 649174604Sscottl case READ_10: 650174604Sscottl case READ_16: 651174604Sscottl case WRITE_6: 652174604Sscottl case WRITE_10: 653174604Sscottl case WRITE_16: 654174604Sscottl case 0x13: 655174604Sscottl case 0x2f: 656174604Sscottl { 657246713Skib int error; 658246713Skib 659174604Sscottl pCmd = ldm_alloc_cmds(vbus, vd->cmds_per_request); 660174604Sscottl if(!pCmd){ 661174604Sscottl KdPrint(("Failed to allocate command!")); 662174604Sscottl ccb->ccb_h.status = CAM_BUSY; 663174604Sscottl break; 664174604Sscottl } 665174604Sscottl 666174604Sscottl switch (cdb[0]) { 667174604Sscottl case READ_6: 668174604Sscottl case WRITE_6: 669174604Sscottl case 0x13: 670174604Sscottl pCmd->uCmd.Ide.Lba = ((HPT_U32)cdb[1] << 16) | ((HPT_U32)cdb[2] << 8) | (HPT_U32)cdb[3]; 671174604Sscottl pCmd->uCmd.Ide.nSectors = (HPT_U16) cdb[4]; 672174604Sscottl break; 673174604Sscottl case READ_16: 674174604Sscottl case WRITE_16: 675174604Sscottl { 676174604Sscottl HPT_U64 block = 677174604Sscottl ((HPT_U64)cdb[2]<<56) | 678174604Sscottl ((HPT_U64)cdb[3]<<48) | 679174604Sscottl ((HPT_U64)cdb[4]<<40) | 680174604Sscottl ((HPT_U64)cdb[5]<<32) | 681174604Sscottl ((HPT_U64)cdb[6]<<24) | 682174604Sscottl ((HPT_U64)cdb[7]<<16) | 683174604Sscottl ((HPT_U64)cdb[8]<<8) | 684174604Sscottl ((HPT_U64)cdb[9]); 685174604Sscottl pCmd->uCmd.Ide.Lba = block; 686174604Sscottl pCmd->uCmd.Ide.nSectors = (HPT_U16)cdb[13] | ((HPT_U16)cdb[12]<<8); 687174604Sscottl break; 688174604Sscottl } 689174604Sscottl 690174604Sscottl default: 691174604Sscottl pCmd->uCmd.Ide.Lba = (HPT_U32)cdb[5] | ((HPT_U32)cdb[4] << 8) | ((HPT_U32)cdb[3] << 16) | ((HPT_U32)cdb[2] << 24); 692174604Sscottl pCmd->uCmd.Ide.nSectors = (HPT_U16) cdb[8] | ((HPT_U16)cdb[7]<<8); 693174604Sscottl break; 694174604Sscottl } 695174604Sscottl 696174604Sscottl switch (cdb[0]) { 697174604Sscottl case READ_6: 698174604Sscottl case READ_10: 699174604Sscottl case READ_16: 700174604Sscottl pCmd->flags.data_in = 1; 701174604Sscottl break; 702174604Sscottl case WRITE_6: 703174604Sscottl case WRITE_10: 704174604Sscottl case WRITE_16: 705174604Sscottl pCmd->flags.data_out = 1; 706174604Sscottl break; 707174604Sscottl } 708174604Sscottl pCmd->priv = ext = cmdext_get(vbus_ext); 709174604Sscottl HPT_ASSERT(ext); 710174604Sscottl ext->ccb = ccb; 711174604Sscottl pCmd->target = vd; 712174604Sscottl pCmd->done = os_cmddone; 713174604Sscottl pCmd->buildsgl = os_buildsgl; 714174604Sscottl pCmd->psg = ext->psg; 715246713Skib pCmd->flags.physical_sg = 1; 716246713Skib error = bus_dmamap_load_ccb(vbus_ext->io_dmat, 717246713Skib ext->dma_map, 718246713Skib ccb, 719246713Skib hpt_io_dmamap_callback, pCmd, 720246713Skib BUS_DMA_WAITOK 721174604Sscottl ); 722246713Skib KdPrint(("bus_dmamap_load return %d", error)); 723246713Skib if (error && error!=EINPROGRESS) { 724246713Skib os_printk("bus_dmamap_load error %d", error); 725246713Skib cmdext_put(ext); 726246713Skib ldm_free_cmds(pCmd); 727246713Skib ccb->ccb_h.status = CAM_REQ_CMP_ERR; 728246713Skib xpt_done(ccb); 729174604Sscottl } 730174604Sscottl return; 731174604Sscottl } 732174604Sscottl 733174604Sscottl default: 734174604Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 735174604Sscottl break; 736174604Sscottl } 737174604Sscottl 738174604Sscottl xpt_done(ccb); 739174604Sscottl return; 740174604Sscottl} 741174604Sscottl 742174604Sscottlstatic void hpt_action(struct cam_sim *sim, union ccb *ccb) 743174604Sscottl{ 744174604Sscottl PVBUS_EXT vbus_ext = (PVBUS_EXT)cam_sim_softc(sim); 745174604Sscottl 746174604Sscottl KdPrint(("hpt_action(fn=%d, id=%d)", ccb->ccb_h.func_code, ccb->ccb_h.target_id)); 747174604Sscottl 748174604Sscottl switch (ccb->ccb_h.func_code) { 749174604Sscottl 750174604Sscottl case XPT_SCSI_IO: 751174604Sscottl hpt_lock_vbus(vbus_ext); 752174604Sscottl hpt_scsi_io(vbus_ext, ccb); 753174604Sscottl hpt_unlock_vbus(vbus_ext); 754174604Sscottl return; 755174604Sscottl 756174604Sscottl case XPT_RESET_BUS: 757174604Sscottl hpt_lock_vbus(vbus_ext); 758174604Sscottl ldm_reset_vbus((PVBUS)vbus_ext->vbus); 759174604Sscottl hpt_unlock_vbus(vbus_ext); 760174604Sscottl break; 761174604Sscottl 762174604Sscottl case XPT_GET_TRAN_SETTINGS: 763174604Sscottl case XPT_SET_TRAN_SETTINGS: 764174604Sscottl ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 765174604Sscottl break; 766174604Sscottl 767174604Sscottl case XPT_CALC_GEOMETRY: 768227912Smarius#if __FreeBSD_version >= 500000 769227912Smarius cam_calc_geometry(&ccb->ccg, 1); 770227912Smarius#else 771174604Sscottl ccb->ccg.heads = 255; 772174604Sscottl ccb->ccg.secs_per_track = 63; 773174604Sscottl ccb->ccg.cylinders = ccb->ccg.volume_size / (ccb->ccg.heads * ccb->ccg.secs_per_track); 774174604Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 775227912Smarius#endif 776174604Sscottl break; 777174604Sscottl 778174604Sscottl case XPT_PATH_INQ: 779174604Sscottl { 780174604Sscottl struct ccb_pathinq *cpi = &ccb->cpi; 781174604Sscottl 782174604Sscottl cpi->version_num = 1; 783174604Sscottl cpi->hba_inquiry = PI_SDTR_ABLE; 784174604Sscottl cpi->target_sprt = 0; 785174604Sscottl cpi->hba_misc = PIM_NOBUSRESET; 786174604Sscottl cpi->hba_eng_cnt = 0; 787174604Sscottl cpi->max_target = osm_max_targets; 788174604Sscottl cpi->max_lun = 0; 789174604Sscottl cpi->unit_number = cam_sim_unit(sim); 790174604Sscottl cpi->bus_id = cam_sim_bus(sim); 791174604Sscottl cpi->initiator_id = osm_max_targets; 792174604Sscottl cpi->base_transfer_speed = 3300; 793174604Sscottl 794174604Sscottl strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 795174604Sscottl strncpy(cpi->hba_vid, "HPT ", HBA_IDLEN); 796174604Sscottl strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 797196415Skensmith cpi->transport = XPORT_SPI; 798196415Skensmith cpi->transport_version = 2; 799196415Skensmith cpi->protocol = PROTO_SCSI; 800196415Skensmith cpi->protocol_version = SCSI_REV_2; 801174604Sscottl cpi->ccb_h.status = CAM_REQ_CMP; 802174604Sscottl break; 803174604Sscottl } 804174604Sscottl 805174604Sscottl default: 806174604Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 807174604Sscottl break; 808174604Sscottl } 809174604Sscottl 810174604Sscottl xpt_done(ccb); 811174604Sscottl return; 812174604Sscottl} 813174604Sscottl 814174604Sscottlstatic void hpt_pci_intr(void *arg) 815174604Sscottl{ 816174604Sscottl PVBUS_EXT vbus_ext = (PVBUS_EXT)arg; 817174604Sscottl hpt_lock_vbus(vbus_ext); 818174604Sscottl ldm_intr((PVBUS)vbus_ext->vbus); 819174604Sscottl hpt_unlock_vbus(vbus_ext); 820174604Sscottl} 821174604Sscottl 822174604Sscottlstatic void hpt_poll(struct cam_sim *sim) 823174604Sscottl{ 824174604Sscottl hpt_pci_intr(cam_sim_softc(sim)); 825174604Sscottl} 826174604Sscottl 827174604Sscottlstatic void hpt_async(void * callback_arg, u_int32_t code, struct cam_path * path, void * arg) 828174604Sscottl{ 829174604Sscottl KdPrint(("hpt_async")); 830174604Sscottl} 831174604Sscottl 832174604Sscottlstatic int hpt_shutdown(device_t dev) 833174604Sscottl{ 834174604Sscottl KdPrint(("hpt_shutdown(dev=%p)", dev)); 835174604Sscottl return 0; 836174604Sscottl} 837174604Sscottl 838174604Sscottlstatic int hpt_detach(device_t dev) 839174604Sscottl{ 840174604Sscottl /* we don't allow the driver to be unloaded. */ 841174604Sscottl return EBUSY; 842174604Sscottl} 843174604Sscottl 844174604Sscottlstatic void hpt_ioctl_done(struct _IOCTL_ARG *arg) 845174604Sscottl{ 846174604Sscottl arg->ioctl_cmnd = 0; 847174604Sscottl wakeup(arg); 848174604Sscottl} 849174604Sscottl 850174604Sscottlstatic void __hpt_do_ioctl(PVBUS_EXT vbus_ext, IOCTL_ARG *ioctl_args) 851174604Sscottl{ 852174604Sscottl ioctl_args->result = -1; 853174604Sscottl ioctl_args->done = hpt_ioctl_done; 854174604Sscottl ioctl_args->ioctl_cmnd = (void *)1; 855174604Sscottl 856174604Sscottl hpt_lock_vbus(vbus_ext); 857174604Sscottl ldm_ioctl((PVBUS)vbus_ext->vbus, ioctl_args); 858174604Sscottl 859174604Sscottl while (ioctl_args->ioctl_cmnd) { 860174604Sscottl if (hpt_sleep(vbus_ext, ioctl_args, PPAUSE, "hptctl", HPT_OSM_TIMEOUT)==0) 861174604Sscottl break; 862174604Sscottl ldm_reset_vbus((PVBUS)vbus_ext->vbus); 863174604Sscottl __hpt_do_tasks(vbus_ext); 864174604Sscottl } 865174604Sscottl 866174604Sscottl /* KdPrint(("ioctl %x result %d", ioctl_args->dwIoControlCode, ioctl_args->result)); */ 867174604Sscottl 868174604Sscottl hpt_unlock_vbus(vbus_ext); 869174604Sscottl} 870174604Sscottl 871174604Sscottlstatic void hpt_do_ioctl(IOCTL_ARG *ioctl_args) 872174604Sscottl{ 873174604Sscottl PVBUS vbus; 874174604Sscottl PVBUS_EXT vbus_ext; 875174604Sscottl 876174604Sscottl ldm_for_each_vbus(vbus, vbus_ext) { 877174604Sscottl __hpt_do_ioctl(vbus_ext, ioctl_args); 878174604Sscottl if (ioctl_args->result!=HPT_IOCTL_RESULT_WRONG_VBUS) 879174604Sscottl return; 880174604Sscottl } 881174604Sscottl} 882174604Sscottl 883174604Sscottl#define HPT_DO_IOCTL(code, inbuf, insize, outbuf, outsize) ({\ 884174604Sscottl IOCTL_ARG arg;\ 885174604Sscottl arg.dwIoControlCode = code;\ 886174604Sscottl arg.lpInBuffer = inbuf;\ 887174604Sscottl arg.lpOutBuffer = outbuf;\ 888174604Sscottl arg.nInBufferSize = insize;\ 889174604Sscottl arg.nOutBufferSize = outsize;\ 890174604Sscottl arg.lpBytesReturned = 0;\ 891174604Sscottl hpt_do_ioctl(&arg);\ 892174604Sscottl arg.result;\ 893174604Sscottl}) 894174604Sscottl 895174604Sscottl#define DEVICEID_VALID(id) ((id) && ((HPT_U32)(id)!=0xffffffff)) 896174604Sscottl 897174604Sscottlstatic int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount) 898174604Sscottl{ 899174604Sscottl int i; 900174604Sscottl HPT_U32 count = nMaxCount-1; 901174604Sscottl 902174604Sscottl if (HPT_DO_IOCTL(HPT_IOCTL_GET_LOGICAL_DEVICES, 903174604Sscottl &count, sizeof(HPT_U32), pIds, sizeof(DEVICEID)*nMaxCount)) 904174604Sscottl return -1; 905174604Sscottl 906174604Sscottl nMaxCount = (int)pIds[0]; 907174604Sscottl for (i=0; i<nMaxCount; i++) pIds[i] = pIds[i+1]; 908174604Sscottl return nMaxCount; 909174604Sscottl} 910174604Sscottl 911174604Sscottlstatic int hpt_get_device_info_v3(DEVICEID id, PLOGICAL_DEVICE_INFO_V3 pInfo) 912174604Sscottl{ 913174604Sscottl return HPT_DO_IOCTL(HPT_IOCTL_GET_DEVICE_INFO_V3, 914174604Sscottl &id, sizeof(DEVICEID), pInfo, sizeof(LOGICAL_DEVICE_INFO_V3)); 915174604Sscottl} 916174604Sscottl 917174604Sscottl/* not belong to this file logically, but we want to use ioctl interface */ 918174604Sscottlstatic int __hpt_stop_tasks(PVBUS_EXT vbus_ext, DEVICEID id) 919174604Sscottl{ 920174604Sscottl LOGICAL_DEVICE_INFO_V3 devinfo; 921174604Sscottl int i, result; 922174604Sscottl DEVICEID param[2] = { id, 0 }; 923174604Sscottl 924174604Sscottl if (hpt_get_device_info_v3(id, &devinfo)) 925174604Sscottl return -1; 926174604Sscottl 927174604Sscottl if (devinfo.Type!=LDT_ARRAY) 928174604Sscottl return -1; 929174604Sscottl 930174604Sscottl if (devinfo.u.array.Flags & ARRAY_FLAG_REBUILDING) 931174604Sscottl param[1] = AS_REBUILD_ABORT; 932174604Sscottl else if (devinfo.u.array.Flags & ARRAY_FLAG_VERIFYING) 933174604Sscottl param[1] = AS_VERIFY_ABORT; 934174604Sscottl else if (devinfo.u.array.Flags & ARRAY_FLAG_INITIALIZING) 935174604Sscottl param[1] = AS_INITIALIZE_ABORT; 936174604Sscottl else if (devinfo.u.array.Flags & ARRAY_FLAG_TRANSFORMING) 937174604Sscottl param[1] = AS_TRANSFORM_ABORT; 938174604Sscottl else 939174604Sscottl return -1; 940174604Sscottl 941174604Sscottl KdPrint(("SET_ARRAY_STATE(%x, %d)", param[0], param[1])); 942174604Sscottl result = HPT_DO_IOCTL(HPT_IOCTL_SET_ARRAY_STATE, 943174604Sscottl param, sizeof(param), 0, 0); 944174604Sscottl 945174604Sscottl for (i=0; i<devinfo.u.array.nDisk; i++) 946174604Sscottl if (DEVICEID_VALID(devinfo.u.array.Members[i])) 947174604Sscottl __hpt_stop_tasks(vbus_ext, devinfo.u.array.Members[i]); 948174604Sscottl 949174604Sscottl return result; 950174604Sscottl} 951174604Sscottl 952174604Sscottlstatic void hpt_stop_tasks(PVBUS_EXT vbus_ext) 953174604Sscottl{ 954174604Sscottl DEVICEID ids[32]; 955174604Sscottl int i, count; 956174604Sscottl 957174604Sscottl count = hpt_get_logical_devices((DEVICEID *)&ids, sizeof(ids)/sizeof(ids[0])); 958174604Sscottl 959174604Sscottl for (i=0; i<count; i++) 960174604Sscottl __hpt_stop_tasks(vbus_ext, ids[i]); 961174604Sscottl} 962174604Sscottl 963174604Sscottlstatic d_open_t hpt_open; 964174604Sscottlstatic d_close_t hpt_close; 965174604Sscottlstatic d_ioctl_t hpt_ioctl; 966174604Sscottlstatic int hpt_rescan_bus(void); 967174604Sscottl 968174604Sscottlstatic struct cdevsw hpt_cdevsw = { 969174604Sscottl .d_open = hpt_open, 970174604Sscottl .d_close = hpt_close, 971174604Sscottl .d_ioctl = hpt_ioctl, 972174604Sscottl .d_name = driver_name, 973174604Sscottl#if __FreeBSD_version>=503000 974174604Sscottl .d_version = D_VERSION, 975174604Sscottl#endif 976174604Sscottl#if (__FreeBSD_version>=503000 && __FreeBSD_version<600034) 977174604Sscottl .d_flags = D_NEEDGIANT, 978174604Sscottl#endif 979174604Sscottl#if __FreeBSD_version<600034 980174604Sscottl#if __FreeBSD_version>501000 981174604Sscottl .d_maj = MAJOR_AUTO, 982174604Sscottl#else 983174604Sscottl .d_maj = HPT_DEV_MAJOR, 984174604Sscottl#endif 985174604Sscottl#endif 986174604Sscottl}; 987174604Sscottl 988174604Sscottlstatic struct intr_config_hook hpt_ich; 989174604Sscottl 990174604Sscottl/* 991174604Sscottl * hpt_final_init will be called after all hpt_attach. 992174604Sscottl */ 993174604Sscottlstatic void hpt_final_init(void *dummy) 994174604Sscottl{ 995174604Sscottl int i; 996174604Sscottl PVBUS_EXT vbus_ext; 997174604Sscottl PVBUS vbus; 998174604Sscottl PHBA hba; 999174604Sscottl 1000174604Sscottl /* Clear the config hook */ 1001174604Sscottl config_intrhook_disestablish(&hpt_ich); 1002174604Sscottl 1003174604Sscottl /* allocate memory */ 1004174604Sscottl i = 0; 1005174604Sscottl ldm_for_each_vbus(vbus, vbus_ext) { 1006174604Sscottl if (hpt_alloc_mem(vbus_ext)) { 1007174604Sscottl os_printk("out of memory"); 1008174604Sscottl return; 1009174604Sscottl } 1010174604Sscottl i++; 1011174604Sscottl } 1012174604Sscottl 1013174604Sscottl if (!i) { 1014175363Ssobomax if (bootverbose) 1015175363Ssobomax os_printk("no controller detected."); 1016174604Sscottl return; 1017174604Sscottl } 1018174604Sscottl 1019174604Sscottl /* initializing hardware */ 1020174604Sscottl ldm_for_each_vbus(vbus, vbus_ext) { 1021174604Sscottl /* make timer available here */ 1022174604Sscottl callout_handle_init(&vbus_ext->timer); 1023174604Sscottl if (hpt_init_vbus(vbus_ext)) { 1024174604Sscottl os_printk("fail to initialize hardware"); 1025174604Sscottl break; /* FIXME */ 1026174604Sscottl } 1027174604Sscottl } 1028174604Sscottl 1029174604Sscottl /* register CAM interface */ 1030174604Sscottl ldm_for_each_vbus(vbus, vbus_ext) { 1031174604Sscottl struct cam_devq *devq; 1032174604Sscottl struct ccb_setasync ccb; 1033174604Sscottl 1034174604Sscottl#if (__FreeBSD_version >= 500000) 1035174604Sscottl mtx_init(&vbus_ext->lock, "hptsleeplock", NULL, MTX_DEF); 1036174604Sscottl#endif 1037174604Sscottl if (bus_dma_tag_create(NULL,/* parent */ 1038174604Sscottl 4, /* alignment */ 1039174604Sscottl BUS_SPACE_MAXADDR_32BIT+1, /* boundary */ 1040174604Sscottl BUS_SPACE_MAXADDR, /* lowaddr */ 1041174604Sscottl BUS_SPACE_MAXADDR, /* highaddr */ 1042174604Sscottl NULL, NULL, /* filter, filterarg */ 1043174604Sscottl PAGE_SIZE * (os_max_sg_descriptors-1), /* maxsize */ 1044174604Sscottl os_max_sg_descriptors, /* nsegments */ 1045174604Sscottl 0x10000, /* maxsegsize */ 1046174604Sscottl BUS_DMA_WAITOK, /* flags */ 1047174604Sscottl#if __FreeBSD_version>502000 1048174604Sscottl busdma_lock_mutex, /* lockfunc */ 1049174604Sscottl &vbus_ext->lock, /* lockfuncarg */ 1050174604Sscottl#endif 1051174604Sscottl &vbus_ext->io_dmat /* tag */)) 1052174604Sscottl { 1053174604Sscottl return ; 1054174604Sscottl } 1055174604Sscottl 1056174604Sscottl for (i=0; i<os_max_queue_comm; i++) { 1057174604Sscottl POS_CMDEXT ext = (POS_CMDEXT)malloc(sizeof(OS_CMDEXT), M_DEVBUF, M_WAITOK); 1058174604Sscottl if (!ext) { 1059174604Sscottl os_printk("Can't alloc cmdext(%d)", i); 1060174604Sscottl return ; 1061174604Sscottl } 1062174604Sscottl ext->vbus_ext = vbus_ext; 1063174604Sscottl ext->next = vbus_ext->cmdext_list; 1064174604Sscottl vbus_ext->cmdext_list = ext; 1065174604Sscottl 1066174604Sscottl if (bus_dmamap_create(vbus_ext->io_dmat, 0, &ext->dma_map)) { 1067174604Sscottl os_printk("Can't create dma map(%d)", i); 1068174604Sscottl return ; 1069174604Sscottl } 1070255871Sscottl callout_handle_init(&ext->timeout_ch); 1071174604Sscottl } 1072174604Sscottl 1073174604Sscottl if ((devq = cam_simq_alloc(os_max_queue_comm)) == NULL) { 1074174604Sscottl os_printk("cam_simq_alloc failed"); 1075174604Sscottl return ; 1076174604Sscottl } 1077174604Sscottl 1078174604Sscottl#if __FreeBSD_version > 700025 1079174604Sscottl vbus_ext->sim = cam_sim_alloc(hpt_action, hpt_poll, driver_name, 1080174604Sscottl vbus_ext, 0, &Giant, os_max_queue_comm, /*tagged*/8, devq); 1081174604Sscottl#else 1082174604Sscottl vbus_ext->sim = cam_sim_alloc(hpt_action, hpt_poll, driver_name, 1083174604Sscottl vbus_ext, 0, os_max_queue_comm, /*tagged*/8, devq); 1084174604Sscottl#endif 1085174604Sscottl 1086174604Sscottl if (!vbus_ext->sim) { 1087174604Sscottl os_printk("cam_sim_alloc failed"); 1088174604Sscottl cam_simq_free(devq); 1089174604Sscottl return ; 1090174604Sscottl } 1091174604Sscottl 1092174604Sscottl#if __FreeBSD_version > 700044 1093174604Sscottl if (xpt_bus_register(vbus_ext->sim, NULL, 0) != CAM_SUCCESS) { 1094174604Sscottl#else 1095174604Sscottl if (xpt_bus_register(vbus_ext->sim, 0) != CAM_SUCCESS) { 1096174604Sscottl#endif 1097174604Sscottl os_printk("xpt_bus_register failed"); 1098174604Sscottl cam_sim_free(vbus_ext->sim, /*free devq*/ TRUE); 1099174604Sscottl vbus_ext->sim = NULL; 1100174604Sscottl return ; 1101174604Sscottl } 1102174604Sscottl 1103174604Sscottl if (xpt_create_path(&vbus_ext->path, /*periph */ NULL, 1104174604Sscottl cam_sim_path(vbus_ext->sim), CAM_TARGET_WILDCARD, 1105174604Sscottl CAM_LUN_WILDCARD) != CAM_REQ_CMP) 1106174604Sscottl { 1107174604Sscottl os_printk("xpt_create_path failed"); 1108174604Sscottl xpt_bus_deregister(cam_sim_path(vbus_ext->sim)); 1109174604Sscottl cam_sim_free(vbus_ext->sim, /*free_devq*/TRUE); 1110174604Sscottl vbus_ext->sim = NULL; 1111174604Sscottl return ; 1112174604Sscottl } 1113174604Sscottl 1114174604Sscottl xpt_setup_ccb(&ccb.ccb_h, vbus_ext->path, /*priority*/5); 1115174604Sscottl ccb.ccb_h.func_code = XPT_SASYNC_CB; 1116174604Sscottl ccb.event_enable = AC_LOST_DEVICE; 1117174604Sscottl ccb.callback = hpt_async; 1118174604Sscottl ccb.callback_arg = vbus_ext; 1119174604Sscottl xpt_action((union ccb *)&ccb); 1120174604Sscottl 1121174604Sscottl for (hba = vbus_ext->hba_list; hba; hba = hba->next) { 1122174604Sscottl int rid = 0; 1123174604Sscottl if ((hba->irq_res = bus_alloc_resource(hba->pcidev, 1124174604Sscottl SYS_RES_IRQ, &rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) 1125174604Sscottl { 1126174604Sscottl os_printk("can't allocate interrupt"); 1127174604Sscottl return ; 1128174604Sscottl } 1129174604Sscottl 1130174604Sscottl if (bus_setup_intr(hba->pcidev, hba->irq_res, INTR_TYPE_CAM, 1131174604Sscottl#if __FreeBSD_version > 700025 1132174604Sscottl NULL, hpt_pci_intr, vbus_ext, &hba->irq_handle)) 1133174604Sscottl#else 1134174604Sscottl hpt_pci_intr, vbus_ext, &hba->irq_handle)) 1135174604Sscottl#endif 1136174604Sscottl { 1137174604Sscottl os_printk("can't set up interrupt"); 1138174604Sscottl return ; 1139174604Sscottl } 1140174604Sscottl hba->ldm_adapter.him->intr_control(hba->ldm_adapter.him_handle, HPT_TRUE); 1141174604Sscottl } 1142174604Sscottl 1143174604Sscottl vbus_ext->shutdown_eh = EVENTHANDLER_REGISTER(shutdown_final, 1144174604Sscottl hpt_shutdown_vbus, vbus_ext, SHUTDOWN_PRI_DEFAULT); 1145174604Sscottl if (!vbus_ext->shutdown_eh) 1146174604Sscottl os_printk("Shutdown event registration failed"); 1147174604Sscottl } 1148174604Sscottl 1149174604Sscottl ldm_for_each_vbus(vbus, vbus_ext) { 1150174604Sscottl TASK_INIT(&vbus_ext->worker, 0, (task_fn_t *)hpt_do_tasks, vbus_ext); 1151174604Sscottl if (vbus_ext->tasks) 1152174604Sscottl TASK_ENQUEUE(&vbus_ext->worker); 1153174604Sscottl } 1154174604Sscottl 1155174604Sscottl make_dev(&hpt_cdevsw, DRIVER_MINOR, UID_ROOT, GID_OPERATOR, 1156213780Srpaulo S_IRUSR | S_IWUSR, "%s", driver_name); 1157174604Sscottl} 1158174604Sscottl 1159174604Sscottl#if defined(KLD_MODULE) && (__FreeBSD_version >= 503000) 1160174604Sscottl 1161174604Sscottltypedef struct driverlink *driverlink_t; 1162174604Sscottlstruct driverlink { 1163174604Sscottl kobj_class_t driver; 1164174604Sscottl TAILQ_ENTRY(driverlink) link; /* list of drivers in devclass */ 1165174604Sscottl}; 1166174604Sscottl 1167174604Sscottltypedef TAILQ_HEAD(driver_list, driverlink) driver_list_t; 1168174604Sscottl 1169174604Sscottlstruct devclass { 1170174604Sscottl TAILQ_ENTRY(devclass) link; 1171174604Sscottl devclass_t parent; /* parent in devclass hierarchy */ 1172174604Sscottl driver_list_t drivers; /* bus devclasses store drivers for bus */ 1173174604Sscottl char *name; 1174174604Sscottl device_t *devices; /* array of devices indexed by unit */ 1175174604Sscottl int maxunit; /* size of devices array */ 1176174604Sscottl}; 1177174604Sscottl 1178174604Sscottlstatic void override_kernel_driver(void) 1179174604Sscottl{ 1180174604Sscottl driverlink_t dl, dlfirst; 1181174604Sscottl driver_t *tmpdriver; 1182174604Sscottl devclass_t dc = devclass_find("pci"); 1183174604Sscottl 1184174604Sscottl if (dc){ 1185174604Sscottl dlfirst = TAILQ_FIRST(&dc->drivers); 1186174604Sscottl for (dl = dlfirst; dl; dl = TAILQ_NEXT(dl, link)) { 1187174604Sscottl if(strcmp(dl->driver->name, driver_name) == 0) { 1188174604Sscottl tmpdriver=dl->driver; 1189174604Sscottl dl->driver=dlfirst->driver; 1190174604Sscottl dlfirst->driver=tmpdriver; 1191174604Sscottl break; 1192174604Sscottl } 1193174604Sscottl } 1194174604Sscottl } 1195174604Sscottl} 1196174604Sscottl 1197174604Sscottl#else 1198174604Sscottl#define override_kernel_driver() 1199174604Sscottl#endif 1200174604Sscottl 1201174604Sscottlstatic void hpt_init(void *dummy) 1202174604Sscottl{ 1203175363Ssobomax if (bootverbose) 1204175363Ssobomax os_printk("%s %s", driver_name_long, driver_ver); 1205174604Sscottl 1206174604Sscottl override_kernel_driver(); 1207174604Sscottl init_config(); 1208174604Sscottl 1209174604Sscottl hpt_ich.ich_func = hpt_final_init; 1210174604Sscottl hpt_ich.ich_arg = NULL; 1211174604Sscottl if (config_intrhook_establish(&hpt_ich) != 0) { 1212174604Sscottl printf("%s: cannot establish configuration hook\n", 1213174604Sscottl driver_name_long); 1214174604Sscottl } 1215174604Sscottl 1216174604Sscottl} 1217174604SscottlSYSINIT(hptinit, SI_SUB_CONFIGURE, SI_ORDER_FIRST, hpt_init, NULL); 1218174604Sscottl 1219174604Sscottl/* 1220174604Sscottl * CAM driver interface 1221174604Sscottl */ 1222174604Sscottlstatic device_method_t driver_methods[] = { 1223174604Sscottl /* Device interface */ 1224174604Sscottl DEVMETHOD(device_probe, hpt_probe), 1225174604Sscottl DEVMETHOD(device_attach, hpt_attach), 1226174604Sscottl DEVMETHOD(device_detach, hpt_detach), 1227174604Sscottl DEVMETHOD(device_shutdown, hpt_shutdown), 1228227912Smarius DEVMETHOD_END 1229174604Sscottl}; 1230174604Sscottl 1231174604Sscottlstatic driver_t hpt_pci_driver = { 1232174604Sscottl driver_name, 1233174604Sscottl driver_methods, 1234174604Sscottl sizeof(HBA) 1235174604Sscottl}; 1236174604Sscottl 1237174604Sscottlstatic devclass_t hpt_devclass; 1238174604Sscottl 1239174604Sscottl#ifndef TARGETNAME 1240174604Sscottl#error "no TARGETNAME found" 1241174604Sscottl#endif 1242174604Sscottl 1243174604Sscottl/* use this to make TARGETNAME be expanded */ 1244174604Sscottl#define __DRIVER_MODULE(p1, p2, p3, p4, p5, p6) DRIVER_MODULE(p1, p2, p3, p4, p5, p6) 1245174604Sscottl#define __MODULE_VERSION(p1, p2) MODULE_VERSION(p1, p2) 1246174604Sscottl#define __MODULE_DEPEND(p1, p2, p3, p4, p5) MODULE_DEPEND(p1, p2, p3, p4, p5) 1247174604Sscottl__DRIVER_MODULE(TARGETNAME, pci, hpt_pci_driver, hpt_devclass, 0, 0); 1248174604Sscottl__MODULE_VERSION(TARGETNAME, 1); 1249174604Sscottl__MODULE_DEPEND(TARGETNAME, cam, 1, 1, 1); 1250174604Sscottl 1251174604Sscottl#if __FreeBSD_version>503000 1252174604Sscottltypedef struct cdev * ioctl_dev_t; 1253174604Sscottl#else 1254174604Sscottltypedef dev_t ioctl_dev_t; 1255174604Sscottl#endif 1256174604Sscottl 1257174604Sscottl#if __FreeBSD_version >= 500000 1258174604Sscottltypedef struct thread * ioctl_thread_t; 1259174604Sscottl#else 1260174604Sscottltypedef struct proc * ioctl_thread_t; 1261174604Sscottl#endif 1262174604Sscottl 1263174604Sscottlstatic int hpt_open(ioctl_dev_t dev, int flags, int devtype, ioctl_thread_t td) 1264174604Sscottl{ 1265174604Sscottl return 0; 1266174604Sscottl} 1267174604Sscottl 1268174604Sscottlstatic int hpt_close(ioctl_dev_t dev, int flags, int devtype, ioctl_thread_t td) 1269174604Sscottl{ 1270174604Sscottl return 0; 1271174604Sscottl} 1272174604Sscottl 1273174604Sscottlstatic int hpt_ioctl(ioctl_dev_t dev, u_long cmd, caddr_t data, int fflag, ioctl_thread_t td) 1274174604Sscottl{ 1275174604Sscottl PHPT_IOCTL_PARAM piop=(PHPT_IOCTL_PARAM)data; 1276174604Sscottl IOCTL_ARG ioctl_args; 1277174604Sscottl HPT_U32 bytesReturned; 1278174604Sscottl 1279174604Sscottl switch (cmd){ 1280174604Sscottl case HPT_DO_IOCONTROL: 1281174604Sscottl { 1282174604Sscottl if (piop->Magic == HPT_IOCTL_MAGIC || piop->Magic == HPT_IOCTL_MAGIC32) { 1283174604Sscottl KdPrint(("ioctl=%x in=%p len=%d out=%p len=%d\n", 1284174604Sscottl piop->dwIoControlCode, 1285174604Sscottl piop->lpInBuffer, 1286174604Sscottl piop->nInBufferSize, 1287174604Sscottl piop->lpOutBuffer, 1288174604Sscottl piop->nOutBufferSize)); 1289174604Sscottl 1290174604Sscottl memset(&ioctl_args, 0, sizeof(ioctl_args)); 1291174604Sscottl 1292174604Sscottl ioctl_args.dwIoControlCode = piop->dwIoControlCode; 1293174604Sscottl ioctl_args.nInBufferSize = piop->nInBufferSize; 1294174604Sscottl ioctl_args.nOutBufferSize = piop->nOutBufferSize; 1295174604Sscottl ioctl_args.lpBytesReturned = &bytesReturned; 1296174604Sscottl 1297174604Sscottl if (ioctl_args.nInBufferSize) { 1298174604Sscottl ioctl_args.lpInBuffer = malloc(ioctl_args.nInBufferSize, M_DEVBUF, M_WAITOK); 1299174604Sscottl if (!ioctl_args.lpInBuffer) 1300174604Sscottl goto invalid; 1301174604Sscottl if (copyin((void*)piop->lpInBuffer, 1302174604Sscottl ioctl_args.lpInBuffer, piop->nInBufferSize)) 1303174604Sscottl goto invalid; 1304174604Sscottl } 1305174604Sscottl 1306174604Sscottl if (ioctl_args.nOutBufferSize) { 1307174604Sscottl ioctl_args.lpOutBuffer = malloc(ioctl_args.nOutBufferSize, M_DEVBUF, M_WAITOK); 1308174604Sscottl if (!ioctl_args.lpOutBuffer) 1309174604Sscottl goto invalid; 1310174604Sscottl } 1311174604Sscottl 1312174604Sscottl#if (__FreeBSD_version >= 500000) 1313174604Sscottl mtx_lock(&Giant); 1314174604Sscottl#endif 1315174604Sscottl 1316174604Sscottl hpt_do_ioctl(&ioctl_args); 1317174604Sscottl 1318174604Sscottl#if (__FreeBSD_version >= 500000) 1319174604Sscottl mtx_unlock(&Giant); 1320174604Sscottl#endif 1321174604Sscottl 1322174604Sscottl if (ioctl_args.result==HPT_IOCTL_RESULT_OK) { 1323174604Sscottl if (piop->nOutBufferSize) { 1324174604Sscottl if (copyout(ioctl_args.lpOutBuffer, 1325174604Sscottl (void*)piop->lpOutBuffer, piop->nOutBufferSize)) 1326174604Sscottl goto invalid; 1327174604Sscottl } 1328174604Sscottl if (piop->lpBytesReturned) { 1329174604Sscottl if (copyout(&bytesReturned, 1330174604Sscottl (void*)piop->lpBytesReturned, sizeof(HPT_U32))) 1331174604Sscottl goto invalid; 1332174604Sscottl } 1333174604Sscottl if (ioctl_args.lpInBuffer) free(ioctl_args.lpInBuffer, M_DEVBUF); 1334174604Sscottl if (ioctl_args.lpOutBuffer) free(ioctl_args.lpOutBuffer, M_DEVBUF); 1335174604Sscottl return 0; 1336174604Sscottl } 1337174604Sscottlinvalid: 1338174604Sscottl if (ioctl_args.lpInBuffer) free(ioctl_args.lpInBuffer, M_DEVBUF); 1339174604Sscottl if (ioctl_args.lpOutBuffer) free(ioctl_args.lpOutBuffer, M_DEVBUF); 1340174604Sscottl return EFAULT; 1341174604Sscottl } 1342174604Sscottl return EFAULT; 1343174604Sscottl } 1344174604Sscottl 1345174604Sscottl case HPT_SCAN_BUS: 1346174604Sscottl { 1347174604Sscottl return hpt_rescan_bus(); 1348174604Sscottl } 1349174604Sscottl default: 1350174604Sscottl KdPrint(("invalid command!")); 1351174604Sscottl return EFAULT; 1352174604Sscottl } 1353174604Sscottl 1354174604Sscottl} 1355174604Sscottl 1356174604Sscottlstatic int hpt_rescan_bus(void) 1357174604Sscottl{ 1358174604Sscottl union ccb *ccb; 1359174604Sscottl PVBUS vbus; 1360174604Sscottl PVBUS_EXT vbus_ext; 1361174604Sscottl 1362174604Sscottl#if (__FreeBSD_version >= 500000) 1363174604Sscottl mtx_lock(&Giant); 1364174604Sscottl#endif 1365174604Sscottl 1366174604Sscottl ldm_for_each_vbus(vbus, vbus_ext) { 1367203108Smav if ((ccb = xpt_alloc_ccb()) == NULL) 1368203108Smav return(ENOMEM); 1369249468Smav if (xpt_create_path(&ccb->ccb_h.path, NULL, 1370203108Smav cam_sim_path(vbus_ext->sim), 1371203108Smav CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 1372203108Smav xpt_free_ccb(ccb); 1373174604Sscottl return(EIO); 1374203108Smav } 1375203108Smav xpt_rescan(ccb); 1376174604Sscottl } 1377174604Sscottl 1378174604Sscottl#if (__FreeBSD_version >= 500000) 1379174604Sscottl mtx_unlock(&Giant); 1380174604Sscottl#endif 1381174604Sscottl 1382174604Sscottl return(0); 1383174604Sscottl} 1384