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: releng/10.3/sys/dev/hptnr/hptnr_osm_bsd.c 331987 2018-04-04 05:43:03Z gordon $ 29252867Sdelphij */ 30252867Sdelphij#include <dev/hptnr/hptnr_config.h> 31252867Sdelphij#include <dev/hptnr/os_bsd.h> 32252867Sdelphij#include <dev/hptnr/hptintf.h> 33281957Sdelphijint msi = 0; 34281957Sdelphijint debug_flag = 0; 35275980Ssmhstatic HIM *hpt_match(device_t dev) 36252867Sdelphij{ 37252867Sdelphij PCI_ID pci_id; 38252867Sdelphij HIM *him; 39252867Sdelphij int i; 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)){ 47275980Ssmh return (him); 48252867Sdelphij } 49252867Sdelphij } 50252867Sdelphij } 51252867Sdelphij 52275980Ssmh return (NULL); 53275980Ssmh} 54275980Ssmh 55275980Ssmhstatic int hpt_probe(device_t dev) 56275980Ssmh{ 57275980Ssmh HIM *him; 58275980Ssmh 59275980Ssmh him = hpt_match(dev); 60275980Ssmh if (him != NULL) { 61275980Ssmh KdPrint(("hpt_probe: adapter at PCI %d:%d:%d, IRQ %d", 62275980Ssmh pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev), pci_get_irq(dev) 63275980Ssmh )); 64275980Ssmh device_set_desc(dev, him->name); 65275980Ssmh return (BUS_PROBE_DEFAULT); 66275980Ssmh } 67275980Ssmh 68252867Sdelphij return (ENXIO); 69252867Sdelphij} 70252867Sdelphij 71252867Sdelphijstatic int hpt_attach(device_t dev) 72252867Sdelphij{ 73252867Sdelphij PHBA hba = (PHBA)device_get_softc(dev); 74275980Ssmh HIM *him; 75252867Sdelphij PCI_ID pci_id; 76252867Sdelphij HPT_UINT size; 77252867Sdelphij PVBUS vbus; 78252867Sdelphij PVBUS_EXT vbus_ext; 79252867Sdelphij 80252867Sdelphij KdPrint(("hpt_attach(%d/%d/%d)", pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev))); 81275980Ssmh 82275980Ssmh him = hpt_match(dev); 83275980Ssmh hba->ext_type = EXT_TYPE_HBA; 84275980Ssmh hba->ldm_adapter.him = him; 85275980Ssmh 86252867Sdelphij pci_enable_busmaster(dev); 87252867Sdelphij 88252867Sdelphij pci_id.vid = pci_get_vendor(dev); 89252867Sdelphij pci_id.did = pci_get_device(dev); 90252867Sdelphij pci_id.rev = pci_get_revid(dev); 91252867Sdelphij pci_id.subsys = (HPT_U32)(pci_get_subdevice(dev)) << 16 | pci_get_subvendor(dev); 92252867Sdelphij 93252867Sdelphij size = him->get_adapter_size(&pci_id); 94252867Sdelphij hba->ldm_adapter.him_handle = malloc(size, M_DEVBUF, M_WAITOK); 95252867Sdelphij 96252867Sdelphij hba->pcidev = dev; 97252867Sdelphij hba->pciaddr.tree = 0; 98252867Sdelphij hba->pciaddr.bus = pci_get_bus(dev); 99252867Sdelphij hba->pciaddr.device = pci_get_slot(dev); 100252867Sdelphij hba->pciaddr.function = pci_get_function(dev); 101252867Sdelphij 102252867Sdelphij if (!him->create_adapter(&pci_id, hba->pciaddr, hba->ldm_adapter.him_handle, hba)) { 103252867Sdelphij free(hba->ldm_adapter.him_handle, M_DEVBUF); 104275980Ssmh return ENXIO; 105252867Sdelphij } 106252867Sdelphij 107252867Sdelphij os_printk("adapter at PCI %d:%d:%d, IRQ %d", 108252867Sdelphij hba->pciaddr.bus, hba->pciaddr.device, hba->pciaddr.function, pci_get_irq(dev)); 109252867Sdelphij 110252867Sdelphij if (!ldm_register_adapter(&hba->ldm_adapter)) { 111252867Sdelphij size = ldm_get_vbus_size(); 112275980Ssmh vbus_ext = malloc(sizeof(VBUS_EXT) + size, M_DEVBUF, M_WAITOK | 113275980Ssmh M_ZERO); 114252867Sdelphij vbus_ext->ext_type = EXT_TYPE_VBUS; 115252867Sdelphij ldm_create_vbus((PVBUS)vbus_ext->vbus, vbus_ext); 116252867Sdelphij ldm_register_adapter(&hba->ldm_adapter); 117252867Sdelphij } 118252867Sdelphij 119252867Sdelphij ldm_for_each_vbus(vbus, vbus_ext) { 120252867Sdelphij if (hba->ldm_adapter.vbus==vbus) { 121252867Sdelphij hba->vbus_ext = vbus_ext; 122252867Sdelphij hba->next = vbus_ext->hba_list; 123252867Sdelphij vbus_ext->hba_list = hba; 124252867Sdelphij break; 125252867Sdelphij } 126252867Sdelphij } 127252867Sdelphij return 0; 128252867Sdelphij} 129252867Sdelphij 130252867Sdelphij/* 131252867Sdelphij * Maybe we'd better to use the bus_dmamem_alloc to alloc DMA memory, 132252867Sdelphij * but there are some problems currently (alignment, etc). 133252867Sdelphij */ 134252867Sdelphijstatic __inline void *__get_free_pages(int order) 135252867Sdelphij{ 136252867Sdelphij /* don't use low memory - other devices may get starved */ 137252867Sdelphij return contigmalloc(PAGE_SIZE<<order, 138252867Sdelphij M_DEVBUF, M_WAITOK, BUS_SPACE_MAXADDR_24BIT, BUS_SPACE_MAXADDR, PAGE_SIZE, 0); 139252867Sdelphij} 140252867Sdelphij 141252867Sdelphijstatic __inline void free_pages(void *p, int order) 142252867Sdelphij{ 143252867Sdelphij contigfree(p, PAGE_SIZE<<order, M_DEVBUF); 144252867Sdelphij} 145252867Sdelphij 146252867Sdelphijstatic int hpt_alloc_mem(PVBUS_EXT vbus_ext) 147252867Sdelphij{ 148252867Sdelphij PHBA hba; 149252867Sdelphij struct freelist *f; 150252867Sdelphij HPT_UINT i; 151252867Sdelphij void **p; 152252867Sdelphij 153252867Sdelphij for (hba = vbus_ext->hba_list; hba; hba = hba->next) 154252867Sdelphij hba->ldm_adapter.him->get_meminfo(hba->ldm_adapter.him_handle); 155252867Sdelphij 156252867Sdelphij ldm_get_mem_info((PVBUS)vbus_ext->vbus, 0); 157252867Sdelphij 158252867Sdelphij for (f=vbus_ext->freelist_head; f; f=f->next) { 159252867Sdelphij KdPrint(("%s: %d*%d=%d bytes", 160252867Sdelphij f->tag, f->count, f->size, f->count*f->size)); 161252867Sdelphij for (i=0; i<f->count; i++) { 162252867Sdelphij p = (void **)malloc(f->size, M_DEVBUF, M_WAITOK); 163252867Sdelphij if (!p) return (ENXIO); 164252867Sdelphij *p = f->head; 165252867Sdelphij f->head = p; 166252867Sdelphij } 167252867Sdelphij } 168252867Sdelphij 169252867Sdelphij for (f=vbus_ext->freelist_dma_head; f; f=f->next) { 170252867Sdelphij int order, size, j; 171252867Sdelphij 172252867Sdelphij HPT_ASSERT((f->size & (f->alignment-1))==0); 173252867Sdelphij 174252867Sdelphij for (order=0, size=PAGE_SIZE; size<f->size; order++, size<<=1) 175252867Sdelphij ; 176252867Sdelphij 177252867Sdelphij KdPrint(("%s: %d*%d=%d bytes, order %d", 178252867Sdelphij f->tag, f->count, f->size, f->count*f->size, order)); 179252867Sdelphij HPT_ASSERT(f->alignment<=PAGE_SIZE); 180252867Sdelphij 181252867Sdelphij for (i=0; i<f->count;) { 182252867Sdelphij p = (void **)__get_free_pages(order); 183252867Sdelphij if (!p) return -1; 184252867Sdelphij for (j = size/f->size; j && i<f->count; i++,j--) { 185252867Sdelphij *p = f->head; 186252867Sdelphij *(BUS_ADDRESS *)(p+1) = (BUS_ADDRESS)vtophys(p); 187252867Sdelphij f->head = p; 188252867Sdelphij p = (void **)((unsigned long)p + f->size); 189252867Sdelphij } 190252867Sdelphij } 191252867Sdelphij } 192252867Sdelphij 193252867Sdelphij HPT_ASSERT(PAGE_SIZE==DMAPOOL_PAGE_SIZE); 194252867Sdelphij 195252867Sdelphij for (i=0; i<os_max_cache_pages; i++) { 196252867Sdelphij p = (void **)__get_free_pages(0); 197252867Sdelphij if (!p) return -1; 198252867Sdelphij HPT_ASSERT(((HPT_UPTR)p & (DMAPOOL_PAGE_SIZE-1))==0); 199252867Sdelphij dmapool_put_page((PVBUS)vbus_ext->vbus, p, (BUS_ADDRESS)vtophys(p)); 200252867Sdelphij } 201252867Sdelphij 202252867Sdelphij return 0; 203252867Sdelphij} 204252867Sdelphij 205252867Sdelphijstatic void hpt_free_mem(PVBUS_EXT vbus_ext) 206252867Sdelphij{ 207252867Sdelphij struct freelist *f; 208252867Sdelphij void *p; 209252867Sdelphij int i; 210252867Sdelphij BUS_ADDRESS bus; 211252867Sdelphij 212252867Sdelphij for (f=vbus_ext->freelist_head; f; f=f->next) { 213252867Sdelphij#if DBG 214252867Sdelphij if (f->count!=f->reserved_count) { 215252867Sdelphij KdPrint(("memory leak for freelist %s (%d/%d)", f->tag, f->count, f->reserved_count)); 216252867Sdelphij } 217252867Sdelphij#endif 218252867Sdelphij while ((p=freelist_get(f))) 219252867Sdelphij free(p, M_DEVBUF); 220252867Sdelphij } 221252867Sdelphij 222252867Sdelphij for (i=0; i<os_max_cache_pages; i++) { 223252867Sdelphij p = dmapool_get_page((PVBUS)vbus_ext->vbus, &bus); 224252867Sdelphij HPT_ASSERT(p); 225252867Sdelphij free_pages(p, 0); 226252867Sdelphij } 227252867Sdelphij 228252867Sdelphij for (f=vbus_ext->freelist_dma_head; f; f=f->next) { 229252867Sdelphij int order, size; 230252867Sdelphij#if DBG 231252867Sdelphij if (f->count!=f->reserved_count) { 232252867Sdelphij KdPrint(("memory leak for dma freelist %s (%d/%d)", f->tag, f->count, f->reserved_count)); 233252867Sdelphij } 234252867Sdelphij#endif 235252867Sdelphij for (order=0, size=PAGE_SIZE; size<f->size; order++, size<<=1) ; 236252867Sdelphij 237252867Sdelphij while ((p=freelist_get_dma(f, &bus))) { 238252867Sdelphij if (order) 239252867Sdelphij free_pages(p, order); 240252867Sdelphij else { 241252867Sdelphij /* can't free immediately since other blocks in this page may still be in the list */ 242252867Sdelphij if (((HPT_UPTR)p & (PAGE_SIZE-1))==0) 243252867Sdelphij dmapool_put_page((PVBUS)vbus_ext->vbus, p, bus); 244252867Sdelphij } 245252867Sdelphij } 246252867Sdelphij } 247252867Sdelphij 248252867Sdelphij while ((p = dmapool_get_page((PVBUS)vbus_ext->vbus, &bus))) 249252867Sdelphij free_pages(p, 0); 250252867Sdelphij} 251252867Sdelphij 252252867Sdelphijstatic int hpt_init_vbus(PVBUS_EXT vbus_ext) 253252867Sdelphij{ 254252867Sdelphij PHBA hba; 255252867Sdelphij 256252867Sdelphij for (hba = vbus_ext->hba_list; hba; hba = hba->next) 257252867Sdelphij if (!hba->ldm_adapter.him->initialize(hba->ldm_adapter.him_handle)) { 258252867Sdelphij KdPrint(("fail to initialize %p", hba)); 259252867Sdelphij return -1; 260252867Sdelphij } 261252867Sdelphij 262252867Sdelphij ldm_initialize_vbus((PVBUS)vbus_ext->vbus, &vbus_ext->hba_list->ldm_adapter); 263252867Sdelphij return 0; 264252867Sdelphij} 265252867Sdelphij 266252867Sdelphijstatic void hpt_flush_done(PCOMMAND pCmd) 267252867Sdelphij{ 268252867Sdelphij PVDEV vd = pCmd->target; 269252867Sdelphij 270252867Sdelphij if (mIsArray(vd->type) && vd->u.array.transform && vd!=vd->u.array.transform->target) { 271252867Sdelphij vd = vd->u.array.transform->target; 272252867Sdelphij HPT_ASSERT(vd); 273252867Sdelphij pCmd->target = vd; 274252867Sdelphij pCmd->Result = RETURN_PENDING; 275252867Sdelphij vdev_queue_cmd(pCmd); 276252867Sdelphij return; 277252867Sdelphij } 278252867Sdelphij 279252867Sdelphij *(int *)pCmd->priv = 1; 280252867Sdelphij wakeup(pCmd); 281252867Sdelphij} 282252867Sdelphij 283252867Sdelphij/* 284252867Sdelphij * flush a vdev (without retry). 285252867Sdelphij */ 286252867Sdelphijstatic int hpt_flush_vdev(PVBUS_EXT vbus_ext, PVDEV vd) 287252867Sdelphij{ 288252867Sdelphij PCOMMAND pCmd; 289252867Sdelphij int result = 0, done; 290252867Sdelphij HPT_UINT count; 291252867Sdelphij 292252867Sdelphij KdPrint(("flusing dev %p", vd)); 293252867Sdelphij 294275980Ssmh hpt_assert_vbus_locked(vbus_ext); 295252867Sdelphij 296252867Sdelphij if (mIsArray(vd->type) && vd->u.array.transform) 297252867Sdelphij count = MAX(vd->u.array.transform->source->cmds_per_request, 298252867Sdelphij vd->u.array.transform->target->cmds_per_request); 299252867Sdelphij else 300252867Sdelphij count = vd->cmds_per_request; 301252867Sdelphij 302252867Sdelphij pCmd = ldm_alloc_cmds(vd->vbus, count); 303252867Sdelphij 304252867Sdelphij if (!pCmd) { 305252867Sdelphij return -1; 306252867Sdelphij } 307252867Sdelphij 308252867Sdelphij pCmd->type = CMD_TYPE_FLUSH; 309252867Sdelphij pCmd->flags.hard_flush = 1; 310252867Sdelphij pCmd->target = vd; 311252867Sdelphij pCmd->done = hpt_flush_done; 312252867Sdelphij done = 0; 313252867Sdelphij pCmd->priv = &done; 314252867Sdelphij 315252867Sdelphij ldm_queue_cmd(pCmd); 316252867Sdelphij 317252867Sdelphij if (!done) { 318252867Sdelphij while (hpt_sleep(vbus_ext, pCmd, PPAUSE, "hptfls", HPT_OSM_TIMEOUT)) { 319252867Sdelphij ldm_reset_vbus(vd->vbus); 320252867Sdelphij } 321252867Sdelphij } 322252867Sdelphij 323252867Sdelphij KdPrint(("flush result %d", pCmd->Result)); 324252867Sdelphij 325252867Sdelphij if (pCmd->Result!=RETURN_SUCCESS) 326252867Sdelphij result = -1; 327252867Sdelphij 328252867Sdelphij ldm_free_cmds(pCmd); 329252867Sdelphij 330252867Sdelphij return result; 331252867Sdelphij} 332252867Sdelphij 333252867Sdelphijstatic void hpt_stop_tasks(PVBUS_EXT vbus_ext); 334252867Sdelphijstatic void hpt_shutdown_vbus(PVBUS_EXT vbus_ext, int howto) 335252867Sdelphij{ 336252867Sdelphij PVBUS vbus = (PVBUS)vbus_ext->vbus; 337252867Sdelphij PHBA hba; 338252867Sdelphij int i; 339252867Sdelphij 340252867Sdelphij KdPrint(("hpt_shutdown_vbus")); 341252867Sdelphij 342252867Sdelphij /* stop all ctl tasks and disable the worker taskqueue */ 343252867Sdelphij hpt_stop_tasks(vbus_ext); 344275980Ssmh hpt_lock_vbus(vbus_ext); 345252867Sdelphij vbus_ext->worker.ta_context = 0; 346252867Sdelphij 347252867Sdelphij /* flush devices */ 348252867Sdelphij for (i=0; i<osm_max_targets; i++) { 349252867Sdelphij PVDEV vd = ldm_find_target(vbus, i); 350252867Sdelphij if (vd) { 351252867Sdelphij /* retry once */ 352252867Sdelphij if (hpt_flush_vdev(vbus_ext, vd)) 353252867Sdelphij hpt_flush_vdev(vbus_ext, vd); 354252867Sdelphij } 355252867Sdelphij } 356252867Sdelphij 357252867Sdelphij ldm_shutdown(vbus); 358252867Sdelphij hpt_unlock_vbus(vbus_ext); 359252867Sdelphij 360252867Sdelphij ldm_release_vbus(vbus); 361252867Sdelphij 362252867Sdelphij for (hba=vbus_ext->hba_list; hba; hba=hba->next) 363252867Sdelphij bus_teardown_intr(hba->pcidev, hba->irq_res, hba->irq_handle); 364252867Sdelphij 365252867Sdelphij hpt_free_mem(vbus_ext); 366252867Sdelphij 367252867Sdelphij while ((hba=vbus_ext->hba_list)) { 368252867Sdelphij vbus_ext->hba_list = hba->next; 369252867Sdelphij free(hba->ldm_adapter.him_handle, M_DEVBUF); 370252867Sdelphij } 371252867Sdelphij 372275980Ssmh callout_drain(&vbus_ext->timer); 373275980Ssmh mtx_destroy(&vbus_ext->lock); 374252867Sdelphij free(vbus_ext, M_DEVBUF); 375252867Sdelphij KdPrint(("hpt_shutdown_vbus done")); 376252867Sdelphij} 377252867Sdelphij 378252867Sdelphijstatic void __hpt_do_tasks(PVBUS_EXT vbus_ext) 379252867Sdelphij{ 380252867Sdelphij OSM_TASK *tasks; 381252867Sdelphij 382252867Sdelphij tasks = vbus_ext->tasks; 383252867Sdelphij vbus_ext->tasks = 0; 384252867Sdelphij 385252867Sdelphij while (tasks) { 386252867Sdelphij OSM_TASK *t = tasks; 387252867Sdelphij tasks = t->next; 388252867Sdelphij t->next = 0; 389252867Sdelphij t->func(vbus_ext->vbus, t->data); 390252867Sdelphij } 391252867Sdelphij} 392252867Sdelphij 393252867Sdelphijstatic void hpt_do_tasks(PVBUS_EXT vbus_ext, int pending) 394252867Sdelphij{ 395252867Sdelphij if(vbus_ext){ 396252867Sdelphij hpt_lock_vbus(vbus_ext); 397252867Sdelphij __hpt_do_tasks(vbus_ext); 398252867Sdelphij hpt_unlock_vbus(vbus_ext); 399252867Sdelphij } 400252867Sdelphij} 401252867Sdelphij 402252867Sdelphijstatic void hpt_action(struct cam_sim *sim, union ccb *ccb); 403252867Sdelphijstatic void hpt_poll(struct cam_sim *sim); 404252867Sdelphijstatic void hpt_async(void * callback_arg, u_int32_t code, struct cam_path * path, void * arg); 405252867Sdelphijstatic void hpt_pci_intr(void *arg); 406252867Sdelphij 407252867Sdelphijstatic __inline POS_CMDEXT cmdext_get(PVBUS_EXT vbus_ext) 408252867Sdelphij{ 409252867Sdelphij POS_CMDEXT p = vbus_ext->cmdext_list; 410252867Sdelphij if (p) 411252867Sdelphij vbus_ext->cmdext_list = p->next; 412252867Sdelphij return p; 413252867Sdelphij} 414252867Sdelphij 415252867Sdelphijstatic __inline void cmdext_put(POS_CMDEXT p) 416252867Sdelphij{ 417252867Sdelphij p->next = p->vbus_ext->cmdext_list; 418252867Sdelphij p->vbus_ext->cmdext_list = p; 419252867Sdelphij} 420252867Sdelphij 421252867Sdelphijstatic void hpt_timeout(void *arg) 422252867Sdelphij{ 423252867Sdelphij PCOMMAND pCmd = (PCOMMAND)arg; 424252867Sdelphij POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv; 425252867Sdelphij 426252867Sdelphij KdPrint(("pCmd %p timeout", pCmd)); 427252867Sdelphij 428252867Sdelphij ldm_reset_vbus((PVBUS)ext->vbus_ext->vbus); 429252867Sdelphij} 430252867Sdelphij 431252867Sdelphijstatic void os_cmddone(PCOMMAND pCmd) 432252867Sdelphij{ 433252867Sdelphij POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv; 434252867Sdelphij union ccb *ccb = ext->ccb; 435281957Sdelphij HPT_U8 *cdb; 436281957Sdelphij 437281957Sdelphij if (ccb->ccb_h.flags & CAM_CDB_POINTER) 438281957Sdelphij cdb = ccb->csio.cdb_io.cdb_ptr; 439281957Sdelphij else 440281957Sdelphij cdb = ccb->csio.cdb_io.cdb_bytes; 441252867Sdelphij 442252867Sdelphij KdPrint(("os_cmddone(%p, %d)", pCmd, pCmd->Result)); 443252867Sdelphij 444275980Ssmh callout_stop(&ext->timeout); 445281957Sdelphij switch(cdb[0]) { 446281957Sdelphij case 0x85: /*ATA_16*/ 447281957Sdelphij case 0xA1: /*ATA_12*/ 448281957Sdelphij { 449281957Sdelphij PassthroughCmd *passthru = &pCmd->uCmd.Passthrough; 450281957Sdelphij HPT_U8 *sense_buffer = (HPT_U8 *)&ccb->csio.sense_data; 451281957Sdelphij memset(&ccb->csio.sense_data, 0,sizeof(ccb->csio.sense_data)); 452275980Ssmh 453281957Sdelphij sense_buffer[0] = 0x72; /* Response Code */ 454281957Sdelphij sense_buffer[7] = 14; /* Additional Sense Length */ 455281957Sdelphij 456281957Sdelphij sense_buffer[8] = 0x9; /* ATA Return Descriptor */ 457281957Sdelphij sense_buffer[9] = 0xc; /* Additional Descriptor Length */ 458281957Sdelphij sense_buffer[11] = (HPT_U8)passthru->bFeaturesReg; /* Error */ 459281957Sdelphij sense_buffer[13] = (HPT_U8)passthru->bSectorCountReg; /* Sector Count (7:0) */ 460281957Sdelphij sense_buffer[15] = (HPT_U8)passthru->bLbaLowReg; /* LBA Low (7:0) */ 461281957Sdelphij sense_buffer[17] = (HPT_U8)passthru->bLbaMidReg; /* LBA Mid (7:0) */ 462281957Sdelphij sense_buffer[19] = (HPT_U8)passthru->bLbaHighReg; /* LBA High (7:0) */ 463281957Sdelphij 464281957Sdelphij if ((cdb[0] == 0x85) && (cdb[1] & 0x1)) 465281957Sdelphij { 466281957Sdelphij sense_buffer[10] = 1; 467281957Sdelphij sense_buffer[12] = (HPT_U8)(passthru->bSectorCountReg >> 8); /* Sector Count (15:8) */ 468281957Sdelphij sense_buffer[14] = (HPT_U8)(passthru->bLbaLowReg >> 8); /* LBA Low (15:8) */ 469281957Sdelphij sense_buffer[16] = (HPT_U8)(passthru->bLbaMidReg >> 8); /* LBA Mid (15:8) */ 470281957Sdelphij sense_buffer[18] = (HPT_U8)(passthru->bLbaHighReg >> 8); /* LBA High (15:8) */ 471281957Sdelphij } 472281957Sdelphij 473281957Sdelphij sense_buffer[20] = (HPT_U8)passthru->bDriveHeadReg; /* Device */ 474281957Sdelphij sense_buffer[21] = (HPT_U8)passthru->bCommandReg; /* Status */ 475281957Sdelphij KdPrint(("sts 0x%x err 0x%x low 0x%x mid 0x%x hig 0x%x dh 0x%x sc 0x%x", 476281957Sdelphij passthru->bCommandReg, 477281957Sdelphij passthru->bFeaturesReg, 478281957Sdelphij passthru->bLbaLowReg, 479281957Sdelphij passthru->bLbaMidReg, 480281957Sdelphij passthru->bLbaHighReg, 481281957Sdelphij passthru->bDriveHeadReg, 482281957Sdelphij passthru->bSectorCountReg)); 483281957Sdelphij KdPrint(("result:0x%x,bFeaturesReg:0x%04x,bSectorCountReg:0x%04x,LBA:0x%04x%04x%04x ", 484281957Sdelphij pCmd->Result,passthru->bFeaturesReg,passthru->bSectorCountReg, 485281957Sdelphij passthru->bLbaHighReg,passthru->bLbaMidReg,passthru->bLbaLowReg)); 486281957Sdelphij } 487281957Sdelphij default: 488281957Sdelphij break; 489281957Sdelphij } 490281957Sdelphij 491252867Sdelphij switch(pCmd->Result) { 492252867Sdelphij case RETURN_SUCCESS: 493252867Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 494252867Sdelphij break; 495252867Sdelphij case RETURN_BAD_DEVICE: 496252867Sdelphij ccb->ccb_h.status = CAM_DEV_NOT_THERE; 497252867Sdelphij break; 498252867Sdelphij case RETURN_DEVICE_BUSY: 499252867Sdelphij ccb->ccb_h.status = CAM_BUSY; 500252867Sdelphij break; 501252867Sdelphij case RETURN_INVALID_REQUEST: 502252867Sdelphij ccb->ccb_h.status = CAM_REQ_INVALID; 503252867Sdelphij break; 504252867Sdelphij case RETURN_SELECTION_TIMEOUT: 505252867Sdelphij ccb->ccb_h.status = CAM_SEL_TIMEOUT; 506252867Sdelphij break; 507252867Sdelphij case RETURN_RETRY: 508252867Sdelphij ccb->ccb_h.status = CAM_BUSY; 509252867Sdelphij break; 510252867Sdelphij default: 511252867Sdelphij ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 512252867Sdelphij break; 513252867Sdelphij } 514252867Sdelphij 515252867Sdelphij if (pCmd->flags.data_in) { 516252867Sdelphij bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, BUS_DMASYNC_POSTREAD); 517252867Sdelphij } 518252867Sdelphij else if (pCmd->flags.data_out) { 519252867Sdelphij bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, BUS_DMASYNC_POSTWRITE); 520252867Sdelphij } 521252867Sdelphij 522252867Sdelphij bus_dmamap_unload(ext->vbus_ext->io_dmat, ext->dma_map); 523252867Sdelphij 524252867Sdelphij cmdext_put(ext); 525252867Sdelphij ldm_free_cmds(pCmd); 526252867Sdelphij xpt_done(ccb); 527252867Sdelphij} 528252867Sdelphij 529252867Sdelphijstatic int os_buildsgl(PCOMMAND pCmd, PSG pSg, int logical) 530252867Sdelphij{ 531252867Sdelphij /* since we have provided physical sg, nobody will ask us to build physical sg */ 532252867Sdelphij HPT_ASSERT(0); 533252867Sdelphij return FALSE; 534252867Sdelphij} 535252867Sdelphij 536252867Sdelphijstatic void hpt_io_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 537252867Sdelphij{ 538252867Sdelphij PCOMMAND pCmd = (PCOMMAND)arg; 539252867Sdelphij POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv; 540252867Sdelphij PSG psg = pCmd->psg; 541252867Sdelphij int idx; 542252867Sdelphij 543252867Sdelphij HPT_ASSERT(pCmd->flags.physical_sg); 544252867Sdelphij 545252867Sdelphij if (error) 546252867Sdelphij panic("busdma error"); 547252867Sdelphij 548252867Sdelphij HPT_ASSERT(nsegs<=os_max_sg_descriptors); 549252867Sdelphij 550252867Sdelphij if (nsegs != 0) { 551252867Sdelphij for (idx = 0; idx < nsegs; idx++, psg++) { 552252867Sdelphij psg->addr.bus = segs[idx].ds_addr; 553252867Sdelphij psg->size = segs[idx].ds_len; 554252867Sdelphij psg->eot = 0; 555252867Sdelphij } 556252867Sdelphij psg[-1].eot = 1; 557252867Sdelphij 558252867Sdelphij if (pCmd->flags.data_in) { 559252867Sdelphij bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, 560252867Sdelphij BUS_DMASYNC_PREREAD); 561252867Sdelphij } 562252867Sdelphij else if (pCmd->flags.data_out) { 563252867Sdelphij bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, 564252867Sdelphij BUS_DMASYNC_PREWRITE); 565252867Sdelphij } 566252867Sdelphij } 567252867Sdelphij 568275980Ssmh callout_reset(&ext->timeout, HPT_OSM_TIMEOUT, hpt_timeout, pCmd); 569252867Sdelphij ldm_queue_cmd(pCmd); 570252867Sdelphij} 571252867Sdelphij 572252867Sdelphijstatic void hpt_scsi_io(PVBUS_EXT vbus_ext, union ccb *ccb) 573252867Sdelphij{ 574252867Sdelphij PVBUS vbus = (PVBUS)vbus_ext->vbus; 575252867Sdelphij PVDEV vd; 576252867Sdelphij PCOMMAND pCmd; 577252867Sdelphij POS_CMDEXT ext; 578252867Sdelphij HPT_U8 *cdb; 579252867Sdelphij 580252867Sdelphij if (ccb->ccb_h.flags & CAM_CDB_POINTER) 581252867Sdelphij cdb = ccb->csio.cdb_io.cdb_ptr; 582252867Sdelphij else 583252867Sdelphij cdb = ccb->csio.cdb_io.cdb_bytes; 584252867Sdelphij 585252867Sdelphij KdPrint(("hpt_scsi_io: ccb %x id %d lun %d cdb %x-%x-%x", 586252867Sdelphij ccb, 587252867Sdelphij ccb->ccb_h.target_id, ccb->ccb_h.target_lun, 588252867Sdelphij *(HPT_U32 *)&cdb[0], *(HPT_U32 *)&cdb[4], *(HPT_U32 *)&cdb[8] 589252867Sdelphij )); 590252867Sdelphij 591252867Sdelphij /* ccb->ccb_h.path_id is not our bus id - don't check it */ 592252867Sdelphij if (ccb->ccb_h.target_lun != 0 || 593252867Sdelphij ccb->ccb_h.target_id >= osm_max_targets || 594252867Sdelphij (ccb->ccb_h.flags & CAM_CDB_PHYS)) 595252867Sdelphij { 596252867Sdelphij ccb->ccb_h.status = CAM_TID_INVALID; 597252867Sdelphij xpt_done(ccb); 598252867Sdelphij return; 599252867Sdelphij } 600252867Sdelphij 601252867Sdelphij vd = ldm_find_target(vbus, ccb->ccb_h.target_id); 602252867Sdelphij 603252867Sdelphij if (!vd) { 604270810Sdelphij ccb->ccb_h.status = CAM_SEL_TIMEOUT; 605252867Sdelphij xpt_done(ccb); 606252867Sdelphij return; 607252867Sdelphij } 608252867Sdelphij 609252867Sdelphij switch (cdb[0]) { 610252867Sdelphij case TEST_UNIT_READY: 611252867Sdelphij case START_STOP_UNIT: 612252867Sdelphij case SYNCHRONIZE_CACHE: 613252867Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 614252867Sdelphij break; 615252867Sdelphij 616281957Sdelphij case 0x85: /*ATA_16*/ 617281957Sdelphij case 0xA1: /*ATA_12*/ 618281957Sdelphij { 619281957Sdelphij int error; 620281957Sdelphij HPT_U8 prot; 621281957Sdelphij PassthroughCmd *passthru; 622281957Sdelphij 623281957Sdelphij if (mIsArray(vd->type)) { 624284935Sdelphij ccb->ccb_h.status = CAM_REQ_INVALID; 625281957Sdelphij break; 626281957Sdelphij } 627281957Sdelphij 628281957Sdelphij HPT_ASSERT(vd->type == VD_RAW && vd->u.raw.legacy_disk); 629281957Sdelphij 630281957Sdelphij prot = (cdb[1] & 0x1e) >> 1; 631281957Sdelphij 632281957Sdelphij 633281957Sdelphij if (prot < 3 || prot > 5) 634252867Sdelphij { 635281957Sdelphij ccb->ccb_h.status = CAM_REQ_INVALID; 636281957Sdelphij break; 637281957Sdelphij } 638252867Sdelphij 639281957Sdelphij pCmd = ldm_alloc_cmds(vbus, vd->cmds_per_request); 640281957Sdelphij if (!pCmd) { 641281957Sdelphij HPT_ASSERT(0); 642281957Sdelphij ccb->ccb_h.status = CAM_BUSY; 643281957Sdelphij break; 644281957Sdelphij } 645281957Sdelphij 646281957Sdelphij passthru = &pCmd->uCmd.Passthrough; 647281957Sdelphij if (cdb[0] == 0x85/*ATA_16*/) { 648281957Sdelphij if (cdb[1] & 0x1) { 649281957Sdelphij passthru->bFeaturesReg = 650281957Sdelphij ((HPT_U16)cdb[3] << 8) 651281957Sdelphij | cdb[4]; 652281957Sdelphij passthru->bSectorCountReg = 653281957Sdelphij ((HPT_U16)cdb[5] << 8) | 654281957Sdelphij cdb[6]; 655281957Sdelphij passthru->bLbaLowReg = 656281957Sdelphij ((HPT_U16)cdb[7] << 8) | 657281957Sdelphij cdb[8]; 658281957Sdelphij passthru->bLbaMidReg = 659281957Sdelphij ((HPT_U16)cdb[9] << 8) | 660281957Sdelphij cdb[10]; 661281957Sdelphij passthru->bLbaHighReg = 662281957Sdelphij ((HPT_U16)cdb[11] << 8) | 663281957Sdelphij cdb[12]; 664281957Sdelphij } else { 665281957Sdelphij passthru->bFeaturesReg = cdb[4]; 666281957Sdelphij passthru->bSectorCountReg = cdb[6]; 667281957Sdelphij passthru->bLbaLowReg = cdb[8]; 668281957Sdelphij passthru->bLbaMidReg = cdb[10]; 669281957Sdelphij passthru->bLbaHighReg = cdb[12]; 670281957Sdelphij } 671281957Sdelphij passthru->bDriveHeadReg = cdb[13]; 672281957Sdelphij passthru->bCommandReg = cdb[14]; 673281957Sdelphij 674281957Sdelphij } else { /*ATA_12*/ 675281957Sdelphij 676281957Sdelphij passthru->bFeaturesReg = cdb[3]; 677281957Sdelphij passthru->bSectorCountReg = cdb[4]; 678281957Sdelphij passthru->bLbaLowReg = cdb[5]; 679281957Sdelphij passthru->bLbaMidReg = cdb[6]; 680281957Sdelphij passthru->bLbaHighReg = cdb[7]; 681281957Sdelphij passthru->bDriveHeadReg = cdb[8]; 682281957Sdelphij passthru->bCommandReg = cdb[9]; 683281957Sdelphij } 684281957Sdelphij 685281957Sdelphij if (cdb[1] & 0xe0) { 686281957Sdelphij 687281957Sdelphij 688281957Sdelphij if (!(passthru->bCommandReg == ATA_CMD_READ_MULTI || 689281957Sdelphij passthru->bCommandReg == ATA_CMD_READ_MULTI_EXT || 690281957Sdelphij passthru->bCommandReg == ATA_CMD_WRITE_MULTI || 691281957Sdelphij passthru->bCommandReg == ATA_CMD_WRITE_MULTI_EXT || 692281957Sdelphij passthru->bCommandReg == ATA_CMD_WRITE_MULTI_FUA_EXT) 693281957Sdelphij ) { 694281957Sdelphij goto error; 695281957Sdelphij } 696281957Sdelphij } 697281957Sdelphij 698281957Sdelphij 699281957Sdelphij if (passthru->bFeaturesReg == ATA_SET_FEATURES_XFER && 700281957Sdelphij passthru->bCommandReg == ATA_CMD_SET_FEATURES) { 701281957Sdelphij goto error; 702281957Sdelphij } 703281957Sdelphij 704281957Sdelphij 705281957Sdelphij passthru->nSectors = ccb->csio.dxfer_len/ATA_SECTOR_SIZE; 706281957Sdelphij switch (prot) { 707281957Sdelphij default: /*None data*/ 708281957Sdelphij break; 709281957Sdelphij case 4: /*PIO data in, T_DIR=1 match check*/ 710281957Sdelphij if ((cdb[2] & 3) && 711281957Sdelphij (cdb[2] & 0x8) == 0) 712281957Sdelphij { 713281957Sdelphij OsPrint(("PIO data in, T_DIR=1 match check")); 714281957Sdelphij goto error; 715281957Sdelphij } 716281957Sdelphij pCmd->flags.data_in = 1; 717281957Sdelphij break; 718281957Sdelphij case 5: /*PIO data out, T_DIR=0 match check*/ 719281957Sdelphij if ((cdb[2] & 3) && 720281957Sdelphij (cdb[2] & 0x8)) 721281957Sdelphij { 722281957Sdelphij OsPrint(("PIO data out, T_DIR=0 match check")); 723281957Sdelphij goto error; 724281957Sdelphij } 725281957Sdelphij 726281957Sdelphij pCmd->flags.data_out = 1; 727281957Sdelphij break; 728281957Sdelphij } 729281957Sdelphij pCmd->type = CMD_TYPE_PASSTHROUGH; 730281957Sdelphij pCmd->priv = ext = cmdext_get(vbus_ext); 731281957Sdelphij HPT_ASSERT(ext); 732281957Sdelphij ext->ccb = ccb; 733281957Sdelphij pCmd->target = vd; 734281957Sdelphij pCmd->done = os_cmddone; 735281957Sdelphij pCmd->buildsgl = os_buildsgl; 736281957Sdelphij pCmd->psg = ext->psg; 737281957Sdelphij 738281957Sdelphij if(!ccb->csio.dxfer_len) 739281957Sdelphij { 740281957Sdelphij ldm_queue_cmd(pCmd); 741281957Sdelphij return; 742281957Sdelphij } 743281957Sdelphij pCmd->flags.physical_sg = 1; 744281957Sdelphij error = bus_dmamap_load_ccb(vbus_ext->io_dmat, 745281957Sdelphij ext->dma_map, ccb, 746281957Sdelphij hpt_io_dmamap_callback, pCmd, 747281957Sdelphij BUS_DMA_WAITOK 748281957Sdelphij ); 749281957Sdelphij KdPrint(("bus_dmamap_load return %d", error)); 750281957Sdelphij if (error && error!=EINPROGRESS) { 751281957Sdelphij os_printk("bus_dmamap_load error %d", error); 752281957Sdelphij cmdext_put(ext); 753281957Sdelphij ldm_free_cmds(pCmd); 754281957Sdelphij ccb->ccb_h.status = CAM_REQ_CMP_ERR; 755281957Sdelphij xpt_done(ccb); 756281957Sdelphij } 757281957Sdelphij return; 758281957Sdelphijerror: 759281957Sdelphij ldm_free_cmds(pCmd); 760284935Sdelphij ccb->ccb_h.status = CAM_REQ_INVALID; 761281957Sdelphij break; 762281957Sdelphij } 763281957Sdelphij 764281957Sdelphij case INQUIRY: 765281957Sdelphij { 766281957Sdelphij PINQUIRYDATA inquiryData; 767281957Sdelphij HIM_DEVICE_CONFIG devconf; 768281957Sdelphij HPT_U8 *rbuf; 769281957Sdelphij 770281957Sdelphij memset(ccb->csio.data_ptr, 0, ccb->csio.dxfer_len); 771281957Sdelphij inquiryData = (PINQUIRYDATA)ccb->csio.data_ptr; 772281957Sdelphij 773281957Sdelphij if (cdb[1] & 1) { 774281957Sdelphij rbuf = (HPT_U8 *)inquiryData; 775281957Sdelphij switch(cdb[2]) { 776281957Sdelphij case 0: 777281957Sdelphij rbuf[0] = 0; 778281957Sdelphij rbuf[1] = 0; 779281957Sdelphij rbuf[2] = 0; 780281957Sdelphij rbuf[3] = 3; 781281957Sdelphij rbuf[4] = 0; 782281957Sdelphij rbuf[5] = 0x80; 783281957Sdelphij rbuf[6] = 0x83; 784281957Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 785281957Sdelphij break; 786281957Sdelphij case 0x80: { 787281957Sdelphij rbuf[0] = 0; 788281957Sdelphij rbuf[1] = 0x80; 789281957Sdelphij rbuf[2] = 0; 790281957Sdelphij if (vd->type == VD_RAW) { 791281957Sdelphij rbuf[3] = 20; 792281957Sdelphij vd->u.raw.him->get_device_config(vd->u.raw.phy_dev,&devconf); 793281957Sdelphij memcpy(&rbuf[4], devconf.pIdentifyData->SerialNumber, 20); 794281957Sdelphij ldm_ide_fixstring(&rbuf[4], 20); 795281957Sdelphij } else { 796281957Sdelphij rbuf[3] = 1; 797281957Sdelphij rbuf[4] = 0x20; 798281957Sdelphij } 799281957Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 800281957Sdelphij break; 801281957Sdelphij } 802281957Sdelphij case 0x83: 803281957Sdelphij rbuf[0] = 0; 804281957Sdelphij rbuf[1] = 0x83; 805281957Sdelphij rbuf[2] = 0; 806281957Sdelphij rbuf[3] = 12; 807281957Sdelphij rbuf[4] = 1; 808281957Sdelphij rbuf[5] = 2; 809281957Sdelphij rbuf[6] = 0; 810281957Sdelphij rbuf[7] = 8; 811281957Sdelphij rbuf[8] = 0; 812281957Sdelphij rbuf[9] = 0x19; 813281957Sdelphij rbuf[10] = 0x3C; 814281957Sdelphij rbuf[11] = 0; 815281957Sdelphij rbuf[12] = 0; 816281957Sdelphij rbuf[13] = 0; 817281957Sdelphij rbuf[14] = 0; 818281957Sdelphij rbuf[15] = 0; 819281957Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 820281957Sdelphij break; 821281957Sdelphij default: 822281957Sdelphij ccb->ccb_h.status = CAM_REQ_INVALID; 823281957Sdelphij break; 824281957Sdelphij } 825281957Sdelphij 826281957Sdelphij break; 827281957Sdelphij } 828281957Sdelphij else if (cdb[2]) { 829281957Sdelphij ccb->ccb_h.status = CAM_REQ_INVALID; 830281957Sdelphij break; 831281957Sdelphij } 832281957Sdelphij 833281957Sdelphij inquiryData->DeviceType = 0; /*DIRECT_ACCESS_DEVICE*/ 834281957Sdelphij inquiryData->Versions = 5; /*SPC-3*/ 835281957Sdelphij inquiryData->ResponseDataFormat = 2; 836281957Sdelphij inquiryData->AdditionalLength = 0x5b; 837281957Sdelphij inquiryData->CommandQueue = 1; 838281957Sdelphij 839281957Sdelphij if (ccb->csio.dxfer_len > 63) { 840281957Sdelphij rbuf = (HPT_U8 *)inquiryData; 841281957Sdelphij rbuf[58] = 0x60; 842281957Sdelphij rbuf[59] = 0x3; 843281957Sdelphij 844281957Sdelphij rbuf[64] = 0x3; 845281957Sdelphij rbuf[66] = 0x3; 846281957Sdelphij rbuf[67] = 0x20; 847281957Sdelphij 848281957Sdelphij } 849281957Sdelphij 850281957Sdelphij if (vd->type == VD_RAW) { 851281957Sdelphij vd->u.raw.him->get_device_config(vd->u.raw.phy_dev,&devconf); 852281957Sdelphij 853281957Sdelphij if ((devconf.pIdentifyData->GeneralConfiguration & 0x80)) 854281957Sdelphij inquiryData->RemovableMedia = 1; 855281957Sdelphij 856281957Sdelphij 857281957Sdelphij memcpy(&inquiryData->VendorId, "ATA ", 8); 858281957Sdelphij memcpy(&inquiryData->ProductId, devconf.pIdentifyData->ModelNumber, 16); 859281957Sdelphij ldm_ide_fixstring((HPT_U8 *)&inquiryData->ProductId, 16); 860281957Sdelphij memcpy(&inquiryData->ProductRevisionLevel, devconf.pIdentifyData->FirmwareRevision, 4); 861281957Sdelphij ldm_ide_fixstring((HPT_U8 *)&inquiryData->ProductRevisionLevel, 4); 862281957Sdelphij if (inquiryData->ProductRevisionLevel[0] == 0 || inquiryData->ProductRevisionLevel[0] == ' ') 863281957Sdelphij memcpy(&inquiryData->ProductRevisionLevel, "n/a ", 4); 864281957Sdelphij } else { 865252867Sdelphij memcpy(&inquiryData->VendorId, "HPT ", 8); 866281957Sdelphij snprintf((char *)&inquiryData->ProductId, 16, "DISK_%d_%d ", 867281957Sdelphij os_get_vbus_seq(vbus_ext), vd->target_id); 868281957Sdelphij inquiryData->ProductId[15] = ' '; 869252867Sdelphij memcpy(&inquiryData->ProductRevisionLevel, "4.00", 4); 870252867Sdelphij } 871281957Sdelphij 872281957Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 873252867Sdelphij break; 874281957Sdelphij } 875252867Sdelphij case READ_CAPACITY: 876252867Sdelphij { 877252867Sdelphij HPT_U8 *rbuf = ccb->csio.data_ptr; 878252867Sdelphij HPT_U32 cap; 879281957Sdelphij HPT_U8 sector_size_shift = 0; 880281957Sdelphij HPT_U64 new_cap; 881281957Sdelphij HPT_U32 sector_size = 0; 882281957Sdelphij 883281957Sdelphij if (mIsArray(vd->type)) 884281957Sdelphij sector_size_shift = vd->u.array.sector_size_shift; 885281957Sdelphij else{ 886281957Sdelphij if(vd->type == VD_RAW){ 887281957Sdelphij sector_size = vd->u.raw.logical_sector_size; 888281957Sdelphij } 889252867Sdelphij 890281957Sdelphij switch (sector_size) { 891281957Sdelphij case 0x1000: 892281957Sdelphij KdPrint(("set 4k setctor size in READ_CAPACITY")); 893281957Sdelphij sector_size_shift = 3; 894281957Sdelphij break; 895281957Sdelphij default: 896281957Sdelphij break; 897281957Sdelphij } 898281957Sdelphij } 899281957Sdelphij new_cap = vd->capacity >> sector_size_shift; 900281957Sdelphij 901281957Sdelphij if (new_cap > 0xfffffffful) 902281957Sdelphij cap = 0xffffffff; 903252867Sdelphij else 904281957Sdelphij cap = new_cap - 1; 905281957Sdelphij 906252867Sdelphij rbuf[0] = (HPT_U8)(cap>>24); 907252867Sdelphij rbuf[1] = (HPT_U8)(cap>>16); 908252867Sdelphij rbuf[2] = (HPT_U8)(cap>>8); 909252867Sdelphij rbuf[3] = (HPT_U8)cap; 910252867Sdelphij rbuf[4] = 0; 911252867Sdelphij rbuf[5] = 0; 912281957Sdelphij rbuf[6] = 2 << sector_size_shift; 913252867Sdelphij rbuf[7] = 0; 914252867Sdelphij 915252867Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 916252867Sdelphij break; 917252867Sdelphij } 918252867Sdelphij 919284935Sdelphij case REPORT_LUNS: 920284935Sdelphij { 921284935Sdelphij HPT_U8 *rbuf = ccb->csio.data_ptr; 922284935Sdelphij memset(rbuf, 0, 16); 923284935Sdelphij rbuf[3] = 8; 924284935Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 925284935Sdelphij break; 926284935Sdelphij } 927252867Sdelphij case SERVICE_ACTION_IN: 928252867Sdelphij { 929252867Sdelphij HPT_U8 *rbuf = ccb->csio.data_ptr; 930281957Sdelphij HPT_U64 cap = 0; 931281957Sdelphij HPT_U8 sector_size_shift = 0; 932281957Sdelphij HPT_U32 sector_size = 0; 933281957Sdelphij 934281957Sdelphij if(mIsArray(vd->type)) 935281957Sdelphij sector_size_shift = vd->u.array.sector_size_shift; 936281957Sdelphij else{ 937281957Sdelphij if(vd->type == VD_RAW){ 938281957Sdelphij sector_size = vd->u.raw.logical_sector_size; 939281957Sdelphij } 940252867Sdelphij 941281957Sdelphij switch (sector_size) { 942281957Sdelphij case 0x1000: 943281957Sdelphij KdPrint(("set 4k setctor size in SERVICE_ACTION_IN")); 944281957Sdelphij sector_size_shift = 3; 945281957Sdelphij break; 946281957Sdelphij default: 947281957Sdelphij break; 948281957Sdelphij } 949281957Sdelphij } 950281957Sdelphij cap = (vd->capacity >> sector_size_shift) - 1; 951281957Sdelphij 952252867Sdelphij rbuf[0] = (HPT_U8)(cap>>56); 953252867Sdelphij rbuf[1] = (HPT_U8)(cap>>48); 954252867Sdelphij rbuf[2] = (HPT_U8)(cap>>40); 955252867Sdelphij rbuf[3] = (HPT_U8)(cap>>32); 956252867Sdelphij rbuf[4] = (HPT_U8)(cap>>24); 957252867Sdelphij rbuf[5] = (HPT_U8)(cap>>16); 958252867Sdelphij rbuf[6] = (HPT_U8)(cap>>8); 959252867Sdelphij rbuf[7] = (HPT_U8)cap; 960252867Sdelphij rbuf[8] = 0; 961252867Sdelphij rbuf[9] = 0; 962281957Sdelphij rbuf[10] = 2 << sector_size_shift; 963252867Sdelphij rbuf[11] = 0; 964252867Sdelphij 965284935Sdelphij if(!mIsArray(vd->type)){ 966284935Sdelphij rbuf[13] = vd->u.raw.logicalsectors_per_physicalsector; 967284935Sdelphij rbuf[14] = (HPT_U8)((vd->u.raw.lowest_aligned >> 8) & 0x3f); 968284935Sdelphij rbuf[15] = (HPT_U8)(vd->u.raw.lowest_aligned); 969284935Sdelphij } 970284935Sdelphij 971252867Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 972252867Sdelphij break; 973252867Sdelphij } 974252867Sdelphij 975252867Sdelphij case READ_6: 976252867Sdelphij case READ_10: 977252867Sdelphij case READ_16: 978252867Sdelphij case WRITE_6: 979252867Sdelphij case WRITE_10: 980252867Sdelphij case WRITE_16: 981252867Sdelphij case 0x13: 982252867Sdelphij case 0x2f: 983252867Sdelphij case 0x8f: /* VERIFY_16 */ 984252867Sdelphij { 985252867Sdelphij int error; 986281957Sdelphij HPT_U8 sector_size_shift = 0; 987281957Sdelphij HPT_U32 sector_size = 0; 988252867Sdelphij pCmd = ldm_alloc_cmds(vbus, vd->cmds_per_request); 989252867Sdelphij if(!pCmd){ 990252867Sdelphij KdPrint(("Failed to allocate command!")); 991252867Sdelphij ccb->ccb_h.status = CAM_BUSY; 992252867Sdelphij break; 993252867Sdelphij } 994252867Sdelphij 995252867Sdelphij switch (cdb[0]) { 996252867Sdelphij case READ_6: 997252867Sdelphij case WRITE_6: 998252867Sdelphij case 0x13: 999252867Sdelphij pCmd->uCmd.Ide.Lba = ((HPT_U32)cdb[1] << 16) | ((HPT_U32)cdb[2] << 8) | (HPT_U32)cdb[3]; 1000252867Sdelphij pCmd->uCmd.Ide.nSectors = (HPT_U16) cdb[4]; 1001252867Sdelphij break; 1002252867Sdelphij case READ_16: 1003252867Sdelphij case WRITE_16: 1004252867Sdelphij case 0x8f: /* VERIFY_16 */ 1005252867Sdelphij { 1006252867Sdelphij HPT_U64 block = 1007252867Sdelphij ((HPT_U64)cdb[2]<<56) | 1008252867Sdelphij ((HPT_U64)cdb[3]<<48) | 1009252867Sdelphij ((HPT_U64)cdb[4]<<40) | 1010252867Sdelphij ((HPT_U64)cdb[5]<<32) | 1011252867Sdelphij ((HPT_U64)cdb[6]<<24) | 1012252867Sdelphij ((HPT_U64)cdb[7]<<16) | 1013252867Sdelphij ((HPT_U64)cdb[8]<<8) | 1014252867Sdelphij ((HPT_U64)cdb[9]); 1015252867Sdelphij pCmd->uCmd.Ide.Lba = block; 1016252867Sdelphij pCmd->uCmd.Ide.nSectors = (HPT_U16)cdb[13] | ((HPT_U16)cdb[12]<<8); 1017252867Sdelphij break; 1018252867Sdelphij } 1019252867Sdelphij 1020252867Sdelphij default: 1021252867Sdelphij pCmd->uCmd.Ide.Lba = (HPT_U32)cdb[5] | ((HPT_U32)cdb[4] << 8) | ((HPT_U32)cdb[3] << 16) | ((HPT_U32)cdb[2] << 24); 1022252867Sdelphij pCmd->uCmd.Ide.nSectors = (HPT_U16) cdb[8] | ((HPT_U16)cdb[7]<<8); 1023252867Sdelphij break; 1024252867Sdelphij } 1025281957Sdelphij 1026281957Sdelphij if(mIsArray(vd->type)) { 1027281957Sdelphij sector_size_shift = vd->u.array.sector_size_shift; 1028281957Sdelphij } 1029281957Sdelphij else{ 1030281957Sdelphij if(vd->type == VD_RAW){ 1031281957Sdelphij sector_size = vd->u.raw.logical_sector_size; 1032281957Sdelphij } 1033281957Sdelphij 1034281957Sdelphij switch (sector_size) { 1035281957Sdelphij case 0x1000: 1036281957Sdelphij KdPrint(("<8>resize sector size from 4k to 512")); 1037281957Sdelphij sector_size_shift = 3; 1038281957Sdelphij break; 1039281957Sdelphij default: 1040281957Sdelphij break; 1041281957Sdelphij } 1042281957Sdelphij } 1043281957Sdelphij pCmd->uCmd.Ide.Lba <<= sector_size_shift; 1044281957Sdelphij pCmd->uCmd.Ide.nSectors <<= sector_size_shift; 1045281957Sdelphij 1046252867Sdelphij 1047252867Sdelphij switch (cdb[0]) { 1048252867Sdelphij case READ_6: 1049252867Sdelphij case READ_10: 1050252867Sdelphij case READ_16: 1051252867Sdelphij pCmd->flags.data_in = 1; 1052252867Sdelphij break; 1053252867Sdelphij case WRITE_6: 1054252867Sdelphij case WRITE_10: 1055252867Sdelphij case WRITE_16: 1056252867Sdelphij pCmd->flags.data_out = 1; 1057252867Sdelphij break; 1058252867Sdelphij } 1059252867Sdelphij pCmd->priv = ext = cmdext_get(vbus_ext); 1060252867Sdelphij HPT_ASSERT(ext); 1061252867Sdelphij ext->ccb = ccb; 1062252867Sdelphij pCmd->target = vd; 1063252867Sdelphij pCmd->done = os_cmddone; 1064252867Sdelphij pCmd->buildsgl = os_buildsgl; 1065252867Sdelphij pCmd->psg = ext->psg; 1066252867Sdelphij pCmd->flags.physical_sg = 1; 1067252867Sdelphij error = bus_dmamap_load_ccb(vbus_ext->io_dmat, 1068252867Sdelphij ext->dma_map, ccb, 1069252867Sdelphij hpt_io_dmamap_callback, pCmd, 1070252867Sdelphij BUS_DMA_WAITOK 1071252867Sdelphij ); 1072252867Sdelphij KdPrint(("bus_dmamap_load return %d", error)); 1073252867Sdelphij if (error && error!=EINPROGRESS) { 1074252867Sdelphij os_printk("bus_dmamap_load error %d", error); 1075252867Sdelphij cmdext_put(ext); 1076252867Sdelphij ldm_free_cmds(pCmd); 1077252867Sdelphij ccb->ccb_h.status = CAM_REQ_CMP_ERR; 1078252867Sdelphij xpt_done(ccb); 1079252867Sdelphij } 1080252867Sdelphij return; 1081252867Sdelphij } 1082252867Sdelphij 1083252867Sdelphij default: 1084284935Sdelphij ccb->ccb_h.status = CAM_REQ_INVALID; 1085252867Sdelphij break; 1086252867Sdelphij } 1087252867Sdelphij 1088252867Sdelphij xpt_done(ccb); 1089252867Sdelphij return; 1090252867Sdelphij} 1091252867Sdelphij 1092252867Sdelphijstatic void hpt_action(struct cam_sim *sim, union ccb *ccb) 1093252867Sdelphij{ 1094252867Sdelphij PVBUS_EXT vbus_ext = (PVBUS_EXT)cam_sim_softc(sim); 1095252867Sdelphij 1096252867Sdelphij KdPrint(("hpt_action(fn=%d, id=%d)", ccb->ccb_h.func_code, ccb->ccb_h.target_id)); 1097252867Sdelphij 1098275980Ssmh hpt_assert_vbus_locked(vbus_ext); 1099252867Sdelphij switch (ccb->ccb_h.func_code) { 1100252867Sdelphij 1101252867Sdelphij case XPT_SCSI_IO: 1102252867Sdelphij hpt_scsi_io(vbus_ext, ccb); 1103252867Sdelphij return; 1104252867Sdelphij 1105252867Sdelphij case XPT_RESET_BUS: 1106252867Sdelphij ldm_reset_vbus((PVBUS)vbus_ext->vbus); 1107252867Sdelphij break; 1108252867Sdelphij 1109252867Sdelphij case XPT_GET_TRAN_SETTINGS: 1110252867Sdelphij case XPT_SET_TRAN_SETTINGS: 1111252867Sdelphij ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 1112252867Sdelphij break; 1113252867Sdelphij 1114252867Sdelphij case XPT_CALC_GEOMETRY: 1115252867Sdelphij ccb->ccg.heads = 255; 1116252867Sdelphij ccb->ccg.secs_per_track = 63; 1117252867Sdelphij ccb->ccg.cylinders = ccb->ccg.volume_size / (ccb->ccg.heads * ccb->ccg.secs_per_track); 1118252867Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 1119252867Sdelphij break; 1120252867Sdelphij 1121252867Sdelphij case XPT_PATH_INQ: 1122252867Sdelphij { 1123252867Sdelphij struct ccb_pathinq *cpi = &ccb->cpi; 1124252867Sdelphij 1125252867Sdelphij cpi->version_num = 1; 1126252867Sdelphij cpi->hba_inquiry = PI_SDTR_ABLE; 1127252867Sdelphij cpi->target_sprt = 0; 1128252867Sdelphij cpi->hba_misc = PIM_NOBUSRESET; 1129252867Sdelphij cpi->hba_eng_cnt = 0; 1130252867Sdelphij cpi->max_target = osm_max_targets; 1131252867Sdelphij cpi->max_lun = 0; 1132252867Sdelphij cpi->unit_number = cam_sim_unit(sim); 1133252867Sdelphij cpi->bus_id = cam_sim_bus(sim); 1134252867Sdelphij cpi->initiator_id = osm_max_targets; 1135252867Sdelphij cpi->base_transfer_speed = 3300; 1136252867Sdelphij 1137252867Sdelphij strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 1138252867Sdelphij strncpy(cpi->hba_vid, "HPT ", HBA_IDLEN); 1139252867Sdelphij strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 1140252867Sdelphij cpi->transport = XPORT_SPI; 1141252867Sdelphij cpi->transport_version = 2; 1142252867Sdelphij cpi->protocol = PROTO_SCSI; 1143252867Sdelphij cpi->protocol_version = SCSI_REV_2; 1144252867Sdelphij cpi->ccb_h.status = CAM_REQ_CMP; 1145252867Sdelphij break; 1146252867Sdelphij } 1147252867Sdelphij 1148252867Sdelphij default: 1149252867Sdelphij ccb->ccb_h.status = CAM_REQ_INVALID; 1150252867Sdelphij break; 1151252867Sdelphij } 1152252867Sdelphij 1153252867Sdelphij xpt_done(ccb); 1154252867Sdelphij return; 1155252867Sdelphij} 1156252867Sdelphij 1157252867Sdelphijstatic void hpt_pci_intr(void *arg) 1158252867Sdelphij{ 1159252867Sdelphij PVBUS_EXT vbus_ext = (PVBUS_EXT)arg; 1160252867Sdelphij hpt_lock_vbus(vbus_ext); 1161252867Sdelphij ldm_intr((PVBUS)vbus_ext->vbus); 1162252867Sdelphij hpt_unlock_vbus(vbus_ext); 1163252867Sdelphij} 1164252867Sdelphij 1165252867Sdelphijstatic void hpt_poll(struct cam_sim *sim) 1166252867Sdelphij{ 1167275980Ssmh PVBUS_EXT vbus_ext = cam_sim_softc(sim); 1168275980Ssmh hpt_assert_vbus_locked(vbus_ext); 1169275980Ssmh ldm_intr((PVBUS)vbus_ext->vbus); 1170252867Sdelphij} 1171252867Sdelphij 1172252867Sdelphijstatic void hpt_async(void * callback_arg, u_int32_t code, struct cam_path * path, void * arg) 1173252867Sdelphij{ 1174252867Sdelphij KdPrint(("hpt_async")); 1175252867Sdelphij} 1176252867Sdelphij 1177252867Sdelphijstatic int hpt_shutdown(device_t dev) 1178252867Sdelphij{ 1179252867Sdelphij KdPrint(("hpt_shutdown(dev=%p)", dev)); 1180252867Sdelphij return 0; 1181252867Sdelphij} 1182252867Sdelphij 1183252867Sdelphijstatic int hpt_detach(device_t dev) 1184252867Sdelphij{ 1185252867Sdelphij /* we don't allow the driver to be unloaded. */ 1186252867Sdelphij return EBUSY; 1187252867Sdelphij} 1188252867Sdelphij 1189252867Sdelphijstatic void hpt_ioctl_done(struct _IOCTL_ARG *arg) 1190252867Sdelphij{ 1191252867Sdelphij arg->ioctl_cmnd = 0; 1192252867Sdelphij wakeup(arg); 1193252867Sdelphij} 1194252867Sdelphij 1195252867Sdelphijstatic void __hpt_do_ioctl(PVBUS_EXT vbus_ext, IOCTL_ARG *ioctl_args) 1196252867Sdelphij{ 1197252867Sdelphij ioctl_args->result = -1; 1198252867Sdelphij ioctl_args->done = hpt_ioctl_done; 1199252867Sdelphij ioctl_args->ioctl_cmnd = (void *)1; 1200252867Sdelphij 1201252867Sdelphij hpt_lock_vbus(vbus_ext); 1202252867Sdelphij ldm_ioctl((PVBUS)vbus_ext->vbus, ioctl_args); 1203252867Sdelphij 1204252867Sdelphij while (ioctl_args->ioctl_cmnd) { 1205252867Sdelphij if (hpt_sleep(vbus_ext, ioctl_args, PPAUSE, "hptctl", HPT_OSM_TIMEOUT)==0) 1206252867Sdelphij break; 1207252867Sdelphij ldm_reset_vbus((PVBUS)vbus_ext->vbus); 1208252867Sdelphij __hpt_do_tasks(vbus_ext); 1209252867Sdelphij } 1210252867Sdelphij 1211252867Sdelphij /* KdPrint(("ioctl %x result %d", ioctl_args->dwIoControlCode, ioctl_args->result)); */ 1212252867Sdelphij 1213252867Sdelphij hpt_unlock_vbus(vbus_ext); 1214252867Sdelphij} 1215252867Sdelphij 1216252867Sdelphijstatic void hpt_do_ioctl(IOCTL_ARG *ioctl_args) 1217252867Sdelphij{ 1218252867Sdelphij PVBUS vbus; 1219252867Sdelphij PVBUS_EXT vbus_ext; 1220252867Sdelphij 1221252867Sdelphij ldm_for_each_vbus(vbus, vbus_ext) { 1222252867Sdelphij __hpt_do_ioctl(vbus_ext, ioctl_args); 1223252867Sdelphij if (ioctl_args->result!=HPT_IOCTL_RESULT_WRONG_VBUS) 1224252867Sdelphij return; 1225252867Sdelphij } 1226252867Sdelphij} 1227252867Sdelphij 1228252867Sdelphij#define HPT_DO_IOCTL(code, inbuf, insize, outbuf, outsize) ({\ 1229252867Sdelphij IOCTL_ARG arg;\ 1230252867Sdelphij arg.dwIoControlCode = code;\ 1231252867Sdelphij arg.lpInBuffer = inbuf;\ 1232252867Sdelphij arg.lpOutBuffer = outbuf;\ 1233252867Sdelphij arg.nInBufferSize = insize;\ 1234252867Sdelphij arg.nOutBufferSize = outsize;\ 1235252867Sdelphij arg.lpBytesReturned = 0;\ 1236252867Sdelphij hpt_do_ioctl(&arg);\ 1237252867Sdelphij arg.result;\ 1238252867Sdelphij}) 1239252867Sdelphij 1240252867Sdelphij#define DEVICEID_VALID(id) ((id) && ((HPT_U32)(id)!=0xffffffff)) 1241252867Sdelphij 1242252867Sdelphijstatic int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount) 1243252867Sdelphij{ 1244252867Sdelphij int i; 1245252867Sdelphij HPT_U32 count = nMaxCount-1; 1246252867Sdelphij 1247252867Sdelphij if (HPT_DO_IOCTL(HPT_IOCTL_GET_LOGICAL_DEVICES, 1248252867Sdelphij &count, sizeof(HPT_U32), pIds, sizeof(DEVICEID)*nMaxCount)) 1249252867Sdelphij return -1; 1250252867Sdelphij 1251252867Sdelphij nMaxCount = (int)pIds[0]; 1252252867Sdelphij for (i=0; i<nMaxCount; i++) pIds[i] = pIds[i+1]; 1253252867Sdelphij return nMaxCount; 1254252867Sdelphij} 1255252867Sdelphij 1256252867Sdelphijstatic int hpt_get_device_info_v3(DEVICEID id, PLOGICAL_DEVICE_INFO_V3 pInfo) 1257252867Sdelphij{ 1258252867Sdelphij return HPT_DO_IOCTL(HPT_IOCTL_GET_DEVICE_INFO_V3, 1259252867Sdelphij &id, sizeof(DEVICEID), pInfo, sizeof(LOGICAL_DEVICE_INFO_V3)); 1260252867Sdelphij} 1261252867Sdelphij 1262252867Sdelphij/* not belong to this file logically, but we want to use ioctl interface */ 1263252867Sdelphijstatic int __hpt_stop_tasks(PVBUS_EXT vbus_ext, DEVICEID id) 1264252867Sdelphij{ 1265252867Sdelphij LOGICAL_DEVICE_INFO_V3 devinfo; 1266252867Sdelphij int i, result; 1267252867Sdelphij DEVICEID param[2] = { id, 0 }; 1268252867Sdelphij 1269252867Sdelphij if (hpt_get_device_info_v3(id, &devinfo)) 1270252867Sdelphij return -1; 1271252867Sdelphij 1272252867Sdelphij if (devinfo.Type!=LDT_ARRAY) 1273252867Sdelphij return -1; 1274252867Sdelphij 1275252867Sdelphij if (devinfo.u.array.Flags & ARRAY_FLAG_REBUILDING) 1276252867Sdelphij param[1] = AS_REBUILD_ABORT; 1277252867Sdelphij else if (devinfo.u.array.Flags & ARRAY_FLAG_VERIFYING) 1278252867Sdelphij param[1] = AS_VERIFY_ABORT; 1279252867Sdelphij else if (devinfo.u.array.Flags & ARRAY_FLAG_INITIALIZING) 1280252867Sdelphij param[1] = AS_INITIALIZE_ABORT; 1281252867Sdelphij else if (devinfo.u.array.Flags & ARRAY_FLAG_TRANSFORMING) 1282252867Sdelphij param[1] = AS_TRANSFORM_ABORT; 1283252867Sdelphij else 1284252867Sdelphij return -1; 1285252867Sdelphij 1286252867Sdelphij KdPrint(("SET_ARRAY_STATE(%x, %d)", param[0], param[1])); 1287252867Sdelphij result = HPT_DO_IOCTL(HPT_IOCTL_SET_ARRAY_STATE, 1288252867Sdelphij param, sizeof(param), 0, 0); 1289252867Sdelphij 1290252867Sdelphij for (i=0; i<devinfo.u.array.nDisk; i++) 1291252867Sdelphij if (DEVICEID_VALID(devinfo.u.array.Members[i])) 1292252867Sdelphij __hpt_stop_tasks(vbus_ext, devinfo.u.array.Members[i]); 1293252867Sdelphij 1294252867Sdelphij return result; 1295252867Sdelphij} 1296252867Sdelphij 1297252867Sdelphijstatic void hpt_stop_tasks(PVBUS_EXT vbus_ext) 1298252867Sdelphij{ 1299252867Sdelphij DEVICEID ids[32]; 1300252867Sdelphij int i, count; 1301252867Sdelphij 1302252867Sdelphij count = hpt_get_logical_devices((DEVICEID *)&ids, sizeof(ids)/sizeof(ids[0])); 1303252867Sdelphij 1304252867Sdelphij for (i=0; i<count; i++) 1305252867Sdelphij __hpt_stop_tasks(vbus_ext, ids[i]); 1306252867Sdelphij} 1307252867Sdelphij 1308252867Sdelphijstatic d_open_t hpt_open; 1309252867Sdelphijstatic d_close_t hpt_close; 1310252867Sdelphijstatic d_ioctl_t hpt_ioctl; 1311252867Sdelphijstatic int hpt_rescan_bus(void); 1312252867Sdelphij 1313252867Sdelphijstatic struct cdevsw hpt_cdevsw = { 1314252867Sdelphij .d_open = hpt_open, 1315252867Sdelphij .d_close = hpt_close, 1316252867Sdelphij .d_ioctl = hpt_ioctl, 1317252867Sdelphij .d_name = driver_name, 1318252867Sdelphij .d_version = D_VERSION, 1319252867Sdelphij}; 1320252867Sdelphij 1321252867Sdelphijstatic struct intr_config_hook hpt_ich; 1322252867Sdelphij 1323252867Sdelphij/* 1324252867Sdelphij * hpt_final_init will be called after all hpt_attach. 1325252867Sdelphij */ 1326252867Sdelphijstatic void hpt_final_init(void *dummy) 1327252867Sdelphij{ 1328252867Sdelphij int i,unit_number=0; 1329252867Sdelphij PVBUS_EXT vbus_ext; 1330252867Sdelphij PVBUS vbus; 1331252867Sdelphij PHBA hba; 1332252867Sdelphij 1333252867Sdelphij /* Clear the config hook */ 1334252867Sdelphij config_intrhook_disestablish(&hpt_ich); 1335252867Sdelphij 1336252867Sdelphij /* allocate memory */ 1337252867Sdelphij i = 0; 1338252867Sdelphij ldm_for_each_vbus(vbus, vbus_ext) { 1339252867Sdelphij if (hpt_alloc_mem(vbus_ext)) { 1340252867Sdelphij os_printk("out of memory"); 1341252867Sdelphij return; 1342252867Sdelphij } 1343252867Sdelphij i++; 1344252867Sdelphij } 1345252867Sdelphij 1346252867Sdelphij if (!i) { 1347252867Sdelphij if (bootverbose) 1348252867Sdelphij os_printk("no controller detected."); 1349252867Sdelphij return; 1350252867Sdelphij } 1351252867Sdelphij 1352252867Sdelphij /* initializing hardware */ 1353252867Sdelphij ldm_for_each_vbus(vbus, vbus_ext) { 1354252867Sdelphij /* make timer available here */ 1355275980Ssmh mtx_init(&vbus_ext->lock, "hptsleeplock", NULL, MTX_DEF); 1356275980Ssmh callout_init_mtx(&vbus_ext->timer, &vbus_ext->lock, 0); 1357252867Sdelphij if (hpt_init_vbus(vbus_ext)) { 1358252867Sdelphij os_printk("fail to initialize hardware"); 1359252867Sdelphij break; /* FIXME */ 1360252867Sdelphij } 1361252867Sdelphij } 1362252867Sdelphij 1363252867Sdelphij /* register CAM interface */ 1364252867Sdelphij ldm_for_each_vbus(vbus, vbus_ext) { 1365252867Sdelphij struct cam_devq *devq; 1366252867Sdelphij struct ccb_setasync ccb; 1367252867Sdelphij 1368252867Sdelphij if (bus_dma_tag_create(NULL,/* parent */ 1369252867Sdelphij 4, /* alignment */ 1370252867Sdelphij BUS_SPACE_MAXADDR_32BIT+1, /* boundary */ 1371252867Sdelphij BUS_SPACE_MAXADDR, /* lowaddr */ 1372252867Sdelphij BUS_SPACE_MAXADDR, /* highaddr */ 1373252867Sdelphij NULL, NULL, /* filter, filterarg */ 1374252867Sdelphij PAGE_SIZE * (os_max_sg_descriptors-1), /* maxsize */ 1375252867Sdelphij os_max_sg_descriptors, /* nsegments */ 1376252867Sdelphij 0x10000, /* maxsegsize */ 1377252867Sdelphij BUS_DMA_WAITOK, /* flags */ 1378252867Sdelphij busdma_lock_mutex, /* lockfunc */ 1379252867Sdelphij &vbus_ext->lock, /* lockfuncarg */ 1380252867Sdelphij &vbus_ext->io_dmat /* tag */)) 1381252867Sdelphij { 1382252867Sdelphij return ; 1383252867Sdelphij } 1384252867Sdelphij 1385252867Sdelphij for (i=0; i<os_max_queue_comm; i++) { 1386252867Sdelphij POS_CMDEXT ext = (POS_CMDEXT)malloc(sizeof(OS_CMDEXT), M_DEVBUF, M_WAITOK); 1387252867Sdelphij if (!ext) { 1388252867Sdelphij os_printk("Can't alloc cmdext(%d)", i); 1389252867Sdelphij return ; 1390252867Sdelphij } 1391252867Sdelphij ext->vbus_ext = vbus_ext; 1392252867Sdelphij ext->next = vbus_ext->cmdext_list; 1393252867Sdelphij vbus_ext->cmdext_list = ext; 1394252867Sdelphij 1395252867Sdelphij if (bus_dmamap_create(vbus_ext->io_dmat, 0, &ext->dma_map)) { 1396252867Sdelphij os_printk("Can't create dma map(%d)", i); 1397252867Sdelphij return ; 1398252867Sdelphij } 1399275980Ssmh callout_init_mtx(&ext->timeout, &vbus_ext->lock, 0); 1400252867Sdelphij } 1401252867Sdelphij 1402252867Sdelphij if ((devq = cam_simq_alloc(os_max_queue_comm)) == NULL) { 1403252867Sdelphij os_printk("cam_simq_alloc failed"); 1404252867Sdelphij return ; 1405252867Sdelphij } 1406252867Sdelphij 1407275980Ssmh hpt_lock_vbus(vbus_ext); 1408252867Sdelphij vbus_ext->sim = cam_sim_alloc(hpt_action, hpt_poll, driver_name, 1409275980Ssmh vbus_ext, unit_number, &vbus_ext->lock, 1410275980Ssmh os_max_queue_comm, /*tagged*/8, devq); 1411252867Sdelphij unit_number++; 1412252867Sdelphij if (!vbus_ext->sim) { 1413252867Sdelphij os_printk("cam_sim_alloc failed"); 1414252867Sdelphij cam_simq_free(devq); 1415275980Ssmh hpt_unlock_vbus(vbus_ext); 1416252867Sdelphij return ; 1417252867Sdelphij } 1418252867Sdelphij 1419252867Sdelphij if (xpt_bus_register(vbus_ext->sim, NULL, 0) != CAM_SUCCESS) { 1420252867Sdelphij os_printk("xpt_bus_register failed"); 1421252867Sdelphij cam_sim_free(vbus_ext->sim, /*free devq*/ TRUE); 1422252867Sdelphij vbus_ext->sim = NULL; 1423252867Sdelphij return ; 1424252867Sdelphij } 1425252867Sdelphij 1426252867Sdelphij if (xpt_create_path(&vbus_ext->path, /*periph */ NULL, 1427252867Sdelphij cam_sim_path(vbus_ext->sim), CAM_TARGET_WILDCARD, 1428252867Sdelphij CAM_LUN_WILDCARD) != CAM_REQ_CMP) 1429252867Sdelphij { 1430252867Sdelphij os_printk("xpt_create_path failed"); 1431252867Sdelphij xpt_bus_deregister(cam_sim_path(vbus_ext->sim)); 1432252867Sdelphij cam_sim_free(vbus_ext->sim, /*free_devq*/TRUE); 1433275980Ssmh hpt_unlock_vbus(vbus_ext); 1434252867Sdelphij vbus_ext->sim = NULL; 1435252867Sdelphij return ; 1436252867Sdelphij } 1437275980Ssmh hpt_unlock_vbus(vbus_ext); 1438252867Sdelphij 1439252867Sdelphij xpt_setup_ccb(&ccb.ccb_h, vbus_ext->path, /*priority*/5); 1440252867Sdelphij ccb.ccb_h.func_code = XPT_SASYNC_CB; 1441252867Sdelphij ccb.event_enable = AC_LOST_DEVICE; 1442252867Sdelphij ccb.callback = hpt_async; 1443252867Sdelphij ccb.callback_arg = vbus_ext; 1444252867Sdelphij xpt_action((union ccb *)&ccb); 1445252867Sdelphij 1446252867Sdelphij for (hba = vbus_ext->hba_list; hba; hba = hba->next) { 1447252867Sdelphij int rid = 0; 1448252867Sdelphij if ((hba->irq_res = bus_alloc_resource(hba->pcidev, 1449252867Sdelphij SYS_RES_IRQ, &rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) 1450252867Sdelphij { 1451252867Sdelphij os_printk("can't allocate interrupt"); 1452252867Sdelphij return ; 1453252867Sdelphij } 1454252867Sdelphij 1455275980Ssmh if (bus_setup_intr(hba->pcidev, hba->irq_res, INTR_TYPE_CAM | INTR_MPSAFE, 1456252867Sdelphij NULL, hpt_pci_intr, vbus_ext, &hba->irq_handle)) 1457252867Sdelphij { 1458252867Sdelphij os_printk("can't set up interrupt"); 1459252867Sdelphij return ; 1460252867Sdelphij } 1461252867Sdelphij hba->ldm_adapter.him->intr_control(hba->ldm_adapter.him_handle, HPT_TRUE); 1462252867Sdelphij 1463252867Sdelphij } 1464252867Sdelphij 1465252867Sdelphij vbus_ext->shutdown_eh = EVENTHANDLER_REGISTER(shutdown_final, 1466252867Sdelphij hpt_shutdown_vbus, vbus_ext, SHUTDOWN_PRI_DEFAULT); 1467252867Sdelphij if (!vbus_ext->shutdown_eh) 1468252867Sdelphij os_printk("Shutdown event registration failed"); 1469252867Sdelphij } 1470252867Sdelphij 1471252867Sdelphij ldm_for_each_vbus(vbus, vbus_ext) { 1472252867Sdelphij TASK_INIT(&vbus_ext->worker, 0, (task_fn_t *)hpt_do_tasks, vbus_ext); 1473252867Sdelphij if (vbus_ext->tasks) 1474252867Sdelphij TASK_ENQUEUE(&vbus_ext->worker); 1475252867Sdelphij } 1476252867Sdelphij 1477252867Sdelphij make_dev(&hpt_cdevsw, DRIVER_MINOR, UID_ROOT, GID_OPERATOR, 1478252867Sdelphij S_IRUSR | S_IWUSR, "%s", driver_name); 1479252867Sdelphij} 1480252867Sdelphij 1481275980Ssmh#if defined(KLD_MODULE) 1482252867Sdelphij 1483252867Sdelphijtypedef struct driverlink *driverlink_t; 1484252867Sdelphijstruct driverlink { 1485252867Sdelphij kobj_class_t driver; 1486252867Sdelphij TAILQ_ENTRY(driverlink) link; /* list of drivers in devclass */ 1487252867Sdelphij}; 1488252867Sdelphij 1489252867Sdelphijtypedef TAILQ_HEAD(driver_list, driverlink) driver_list_t; 1490252867Sdelphij 1491252867Sdelphijstruct devclass { 1492252867Sdelphij TAILQ_ENTRY(devclass) link; 1493252867Sdelphij devclass_t parent; /* parent in devclass hierarchy */ 1494252867Sdelphij driver_list_t drivers; /* bus devclasses store drivers for bus */ 1495252867Sdelphij char *name; 1496252867Sdelphij device_t *devices; /* array of devices indexed by unit */ 1497252867Sdelphij int maxunit; /* size of devices array */ 1498252867Sdelphij}; 1499252867Sdelphij 1500252867Sdelphijstatic void override_kernel_driver(void) 1501252867Sdelphij{ 1502252867Sdelphij driverlink_t dl, dlfirst; 1503252867Sdelphij driver_t *tmpdriver; 1504252867Sdelphij devclass_t dc = devclass_find("pci"); 1505252867Sdelphij 1506252867Sdelphij if (dc){ 1507252867Sdelphij dlfirst = TAILQ_FIRST(&dc->drivers); 1508252867Sdelphij for (dl = dlfirst; dl; dl = TAILQ_NEXT(dl, link)) { 1509252867Sdelphij if(strcmp(dl->driver->name, driver_name) == 0) { 1510252867Sdelphij tmpdriver=dl->driver; 1511252867Sdelphij dl->driver=dlfirst->driver; 1512252867Sdelphij dlfirst->driver=tmpdriver; 1513252867Sdelphij break; 1514252867Sdelphij } 1515252867Sdelphij } 1516252867Sdelphij } 1517252867Sdelphij} 1518252867Sdelphij 1519252867Sdelphij#else 1520252867Sdelphij#define override_kernel_driver() 1521252867Sdelphij#endif 1522252867Sdelphij 1523252867Sdelphijstatic void hpt_init(void *dummy) 1524252867Sdelphij{ 1525252867Sdelphij if (bootverbose) 1526252867Sdelphij os_printk("%s %s", driver_name_long, driver_ver); 1527252867Sdelphij 1528252867Sdelphij override_kernel_driver(); 1529252867Sdelphij init_config(); 1530252867Sdelphij 1531252867Sdelphij hpt_ich.ich_func = hpt_final_init; 1532252867Sdelphij hpt_ich.ich_arg = NULL; 1533252867Sdelphij if (config_intrhook_establish(&hpt_ich) != 0) { 1534252867Sdelphij printf("%s: cannot establish configuration hook\n", 1535252867Sdelphij driver_name_long); 1536252867Sdelphij } 1537252867Sdelphij 1538252867Sdelphij} 1539252867SdelphijSYSINIT(hptinit, SI_SUB_CONFIGURE, SI_ORDER_FIRST, hpt_init, NULL); 1540252867Sdelphij 1541252867Sdelphij/* 1542252867Sdelphij * CAM driver interface 1543252867Sdelphij */ 1544252867Sdelphijstatic device_method_t driver_methods[] = { 1545252867Sdelphij /* Device interface */ 1546252867Sdelphij DEVMETHOD(device_probe, hpt_probe), 1547252867Sdelphij DEVMETHOD(device_attach, hpt_attach), 1548252867Sdelphij DEVMETHOD(device_detach, hpt_detach), 1549252867Sdelphij DEVMETHOD(device_shutdown, hpt_shutdown), 1550252867Sdelphij { 0, 0 } 1551252867Sdelphij}; 1552252867Sdelphij 1553252867Sdelphijstatic driver_t hpt_pci_driver = { 1554252867Sdelphij driver_name, 1555252867Sdelphij driver_methods, 1556252867Sdelphij sizeof(HBA) 1557252867Sdelphij}; 1558252867Sdelphij 1559252867Sdelphijstatic devclass_t hpt_devclass; 1560252867Sdelphij 1561252867Sdelphij#ifndef TARGETNAME 1562252867Sdelphij#error "no TARGETNAME found" 1563252867Sdelphij#endif 1564252867Sdelphij 1565252867Sdelphij/* use this to make TARGETNAME be expanded */ 1566252867Sdelphij#define __DRIVER_MODULE(p1, p2, p3, p4, p5, p6) DRIVER_MODULE(p1, p2, p3, p4, p5, p6) 1567252867Sdelphij#define __MODULE_VERSION(p1, p2) MODULE_VERSION(p1, p2) 1568252867Sdelphij#define __MODULE_DEPEND(p1, p2, p3, p4, p5) MODULE_DEPEND(p1, p2, p3, p4, p5) 1569252867Sdelphij__DRIVER_MODULE(TARGETNAME, pci, hpt_pci_driver, hpt_devclass, 0, 0); 1570252867Sdelphij__MODULE_VERSION(TARGETNAME, 1); 1571252867Sdelphij__MODULE_DEPEND(TARGETNAME, cam, 1, 1, 1); 1572252867Sdelphij 1573275980Ssmhstatic int hpt_open(struct cdev *dev, int flags, int devtype, struct thread *td) 1574252867Sdelphij{ 1575252867Sdelphij return 0; 1576252867Sdelphij} 1577252867Sdelphij 1578275980Ssmhstatic int hpt_close(struct cdev *dev, int flags, int devtype, struct thread *td) 1579252867Sdelphij{ 1580252867Sdelphij return 0; 1581252867Sdelphij} 1582252867Sdelphij 1583275980Ssmhstatic int hpt_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td) 1584252867Sdelphij{ 1585252867Sdelphij PHPT_IOCTL_PARAM piop=(PHPT_IOCTL_PARAM)data; 1586252867Sdelphij IOCTL_ARG ioctl_args; 1587331987Sgordon HPT_U32 bytesReturned = 0; 1588252867Sdelphij 1589252867Sdelphij switch (cmd){ 1590252867Sdelphij case HPT_DO_IOCONTROL: 1591252867Sdelphij { 1592252867Sdelphij if (piop->Magic == HPT_IOCTL_MAGIC || piop->Magic == HPT_IOCTL_MAGIC32) { 1593252867Sdelphij KdPrint(("ioctl=%x in=%p len=%d out=%p len=%d\n", 1594252867Sdelphij piop->dwIoControlCode, 1595252867Sdelphij piop->lpInBuffer, 1596252867Sdelphij piop->nInBufferSize, 1597252867Sdelphij piop->lpOutBuffer, 1598252867Sdelphij piop->nOutBufferSize)); 1599252867Sdelphij 1600252867Sdelphij memset(&ioctl_args, 0, sizeof(ioctl_args)); 1601252867Sdelphij 1602252867Sdelphij ioctl_args.dwIoControlCode = piop->dwIoControlCode; 1603252867Sdelphij ioctl_args.nInBufferSize = piop->nInBufferSize; 1604252867Sdelphij ioctl_args.nOutBufferSize = piop->nOutBufferSize; 1605252867Sdelphij ioctl_args.lpBytesReturned = &bytesReturned; 1606252867Sdelphij 1607252867Sdelphij if (ioctl_args.nInBufferSize) { 1608252867Sdelphij ioctl_args.lpInBuffer = malloc(ioctl_args.nInBufferSize, M_DEVBUF, M_WAITOK); 1609252867Sdelphij if (!ioctl_args.lpInBuffer) 1610252867Sdelphij goto invalid; 1611252867Sdelphij if (copyin((void*)piop->lpInBuffer, 1612252867Sdelphij ioctl_args.lpInBuffer, piop->nInBufferSize)) 1613252867Sdelphij goto invalid; 1614252867Sdelphij } 1615252867Sdelphij 1616252867Sdelphij if (ioctl_args.nOutBufferSize) { 1617331987Sgordon ioctl_args.lpOutBuffer = malloc(ioctl_args.nOutBufferSize, M_DEVBUF, M_WAITOK | M_ZERO); 1618252867Sdelphij if (!ioctl_args.lpOutBuffer) 1619252867Sdelphij goto invalid; 1620252867Sdelphij } 1621252867Sdelphij 1622252867Sdelphij hpt_do_ioctl(&ioctl_args); 1623252867Sdelphij 1624252867Sdelphij if (ioctl_args.result==HPT_IOCTL_RESULT_OK) { 1625252867Sdelphij if (piop->nOutBufferSize) { 1626252867Sdelphij if (copyout(ioctl_args.lpOutBuffer, 1627252867Sdelphij (void*)piop->lpOutBuffer, piop->nOutBufferSize)) 1628252867Sdelphij goto invalid; 1629252867Sdelphij } 1630252867Sdelphij if (piop->lpBytesReturned) { 1631252867Sdelphij if (copyout(&bytesReturned, 1632252867Sdelphij (void*)piop->lpBytesReturned, sizeof(HPT_U32))) 1633252867Sdelphij goto invalid; 1634252867Sdelphij } 1635252867Sdelphij if (ioctl_args.lpInBuffer) free(ioctl_args.lpInBuffer, M_DEVBUF); 1636252867Sdelphij if (ioctl_args.lpOutBuffer) free(ioctl_args.lpOutBuffer, M_DEVBUF); 1637252867Sdelphij return 0; 1638252867Sdelphij } 1639252867Sdelphijinvalid: 1640252867Sdelphij if (ioctl_args.lpInBuffer) free(ioctl_args.lpInBuffer, M_DEVBUF); 1641252867Sdelphij if (ioctl_args.lpOutBuffer) free(ioctl_args.lpOutBuffer, M_DEVBUF); 1642252867Sdelphij return EFAULT; 1643252867Sdelphij } 1644252867Sdelphij return EFAULT; 1645252867Sdelphij } 1646252867Sdelphij 1647252867Sdelphij case HPT_SCAN_BUS: 1648252867Sdelphij { 1649252867Sdelphij return hpt_rescan_bus(); 1650252867Sdelphij } 1651252867Sdelphij default: 1652252867Sdelphij KdPrint(("invalid command!")); 1653252867Sdelphij return EFAULT; 1654252867Sdelphij } 1655252867Sdelphij 1656252867Sdelphij} 1657252867Sdelphij 1658252867Sdelphijstatic int hpt_rescan_bus(void) 1659252867Sdelphij{ 1660252867Sdelphij union ccb *ccb; 1661252867Sdelphij PVBUS vbus; 1662252867Sdelphij PVBUS_EXT vbus_ext; 1663252867Sdelphij 1664252867Sdelphij ldm_for_each_vbus(vbus, vbus_ext) { 1665252867Sdelphij if ((ccb = xpt_alloc_ccb()) == NULL) 1666252867Sdelphij { 1667252867Sdelphij return(ENOMEM); 1668252867Sdelphij } 1669253288Sdelphij if (xpt_create_path(&ccb->ccb_h.path, NULL, cam_sim_path(vbus_ext->sim), 1670252867Sdelphij CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) 1671252867Sdelphij { 1672252867Sdelphij xpt_free_ccb(ccb); 1673252867Sdelphij return(EIO); 1674252867Sdelphij } 1675252867Sdelphij xpt_rescan(ccb); 1676252867Sdelphij } 1677252867Sdelphij return(0); 1678252867Sdelphij} 1679