1252867Sdelphij/* $Id: osm_bsd.c,v 1.36 2010/05/11 03:12:11 lcn Exp $ */ 2252867Sdelphij/*- 3252867Sdelphij * HighPoint RAID Driver for FreeBSD 4252867Sdelphij * Copyright (C) 2005-2011 HighPoint Technologies, Inc. 5252867Sdelphij * All rights reserved. 6252867Sdelphij * 7252867Sdelphij * Redistribution and use in source and binary forms, with or without 8252867Sdelphij * modification, are permitted provided that the following conditions 9252867Sdelphij * are met: 10252867Sdelphij * 1. Redistributions of source code must retain the above copyright 11252867Sdelphij * notice, this list of conditions and the following disclaimer. 12252867Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 13252867Sdelphij * notice, this list of conditions and the following disclaimer in the 14252867Sdelphij * documentation and/or other materials provided with the distribution. 15252867Sdelphij * 16252867Sdelphij * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17252867Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18252867Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19252867Sdelphij * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20252867Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21252867Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22252867Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23252867Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24252867Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25252867Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26252867Sdelphij * SUCH DAMAGE. 27252867Sdelphij * 28252867Sdelphij * $FreeBSD$ 29252867Sdelphij */ 30252867Sdelphij#include <dev/hptnr/hptnr_config.h> 31252867Sdelphij#include <dev/hptnr/os_bsd.h> 32252867Sdelphij#include <dev/hptnr/hptintf.h> 33252867Sdelphij 34252867Sdelphijstatic int hpt_probe(device_t dev) 35252867Sdelphij{ 36252867Sdelphij PCI_ID pci_id; 37252867Sdelphij HIM *him; 38252867Sdelphij int i; 39252867Sdelphij PHBA hba; 40252867Sdelphij 41252867Sdelphij for (him = him_list; him; him = him->next) { 42252867Sdelphij for (i=0; him->get_supported_device_id(i, &pci_id); i++) { 43252867Sdelphij if (him->get_controller_count) 44252867Sdelphij him->get_controller_count(&pci_id,0,0); 45252867Sdelphij if ((pci_get_vendor(dev) == pci_id.vid) && 46252867Sdelphij (pci_get_device(dev) == pci_id.did)){ 47252867Sdelphij KdPrint(("hpt_probe: adapter at PCI %d:%d:%d, IRQ %d", 48252867Sdelphij pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev), pci_get_irq(dev) 49252867Sdelphij )); 50252867Sdelphij device_set_desc(dev, him->name); 51252867Sdelphij hba = (PHBA)device_get_softc(dev); 52252867Sdelphij memset(hba, 0, sizeof(HBA)); 53252867Sdelphij hba->ext_type = EXT_TYPE_HBA; 54252867Sdelphij hba->ldm_adapter.him = him; 55252867Sdelphij return 0; 56252867Sdelphij } 57252867Sdelphij } 58252867Sdelphij } 59252867Sdelphij 60252867Sdelphij return (ENXIO); 61252867Sdelphij} 62252867Sdelphij 63252867Sdelphijstatic int hpt_attach(device_t dev) 64252867Sdelphij{ 65252867Sdelphij PHBA hba = (PHBA)device_get_softc(dev); 66252867Sdelphij HIM *him = hba->ldm_adapter.him; 67252867Sdelphij PCI_ID pci_id; 68252867Sdelphij HPT_UINT size; 69252867Sdelphij PVBUS vbus; 70252867Sdelphij PVBUS_EXT vbus_ext; 71252867Sdelphij 72252867Sdelphij KdPrint(("hpt_attach(%d/%d/%d)", pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev))); 73252867Sdelphij 74252867Sdelphij#if __FreeBSD_version >=440000 75252867Sdelphij pci_enable_busmaster(dev); 76252867Sdelphij#endif 77252867Sdelphij 78252867Sdelphij pci_id.vid = pci_get_vendor(dev); 79252867Sdelphij pci_id.did = pci_get_device(dev); 80252867Sdelphij pci_id.rev = pci_get_revid(dev); 81252867Sdelphij pci_id.subsys = (HPT_U32)(pci_get_subdevice(dev)) << 16 | pci_get_subvendor(dev); 82252867Sdelphij 83252867Sdelphij size = him->get_adapter_size(&pci_id); 84252867Sdelphij hba->ldm_adapter.him_handle = malloc(size, M_DEVBUF, M_WAITOK); 85252867Sdelphij if (!hba->ldm_adapter.him_handle) 86252867Sdelphij return ENXIO; 87252867Sdelphij 88252867Sdelphij hba->pcidev = dev; 89252867Sdelphij hba->pciaddr.tree = 0; 90252867Sdelphij hba->pciaddr.bus = pci_get_bus(dev); 91252867Sdelphij hba->pciaddr.device = pci_get_slot(dev); 92252867Sdelphij hba->pciaddr.function = pci_get_function(dev); 93252867Sdelphij 94252867Sdelphij if (!him->create_adapter(&pci_id, hba->pciaddr, hba->ldm_adapter.him_handle, hba)) { 95252867Sdelphij free(hba->ldm_adapter.him_handle, M_DEVBUF); 96252867Sdelphij return -1; 97252867Sdelphij } 98252867Sdelphij 99252867Sdelphij os_printk("adapter at PCI %d:%d:%d, IRQ %d", 100252867Sdelphij hba->pciaddr.bus, hba->pciaddr.device, hba->pciaddr.function, pci_get_irq(dev)); 101252867Sdelphij 102252867Sdelphij if (!ldm_register_adapter(&hba->ldm_adapter)) { 103252867Sdelphij size = ldm_get_vbus_size(); 104252867Sdelphij vbus_ext = malloc(sizeof(VBUS_EXT) + size, M_DEVBUF, M_WAITOK); 105252867Sdelphij if (!vbus_ext) { 106252867Sdelphij free(hba->ldm_adapter.him_handle, M_DEVBUF); 107252867Sdelphij return -1; 108252867Sdelphij } 109252867Sdelphij memset(vbus_ext, 0, sizeof(VBUS_EXT)); 110252867Sdelphij vbus_ext->ext_type = EXT_TYPE_VBUS; 111252867Sdelphij ldm_create_vbus((PVBUS)vbus_ext->vbus, vbus_ext); 112252867Sdelphij ldm_register_adapter(&hba->ldm_adapter); 113252867Sdelphij } 114252867Sdelphij 115252867Sdelphij ldm_for_each_vbus(vbus, vbus_ext) { 116252867Sdelphij if (hba->ldm_adapter.vbus==vbus) { 117252867Sdelphij hba->vbus_ext = vbus_ext; 118252867Sdelphij hba->next = vbus_ext->hba_list; 119252867Sdelphij vbus_ext->hba_list = hba; 120252867Sdelphij break; 121252867Sdelphij } 122252867Sdelphij } 123252867Sdelphij return 0; 124252867Sdelphij} 125252867Sdelphij 126252867Sdelphij/* 127252867Sdelphij * Maybe we'd better to use the bus_dmamem_alloc to alloc DMA memory, 128252867Sdelphij * but there are some problems currently (alignment, etc). 129252867Sdelphij */ 130252867Sdelphijstatic __inline void *__get_free_pages(int order) 131252867Sdelphij{ 132252867Sdelphij /* don't use low memory - other devices may get starved */ 133252867Sdelphij return contigmalloc(PAGE_SIZE<<order, 134252867Sdelphij M_DEVBUF, M_WAITOK, BUS_SPACE_MAXADDR_24BIT, BUS_SPACE_MAXADDR, PAGE_SIZE, 0); 135252867Sdelphij} 136252867Sdelphij 137252867Sdelphijstatic __inline void free_pages(void *p, int order) 138252867Sdelphij{ 139252867Sdelphij contigfree(p, PAGE_SIZE<<order, M_DEVBUF); 140252867Sdelphij} 141252867Sdelphij 142252867Sdelphijstatic int hpt_alloc_mem(PVBUS_EXT vbus_ext) 143252867Sdelphij{ 144252867Sdelphij PHBA hba; 145252867Sdelphij struct freelist *f; 146252867Sdelphij HPT_UINT i; 147252867Sdelphij void **p; 148252867Sdelphij 149252867Sdelphij for (hba = vbus_ext->hba_list; hba; hba = hba->next) 150252867Sdelphij hba->ldm_adapter.him->get_meminfo(hba->ldm_adapter.him_handle); 151252867Sdelphij 152252867Sdelphij ldm_get_mem_info((PVBUS)vbus_ext->vbus, 0); 153252867Sdelphij 154252867Sdelphij for (f=vbus_ext->freelist_head; f; f=f->next) { 155252867Sdelphij KdPrint(("%s: %d*%d=%d bytes", 156252867Sdelphij f->tag, f->count, f->size, f->count*f->size)); 157252867Sdelphij for (i=0; i<f->count; i++) { 158252867Sdelphij p = (void **)malloc(f->size, M_DEVBUF, M_WAITOK); 159252867Sdelphij if (!p) return (ENXIO); 160252867Sdelphij *p = f->head; 161252867Sdelphij f->head = p; 162252867Sdelphij } 163252867Sdelphij } 164252867Sdelphij 165252867Sdelphij for (f=vbus_ext->freelist_dma_head; f; f=f->next) { 166252867Sdelphij int order, size, j; 167252867Sdelphij 168252867Sdelphij HPT_ASSERT((f->size & (f->alignment-1))==0); 169252867Sdelphij 170252867Sdelphij for (order=0, size=PAGE_SIZE; size<f->size; order++, size<<=1) 171252867Sdelphij ; 172252867Sdelphij 173252867Sdelphij KdPrint(("%s: %d*%d=%d bytes, order %d", 174252867Sdelphij f->tag, f->count, f->size, f->count*f->size, order)); 175252867Sdelphij HPT_ASSERT(f->alignment<=PAGE_SIZE); 176252867Sdelphij 177252867Sdelphij for (i=0; i<f->count;) { 178252867Sdelphij p = (void **)__get_free_pages(order); 179252867Sdelphij if (!p) return -1; 180252867Sdelphij for (j = size/f->size; j && i<f->count; i++,j--) { 181252867Sdelphij *p = f->head; 182252867Sdelphij *(BUS_ADDRESS *)(p+1) = (BUS_ADDRESS)vtophys(p); 183252867Sdelphij f->head = p; 184252867Sdelphij p = (void **)((unsigned long)p + f->size); 185252867Sdelphij } 186252867Sdelphij } 187252867Sdelphij } 188252867Sdelphij 189252867Sdelphij HPT_ASSERT(PAGE_SIZE==DMAPOOL_PAGE_SIZE); 190252867Sdelphij 191252867Sdelphij for (i=0; i<os_max_cache_pages; i++) { 192252867Sdelphij p = (void **)__get_free_pages(0); 193252867Sdelphij if (!p) return -1; 194252867Sdelphij HPT_ASSERT(((HPT_UPTR)p & (DMAPOOL_PAGE_SIZE-1))==0); 195252867Sdelphij dmapool_put_page((PVBUS)vbus_ext->vbus, p, (BUS_ADDRESS)vtophys(p)); 196252867Sdelphij } 197252867Sdelphij 198252867Sdelphij return 0; 199252867Sdelphij} 200252867Sdelphij 201252867Sdelphijstatic void hpt_free_mem(PVBUS_EXT vbus_ext) 202252867Sdelphij{ 203252867Sdelphij struct freelist *f; 204252867Sdelphij void *p; 205252867Sdelphij int i; 206252867Sdelphij BUS_ADDRESS bus; 207252867Sdelphij 208252867Sdelphij for (f=vbus_ext->freelist_head; f; f=f->next) { 209252867Sdelphij#if DBG 210252867Sdelphij if (f->count!=f->reserved_count) { 211252867Sdelphij KdPrint(("memory leak for freelist %s (%d/%d)", f->tag, f->count, f->reserved_count)); 212252867Sdelphij } 213252867Sdelphij#endif 214252867Sdelphij while ((p=freelist_get(f))) 215252867Sdelphij free(p, M_DEVBUF); 216252867Sdelphij } 217252867Sdelphij 218252867Sdelphij for (i=0; i<os_max_cache_pages; i++) { 219252867Sdelphij p = dmapool_get_page((PVBUS)vbus_ext->vbus, &bus); 220252867Sdelphij HPT_ASSERT(p); 221252867Sdelphij free_pages(p, 0); 222252867Sdelphij } 223252867Sdelphij 224252867Sdelphij for (f=vbus_ext->freelist_dma_head; f; f=f->next) { 225252867Sdelphij int order, size; 226252867Sdelphij#if DBG 227252867Sdelphij if (f->count!=f->reserved_count) { 228252867Sdelphij KdPrint(("memory leak for dma freelist %s (%d/%d)", f->tag, f->count, f->reserved_count)); 229252867Sdelphij } 230252867Sdelphij#endif 231252867Sdelphij for (order=0, size=PAGE_SIZE; size<f->size; order++, size<<=1) ; 232252867Sdelphij 233252867Sdelphij while ((p=freelist_get_dma(f, &bus))) { 234252867Sdelphij if (order) 235252867Sdelphij free_pages(p, order); 236252867Sdelphij else { 237252867Sdelphij /* can't free immediately since other blocks in this page may still be in the list */ 238252867Sdelphij if (((HPT_UPTR)p & (PAGE_SIZE-1))==0) 239252867Sdelphij dmapool_put_page((PVBUS)vbus_ext->vbus, p, bus); 240252867Sdelphij } 241252867Sdelphij } 242252867Sdelphij } 243252867Sdelphij 244252867Sdelphij while ((p = dmapool_get_page((PVBUS)vbus_ext->vbus, &bus))) 245252867Sdelphij free_pages(p, 0); 246252867Sdelphij} 247252867Sdelphij 248252867Sdelphijstatic int hpt_init_vbus(PVBUS_EXT vbus_ext) 249252867Sdelphij{ 250252867Sdelphij PHBA hba; 251252867Sdelphij 252252867Sdelphij for (hba = vbus_ext->hba_list; hba; hba = hba->next) 253252867Sdelphij if (!hba->ldm_adapter.him->initialize(hba->ldm_adapter.him_handle)) { 254252867Sdelphij KdPrint(("fail to initialize %p", hba)); 255252867Sdelphij return -1; 256252867Sdelphij } 257252867Sdelphij 258252867Sdelphij ldm_initialize_vbus((PVBUS)vbus_ext->vbus, &vbus_ext->hba_list->ldm_adapter); 259252867Sdelphij return 0; 260252867Sdelphij} 261252867Sdelphij 262252867Sdelphijstatic void hpt_flush_done(PCOMMAND pCmd) 263252867Sdelphij{ 264252867Sdelphij PVDEV vd = pCmd->target; 265252867Sdelphij 266252867Sdelphij if (mIsArray(vd->type) && vd->u.array.transform && vd!=vd->u.array.transform->target) { 267252867Sdelphij vd = vd->u.array.transform->target; 268252867Sdelphij HPT_ASSERT(vd); 269252867Sdelphij pCmd->target = vd; 270252867Sdelphij pCmd->Result = RETURN_PENDING; 271252867Sdelphij vdev_queue_cmd(pCmd); 272252867Sdelphij return; 273252867Sdelphij } 274252867Sdelphij 275252867Sdelphij *(int *)pCmd->priv = 1; 276252867Sdelphij wakeup(pCmd); 277252867Sdelphij} 278252867Sdelphij 279252867Sdelphij/* 280252867Sdelphij * flush a vdev (without retry). 281252867Sdelphij */ 282252867Sdelphijstatic int hpt_flush_vdev(PVBUS_EXT vbus_ext, PVDEV vd) 283252867Sdelphij{ 284252867Sdelphij PCOMMAND pCmd; 285252867Sdelphij int result = 0, done; 286252867Sdelphij HPT_UINT count; 287252867Sdelphij 288252867Sdelphij KdPrint(("flusing dev %p", vd)); 289252867Sdelphij 290252867Sdelphij hpt_lock_vbus(vbus_ext); 291252867Sdelphij 292252867Sdelphij if (mIsArray(vd->type) && vd->u.array.transform) 293252867Sdelphij count = MAX(vd->u.array.transform->source->cmds_per_request, 294252867Sdelphij vd->u.array.transform->target->cmds_per_request); 295252867Sdelphij else 296252867Sdelphij count = vd->cmds_per_request; 297252867Sdelphij 298252867Sdelphij pCmd = ldm_alloc_cmds(vd->vbus, count); 299252867Sdelphij 300252867Sdelphij if (!pCmd) { 301252867Sdelphij hpt_unlock_vbus(vbus_ext); 302252867Sdelphij return -1; 303252867Sdelphij } 304252867Sdelphij 305252867Sdelphij pCmd->type = CMD_TYPE_FLUSH; 306252867Sdelphij pCmd->flags.hard_flush = 1; 307252867Sdelphij pCmd->target = vd; 308252867Sdelphij pCmd->done = hpt_flush_done; 309252867Sdelphij done = 0; 310252867Sdelphij pCmd->priv = &done; 311252867Sdelphij 312252867Sdelphij ldm_queue_cmd(pCmd); 313252867Sdelphij 314252867Sdelphij if (!done) { 315252867Sdelphij while (hpt_sleep(vbus_ext, pCmd, PPAUSE, "hptfls", HPT_OSM_TIMEOUT)) { 316252867Sdelphij ldm_reset_vbus(vd->vbus); 317252867Sdelphij } 318252867Sdelphij } 319252867Sdelphij 320252867Sdelphij KdPrint(("flush result %d", pCmd->Result)); 321252867Sdelphij 322252867Sdelphij if (pCmd->Result!=RETURN_SUCCESS) 323252867Sdelphij result = -1; 324252867Sdelphij 325252867Sdelphij ldm_free_cmds(pCmd); 326252867Sdelphij 327252867Sdelphij hpt_unlock_vbus(vbus_ext); 328252867Sdelphij 329252867Sdelphij return result; 330252867Sdelphij} 331252867Sdelphij 332252867Sdelphijstatic void hpt_stop_tasks(PVBUS_EXT vbus_ext); 333252867Sdelphijstatic void hpt_shutdown_vbus(PVBUS_EXT vbus_ext, int howto) 334252867Sdelphij{ 335252867Sdelphij PVBUS vbus = (PVBUS)vbus_ext->vbus; 336252867Sdelphij PHBA hba; 337252867Sdelphij int i; 338252867Sdelphij 339252867Sdelphij KdPrint(("hpt_shutdown_vbus")); 340252867Sdelphij 341252867Sdelphij /* stop all ctl tasks and disable the worker taskqueue */ 342252867Sdelphij hpt_stop_tasks(vbus_ext); 343252867Sdelphij vbus_ext->worker.ta_context = 0; 344252867Sdelphij 345252867Sdelphij /* flush devices */ 346252867Sdelphij for (i=0; i<osm_max_targets; i++) { 347252867Sdelphij PVDEV vd = ldm_find_target(vbus, i); 348252867Sdelphij if (vd) { 349252867Sdelphij /* retry once */ 350252867Sdelphij if (hpt_flush_vdev(vbus_ext, vd)) 351252867Sdelphij hpt_flush_vdev(vbus_ext, vd); 352252867Sdelphij } 353252867Sdelphij } 354252867Sdelphij 355252867Sdelphij hpt_lock_vbus(vbus_ext); 356252867Sdelphij ldm_shutdown(vbus); 357252867Sdelphij hpt_unlock_vbus(vbus_ext); 358252867Sdelphij 359252867Sdelphij ldm_release_vbus(vbus); 360252867Sdelphij 361252867Sdelphij for (hba=vbus_ext->hba_list; hba; hba=hba->next) 362252867Sdelphij bus_teardown_intr(hba->pcidev, hba->irq_res, hba->irq_handle); 363252867Sdelphij 364252867Sdelphij hpt_free_mem(vbus_ext); 365252867Sdelphij 366252867Sdelphij while ((hba=vbus_ext->hba_list)) { 367252867Sdelphij vbus_ext->hba_list = hba->next; 368252867Sdelphij free(hba->ldm_adapter.him_handle, M_DEVBUF); 369252867Sdelphij } 370252867Sdelphij 371252867Sdelphij free(vbus_ext, M_DEVBUF); 372252867Sdelphij KdPrint(("hpt_shutdown_vbus done")); 373252867Sdelphij} 374252867Sdelphij 375252867Sdelphijstatic void __hpt_do_tasks(PVBUS_EXT vbus_ext) 376252867Sdelphij{ 377252867Sdelphij OSM_TASK *tasks; 378252867Sdelphij 379252867Sdelphij tasks = vbus_ext->tasks; 380252867Sdelphij vbus_ext->tasks = 0; 381252867Sdelphij 382252867Sdelphij while (tasks) { 383252867Sdelphij OSM_TASK *t = tasks; 384252867Sdelphij tasks = t->next; 385252867Sdelphij t->next = 0; 386252867Sdelphij t->func(vbus_ext->vbus, t->data); 387252867Sdelphij } 388252867Sdelphij} 389252867Sdelphij 390252867Sdelphijstatic void hpt_do_tasks(PVBUS_EXT vbus_ext, int pending) 391252867Sdelphij{ 392252867Sdelphij if(vbus_ext){ 393252867Sdelphij hpt_lock_vbus(vbus_ext); 394252867Sdelphij __hpt_do_tasks(vbus_ext); 395252867Sdelphij hpt_unlock_vbus(vbus_ext); 396252867Sdelphij } 397252867Sdelphij} 398252867Sdelphij 399252867Sdelphijstatic void hpt_action(struct cam_sim *sim, union ccb *ccb); 400252867Sdelphijstatic void hpt_poll(struct cam_sim *sim); 401252867Sdelphijstatic void hpt_async(void * callback_arg, u_int32_t code, struct cam_path * path, void * arg); 402252867Sdelphijstatic void hpt_pci_intr(void *arg); 403252867Sdelphij 404252867Sdelphijstatic __inline POS_CMDEXT cmdext_get(PVBUS_EXT vbus_ext) 405252867Sdelphij{ 406252867Sdelphij POS_CMDEXT p = vbus_ext->cmdext_list; 407252867Sdelphij if (p) 408252867Sdelphij vbus_ext->cmdext_list = p->next; 409252867Sdelphij return p; 410252867Sdelphij} 411252867Sdelphij 412252867Sdelphijstatic __inline void cmdext_put(POS_CMDEXT p) 413252867Sdelphij{ 414252867Sdelphij p->next = p->vbus_ext->cmdext_list; 415252867Sdelphij p->vbus_ext->cmdext_list = p; 416252867Sdelphij} 417252867Sdelphij 418252867Sdelphijstatic void hpt_timeout(void *arg) 419252867Sdelphij{ 420252867Sdelphij PCOMMAND pCmd = (PCOMMAND)arg; 421252867Sdelphij POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv; 422252867Sdelphij 423252867Sdelphij KdPrint(("pCmd %p timeout", pCmd)); 424252867Sdelphij 425252867Sdelphij ldm_reset_vbus((PVBUS)ext->vbus_ext->vbus); 426252867Sdelphij} 427252867Sdelphij 428252867Sdelphijstatic void os_cmddone(PCOMMAND pCmd) 429252867Sdelphij{ 430252867Sdelphij POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv; 431252867Sdelphij union ccb *ccb = ext->ccb; 432252867Sdelphij 433252867Sdelphij KdPrint(("os_cmddone(%p, %d)", pCmd, pCmd->Result)); 434252867Sdelphij 435252867Sdelphij untimeout(hpt_timeout, pCmd, ccb->ccb_h.timeout_ch); 436252867Sdelphij 437252867Sdelphij switch(pCmd->Result) { 438252867Sdelphij case RETURN_SUCCESS: 439252867Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 440252867Sdelphij break; 441252867Sdelphij case RETURN_BAD_DEVICE: 442252867Sdelphij ccb->ccb_h.status = CAM_DEV_NOT_THERE; 443252867Sdelphij break; 444252867Sdelphij case RETURN_DEVICE_BUSY: 445252867Sdelphij ccb->ccb_h.status = CAM_BUSY; 446252867Sdelphij break; 447252867Sdelphij case RETURN_INVALID_REQUEST: 448252867Sdelphij ccb->ccb_h.status = CAM_REQ_INVALID; 449252867Sdelphij break; 450252867Sdelphij case RETURN_SELECTION_TIMEOUT: 451252867Sdelphij ccb->ccb_h.status = CAM_SEL_TIMEOUT; 452252867Sdelphij break; 453252867Sdelphij case RETURN_RETRY: 454252867Sdelphij ccb->ccb_h.status = CAM_BUSY; 455252867Sdelphij break; 456252867Sdelphij default: 457252867Sdelphij ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 458252867Sdelphij break; 459252867Sdelphij } 460252867Sdelphij 461252867Sdelphij if (pCmd->flags.data_in) { 462252867Sdelphij bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, BUS_DMASYNC_POSTREAD); 463252867Sdelphij } 464252867Sdelphij else if (pCmd->flags.data_out) { 465252867Sdelphij bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, BUS_DMASYNC_POSTWRITE); 466252867Sdelphij } 467252867Sdelphij 468252867Sdelphij bus_dmamap_unload(ext->vbus_ext->io_dmat, ext->dma_map); 469252867Sdelphij 470252867Sdelphij cmdext_put(ext); 471252867Sdelphij ldm_free_cmds(pCmd); 472252867Sdelphij xpt_done(ccb); 473252867Sdelphij} 474252867Sdelphij 475252867Sdelphijstatic int os_buildsgl(PCOMMAND pCmd, PSG pSg, int logical) 476252867Sdelphij{ 477252903Sdelphij POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv; 478252903Sdelphij union ccb *ccb = ext->ccb; 479252903Sdelphij bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr; 480252903Sdelphij int idx; 481252903Sdelphij 482252903Sdelphij if(logical) { 483252903Sdelphij if (ccb->ccb_h.flags & CAM_DATA_PHYS) 484252903Sdelphij panic("physical address unsupported"); 485252903Sdelphij 486252903Sdelphij if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { 487252903Sdelphij if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) 488252903Sdelphij panic("physical address unsupported"); 489252903Sdelphij 490252903Sdelphij for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) { 491252903Sdelphij os_set_sgptr(&pSg[idx], (HPT_U8 *)(HPT_UPTR)sgList[idx].ds_addr); 492252903Sdelphij pSg[idx].size = sgList[idx].ds_len; 493252903Sdelphij pSg[idx].eot = (idx==ccb->csio.sglist_cnt-1)? 1 : 0; 494252903Sdelphij } 495252903Sdelphij } 496252903Sdelphij else { 497252903Sdelphij os_set_sgptr(pSg, (HPT_U8 *)ccb->csio.data_ptr); 498252903Sdelphij pSg->size = ccb->csio.dxfer_len; 499252903Sdelphij pSg->eot = 1; 500252903Sdelphij } 501252903Sdelphij return TRUE; 502252903Sdelphij } 503252903Sdelphij 504252867Sdelphij /* since we have provided physical sg, nobody will ask us to build physical sg */ 505252867Sdelphij HPT_ASSERT(0); 506252867Sdelphij return FALSE; 507252867Sdelphij} 508252867Sdelphij 509252867Sdelphijstatic void hpt_io_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 510252867Sdelphij{ 511252867Sdelphij PCOMMAND pCmd = (PCOMMAND)arg; 512252867Sdelphij POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv; 513252867Sdelphij PSG psg = pCmd->psg; 514252867Sdelphij int idx; 515252867Sdelphij 516252867Sdelphij HPT_ASSERT(pCmd->flags.physical_sg); 517252867Sdelphij 518252903Sdelphij if (error || nsegs == 0) 519252867Sdelphij panic("busdma error"); 520252867Sdelphij 521252867Sdelphij HPT_ASSERT(nsegs<=os_max_sg_descriptors); 522252867Sdelphij 523252903Sdelphij for (idx = 0; idx < nsegs; idx++, psg++) { 524252903Sdelphij psg->addr.bus = segs[idx].ds_addr; 525252903Sdelphij psg->size = segs[idx].ds_len; 526252903Sdelphij psg->eot = 0; 527252903Sdelphij } 528252903Sdelphij psg[-1].eot = 1; 529252867Sdelphij 530252903Sdelphij if (pCmd->flags.data_in) { 531252903Sdelphij bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, BUS_DMASYNC_PREREAD); 532252867Sdelphij } 533252903Sdelphij else if (pCmd->flags.data_out) { 534252903Sdelphij bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, BUS_DMASYNC_PREWRITE); 535252903Sdelphij } 536252867Sdelphij 537252867Sdelphij ext->ccb->ccb_h.timeout_ch = timeout(hpt_timeout, pCmd, HPT_OSM_TIMEOUT); 538252867Sdelphij ldm_queue_cmd(pCmd); 539252867Sdelphij} 540252867Sdelphij 541252867Sdelphijstatic void hpt_scsi_io(PVBUS_EXT vbus_ext, union ccb *ccb) 542252867Sdelphij{ 543252867Sdelphij PVBUS vbus = (PVBUS)vbus_ext->vbus; 544252867Sdelphij PVDEV vd; 545252867Sdelphij PCOMMAND pCmd; 546252867Sdelphij POS_CMDEXT ext; 547252867Sdelphij HPT_U8 *cdb; 548252867Sdelphij 549252867Sdelphij if (ccb->ccb_h.flags & CAM_CDB_POINTER) 550252867Sdelphij cdb = ccb->csio.cdb_io.cdb_ptr; 551252867Sdelphij else 552252867Sdelphij cdb = ccb->csio.cdb_io.cdb_bytes; 553252867Sdelphij 554252867Sdelphij KdPrint(("hpt_scsi_io: ccb %x id %d lun %d cdb %x-%x-%x", 555252867Sdelphij ccb, 556252867Sdelphij ccb->ccb_h.target_id, ccb->ccb_h.target_lun, 557252867Sdelphij *(HPT_U32 *)&cdb[0], *(HPT_U32 *)&cdb[4], *(HPT_U32 *)&cdb[8] 558252867Sdelphij )); 559252867Sdelphij 560252867Sdelphij /* ccb->ccb_h.path_id is not our bus id - don't check it */ 561252867Sdelphij if (ccb->ccb_h.target_lun != 0 || 562252867Sdelphij ccb->ccb_h.target_id >= osm_max_targets || 563252867Sdelphij (ccb->ccb_h.flags & CAM_CDB_PHYS)) 564252867Sdelphij { 565252867Sdelphij ccb->ccb_h.status = CAM_TID_INVALID; 566252867Sdelphij xpt_done(ccb); 567252867Sdelphij return; 568252867Sdelphij } 569252867Sdelphij 570252867Sdelphij vd = ldm_find_target(vbus, ccb->ccb_h.target_id); 571252867Sdelphij 572252867Sdelphij if (!vd) { 573252867Sdelphij ccb->ccb_h.status = CAM_TID_INVALID; 574252867Sdelphij xpt_done(ccb); 575252867Sdelphij return; 576252867Sdelphij } 577252867Sdelphij 578252867Sdelphij switch (cdb[0]) { 579252867Sdelphij case TEST_UNIT_READY: 580252867Sdelphij case START_STOP_UNIT: 581252867Sdelphij case SYNCHRONIZE_CACHE: 582252867Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 583252867Sdelphij break; 584252867Sdelphij 585252867Sdelphij case INQUIRY: 586252867Sdelphij { 587252867Sdelphij PINQUIRYDATA inquiryData; 588252867Sdelphij memset(ccb->csio.data_ptr, 0, ccb->csio.dxfer_len); 589252867Sdelphij inquiryData = (PINQUIRYDATA)ccb->csio.data_ptr; 590252867Sdelphij 591252867Sdelphij inquiryData->AdditionalLength = 31; 592252867Sdelphij inquiryData->CommandQueue = 1; 593252867Sdelphij memcpy(&inquiryData->VendorId, "HPT ", 8); 594252867Sdelphij memcpy(&inquiryData->ProductId, "DISK 0_0 ", 16); 595252867Sdelphij 596252867Sdelphij if (vd->target_id / 10) { 597252867Sdelphij inquiryData->ProductId[7] = (vd->target_id % 100) / 10 + '0'; 598252867Sdelphij inquiryData->ProductId[8] = (vd->target_id % 100) % 10 + '0'; 599252867Sdelphij } 600252867Sdelphij else 601252867Sdelphij inquiryData->ProductId[7] = (vd->target_id % 100) % 10 + '0'; 602252867Sdelphij 603252867Sdelphij memcpy(&inquiryData->ProductRevisionLevel, "4.00", 4); 604252867Sdelphij 605252867Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 606252867Sdelphij } 607252867Sdelphij break; 608252867Sdelphij 609252867Sdelphij case READ_CAPACITY: 610252867Sdelphij { 611252867Sdelphij HPT_U8 *rbuf = ccb->csio.data_ptr; 612252867Sdelphij HPT_U32 cap; 613252867Sdelphij 614252867Sdelphij if (vd->capacity>0xfffffffful) 615252867Sdelphij cap = 0xfffffffful; 616252867Sdelphij else 617252867Sdelphij cap = vd->capacity - 1; 618252867Sdelphij 619252867Sdelphij rbuf[0] = (HPT_U8)(cap>>24); 620252867Sdelphij rbuf[1] = (HPT_U8)(cap>>16); 621252867Sdelphij rbuf[2] = (HPT_U8)(cap>>8); 622252867Sdelphij rbuf[3] = (HPT_U8)cap; 623252867Sdelphij rbuf[4] = 0; 624252867Sdelphij rbuf[5] = 0; 625252867Sdelphij rbuf[6] = 2; 626252867Sdelphij rbuf[7] = 0; 627252867Sdelphij 628252867Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 629252867Sdelphij break; 630252867Sdelphij } 631252867Sdelphij 632252867Sdelphij case SERVICE_ACTION_IN: 633252867Sdelphij { 634252867Sdelphij HPT_U8 *rbuf = ccb->csio.data_ptr; 635252867Sdelphij HPT_U64 cap = vd->capacity - 1; 636252867Sdelphij 637252867Sdelphij rbuf[0] = (HPT_U8)(cap>>56); 638252867Sdelphij rbuf[1] = (HPT_U8)(cap>>48); 639252867Sdelphij rbuf[2] = (HPT_U8)(cap>>40); 640252867Sdelphij rbuf[3] = (HPT_U8)(cap>>32); 641252867Sdelphij rbuf[4] = (HPT_U8)(cap>>24); 642252867Sdelphij rbuf[5] = (HPT_U8)(cap>>16); 643252867Sdelphij rbuf[6] = (HPT_U8)(cap>>8); 644252867Sdelphij rbuf[7] = (HPT_U8)cap; 645252867Sdelphij rbuf[8] = 0; 646252867Sdelphij rbuf[9] = 0; 647252867Sdelphij rbuf[10] = 2; 648252867Sdelphij rbuf[11] = 0; 649252867Sdelphij 650252867Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 651252867Sdelphij break; 652252867Sdelphij } 653252867Sdelphij 654252867Sdelphij case READ_6: 655252867Sdelphij case READ_10: 656252867Sdelphij case READ_16: 657252867Sdelphij case WRITE_6: 658252867Sdelphij case WRITE_10: 659252867Sdelphij case WRITE_16: 660252867Sdelphij case 0x13: 661252867Sdelphij case 0x2f: 662252867Sdelphij case 0x8f: /* VERIFY_16 */ 663252867Sdelphij { 664252867Sdelphij pCmd = ldm_alloc_cmds(vbus, vd->cmds_per_request); 665252867Sdelphij if(!pCmd){ 666252867Sdelphij KdPrint(("Failed to allocate command!")); 667252867Sdelphij ccb->ccb_h.status = CAM_BUSY; 668252867Sdelphij break; 669252867Sdelphij } 670252867Sdelphij 671252867Sdelphij switch (cdb[0]) { 672252867Sdelphij case READ_6: 673252867Sdelphij case WRITE_6: 674252867Sdelphij case 0x13: 675252867Sdelphij pCmd->uCmd.Ide.Lba = ((HPT_U32)cdb[1] << 16) | ((HPT_U32)cdb[2] << 8) | (HPT_U32)cdb[3]; 676252867Sdelphij pCmd->uCmd.Ide.nSectors = (HPT_U16) cdb[4]; 677252867Sdelphij break; 678252867Sdelphij case READ_16: 679252867Sdelphij case WRITE_16: 680252867Sdelphij case 0x8f: /* VERIFY_16 */ 681252867Sdelphij { 682252867Sdelphij HPT_U64 block = 683252867Sdelphij ((HPT_U64)cdb[2]<<56) | 684252867Sdelphij ((HPT_U64)cdb[3]<<48) | 685252867Sdelphij ((HPT_U64)cdb[4]<<40) | 686252867Sdelphij ((HPT_U64)cdb[5]<<32) | 687252867Sdelphij ((HPT_U64)cdb[6]<<24) | 688252867Sdelphij ((HPT_U64)cdb[7]<<16) | 689252867Sdelphij ((HPT_U64)cdb[8]<<8) | 690252867Sdelphij ((HPT_U64)cdb[9]); 691252867Sdelphij pCmd->uCmd.Ide.Lba = block; 692252867Sdelphij pCmd->uCmd.Ide.nSectors = (HPT_U16)cdb[13] | ((HPT_U16)cdb[12]<<8); 693252867Sdelphij break; 694252867Sdelphij } 695252867Sdelphij 696252867Sdelphij default: 697252867Sdelphij pCmd->uCmd.Ide.Lba = (HPT_U32)cdb[5] | ((HPT_U32)cdb[4] << 8) | ((HPT_U32)cdb[3] << 16) | ((HPT_U32)cdb[2] << 24); 698252867Sdelphij pCmd->uCmd.Ide.nSectors = (HPT_U16) cdb[8] | ((HPT_U16)cdb[7]<<8); 699252867Sdelphij break; 700252867Sdelphij } 701252867Sdelphij 702252867Sdelphij switch (cdb[0]) { 703252867Sdelphij case READ_6: 704252867Sdelphij case READ_10: 705252867Sdelphij case READ_16: 706252867Sdelphij pCmd->flags.data_in = 1; 707252867Sdelphij break; 708252867Sdelphij case WRITE_6: 709252867Sdelphij case WRITE_10: 710252867Sdelphij case WRITE_16: 711252867Sdelphij pCmd->flags.data_out = 1; 712252867Sdelphij break; 713252867Sdelphij } 714252867Sdelphij pCmd->priv = ext = cmdext_get(vbus_ext); 715252867Sdelphij HPT_ASSERT(ext); 716252867Sdelphij ext->ccb = ccb; 717252867Sdelphij pCmd->target = vd; 718252867Sdelphij pCmd->done = os_cmddone; 719252867Sdelphij pCmd->buildsgl = os_buildsgl; 720252903Sdelphij 721252867Sdelphij pCmd->psg = ext->psg; 722252903Sdelphij 723252903Sdelphij if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { 724252903Sdelphij int idx; 725252903Sdelphij bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr; 726252903Sdelphij 727252903Sdelphij if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) 728252903Sdelphij pCmd->flags.physical_sg = 1; 729252903Sdelphij 730252903Sdelphij for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) { 731252903Sdelphij pCmd->psg[idx].addr.bus = sgList[idx].ds_addr; 732252903Sdelphij pCmd->psg[idx].size = sgList[idx].ds_len; 733252903Sdelphij pCmd->psg[idx].eot = (idx==ccb->csio.sglist_cnt-1)? 1 : 0; 734252903Sdelphij } 735252903Sdelphij 736252903Sdelphij ccb->ccb_h.timeout_ch = timeout(hpt_timeout, pCmd, HPT_OSM_TIMEOUT); 737252903Sdelphij ldm_queue_cmd(pCmd); 738252903Sdelphij } 739252903Sdelphij else { 740252903Sdelphij int error; 741252903Sdelphij pCmd->flags.physical_sg = 1; 742252903Sdelphij error = bus_dmamap_load(vbus_ext->io_dmat, 743252903Sdelphij ext->dma_map, 744252903Sdelphij ccb->csio.data_ptr, ccb->csio.dxfer_len, 745252903Sdelphij hpt_io_dmamap_callback, pCmd, 746252867Sdelphij BUS_DMA_WAITOK 747252867Sdelphij ); 748252903Sdelphij KdPrint(("bus_dmamap_load return %d", error)); 749252903Sdelphij if (error && error!=EINPROGRESS) { 750252903Sdelphij os_printk("bus_dmamap_load error %d", error); 751252903Sdelphij cmdext_put(ext); 752252903Sdelphij ldm_free_cmds(pCmd); 753252903Sdelphij ccb->ccb_h.status = CAM_REQ_CMP_ERR; 754252903Sdelphij xpt_done(ccb); 755252903Sdelphij } 756252867Sdelphij } 757252867Sdelphij return; 758252867Sdelphij } 759252867Sdelphij 760252867Sdelphij default: 761252867Sdelphij ccb->ccb_h.status = CAM_REQ_INVALID; 762252867Sdelphij break; 763252867Sdelphij } 764252867Sdelphij 765252867Sdelphij xpt_done(ccb); 766252867Sdelphij return; 767252867Sdelphij} 768252867Sdelphij 769252867Sdelphijstatic void hpt_action(struct cam_sim *sim, union ccb *ccb) 770252867Sdelphij{ 771252867Sdelphij PVBUS_EXT vbus_ext = (PVBUS_EXT)cam_sim_softc(sim); 772252867Sdelphij 773252867Sdelphij KdPrint(("hpt_action(fn=%d, id=%d)", ccb->ccb_h.func_code, ccb->ccb_h.target_id)); 774252867Sdelphij 775252867Sdelphij switch (ccb->ccb_h.func_code) { 776252867Sdelphij 777252867Sdelphij case XPT_SCSI_IO: 778252867Sdelphij hpt_lock_vbus(vbus_ext); 779252867Sdelphij hpt_scsi_io(vbus_ext, ccb); 780252867Sdelphij hpt_unlock_vbus(vbus_ext); 781252867Sdelphij return; 782252867Sdelphij 783252867Sdelphij case XPT_RESET_BUS: 784252867Sdelphij hpt_lock_vbus(vbus_ext); 785252867Sdelphij ldm_reset_vbus((PVBUS)vbus_ext->vbus); 786252867Sdelphij hpt_unlock_vbus(vbus_ext); 787252867Sdelphij break; 788252867Sdelphij 789252867Sdelphij case XPT_GET_TRAN_SETTINGS: 790252867Sdelphij case XPT_SET_TRAN_SETTINGS: 791252867Sdelphij ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 792252867Sdelphij break; 793252867Sdelphij 794252867Sdelphij case XPT_CALC_GEOMETRY: 795252867Sdelphij ccb->ccg.heads = 255; 796252867Sdelphij ccb->ccg.secs_per_track = 63; 797252867Sdelphij ccb->ccg.cylinders = ccb->ccg.volume_size / (ccb->ccg.heads * ccb->ccg.secs_per_track); 798252867Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 799252867Sdelphij break; 800252867Sdelphij 801252867Sdelphij case XPT_PATH_INQ: 802252867Sdelphij { 803252867Sdelphij struct ccb_pathinq *cpi = &ccb->cpi; 804252867Sdelphij 805252867Sdelphij cpi->version_num = 1; 806252867Sdelphij cpi->hba_inquiry = PI_SDTR_ABLE; 807252867Sdelphij cpi->target_sprt = 0; 808252867Sdelphij cpi->hba_misc = PIM_NOBUSRESET; 809252867Sdelphij cpi->hba_eng_cnt = 0; 810252867Sdelphij cpi->max_target = osm_max_targets; 811252867Sdelphij cpi->max_lun = 0; 812252867Sdelphij cpi->unit_number = cam_sim_unit(sim); 813252867Sdelphij cpi->bus_id = cam_sim_bus(sim); 814252867Sdelphij cpi->initiator_id = osm_max_targets; 815252867Sdelphij cpi->base_transfer_speed = 3300; 816252867Sdelphij 817252867Sdelphij strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 818252867Sdelphij strncpy(cpi->hba_vid, "HPT ", HBA_IDLEN); 819252867Sdelphij strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 820252867Sdelphij#if (__FreeBSD_version >= 800000) 821252867Sdelphij cpi->transport = XPORT_SPI; 822252867Sdelphij cpi->transport_version = 2; 823252867Sdelphij cpi->protocol = PROTO_SCSI; 824252867Sdelphij cpi->protocol_version = SCSI_REV_2; 825252867Sdelphij#endif 826252867Sdelphij cpi->ccb_h.status = CAM_REQ_CMP; 827252867Sdelphij break; 828252867Sdelphij } 829252867Sdelphij 830252867Sdelphij default: 831252867Sdelphij ccb->ccb_h.status = CAM_REQ_INVALID; 832252867Sdelphij break; 833252867Sdelphij } 834252867Sdelphij 835252867Sdelphij xpt_done(ccb); 836252867Sdelphij return; 837252867Sdelphij} 838252867Sdelphij 839252867Sdelphijstatic void hpt_pci_intr(void *arg) 840252867Sdelphij{ 841252867Sdelphij PVBUS_EXT vbus_ext = (PVBUS_EXT)arg; 842252867Sdelphij hpt_lock_vbus(vbus_ext); 843252867Sdelphij ldm_intr((PVBUS)vbus_ext->vbus); 844252867Sdelphij hpt_unlock_vbus(vbus_ext); 845252867Sdelphij} 846252867Sdelphij 847252867Sdelphijstatic void hpt_poll(struct cam_sim *sim) 848252867Sdelphij{ 849252867Sdelphij hpt_pci_intr(cam_sim_softc(sim)); 850252867Sdelphij} 851252867Sdelphij 852252867Sdelphijstatic void hpt_async(void * callback_arg, u_int32_t code, struct cam_path * path, void * arg) 853252867Sdelphij{ 854252867Sdelphij KdPrint(("hpt_async")); 855252867Sdelphij} 856252867Sdelphij 857252867Sdelphijstatic int hpt_shutdown(device_t dev) 858252867Sdelphij{ 859252867Sdelphij KdPrint(("hpt_shutdown(dev=%p)", dev)); 860252867Sdelphij return 0; 861252867Sdelphij} 862252867Sdelphij 863252867Sdelphijstatic int hpt_detach(device_t dev) 864252867Sdelphij{ 865252867Sdelphij /* we don't allow the driver to be unloaded. */ 866252867Sdelphij return EBUSY; 867252867Sdelphij} 868252867Sdelphij 869252867Sdelphijstatic void hpt_ioctl_done(struct _IOCTL_ARG *arg) 870252867Sdelphij{ 871252867Sdelphij arg->ioctl_cmnd = 0; 872252867Sdelphij wakeup(arg); 873252867Sdelphij} 874252867Sdelphij 875252867Sdelphijstatic void __hpt_do_ioctl(PVBUS_EXT vbus_ext, IOCTL_ARG *ioctl_args) 876252867Sdelphij{ 877252867Sdelphij ioctl_args->result = -1; 878252867Sdelphij ioctl_args->done = hpt_ioctl_done; 879252867Sdelphij ioctl_args->ioctl_cmnd = (void *)1; 880252867Sdelphij 881252867Sdelphij hpt_lock_vbus(vbus_ext); 882252867Sdelphij ldm_ioctl((PVBUS)vbus_ext->vbus, ioctl_args); 883252867Sdelphij 884252867Sdelphij while (ioctl_args->ioctl_cmnd) { 885252867Sdelphij if (hpt_sleep(vbus_ext, ioctl_args, PPAUSE, "hptctl", HPT_OSM_TIMEOUT)==0) 886252867Sdelphij break; 887252867Sdelphij ldm_reset_vbus((PVBUS)vbus_ext->vbus); 888252867Sdelphij __hpt_do_tasks(vbus_ext); 889252867Sdelphij } 890252867Sdelphij 891252867Sdelphij /* KdPrint(("ioctl %x result %d", ioctl_args->dwIoControlCode, ioctl_args->result)); */ 892252867Sdelphij 893252867Sdelphij hpt_unlock_vbus(vbus_ext); 894252867Sdelphij} 895252867Sdelphij 896252867Sdelphijstatic void hpt_do_ioctl(IOCTL_ARG *ioctl_args) 897252867Sdelphij{ 898252867Sdelphij PVBUS vbus; 899252867Sdelphij PVBUS_EXT vbus_ext; 900252867Sdelphij 901252867Sdelphij ldm_for_each_vbus(vbus, vbus_ext) { 902252867Sdelphij __hpt_do_ioctl(vbus_ext, ioctl_args); 903252867Sdelphij if (ioctl_args->result!=HPT_IOCTL_RESULT_WRONG_VBUS) 904252867Sdelphij return; 905252867Sdelphij } 906252867Sdelphij} 907252867Sdelphij 908252867Sdelphij#define HPT_DO_IOCTL(code, inbuf, insize, outbuf, outsize) ({\ 909252867Sdelphij IOCTL_ARG arg;\ 910252867Sdelphij arg.dwIoControlCode = code;\ 911252867Sdelphij arg.lpInBuffer = inbuf;\ 912252867Sdelphij arg.lpOutBuffer = outbuf;\ 913252867Sdelphij arg.nInBufferSize = insize;\ 914252867Sdelphij arg.nOutBufferSize = outsize;\ 915252867Sdelphij arg.lpBytesReturned = 0;\ 916252867Sdelphij hpt_do_ioctl(&arg);\ 917252867Sdelphij arg.result;\ 918252867Sdelphij}) 919252867Sdelphij 920252867Sdelphij#define DEVICEID_VALID(id) ((id) && ((HPT_U32)(id)!=0xffffffff)) 921252867Sdelphij 922252867Sdelphijstatic int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount) 923252867Sdelphij{ 924252867Sdelphij int i; 925252867Sdelphij HPT_U32 count = nMaxCount-1; 926252867Sdelphij 927252867Sdelphij if (HPT_DO_IOCTL(HPT_IOCTL_GET_LOGICAL_DEVICES, 928252867Sdelphij &count, sizeof(HPT_U32), pIds, sizeof(DEVICEID)*nMaxCount)) 929252867Sdelphij return -1; 930252867Sdelphij 931252867Sdelphij nMaxCount = (int)pIds[0]; 932252867Sdelphij for (i=0; i<nMaxCount; i++) pIds[i] = pIds[i+1]; 933252867Sdelphij return nMaxCount; 934252867Sdelphij} 935252867Sdelphij 936252867Sdelphijstatic int hpt_get_device_info_v3(DEVICEID id, PLOGICAL_DEVICE_INFO_V3 pInfo) 937252867Sdelphij{ 938252867Sdelphij return HPT_DO_IOCTL(HPT_IOCTL_GET_DEVICE_INFO_V3, 939252867Sdelphij &id, sizeof(DEVICEID), pInfo, sizeof(LOGICAL_DEVICE_INFO_V3)); 940252867Sdelphij} 941252867Sdelphij 942252867Sdelphij/* not belong to this file logically, but we want to use ioctl interface */ 943252867Sdelphijstatic int __hpt_stop_tasks(PVBUS_EXT vbus_ext, DEVICEID id) 944252867Sdelphij{ 945252867Sdelphij LOGICAL_DEVICE_INFO_V3 devinfo; 946252867Sdelphij int i, result; 947252867Sdelphij DEVICEID param[2] = { id, 0 }; 948252867Sdelphij 949252867Sdelphij if (hpt_get_device_info_v3(id, &devinfo)) 950252867Sdelphij return -1; 951252867Sdelphij 952252867Sdelphij if (devinfo.Type!=LDT_ARRAY) 953252867Sdelphij return -1; 954252867Sdelphij 955252867Sdelphij if (devinfo.u.array.Flags & ARRAY_FLAG_REBUILDING) 956252867Sdelphij param[1] = AS_REBUILD_ABORT; 957252867Sdelphij else if (devinfo.u.array.Flags & ARRAY_FLAG_VERIFYING) 958252867Sdelphij param[1] = AS_VERIFY_ABORT; 959252867Sdelphij else if (devinfo.u.array.Flags & ARRAY_FLAG_INITIALIZING) 960252867Sdelphij param[1] = AS_INITIALIZE_ABORT; 961252867Sdelphij else if (devinfo.u.array.Flags & ARRAY_FLAG_TRANSFORMING) 962252867Sdelphij param[1] = AS_TRANSFORM_ABORT; 963252867Sdelphij else 964252867Sdelphij return -1; 965252867Sdelphij 966252867Sdelphij KdPrint(("SET_ARRAY_STATE(%x, %d)", param[0], param[1])); 967252867Sdelphij result = HPT_DO_IOCTL(HPT_IOCTL_SET_ARRAY_STATE, 968252867Sdelphij param, sizeof(param), 0, 0); 969252867Sdelphij 970252867Sdelphij for (i=0; i<devinfo.u.array.nDisk; i++) 971252867Sdelphij if (DEVICEID_VALID(devinfo.u.array.Members[i])) 972252867Sdelphij __hpt_stop_tasks(vbus_ext, devinfo.u.array.Members[i]); 973252867Sdelphij 974252867Sdelphij return result; 975252867Sdelphij} 976252867Sdelphij 977252867Sdelphijstatic void hpt_stop_tasks(PVBUS_EXT vbus_ext) 978252867Sdelphij{ 979252867Sdelphij DEVICEID ids[32]; 980252867Sdelphij int i, count; 981252867Sdelphij 982252867Sdelphij count = hpt_get_logical_devices((DEVICEID *)&ids, sizeof(ids)/sizeof(ids[0])); 983252867Sdelphij 984252867Sdelphij for (i=0; i<count; i++) 985252867Sdelphij __hpt_stop_tasks(vbus_ext, ids[i]); 986252867Sdelphij} 987252867Sdelphij 988252867Sdelphijstatic d_open_t hpt_open; 989252867Sdelphijstatic d_close_t hpt_close; 990252867Sdelphijstatic d_ioctl_t hpt_ioctl; 991252867Sdelphijstatic int hpt_rescan_bus(void); 992252867Sdelphij 993252867Sdelphijstatic struct cdevsw hpt_cdevsw = { 994252867Sdelphij .d_open = hpt_open, 995252867Sdelphij .d_close = hpt_close, 996252867Sdelphij .d_ioctl = hpt_ioctl, 997252867Sdelphij .d_name = driver_name, 998252867Sdelphij#if __FreeBSD_version>=503000 999252867Sdelphij .d_version = D_VERSION, 1000252867Sdelphij#endif 1001252867Sdelphij#if (__FreeBSD_version>=503000 && __FreeBSD_version<600034) 1002252867Sdelphij .d_flags = D_NEEDGIANT, 1003252867Sdelphij#endif 1004252867Sdelphij#if __FreeBSD_version<600034 1005252867Sdelphij#if __FreeBSD_version>501000 1006252867Sdelphij .d_maj = MAJOR_AUTO, 1007252867Sdelphij#else 1008252867Sdelphij .d_maj = HPT_DEV_MAJOR, 1009252867Sdelphij#endif 1010252867Sdelphij#endif 1011252867Sdelphij}; 1012252867Sdelphij 1013252867Sdelphijstatic struct intr_config_hook hpt_ich; 1014252867Sdelphij 1015252867Sdelphij/* 1016252867Sdelphij * hpt_final_init will be called after all hpt_attach. 1017252867Sdelphij */ 1018252867Sdelphijstatic void hpt_final_init(void *dummy) 1019252867Sdelphij{ 1020252867Sdelphij int i,unit_number=0; 1021252867Sdelphij PVBUS_EXT vbus_ext; 1022252867Sdelphij PVBUS vbus; 1023252867Sdelphij PHBA hba; 1024252867Sdelphij 1025252867Sdelphij /* Clear the config hook */ 1026252867Sdelphij config_intrhook_disestablish(&hpt_ich); 1027252867Sdelphij 1028252867Sdelphij /* allocate memory */ 1029252867Sdelphij i = 0; 1030252867Sdelphij ldm_for_each_vbus(vbus, vbus_ext) { 1031252867Sdelphij if (hpt_alloc_mem(vbus_ext)) { 1032252867Sdelphij os_printk("out of memory"); 1033252867Sdelphij return; 1034252867Sdelphij } 1035252867Sdelphij i++; 1036252867Sdelphij } 1037252867Sdelphij 1038252867Sdelphij if (!i) { 1039252867Sdelphij if (bootverbose) 1040252867Sdelphij os_printk("no controller detected."); 1041252867Sdelphij return; 1042252867Sdelphij } 1043252867Sdelphij 1044252867Sdelphij /* initializing hardware */ 1045252867Sdelphij ldm_for_each_vbus(vbus, vbus_ext) { 1046252867Sdelphij /* make timer available here */ 1047252867Sdelphij callout_handle_init(&vbus_ext->timer); 1048252867Sdelphij if (hpt_init_vbus(vbus_ext)) { 1049252867Sdelphij os_printk("fail to initialize hardware"); 1050252867Sdelphij break; /* FIXME */ 1051252867Sdelphij } 1052252867Sdelphij } 1053252867Sdelphij 1054252867Sdelphij /* register CAM interface */ 1055252867Sdelphij ldm_for_each_vbus(vbus, vbus_ext) { 1056252867Sdelphij struct cam_devq *devq; 1057252867Sdelphij struct ccb_setasync ccb; 1058252867Sdelphij 1059252867Sdelphij#if (__FreeBSD_version >= 500000) 1060252867Sdelphij mtx_init(&vbus_ext->lock, "hptsleeplock", NULL, MTX_DEF); 1061252867Sdelphij#endif 1062252867Sdelphij if (bus_dma_tag_create(NULL,/* parent */ 1063252867Sdelphij 4, /* alignment */ 1064252867Sdelphij BUS_SPACE_MAXADDR_32BIT+1, /* boundary */ 1065252867Sdelphij BUS_SPACE_MAXADDR, /* lowaddr */ 1066252867Sdelphij BUS_SPACE_MAXADDR, /* highaddr */ 1067252867Sdelphij NULL, NULL, /* filter, filterarg */ 1068252867Sdelphij PAGE_SIZE * (os_max_sg_descriptors-1), /* maxsize */ 1069252867Sdelphij os_max_sg_descriptors, /* nsegments */ 1070252867Sdelphij 0x10000, /* maxsegsize */ 1071252867Sdelphij BUS_DMA_WAITOK, /* flags */ 1072252867Sdelphij#if __FreeBSD_version>502000 1073252867Sdelphij busdma_lock_mutex, /* lockfunc */ 1074252867Sdelphij &vbus_ext->lock, /* lockfuncarg */ 1075252867Sdelphij#endif 1076252867Sdelphij &vbus_ext->io_dmat /* tag */)) 1077252867Sdelphij { 1078252867Sdelphij return ; 1079252867Sdelphij } 1080252867Sdelphij 1081252867Sdelphij for (i=0; i<os_max_queue_comm; i++) { 1082252867Sdelphij POS_CMDEXT ext = (POS_CMDEXT)malloc(sizeof(OS_CMDEXT), M_DEVBUF, M_WAITOK); 1083252867Sdelphij if (!ext) { 1084252867Sdelphij os_printk("Can't alloc cmdext(%d)", i); 1085252867Sdelphij return ; 1086252867Sdelphij } 1087252867Sdelphij ext->vbus_ext = vbus_ext; 1088252867Sdelphij ext->next = vbus_ext->cmdext_list; 1089252867Sdelphij vbus_ext->cmdext_list = ext; 1090252867Sdelphij 1091252867Sdelphij if (bus_dmamap_create(vbus_ext->io_dmat, 0, &ext->dma_map)) { 1092252867Sdelphij os_printk("Can't create dma map(%d)", i); 1093252867Sdelphij return ; 1094252867Sdelphij } 1095252867Sdelphij } 1096252867Sdelphij 1097252867Sdelphij if ((devq = cam_simq_alloc(os_max_queue_comm)) == NULL) { 1098252867Sdelphij os_printk("cam_simq_alloc failed"); 1099252867Sdelphij return ; 1100252867Sdelphij } 1101252867Sdelphij 1102252867Sdelphij#if __FreeBSD_version > 700025 1103252867Sdelphij vbus_ext->sim = cam_sim_alloc(hpt_action, hpt_poll, driver_name, 1104252867Sdelphij vbus_ext, unit_number, &Giant, os_max_queue_comm, /*tagged*/8, devq); 1105252867Sdelphij#else 1106252867Sdelphij vbus_ext->sim = cam_sim_alloc(hpt_action, hpt_poll, driver_name, 1107252867Sdelphij vbus_ext, unit_number, os_max_queue_comm, /*tagged*/8, devq); 1108252867Sdelphij#endif 1109252867Sdelphij unit_number++; 1110252867Sdelphij if (!vbus_ext->sim) { 1111252867Sdelphij os_printk("cam_sim_alloc failed"); 1112252867Sdelphij cam_simq_free(devq); 1113252867Sdelphij return ; 1114252867Sdelphij } 1115252867Sdelphij 1116252867Sdelphij#if __FreeBSD_version > 700044 1117252867Sdelphij if (xpt_bus_register(vbus_ext->sim, NULL, 0) != CAM_SUCCESS) { 1118252867Sdelphij#else 1119252867Sdelphij if (xpt_bus_register(vbus_ext->sim, 0) != CAM_SUCCESS) { 1120252867Sdelphij#endif 1121252867Sdelphij os_printk("xpt_bus_register failed"); 1122252867Sdelphij cam_sim_free(vbus_ext->sim, /*free devq*/ TRUE); 1123252867Sdelphij vbus_ext->sim = NULL; 1124252867Sdelphij return ; 1125252867Sdelphij } 1126252867Sdelphij 1127252903Sdelphij if (xpt_create_path(&vbus_ext->path, /*periph */ xpt_periph, 1128252867Sdelphij cam_sim_path(vbus_ext->sim), CAM_TARGET_WILDCARD, 1129252867Sdelphij CAM_LUN_WILDCARD) != CAM_REQ_CMP) 1130252867Sdelphij { 1131252867Sdelphij os_printk("xpt_create_path failed"); 1132252867Sdelphij xpt_bus_deregister(cam_sim_path(vbus_ext->sim)); 1133252867Sdelphij cam_sim_free(vbus_ext->sim, /*free_devq*/TRUE); 1134252867Sdelphij vbus_ext->sim = NULL; 1135252867Sdelphij return ; 1136252867Sdelphij } 1137252867Sdelphij 1138252867Sdelphij xpt_setup_ccb(&ccb.ccb_h, vbus_ext->path, /*priority*/5); 1139252867Sdelphij ccb.ccb_h.func_code = XPT_SASYNC_CB; 1140252867Sdelphij ccb.event_enable = AC_LOST_DEVICE; 1141252867Sdelphij ccb.callback = hpt_async; 1142252867Sdelphij ccb.callback_arg = vbus_ext; 1143252867Sdelphij xpt_action((union ccb *)&ccb); 1144252867Sdelphij 1145252867Sdelphij for (hba = vbus_ext->hba_list; hba; hba = hba->next) { 1146252867Sdelphij int rid = 0; 1147252867Sdelphij if ((hba->irq_res = bus_alloc_resource(hba->pcidev, 1148252867Sdelphij SYS_RES_IRQ, &rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) 1149252867Sdelphij { 1150252867Sdelphij os_printk("can't allocate interrupt"); 1151252867Sdelphij return ; 1152252867Sdelphij } 1153252867Sdelphij 1154252867Sdelphij if (bus_setup_intr(hba->pcidev, hba->irq_res, INTR_TYPE_CAM, 1155252867Sdelphij#if __FreeBSD_version > 700025 1156252867Sdelphij NULL, hpt_pci_intr, vbus_ext, &hba->irq_handle)) 1157252867Sdelphij#else 1158252867Sdelphij hpt_pci_intr, vbus_ext, &hba->irq_handle)) 1159252867Sdelphij#endif 1160252867Sdelphij { 1161252867Sdelphij os_printk("can't set up interrupt"); 1162252867Sdelphij return ; 1163252867Sdelphij } 1164252867Sdelphij hba->ldm_adapter.him->intr_control(hba->ldm_adapter.him_handle, HPT_TRUE); 1165252867Sdelphij 1166252867Sdelphij } 1167252867Sdelphij 1168252867Sdelphij vbus_ext->shutdown_eh = EVENTHANDLER_REGISTER(shutdown_final, 1169252867Sdelphij hpt_shutdown_vbus, vbus_ext, SHUTDOWN_PRI_DEFAULT); 1170252867Sdelphij if (!vbus_ext->shutdown_eh) 1171252867Sdelphij os_printk("Shutdown event registration failed"); 1172252867Sdelphij } 1173252867Sdelphij 1174252867Sdelphij ldm_for_each_vbus(vbus, vbus_ext) { 1175252867Sdelphij TASK_INIT(&vbus_ext->worker, 0, (task_fn_t *)hpt_do_tasks, vbus_ext); 1176252867Sdelphij if (vbus_ext->tasks) 1177252867Sdelphij TASK_ENQUEUE(&vbus_ext->worker); 1178252867Sdelphij } 1179252867Sdelphij 1180252867Sdelphij make_dev(&hpt_cdevsw, DRIVER_MINOR, UID_ROOT, GID_OPERATOR, 1181252867Sdelphij S_IRUSR | S_IWUSR, "%s", driver_name); 1182252867Sdelphij} 1183252867Sdelphij 1184252867Sdelphij#if defined(KLD_MODULE) && (__FreeBSD_version >= 503000) 1185252867Sdelphij 1186252867Sdelphijtypedef struct driverlink *driverlink_t; 1187252867Sdelphijstruct driverlink { 1188252867Sdelphij kobj_class_t driver; 1189252867Sdelphij TAILQ_ENTRY(driverlink) link; /* list of drivers in devclass */ 1190252867Sdelphij}; 1191252867Sdelphij 1192252867Sdelphijtypedef TAILQ_HEAD(driver_list, driverlink) driver_list_t; 1193252867Sdelphij 1194252867Sdelphijstruct devclass { 1195252867Sdelphij TAILQ_ENTRY(devclass) link; 1196252867Sdelphij devclass_t parent; /* parent in devclass hierarchy */ 1197252867Sdelphij driver_list_t drivers; /* bus devclasses store drivers for bus */ 1198252867Sdelphij char *name; 1199252867Sdelphij device_t *devices; /* array of devices indexed by unit */ 1200252867Sdelphij int maxunit; /* size of devices array */ 1201252867Sdelphij}; 1202252867Sdelphij 1203252867Sdelphijstatic void override_kernel_driver(void) 1204252867Sdelphij{ 1205252867Sdelphij driverlink_t dl, dlfirst; 1206252867Sdelphij driver_t *tmpdriver; 1207252867Sdelphij devclass_t dc = devclass_find("pci"); 1208252867Sdelphij 1209252867Sdelphij if (dc){ 1210252867Sdelphij dlfirst = TAILQ_FIRST(&dc->drivers); 1211252867Sdelphij for (dl = dlfirst; dl; dl = TAILQ_NEXT(dl, link)) { 1212252867Sdelphij if(strcmp(dl->driver->name, driver_name) == 0) { 1213252867Sdelphij tmpdriver=dl->driver; 1214252867Sdelphij dl->driver=dlfirst->driver; 1215252867Sdelphij dlfirst->driver=tmpdriver; 1216252867Sdelphij break; 1217252867Sdelphij } 1218252867Sdelphij } 1219252867Sdelphij } 1220252867Sdelphij} 1221252867Sdelphij 1222252867Sdelphij#else 1223252867Sdelphij#define override_kernel_driver() 1224252867Sdelphij#endif 1225252867Sdelphij 1226252867Sdelphijstatic void hpt_init(void *dummy) 1227252867Sdelphij{ 1228252867Sdelphij if (bootverbose) 1229252867Sdelphij os_printk("%s %s", driver_name_long, driver_ver); 1230252867Sdelphij 1231252867Sdelphij override_kernel_driver(); 1232252867Sdelphij init_config(); 1233252867Sdelphij 1234252867Sdelphij hpt_ich.ich_func = hpt_final_init; 1235252867Sdelphij hpt_ich.ich_arg = NULL; 1236252867Sdelphij if (config_intrhook_establish(&hpt_ich) != 0) { 1237252867Sdelphij printf("%s: cannot establish configuration hook\n", 1238252867Sdelphij driver_name_long); 1239252867Sdelphij } 1240252867Sdelphij 1241252867Sdelphij} 1242252867SdelphijSYSINIT(hptinit, SI_SUB_CONFIGURE, SI_ORDER_FIRST, hpt_init, NULL); 1243252867Sdelphij 1244252867Sdelphij/* 1245252867Sdelphij * CAM driver interface 1246252867Sdelphij */ 1247252867Sdelphijstatic device_method_t driver_methods[] = { 1248252867Sdelphij /* Device interface */ 1249252867Sdelphij DEVMETHOD(device_probe, hpt_probe), 1250252867Sdelphij DEVMETHOD(device_attach, hpt_attach), 1251252867Sdelphij DEVMETHOD(device_detach, hpt_detach), 1252252867Sdelphij DEVMETHOD(device_shutdown, hpt_shutdown), 1253252867Sdelphij { 0, 0 } 1254252867Sdelphij}; 1255252867Sdelphij 1256252867Sdelphijstatic driver_t hpt_pci_driver = { 1257252867Sdelphij driver_name, 1258252867Sdelphij driver_methods, 1259252867Sdelphij sizeof(HBA) 1260252867Sdelphij}; 1261252867Sdelphij 1262252867Sdelphijstatic devclass_t hpt_devclass; 1263252867Sdelphij 1264252867Sdelphij#ifndef TARGETNAME 1265252867Sdelphij#error "no TARGETNAME found" 1266252867Sdelphij#endif 1267252867Sdelphij 1268252867Sdelphij/* use this to make TARGETNAME be expanded */ 1269252867Sdelphij#define __DRIVER_MODULE(p1, p2, p3, p4, p5, p6) DRIVER_MODULE(p1, p2, p3, p4, p5, p6) 1270252867Sdelphij#define __MODULE_VERSION(p1, p2) MODULE_VERSION(p1, p2) 1271252867Sdelphij#define __MODULE_DEPEND(p1, p2, p3, p4, p5) MODULE_DEPEND(p1, p2, p3, p4, p5) 1272252867Sdelphij__DRIVER_MODULE(TARGETNAME, pci, hpt_pci_driver, hpt_devclass, 0, 0); 1273252867Sdelphij__MODULE_VERSION(TARGETNAME, 1); 1274252867Sdelphij__MODULE_DEPEND(TARGETNAME, cam, 1, 1, 1); 1275252867Sdelphij 1276252867Sdelphij#if __FreeBSD_version>503000 1277252867Sdelphijtypedef struct cdev * ioctl_dev_t; 1278252867Sdelphij#else 1279252867Sdelphijtypedef dev_t ioctl_dev_t; 1280252867Sdelphij#endif 1281252867Sdelphij 1282252867Sdelphij#if __FreeBSD_version >= 500000 1283252867Sdelphijtypedef struct thread * ioctl_thread_t; 1284252867Sdelphij#else 1285252867Sdelphijtypedef struct proc * ioctl_thread_t; 1286252867Sdelphij#endif 1287252867Sdelphij 1288252867Sdelphijstatic int hpt_open(ioctl_dev_t dev, int flags, int devtype, ioctl_thread_t td) 1289252867Sdelphij{ 1290252867Sdelphij return 0; 1291252867Sdelphij} 1292252867Sdelphij 1293252867Sdelphijstatic int hpt_close(ioctl_dev_t dev, int flags, int devtype, ioctl_thread_t td) 1294252867Sdelphij{ 1295252867Sdelphij return 0; 1296252867Sdelphij} 1297252867Sdelphij 1298252867Sdelphijstatic int hpt_ioctl(ioctl_dev_t dev, u_long cmd, caddr_t data, int fflag, ioctl_thread_t td) 1299252867Sdelphij{ 1300252867Sdelphij PHPT_IOCTL_PARAM piop=(PHPT_IOCTL_PARAM)data; 1301252867Sdelphij IOCTL_ARG ioctl_args; 1302252867Sdelphij HPT_U32 bytesReturned; 1303252867Sdelphij 1304252867Sdelphij switch (cmd){ 1305252867Sdelphij case HPT_DO_IOCONTROL: 1306252867Sdelphij { 1307252867Sdelphij if (piop->Magic == HPT_IOCTL_MAGIC || piop->Magic == HPT_IOCTL_MAGIC32) { 1308252867Sdelphij KdPrint(("ioctl=%x in=%p len=%d out=%p len=%d\n", 1309252867Sdelphij piop->dwIoControlCode, 1310252867Sdelphij piop->lpInBuffer, 1311252867Sdelphij piop->nInBufferSize, 1312252867Sdelphij piop->lpOutBuffer, 1313252867Sdelphij piop->nOutBufferSize)); 1314252867Sdelphij 1315252867Sdelphij memset(&ioctl_args, 0, sizeof(ioctl_args)); 1316252867Sdelphij 1317252867Sdelphij ioctl_args.dwIoControlCode = piop->dwIoControlCode; 1318252867Sdelphij ioctl_args.nInBufferSize = piop->nInBufferSize; 1319252867Sdelphij ioctl_args.nOutBufferSize = piop->nOutBufferSize; 1320252867Sdelphij ioctl_args.lpBytesReturned = &bytesReturned; 1321252867Sdelphij 1322252867Sdelphij if (ioctl_args.nInBufferSize) { 1323252867Sdelphij ioctl_args.lpInBuffer = malloc(ioctl_args.nInBufferSize, M_DEVBUF, M_WAITOK); 1324252867Sdelphij if (!ioctl_args.lpInBuffer) 1325252867Sdelphij goto invalid; 1326252867Sdelphij if (copyin((void*)piop->lpInBuffer, 1327252867Sdelphij ioctl_args.lpInBuffer, piop->nInBufferSize)) 1328252867Sdelphij goto invalid; 1329252867Sdelphij } 1330252867Sdelphij 1331252867Sdelphij if (ioctl_args.nOutBufferSize) { 1332252867Sdelphij ioctl_args.lpOutBuffer = malloc(ioctl_args.nOutBufferSize, M_DEVBUF, M_WAITOK); 1333252867Sdelphij if (!ioctl_args.lpOutBuffer) 1334252867Sdelphij goto invalid; 1335252867Sdelphij } 1336252867Sdelphij 1337252867Sdelphij#if (__FreeBSD_version >= 500000) 1338252867Sdelphij mtx_lock(&Giant); 1339252867Sdelphij#endif 1340252867Sdelphij 1341252867Sdelphij hpt_do_ioctl(&ioctl_args); 1342252867Sdelphij 1343252867Sdelphij#if (__FreeBSD_version >= 500000) 1344252867Sdelphij mtx_unlock(&Giant); 1345252867Sdelphij#endif 1346252867Sdelphij 1347252867Sdelphij if (ioctl_args.result==HPT_IOCTL_RESULT_OK) { 1348252867Sdelphij if (piop->nOutBufferSize) { 1349252867Sdelphij if (copyout(ioctl_args.lpOutBuffer, 1350252867Sdelphij (void*)piop->lpOutBuffer, piop->nOutBufferSize)) 1351252867Sdelphij goto invalid; 1352252867Sdelphij } 1353252867Sdelphij if (piop->lpBytesReturned) { 1354252867Sdelphij if (copyout(&bytesReturned, 1355252867Sdelphij (void*)piop->lpBytesReturned, sizeof(HPT_U32))) 1356252867Sdelphij goto invalid; 1357252867Sdelphij } 1358252867Sdelphij if (ioctl_args.lpInBuffer) free(ioctl_args.lpInBuffer, M_DEVBUF); 1359252867Sdelphij if (ioctl_args.lpOutBuffer) free(ioctl_args.lpOutBuffer, M_DEVBUF); 1360252867Sdelphij return 0; 1361252867Sdelphij } 1362252867Sdelphijinvalid: 1363252867Sdelphij if (ioctl_args.lpInBuffer) free(ioctl_args.lpInBuffer, M_DEVBUF); 1364252867Sdelphij if (ioctl_args.lpOutBuffer) free(ioctl_args.lpOutBuffer, M_DEVBUF); 1365252867Sdelphij return EFAULT; 1366252867Sdelphij } 1367252867Sdelphij return EFAULT; 1368252867Sdelphij } 1369252867Sdelphij 1370252867Sdelphij case HPT_SCAN_BUS: 1371252867Sdelphij { 1372252867Sdelphij return hpt_rescan_bus(); 1373252867Sdelphij } 1374252867Sdelphij default: 1375252867Sdelphij KdPrint(("invalid command!")); 1376252867Sdelphij return EFAULT; 1377252867Sdelphij } 1378252867Sdelphij 1379252867Sdelphij} 1380252867Sdelphij 1381252867Sdelphijstatic int hpt_rescan_bus(void) 1382252867Sdelphij{ 1383252867Sdelphij union ccb *ccb; 1384252867Sdelphij PVBUS vbus; 1385252867Sdelphij PVBUS_EXT vbus_ext; 1386252867Sdelphij 1387252867Sdelphij mtx_lock(&Giant); 1388252867Sdelphij 1389252867Sdelphij ldm_for_each_vbus(vbus, vbus_ext) { 1390252867Sdelphij if ((ccb = xpt_alloc_ccb()) == NULL) 1391252867Sdelphij { 1392252867Sdelphij return(ENOMEM); 1393252867Sdelphij } 1394252867Sdelphij if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(vbus_ext->sim), 1395252867Sdelphij CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) 1396252867Sdelphij { 1397252867Sdelphij xpt_free_ccb(ccb); 1398252867Sdelphij return(EIO); 1399252867Sdelphij } 1400252867Sdelphij xpt_rescan(ccb); 1401252867Sdelphij } 1402252867Sdelphij mtx_unlock(&Giant); 1403252867Sdelphij return(0); 1404252867Sdelphij} 1405