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