1*1fdeb165SXin LI /* $Id: osm_bsd.c,v 1.36 2010/05/11 03:12:11 lcn Exp $ */ 2*1fdeb165SXin LI /*- 3*1fdeb165SXin LI * HighPoint RAID Driver for FreeBSD 4*1fdeb165SXin LI * Copyright (C) 2005-2011 HighPoint Technologies, Inc. 5*1fdeb165SXin LI * All rights reserved. 6*1fdeb165SXin LI * 7*1fdeb165SXin LI * Redistribution and use in source and binary forms, with or without 8*1fdeb165SXin LI * modification, are permitted provided that the following conditions 9*1fdeb165SXin LI * are met: 10*1fdeb165SXin LI * 1. Redistributions of source code must retain the above copyright 11*1fdeb165SXin LI * notice, this list of conditions and the following disclaimer. 12*1fdeb165SXin LI * 2. Redistributions in binary form must reproduce the above copyright 13*1fdeb165SXin LI * notice, this list of conditions and the following disclaimer in the 14*1fdeb165SXin LI * documentation and/or other materials provided with the distribution. 15*1fdeb165SXin LI * 16*1fdeb165SXin LI * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17*1fdeb165SXin LI * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18*1fdeb165SXin LI * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19*1fdeb165SXin LI * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20*1fdeb165SXin LI * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21*1fdeb165SXin LI * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22*1fdeb165SXin LI * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23*1fdeb165SXin LI * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24*1fdeb165SXin LI * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25*1fdeb165SXin LI * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26*1fdeb165SXin LI * SUCH DAMAGE. 27*1fdeb165SXin LI * 28*1fdeb165SXin LI * $FreeBSD$ 29*1fdeb165SXin LI */ 30*1fdeb165SXin LI #include <dev/hptnr/hptnr_config.h> 31*1fdeb165SXin LI #include <dev/hptnr/os_bsd.h> 32*1fdeb165SXin LI #include <dev/hptnr/hptintf.h> 33*1fdeb165SXin LI 34*1fdeb165SXin LI static int hpt_probe(device_t dev) 35*1fdeb165SXin LI { 36*1fdeb165SXin LI PCI_ID pci_id; 37*1fdeb165SXin LI HIM *him; 38*1fdeb165SXin LI int i; 39*1fdeb165SXin LI PHBA hba; 40*1fdeb165SXin LI 41*1fdeb165SXin LI for (him = him_list; him; him = him->next) { 42*1fdeb165SXin LI for (i=0; him->get_supported_device_id(i, &pci_id); i++) { 43*1fdeb165SXin LI if (him->get_controller_count) 44*1fdeb165SXin LI him->get_controller_count(&pci_id,0,0); 45*1fdeb165SXin LI if ((pci_get_vendor(dev) == pci_id.vid) && 46*1fdeb165SXin LI (pci_get_device(dev) == pci_id.did)){ 47*1fdeb165SXin LI KdPrint(("hpt_probe: adapter at PCI %d:%d:%d, IRQ %d", 48*1fdeb165SXin LI pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev), pci_get_irq(dev) 49*1fdeb165SXin LI )); 50*1fdeb165SXin LI device_set_desc(dev, him->name); 51*1fdeb165SXin LI hba = (PHBA)device_get_softc(dev); 52*1fdeb165SXin LI memset(hba, 0, sizeof(HBA)); 53*1fdeb165SXin LI hba->ext_type = EXT_TYPE_HBA; 54*1fdeb165SXin LI hba->ldm_adapter.him = him; 55*1fdeb165SXin LI return 0; 56*1fdeb165SXin LI } 57*1fdeb165SXin LI } 58*1fdeb165SXin LI } 59*1fdeb165SXin LI 60*1fdeb165SXin LI return (ENXIO); 61*1fdeb165SXin LI } 62*1fdeb165SXin LI 63*1fdeb165SXin LI static int hpt_attach(device_t dev) 64*1fdeb165SXin LI { 65*1fdeb165SXin LI PHBA hba = (PHBA)device_get_softc(dev); 66*1fdeb165SXin LI HIM *him = hba->ldm_adapter.him; 67*1fdeb165SXin LI PCI_ID pci_id; 68*1fdeb165SXin LI HPT_UINT size; 69*1fdeb165SXin LI PVBUS vbus; 70*1fdeb165SXin LI PVBUS_EXT vbus_ext; 71*1fdeb165SXin LI 72*1fdeb165SXin LI KdPrint(("hpt_attach(%d/%d/%d)", pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev))); 73*1fdeb165SXin LI 74*1fdeb165SXin LI #if __FreeBSD_version >=440000 75*1fdeb165SXin LI pci_enable_busmaster(dev); 76*1fdeb165SXin LI #endif 77*1fdeb165SXin LI 78*1fdeb165SXin LI pci_id.vid = pci_get_vendor(dev); 79*1fdeb165SXin LI pci_id.did = pci_get_device(dev); 80*1fdeb165SXin LI pci_id.rev = pci_get_revid(dev); 81*1fdeb165SXin LI pci_id.subsys = (HPT_U32)(pci_get_subdevice(dev)) << 16 | pci_get_subvendor(dev); 82*1fdeb165SXin LI 83*1fdeb165SXin LI size = him->get_adapter_size(&pci_id); 84*1fdeb165SXin LI hba->ldm_adapter.him_handle = malloc(size, M_DEVBUF, M_WAITOK); 85*1fdeb165SXin LI if (!hba->ldm_adapter.him_handle) 86*1fdeb165SXin LI return ENXIO; 87*1fdeb165SXin LI 88*1fdeb165SXin LI hba->pcidev = dev; 89*1fdeb165SXin LI hba->pciaddr.tree = 0; 90*1fdeb165SXin LI hba->pciaddr.bus = pci_get_bus(dev); 91*1fdeb165SXin LI hba->pciaddr.device = pci_get_slot(dev); 92*1fdeb165SXin LI hba->pciaddr.function = pci_get_function(dev); 93*1fdeb165SXin LI 94*1fdeb165SXin LI if (!him->create_adapter(&pci_id, hba->pciaddr, hba->ldm_adapter.him_handle, hba)) { 95*1fdeb165SXin LI free(hba->ldm_adapter.him_handle, M_DEVBUF); 96*1fdeb165SXin LI return -1; 97*1fdeb165SXin LI } 98*1fdeb165SXin LI 99*1fdeb165SXin LI os_printk("adapter at PCI %d:%d:%d, IRQ %d", 100*1fdeb165SXin LI hba->pciaddr.bus, hba->pciaddr.device, hba->pciaddr.function, pci_get_irq(dev)); 101*1fdeb165SXin LI 102*1fdeb165SXin LI if (!ldm_register_adapter(&hba->ldm_adapter)) { 103*1fdeb165SXin LI size = ldm_get_vbus_size(); 104*1fdeb165SXin LI vbus_ext = malloc(sizeof(VBUS_EXT) + size, M_DEVBUF, M_WAITOK); 105*1fdeb165SXin LI if (!vbus_ext) { 106*1fdeb165SXin LI free(hba->ldm_adapter.him_handle, M_DEVBUF); 107*1fdeb165SXin LI return -1; 108*1fdeb165SXin LI } 109*1fdeb165SXin LI memset(vbus_ext, 0, sizeof(VBUS_EXT)); 110*1fdeb165SXin LI vbus_ext->ext_type = EXT_TYPE_VBUS; 111*1fdeb165SXin LI ldm_create_vbus((PVBUS)vbus_ext->vbus, vbus_ext); 112*1fdeb165SXin LI ldm_register_adapter(&hba->ldm_adapter); 113*1fdeb165SXin LI } 114*1fdeb165SXin LI 115*1fdeb165SXin LI ldm_for_each_vbus(vbus, vbus_ext) { 116*1fdeb165SXin LI if (hba->ldm_adapter.vbus==vbus) { 117*1fdeb165SXin LI hba->vbus_ext = vbus_ext; 118*1fdeb165SXin LI hba->next = vbus_ext->hba_list; 119*1fdeb165SXin LI vbus_ext->hba_list = hba; 120*1fdeb165SXin LI break; 121*1fdeb165SXin LI } 122*1fdeb165SXin LI } 123*1fdeb165SXin LI return 0; 124*1fdeb165SXin LI } 125*1fdeb165SXin LI 126*1fdeb165SXin LI /* 127*1fdeb165SXin LI * Maybe we'd better to use the bus_dmamem_alloc to alloc DMA memory, 128*1fdeb165SXin LI * but there are some problems currently (alignment, etc). 129*1fdeb165SXin LI */ 130*1fdeb165SXin LI static __inline void *__get_free_pages(int order) 131*1fdeb165SXin LI { 132*1fdeb165SXin LI /* don't use low memory - other devices may get starved */ 133*1fdeb165SXin LI return contigmalloc(PAGE_SIZE<<order, 134*1fdeb165SXin LI M_DEVBUF, M_WAITOK, BUS_SPACE_MAXADDR_24BIT, BUS_SPACE_MAXADDR, PAGE_SIZE, 0); 135*1fdeb165SXin LI } 136*1fdeb165SXin LI 137*1fdeb165SXin LI static __inline void free_pages(void *p, int order) 138*1fdeb165SXin LI { 139*1fdeb165SXin LI contigfree(p, PAGE_SIZE<<order, M_DEVBUF); 140*1fdeb165SXin LI } 141*1fdeb165SXin LI 142*1fdeb165SXin LI static int hpt_alloc_mem(PVBUS_EXT vbus_ext) 143*1fdeb165SXin LI { 144*1fdeb165SXin LI PHBA hba; 145*1fdeb165SXin LI struct freelist *f; 146*1fdeb165SXin LI HPT_UINT i; 147*1fdeb165SXin LI void **p; 148*1fdeb165SXin LI 149*1fdeb165SXin LI for (hba = vbus_ext->hba_list; hba; hba = hba->next) 150*1fdeb165SXin LI hba->ldm_adapter.him->get_meminfo(hba->ldm_adapter.him_handle); 151*1fdeb165SXin LI 152*1fdeb165SXin LI ldm_get_mem_info((PVBUS)vbus_ext->vbus, 0); 153*1fdeb165SXin LI 154*1fdeb165SXin LI for (f=vbus_ext->freelist_head; f; f=f->next) { 155*1fdeb165SXin LI KdPrint(("%s: %d*%d=%d bytes", 156*1fdeb165SXin LI f->tag, f->count, f->size, f->count*f->size)); 157*1fdeb165SXin LI for (i=0; i<f->count; i++) { 158*1fdeb165SXin LI p = (void **)malloc(f->size, M_DEVBUF, M_WAITOK); 159*1fdeb165SXin LI if (!p) return (ENXIO); 160*1fdeb165SXin LI *p = f->head; 161*1fdeb165SXin LI f->head = p; 162*1fdeb165SXin LI } 163*1fdeb165SXin LI } 164*1fdeb165SXin LI 165*1fdeb165SXin LI for (f=vbus_ext->freelist_dma_head; f; f=f->next) { 166*1fdeb165SXin LI int order, size, j; 167*1fdeb165SXin LI 168*1fdeb165SXin LI HPT_ASSERT((f->size & (f->alignment-1))==0); 169*1fdeb165SXin LI 170*1fdeb165SXin LI for (order=0, size=PAGE_SIZE; size<f->size; order++, size<<=1) 171*1fdeb165SXin LI ; 172*1fdeb165SXin LI 173*1fdeb165SXin LI KdPrint(("%s: %d*%d=%d bytes, order %d", 174*1fdeb165SXin LI f->tag, f->count, f->size, f->count*f->size, order)); 175*1fdeb165SXin LI HPT_ASSERT(f->alignment<=PAGE_SIZE); 176*1fdeb165SXin LI 177*1fdeb165SXin LI for (i=0; i<f->count;) { 178*1fdeb165SXin LI p = (void **)__get_free_pages(order); 179*1fdeb165SXin LI if (!p) return -1; 180*1fdeb165SXin LI for (j = size/f->size; j && i<f->count; i++,j--) { 181*1fdeb165SXin LI *p = f->head; 182*1fdeb165SXin LI *(BUS_ADDRESS *)(p+1) = (BUS_ADDRESS)vtophys(p); 183*1fdeb165SXin LI f->head = p; 184*1fdeb165SXin LI p = (void **)((unsigned long)p + f->size); 185*1fdeb165SXin LI } 186*1fdeb165SXin LI } 187*1fdeb165SXin LI } 188*1fdeb165SXin LI 189*1fdeb165SXin LI HPT_ASSERT(PAGE_SIZE==DMAPOOL_PAGE_SIZE); 190*1fdeb165SXin LI 191*1fdeb165SXin LI for (i=0; i<os_max_cache_pages; i++) { 192*1fdeb165SXin LI p = (void **)__get_free_pages(0); 193*1fdeb165SXin LI if (!p) return -1; 194*1fdeb165SXin LI HPT_ASSERT(((HPT_UPTR)p & (DMAPOOL_PAGE_SIZE-1))==0); 195*1fdeb165SXin LI dmapool_put_page((PVBUS)vbus_ext->vbus, p, (BUS_ADDRESS)vtophys(p)); 196*1fdeb165SXin LI } 197*1fdeb165SXin LI 198*1fdeb165SXin LI return 0; 199*1fdeb165SXin LI } 200*1fdeb165SXin LI 201*1fdeb165SXin LI static void hpt_free_mem(PVBUS_EXT vbus_ext) 202*1fdeb165SXin LI { 203*1fdeb165SXin LI struct freelist *f; 204*1fdeb165SXin LI void *p; 205*1fdeb165SXin LI int i; 206*1fdeb165SXin LI BUS_ADDRESS bus; 207*1fdeb165SXin LI 208*1fdeb165SXin LI for (f=vbus_ext->freelist_head; f; f=f->next) { 209*1fdeb165SXin LI #if DBG 210*1fdeb165SXin LI if (f->count!=f->reserved_count) { 211*1fdeb165SXin LI KdPrint(("memory leak for freelist %s (%d/%d)", f->tag, f->count, f->reserved_count)); 212*1fdeb165SXin LI } 213*1fdeb165SXin LI #endif 214*1fdeb165SXin LI while ((p=freelist_get(f))) 215*1fdeb165SXin LI free(p, M_DEVBUF); 216*1fdeb165SXin LI } 217*1fdeb165SXin LI 218*1fdeb165SXin LI for (i=0; i<os_max_cache_pages; i++) { 219*1fdeb165SXin LI p = dmapool_get_page((PVBUS)vbus_ext->vbus, &bus); 220*1fdeb165SXin LI HPT_ASSERT(p); 221*1fdeb165SXin LI free_pages(p, 0); 222*1fdeb165SXin LI } 223*1fdeb165SXin LI 224*1fdeb165SXin LI for (f=vbus_ext->freelist_dma_head; f; f=f->next) { 225*1fdeb165SXin LI int order, size; 226*1fdeb165SXin LI #if DBG 227*1fdeb165SXin LI if (f->count!=f->reserved_count) { 228*1fdeb165SXin LI KdPrint(("memory leak for dma freelist %s (%d/%d)", f->tag, f->count, f->reserved_count)); 229*1fdeb165SXin LI } 230*1fdeb165SXin LI #endif 231*1fdeb165SXin LI for (order=0, size=PAGE_SIZE; size<f->size; order++, size<<=1) ; 232*1fdeb165SXin LI 233*1fdeb165SXin LI while ((p=freelist_get_dma(f, &bus))) { 234*1fdeb165SXin LI if (order) 235*1fdeb165SXin LI free_pages(p, order); 236*1fdeb165SXin LI else { 237*1fdeb165SXin LI /* can't free immediately since other blocks in this page may still be in the list */ 238*1fdeb165SXin LI if (((HPT_UPTR)p & (PAGE_SIZE-1))==0) 239*1fdeb165SXin LI dmapool_put_page((PVBUS)vbus_ext->vbus, p, bus); 240*1fdeb165SXin LI } 241*1fdeb165SXin LI } 242*1fdeb165SXin LI } 243*1fdeb165SXin LI 244*1fdeb165SXin LI while ((p = dmapool_get_page((PVBUS)vbus_ext->vbus, &bus))) 245*1fdeb165SXin LI free_pages(p, 0); 246*1fdeb165SXin LI } 247*1fdeb165SXin LI 248*1fdeb165SXin LI static int hpt_init_vbus(PVBUS_EXT vbus_ext) 249*1fdeb165SXin LI { 250*1fdeb165SXin LI PHBA hba; 251*1fdeb165SXin LI 252*1fdeb165SXin LI for (hba = vbus_ext->hba_list; hba; hba = hba->next) 253*1fdeb165SXin LI if (!hba->ldm_adapter.him->initialize(hba->ldm_adapter.him_handle)) { 254*1fdeb165SXin LI KdPrint(("fail to initialize %p", hba)); 255*1fdeb165SXin LI return -1; 256*1fdeb165SXin LI } 257*1fdeb165SXin LI 258*1fdeb165SXin LI ldm_initialize_vbus((PVBUS)vbus_ext->vbus, &vbus_ext->hba_list->ldm_adapter); 259*1fdeb165SXin LI return 0; 260*1fdeb165SXin LI } 261*1fdeb165SXin LI 262*1fdeb165SXin LI static void hpt_flush_done(PCOMMAND pCmd) 263*1fdeb165SXin LI { 264*1fdeb165SXin LI PVDEV vd = pCmd->target; 265*1fdeb165SXin LI 266*1fdeb165SXin LI if (mIsArray(vd->type) && vd->u.array.transform && vd!=vd->u.array.transform->target) { 267*1fdeb165SXin LI vd = vd->u.array.transform->target; 268*1fdeb165SXin LI HPT_ASSERT(vd); 269*1fdeb165SXin LI pCmd->target = vd; 270*1fdeb165SXin LI pCmd->Result = RETURN_PENDING; 271*1fdeb165SXin LI vdev_queue_cmd(pCmd); 272*1fdeb165SXin LI return; 273*1fdeb165SXin LI } 274*1fdeb165SXin LI 275*1fdeb165SXin LI *(int *)pCmd->priv = 1; 276*1fdeb165SXin LI wakeup(pCmd); 277*1fdeb165SXin LI } 278*1fdeb165SXin LI 279*1fdeb165SXin LI /* 280*1fdeb165SXin LI * flush a vdev (without retry). 281*1fdeb165SXin LI */ 282*1fdeb165SXin LI static int hpt_flush_vdev(PVBUS_EXT vbus_ext, PVDEV vd) 283*1fdeb165SXin LI { 284*1fdeb165SXin LI PCOMMAND pCmd; 285*1fdeb165SXin LI int result = 0, done; 286*1fdeb165SXin LI HPT_UINT count; 287*1fdeb165SXin LI 288*1fdeb165SXin LI KdPrint(("flusing dev %p", vd)); 289*1fdeb165SXin LI 290*1fdeb165SXin LI hpt_lock_vbus(vbus_ext); 291*1fdeb165SXin LI 292*1fdeb165SXin LI if (mIsArray(vd->type) && vd->u.array.transform) 293*1fdeb165SXin LI count = MAX(vd->u.array.transform->source->cmds_per_request, 294*1fdeb165SXin LI vd->u.array.transform->target->cmds_per_request); 295*1fdeb165SXin LI else 296*1fdeb165SXin LI count = vd->cmds_per_request; 297*1fdeb165SXin LI 298*1fdeb165SXin LI pCmd = ldm_alloc_cmds(vd->vbus, count); 299*1fdeb165SXin LI 300*1fdeb165SXin LI if (!pCmd) { 301*1fdeb165SXin LI hpt_unlock_vbus(vbus_ext); 302*1fdeb165SXin LI return -1; 303*1fdeb165SXin LI } 304*1fdeb165SXin LI 305*1fdeb165SXin LI pCmd->type = CMD_TYPE_FLUSH; 306*1fdeb165SXin LI pCmd->flags.hard_flush = 1; 307*1fdeb165SXin LI pCmd->target = vd; 308*1fdeb165SXin LI pCmd->done = hpt_flush_done; 309*1fdeb165SXin LI done = 0; 310*1fdeb165SXin LI pCmd->priv = &done; 311*1fdeb165SXin LI 312*1fdeb165SXin LI ldm_queue_cmd(pCmd); 313*1fdeb165SXin LI 314*1fdeb165SXin LI if (!done) { 315*1fdeb165SXin LI while (hpt_sleep(vbus_ext, pCmd, PPAUSE, "hptfls", HPT_OSM_TIMEOUT)) { 316*1fdeb165SXin LI ldm_reset_vbus(vd->vbus); 317*1fdeb165SXin LI } 318*1fdeb165SXin LI } 319*1fdeb165SXin LI 320*1fdeb165SXin LI KdPrint(("flush result %d", pCmd->Result)); 321*1fdeb165SXin LI 322*1fdeb165SXin LI if (pCmd->Result!=RETURN_SUCCESS) 323*1fdeb165SXin LI result = -1; 324*1fdeb165SXin LI 325*1fdeb165SXin LI ldm_free_cmds(pCmd); 326*1fdeb165SXin LI 327*1fdeb165SXin LI hpt_unlock_vbus(vbus_ext); 328*1fdeb165SXin LI 329*1fdeb165SXin LI return result; 330*1fdeb165SXin LI } 331*1fdeb165SXin LI 332*1fdeb165SXin LI static void hpt_stop_tasks(PVBUS_EXT vbus_ext); 333*1fdeb165SXin LI static void hpt_shutdown_vbus(PVBUS_EXT vbus_ext, int howto) 334*1fdeb165SXin LI { 335*1fdeb165SXin LI PVBUS vbus = (PVBUS)vbus_ext->vbus; 336*1fdeb165SXin LI PHBA hba; 337*1fdeb165SXin LI int i; 338*1fdeb165SXin LI 339*1fdeb165SXin LI KdPrint(("hpt_shutdown_vbus")); 340*1fdeb165SXin LI 341*1fdeb165SXin LI /* stop all ctl tasks and disable the worker taskqueue */ 342*1fdeb165SXin LI hpt_stop_tasks(vbus_ext); 343*1fdeb165SXin LI vbus_ext->worker.ta_context = 0; 344*1fdeb165SXin LI 345*1fdeb165SXin LI /* flush devices */ 346*1fdeb165SXin LI for (i=0; i<osm_max_targets; i++) { 347*1fdeb165SXin LI PVDEV vd = ldm_find_target(vbus, i); 348*1fdeb165SXin LI if (vd) { 349*1fdeb165SXin LI /* retry once */ 350*1fdeb165SXin LI if (hpt_flush_vdev(vbus_ext, vd)) 351*1fdeb165SXin LI hpt_flush_vdev(vbus_ext, vd); 352*1fdeb165SXin LI } 353*1fdeb165SXin LI } 354*1fdeb165SXin LI 355*1fdeb165SXin LI hpt_lock_vbus(vbus_ext); 356*1fdeb165SXin LI ldm_shutdown(vbus); 357*1fdeb165SXin LI hpt_unlock_vbus(vbus_ext); 358*1fdeb165SXin LI 359*1fdeb165SXin LI ldm_release_vbus(vbus); 360*1fdeb165SXin LI 361*1fdeb165SXin LI for (hba=vbus_ext->hba_list; hba; hba=hba->next) 362*1fdeb165SXin LI bus_teardown_intr(hba->pcidev, hba->irq_res, hba->irq_handle); 363*1fdeb165SXin LI 364*1fdeb165SXin LI hpt_free_mem(vbus_ext); 365*1fdeb165SXin LI 366*1fdeb165SXin LI while ((hba=vbus_ext->hba_list)) { 367*1fdeb165SXin LI vbus_ext->hba_list = hba->next; 368*1fdeb165SXin LI free(hba->ldm_adapter.him_handle, M_DEVBUF); 369*1fdeb165SXin LI } 370*1fdeb165SXin LI 371*1fdeb165SXin LI free(vbus_ext, M_DEVBUF); 372*1fdeb165SXin LI KdPrint(("hpt_shutdown_vbus done")); 373*1fdeb165SXin LI } 374*1fdeb165SXin LI 375*1fdeb165SXin LI static void __hpt_do_tasks(PVBUS_EXT vbus_ext) 376*1fdeb165SXin LI { 377*1fdeb165SXin LI OSM_TASK *tasks; 378*1fdeb165SXin LI 379*1fdeb165SXin LI tasks = vbus_ext->tasks; 380*1fdeb165SXin LI vbus_ext->tasks = 0; 381*1fdeb165SXin LI 382*1fdeb165SXin LI while (tasks) { 383*1fdeb165SXin LI OSM_TASK *t = tasks; 384*1fdeb165SXin LI tasks = t->next; 385*1fdeb165SXin LI t->next = 0; 386*1fdeb165SXin LI t->func(vbus_ext->vbus, t->data); 387*1fdeb165SXin LI } 388*1fdeb165SXin LI } 389*1fdeb165SXin LI 390*1fdeb165SXin LI static void hpt_do_tasks(PVBUS_EXT vbus_ext, int pending) 391*1fdeb165SXin LI { 392*1fdeb165SXin LI if(vbus_ext){ 393*1fdeb165SXin LI hpt_lock_vbus(vbus_ext); 394*1fdeb165SXin LI __hpt_do_tasks(vbus_ext); 395*1fdeb165SXin LI hpt_unlock_vbus(vbus_ext); 396*1fdeb165SXin LI } 397*1fdeb165SXin LI } 398*1fdeb165SXin LI 399*1fdeb165SXin LI static void hpt_action(struct cam_sim *sim, union ccb *ccb); 400*1fdeb165SXin LI static void hpt_poll(struct cam_sim *sim); 401*1fdeb165SXin LI static void hpt_async(void * callback_arg, u_int32_t code, struct cam_path * path, void * arg); 402*1fdeb165SXin LI static void hpt_pci_intr(void *arg); 403*1fdeb165SXin LI 404*1fdeb165SXin LI static __inline POS_CMDEXT cmdext_get(PVBUS_EXT vbus_ext) 405*1fdeb165SXin LI { 406*1fdeb165SXin LI POS_CMDEXT p = vbus_ext->cmdext_list; 407*1fdeb165SXin LI if (p) 408*1fdeb165SXin LI vbus_ext->cmdext_list = p->next; 409*1fdeb165SXin LI return p; 410*1fdeb165SXin LI } 411*1fdeb165SXin LI 412*1fdeb165SXin LI static __inline void cmdext_put(POS_CMDEXT p) 413*1fdeb165SXin LI { 414*1fdeb165SXin LI p->next = p->vbus_ext->cmdext_list; 415*1fdeb165SXin LI p->vbus_ext->cmdext_list = p; 416*1fdeb165SXin LI } 417*1fdeb165SXin LI 418*1fdeb165SXin LI static void hpt_timeout(void *arg) 419*1fdeb165SXin LI { 420*1fdeb165SXin LI PCOMMAND pCmd = (PCOMMAND)arg; 421*1fdeb165SXin LI POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv; 422*1fdeb165SXin LI 423*1fdeb165SXin LI KdPrint(("pCmd %p timeout", pCmd)); 424*1fdeb165SXin LI 425*1fdeb165SXin LI ldm_reset_vbus((PVBUS)ext->vbus_ext->vbus); 426*1fdeb165SXin LI } 427*1fdeb165SXin LI 428*1fdeb165SXin LI static void os_cmddone(PCOMMAND pCmd) 429*1fdeb165SXin LI { 430*1fdeb165SXin LI POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv; 431*1fdeb165SXin LI union ccb *ccb = ext->ccb; 432*1fdeb165SXin LI 433*1fdeb165SXin LI KdPrint(("os_cmddone(%p, %d)", pCmd, pCmd->Result)); 434*1fdeb165SXin LI 435*1fdeb165SXin LI untimeout(hpt_timeout, pCmd, ccb->ccb_h.timeout_ch); 436*1fdeb165SXin LI 437*1fdeb165SXin LI switch(pCmd->Result) { 438*1fdeb165SXin LI case RETURN_SUCCESS: 439*1fdeb165SXin LI ccb->ccb_h.status = CAM_REQ_CMP; 440*1fdeb165SXin LI break; 441*1fdeb165SXin LI case RETURN_BAD_DEVICE: 442*1fdeb165SXin LI ccb->ccb_h.status = CAM_DEV_NOT_THERE; 443*1fdeb165SXin LI break; 444*1fdeb165SXin LI case RETURN_DEVICE_BUSY: 445*1fdeb165SXin LI ccb->ccb_h.status = CAM_BUSY; 446*1fdeb165SXin LI break; 447*1fdeb165SXin LI case RETURN_INVALID_REQUEST: 448*1fdeb165SXin LI ccb->ccb_h.status = CAM_REQ_INVALID; 449*1fdeb165SXin LI break; 450*1fdeb165SXin LI case RETURN_SELECTION_TIMEOUT: 451*1fdeb165SXin LI ccb->ccb_h.status = CAM_SEL_TIMEOUT; 452*1fdeb165SXin LI break; 453*1fdeb165SXin LI case RETURN_RETRY: 454*1fdeb165SXin LI ccb->ccb_h.status = CAM_BUSY; 455*1fdeb165SXin LI break; 456*1fdeb165SXin LI default: 457*1fdeb165SXin LI ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 458*1fdeb165SXin LI break; 459*1fdeb165SXin LI } 460*1fdeb165SXin LI 461*1fdeb165SXin LI if (pCmd->flags.data_in) { 462*1fdeb165SXin LI bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, BUS_DMASYNC_POSTREAD); 463*1fdeb165SXin LI } 464*1fdeb165SXin LI else if (pCmd->flags.data_out) { 465*1fdeb165SXin LI bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, BUS_DMASYNC_POSTWRITE); 466*1fdeb165SXin LI } 467*1fdeb165SXin LI 468*1fdeb165SXin LI bus_dmamap_unload(ext->vbus_ext->io_dmat, ext->dma_map); 469*1fdeb165SXin LI 470*1fdeb165SXin LI cmdext_put(ext); 471*1fdeb165SXin LI ldm_free_cmds(pCmd); 472*1fdeb165SXin LI xpt_done(ccb); 473*1fdeb165SXin LI } 474*1fdeb165SXin LI 475*1fdeb165SXin LI static int os_buildsgl(PCOMMAND pCmd, PSG pSg, int logical) 476*1fdeb165SXin LI { 477*1fdeb165SXin LI /* since we have provided physical sg, nobody will ask us to build physical sg */ 478*1fdeb165SXin LI HPT_ASSERT(0); 479*1fdeb165SXin LI return FALSE; 480*1fdeb165SXin LI } 481*1fdeb165SXin LI 482*1fdeb165SXin LI static void hpt_io_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 483*1fdeb165SXin LI { 484*1fdeb165SXin LI PCOMMAND pCmd = (PCOMMAND)arg; 485*1fdeb165SXin LI POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv; 486*1fdeb165SXin LI PSG psg = pCmd->psg; 487*1fdeb165SXin LI int idx; 488*1fdeb165SXin LI 489*1fdeb165SXin LI HPT_ASSERT(pCmd->flags.physical_sg); 490*1fdeb165SXin LI 491*1fdeb165SXin LI if (error) 492*1fdeb165SXin LI panic("busdma error"); 493*1fdeb165SXin LI 494*1fdeb165SXin LI HPT_ASSERT(nsegs<=os_max_sg_descriptors); 495*1fdeb165SXin LI 496*1fdeb165SXin LI if (nsegs != 0) { 497*1fdeb165SXin LI for (idx = 0; idx < nsegs; idx++, psg++) { 498*1fdeb165SXin LI psg->addr.bus = segs[idx].ds_addr; 499*1fdeb165SXin LI psg->size = segs[idx].ds_len; 500*1fdeb165SXin LI psg->eot = 0; 501*1fdeb165SXin LI } 502*1fdeb165SXin LI psg[-1].eot = 1; 503*1fdeb165SXin LI 504*1fdeb165SXin LI if (pCmd->flags.data_in) { 505*1fdeb165SXin LI bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, 506*1fdeb165SXin LI BUS_DMASYNC_PREREAD); 507*1fdeb165SXin LI } 508*1fdeb165SXin LI else if (pCmd->flags.data_out) { 509*1fdeb165SXin LI bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, 510*1fdeb165SXin LI BUS_DMASYNC_PREWRITE); 511*1fdeb165SXin LI } 512*1fdeb165SXin LI } 513*1fdeb165SXin LI 514*1fdeb165SXin LI ext->ccb->ccb_h.timeout_ch = timeout(hpt_timeout, pCmd, HPT_OSM_TIMEOUT); 515*1fdeb165SXin LI ldm_queue_cmd(pCmd); 516*1fdeb165SXin LI } 517*1fdeb165SXin LI 518*1fdeb165SXin LI static void hpt_scsi_io(PVBUS_EXT vbus_ext, union ccb *ccb) 519*1fdeb165SXin LI { 520*1fdeb165SXin LI PVBUS vbus = (PVBUS)vbus_ext->vbus; 521*1fdeb165SXin LI PVDEV vd; 522*1fdeb165SXin LI PCOMMAND pCmd; 523*1fdeb165SXin LI POS_CMDEXT ext; 524*1fdeb165SXin LI HPT_U8 *cdb; 525*1fdeb165SXin LI 526*1fdeb165SXin LI if (ccb->ccb_h.flags & CAM_CDB_POINTER) 527*1fdeb165SXin LI cdb = ccb->csio.cdb_io.cdb_ptr; 528*1fdeb165SXin LI else 529*1fdeb165SXin LI cdb = ccb->csio.cdb_io.cdb_bytes; 530*1fdeb165SXin LI 531*1fdeb165SXin LI KdPrint(("hpt_scsi_io: ccb %x id %d lun %d cdb %x-%x-%x", 532*1fdeb165SXin LI ccb, 533*1fdeb165SXin LI ccb->ccb_h.target_id, ccb->ccb_h.target_lun, 534*1fdeb165SXin LI *(HPT_U32 *)&cdb[0], *(HPT_U32 *)&cdb[4], *(HPT_U32 *)&cdb[8] 535*1fdeb165SXin LI )); 536*1fdeb165SXin LI 537*1fdeb165SXin LI /* ccb->ccb_h.path_id is not our bus id - don't check it */ 538*1fdeb165SXin LI if (ccb->ccb_h.target_lun != 0 || 539*1fdeb165SXin LI ccb->ccb_h.target_id >= osm_max_targets || 540*1fdeb165SXin LI (ccb->ccb_h.flags & CAM_CDB_PHYS)) 541*1fdeb165SXin LI { 542*1fdeb165SXin LI ccb->ccb_h.status = CAM_TID_INVALID; 543*1fdeb165SXin LI xpt_done(ccb); 544*1fdeb165SXin LI return; 545*1fdeb165SXin LI } 546*1fdeb165SXin LI 547*1fdeb165SXin LI vd = ldm_find_target(vbus, ccb->ccb_h.target_id); 548*1fdeb165SXin LI 549*1fdeb165SXin LI if (!vd) { 550*1fdeb165SXin LI ccb->ccb_h.status = CAM_TID_INVALID; 551*1fdeb165SXin LI xpt_done(ccb); 552*1fdeb165SXin LI return; 553*1fdeb165SXin LI } 554*1fdeb165SXin LI 555*1fdeb165SXin LI switch (cdb[0]) { 556*1fdeb165SXin LI case TEST_UNIT_READY: 557*1fdeb165SXin LI case START_STOP_UNIT: 558*1fdeb165SXin LI case SYNCHRONIZE_CACHE: 559*1fdeb165SXin LI ccb->ccb_h.status = CAM_REQ_CMP; 560*1fdeb165SXin LI break; 561*1fdeb165SXin LI 562*1fdeb165SXin LI case INQUIRY: 563*1fdeb165SXin LI { 564*1fdeb165SXin LI PINQUIRYDATA inquiryData; 565*1fdeb165SXin LI memset(ccb->csio.data_ptr, 0, ccb->csio.dxfer_len); 566*1fdeb165SXin LI inquiryData = (PINQUIRYDATA)ccb->csio.data_ptr; 567*1fdeb165SXin LI 568*1fdeb165SXin LI inquiryData->AdditionalLength = 31; 569*1fdeb165SXin LI inquiryData->CommandQueue = 1; 570*1fdeb165SXin LI memcpy(&inquiryData->VendorId, "HPT ", 8); 571*1fdeb165SXin LI memcpy(&inquiryData->ProductId, "DISK 0_0 ", 16); 572*1fdeb165SXin LI 573*1fdeb165SXin LI if (vd->target_id / 10) { 574*1fdeb165SXin LI inquiryData->ProductId[7] = (vd->target_id % 100) / 10 + '0'; 575*1fdeb165SXin LI inquiryData->ProductId[8] = (vd->target_id % 100) % 10 + '0'; 576*1fdeb165SXin LI } 577*1fdeb165SXin LI else 578*1fdeb165SXin LI inquiryData->ProductId[7] = (vd->target_id % 100) % 10 + '0'; 579*1fdeb165SXin LI 580*1fdeb165SXin LI memcpy(&inquiryData->ProductRevisionLevel, "4.00", 4); 581*1fdeb165SXin LI 582*1fdeb165SXin LI ccb->ccb_h.status = CAM_REQ_CMP; 583*1fdeb165SXin LI } 584*1fdeb165SXin LI break; 585*1fdeb165SXin LI 586*1fdeb165SXin LI case READ_CAPACITY: 587*1fdeb165SXin LI { 588*1fdeb165SXin LI HPT_U8 *rbuf = ccb->csio.data_ptr; 589*1fdeb165SXin LI HPT_U32 cap; 590*1fdeb165SXin LI 591*1fdeb165SXin LI if (vd->capacity>0xfffffffful) 592*1fdeb165SXin LI cap = 0xfffffffful; 593*1fdeb165SXin LI else 594*1fdeb165SXin LI cap = vd->capacity - 1; 595*1fdeb165SXin LI 596*1fdeb165SXin LI rbuf[0] = (HPT_U8)(cap>>24); 597*1fdeb165SXin LI rbuf[1] = (HPT_U8)(cap>>16); 598*1fdeb165SXin LI rbuf[2] = (HPT_U8)(cap>>8); 599*1fdeb165SXin LI rbuf[3] = (HPT_U8)cap; 600*1fdeb165SXin LI rbuf[4] = 0; 601*1fdeb165SXin LI rbuf[5] = 0; 602*1fdeb165SXin LI rbuf[6] = 2; 603*1fdeb165SXin LI rbuf[7] = 0; 604*1fdeb165SXin LI 605*1fdeb165SXin LI ccb->ccb_h.status = CAM_REQ_CMP; 606*1fdeb165SXin LI break; 607*1fdeb165SXin LI } 608*1fdeb165SXin LI 609*1fdeb165SXin LI case SERVICE_ACTION_IN: 610*1fdeb165SXin LI { 611*1fdeb165SXin LI HPT_U8 *rbuf = ccb->csio.data_ptr; 612*1fdeb165SXin LI HPT_U64 cap = vd->capacity - 1; 613*1fdeb165SXin LI 614*1fdeb165SXin LI rbuf[0] = (HPT_U8)(cap>>56); 615*1fdeb165SXin LI rbuf[1] = (HPT_U8)(cap>>48); 616*1fdeb165SXin LI rbuf[2] = (HPT_U8)(cap>>40); 617*1fdeb165SXin LI rbuf[3] = (HPT_U8)(cap>>32); 618*1fdeb165SXin LI rbuf[4] = (HPT_U8)(cap>>24); 619*1fdeb165SXin LI rbuf[5] = (HPT_U8)(cap>>16); 620*1fdeb165SXin LI rbuf[6] = (HPT_U8)(cap>>8); 621*1fdeb165SXin LI rbuf[7] = (HPT_U8)cap; 622*1fdeb165SXin LI rbuf[8] = 0; 623*1fdeb165SXin LI rbuf[9] = 0; 624*1fdeb165SXin LI rbuf[10] = 2; 625*1fdeb165SXin LI rbuf[11] = 0; 626*1fdeb165SXin LI 627*1fdeb165SXin LI ccb->ccb_h.status = CAM_REQ_CMP; 628*1fdeb165SXin LI break; 629*1fdeb165SXin LI } 630*1fdeb165SXin LI 631*1fdeb165SXin LI case READ_6: 632*1fdeb165SXin LI case READ_10: 633*1fdeb165SXin LI case READ_16: 634*1fdeb165SXin LI case WRITE_6: 635*1fdeb165SXin LI case WRITE_10: 636*1fdeb165SXin LI case WRITE_16: 637*1fdeb165SXin LI case 0x13: 638*1fdeb165SXin LI case 0x2f: 639*1fdeb165SXin LI case 0x8f: /* VERIFY_16 */ 640*1fdeb165SXin LI { 641*1fdeb165SXin LI int error; 642*1fdeb165SXin LI pCmd = ldm_alloc_cmds(vbus, vd->cmds_per_request); 643*1fdeb165SXin LI if(!pCmd){ 644*1fdeb165SXin LI KdPrint(("Failed to allocate command!")); 645*1fdeb165SXin LI ccb->ccb_h.status = CAM_BUSY; 646*1fdeb165SXin LI break; 647*1fdeb165SXin LI } 648*1fdeb165SXin LI 649*1fdeb165SXin LI switch (cdb[0]) { 650*1fdeb165SXin LI case READ_6: 651*1fdeb165SXin LI case WRITE_6: 652*1fdeb165SXin LI case 0x13: 653*1fdeb165SXin LI pCmd->uCmd.Ide.Lba = ((HPT_U32)cdb[1] << 16) | ((HPT_U32)cdb[2] << 8) | (HPT_U32)cdb[3]; 654*1fdeb165SXin LI pCmd->uCmd.Ide.nSectors = (HPT_U16) cdb[4]; 655*1fdeb165SXin LI break; 656*1fdeb165SXin LI case READ_16: 657*1fdeb165SXin LI case WRITE_16: 658*1fdeb165SXin LI case 0x8f: /* VERIFY_16 */ 659*1fdeb165SXin LI { 660*1fdeb165SXin LI HPT_U64 block = 661*1fdeb165SXin LI ((HPT_U64)cdb[2]<<56) | 662*1fdeb165SXin LI ((HPT_U64)cdb[3]<<48) | 663*1fdeb165SXin LI ((HPT_U64)cdb[4]<<40) | 664*1fdeb165SXin LI ((HPT_U64)cdb[5]<<32) | 665*1fdeb165SXin LI ((HPT_U64)cdb[6]<<24) | 666*1fdeb165SXin LI ((HPT_U64)cdb[7]<<16) | 667*1fdeb165SXin LI ((HPT_U64)cdb[8]<<8) | 668*1fdeb165SXin LI ((HPT_U64)cdb[9]); 669*1fdeb165SXin LI pCmd->uCmd.Ide.Lba = block; 670*1fdeb165SXin LI pCmd->uCmd.Ide.nSectors = (HPT_U16)cdb[13] | ((HPT_U16)cdb[12]<<8); 671*1fdeb165SXin LI break; 672*1fdeb165SXin LI } 673*1fdeb165SXin LI 674*1fdeb165SXin LI default: 675*1fdeb165SXin LI pCmd->uCmd.Ide.Lba = (HPT_U32)cdb[5] | ((HPT_U32)cdb[4] << 8) | ((HPT_U32)cdb[3] << 16) | ((HPT_U32)cdb[2] << 24); 676*1fdeb165SXin LI pCmd->uCmd.Ide.nSectors = (HPT_U16) cdb[8] | ((HPT_U16)cdb[7]<<8); 677*1fdeb165SXin LI break; 678*1fdeb165SXin LI } 679*1fdeb165SXin LI 680*1fdeb165SXin LI switch (cdb[0]) { 681*1fdeb165SXin LI case READ_6: 682*1fdeb165SXin LI case READ_10: 683*1fdeb165SXin LI case READ_16: 684*1fdeb165SXin LI pCmd->flags.data_in = 1; 685*1fdeb165SXin LI break; 686*1fdeb165SXin LI case WRITE_6: 687*1fdeb165SXin LI case WRITE_10: 688*1fdeb165SXin LI case WRITE_16: 689*1fdeb165SXin LI pCmd->flags.data_out = 1; 690*1fdeb165SXin LI break; 691*1fdeb165SXin LI } 692*1fdeb165SXin LI pCmd->priv = ext = cmdext_get(vbus_ext); 693*1fdeb165SXin LI HPT_ASSERT(ext); 694*1fdeb165SXin LI ext->ccb = ccb; 695*1fdeb165SXin LI pCmd->target = vd; 696*1fdeb165SXin LI pCmd->done = os_cmddone; 697*1fdeb165SXin LI pCmd->buildsgl = os_buildsgl; 698*1fdeb165SXin LI pCmd->psg = ext->psg; 699*1fdeb165SXin LI pCmd->flags.physical_sg = 1; 700*1fdeb165SXin LI error = bus_dmamap_load_ccb(vbus_ext->io_dmat, 701*1fdeb165SXin LI ext->dma_map, ccb, 702*1fdeb165SXin LI hpt_io_dmamap_callback, pCmd, 703*1fdeb165SXin LI BUS_DMA_WAITOK 704*1fdeb165SXin LI ); 705*1fdeb165SXin LI KdPrint(("bus_dmamap_load return %d", error)); 706*1fdeb165SXin LI if (error && error!=EINPROGRESS) { 707*1fdeb165SXin LI os_printk("bus_dmamap_load error %d", error); 708*1fdeb165SXin LI cmdext_put(ext); 709*1fdeb165SXin LI ldm_free_cmds(pCmd); 710*1fdeb165SXin LI ccb->ccb_h.status = CAM_REQ_CMP_ERR; 711*1fdeb165SXin LI xpt_done(ccb); 712*1fdeb165SXin LI } 713*1fdeb165SXin LI return; 714*1fdeb165SXin LI } 715*1fdeb165SXin LI 716*1fdeb165SXin LI default: 717*1fdeb165SXin LI ccb->ccb_h.status = CAM_REQ_INVALID; 718*1fdeb165SXin LI break; 719*1fdeb165SXin LI } 720*1fdeb165SXin LI 721*1fdeb165SXin LI xpt_done(ccb); 722*1fdeb165SXin LI return; 723*1fdeb165SXin LI } 724*1fdeb165SXin LI 725*1fdeb165SXin LI static void hpt_action(struct cam_sim *sim, union ccb *ccb) 726*1fdeb165SXin LI { 727*1fdeb165SXin LI PVBUS_EXT vbus_ext = (PVBUS_EXT)cam_sim_softc(sim); 728*1fdeb165SXin LI 729*1fdeb165SXin LI KdPrint(("hpt_action(fn=%d, id=%d)", ccb->ccb_h.func_code, ccb->ccb_h.target_id)); 730*1fdeb165SXin LI 731*1fdeb165SXin LI switch (ccb->ccb_h.func_code) { 732*1fdeb165SXin LI 733*1fdeb165SXin LI case XPT_SCSI_IO: 734*1fdeb165SXin LI hpt_lock_vbus(vbus_ext); 735*1fdeb165SXin LI hpt_scsi_io(vbus_ext, ccb); 736*1fdeb165SXin LI hpt_unlock_vbus(vbus_ext); 737*1fdeb165SXin LI return; 738*1fdeb165SXin LI 739*1fdeb165SXin LI case XPT_RESET_BUS: 740*1fdeb165SXin LI hpt_lock_vbus(vbus_ext); 741*1fdeb165SXin LI ldm_reset_vbus((PVBUS)vbus_ext->vbus); 742*1fdeb165SXin LI hpt_unlock_vbus(vbus_ext); 743*1fdeb165SXin LI break; 744*1fdeb165SXin LI 745*1fdeb165SXin LI case XPT_GET_TRAN_SETTINGS: 746*1fdeb165SXin LI case XPT_SET_TRAN_SETTINGS: 747*1fdeb165SXin LI ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 748*1fdeb165SXin LI break; 749*1fdeb165SXin LI 750*1fdeb165SXin LI case XPT_CALC_GEOMETRY: 751*1fdeb165SXin LI ccb->ccg.heads = 255; 752*1fdeb165SXin LI ccb->ccg.secs_per_track = 63; 753*1fdeb165SXin LI ccb->ccg.cylinders = ccb->ccg.volume_size / (ccb->ccg.heads * ccb->ccg.secs_per_track); 754*1fdeb165SXin LI ccb->ccb_h.status = CAM_REQ_CMP; 755*1fdeb165SXin LI break; 756*1fdeb165SXin LI 757*1fdeb165SXin LI case XPT_PATH_INQ: 758*1fdeb165SXin LI { 759*1fdeb165SXin LI struct ccb_pathinq *cpi = &ccb->cpi; 760*1fdeb165SXin LI 761*1fdeb165SXin LI cpi->version_num = 1; 762*1fdeb165SXin LI cpi->hba_inquiry = PI_SDTR_ABLE; 763*1fdeb165SXin LI cpi->target_sprt = 0; 764*1fdeb165SXin LI cpi->hba_misc = PIM_NOBUSRESET; 765*1fdeb165SXin LI cpi->hba_eng_cnt = 0; 766*1fdeb165SXin LI cpi->max_target = osm_max_targets; 767*1fdeb165SXin LI cpi->max_lun = 0; 768*1fdeb165SXin LI cpi->unit_number = cam_sim_unit(sim); 769*1fdeb165SXin LI cpi->bus_id = cam_sim_bus(sim); 770*1fdeb165SXin LI cpi->initiator_id = osm_max_targets; 771*1fdeb165SXin LI cpi->base_transfer_speed = 3300; 772*1fdeb165SXin LI 773*1fdeb165SXin LI strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 774*1fdeb165SXin LI strncpy(cpi->hba_vid, "HPT ", HBA_IDLEN); 775*1fdeb165SXin LI strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 776*1fdeb165SXin LI #if (__FreeBSD_version >= 800000) 777*1fdeb165SXin LI cpi->transport = XPORT_SPI; 778*1fdeb165SXin LI cpi->transport_version = 2; 779*1fdeb165SXin LI cpi->protocol = PROTO_SCSI; 780*1fdeb165SXin LI cpi->protocol_version = SCSI_REV_2; 781*1fdeb165SXin LI #endif 782*1fdeb165SXin LI cpi->ccb_h.status = CAM_REQ_CMP; 783*1fdeb165SXin LI break; 784*1fdeb165SXin LI } 785*1fdeb165SXin LI 786*1fdeb165SXin LI default: 787*1fdeb165SXin LI ccb->ccb_h.status = CAM_REQ_INVALID; 788*1fdeb165SXin LI break; 789*1fdeb165SXin LI } 790*1fdeb165SXin LI 791*1fdeb165SXin LI xpt_done(ccb); 792*1fdeb165SXin LI return; 793*1fdeb165SXin LI } 794*1fdeb165SXin LI 795*1fdeb165SXin LI static void hpt_pci_intr(void *arg) 796*1fdeb165SXin LI { 797*1fdeb165SXin LI PVBUS_EXT vbus_ext = (PVBUS_EXT)arg; 798*1fdeb165SXin LI hpt_lock_vbus(vbus_ext); 799*1fdeb165SXin LI ldm_intr((PVBUS)vbus_ext->vbus); 800*1fdeb165SXin LI hpt_unlock_vbus(vbus_ext); 801*1fdeb165SXin LI } 802*1fdeb165SXin LI 803*1fdeb165SXin LI static void hpt_poll(struct cam_sim *sim) 804*1fdeb165SXin LI { 805*1fdeb165SXin LI hpt_pci_intr(cam_sim_softc(sim)); 806*1fdeb165SXin LI } 807*1fdeb165SXin LI 808*1fdeb165SXin LI static void hpt_async(void * callback_arg, u_int32_t code, struct cam_path * path, void * arg) 809*1fdeb165SXin LI { 810*1fdeb165SXin LI KdPrint(("hpt_async")); 811*1fdeb165SXin LI } 812*1fdeb165SXin LI 813*1fdeb165SXin LI static int hpt_shutdown(device_t dev) 814*1fdeb165SXin LI { 815*1fdeb165SXin LI KdPrint(("hpt_shutdown(dev=%p)", dev)); 816*1fdeb165SXin LI return 0; 817*1fdeb165SXin LI } 818*1fdeb165SXin LI 819*1fdeb165SXin LI static int hpt_detach(device_t dev) 820*1fdeb165SXin LI { 821*1fdeb165SXin LI /* we don't allow the driver to be unloaded. */ 822*1fdeb165SXin LI return EBUSY; 823*1fdeb165SXin LI } 824*1fdeb165SXin LI 825*1fdeb165SXin LI static void hpt_ioctl_done(struct _IOCTL_ARG *arg) 826*1fdeb165SXin LI { 827*1fdeb165SXin LI arg->ioctl_cmnd = 0; 828*1fdeb165SXin LI wakeup(arg); 829*1fdeb165SXin LI } 830*1fdeb165SXin LI 831*1fdeb165SXin LI static void __hpt_do_ioctl(PVBUS_EXT vbus_ext, IOCTL_ARG *ioctl_args) 832*1fdeb165SXin LI { 833*1fdeb165SXin LI ioctl_args->result = -1; 834*1fdeb165SXin LI ioctl_args->done = hpt_ioctl_done; 835*1fdeb165SXin LI ioctl_args->ioctl_cmnd = (void *)1; 836*1fdeb165SXin LI 837*1fdeb165SXin LI hpt_lock_vbus(vbus_ext); 838*1fdeb165SXin LI ldm_ioctl((PVBUS)vbus_ext->vbus, ioctl_args); 839*1fdeb165SXin LI 840*1fdeb165SXin LI while (ioctl_args->ioctl_cmnd) { 841*1fdeb165SXin LI if (hpt_sleep(vbus_ext, ioctl_args, PPAUSE, "hptctl", HPT_OSM_TIMEOUT)==0) 842*1fdeb165SXin LI break; 843*1fdeb165SXin LI ldm_reset_vbus((PVBUS)vbus_ext->vbus); 844*1fdeb165SXin LI __hpt_do_tasks(vbus_ext); 845*1fdeb165SXin LI } 846*1fdeb165SXin LI 847*1fdeb165SXin LI /* KdPrint(("ioctl %x result %d", ioctl_args->dwIoControlCode, ioctl_args->result)); */ 848*1fdeb165SXin LI 849*1fdeb165SXin LI hpt_unlock_vbus(vbus_ext); 850*1fdeb165SXin LI } 851*1fdeb165SXin LI 852*1fdeb165SXin LI static void hpt_do_ioctl(IOCTL_ARG *ioctl_args) 853*1fdeb165SXin LI { 854*1fdeb165SXin LI PVBUS vbus; 855*1fdeb165SXin LI PVBUS_EXT vbus_ext; 856*1fdeb165SXin LI 857*1fdeb165SXin LI ldm_for_each_vbus(vbus, vbus_ext) { 858*1fdeb165SXin LI __hpt_do_ioctl(vbus_ext, ioctl_args); 859*1fdeb165SXin LI if (ioctl_args->result!=HPT_IOCTL_RESULT_WRONG_VBUS) 860*1fdeb165SXin LI return; 861*1fdeb165SXin LI } 862*1fdeb165SXin LI } 863*1fdeb165SXin LI 864*1fdeb165SXin LI #define HPT_DO_IOCTL(code, inbuf, insize, outbuf, outsize) ({\ 865*1fdeb165SXin LI IOCTL_ARG arg;\ 866*1fdeb165SXin LI arg.dwIoControlCode = code;\ 867*1fdeb165SXin LI arg.lpInBuffer = inbuf;\ 868*1fdeb165SXin LI arg.lpOutBuffer = outbuf;\ 869*1fdeb165SXin LI arg.nInBufferSize = insize;\ 870*1fdeb165SXin LI arg.nOutBufferSize = outsize;\ 871*1fdeb165SXin LI arg.lpBytesReturned = 0;\ 872*1fdeb165SXin LI hpt_do_ioctl(&arg);\ 873*1fdeb165SXin LI arg.result;\ 874*1fdeb165SXin LI }) 875*1fdeb165SXin LI 876*1fdeb165SXin LI #define DEVICEID_VALID(id) ((id) && ((HPT_U32)(id)!=0xffffffff)) 877*1fdeb165SXin LI 878*1fdeb165SXin LI static int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount) 879*1fdeb165SXin LI { 880*1fdeb165SXin LI int i; 881*1fdeb165SXin LI HPT_U32 count = nMaxCount-1; 882*1fdeb165SXin LI 883*1fdeb165SXin LI if (HPT_DO_IOCTL(HPT_IOCTL_GET_LOGICAL_DEVICES, 884*1fdeb165SXin LI &count, sizeof(HPT_U32), pIds, sizeof(DEVICEID)*nMaxCount)) 885*1fdeb165SXin LI return -1; 886*1fdeb165SXin LI 887*1fdeb165SXin LI nMaxCount = (int)pIds[0]; 888*1fdeb165SXin LI for (i=0; i<nMaxCount; i++) pIds[i] = pIds[i+1]; 889*1fdeb165SXin LI return nMaxCount; 890*1fdeb165SXin LI } 891*1fdeb165SXin LI 892*1fdeb165SXin LI static int hpt_get_device_info_v3(DEVICEID id, PLOGICAL_DEVICE_INFO_V3 pInfo) 893*1fdeb165SXin LI { 894*1fdeb165SXin LI return HPT_DO_IOCTL(HPT_IOCTL_GET_DEVICE_INFO_V3, 895*1fdeb165SXin LI &id, sizeof(DEVICEID), pInfo, sizeof(LOGICAL_DEVICE_INFO_V3)); 896*1fdeb165SXin LI } 897*1fdeb165SXin LI 898*1fdeb165SXin LI /* not belong to this file logically, but we want to use ioctl interface */ 899*1fdeb165SXin LI static int __hpt_stop_tasks(PVBUS_EXT vbus_ext, DEVICEID id) 900*1fdeb165SXin LI { 901*1fdeb165SXin LI LOGICAL_DEVICE_INFO_V3 devinfo; 902*1fdeb165SXin LI int i, result; 903*1fdeb165SXin LI DEVICEID param[2] = { id, 0 }; 904*1fdeb165SXin LI 905*1fdeb165SXin LI if (hpt_get_device_info_v3(id, &devinfo)) 906*1fdeb165SXin LI return -1; 907*1fdeb165SXin LI 908*1fdeb165SXin LI if (devinfo.Type!=LDT_ARRAY) 909*1fdeb165SXin LI return -1; 910*1fdeb165SXin LI 911*1fdeb165SXin LI if (devinfo.u.array.Flags & ARRAY_FLAG_REBUILDING) 912*1fdeb165SXin LI param[1] = AS_REBUILD_ABORT; 913*1fdeb165SXin LI else if (devinfo.u.array.Flags & ARRAY_FLAG_VERIFYING) 914*1fdeb165SXin LI param[1] = AS_VERIFY_ABORT; 915*1fdeb165SXin LI else if (devinfo.u.array.Flags & ARRAY_FLAG_INITIALIZING) 916*1fdeb165SXin LI param[1] = AS_INITIALIZE_ABORT; 917*1fdeb165SXin LI else if (devinfo.u.array.Flags & ARRAY_FLAG_TRANSFORMING) 918*1fdeb165SXin LI param[1] = AS_TRANSFORM_ABORT; 919*1fdeb165SXin LI else 920*1fdeb165SXin LI return -1; 921*1fdeb165SXin LI 922*1fdeb165SXin LI KdPrint(("SET_ARRAY_STATE(%x, %d)", param[0], param[1])); 923*1fdeb165SXin LI result = HPT_DO_IOCTL(HPT_IOCTL_SET_ARRAY_STATE, 924*1fdeb165SXin LI param, sizeof(param), 0, 0); 925*1fdeb165SXin LI 926*1fdeb165SXin LI for (i=0; i<devinfo.u.array.nDisk; i++) 927*1fdeb165SXin LI if (DEVICEID_VALID(devinfo.u.array.Members[i])) 928*1fdeb165SXin LI __hpt_stop_tasks(vbus_ext, devinfo.u.array.Members[i]); 929*1fdeb165SXin LI 930*1fdeb165SXin LI return result; 931*1fdeb165SXin LI } 932*1fdeb165SXin LI 933*1fdeb165SXin LI static void hpt_stop_tasks(PVBUS_EXT vbus_ext) 934*1fdeb165SXin LI { 935*1fdeb165SXin LI DEVICEID ids[32]; 936*1fdeb165SXin LI int i, count; 937*1fdeb165SXin LI 938*1fdeb165SXin LI count = hpt_get_logical_devices((DEVICEID *)&ids, sizeof(ids)/sizeof(ids[0])); 939*1fdeb165SXin LI 940*1fdeb165SXin LI for (i=0; i<count; i++) 941*1fdeb165SXin LI __hpt_stop_tasks(vbus_ext, ids[i]); 942*1fdeb165SXin LI } 943*1fdeb165SXin LI 944*1fdeb165SXin LI static d_open_t hpt_open; 945*1fdeb165SXin LI static d_close_t hpt_close; 946*1fdeb165SXin LI static d_ioctl_t hpt_ioctl; 947*1fdeb165SXin LI static int hpt_rescan_bus(void); 948*1fdeb165SXin LI 949*1fdeb165SXin LI static struct cdevsw hpt_cdevsw = { 950*1fdeb165SXin LI .d_open = hpt_open, 951*1fdeb165SXin LI .d_close = hpt_close, 952*1fdeb165SXin LI .d_ioctl = hpt_ioctl, 953*1fdeb165SXin LI .d_name = driver_name, 954*1fdeb165SXin LI #if __FreeBSD_version>=503000 955*1fdeb165SXin LI .d_version = D_VERSION, 956*1fdeb165SXin LI #endif 957*1fdeb165SXin LI #if (__FreeBSD_version>=503000 && __FreeBSD_version<600034) 958*1fdeb165SXin LI .d_flags = D_NEEDGIANT, 959*1fdeb165SXin LI #endif 960*1fdeb165SXin LI #if __FreeBSD_version<600034 961*1fdeb165SXin LI #if __FreeBSD_version>501000 962*1fdeb165SXin LI .d_maj = MAJOR_AUTO, 963*1fdeb165SXin LI #else 964*1fdeb165SXin LI .d_maj = HPT_DEV_MAJOR, 965*1fdeb165SXin LI #endif 966*1fdeb165SXin LI #endif 967*1fdeb165SXin LI }; 968*1fdeb165SXin LI 969*1fdeb165SXin LI static struct intr_config_hook hpt_ich; 970*1fdeb165SXin LI 971*1fdeb165SXin LI /* 972*1fdeb165SXin LI * hpt_final_init will be called after all hpt_attach. 973*1fdeb165SXin LI */ 974*1fdeb165SXin LI static void hpt_final_init(void *dummy) 975*1fdeb165SXin LI { 976*1fdeb165SXin LI int i,unit_number=0; 977*1fdeb165SXin LI PVBUS_EXT vbus_ext; 978*1fdeb165SXin LI PVBUS vbus; 979*1fdeb165SXin LI PHBA hba; 980*1fdeb165SXin LI 981*1fdeb165SXin LI /* Clear the config hook */ 982*1fdeb165SXin LI config_intrhook_disestablish(&hpt_ich); 983*1fdeb165SXin LI 984*1fdeb165SXin LI /* allocate memory */ 985*1fdeb165SXin LI i = 0; 986*1fdeb165SXin LI ldm_for_each_vbus(vbus, vbus_ext) { 987*1fdeb165SXin LI if (hpt_alloc_mem(vbus_ext)) { 988*1fdeb165SXin LI os_printk("out of memory"); 989*1fdeb165SXin LI return; 990*1fdeb165SXin LI } 991*1fdeb165SXin LI i++; 992*1fdeb165SXin LI } 993*1fdeb165SXin LI 994*1fdeb165SXin LI if (!i) { 995*1fdeb165SXin LI if (bootverbose) 996*1fdeb165SXin LI os_printk("no controller detected."); 997*1fdeb165SXin LI return; 998*1fdeb165SXin LI } 999*1fdeb165SXin LI 1000*1fdeb165SXin LI /* initializing hardware */ 1001*1fdeb165SXin LI ldm_for_each_vbus(vbus, vbus_ext) { 1002*1fdeb165SXin LI /* make timer available here */ 1003*1fdeb165SXin LI callout_handle_init(&vbus_ext->timer); 1004*1fdeb165SXin LI if (hpt_init_vbus(vbus_ext)) { 1005*1fdeb165SXin LI os_printk("fail to initialize hardware"); 1006*1fdeb165SXin LI break; /* FIXME */ 1007*1fdeb165SXin LI } 1008*1fdeb165SXin LI } 1009*1fdeb165SXin LI 1010*1fdeb165SXin LI /* register CAM interface */ 1011*1fdeb165SXin LI ldm_for_each_vbus(vbus, vbus_ext) { 1012*1fdeb165SXin LI struct cam_devq *devq; 1013*1fdeb165SXin LI struct ccb_setasync ccb; 1014*1fdeb165SXin LI 1015*1fdeb165SXin LI #if (__FreeBSD_version >= 500000) 1016*1fdeb165SXin LI mtx_init(&vbus_ext->lock, "hptsleeplock", NULL, MTX_DEF); 1017*1fdeb165SXin LI #endif 1018*1fdeb165SXin LI if (bus_dma_tag_create(NULL,/* parent */ 1019*1fdeb165SXin LI 4, /* alignment */ 1020*1fdeb165SXin LI BUS_SPACE_MAXADDR_32BIT+1, /* boundary */ 1021*1fdeb165SXin LI BUS_SPACE_MAXADDR, /* lowaddr */ 1022*1fdeb165SXin LI BUS_SPACE_MAXADDR, /* highaddr */ 1023*1fdeb165SXin LI NULL, NULL, /* filter, filterarg */ 1024*1fdeb165SXin LI PAGE_SIZE * (os_max_sg_descriptors-1), /* maxsize */ 1025*1fdeb165SXin LI os_max_sg_descriptors, /* nsegments */ 1026*1fdeb165SXin LI 0x10000, /* maxsegsize */ 1027*1fdeb165SXin LI BUS_DMA_WAITOK, /* flags */ 1028*1fdeb165SXin LI #if __FreeBSD_version>502000 1029*1fdeb165SXin LI busdma_lock_mutex, /* lockfunc */ 1030*1fdeb165SXin LI &vbus_ext->lock, /* lockfuncarg */ 1031*1fdeb165SXin LI #endif 1032*1fdeb165SXin LI &vbus_ext->io_dmat /* tag */)) 1033*1fdeb165SXin LI { 1034*1fdeb165SXin LI return ; 1035*1fdeb165SXin LI } 1036*1fdeb165SXin LI 1037*1fdeb165SXin LI for (i=0; i<os_max_queue_comm; i++) { 1038*1fdeb165SXin LI POS_CMDEXT ext = (POS_CMDEXT)malloc(sizeof(OS_CMDEXT), M_DEVBUF, M_WAITOK); 1039*1fdeb165SXin LI if (!ext) { 1040*1fdeb165SXin LI os_printk("Can't alloc cmdext(%d)", i); 1041*1fdeb165SXin LI return ; 1042*1fdeb165SXin LI } 1043*1fdeb165SXin LI ext->vbus_ext = vbus_ext; 1044*1fdeb165SXin LI ext->next = vbus_ext->cmdext_list; 1045*1fdeb165SXin LI vbus_ext->cmdext_list = ext; 1046*1fdeb165SXin LI 1047*1fdeb165SXin LI if (bus_dmamap_create(vbus_ext->io_dmat, 0, &ext->dma_map)) { 1048*1fdeb165SXin LI os_printk("Can't create dma map(%d)", i); 1049*1fdeb165SXin LI return ; 1050*1fdeb165SXin LI } 1051*1fdeb165SXin LI } 1052*1fdeb165SXin LI 1053*1fdeb165SXin LI if ((devq = cam_simq_alloc(os_max_queue_comm)) == NULL) { 1054*1fdeb165SXin LI os_printk("cam_simq_alloc failed"); 1055*1fdeb165SXin LI return ; 1056*1fdeb165SXin LI } 1057*1fdeb165SXin LI 1058*1fdeb165SXin LI #if __FreeBSD_version > 700025 1059*1fdeb165SXin LI vbus_ext->sim = cam_sim_alloc(hpt_action, hpt_poll, driver_name, 1060*1fdeb165SXin LI vbus_ext, unit_number, &Giant, os_max_queue_comm, /*tagged*/8, devq); 1061*1fdeb165SXin LI #else 1062*1fdeb165SXin LI vbus_ext->sim = cam_sim_alloc(hpt_action, hpt_poll, driver_name, 1063*1fdeb165SXin LI vbus_ext, unit_number, os_max_queue_comm, /*tagged*/8, devq); 1064*1fdeb165SXin LI #endif 1065*1fdeb165SXin LI unit_number++; 1066*1fdeb165SXin LI if (!vbus_ext->sim) { 1067*1fdeb165SXin LI os_printk("cam_sim_alloc failed"); 1068*1fdeb165SXin LI cam_simq_free(devq); 1069*1fdeb165SXin LI return ; 1070*1fdeb165SXin LI } 1071*1fdeb165SXin LI 1072*1fdeb165SXin LI #if __FreeBSD_version > 700044 1073*1fdeb165SXin LI if (xpt_bus_register(vbus_ext->sim, NULL, 0) != CAM_SUCCESS) { 1074*1fdeb165SXin LI #else 1075*1fdeb165SXin LI if (xpt_bus_register(vbus_ext->sim, 0) != CAM_SUCCESS) { 1076*1fdeb165SXin LI #endif 1077*1fdeb165SXin LI os_printk("xpt_bus_register failed"); 1078*1fdeb165SXin LI cam_sim_free(vbus_ext->sim, /*free devq*/ TRUE); 1079*1fdeb165SXin LI vbus_ext->sim = NULL; 1080*1fdeb165SXin LI return ; 1081*1fdeb165SXin LI } 1082*1fdeb165SXin LI 1083*1fdeb165SXin LI if (xpt_create_path(&vbus_ext->path, /*periph */ NULL, 1084*1fdeb165SXin LI cam_sim_path(vbus_ext->sim), CAM_TARGET_WILDCARD, 1085*1fdeb165SXin LI CAM_LUN_WILDCARD) != CAM_REQ_CMP) 1086*1fdeb165SXin LI { 1087*1fdeb165SXin LI os_printk("xpt_create_path failed"); 1088*1fdeb165SXin LI xpt_bus_deregister(cam_sim_path(vbus_ext->sim)); 1089*1fdeb165SXin LI cam_sim_free(vbus_ext->sim, /*free_devq*/TRUE); 1090*1fdeb165SXin LI vbus_ext->sim = NULL; 1091*1fdeb165SXin LI return ; 1092*1fdeb165SXin LI } 1093*1fdeb165SXin LI 1094*1fdeb165SXin LI xpt_setup_ccb(&ccb.ccb_h, vbus_ext->path, /*priority*/5); 1095*1fdeb165SXin LI ccb.ccb_h.func_code = XPT_SASYNC_CB; 1096*1fdeb165SXin LI ccb.event_enable = AC_LOST_DEVICE; 1097*1fdeb165SXin LI ccb.callback = hpt_async; 1098*1fdeb165SXin LI ccb.callback_arg = vbus_ext; 1099*1fdeb165SXin LI xpt_action((union ccb *)&ccb); 1100*1fdeb165SXin LI 1101*1fdeb165SXin LI for (hba = vbus_ext->hba_list; hba; hba = hba->next) { 1102*1fdeb165SXin LI int rid = 0; 1103*1fdeb165SXin LI if ((hba->irq_res = bus_alloc_resource(hba->pcidev, 1104*1fdeb165SXin LI SYS_RES_IRQ, &rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) 1105*1fdeb165SXin LI { 1106*1fdeb165SXin LI os_printk("can't allocate interrupt"); 1107*1fdeb165SXin LI return ; 1108*1fdeb165SXin LI } 1109*1fdeb165SXin LI 1110*1fdeb165SXin LI if (bus_setup_intr(hba->pcidev, hba->irq_res, INTR_TYPE_CAM, 1111*1fdeb165SXin LI #if __FreeBSD_version > 700025 1112*1fdeb165SXin LI NULL, hpt_pci_intr, vbus_ext, &hba->irq_handle)) 1113*1fdeb165SXin LI #else 1114*1fdeb165SXin LI hpt_pci_intr, vbus_ext, &hba->irq_handle)) 1115*1fdeb165SXin LI #endif 1116*1fdeb165SXin LI { 1117*1fdeb165SXin LI os_printk("can't set up interrupt"); 1118*1fdeb165SXin LI return ; 1119*1fdeb165SXin LI } 1120*1fdeb165SXin LI hba->ldm_adapter.him->intr_control(hba->ldm_adapter.him_handle, HPT_TRUE); 1121*1fdeb165SXin LI 1122*1fdeb165SXin LI } 1123*1fdeb165SXin LI 1124*1fdeb165SXin LI vbus_ext->shutdown_eh = EVENTHANDLER_REGISTER(shutdown_final, 1125*1fdeb165SXin LI hpt_shutdown_vbus, vbus_ext, SHUTDOWN_PRI_DEFAULT); 1126*1fdeb165SXin LI if (!vbus_ext->shutdown_eh) 1127*1fdeb165SXin LI os_printk("Shutdown event registration failed"); 1128*1fdeb165SXin LI } 1129*1fdeb165SXin LI 1130*1fdeb165SXin LI ldm_for_each_vbus(vbus, vbus_ext) { 1131*1fdeb165SXin LI TASK_INIT(&vbus_ext->worker, 0, (task_fn_t *)hpt_do_tasks, vbus_ext); 1132*1fdeb165SXin LI if (vbus_ext->tasks) 1133*1fdeb165SXin LI TASK_ENQUEUE(&vbus_ext->worker); 1134*1fdeb165SXin LI } 1135*1fdeb165SXin LI 1136*1fdeb165SXin LI make_dev(&hpt_cdevsw, DRIVER_MINOR, UID_ROOT, GID_OPERATOR, 1137*1fdeb165SXin LI S_IRUSR | S_IWUSR, "%s", driver_name); 1138*1fdeb165SXin LI } 1139*1fdeb165SXin LI 1140*1fdeb165SXin LI #if defined(KLD_MODULE) && (__FreeBSD_version >= 503000) 1141*1fdeb165SXin LI 1142*1fdeb165SXin LI typedef struct driverlink *driverlink_t; 1143*1fdeb165SXin LI struct driverlink { 1144*1fdeb165SXin LI kobj_class_t driver; 1145*1fdeb165SXin LI TAILQ_ENTRY(driverlink) link; /* list of drivers in devclass */ 1146*1fdeb165SXin LI }; 1147*1fdeb165SXin LI 1148*1fdeb165SXin LI typedef TAILQ_HEAD(driver_list, driverlink) driver_list_t; 1149*1fdeb165SXin LI 1150*1fdeb165SXin LI struct devclass { 1151*1fdeb165SXin LI TAILQ_ENTRY(devclass) link; 1152*1fdeb165SXin LI devclass_t parent; /* parent in devclass hierarchy */ 1153*1fdeb165SXin LI driver_list_t drivers; /* bus devclasses store drivers for bus */ 1154*1fdeb165SXin LI char *name; 1155*1fdeb165SXin LI device_t *devices; /* array of devices indexed by unit */ 1156*1fdeb165SXin LI int maxunit; /* size of devices array */ 1157*1fdeb165SXin LI }; 1158*1fdeb165SXin LI 1159*1fdeb165SXin LI static void override_kernel_driver(void) 1160*1fdeb165SXin LI { 1161*1fdeb165SXin LI driverlink_t dl, dlfirst; 1162*1fdeb165SXin LI driver_t *tmpdriver; 1163*1fdeb165SXin LI devclass_t dc = devclass_find("pci"); 1164*1fdeb165SXin LI 1165*1fdeb165SXin LI if (dc){ 1166*1fdeb165SXin LI dlfirst = TAILQ_FIRST(&dc->drivers); 1167*1fdeb165SXin LI for (dl = dlfirst; dl; dl = TAILQ_NEXT(dl, link)) { 1168*1fdeb165SXin LI if(strcmp(dl->driver->name, driver_name) == 0) { 1169*1fdeb165SXin LI tmpdriver=dl->driver; 1170*1fdeb165SXin LI dl->driver=dlfirst->driver; 1171*1fdeb165SXin LI dlfirst->driver=tmpdriver; 1172*1fdeb165SXin LI break; 1173*1fdeb165SXin LI } 1174*1fdeb165SXin LI } 1175*1fdeb165SXin LI } 1176*1fdeb165SXin LI } 1177*1fdeb165SXin LI 1178*1fdeb165SXin LI #else 1179*1fdeb165SXin LI #define override_kernel_driver() 1180*1fdeb165SXin LI #endif 1181*1fdeb165SXin LI 1182*1fdeb165SXin LI static void hpt_init(void *dummy) 1183*1fdeb165SXin LI { 1184*1fdeb165SXin LI if (bootverbose) 1185*1fdeb165SXin LI os_printk("%s %s", driver_name_long, driver_ver); 1186*1fdeb165SXin LI 1187*1fdeb165SXin LI override_kernel_driver(); 1188*1fdeb165SXin LI init_config(); 1189*1fdeb165SXin LI 1190*1fdeb165SXin LI hpt_ich.ich_func = hpt_final_init; 1191*1fdeb165SXin LI hpt_ich.ich_arg = NULL; 1192*1fdeb165SXin LI if (config_intrhook_establish(&hpt_ich) != 0) { 1193*1fdeb165SXin LI printf("%s: cannot establish configuration hook\n", 1194*1fdeb165SXin LI driver_name_long); 1195*1fdeb165SXin LI } 1196*1fdeb165SXin LI 1197*1fdeb165SXin LI } 1198*1fdeb165SXin LI SYSINIT(hptinit, SI_SUB_CONFIGURE, SI_ORDER_FIRST, hpt_init, NULL); 1199*1fdeb165SXin LI 1200*1fdeb165SXin LI /* 1201*1fdeb165SXin LI * CAM driver interface 1202*1fdeb165SXin LI */ 1203*1fdeb165SXin LI static device_method_t driver_methods[] = { 1204*1fdeb165SXin LI /* Device interface */ 1205*1fdeb165SXin LI DEVMETHOD(device_probe, hpt_probe), 1206*1fdeb165SXin LI DEVMETHOD(device_attach, hpt_attach), 1207*1fdeb165SXin LI DEVMETHOD(device_detach, hpt_detach), 1208*1fdeb165SXin LI DEVMETHOD(device_shutdown, hpt_shutdown), 1209*1fdeb165SXin LI { 0, 0 } 1210*1fdeb165SXin LI }; 1211*1fdeb165SXin LI 1212*1fdeb165SXin LI static driver_t hpt_pci_driver = { 1213*1fdeb165SXin LI driver_name, 1214*1fdeb165SXin LI driver_methods, 1215*1fdeb165SXin LI sizeof(HBA) 1216*1fdeb165SXin LI }; 1217*1fdeb165SXin LI 1218*1fdeb165SXin LI static devclass_t hpt_devclass; 1219*1fdeb165SXin LI 1220*1fdeb165SXin LI #ifndef TARGETNAME 1221*1fdeb165SXin LI #error "no TARGETNAME found" 1222*1fdeb165SXin LI #endif 1223*1fdeb165SXin LI 1224*1fdeb165SXin LI /* use this to make TARGETNAME be expanded */ 1225*1fdeb165SXin LI #define __DRIVER_MODULE(p1, p2, p3, p4, p5, p6) DRIVER_MODULE(p1, p2, p3, p4, p5, p6) 1226*1fdeb165SXin LI #define __MODULE_VERSION(p1, p2) MODULE_VERSION(p1, p2) 1227*1fdeb165SXin LI #define __MODULE_DEPEND(p1, p2, p3, p4, p5) MODULE_DEPEND(p1, p2, p3, p4, p5) 1228*1fdeb165SXin LI __DRIVER_MODULE(TARGETNAME, pci, hpt_pci_driver, hpt_devclass, 0, 0); 1229*1fdeb165SXin LI __MODULE_VERSION(TARGETNAME, 1); 1230*1fdeb165SXin LI __MODULE_DEPEND(TARGETNAME, cam, 1, 1, 1); 1231*1fdeb165SXin LI 1232*1fdeb165SXin LI #if __FreeBSD_version>503000 1233*1fdeb165SXin LI typedef struct cdev * ioctl_dev_t; 1234*1fdeb165SXin LI #else 1235*1fdeb165SXin LI typedef dev_t ioctl_dev_t; 1236*1fdeb165SXin LI #endif 1237*1fdeb165SXin LI 1238*1fdeb165SXin LI #if __FreeBSD_version >= 500000 1239*1fdeb165SXin LI typedef struct thread * ioctl_thread_t; 1240*1fdeb165SXin LI #else 1241*1fdeb165SXin LI typedef struct proc * ioctl_thread_t; 1242*1fdeb165SXin LI #endif 1243*1fdeb165SXin LI 1244*1fdeb165SXin LI static int hpt_open(ioctl_dev_t dev, int flags, int devtype, ioctl_thread_t td) 1245*1fdeb165SXin LI { 1246*1fdeb165SXin LI return 0; 1247*1fdeb165SXin LI } 1248*1fdeb165SXin LI 1249*1fdeb165SXin LI static int hpt_close(ioctl_dev_t dev, int flags, int devtype, ioctl_thread_t td) 1250*1fdeb165SXin LI { 1251*1fdeb165SXin LI return 0; 1252*1fdeb165SXin LI } 1253*1fdeb165SXin LI 1254*1fdeb165SXin LI static int hpt_ioctl(ioctl_dev_t dev, u_long cmd, caddr_t data, int fflag, ioctl_thread_t td) 1255*1fdeb165SXin LI { 1256*1fdeb165SXin LI PHPT_IOCTL_PARAM piop=(PHPT_IOCTL_PARAM)data; 1257*1fdeb165SXin LI IOCTL_ARG ioctl_args; 1258*1fdeb165SXin LI HPT_U32 bytesReturned; 1259*1fdeb165SXin LI 1260*1fdeb165SXin LI switch (cmd){ 1261*1fdeb165SXin LI case HPT_DO_IOCONTROL: 1262*1fdeb165SXin LI { 1263*1fdeb165SXin LI if (piop->Magic == HPT_IOCTL_MAGIC || piop->Magic == HPT_IOCTL_MAGIC32) { 1264*1fdeb165SXin LI KdPrint(("ioctl=%x in=%p len=%d out=%p len=%d\n", 1265*1fdeb165SXin LI piop->dwIoControlCode, 1266*1fdeb165SXin LI piop->lpInBuffer, 1267*1fdeb165SXin LI piop->nInBufferSize, 1268*1fdeb165SXin LI piop->lpOutBuffer, 1269*1fdeb165SXin LI piop->nOutBufferSize)); 1270*1fdeb165SXin LI 1271*1fdeb165SXin LI memset(&ioctl_args, 0, sizeof(ioctl_args)); 1272*1fdeb165SXin LI 1273*1fdeb165SXin LI ioctl_args.dwIoControlCode = piop->dwIoControlCode; 1274*1fdeb165SXin LI ioctl_args.nInBufferSize = piop->nInBufferSize; 1275*1fdeb165SXin LI ioctl_args.nOutBufferSize = piop->nOutBufferSize; 1276*1fdeb165SXin LI ioctl_args.lpBytesReturned = &bytesReturned; 1277*1fdeb165SXin LI 1278*1fdeb165SXin LI if (ioctl_args.nInBufferSize) { 1279*1fdeb165SXin LI ioctl_args.lpInBuffer = malloc(ioctl_args.nInBufferSize, M_DEVBUF, M_WAITOK); 1280*1fdeb165SXin LI if (!ioctl_args.lpInBuffer) 1281*1fdeb165SXin LI goto invalid; 1282*1fdeb165SXin LI if (copyin((void*)piop->lpInBuffer, 1283*1fdeb165SXin LI ioctl_args.lpInBuffer, piop->nInBufferSize)) 1284*1fdeb165SXin LI goto invalid; 1285*1fdeb165SXin LI } 1286*1fdeb165SXin LI 1287*1fdeb165SXin LI if (ioctl_args.nOutBufferSize) { 1288*1fdeb165SXin LI ioctl_args.lpOutBuffer = malloc(ioctl_args.nOutBufferSize, M_DEVBUF, M_WAITOK); 1289*1fdeb165SXin LI if (!ioctl_args.lpOutBuffer) 1290*1fdeb165SXin LI goto invalid; 1291*1fdeb165SXin LI } 1292*1fdeb165SXin LI 1293*1fdeb165SXin LI #if (__FreeBSD_version >= 500000) 1294*1fdeb165SXin LI mtx_lock(&Giant); 1295*1fdeb165SXin LI #endif 1296*1fdeb165SXin LI 1297*1fdeb165SXin LI hpt_do_ioctl(&ioctl_args); 1298*1fdeb165SXin LI 1299*1fdeb165SXin LI #if (__FreeBSD_version >= 500000) 1300*1fdeb165SXin LI mtx_unlock(&Giant); 1301*1fdeb165SXin LI #endif 1302*1fdeb165SXin LI 1303*1fdeb165SXin LI if (ioctl_args.result==HPT_IOCTL_RESULT_OK) { 1304*1fdeb165SXin LI if (piop->nOutBufferSize) { 1305*1fdeb165SXin LI if (copyout(ioctl_args.lpOutBuffer, 1306*1fdeb165SXin LI (void*)piop->lpOutBuffer, piop->nOutBufferSize)) 1307*1fdeb165SXin LI goto invalid; 1308*1fdeb165SXin LI } 1309*1fdeb165SXin LI if (piop->lpBytesReturned) { 1310*1fdeb165SXin LI if (copyout(&bytesReturned, 1311*1fdeb165SXin LI (void*)piop->lpBytesReturned, sizeof(HPT_U32))) 1312*1fdeb165SXin LI goto invalid; 1313*1fdeb165SXin LI } 1314*1fdeb165SXin LI if (ioctl_args.lpInBuffer) free(ioctl_args.lpInBuffer, M_DEVBUF); 1315*1fdeb165SXin LI if (ioctl_args.lpOutBuffer) free(ioctl_args.lpOutBuffer, M_DEVBUF); 1316*1fdeb165SXin LI return 0; 1317*1fdeb165SXin LI } 1318*1fdeb165SXin LI invalid: 1319*1fdeb165SXin LI if (ioctl_args.lpInBuffer) free(ioctl_args.lpInBuffer, M_DEVBUF); 1320*1fdeb165SXin LI if (ioctl_args.lpOutBuffer) free(ioctl_args.lpOutBuffer, M_DEVBUF); 1321*1fdeb165SXin LI return EFAULT; 1322*1fdeb165SXin LI } 1323*1fdeb165SXin LI return EFAULT; 1324*1fdeb165SXin LI } 1325*1fdeb165SXin LI 1326*1fdeb165SXin LI case HPT_SCAN_BUS: 1327*1fdeb165SXin LI { 1328*1fdeb165SXin LI return hpt_rescan_bus(); 1329*1fdeb165SXin LI } 1330*1fdeb165SXin LI default: 1331*1fdeb165SXin LI KdPrint(("invalid command!")); 1332*1fdeb165SXin LI return EFAULT; 1333*1fdeb165SXin LI } 1334*1fdeb165SXin LI 1335*1fdeb165SXin LI } 1336*1fdeb165SXin LI 1337*1fdeb165SXin LI static int hpt_rescan_bus(void) 1338*1fdeb165SXin LI { 1339*1fdeb165SXin LI union ccb *ccb; 1340*1fdeb165SXin LI PVBUS vbus; 1341*1fdeb165SXin LI PVBUS_EXT vbus_ext; 1342*1fdeb165SXin LI 1343*1fdeb165SXin LI mtx_lock(&Giant); 1344*1fdeb165SXin LI 1345*1fdeb165SXin LI ldm_for_each_vbus(vbus, vbus_ext) { 1346*1fdeb165SXin LI if ((ccb = xpt_alloc_ccb()) == NULL) 1347*1fdeb165SXin LI { 1348*1fdeb165SXin LI return(ENOMEM); 1349*1fdeb165SXin LI } 1350*1fdeb165SXin LI if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(vbus_ext->sim), 1351*1fdeb165SXin LI CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) 1352*1fdeb165SXin LI { 1353*1fdeb165SXin LI xpt_free_ccb(ccb); 1354*1fdeb165SXin LI return(EIO); 1355*1fdeb165SXin LI } 1356*1fdeb165SXin LI xpt_rescan(ccb); 1357*1fdeb165SXin LI } 1358*1fdeb165SXin LI mtx_unlock(&Giant); 1359*1fdeb165SXin LI return(0); 1360*1fdeb165SXin LI } 1361