mvs.c revision 212732
1207536Smav/*- 2207536Smav * Copyright (c) 2010 Alexander Motin <mav@FreeBSD.org> 3207536Smav * All rights reserved. 4207536Smav * 5207536Smav * Redistribution and use in source and binary forms, with or without 6207536Smav * modification, are permitted provided that the following conditions 7207536Smav * are met: 8207536Smav * 1. Redistributions of source code must retain the above copyright 9207536Smav * notice, this list of conditions and the following disclaimer, 10207536Smav * without modification, immediately at the beginning of the file. 11207536Smav * 2. Redistributions in binary form must reproduce the above copyright 12207536Smav * notice, this list of conditions and the following disclaimer in the 13207536Smav * documentation and/or other materials provided with the distribution. 14207536Smav * 15207536Smav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16207536Smav * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17207536Smav * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18207536Smav * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19207536Smav * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20207536Smav * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21207536Smav * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22207536Smav * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23207536Smav * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24207536Smav * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25207536Smav */ 26207536Smav 27207536Smav#include <sys/cdefs.h> 28207536Smav__FBSDID("$FreeBSD: head/sys/dev/mvs/mvs.c 212732 2010-09-16 12:39:50Z mav $"); 29207536Smav 30207536Smav#include <sys/param.h> 31207536Smav#include <sys/module.h> 32207536Smav#include <sys/systm.h> 33207536Smav#include <sys/kernel.h> 34207536Smav#include <sys/ata.h> 35207536Smav#include <sys/bus.h> 36207536Smav#include <sys/endian.h> 37207536Smav#include <sys/malloc.h> 38207536Smav#include <sys/lock.h> 39207536Smav#include <sys/mutex.h> 40207536Smav#include <vm/uma.h> 41207536Smav#include <machine/stdarg.h> 42207536Smav#include <machine/resource.h> 43207536Smav#include <machine/bus.h> 44207536Smav#include <sys/rman.h> 45210471Smav#include <dev/pci/pcivar.h> 46207536Smav#include "mvs.h" 47207536Smav 48207536Smav#include <cam/cam.h> 49207536Smav#include <cam/cam_ccb.h> 50207536Smav#include <cam/cam_sim.h> 51207536Smav#include <cam/cam_xpt_sim.h> 52207536Smav#include <cam/cam_debug.h> 53207536Smav 54207536Smav/* local prototypes */ 55208393Smavstatic int mvs_ch_init(device_t dev); 56208393Smavstatic int mvs_ch_deinit(device_t dev); 57207536Smavstatic int mvs_ch_suspend(device_t dev); 58207536Smavstatic int mvs_ch_resume(device_t dev); 59207536Smavstatic void mvs_dmainit(device_t dev); 60207536Smavstatic void mvs_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error); 61207536Smavstatic void mvs_dmafini(device_t dev); 62207536Smavstatic void mvs_slotsalloc(device_t dev); 63207536Smavstatic void mvs_slotsfree(device_t dev); 64207536Smavstatic void mvs_setup_edma_queues(device_t dev); 65207536Smavstatic void mvs_set_edma_mode(device_t dev, enum mvs_edma_mode mode); 66207536Smavstatic void mvs_ch_pm(void *arg); 67207536Smavstatic void mvs_ch_intr_locked(void *data); 68207536Smavstatic void mvs_ch_intr(void *data); 69207536Smavstatic void mvs_reset(device_t dev); 70207536Smavstatic void mvs_softreset(device_t dev, union ccb *ccb); 71207536Smav 72207536Smavstatic int mvs_sata_connect(struct mvs_channel *ch); 73207536Smavstatic int mvs_sata_phy_reset(device_t dev); 74207536Smavstatic int mvs_wait(device_t dev, u_int s, u_int c, int t); 75207536Smavstatic void mvs_tfd_read(device_t dev, union ccb *ccb); 76207536Smavstatic void mvs_tfd_write(device_t dev, union ccb *ccb); 77207536Smavstatic void mvs_legacy_intr(device_t dev); 78207536Smavstatic void mvs_crbq_intr(device_t dev); 79207536Smavstatic void mvs_begin_transaction(device_t dev, union ccb *ccb); 80207536Smavstatic void mvs_legacy_execute_transaction(struct mvs_slot *slot); 81207536Smavstatic void mvs_timeout(struct mvs_slot *slot); 82207536Smavstatic void mvs_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error); 83207536Smavstatic void mvs_requeue_frozen(device_t dev); 84207536Smavstatic void mvs_execute_transaction(struct mvs_slot *slot); 85207536Smavstatic void mvs_end_transaction(struct mvs_slot *slot, enum mvs_err_type et); 86207536Smav 87207536Smavstatic void mvs_issue_read_log(device_t dev); 88207536Smavstatic void mvs_process_read_log(device_t dev, union ccb *ccb); 89207536Smav 90207536Smavstatic void mvsaction(struct cam_sim *sim, union ccb *ccb); 91207536Smavstatic void mvspoll(struct cam_sim *sim); 92207536Smav 93207536SmavMALLOC_DEFINE(M_MVS, "MVS driver", "MVS driver data buffers"); 94207536Smav 95207536Smavstatic int 96207536Smavmvs_ch_probe(device_t dev) 97207536Smav{ 98207536Smav 99207536Smav device_set_desc_copy(dev, "Marvell SATA channel"); 100207536Smav return (0); 101207536Smav} 102207536Smav 103207536Smavstatic int 104207536Smavmvs_ch_attach(device_t dev) 105207536Smav{ 106207536Smav struct mvs_controller *ctlr = device_get_softc(device_get_parent(dev)); 107207536Smav struct mvs_channel *ch = device_get_softc(dev); 108207536Smav struct cam_devq *devq; 109207536Smav int rid, error, i, sata_rev = 0; 110207536Smav 111207536Smav ch->dev = dev; 112207536Smav ch->unit = (intptr_t)device_get_ivars(dev); 113207536Smav ch->quirks = ctlr->quirks; 114207536Smav mtx_init(&ch->mtx, "MVS channel lock", NULL, MTX_DEF); 115207536Smav resource_int_value(device_get_name(dev), 116207536Smav device_get_unit(dev), "pm_level", &ch->pm_level); 117207536Smav if (ch->pm_level > 3) 118207536Smav callout_init_mtx(&ch->pm_timer, &ch->mtx, 0); 119207536Smav resource_int_value(device_get_name(dev), 120207536Smav device_get_unit(dev), "sata_rev", &sata_rev); 121207536Smav for (i = 0; i < 16; i++) { 122207536Smav ch->user[i].revision = sata_rev; 123207536Smav ch->user[i].mode = 0; 124207536Smav ch->user[i].bytecount = (ch->quirks & MVS_Q_GENIIE) ? 8192 : 2048; 125207536Smav ch->user[i].tags = MVS_MAX_SLOTS; 126207536Smav ch->curr[i] = ch->user[i]; 127207536Smav if (ch->pm_level) { 128207536Smav ch->user[i].caps = CTS_SATA_CAPS_H_PMREQ | 129207536Smav CTS_SATA_CAPS_H_APST | 130207536Smav CTS_SATA_CAPS_D_PMREQ | CTS_SATA_CAPS_D_APST; 131207536Smav } 132207536Smav } 133207536Smav rid = ch->unit; 134207536Smav if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 135207536Smav &rid, RF_ACTIVE))) 136207536Smav return (ENXIO); 137207536Smav mvs_dmainit(dev); 138207536Smav mvs_slotsalloc(dev); 139208393Smav mvs_ch_init(dev); 140207536Smav mtx_lock(&ch->mtx); 141207536Smav rid = ATA_IRQ_RID; 142207536Smav if (!(ch->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, 143207536Smav &rid, RF_SHAREABLE | RF_ACTIVE))) { 144207536Smav device_printf(dev, "Unable to map interrupt\n"); 145207536Smav error = ENXIO; 146207536Smav goto err0; 147207536Smav } 148207536Smav if ((bus_setup_intr(dev, ch->r_irq, ATA_INTR_FLAGS, NULL, 149207536Smav mvs_ch_intr_locked, dev, &ch->ih))) { 150207536Smav device_printf(dev, "Unable to setup interrupt\n"); 151207536Smav error = ENXIO; 152207536Smav goto err1; 153207536Smav } 154207536Smav /* Create the device queue for our SIM. */ 155207536Smav devq = cam_simq_alloc(MVS_MAX_SLOTS - 1); 156207536Smav if (devq == NULL) { 157207536Smav device_printf(dev, "Unable to allocate simq\n"); 158207536Smav error = ENOMEM; 159207536Smav goto err1; 160207536Smav } 161207536Smav /* Construct SIM entry */ 162207536Smav ch->sim = cam_sim_alloc(mvsaction, mvspoll, "mvsch", ch, 163207536Smav device_get_unit(dev), &ch->mtx, 164207536Smav 2, (ch->quirks & MVS_Q_GENI) ? 0 : MVS_MAX_SLOTS - 1, 165207536Smav devq); 166207536Smav if (ch->sim == NULL) { 167207536Smav cam_simq_free(devq); 168207536Smav device_printf(dev, "unable to allocate sim\n"); 169207536Smav error = ENOMEM; 170207536Smav goto err1; 171207536Smav } 172207536Smav if (xpt_bus_register(ch->sim, dev, 0) != CAM_SUCCESS) { 173207536Smav device_printf(dev, "unable to register xpt bus\n"); 174207536Smav error = ENXIO; 175207536Smav goto err2; 176207536Smav } 177207536Smav if (xpt_create_path(&ch->path, /*periph*/NULL, cam_sim_path(ch->sim), 178207536Smav CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 179207536Smav device_printf(dev, "unable to create path\n"); 180207536Smav error = ENXIO; 181207536Smav goto err3; 182207536Smav } 183207536Smav if (ch->pm_level > 3) { 184207536Smav callout_reset(&ch->pm_timer, 185207536Smav (ch->pm_level == 4) ? hz / 1000 : hz / 8, 186207536Smav mvs_ch_pm, dev); 187207536Smav } 188207536Smav mtx_unlock(&ch->mtx); 189207536Smav return (0); 190207536Smav 191207536Smaverr3: 192207536Smav xpt_bus_deregister(cam_sim_path(ch->sim)); 193207536Smaverr2: 194207536Smav cam_sim_free(ch->sim, /*free_devq*/TRUE); 195207536Smaverr1: 196207536Smav bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq); 197207536Smaverr0: 198207536Smav bus_release_resource(dev, SYS_RES_MEMORY, ch->unit, ch->r_mem); 199207536Smav mtx_unlock(&ch->mtx); 200207536Smav mtx_destroy(&ch->mtx); 201207536Smav return (error); 202207536Smav} 203207536Smav 204207536Smavstatic int 205207536Smavmvs_ch_detach(device_t dev) 206207536Smav{ 207207536Smav struct mvs_channel *ch = device_get_softc(dev); 208207536Smav 209207536Smav mtx_lock(&ch->mtx); 210207536Smav xpt_async(AC_LOST_DEVICE, ch->path, NULL); 211207536Smav xpt_free_path(ch->path); 212207536Smav xpt_bus_deregister(cam_sim_path(ch->sim)); 213207536Smav cam_sim_free(ch->sim, /*free_devq*/TRUE); 214207536Smav mtx_unlock(&ch->mtx); 215207536Smav 216207536Smav if (ch->pm_level > 3) 217207536Smav callout_drain(&ch->pm_timer); 218207536Smav bus_teardown_intr(dev, ch->r_irq, ch->ih); 219207536Smav bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq); 220207536Smav 221208393Smav mvs_ch_deinit(dev); 222207536Smav mvs_slotsfree(dev); 223207536Smav mvs_dmafini(dev); 224207536Smav 225207536Smav bus_release_resource(dev, SYS_RES_MEMORY, ch->unit, ch->r_mem); 226207536Smav mtx_destroy(&ch->mtx); 227207536Smav return (0); 228207536Smav} 229207536Smav 230207536Smavstatic int 231208393Smavmvs_ch_init(device_t dev) 232207536Smav{ 233207536Smav struct mvs_channel *ch = device_get_softc(dev); 234207536Smav uint32_t reg; 235207536Smav 236207536Smav /* Disable port interrupts */ 237207536Smav ATA_OUTL(ch->r_mem, EDMA_IEM, 0); 238207536Smav /* Stop EDMA */ 239207536Smav ch->curr_mode = MVS_EDMA_UNKNOWN; 240207536Smav mvs_set_edma_mode(dev, MVS_EDMA_OFF); 241207536Smav /* Clear and configure FIS interrupts. */ 242207536Smav ATA_OUTL(ch->r_mem, SATA_FISIC, 0); 243207536Smav reg = ATA_INL(ch->r_mem, SATA_FISC); 244207536Smav reg |= SATA_FISC_FISWAIT4HOSTRDYEN_B1; 245207536Smav ATA_OUTL(ch->r_mem, SATA_FISC, reg); 246207536Smav reg = ATA_INL(ch->r_mem, SATA_FISIM); 247207536Smav reg |= SATA_FISC_FISWAIT4HOSTRDYEN_B1; 248207536Smav ATA_OUTL(ch->r_mem, SATA_FISC, reg); 249207536Smav /* Clear SATA error register. */ 250207536Smav ATA_OUTL(ch->r_mem, SATA_SE, 0xffffffff); 251207536Smav /* Clear any outstanding error interrupts. */ 252207536Smav ATA_OUTL(ch->r_mem, EDMA_IEC, 0); 253207536Smav /* Unmask all error interrupts */ 254207536Smav ATA_OUTL(ch->r_mem, EDMA_IEM, ~EDMA_IE_TRANSIENT); 255207536Smav return (0); 256207536Smav} 257207536Smav 258208393Smavstatic int 259208393Smavmvs_ch_deinit(device_t dev) 260208393Smav{ 261208393Smav struct mvs_channel *ch = device_get_softc(dev); 262208393Smav 263208393Smav /* Stop EDMA */ 264208393Smav mvs_set_edma_mode(dev, MVS_EDMA_OFF); 265208393Smav /* Disable port interrupts. */ 266208393Smav ATA_OUTL(ch->r_mem, EDMA_IEM, 0); 267208393Smav return (0); 268208393Smav} 269208393Smav 270208393Smavstatic int 271208393Smavmvs_ch_suspend(device_t dev) 272208393Smav{ 273208393Smav struct mvs_channel *ch = device_get_softc(dev); 274208393Smav 275208393Smav mtx_lock(&ch->mtx); 276208393Smav xpt_freeze_simq(ch->sim, 1); 277208393Smav while (ch->oslots) 278208393Smav msleep(ch, &ch->mtx, PRIBIO, "mvssusp", hz/100); 279208393Smav mvs_ch_deinit(dev); 280208393Smav mtx_unlock(&ch->mtx); 281208393Smav return (0); 282208393Smav} 283208393Smav 284208393Smavstatic int 285208393Smavmvs_ch_resume(device_t dev) 286208393Smav{ 287208393Smav struct mvs_channel *ch = device_get_softc(dev); 288208393Smav 289208393Smav mtx_lock(&ch->mtx); 290208393Smav mvs_ch_init(dev); 291208393Smav mvs_reset(dev); 292208393Smav xpt_release_simq(ch->sim, TRUE); 293208393Smav mtx_unlock(&ch->mtx); 294208393Smav return (0); 295208393Smav} 296208393Smav 297207536Smavstruct mvs_dc_cb_args { 298207536Smav bus_addr_t maddr; 299207536Smav int error; 300207536Smav}; 301207536Smav 302207536Smavstatic void 303207536Smavmvs_dmainit(device_t dev) 304207536Smav{ 305207536Smav struct mvs_channel *ch = device_get_softc(dev); 306207536Smav struct mvs_dc_cb_args dcba; 307207536Smav 308207536Smav /* EDMA command request area. */ 309207536Smav if (bus_dma_tag_create(bus_get_dma_tag(dev), 1024, 0, 310207536Smav BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 311207536Smav NULL, NULL, MVS_WORKRQ_SIZE, 1, MVS_WORKRQ_SIZE, 312207536Smav 0, NULL, NULL, &ch->dma.workrq_tag)) 313207536Smav goto error; 314207536Smav if (bus_dmamem_alloc(ch->dma.workrq_tag, (void **)&ch->dma.workrq, 0, 315207536Smav &ch->dma.workrq_map)) 316207536Smav goto error; 317207536Smav if (bus_dmamap_load(ch->dma.workrq_tag, ch->dma.workrq_map, ch->dma.workrq, 318207536Smav MVS_WORKRQ_SIZE, mvs_dmasetupc_cb, &dcba, 0) || dcba.error) { 319207536Smav bus_dmamem_free(ch->dma.workrq_tag, ch->dma.workrq, ch->dma.workrq_map); 320207536Smav goto error; 321207536Smav } 322207536Smav ch->dma.workrq_bus = dcba.maddr; 323207536Smav /* EDMA command response area. */ 324207536Smav if (bus_dma_tag_create(bus_get_dma_tag(dev), 256, 0, 325207536Smav BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 326207536Smav NULL, NULL, MVS_WORKRP_SIZE, 1, MVS_WORKRP_SIZE, 327207536Smav 0, NULL, NULL, &ch->dma.workrp_tag)) 328207536Smav goto error; 329207536Smav if (bus_dmamem_alloc(ch->dma.workrp_tag, (void **)&ch->dma.workrp, 0, 330207536Smav &ch->dma.workrp_map)) 331207536Smav goto error; 332207536Smav if (bus_dmamap_load(ch->dma.workrp_tag, ch->dma.workrp_map, ch->dma.workrp, 333207536Smav MVS_WORKRP_SIZE, mvs_dmasetupc_cb, &dcba, 0) || dcba.error) { 334207536Smav bus_dmamem_free(ch->dma.workrp_tag, ch->dma.workrp, ch->dma.workrp_map); 335207536Smav goto error; 336207536Smav } 337207536Smav ch->dma.workrp_bus = dcba.maddr; 338207536Smav /* Data area. */ 339207536Smav if (bus_dma_tag_create(bus_get_dma_tag(dev), 2, MVS_EPRD_MAX, 340207536Smav BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 341207536Smav NULL, NULL, 342207536Smav MVS_SG_ENTRIES * PAGE_SIZE * MVS_MAX_SLOTS, 343207536Smav MVS_SG_ENTRIES, MVS_EPRD_MAX, 344207536Smav 0, busdma_lock_mutex, &ch->mtx, &ch->dma.data_tag)) { 345207536Smav goto error; 346207536Smav } 347207536Smav return; 348207536Smav 349207536Smaverror: 350207536Smav device_printf(dev, "WARNING - DMA initialization failed\n"); 351207536Smav mvs_dmafini(dev); 352207536Smav} 353207536Smav 354207536Smavstatic void 355207536Smavmvs_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) 356207536Smav{ 357207536Smav struct mvs_dc_cb_args *dcba = (struct mvs_dc_cb_args *)xsc; 358207536Smav 359207536Smav if (!(dcba->error = error)) 360207536Smav dcba->maddr = segs[0].ds_addr; 361207536Smav} 362207536Smav 363207536Smavstatic void 364207536Smavmvs_dmafini(device_t dev) 365207536Smav{ 366207536Smav struct mvs_channel *ch = device_get_softc(dev); 367207536Smav 368207536Smav if (ch->dma.data_tag) { 369207536Smav bus_dma_tag_destroy(ch->dma.data_tag); 370207536Smav ch->dma.data_tag = NULL; 371207536Smav } 372207536Smav if (ch->dma.workrp_bus) { 373207536Smav bus_dmamap_unload(ch->dma.workrp_tag, ch->dma.workrp_map); 374207536Smav bus_dmamem_free(ch->dma.workrp_tag, ch->dma.workrp, ch->dma.workrp_map); 375207536Smav ch->dma.workrp_bus = 0; 376207536Smav ch->dma.workrp_map = NULL; 377207536Smav ch->dma.workrp = NULL; 378207536Smav } 379207536Smav if (ch->dma.workrp_tag) { 380207536Smav bus_dma_tag_destroy(ch->dma.workrp_tag); 381207536Smav ch->dma.workrp_tag = NULL; 382207536Smav } 383207536Smav if (ch->dma.workrq_bus) { 384207536Smav bus_dmamap_unload(ch->dma.workrq_tag, ch->dma.workrq_map); 385207536Smav bus_dmamem_free(ch->dma.workrq_tag, ch->dma.workrq, ch->dma.workrq_map); 386207536Smav ch->dma.workrq_bus = 0; 387207536Smav ch->dma.workrq_map = NULL; 388207536Smav ch->dma.workrq = NULL; 389207536Smav } 390207536Smav if (ch->dma.workrq_tag) { 391207536Smav bus_dma_tag_destroy(ch->dma.workrq_tag); 392207536Smav ch->dma.workrq_tag = NULL; 393207536Smav } 394207536Smav} 395207536Smav 396207536Smavstatic void 397207536Smavmvs_slotsalloc(device_t dev) 398207536Smav{ 399207536Smav struct mvs_channel *ch = device_get_softc(dev); 400207536Smav int i; 401207536Smav 402207536Smav /* Alloc and setup command/dma slots */ 403207536Smav bzero(ch->slot, sizeof(ch->slot)); 404207536Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 405207536Smav struct mvs_slot *slot = &ch->slot[i]; 406207536Smav 407207536Smav slot->dev = dev; 408207536Smav slot->slot = i; 409207536Smav slot->state = MVS_SLOT_EMPTY; 410207536Smav slot->ccb = NULL; 411207536Smav callout_init_mtx(&slot->timeout, &ch->mtx, 0); 412207536Smav 413207536Smav if (bus_dmamap_create(ch->dma.data_tag, 0, &slot->dma.data_map)) 414207536Smav device_printf(ch->dev, "FAILURE - create data_map\n"); 415207536Smav } 416207536Smav} 417207536Smav 418207536Smavstatic void 419207536Smavmvs_slotsfree(device_t dev) 420207536Smav{ 421207536Smav struct mvs_channel *ch = device_get_softc(dev); 422207536Smav int i; 423207536Smav 424207536Smav /* Free all dma slots */ 425207536Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 426207536Smav struct mvs_slot *slot = &ch->slot[i]; 427207536Smav 428207536Smav callout_drain(&slot->timeout); 429207536Smav if (slot->dma.data_map) { 430207536Smav bus_dmamap_destroy(ch->dma.data_tag, slot->dma.data_map); 431207536Smav slot->dma.data_map = NULL; 432207536Smav } 433207536Smav } 434207536Smav} 435207536Smav 436207536Smavstatic void 437207536Smavmvs_setup_edma_queues(device_t dev) 438207536Smav{ 439207536Smav struct mvs_channel *ch = device_get_softc(dev); 440207536Smav uint64_t work; 441207536Smav 442207536Smav /* Requests queue. */ 443207536Smav work = ch->dma.workrq_bus; 444207536Smav ATA_OUTL(ch->r_mem, EDMA_REQQBAH, work >> 32); 445207536Smav ATA_OUTL(ch->r_mem, EDMA_REQQIP, work & 0xffffffff); 446207536Smav ATA_OUTL(ch->r_mem, EDMA_REQQOP, work & 0xffffffff); 447207536Smav bus_dmamap_sync(ch->dma.workrq_tag, ch->dma.workrq_map, BUS_DMASYNC_PREWRITE); 448207536Smav /* Reponses queue. */ 449207536Smav bzero(ch->dma.workrp, 256); 450207536Smav work = ch->dma.workrp_bus; 451207536Smav ATA_OUTL(ch->r_mem, EDMA_RESQBAH, work >> 32); 452207536Smav ATA_OUTL(ch->r_mem, EDMA_RESQIP, work & 0xffffffff); 453207536Smav ATA_OUTL(ch->r_mem, EDMA_RESQOP, work & 0xffffffff); 454207536Smav bus_dmamap_sync(ch->dma.workrp_tag, ch->dma.workrp_map, BUS_DMASYNC_PREREAD); 455207536Smav ch->out_idx = 0; 456207536Smav ch->in_idx = 0; 457207536Smav} 458207536Smav 459207536Smavstatic void 460207536Smavmvs_set_edma_mode(device_t dev, enum mvs_edma_mode mode) 461207536Smav{ 462207536Smav struct mvs_channel *ch = device_get_softc(dev); 463207536Smav int timeout; 464207536Smav uint32_t ecfg, fcfg, hc, ltm, unkn; 465207536Smav 466207536Smav if (mode == ch->curr_mode) 467207536Smav return; 468207536Smav /* If we are running, we should stop first. */ 469207536Smav if (ch->curr_mode != MVS_EDMA_OFF) { 470207536Smav ATA_OUTL(ch->r_mem, EDMA_CMD, EDMA_CMD_EDSEDMA); 471207536Smav timeout = 0; 472207536Smav while (ATA_INL(ch->r_mem, EDMA_CMD) & EDMA_CMD_EENEDMA) { 473207536Smav DELAY(1000); 474207536Smav if (timeout++ > 1000) { 475207536Smav device_printf(dev, "stopping EDMA engine failed\n"); 476207536Smav break; 477207536Smav } 478207536Smav }; 479207536Smav } 480207536Smav ch->curr_mode = mode; 481207536Smav ch->fbs_enabled = 0; 482207536Smav ch->fake_busy = 0; 483207536Smav /* Report mode to controller. Needed for correct CCC operation. */ 484207536Smav MVS_EDMA(device_get_parent(dev), dev, mode); 485207536Smav /* Configure new mode. */ 486207536Smav ecfg = EDMA_CFG_RESERVED | EDMA_CFG_RESERVED2 | EDMA_CFG_EHOSTQUEUECACHEEN; 487207536Smav if (ch->pm_present) { 488207536Smav ecfg |= EDMA_CFG_EMASKRXPM; 489207536Smav if (ch->quirks & MVS_Q_GENIIE) { 490207536Smav ecfg |= EDMA_CFG_EEDMAFBS; 491207536Smav ch->fbs_enabled = 1; 492207536Smav } 493207536Smav } 494207536Smav if (ch->quirks & MVS_Q_GENI) 495207536Smav ecfg |= EDMA_CFG_ERDBSZ; 496207536Smav else if (ch->quirks & MVS_Q_GENII) 497207536Smav ecfg |= EDMA_CFG_ERDBSZEXT | EDMA_CFG_EWRBUFFERLEN; 498207536Smav if (ch->quirks & MVS_Q_CT) 499207536Smav ecfg |= EDMA_CFG_ECUTTHROUGHEN; 500207536Smav if (mode != MVS_EDMA_OFF) 501207536Smav ecfg |= EDMA_CFG_EEARLYCOMPLETIONEN; 502207536Smav if (mode == MVS_EDMA_QUEUED) 503207536Smav ecfg |= EDMA_CFG_EQUE; 504207536Smav else if (mode == MVS_EDMA_NCQ) 505207536Smav ecfg |= EDMA_CFG_ESATANATVCMDQUE; 506207536Smav ATA_OUTL(ch->r_mem, EDMA_CFG, ecfg); 507207536Smav mvs_setup_edma_queues(dev); 508207536Smav if (ch->quirks & MVS_Q_GENIIE) { 509207536Smav /* Configure FBS-related registers */ 510207536Smav fcfg = ATA_INL(ch->r_mem, SATA_FISC); 511207536Smav ltm = ATA_INL(ch->r_mem, SATA_LTM); 512207536Smav hc = ATA_INL(ch->r_mem, EDMA_HC); 513207536Smav if (ch->fbs_enabled) { 514207536Smav fcfg |= SATA_FISC_FISDMAACTIVATESYNCRESP; 515207536Smav if (mode == MVS_EDMA_NCQ) { 516207536Smav fcfg &= ~SATA_FISC_FISWAIT4HOSTRDYEN_B0; 517207536Smav hc &= ~EDMA_IE_EDEVERR; 518207536Smav } else { 519207536Smav fcfg |= SATA_FISC_FISWAIT4HOSTRDYEN_B0; 520207536Smav hc |= EDMA_IE_EDEVERR; 521207536Smav } 522207536Smav ltm |= (1 << 8); 523207536Smav } else { 524207536Smav fcfg &= ~SATA_FISC_FISDMAACTIVATESYNCRESP; 525207536Smav fcfg &= ~SATA_FISC_FISWAIT4HOSTRDYEN_B0; 526207536Smav hc |= EDMA_IE_EDEVERR; 527207536Smav ltm &= ~(1 << 8); 528207536Smav } 529207536Smav ATA_OUTL(ch->r_mem, SATA_FISC, fcfg); 530207536Smav ATA_OUTL(ch->r_mem, SATA_LTM, ltm); 531207536Smav ATA_OUTL(ch->r_mem, EDMA_HC, hc); 532207536Smav /* This is some magic, required to handle several DRQs 533207536Smav * with basic DMA. */ 534207536Smav unkn = ATA_INL(ch->r_mem, EDMA_UNKN_RESD); 535207536Smav if (mode == MVS_EDMA_OFF) 536207536Smav unkn |= 1; 537207536Smav else 538207536Smav unkn &= ~1; 539207536Smav ATA_OUTL(ch->r_mem, EDMA_UNKN_RESD, unkn); 540207536Smav } 541207536Smav /* Run EDMA. */ 542207536Smav if (mode != MVS_EDMA_OFF) 543207536Smav ATA_OUTL(ch->r_mem, EDMA_CMD, EDMA_CMD_EENEDMA); 544207536Smav} 545207536Smav 546207536Smavdevclass_t mvs_devclass; 547207536Smavdevclass_t mvsch_devclass; 548207536Smavstatic device_method_t mvsch_methods[] = { 549207536Smav DEVMETHOD(device_probe, mvs_ch_probe), 550207536Smav DEVMETHOD(device_attach, mvs_ch_attach), 551207536Smav DEVMETHOD(device_detach, mvs_ch_detach), 552207536Smav DEVMETHOD(device_suspend, mvs_ch_suspend), 553207536Smav DEVMETHOD(device_resume, mvs_ch_resume), 554207536Smav { 0, 0 } 555207536Smav}; 556207536Smavstatic driver_t mvsch_driver = { 557207536Smav "mvsch", 558207536Smav mvsch_methods, 559207536Smav sizeof(struct mvs_channel) 560207536Smav}; 561207536SmavDRIVER_MODULE(mvsch, mvs, mvsch_driver, mvsch_devclass, 0, 0); 562207536SmavDRIVER_MODULE(mvsch, sata, mvsch_driver, mvsch_devclass, 0, 0); 563207536Smav 564207536Smavstatic void 565207536Smavmvs_phy_check_events(device_t dev, u_int32_t serr) 566207536Smav{ 567207536Smav struct mvs_channel *ch = device_get_softc(dev); 568207536Smav 569207536Smav if (ch->pm_level == 0) { 570207536Smav u_int32_t status = ATA_INL(ch->r_mem, SATA_SS); 571207536Smav union ccb *ccb; 572207536Smav 573207536Smav if (bootverbose) { 574207536Smav if (((status & SATA_SS_DET_MASK) == SATA_SS_DET_PHY_ONLINE) && 575207536Smav ((status & SATA_SS_SPD_MASK) != SATA_SS_SPD_NO_SPEED) && 576207536Smav ((status & SATA_SS_IPM_MASK) == SATA_SS_IPM_ACTIVE)) { 577207536Smav device_printf(dev, "CONNECT requested\n"); 578207536Smav } else 579207536Smav device_printf(dev, "DISCONNECT requested\n"); 580207536Smav } 581207536Smav mvs_reset(dev); 582207536Smav if ((ccb = xpt_alloc_ccb_nowait()) == NULL) 583207536Smav return; 584207536Smav if (xpt_create_path(&ccb->ccb_h.path, NULL, 585207536Smav cam_sim_path(ch->sim), 586207536Smav CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 587207536Smav xpt_free_ccb(ccb); 588207536Smav return; 589207536Smav } 590207536Smav xpt_rescan(ccb); 591207536Smav } 592207536Smav} 593207536Smav 594207536Smavstatic void 595207536Smavmvs_notify_events(device_t dev) 596207536Smav{ 597207536Smav struct mvs_channel *ch = device_get_softc(dev); 598207536Smav struct cam_path *dpath; 599207536Smav uint32_t fis; 600207536Smav int d; 601207536Smav 602207536Smav /* Try to read PMP field from SDB FIS. Present only for Gen-IIe. */ 603207536Smav fis = ATA_INL(ch->r_mem, SATA_FISDW0); 604207536Smav if ((fis & 0x80ff) == 0x80a1) 605207536Smav d = (fis & 0x0f00) >> 8; 606207536Smav else 607207536Smav d = ch->pm_present ? 15 : 0; 608207536Smav if (bootverbose) 609207536Smav device_printf(dev, "SNTF %d\n", d); 610207536Smav if (xpt_create_path(&dpath, NULL, 611207536Smav xpt_path_path_id(ch->path), d, 0) == CAM_REQ_CMP) { 612207536Smav xpt_async(AC_SCSI_AEN, dpath, NULL); 613207536Smav xpt_free_path(dpath); 614207536Smav } 615207536Smav} 616207536Smav 617207536Smavstatic void 618207536Smavmvs_ch_intr_locked(void *data) 619207536Smav{ 620207536Smav struct mvs_intr_arg *arg = (struct mvs_intr_arg *)data; 621207536Smav device_t dev = (device_t)arg->arg; 622207536Smav struct mvs_channel *ch = device_get_softc(dev); 623207536Smav 624207536Smav mtx_lock(&ch->mtx); 625207536Smav mvs_ch_intr(data); 626207536Smav mtx_unlock(&ch->mtx); 627207536Smav} 628207536Smav 629207536Smavstatic void 630207536Smavmvs_ch_pm(void *arg) 631207536Smav{ 632207536Smav device_t dev = (device_t)arg; 633207536Smav struct mvs_channel *ch = device_get_softc(dev); 634207536Smav uint32_t work; 635207536Smav 636207536Smav if (ch->numrslots != 0) 637207536Smav return; 638207536Smav /* If we are idle - request power state transition. */ 639207536Smav work = ATA_INL(ch->r_mem, SATA_SC); 640207536Smav work &= ~SATA_SC_SPM_MASK; 641207536Smav if (ch->pm_level == 4) 642207536Smav work |= SATA_SC_SPM_PARTIAL; 643207536Smav else 644207536Smav work |= SATA_SC_SPM_SLUMBER; 645207536Smav ATA_OUTL(ch->r_mem, SATA_SC, work); 646207536Smav} 647207536Smav 648207536Smavstatic void 649207536Smavmvs_ch_pm_wake(device_t dev) 650207536Smav{ 651207536Smav struct mvs_channel *ch = device_get_softc(dev); 652207536Smav uint32_t work; 653207536Smav int timeout = 0; 654207536Smav 655207536Smav work = ATA_INL(ch->r_mem, SATA_SS); 656207536Smav if (work & SATA_SS_IPM_ACTIVE) 657207536Smav return; 658207536Smav /* If we are not in active state - request power state transition. */ 659207536Smav work = ATA_INL(ch->r_mem, SATA_SC); 660207536Smav work &= ~SATA_SC_SPM_MASK; 661207536Smav work |= SATA_SC_SPM_ACTIVE; 662207536Smav ATA_OUTL(ch->r_mem, SATA_SC, work); 663207536Smav /* Wait for transition to happen. */ 664207536Smav while ((ATA_INL(ch->r_mem, SATA_SS) & SATA_SS_IPM_ACTIVE) == 0 && 665207536Smav timeout++ < 100) { 666207536Smav DELAY(100); 667207536Smav } 668207536Smav} 669207536Smav 670207536Smavstatic void 671207536Smavmvs_ch_intr(void *data) 672207536Smav{ 673207536Smav struct mvs_intr_arg *arg = (struct mvs_intr_arg *)data; 674207536Smav device_t dev = (device_t)arg->arg; 675207536Smav struct mvs_channel *ch = device_get_softc(dev); 676207536Smav uint32_t iec, serr = 0, fisic = 0; 677207536Smav enum mvs_err_type et; 678207536Smav int i, ccs, port = -1, selfdis = 0; 679207536Smav int edma = (ch->numtslots != 0 || ch->numdslots != 0); 680207536Smav 681207536Smav//device_printf(dev, "irq cause %02x EDMA %d IEC %08x\n", 682207536Smav// arg->cause, edma, ATA_INL(ch->r_mem, EDMA_IEC)); 683207536Smav /* New item in response queue. */ 684207536Smav if ((arg->cause & 2) && edma) 685207536Smav mvs_crbq_intr(dev); 686207536Smav /* Some error or special event. */ 687207536Smav if (arg->cause & 1) { 688207536Smav iec = ATA_INL(ch->r_mem, EDMA_IEC); 689207536Smav//device_printf(dev, "irq cause %02x EDMA %d IEC %08x\n", 690207536Smav// arg->cause, edma, iec); 691207536Smav if (iec & EDMA_IE_SERRINT) { 692207536Smav serr = ATA_INL(ch->r_mem, SATA_SE); 693207536Smav ATA_OUTL(ch->r_mem, SATA_SE, serr); 694207536Smav//device_printf(dev, "SERR %08x\n", serr); 695207536Smav } 696207536Smav /* EDMA self-disabled due to error. */ 697207536Smav if (iec & EDMA_IE_ESELFDIS) 698207536Smav selfdis = 1; 699207536Smav /* Transport interrupt. */ 700207536Smav if (iec & EDMA_IE_ETRANSINT) { 701207536Smav /* For Gen-I this bit means self-disable. */ 702207536Smav if (ch->quirks & MVS_Q_GENI) 703207536Smav selfdis = 1; 704207536Smav /* For Gen-II this bit means SDB-N. */ 705207536Smav else if (ch->quirks & MVS_Q_GENII) 706207536Smav fisic = SATA_FISC_FISWAIT4HOSTRDYEN_B1; 707207536Smav else /* For Gen-IIe - read FIS interrupt cause. */ 708207536Smav fisic = ATA_INL(ch->r_mem, SATA_FISIC); 709207536Smav//device_printf(dev, "FISIC %08x\n", fisic); 710207536Smav } 711207536Smav if (selfdis) 712207536Smav ch->curr_mode = MVS_EDMA_UNKNOWN; 713207536Smav ATA_OUTL(ch->r_mem, EDMA_IEC, ~iec); 714207536Smav /* Interface errors or Device error. */ 715207536Smav if (iec & (0xfc1e9000 | EDMA_IE_EDEVERR)) { 716207536Smav port = -1; 717207536Smav if (ch->numpslots != 0) { 718207536Smav ccs = 0; 719207536Smav } else { 720207536Smav if (ch->quirks & MVS_Q_GENIIE) 721207536Smav ccs = EDMA_S_EIOID(ATA_INL(ch->r_mem, EDMA_S)); 722207536Smav else 723207536Smav ccs = EDMA_S_EDEVQUETAG(ATA_INL(ch->r_mem, EDMA_S)); 724207536Smav /* Check if error is one-PMP-port-specific, */ 725207536Smav if (ch->fbs_enabled) { 726207536Smav /* Which ports were active. */ 727207536Smav for (i = 0; i < 16; i++) { 728207536Smav if (ch->numrslotspd[i] == 0) 729207536Smav continue; 730207536Smav if (port == -1) 731207536Smav port = i; 732207536Smav else if (port != i) { 733207536Smav port = -2; 734207536Smav break; 735207536Smav } 736207536Smav } 737207536Smav /* If several ports were active and EDMA still enabled - 738207536Smav * other ports are probably unaffected and may continue. 739207536Smav */ 740207536Smav if (port == -2 && !selfdis) { 741207536Smav uint16_t p = ATA_INL(ch->r_mem, SATA_SATAITC) >> 16; 742207536Smav port = ffs(p) - 1; 743207536Smav if (port != (fls(p) - 1)) 744207536Smav port = -2; 745207536Smav } 746207536Smav } 747207536Smav } 748207536Smav//device_printf(dev, "err slot %d port %d\n", ccs, port); 749207536Smav mvs_requeue_frozen(dev); 750207536Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 751207536Smav /* XXX: reqests in loading state. */ 752207536Smav if (((ch->rslots >> i) & 1) == 0) 753207536Smav continue; 754207536Smav if (port >= 0 && 755207536Smav ch->slot[i].ccb->ccb_h.target_id != port) 756207536Smav continue; 757207536Smav if (iec & EDMA_IE_EDEVERR) { /* Device error. */ 758207536Smav if (port != -2) { 759207536Smav if (ch->numtslots == 0) { 760207536Smav /* Untagged operation. */ 761207536Smav if (i == ccs) 762207536Smav et = MVS_ERR_TFE; 763207536Smav else 764207536Smav et = MVS_ERR_INNOCENT; 765207536Smav } else { 766207536Smav /* Tagged operation. */ 767207536Smav et = MVS_ERR_NCQ; 768207536Smav } 769207536Smav } else { 770207536Smav et = MVS_ERR_TFE; 771207536Smav ch->fatalerr = 1; 772207536Smav } 773207536Smav } else if (iec & 0xfc1e9000) { 774207536Smav if (ch->numtslots == 0 && i != ccs && port != -2) 775207536Smav et = MVS_ERR_INNOCENT; 776207536Smav else 777207536Smav et = MVS_ERR_SATA; 778207536Smav } else 779207536Smav et = MVS_ERR_INVALID; 780207536Smav mvs_end_transaction(&ch->slot[i], et); 781207536Smav } 782207536Smav } 783207536Smav /* Process SDB-N. */ 784207536Smav if (fisic & SATA_FISC_FISWAIT4HOSTRDYEN_B1) 785207536Smav mvs_notify_events(dev); 786207536Smav if (fisic) 787207536Smav ATA_OUTL(ch->r_mem, SATA_FISIC, ~fisic); 788207536Smav /* Process hot-plug. */ 789207536Smav if ((iec & (EDMA_IE_EDEVDIS | EDMA_IE_EDEVCON)) || 790207536Smav (serr & SATA_SE_PHY_CHANGED)) 791207536Smav mvs_phy_check_events(dev, serr); 792207536Smav } 793207536Smav /* Legacy mode device interrupt. */ 794207536Smav if ((arg->cause & 2) && !edma) 795207536Smav mvs_legacy_intr(dev); 796207536Smav} 797207536Smav 798207536Smavstatic uint8_t 799207536Smavmvs_getstatus(device_t dev, int clear) 800207536Smav{ 801207536Smav struct mvs_channel *ch = device_get_softc(dev); 802207536Smav uint8_t status = ATA_INB(ch->r_mem, clear ? ATA_STATUS : ATA_ALTSTAT); 803207536Smav 804207536Smav if (ch->fake_busy) { 805207536Smav if (status & (ATA_S_BUSY | ATA_S_DRQ | ATA_S_ERROR)) 806207536Smav ch->fake_busy = 0; 807207536Smav else 808207536Smav status |= ATA_S_BUSY; 809207536Smav } 810207536Smav return (status); 811207536Smav} 812207536Smav 813207536Smavstatic void 814207536Smavmvs_legacy_intr(device_t dev) 815207536Smav{ 816207536Smav struct mvs_channel *ch = device_get_softc(dev); 817207536Smav struct mvs_slot *slot = &ch->slot[0]; /* PIO is always in slot 0. */ 818207536Smav union ccb *ccb = slot->ccb; 819207536Smav enum mvs_err_type et = MVS_ERR_NONE; 820207536Smav int port; 821207536Smav u_int length; 822207536Smav uint8_t status, ireason; 823207536Smav 824207536Smav /* Clear interrupt and get status. */ 825207536Smav status = mvs_getstatus(dev, 1); 826207536Smav// device_printf(dev, "Legacy intr status %02x\n", 827207536Smav// status); 828207536Smav if (slot->state < MVS_SLOT_RUNNING) 829207536Smav return; 830207536Smav port = ccb->ccb_h.target_id & 0x0f; 831207536Smav /* Wait a bit for late !BUSY status update. */ 832207536Smav if (status & ATA_S_BUSY) { 833207536Smav DELAY(100); 834207536Smav if ((status = mvs_getstatus(dev, 1)) & ATA_S_BUSY) { 835207536Smav DELAY(1000); 836207536Smav if ((status = mvs_getstatus(dev, 1)) & ATA_S_BUSY) 837207536Smav return; 838207536Smav } 839207536Smav } 840207536Smav /* If we got an error, we are done. */ 841207536Smav if (status & ATA_S_ERROR) { 842207536Smav et = MVS_ERR_TFE; 843207536Smav goto end_finished; 844207536Smav } 845207536Smav if (ccb->ccb_h.func_code == XPT_ATA_IO) { /* ATA PIO */ 846207536Smav ccb->ataio.res.status = status; 847207536Smav /* Are we moving data? */ 848207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 849207536Smav /* If data read command - get them. */ 850207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 851207536Smav if (mvs_wait(dev, ATA_S_DRQ, ATA_S_BUSY, 1000) < 0) { 852207536Smav device_printf(dev, "timeout waiting for read DRQ\n"); 853207536Smav et = MVS_ERR_TIMEOUT; 854207536Smav goto end_finished; 855207536Smav } 856207536Smav ATA_INSW_STRM(ch->r_mem, ATA_DATA, 857207536Smav (uint16_t *)(ccb->ataio.data_ptr + ch->donecount), 858207536Smav ch->transfersize / 2); 859207536Smav } 860207536Smav /* Update how far we've gotten. */ 861207536Smav ch->donecount += ch->transfersize; 862207536Smav /* Do we need more? */ 863207536Smav if (ccb->ataio.dxfer_len > ch->donecount) { 864207536Smav /* Set this transfer size according to HW capabilities */ 865207536Smav ch->transfersize = min(ccb->ataio.dxfer_len - ch->donecount, 866207536Smav ch->curr[ccb->ccb_h.target_id].bytecount); 867207536Smav /* If data write command - put them */ 868207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 869207536Smav if (mvs_wait(dev, ATA_S_DRQ, ATA_S_BUSY, 1000) < 0) { 870207536Smav device_printf(dev, "timeout waiting for write DRQ\n"); 871207536Smav et = MVS_ERR_TIMEOUT; 872207536Smav goto end_finished; 873207536Smav } 874207536Smav ATA_OUTSW_STRM(ch->r_mem, ATA_DATA, 875207536Smav (uint16_t *)(ccb->ataio.data_ptr + ch->donecount), 876207536Smav ch->transfersize / 2); 877207536Smav return; 878207536Smav } 879207536Smav /* If data read command, return & wait for interrupt */ 880207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 881207536Smav return; 882207536Smav } 883207536Smav } 884207536Smav } else if (ch->basic_dma) { /* ATAPI DMA */ 885207536Smav if (status & ATA_S_DWF) 886207536Smav et = MVS_ERR_TFE; 887207536Smav else if (ATA_INL(ch->r_mem, DMA_S) & DMA_S_ERR) 888207536Smav et = MVS_ERR_TFE; 889207536Smav /* Stop basic DMA. */ 890207536Smav ATA_OUTL(ch->r_mem, DMA_C, 0); 891207536Smav goto end_finished; 892207536Smav } else { /* ATAPI PIO */ 893207536Smav length = ATA_INB(ch->r_mem,ATA_CYL_LSB) | (ATA_INB(ch->r_mem,ATA_CYL_MSB) << 8); 894207536Smav ireason = ATA_INB(ch->r_mem,ATA_IREASON); 895207536Smav//device_printf(dev, "status %02x, ireason %02x, length %d\n", status, ireason, length); 896207536Smav switch ((ireason & (ATA_I_CMD | ATA_I_IN)) | 897207536Smav (status & ATA_S_DRQ)) { 898207536Smav 899207536Smav case ATAPI_P_CMDOUT: 900207536Smavdevice_printf(dev, "ATAPI CMDOUT\n"); 901207536Smav /* Return wait for interrupt */ 902207536Smav return; 903207536Smav 904207536Smav case ATAPI_P_WRITE: 905207536Smav//device_printf(dev, "ATAPI WRITE\n"); 906207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 907207536Smav device_printf(dev, "trying to write on read buffer\n"); 908207536Smav et = MVS_ERR_TFE; 909207536Smav goto end_finished; 910207536Smav break; 911207536Smav } 912207536Smav ATA_OUTSW_STRM(ch->r_mem, ATA_DATA, 913207536Smav (uint16_t *)(ccb->csio.data_ptr + ch->donecount), 914207536Smav length / 2); 915207536Smav ch->donecount += length; 916207536Smav /* Set next transfer size according to HW capabilities */ 917207536Smav ch->transfersize = min(ccb->csio.dxfer_len - ch->donecount, 918207536Smav ch->curr[ccb->ccb_h.target_id].bytecount); 919207536Smav /* Return wait for interrupt */ 920207536Smav return; 921207536Smav 922207536Smav case ATAPI_P_READ: 923207536Smav//device_printf(dev, "ATAPI READ\n"); 924207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 925207536Smav device_printf(dev, "trying to read on write buffer\n"); 926207536Smav et = MVS_ERR_TFE; 927207536Smav goto end_finished; 928207536Smav } 929207536Smav ATA_INSW_STRM(ch->r_mem, ATA_DATA, 930207536Smav (uint16_t *)(ccb->csio.data_ptr + ch->donecount), 931207536Smav length / 2); 932207536Smav ch->donecount += length; 933207536Smav /* Set next transfer size according to HW capabilities */ 934207536Smav ch->transfersize = min(ccb->csio.dxfer_len - ch->donecount, 935207536Smav ch->curr[ccb->ccb_h.target_id].bytecount); 936207536Smav /* Return wait for interrupt */ 937207536Smav return; 938207536Smav 939207536Smav case ATAPI_P_DONEDRQ: 940207536Smavdevice_printf(dev, "ATAPI DONEDRQ\n"); 941207536Smav device_printf(dev, 942207536Smav "WARNING - DONEDRQ non conformant device\n"); 943207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 944207536Smav ATA_INSW_STRM(ch->r_mem, ATA_DATA, 945207536Smav (uint16_t *)(ccb->csio.data_ptr + ch->donecount), 946207536Smav length / 2); 947207536Smav ch->donecount += length; 948207536Smav } 949207536Smav else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 950207536Smav ATA_OUTSW_STRM(ch->r_mem, ATA_DATA, 951207536Smav (uint16_t *)(ccb->csio.data_ptr + ch->donecount), 952207536Smav length / 2); 953207536Smav ch->donecount += length; 954207536Smav } 955207536Smav else 956207536Smav et = MVS_ERR_TFE; 957207536Smav /* FALLTHROUGH */ 958207536Smav 959207536Smav case ATAPI_P_ABORT: 960207536Smav case ATAPI_P_DONE: 961207536Smav//device_printf(dev, "ATAPI ABORT/DONE\n"); 962207536Smav if (status & (ATA_S_ERROR | ATA_S_DWF)) 963207536Smav et = MVS_ERR_TFE; 964207536Smav goto end_finished; 965207536Smav 966207536Smav default: 967207536Smav device_printf(dev, "unknown transfer phase (status %02x, ireason %02x)\n", 968207536Smav status, ireason); 969207536Smav et = MVS_ERR_TFE; 970207536Smav } 971207536Smav } 972207536Smav 973207536Smavend_finished: 974207536Smav mvs_end_transaction(slot, et); 975207536Smav} 976207536Smav 977207536Smavstatic void 978207536Smavmvs_crbq_intr(device_t dev) 979207536Smav{ 980207536Smav struct mvs_channel *ch = device_get_softc(dev); 981207536Smav struct mvs_crpb *crpb; 982207536Smav union ccb *ccb; 983207536Smav int in_idx, cin_idx, slot; 984207536Smav uint16_t flags; 985207536Smav 986207536Smav in_idx = (ATA_INL(ch->r_mem, EDMA_RESQIP) & EDMA_RESQP_ERPQP_MASK) >> 987207536Smav EDMA_RESQP_ERPQP_SHIFT; 988207536Smav bus_dmamap_sync(ch->dma.workrp_tag, ch->dma.workrp_map, 989207536Smav BUS_DMASYNC_POSTREAD); 990207536Smav cin_idx = ch->in_idx; 991207536Smav ch->in_idx = in_idx; 992207536Smav while (in_idx != cin_idx) { 993207536Smav crpb = (struct mvs_crpb *) 994207536Smav (ch->dma.workrp + MVS_CRPB_OFFSET + (MVS_CRPB_SIZE * cin_idx)); 995207536Smav slot = le16toh(crpb->id) & MVS_CRPB_TAG_MASK; 996207536Smav flags = le16toh(crpb->rspflg); 997207536Smav//device_printf(dev, "CRPB %d %d %04x\n", cin_idx, slot, flags); 998207536Smav /* 999207536Smav * Handle only successfull completions here. 1000207536Smav * Errors will be handled by main intr handler. 1001207536Smav */ 1002207536Smav if (ch->numtslots != 0 || (flags & EDMA_IE_EDEVERR) == 0) { 1003207536Smavif ((flags >> 8) & ATA_S_ERROR) 1004207536Smavdevice_printf(dev, "ERROR STATUS CRPB %d %d %04x\n", cin_idx, slot, flags); 1005207536Smav if (ch->slot[slot].state >= MVS_SLOT_RUNNING) { 1006207536Smav ccb = ch->slot[slot].ccb; 1007207536Smav ccb->ataio.res.status = (flags & MVS_CRPB_ATASTS_MASK) >> 1008207536Smav MVS_CRPB_ATASTS_SHIFT; 1009207536Smav mvs_end_transaction(&ch->slot[slot], MVS_ERR_NONE); 1010207536Smav } else 1011207536Smavdevice_printf(dev, "EMPTY CRPB %d (->%d) %d %04x\n", cin_idx, in_idx, slot, flags); 1012207536Smav } else 1013207536Smavdevice_printf(dev, "ERROR FLAGS CRPB %d %d %04x\n", cin_idx, slot, flags); 1014207536Smav 1015207536Smav cin_idx = (cin_idx + 1) & (MVS_MAX_SLOTS - 1); 1016207536Smav } 1017207536Smav bus_dmamap_sync(ch->dma.workrp_tag, ch->dma.workrp_map, 1018207536Smav BUS_DMASYNC_PREREAD); 1019207536Smav if (cin_idx == ch->in_idx) { 1020207536Smav ATA_OUTL(ch->r_mem, EDMA_RESQOP, 1021207536Smav ch->dma.workrp_bus | (cin_idx << EDMA_RESQP_ERPQP_SHIFT)); 1022207536Smav } 1023207536Smav} 1024207536Smav 1025207536Smav/* Must be called with channel locked. */ 1026207536Smavstatic int 1027207536Smavmvs_check_collision(device_t dev, union ccb *ccb) 1028207536Smav{ 1029207536Smav struct mvs_channel *ch = device_get_softc(dev); 1030207536Smav 1031207536Smav if (ccb->ccb_h.func_code == XPT_ATA_IO) { 1032207536Smav /* NCQ DMA */ 1033207536Smav if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) { 1034207536Smav /* Can't mix NCQ and non-NCQ DMA commands. */ 1035207536Smav if (ch->numdslots != 0) 1036207536Smav return (1); 1037207536Smav /* Can't mix NCQ and PIO commands. */ 1038207536Smav if (ch->numpslots != 0) 1039207536Smav return (1); 1040207536Smav /* If we have no FBS */ 1041207536Smav if (!ch->fbs_enabled) { 1042207536Smav /* Tagged command while tagged to other target is active. */ 1043207536Smav if (ch->numtslots != 0 && 1044207536Smav ch->taggedtarget != ccb->ccb_h.target_id) 1045207536Smav return (1); 1046207536Smav } 1047207536Smav /* Non-NCQ DMA */ 1048207536Smav } else if (ccb->ataio.cmd.flags & CAM_ATAIO_DMA) { 1049207536Smav /* Can't mix non-NCQ DMA and NCQ commands. */ 1050207536Smav if (ch->numtslots != 0) 1051207536Smav return (1); 1052207536Smav /* Can't mix non-NCQ DMA and PIO commands. */ 1053207536Smav if (ch->numpslots != 0) 1054207536Smav return (1); 1055207536Smav /* PIO */ 1056207536Smav } else { 1057207536Smav /* Can't mix PIO with anything. */ 1058207536Smav if (ch->numrslots != 0) 1059207536Smav return (1); 1060207536Smav } 1061207536Smav if (ccb->ataio.cmd.flags & (CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT)) { 1062207536Smav /* Atomic command while anything active. */ 1063207536Smav if (ch->numrslots != 0) 1064207536Smav return (1); 1065207536Smav } 1066207536Smav } else { /* ATAPI */ 1067207536Smav /* ATAPI goes without EDMA, so can't mix it with anything. */ 1068207536Smav if (ch->numrslots != 0) 1069207536Smav return (1); 1070207536Smav } 1071207536Smav /* We have some atomic command running. */ 1072207536Smav if (ch->aslots != 0) 1073207536Smav return (1); 1074207536Smav return (0); 1075207536Smav} 1076207536Smav 1077207536Smavstatic void 1078207536Smavmvs_tfd_read(device_t dev, union ccb *ccb) 1079207536Smav{ 1080207536Smav struct mvs_channel *ch = device_get_softc(dev); 1081207536Smav struct ata_res *res = &ccb->ataio.res; 1082207536Smav 1083207536Smav res->status = ATA_INB(ch->r_mem, ATA_ALTSTAT); 1084207536Smav res->error = ATA_INB(ch->r_mem, ATA_ERROR); 1085207536Smav res->device = ATA_INB(ch->r_mem, ATA_DRIVE); 1086207536Smav ATA_OUTB(ch->r_mem, ATA_CONTROL, ATA_A_HOB); 1087207536Smav res->sector_count_exp = ATA_INB(ch->r_mem, ATA_COUNT); 1088207536Smav res->lba_low_exp = ATA_INB(ch->r_mem, ATA_SECTOR); 1089207536Smav res->lba_mid_exp = ATA_INB(ch->r_mem, ATA_CYL_LSB); 1090207536Smav res->lba_high_exp = ATA_INB(ch->r_mem, ATA_CYL_MSB); 1091207536Smav ATA_OUTB(ch->r_mem, ATA_CONTROL, 0); 1092207536Smav res->sector_count = ATA_INB(ch->r_mem, ATA_COUNT); 1093207536Smav res->lba_low = ATA_INB(ch->r_mem, ATA_SECTOR); 1094207536Smav res->lba_mid = ATA_INB(ch->r_mem, ATA_CYL_LSB); 1095207536Smav res->lba_high = ATA_INB(ch->r_mem, ATA_CYL_MSB); 1096207536Smav} 1097207536Smav 1098207536Smavstatic void 1099207536Smavmvs_tfd_write(device_t dev, union ccb *ccb) 1100207536Smav{ 1101207536Smav struct mvs_channel *ch = device_get_softc(dev); 1102207536Smav struct ata_cmd *cmd = &ccb->ataio.cmd; 1103207536Smav 1104207536Smav ATA_OUTB(ch->r_mem, ATA_DRIVE, cmd->device); 1105207536Smav ATA_OUTB(ch->r_mem, ATA_CONTROL, cmd->control); 1106207536Smav ATA_OUTB(ch->r_mem, ATA_FEATURE, cmd->features_exp); 1107207536Smav ATA_OUTB(ch->r_mem, ATA_FEATURE, cmd->features); 1108207536Smav ATA_OUTB(ch->r_mem, ATA_COUNT, cmd->sector_count_exp); 1109207536Smav ATA_OUTB(ch->r_mem, ATA_COUNT, cmd->sector_count); 1110207536Smav ATA_OUTB(ch->r_mem, ATA_SECTOR, cmd->lba_low_exp); 1111207536Smav ATA_OUTB(ch->r_mem, ATA_SECTOR, cmd->lba_low); 1112207536Smav ATA_OUTB(ch->r_mem, ATA_CYL_LSB, cmd->lba_mid_exp); 1113207536Smav ATA_OUTB(ch->r_mem, ATA_CYL_LSB, cmd->lba_mid); 1114207536Smav ATA_OUTB(ch->r_mem, ATA_CYL_MSB, cmd->lba_high_exp); 1115207536Smav ATA_OUTB(ch->r_mem, ATA_CYL_MSB, cmd->lba_high); 1116207536Smav ATA_OUTB(ch->r_mem, ATA_COMMAND, cmd->command); 1117207536Smav} 1118207536Smav 1119207536Smav 1120207536Smav/* Must be called with channel locked. */ 1121207536Smavstatic void 1122207536Smavmvs_begin_transaction(device_t dev, union ccb *ccb) 1123207536Smav{ 1124207536Smav struct mvs_channel *ch = device_get_softc(dev); 1125207536Smav struct mvs_slot *slot; 1126207536Smav int slotn, tag; 1127207536Smav 1128207536Smav if (ch->pm_level > 0) 1129207536Smav mvs_ch_pm_wake(dev); 1130207536Smav /* Softreset is a special case. */ 1131207536Smav if (ccb->ccb_h.func_code == XPT_ATA_IO && 1132207536Smav (ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL)) { 1133207536Smav mvs_softreset(dev, ccb); 1134207536Smav return; 1135207536Smav } 1136207536Smav /* Choose empty slot. */ 1137207536Smav slotn = ffs(~ch->oslots) - 1; 1138207536Smav if ((ccb->ccb_h.func_code == XPT_ATA_IO) && 1139207536Smav (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) { 1140207536Smav if (ch->quirks & MVS_Q_GENIIE) 1141207536Smav tag = ffs(~ch->otagspd[ccb->ccb_h.target_id]) - 1; 1142207536Smav else 1143207536Smav tag = slotn; 1144207536Smav } else 1145207536Smav tag = 0; 1146207536Smav /* Occupy chosen slot. */ 1147207536Smav slot = &ch->slot[slotn]; 1148207536Smav slot->ccb = ccb; 1149207536Smav slot->tag = tag; 1150207536Smav /* Stop PM timer. */ 1151207536Smav if (ch->numrslots == 0 && ch->pm_level > 3) 1152207536Smav callout_stop(&ch->pm_timer); 1153207536Smav /* Update channel stats. */ 1154207536Smav ch->oslots |= (1 << slot->slot); 1155207536Smav ch->numrslots++; 1156207536Smav ch->numrslotspd[ccb->ccb_h.target_id]++; 1157207536Smav if (ccb->ccb_h.func_code == XPT_ATA_IO) { 1158207536Smav if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) { 1159207536Smav ch->otagspd[ccb->ccb_h.target_id] |= (1 << slot->tag); 1160207536Smav ch->numtslots++; 1161207536Smav ch->numtslotspd[ccb->ccb_h.target_id]++; 1162207536Smav ch->taggedtarget = ccb->ccb_h.target_id; 1163207536Smav mvs_set_edma_mode(dev, MVS_EDMA_NCQ); 1164207536Smav } else if (ccb->ataio.cmd.flags & CAM_ATAIO_DMA) { 1165207536Smav ch->numdslots++; 1166207536Smav mvs_set_edma_mode(dev, MVS_EDMA_ON); 1167207536Smav } else { 1168207536Smav ch->numpslots++; 1169207536Smav mvs_set_edma_mode(dev, MVS_EDMA_OFF); 1170207536Smav } 1171207536Smav if (ccb->ataio.cmd.flags & 1172207536Smav (CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT)) { 1173207536Smav ch->aslots |= (1 << slot->slot); 1174207536Smav } 1175207536Smav } else { 1176207536Smav uint8_t *cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ? 1177207536Smav ccb->csio.cdb_io.cdb_ptr : ccb->csio.cdb_io.cdb_bytes; 1178207536Smav ch->numpslots++; 1179207536Smav /* Use ATAPI DMA only for commands without under-/overruns. */ 1180207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE && 1181207536Smav ch->curr[ccb->ccb_h.target_id].mode >= ATA_DMA && 1182207536Smav (ch->quirks & MVS_Q_SOC) == 0 && 1183207536Smav (cdb[0] == 0x08 || 1184207536Smav cdb[0] == 0x0a || 1185207536Smav cdb[0] == 0x28 || 1186207536Smav cdb[0] == 0x2a || 1187207536Smav cdb[0] == 0x88 || 1188207536Smav cdb[0] == 0x8a || 1189207536Smav cdb[0] == 0xa8 || 1190207536Smav cdb[0] == 0xaa || 1191207536Smav cdb[0] == 0xbe)) { 1192207536Smav ch->basic_dma = 1; 1193207536Smav } 1194207536Smav mvs_set_edma_mode(dev, MVS_EDMA_OFF); 1195207536Smav } 1196207536Smav if (ch->numpslots == 0 || ch->basic_dma) { 1197207536Smav void *buf; 1198207536Smav bus_size_t size; 1199207536Smav 1200207536Smav slot->state = MVS_SLOT_LOADING; 1201207536Smav if (ccb->ccb_h.func_code == XPT_ATA_IO) { 1202207536Smav buf = ccb->ataio.data_ptr; 1203207536Smav size = ccb->ataio.dxfer_len; 1204207536Smav } else { 1205207536Smav buf = ccb->csio.data_ptr; 1206207536Smav size = ccb->csio.dxfer_len; 1207207536Smav } 1208207536Smav bus_dmamap_load(ch->dma.data_tag, slot->dma.data_map, 1209207536Smav buf, size, mvs_dmasetprd, slot, 0); 1210207536Smav } else 1211207536Smav mvs_legacy_execute_transaction(slot); 1212207536Smav} 1213207536Smav 1214207536Smav/* Locked by busdma engine. */ 1215207536Smavstatic void 1216207536Smavmvs_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 1217207536Smav{ 1218207536Smav struct mvs_slot *slot = arg; 1219207536Smav struct mvs_channel *ch = device_get_softc(slot->dev); 1220207536Smav struct mvs_eprd *eprd; 1221207536Smav int i; 1222207536Smav 1223207536Smav if (error) { 1224207536Smav device_printf(slot->dev, "DMA load error\n"); 1225207536Smav mvs_end_transaction(slot, MVS_ERR_INVALID); 1226207536Smav return; 1227207536Smav } 1228207536Smav KASSERT(nsegs <= MVS_SG_ENTRIES, ("too many DMA segment entries\n")); 1229207536Smav /* If there is only one segment - no need to use S/G table on Gen-IIe. */ 1230207536Smav if (nsegs == 1 && ch->basic_dma == 0 && (ch->quirks & MVS_Q_GENIIE)) { 1231207536Smav slot->dma.addr = segs[0].ds_addr; 1232207536Smav slot->dma.len = segs[0].ds_len; 1233207536Smav } else { 1234207536Smav slot->dma.addr = 0; 1235207536Smav /* Get a piece of the workspace for this EPRD */ 1236207536Smav eprd = (struct mvs_eprd *) 1237207536Smav (ch->dma.workrq + MVS_EPRD_OFFSET + (MVS_EPRD_SIZE * slot->slot)); 1238207536Smav /* Fill S/G table */ 1239207536Smav for (i = 0; i < nsegs; i++) { 1240207536Smav eprd[i].prdbal = htole32(segs[i].ds_addr); 1241207536Smav eprd[i].bytecount = htole32(segs[i].ds_len & MVS_EPRD_MASK); 1242207536Smav eprd[i].prdbah = htole32((segs[i].ds_addr >> 16) >> 16); 1243207536Smav } 1244207536Smav eprd[i - 1].bytecount |= htole32(MVS_EPRD_EOF); 1245207536Smav } 1246207536Smav bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map, 1247207536Smav ((slot->ccb->ccb_h.flags & CAM_DIR_IN) ? 1248207536Smav BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE)); 1249207536Smav if (ch->basic_dma) 1250207536Smav mvs_legacy_execute_transaction(slot); 1251207536Smav else 1252207536Smav mvs_execute_transaction(slot); 1253207536Smav} 1254207536Smav 1255207536Smavstatic void 1256207536Smavmvs_legacy_execute_transaction(struct mvs_slot *slot) 1257207536Smav{ 1258207536Smav device_t dev = slot->dev; 1259207536Smav struct mvs_channel *ch = device_get_softc(dev); 1260207536Smav bus_addr_t eprd; 1261207536Smav union ccb *ccb = slot->ccb; 1262207536Smav int port = ccb->ccb_h.target_id & 0x0f; 1263207536Smav int timeout; 1264207536Smav 1265207536Smav slot->state = MVS_SLOT_RUNNING; 1266207536Smav ch->rslots |= (1 << slot->slot); 1267207536Smav ATA_OUTB(ch->r_mem, SATA_SATAICTL, port << SATA_SATAICTL_PMPTX_SHIFT); 1268207536Smav if (ccb->ccb_h.func_code == XPT_ATA_IO) { 1269207536Smav// device_printf(dev, "%d Legacy command %02x size %d\n", 1270207536Smav// port, ccb->ataio.cmd.command, ccb->ataio.dxfer_len); 1271207536Smav mvs_tfd_write(dev, ccb); 1272207536Smav /* Device reset doesn't interrupt. */ 1273207536Smav if (ccb->ataio.cmd.command == ATA_DEVICE_RESET) { 1274207536Smav int timeout = 1000000; 1275207536Smav do { 1276207536Smav DELAY(10); 1277207536Smav ccb->ataio.res.status = ATA_INB(ch->r_mem, ATA_STATUS); 1278207536Smav } while (ccb->ataio.res.status & ATA_S_BUSY && timeout--); 1279207536Smav mvs_legacy_intr(dev); 1280207536Smav return; 1281207536Smav } 1282207536Smav ch->donecount = 0; 1283207536Smav ch->transfersize = min(ccb->ataio.dxfer_len, 1284207536Smav ch->curr[port].bytecount); 1285207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) 1286207536Smav ch->fake_busy = 1; 1287207536Smav /* If data write command - output the data */ 1288207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 1289207536Smav if (mvs_wait(dev, ATA_S_DRQ, ATA_S_BUSY, 1000) < 0) { 1290207536Smav device_printf(dev, "timeout waiting for write DRQ\n"); 1291207536Smav mvs_end_transaction(slot, MVS_ERR_TIMEOUT); 1292207536Smav return; 1293207536Smav } 1294207536Smav ATA_OUTSW_STRM(ch->r_mem, ATA_DATA, 1295207536Smav (uint16_t *)(ccb->ataio.data_ptr + ch->donecount), 1296207536Smav ch->transfersize / 2); 1297207536Smav } 1298207536Smav } else { 1299207536Smav// device_printf(dev, "%d ATAPI command %02x size %d dma %d\n", 1300207536Smav// port, ccb->csio.cdb_io.cdb_bytes[0], ccb->csio.dxfer_len, 1301207536Smav// ch->basic_dma); 1302207536Smav ch->donecount = 0; 1303207536Smav ch->transfersize = min(ccb->csio.dxfer_len, 1304207536Smav ch->curr[port].bytecount); 1305207536Smav /* Write ATA PACKET command. */ 1306207536Smav if (ch->basic_dma) { 1307207536Smav ATA_OUTB(ch->r_mem, ATA_FEATURE, ATA_F_DMA); 1308207536Smav ATA_OUTB(ch->r_mem, ATA_CYL_LSB, 0); 1309207536Smav ATA_OUTB(ch->r_mem, ATA_CYL_MSB, 0); 1310207536Smav } else { 1311207536Smav ATA_OUTB(ch->r_mem, ATA_FEATURE, 0); 1312207536Smav ATA_OUTB(ch->r_mem, ATA_CYL_LSB, ch->transfersize); 1313207536Smav ATA_OUTB(ch->r_mem, ATA_CYL_MSB, ch->transfersize >> 8); 1314207536Smav } 1315207536Smav ATA_OUTB(ch->r_mem, ATA_COMMAND, ATA_PACKET_CMD); 1316207536Smav ch->fake_busy = 1; 1317207536Smav /* Wait for ready to write ATAPI command block */ 1318207536Smav if (mvs_wait(dev, 0, ATA_S_BUSY, 1000) < 0) { 1319207536Smav device_printf(dev, "timeout waiting for ATAPI !BUSY\n"); 1320207536Smav mvs_end_transaction(slot, MVS_ERR_TIMEOUT); 1321207536Smav return; 1322207536Smav } 1323207536Smav timeout = 5000; 1324207536Smav while (timeout--) { 1325207536Smav int reason = ATA_INB(ch->r_mem, ATA_IREASON); 1326207536Smav int status = ATA_INB(ch->r_mem, ATA_STATUS); 1327207536Smav 1328207536Smav if (((reason & (ATA_I_CMD | ATA_I_IN)) | 1329207536Smav (status & (ATA_S_DRQ | ATA_S_BUSY))) == ATAPI_P_CMDOUT) 1330207536Smav break; 1331207536Smav DELAY(20); 1332207536Smav } 1333207536Smav if (timeout <= 0) { 1334207536Smav device_printf(dev, "timeout waiting for ATAPI command ready\n"); 1335207536Smav mvs_end_transaction(slot, MVS_ERR_TIMEOUT); 1336207536Smav return; 1337207536Smav } 1338207536Smav /* Write ATAPI command. */ 1339207536Smav ATA_OUTSW_STRM(ch->r_mem, ATA_DATA, 1340207536Smav (uint16_t *)((ccb->ccb_h.flags & CAM_CDB_POINTER) ? 1341207536Smav ccb->csio.cdb_io.cdb_ptr : ccb->csio.cdb_io.cdb_bytes), 1342207536Smav ch->curr[port].atapi / 2); 1343207536Smav DELAY(10); 1344207536Smav if (ch->basic_dma) { 1345207536Smav /* Start basic DMA. */ 1346207536Smav eprd = ch->dma.workrq_bus + MVS_EPRD_OFFSET + 1347207536Smav (MVS_EPRD_SIZE * slot->slot); 1348207536Smav ATA_OUTL(ch->r_mem, DMA_DTLBA, eprd); 1349207536Smav ATA_OUTL(ch->r_mem, DMA_DTHBA, (eprd >> 16) >> 16); 1350207536Smav ATA_OUTL(ch->r_mem, DMA_C, DMA_C_START | 1351207536Smav (((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) ? 1352207536Smav DMA_C_READ : 0)); 1353207536Smav } else if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) 1354207536Smav ch->fake_busy = 1; 1355207536Smav } 1356207536Smav /* Start command execution timeout */ 1357207536Smav callout_reset(&slot->timeout, (int)ccb->ccb_h.timeout * hz / 1000, 1358207536Smav (timeout_t*)mvs_timeout, slot); 1359207536Smav} 1360207536Smav 1361207536Smav/* Must be called with channel locked. */ 1362207536Smavstatic void 1363207536Smavmvs_execute_transaction(struct mvs_slot *slot) 1364207536Smav{ 1365207536Smav device_t dev = slot->dev; 1366207536Smav struct mvs_channel *ch = device_get_softc(dev); 1367207536Smav bus_addr_t eprd; 1368207536Smav struct mvs_crqb *crqb; 1369207536Smav struct mvs_crqb_gen2e *crqb2e; 1370207536Smav union ccb *ccb = slot->ccb; 1371207536Smav int port = ccb->ccb_h.target_id & 0x0f; 1372207536Smav int i; 1373207536Smav 1374207536Smav// device_printf(dev, "%d EDMA command %02x size %d slot %d tag %d\n", 1375207536Smav// port, ccb->ataio.cmd.command, ccb->ataio.dxfer_len, slot->slot, slot->tag); 1376207536Smav /* Get address of the prepared EPRD */ 1377207536Smav eprd = ch->dma.workrq_bus + MVS_EPRD_OFFSET + (MVS_EPRD_SIZE * slot->slot); 1378207536Smav /* Prepare CRQB. Gen IIe uses different CRQB format. */ 1379207536Smav if (ch->quirks & MVS_Q_GENIIE) { 1380207536Smav crqb2e = (struct mvs_crqb_gen2e *) 1381207536Smav (ch->dma.workrq + MVS_CRQB_OFFSET + (MVS_CRQB_SIZE * ch->out_idx)); 1382207536Smav crqb2e->ctrlflg = htole32( 1383207536Smav ((ccb->ccb_h.flags & CAM_DIR_IN) ? MVS_CRQB2E_READ : 0) | 1384207536Smav (slot->tag << MVS_CRQB2E_DTAG_SHIFT) | 1385207536Smav (port << MVS_CRQB2E_PMP_SHIFT) | 1386207536Smav (slot->slot << MVS_CRQB2E_HTAG_SHIFT)); 1387207536Smav /* If there is only one segment - no need to use S/G table. */ 1388207536Smav if (slot->dma.addr != 0) { 1389207536Smav eprd = slot->dma.addr; 1390207536Smav crqb2e->ctrlflg |= htole32(MVS_CRQB2E_CPRD); 1391207536Smav crqb2e->drbc = slot->dma.len; 1392207536Smav } 1393207536Smav crqb2e->cprdbl = htole32(eprd); 1394207536Smav crqb2e->cprdbh = htole32((eprd >> 16) >> 16); 1395207536Smav crqb2e->cmd[0] = 0; 1396207536Smav crqb2e->cmd[1] = 0; 1397207536Smav crqb2e->cmd[2] = ccb->ataio.cmd.command; 1398207536Smav crqb2e->cmd[3] = ccb->ataio.cmd.features; 1399207536Smav crqb2e->cmd[4] = ccb->ataio.cmd.lba_low; 1400207536Smav crqb2e->cmd[5] = ccb->ataio.cmd.lba_mid; 1401207536Smav crqb2e->cmd[6] = ccb->ataio.cmd.lba_high; 1402207536Smav crqb2e->cmd[7] = ccb->ataio.cmd.device; 1403207536Smav crqb2e->cmd[8] = ccb->ataio.cmd.lba_low_exp; 1404207536Smav crqb2e->cmd[9] = ccb->ataio.cmd.lba_mid_exp; 1405207536Smav crqb2e->cmd[10] = ccb->ataio.cmd.lba_high_exp; 1406207536Smav crqb2e->cmd[11] = ccb->ataio.cmd.features_exp; 1407207536Smav if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) { 1408207536Smav crqb2e->cmd[12] = slot->tag << 3; 1409207536Smav crqb2e->cmd[13] = 0; 1410207536Smav } else { 1411207536Smav crqb2e->cmd[12] = ccb->ataio.cmd.sector_count; 1412207536Smav crqb2e->cmd[13] = ccb->ataio.cmd.sector_count_exp; 1413207536Smav } 1414207536Smav crqb2e->cmd[14] = 0; 1415207536Smav crqb2e->cmd[15] = 0; 1416207536Smav } else { 1417207536Smav crqb = (struct mvs_crqb *) 1418207536Smav (ch->dma.workrq + MVS_CRQB_OFFSET + (MVS_CRQB_SIZE * ch->out_idx)); 1419207536Smav crqb->cprdbl = htole32(eprd); 1420207536Smav crqb->cprdbh = htole32((eprd >> 16) >> 16); 1421207536Smav crqb->ctrlflg = htole16( 1422207536Smav ((ccb->ccb_h.flags & CAM_DIR_IN) ? MVS_CRQB_READ : 0) | 1423207536Smav (slot->slot << MVS_CRQB_TAG_SHIFT) | 1424207536Smav (port << MVS_CRQB_PMP_SHIFT)); 1425207536Smav i = 0; 1426207536Smav /* 1427207536Smav * Controller can handle only 11 of 12 ATA registers, 1428207536Smav * so we have to choose which one to skip. 1429207536Smav */ 1430207536Smav if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) { 1431207536Smav crqb->cmd[i++] = ccb->ataio.cmd.features_exp; 1432207536Smav crqb->cmd[i++] = 0x11; 1433207536Smav } 1434207536Smav crqb->cmd[i++] = ccb->ataio.cmd.features; 1435207536Smav crqb->cmd[i++] = 0x11; 1436207536Smav if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) { 1437207536Smav crqb->cmd[i++] = slot->tag << 3; 1438207536Smav crqb->cmd[i++] = 0x12; 1439207536Smav } else { 1440207536Smav crqb->cmd[i++] = ccb->ataio.cmd.sector_count_exp; 1441207536Smav crqb->cmd[i++] = 0x12; 1442207536Smav crqb->cmd[i++] = ccb->ataio.cmd.sector_count; 1443207536Smav crqb->cmd[i++] = 0x12; 1444207536Smav } 1445207536Smav crqb->cmd[i++] = ccb->ataio.cmd.lba_low_exp; 1446207536Smav crqb->cmd[i++] = 0x13; 1447207536Smav crqb->cmd[i++] = ccb->ataio.cmd.lba_low; 1448207536Smav crqb->cmd[i++] = 0x13; 1449207536Smav crqb->cmd[i++] = ccb->ataio.cmd.lba_mid_exp; 1450207536Smav crqb->cmd[i++] = 0x14; 1451207536Smav crqb->cmd[i++] = ccb->ataio.cmd.lba_mid; 1452207536Smav crqb->cmd[i++] = 0x14; 1453207536Smav crqb->cmd[i++] = ccb->ataio.cmd.lba_high_exp; 1454207536Smav crqb->cmd[i++] = 0x15; 1455207536Smav crqb->cmd[i++] = ccb->ataio.cmd.lba_high; 1456207536Smav crqb->cmd[i++] = 0x15; 1457207536Smav crqb->cmd[i++] = ccb->ataio.cmd.device; 1458207536Smav crqb->cmd[i++] = 0x16; 1459207536Smav crqb->cmd[i++] = ccb->ataio.cmd.command; 1460207536Smav crqb->cmd[i++] = 0x97; 1461207536Smav } 1462207536Smav bus_dmamap_sync(ch->dma.workrq_tag, ch->dma.workrq_map, 1463207536Smav BUS_DMASYNC_PREWRITE); 1464207536Smav bus_dmamap_sync(ch->dma.workrp_tag, ch->dma.workrp_map, 1465207536Smav BUS_DMASYNC_PREREAD); 1466207536Smav slot->state = MVS_SLOT_RUNNING; 1467207536Smav ch->rslots |= (1 << slot->slot); 1468207536Smav /* Issue command to the controller. */ 1469207536Smav ch->out_idx = (ch->out_idx + 1) & (MVS_MAX_SLOTS - 1); 1470207536Smav ATA_OUTL(ch->r_mem, EDMA_REQQIP, 1471207536Smav ch->dma.workrq_bus + MVS_CRQB_OFFSET + (MVS_CRQB_SIZE * ch->out_idx)); 1472207536Smav /* Start command execution timeout */ 1473207536Smav callout_reset(&slot->timeout, (int)ccb->ccb_h.timeout * hz / 1000, 1474207536Smav (timeout_t*)mvs_timeout, slot); 1475207536Smav return; 1476207536Smav} 1477207536Smav 1478207536Smav/* Must be called with channel locked. */ 1479207536Smavstatic void 1480207536Smavmvs_process_timeout(device_t dev) 1481207536Smav{ 1482207536Smav struct mvs_channel *ch = device_get_softc(dev); 1483207536Smav int i; 1484207536Smav 1485207536Smav mtx_assert(&ch->mtx, MA_OWNED); 1486207536Smav /* Handle the rest of commands. */ 1487207536Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 1488207536Smav /* Do we have a running request on slot? */ 1489207536Smav if (ch->slot[i].state < MVS_SLOT_RUNNING) 1490207536Smav continue; 1491207536Smav mvs_end_transaction(&ch->slot[i], MVS_ERR_TIMEOUT); 1492207536Smav } 1493207536Smav} 1494207536Smav 1495207536Smav/* Must be called with channel locked. */ 1496207536Smavstatic void 1497207536Smavmvs_rearm_timeout(device_t dev) 1498207536Smav{ 1499207536Smav struct mvs_channel *ch = device_get_softc(dev); 1500207536Smav int i; 1501207536Smav 1502207536Smav mtx_assert(&ch->mtx, MA_OWNED); 1503207536Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 1504207536Smav struct mvs_slot *slot = &ch->slot[i]; 1505207536Smav 1506207536Smav /* Do we have a running request on slot? */ 1507207536Smav if (slot->state < MVS_SLOT_RUNNING) 1508207536Smav continue; 1509207536Smav if ((ch->toslots & (1 << i)) == 0) 1510207536Smav continue; 1511207536Smav callout_reset(&slot->timeout, 1512207536Smav (int)slot->ccb->ccb_h.timeout * hz / 2000, 1513207536Smav (timeout_t*)mvs_timeout, slot); 1514207536Smav } 1515207536Smav} 1516207536Smav 1517207536Smav/* Locked by callout mechanism. */ 1518207536Smavstatic void 1519207536Smavmvs_timeout(struct mvs_slot *slot) 1520207536Smav{ 1521207536Smav device_t dev = slot->dev; 1522207536Smav struct mvs_channel *ch = device_get_softc(dev); 1523207536Smav 1524207536Smav /* Check for stale timeout. */ 1525207536Smav if (slot->state < MVS_SLOT_RUNNING) 1526207536Smav return; 1527207536Smav device_printf(dev, "Timeout on slot %d\n", slot->slot); 1528207536Smav device_printf(dev, "iec %08x sstat %08x serr %08x edma_s %08x " 1529207536Smav "dma_c %08x dma_s %08x rs %08x status %02x\n", 1530207536Smav ATA_INL(ch->r_mem, EDMA_IEC), 1531207536Smav ATA_INL(ch->r_mem, SATA_SS), ATA_INL(ch->r_mem, SATA_SE), 1532207536Smav ATA_INL(ch->r_mem, EDMA_S), ATA_INL(ch->r_mem, DMA_C), 1533207536Smav ATA_INL(ch->r_mem, DMA_S), ch->rslots, 1534207536Smav ATA_INB(ch->r_mem, ATA_ALTSTAT)); 1535207536Smav /* Handle frozen command. */ 1536207536Smav mvs_requeue_frozen(dev); 1537207536Smav /* We wait for other commands timeout and pray. */ 1538207536Smav if (ch->toslots == 0) 1539207536Smav xpt_freeze_simq(ch->sim, 1); 1540207536Smav ch->toslots |= (1 << slot->slot); 1541207536Smav if ((ch->rslots & ~ch->toslots) == 0) 1542207536Smav mvs_process_timeout(dev); 1543207536Smav else 1544207536Smav device_printf(dev, " ... waiting for slots %08x\n", 1545207536Smav ch->rslots & ~ch->toslots); 1546207536Smav} 1547207536Smav 1548207536Smav/* Must be called with channel locked. */ 1549207536Smavstatic void 1550207536Smavmvs_end_transaction(struct mvs_slot *slot, enum mvs_err_type et) 1551207536Smav{ 1552207536Smav device_t dev = slot->dev; 1553207536Smav struct mvs_channel *ch = device_get_softc(dev); 1554207536Smav union ccb *ccb = slot->ccb; 1555212732Smav int lastto; 1556207536Smav 1557207536Smav//device_printf(dev, "cmd done status %d\n", et); 1558207536Smav bus_dmamap_sync(ch->dma.workrq_tag, ch->dma.workrq_map, 1559207536Smav BUS_DMASYNC_POSTWRITE); 1560207536Smav /* Read result registers to the result struct 1561207536Smav * May be incorrect if several commands finished same time, 1562207536Smav * so read only when sure or have to. 1563207536Smav */ 1564207536Smav if (ccb->ccb_h.func_code == XPT_ATA_IO) { 1565207536Smav struct ata_res *res = &ccb->ataio.res; 1566207536Smav 1567207536Smav if ((et == MVS_ERR_TFE) || 1568207536Smav (ccb->ataio.cmd.flags & CAM_ATAIO_NEEDRESULT)) { 1569207536Smav mvs_tfd_read(dev, ccb); 1570207536Smav } else 1571207536Smav bzero(res, sizeof(*res)); 1572207536Smav } 1573207536Smav if (ch->numpslots == 0 || ch->basic_dma) { 1574207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 1575207536Smav bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map, 1576207536Smav (ccb->ccb_h.flags & CAM_DIR_IN) ? 1577207536Smav BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 1578207536Smav bus_dmamap_unload(ch->dma.data_tag, slot->dma.data_map); 1579207536Smav } 1580207536Smav } 1581207536Smav if (et != MVS_ERR_NONE) 1582207536Smav ch->eslots |= (1 << slot->slot); 1583207536Smav /* In case of error, freeze device for proper recovery. */ 1584207536Smav if ((et != MVS_ERR_NONE) && (!ch->readlog) && 1585207536Smav !(ccb->ccb_h.status & CAM_DEV_QFRZN)) { 1586207536Smav xpt_freeze_devq(ccb->ccb_h.path, 1); 1587207536Smav ccb->ccb_h.status |= CAM_DEV_QFRZN; 1588207536Smav } 1589207536Smav /* Set proper result status. */ 1590207536Smav ccb->ccb_h.status &= ~CAM_STATUS_MASK; 1591207536Smav switch (et) { 1592207536Smav case MVS_ERR_NONE: 1593207536Smav ccb->ccb_h.status |= CAM_REQ_CMP; 1594207536Smav if (ccb->ccb_h.func_code == XPT_SCSI_IO) 1595207536Smav ccb->csio.scsi_status = SCSI_STATUS_OK; 1596207536Smav break; 1597207536Smav case MVS_ERR_INVALID: 1598207536Smav ch->fatalerr = 1; 1599207536Smav ccb->ccb_h.status |= CAM_REQ_INVALID; 1600207536Smav break; 1601207536Smav case MVS_ERR_INNOCENT: 1602207536Smav ccb->ccb_h.status |= CAM_REQUEUE_REQ; 1603207536Smav break; 1604207536Smav case MVS_ERR_TFE: 1605207536Smav case MVS_ERR_NCQ: 1606207536Smav if (ccb->ccb_h.func_code == XPT_SCSI_IO) { 1607207536Smav ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 1608207536Smav ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 1609207536Smav } else { 1610207536Smav ccb->ccb_h.status |= CAM_ATA_STATUS_ERROR; 1611207536Smav } 1612207536Smav break; 1613207536Smav case MVS_ERR_SATA: 1614207536Smav ch->fatalerr = 1; 1615207536Smav if (!ch->readlog) { 1616207536Smav xpt_freeze_simq(ch->sim, 1); 1617207536Smav ccb->ccb_h.status &= ~CAM_STATUS_MASK; 1618207536Smav ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 1619207536Smav } 1620207536Smav ccb->ccb_h.status |= CAM_UNCOR_PARITY; 1621207536Smav break; 1622207536Smav case MVS_ERR_TIMEOUT: 1623207536Smav if (!ch->readlog) { 1624207536Smav xpt_freeze_simq(ch->sim, 1); 1625207536Smav ccb->ccb_h.status &= ~CAM_STATUS_MASK; 1626207536Smav ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 1627207536Smav } 1628207536Smav ccb->ccb_h.status |= CAM_CMD_TIMEOUT; 1629207536Smav break; 1630207536Smav default: 1631207536Smav ch->fatalerr = 1; 1632207536Smav ccb->ccb_h.status |= CAM_REQ_CMP_ERR; 1633207536Smav } 1634207536Smav /* Free slot. */ 1635207536Smav ch->oslots &= ~(1 << slot->slot); 1636207536Smav ch->rslots &= ~(1 << slot->slot); 1637207536Smav ch->aslots &= ~(1 << slot->slot); 1638207536Smav slot->state = MVS_SLOT_EMPTY; 1639207536Smav slot->ccb = NULL; 1640207536Smav /* Update channel stats. */ 1641207536Smav ch->numrslots--; 1642207536Smav ch->numrslotspd[ccb->ccb_h.target_id]--; 1643207536Smav if (ccb->ccb_h.func_code == XPT_ATA_IO) { 1644207536Smav if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) { 1645207536Smav ch->otagspd[ccb->ccb_h.target_id] &= ~(1 << slot->tag); 1646207536Smav ch->numtslots--; 1647207536Smav ch->numtslotspd[ccb->ccb_h.target_id]--; 1648207536Smav } else if (ccb->ataio.cmd.flags & CAM_ATAIO_DMA) { 1649207536Smav ch->numdslots--; 1650207536Smav } else { 1651207536Smav ch->numpslots--; 1652207536Smav } 1653207536Smav } else { 1654207536Smav ch->numpslots--; 1655207536Smav ch->basic_dma = 0; 1656207536Smav } 1657212732Smav /* Cancel timeout state if request completed normally. */ 1658212732Smav if (et != MVS_ERR_TIMEOUT) { 1659212732Smav lastto = (ch->toslots == (1 << slot->slot)); 1660212732Smav ch->toslots &= ~(1 << slot->slot); 1661212732Smav if (lastto) 1662212732Smav xpt_release_simq(ch->sim, TRUE); 1663212732Smav } 1664207536Smav /* If it was our READ LOG command - process it. */ 1665207536Smav if (ch->readlog) { 1666207536Smav mvs_process_read_log(dev, ccb); 1667207536Smav /* If it was NCQ command error, put result on hold. */ 1668207536Smav } else if (et == MVS_ERR_NCQ) { 1669207536Smav ch->hold[slot->slot] = ccb; 1670207536Smav ch->holdtag[slot->slot] = slot->tag; 1671207536Smav ch->numhslots++; 1672207536Smav } else 1673207536Smav xpt_done(ccb); 1674207536Smav /* Unfreeze frozen command. */ 1675207536Smav if (ch->frozen && !mvs_check_collision(dev, ch->frozen)) { 1676207536Smav union ccb *fccb = ch->frozen; 1677207536Smav ch->frozen = NULL; 1678207536Smav mvs_begin_transaction(dev, fccb); 1679207536Smav xpt_release_simq(ch->sim, TRUE); 1680207536Smav } 1681207536Smav /* If we have no other active commands, ... */ 1682207536Smav if (ch->rslots == 0) { 1683207536Smav /* if there was fatal error - reset port. */ 1684207536Smav if (ch->toslots != 0 || ch->fatalerr) { 1685207536Smav mvs_reset(dev); 1686207536Smav } else { 1687207536Smav /* if we have slots in error, we can reinit port. */ 1688207536Smav if (ch->eslots != 0) { 1689207536Smav mvs_set_edma_mode(dev, MVS_EDMA_OFF); 1690207536Smav ch->eslots = 0; 1691207536Smav } 1692207536Smav /* if there commands on hold, we can do READ LOG. */ 1693207536Smav if (!ch->readlog && ch->numhslots) 1694207536Smav mvs_issue_read_log(dev); 1695207536Smav } 1696207536Smav /* If all the rest of commands are in timeout - give them chance. */ 1697207536Smav } else if ((ch->rslots & ~ch->toslots) == 0 && 1698207536Smav et != MVS_ERR_TIMEOUT) 1699207536Smav mvs_rearm_timeout(dev); 1700207536Smav /* Start PM timer. */ 1701207536Smav if (ch->numrslots == 0 && ch->pm_level > 3 && 1702207536Smav (ch->curr[ch->pm_present ? 15 : 0].caps & CTS_SATA_CAPS_D_PMREQ)) { 1703207536Smav callout_schedule(&ch->pm_timer, 1704207536Smav (ch->pm_level == 4) ? hz / 1000 : hz / 8); 1705207536Smav } 1706207536Smav} 1707207536Smav 1708207536Smavstatic void 1709207536Smavmvs_issue_read_log(device_t dev) 1710207536Smav{ 1711207536Smav struct mvs_channel *ch = device_get_softc(dev); 1712207536Smav union ccb *ccb; 1713207536Smav struct ccb_ataio *ataio; 1714207536Smav int i; 1715207536Smav 1716207536Smav ch->readlog = 1; 1717207536Smav /* Find some holden command. */ 1718207536Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 1719207536Smav if (ch->hold[i]) 1720207536Smav break; 1721207536Smav } 1722207536Smav ccb = xpt_alloc_ccb_nowait(); 1723207536Smav if (ccb == NULL) { 1724207536Smav device_printf(dev, "Unable allocate READ LOG command"); 1725207536Smav return; /* XXX */ 1726207536Smav } 1727207536Smav ccb->ccb_h = ch->hold[i]->ccb_h; /* Reuse old header. */ 1728207536Smav ccb->ccb_h.func_code = XPT_ATA_IO; 1729207536Smav ccb->ccb_h.flags = CAM_DIR_IN; 1730207536Smav ccb->ccb_h.timeout = 1000; /* 1s should be enough. */ 1731207536Smav ataio = &ccb->ataio; 1732207536Smav ataio->data_ptr = malloc(512, M_MVS, M_NOWAIT); 1733207536Smav if (ataio->data_ptr == NULL) { 1734208818Smav xpt_free_ccb(ccb); 1735207536Smav device_printf(dev, "Unable allocate memory for READ LOG command"); 1736207536Smav return; /* XXX */ 1737207536Smav } 1738207536Smav ataio->dxfer_len = 512; 1739207536Smav bzero(&ataio->cmd, sizeof(ataio->cmd)); 1740207536Smav ataio->cmd.flags = CAM_ATAIO_48BIT; 1741207536Smav ataio->cmd.command = 0x2F; /* READ LOG EXT */ 1742207536Smav ataio->cmd.sector_count = 1; 1743207536Smav ataio->cmd.sector_count_exp = 0; 1744207536Smav ataio->cmd.lba_low = 0x10; 1745207536Smav ataio->cmd.lba_mid = 0; 1746207536Smav ataio->cmd.lba_mid_exp = 0; 1747207536Smav /* Freeze SIM while doing READ LOG EXT. */ 1748207536Smav xpt_freeze_simq(ch->sim, 1); 1749207536Smav mvs_begin_transaction(dev, ccb); 1750207536Smav} 1751207536Smav 1752207536Smavstatic void 1753207536Smavmvs_process_read_log(device_t dev, union ccb *ccb) 1754207536Smav{ 1755207536Smav struct mvs_channel *ch = device_get_softc(dev); 1756207536Smav uint8_t *data; 1757207536Smav struct ata_res *res; 1758207536Smav int i; 1759207536Smav 1760207536Smav ch->readlog = 0; 1761207536Smav 1762207536Smav data = ccb->ataio.data_ptr; 1763207536Smav if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP && 1764207536Smav (data[0] & 0x80) == 0) { 1765207536Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 1766207536Smav if (!ch->hold[i]) 1767207536Smav continue; 1768207536Smav if (ch->hold[i]->ccb_h.target_id != ccb->ccb_h.target_id) 1769207536Smav continue; 1770207536Smav if ((data[0] & 0x1F) == ch->holdtag[i]) { 1771207536Smav res = &ch->hold[i]->ataio.res; 1772207536Smav res->status = data[2]; 1773207536Smav res->error = data[3]; 1774207536Smav res->lba_low = data[4]; 1775207536Smav res->lba_mid = data[5]; 1776207536Smav res->lba_high = data[6]; 1777207536Smav res->device = data[7]; 1778207536Smav res->lba_low_exp = data[8]; 1779207536Smav res->lba_mid_exp = data[9]; 1780207536Smav res->lba_high_exp = data[10]; 1781207536Smav res->sector_count = data[12]; 1782207536Smav res->sector_count_exp = data[13]; 1783207536Smav } else { 1784207536Smav ch->hold[i]->ccb_h.status &= ~CAM_STATUS_MASK; 1785207536Smav ch->hold[i]->ccb_h.status |= CAM_REQUEUE_REQ; 1786207536Smav } 1787207536Smav xpt_done(ch->hold[i]); 1788207536Smav ch->hold[i] = NULL; 1789207536Smav ch->numhslots--; 1790207536Smav } 1791207536Smav } else { 1792207536Smav if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 1793207536Smav device_printf(dev, "Error while READ LOG EXT\n"); 1794207536Smav else if ((data[0] & 0x80) == 0) { 1795207536Smav device_printf(dev, "Non-queued command error in READ LOG EXT\n"); 1796207536Smav } 1797207536Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 1798207536Smav if (!ch->hold[i]) 1799207536Smav continue; 1800207536Smav if (ch->hold[i]->ccb_h.target_id != ccb->ccb_h.target_id) 1801207536Smav continue; 1802207536Smav xpt_done(ch->hold[i]); 1803207536Smav ch->hold[i] = NULL; 1804207536Smav ch->numhslots--; 1805207536Smav } 1806207536Smav } 1807207536Smav free(ccb->ataio.data_ptr, M_MVS); 1808207536Smav xpt_free_ccb(ccb); 1809207536Smav xpt_release_simq(ch->sim, TRUE); 1810207536Smav} 1811207536Smav 1812207536Smavstatic int 1813207536Smavmvs_wait(device_t dev, u_int s, u_int c, int t) 1814207536Smav{ 1815207536Smav int timeout = 0; 1816207536Smav uint8_t st; 1817207536Smav 1818207536Smav while (((st = mvs_getstatus(dev, 0)) & (s | c)) != s) { 1819207536Smav DELAY(1000); 1820207536Smav if (timeout++ > t) { 1821207536Smav device_printf(dev, "Wait status %02x\n", st); 1822207536Smav return (-1); 1823207536Smav } 1824207536Smav } 1825207536Smav return (timeout); 1826207536Smav} 1827207536Smav 1828207536Smavstatic void 1829207536Smavmvs_requeue_frozen(device_t dev) 1830207536Smav{ 1831207536Smav struct mvs_channel *ch = device_get_softc(dev); 1832207536Smav union ccb *fccb = ch->frozen; 1833207536Smav 1834207536Smav if (fccb) { 1835207536Smav ch->frozen = NULL; 1836207536Smav fccb->ccb_h.status = CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ; 1837207536Smav if (!(fccb->ccb_h.status & CAM_DEV_QFRZN)) { 1838207536Smav xpt_freeze_devq(fccb->ccb_h.path, 1); 1839207536Smav fccb->ccb_h.status |= CAM_DEV_QFRZN; 1840207536Smav } 1841207536Smav xpt_done(fccb); 1842207536Smav } 1843207536Smav} 1844207536Smav 1845207536Smavstatic void 1846207536Smavmvs_reset(device_t dev) 1847207536Smav{ 1848207536Smav struct mvs_channel *ch = device_get_softc(dev); 1849207536Smav int i; 1850207536Smav 1851207536Smav xpt_freeze_simq(ch->sim, 1); 1852207536Smav if (bootverbose) 1853207536Smav device_printf(dev, "MVS reset...\n"); 1854207536Smav /* Requeue freezed command. */ 1855207536Smav mvs_requeue_frozen(dev); 1856207536Smav /* Kill the engine and requeue all running commands. */ 1857207536Smav mvs_set_edma_mode(dev, MVS_EDMA_OFF); 1858207536Smav ATA_OUTL(ch->r_mem, DMA_C, 0); 1859207536Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 1860207536Smav /* Do we have a running request on slot? */ 1861207536Smav if (ch->slot[i].state < MVS_SLOT_RUNNING) 1862207536Smav continue; 1863207536Smav /* XXX; Commands in loading state. */ 1864207536Smav mvs_end_transaction(&ch->slot[i], MVS_ERR_INNOCENT); 1865207536Smav } 1866207536Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 1867207536Smav if (!ch->hold[i]) 1868207536Smav continue; 1869207536Smav xpt_done(ch->hold[i]); 1870207536Smav ch->hold[i] = NULL; 1871207536Smav ch->numhslots--; 1872207536Smav } 1873207536Smav if (ch->toslots != 0) 1874207536Smav xpt_release_simq(ch->sim, TRUE); 1875207536Smav ch->eslots = 0; 1876207536Smav ch->toslots = 0; 1877207536Smav ch->fatalerr = 0; 1878207536Smav /* Tell the XPT about the event */ 1879207536Smav xpt_async(AC_BUS_RESET, ch->path, NULL); 1880207536Smav ATA_OUTL(ch->r_mem, EDMA_IEM, 0); 1881207536Smav ATA_OUTL(ch->r_mem, EDMA_CMD, EDMA_CMD_EATARST); 1882207536Smav DELAY(25); 1883207536Smav ATA_OUTL(ch->r_mem, EDMA_CMD, 0); 1884207536Smav /* Reset and reconnect PHY, */ 1885207536Smav if (!mvs_sata_phy_reset(dev)) { 1886207536Smav if (bootverbose) 1887207536Smav device_printf(dev, 1888207536Smav "MVS reset done: phy reset found no device\n"); 1889207536Smav ch->devices = 0; 1890207536Smav ATA_OUTL(ch->r_mem, SATA_SE, 0xffffffff); 1891207536Smav ATA_OUTL(ch->r_mem, EDMA_IEC, 0); 1892207536Smav ATA_OUTL(ch->r_mem, EDMA_IEM, ~EDMA_IE_TRANSIENT); 1893207536Smav xpt_release_simq(ch->sim, TRUE); 1894207536Smav return; 1895207536Smav } 1896207536Smav /* Wait for clearing busy status. */ 1897207536Smav if ((i = mvs_wait(dev, 0, ATA_S_BUSY | ATA_S_DRQ, 15000)) < 0) 1898207536Smav device_printf(dev, "device is not ready\n"); 1899207536Smav else if (bootverbose) 1900207536Smav device_printf(dev, "ready wait time=%dms\n", i); 1901207536Smav ch->devices = 1; 1902207536Smav ATA_OUTL(ch->r_mem, SATA_SE, 0xffffffff); 1903207536Smav ATA_OUTL(ch->r_mem, EDMA_IEC, 0); 1904207536Smav ATA_OUTL(ch->r_mem, EDMA_IEM, ~EDMA_IE_TRANSIENT); 1905207536Smav if (bootverbose) 1906207536Smav device_printf(dev, "MVS reset done: device found\n"); 1907207536Smav xpt_release_simq(ch->sim, TRUE); 1908207536Smav} 1909207536Smav 1910207536Smavstatic void 1911207536Smavmvs_softreset(device_t dev, union ccb *ccb) 1912207536Smav{ 1913207536Smav struct mvs_channel *ch = device_get_softc(dev); 1914207536Smav int port = ccb->ccb_h.target_id & 0x0f; 1915207536Smav int i; 1916207536Smav 1917207536Smav mvs_set_edma_mode(dev, MVS_EDMA_OFF); 1918207536Smav ATA_OUTB(ch->r_mem, SATA_SATAICTL, port << SATA_SATAICTL_PMPTX_SHIFT); 1919207536Smav ATA_OUTB(ch->r_mem, ATA_CONTROL, ATA_A_RESET); 1920207536Smav DELAY(10000); 1921207536Smav ATA_OUTB(ch->r_mem, ATA_CONTROL, 0); 1922207536Smav ccb->ccb_h.status &= ~CAM_STATUS_MASK; 1923207536Smav /* Wait for clearing busy status. */ 1924207536Smav if ((i = mvs_wait(dev, 0, ATA_S_BUSY | ATA_S_DRQ, ccb->ccb_h.timeout)) < 0) { 1925207536Smav ccb->ccb_h.status |= CAM_CMD_TIMEOUT; 1926207536Smav } else { 1927207536Smav ccb->ccb_h.status |= CAM_REQ_CMP; 1928207536Smav } 1929207536Smav mvs_tfd_read(dev, ccb); 1930207536Smav xpt_done(ccb); 1931207536Smav} 1932207536Smav 1933207536Smavstatic int 1934207536Smavmvs_sata_connect(struct mvs_channel *ch) 1935207536Smav{ 1936207536Smav u_int32_t status; 1937207536Smav int timeout; 1938207536Smav 1939207536Smav /* Wait up to 100ms for "connect well" */ 1940207536Smav for (timeout = 0; timeout < 100 ; timeout++) { 1941207536Smav status = ATA_INL(ch->r_mem, SATA_SS); 1942207536Smav if (((status & SATA_SS_DET_MASK) == SATA_SS_DET_PHY_ONLINE) && 1943207536Smav ((status & SATA_SS_SPD_MASK) != SATA_SS_SPD_NO_SPEED) && 1944207536Smav ((status & SATA_SS_IPM_MASK) == SATA_SS_IPM_ACTIVE)) 1945207536Smav break; 1946207536Smav if ((status & SATA_SS_DET_MASK) == SATA_SS_DET_PHY_OFFLINE) { 1947207536Smav if (bootverbose) { 1948207536Smav device_printf(ch->dev, "SATA offline status=%08x\n", 1949207536Smav status); 1950207536Smav } 1951207536Smav return (0); 1952207536Smav } 1953207536Smav DELAY(1000); 1954207536Smav } 1955207536Smav if (timeout >= 100) { 1956207536Smav if (bootverbose) { 1957207536Smav device_printf(ch->dev, "SATA connect timeout status=%08x\n", 1958207536Smav status); 1959207536Smav } 1960207536Smav return (0); 1961207536Smav } 1962207536Smav if (bootverbose) { 1963207536Smav device_printf(ch->dev, "SATA connect time=%dms status=%08x\n", 1964207536Smav timeout, status); 1965207536Smav } 1966207536Smav /* Clear SATA error register */ 1967207536Smav ATA_OUTL(ch->r_mem, SATA_SE, 0xffffffff); 1968207536Smav return (1); 1969207536Smav} 1970207536Smav 1971207536Smavstatic int 1972207536Smavmvs_sata_phy_reset(device_t dev) 1973207536Smav{ 1974207536Smav struct mvs_channel *ch = device_get_softc(dev); 1975207536Smav int sata_rev; 1976207536Smav uint32_t val; 1977207536Smav 1978207536Smav sata_rev = ch->user[ch->pm_present ? 15 : 0].revision; 1979207536Smav if (sata_rev == 1) 1980207536Smav val = SATA_SC_SPD_SPEED_GEN1; 1981207536Smav else if (sata_rev == 2) 1982207536Smav val = SATA_SC_SPD_SPEED_GEN2; 1983207536Smav else if (sata_rev == 3) 1984207536Smav val = SATA_SC_SPD_SPEED_GEN3; 1985207536Smav else 1986207536Smav val = 0; 1987207536Smav ATA_OUTL(ch->r_mem, SATA_SC, 1988207536Smav SATA_SC_DET_RESET | val | 1989207536Smav SATA_SC_IPM_DIS_PARTIAL | SATA_SC_IPM_DIS_SLUMBER); 1990207536Smav DELAY(5000); 1991207536Smav ATA_OUTL(ch->r_mem, SATA_SC, 1992207536Smav SATA_SC_DET_IDLE | val | ((ch->pm_level > 0) ? 0 : 1993207536Smav (SATA_SC_IPM_DIS_PARTIAL | SATA_SC_IPM_DIS_SLUMBER))); 1994207536Smav DELAY(5000); 1995207536Smav if (!mvs_sata_connect(ch)) { 1996207536Smav if (ch->pm_level > 0) 1997207536Smav ATA_OUTL(ch->r_mem, SATA_SC, SATA_SC_DET_DISABLE); 1998207536Smav return (0); 1999207536Smav } 2000207536Smav return (1); 2001207536Smav} 2002207536Smav 2003207536Smavstatic int 2004207536Smavmvs_check_ids(device_t dev, union ccb *ccb) 2005207536Smav{ 2006207536Smav struct mvs_channel *ch = device_get_softc(dev); 2007207536Smav 2008207536Smav if (ccb->ccb_h.target_id > ((ch->quirks & MVS_Q_GENI) ? 0 : 15)) { 2009207536Smav ccb->ccb_h.status = CAM_TID_INVALID; 2010207536Smav xpt_done(ccb); 2011207536Smav return (-1); 2012207536Smav } 2013207536Smav if (ccb->ccb_h.target_lun != 0) { 2014207536Smav ccb->ccb_h.status = CAM_LUN_INVALID; 2015207536Smav xpt_done(ccb); 2016207536Smav return (-1); 2017207536Smav } 2018207536Smav return (0); 2019207536Smav} 2020207536Smav 2021207536Smavstatic void 2022207536Smavmvsaction(struct cam_sim *sim, union ccb *ccb) 2023207536Smav{ 2024210471Smav device_t dev, parent; 2025207536Smav struct mvs_channel *ch; 2026207536Smav 2027207536Smav CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("mvsaction func_code=%x\n", 2028207536Smav ccb->ccb_h.func_code)); 2029207536Smav 2030207536Smav ch = (struct mvs_channel *)cam_sim_softc(sim); 2031207536Smav dev = ch->dev; 2032207536Smav switch (ccb->ccb_h.func_code) { 2033207536Smav /* Common cases first */ 2034207536Smav case XPT_ATA_IO: /* Execute the requested I/O operation */ 2035207536Smav case XPT_SCSI_IO: 2036207536Smav if (mvs_check_ids(dev, ccb)) 2037207536Smav return; 2038207536Smav if (ch->devices == 0 || 2039207536Smav (ch->pm_present == 0 && 2040207536Smav ccb->ccb_h.target_id > 0 && ccb->ccb_h.target_id < 15)) { 2041207536Smav ccb->ccb_h.status = CAM_SEL_TIMEOUT; 2042207536Smav break; 2043207536Smav } 2044207536Smav /* Check for command collision. */ 2045207536Smav if (mvs_check_collision(dev, ccb)) { 2046207536Smav /* Freeze command. */ 2047207536Smav ch->frozen = ccb; 2048207536Smav /* We have only one frozen slot, so freeze simq also. */ 2049207536Smav xpt_freeze_simq(ch->sim, 1); 2050207536Smav return; 2051207536Smav } 2052207536Smav mvs_begin_transaction(dev, ccb); 2053207536Smav return; 2054207536Smav case XPT_EN_LUN: /* Enable LUN as a target */ 2055207536Smav case XPT_TARGET_IO: /* Execute target I/O request */ 2056207536Smav case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 2057207536Smav case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ 2058207536Smav case XPT_ABORT: /* Abort the specified CCB */ 2059207536Smav /* XXX Implement */ 2060207536Smav ccb->ccb_h.status = CAM_REQ_INVALID; 2061207536Smav break; 2062207536Smav case XPT_SET_TRAN_SETTINGS: 2063207536Smav { 2064207536Smav struct ccb_trans_settings *cts = &ccb->cts; 2065207536Smav struct mvs_device *d; 2066207536Smav 2067207536Smav if (mvs_check_ids(dev, ccb)) 2068207536Smav return; 2069207536Smav if (cts->type == CTS_TYPE_CURRENT_SETTINGS) 2070207536Smav d = &ch->curr[ccb->ccb_h.target_id]; 2071207536Smav else 2072207536Smav d = &ch->user[ccb->ccb_h.target_id]; 2073207536Smav if (cts->xport_specific.sata.valid & CTS_SATA_VALID_REVISION) 2074207536Smav d->revision = cts->xport_specific.sata.revision; 2075207536Smav if (cts->xport_specific.sata.valid & CTS_SATA_VALID_MODE) 2076207536Smav d->mode = cts->xport_specific.sata.mode; 2077207536Smav if (cts->xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) { 2078207536Smav d->bytecount = min((ch->quirks & MVS_Q_GENIIE) ? 8192 : 2048, 2079207536Smav cts->xport_specific.sata.bytecount); 2080207536Smav } 2081207536Smav if (cts->xport_specific.sata.valid & CTS_SATA_VALID_TAGS) 2082207536Smav d->tags = min(MVS_MAX_SLOTS, cts->xport_specific.sata.tags); 2083207536Smav if (cts->xport_specific.sata.valid & CTS_SATA_VALID_PM) 2084207536Smav ch->pm_present = cts->xport_specific.sata.pm_present; 2085207536Smav if (cts->xport_specific.sata.valid & CTS_SATA_VALID_ATAPI) 2086207536Smav d->atapi = cts->xport_specific.sata.atapi; 2087207536Smav if (cts->xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 2088207536Smav d->caps = cts->xport_specific.sata.caps; 2089207536Smav ccb->ccb_h.status = CAM_REQ_CMP; 2090207536Smav break; 2091207536Smav } 2092207536Smav case XPT_GET_TRAN_SETTINGS: 2093207536Smav /* Get default/user set transfer settings for the target */ 2094207536Smav { 2095207536Smav struct ccb_trans_settings *cts = &ccb->cts; 2096207536Smav struct mvs_device *d; 2097207536Smav uint32_t status; 2098207536Smav 2099207536Smav if (mvs_check_ids(dev, ccb)) 2100207536Smav return; 2101207536Smav if (cts->type == CTS_TYPE_CURRENT_SETTINGS) 2102207536Smav d = &ch->curr[ccb->ccb_h.target_id]; 2103207536Smav else 2104207536Smav d = &ch->user[ccb->ccb_h.target_id]; 2105207536Smav cts->protocol = PROTO_ATA; 2106207536Smav cts->protocol_version = PROTO_VERSION_UNSPECIFIED; 2107207536Smav cts->transport = XPORT_SATA; 2108207536Smav cts->transport_version = XPORT_VERSION_UNSPECIFIED; 2109207536Smav cts->proto_specific.valid = 0; 2110207536Smav cts->xport_specific.sata.valid = 0; 2111207536Smav if (cts->type == CTS_TYPE_CURRENT_SETTINGS && 2112207536Smav (ccb->ccb_h.target_id == 15 || 2113207536Smav (ccb->ccb_h.target_id == 0 && !ch->pm_present))) { 2114207536Smav status = ATA_INL(ch->r_mem, SATA_SS) & SATA_SS_SPD_MASK; 2115207536Smav if (status & 0x0f0) { 2116207536Smav cts->xport_specific.sata.revision = 2117207536Smav (status & 0x0f0) >> 4; 2118207536Smav cts->xport_specific.sata.valid |= 2119207536Smav CTS_SATA_VALID_REVISION; 2120207536Smav } 2121207536Smav cts->xport_specific.sata.caps = d->caps & CTS_SATA_CAPS_D; 2122207536Smav// if (ch->pm_level) 2123207536Smav// cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_PMREQ; 2124207536Smav cts->xport_specific.sata.caps &= 2125207536Smav ch->user[ccb->ccb_h.target_id].caps; 2126207536Smav cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS; 2127207536Smav } else { 2128207536Smav cts->xport_specific.sata.revision = d->revision; 2129207536Smav cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION; 2130207536Smav cts->xport_specific.sata.caps = d->caps; 2131207536Smav cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS; 2132207536Smav } 2133207536Smav cts->xport_specific.sata.mode = d->mode; 2134207536Smav cts->xport_specific.sata.valid |= CTS_SATA_VALID_MODE; 2135207536Smav cts->xport_specific.sata.bytecount = d->bytecount; 2136207536Smav cts->xport_specific.sata.valid |= CTS_SATA_VALID_BYTECOUNT; 2137207536Smav cts->xport_specific.sata.pm_present = ch->pm_present; 2138207536Smav cts->xport_specific.sata.valid |= CTS_SATA_VALID_PM; 2139207536Smav cts->xport_specific.sata.tags = d->tags; 2140207536Smav cts->xport_specific.sata.valid |= CTS_SATA_VALID_TAGS; 2141207536Smav cts->xport_specific.sata.atapi = d->atapi; 2142207536Smav cts->xport_specific.sata.valid |= CTS_SATA_VALID_ATAPI; 2143207536Smav ccb->ccb_h.status = CAM_REQ_CMP; 2144207536Smav break; 2145207536Smav } 2146207536Smav case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 2147207536Smav case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 2148207536Smav mvs_reset(dev); 2149207536Smav ccb->ccb_h.status = CAM_REQ_CMP; 2150207536Smav break; 2151207536Smav case XPT_TERM_IO: /* Terminate the I/O process */ 2152207536Smav /* XXX Implement */ 2153207536Smav ccb->ccb_h.status = CAM_REQ_INVALID; 2154207536Smav break; 2155207536Smav case XPT_PATH_INQ: /* Path routing inquiry */ 2156207536Smav { 2157207536Smav struct ccb_pathinq *cpi = &ccb->cpi; 2158207536Smav 2159210471Smav parent = device_get_parent(dev); 2160207536Smav cpi->version_num = 1; /* XXX??? */ 2161207536Smav cpi->hba_inquiry = PI_SDTR_ABLE; 2162207536Smav if (!(ch->quirks & MVS_Q_GENI)) { 2163207536Smav cpi->hba_inquiry |= PI_SATAPM; 2164207536Smav /* Gen-II is extremely slow with NCQ on PMP. */ 2165207536Smav if ((ch->quirks & MVS_Q_GENIIE) || ch->pm_present == 0) 2166207536Smav cpi->hba_inquiry |= PI_TAG_ABLE; 2167207536Smav } 2168207536Smav cpi->target_sprt = 0; 2169207536Smav cpi->hba_misc = PIM_SEQSCAN; 2170207536Smav cpi->hba_eng_cnt = 0; 2171207536Smav if (!(ch->quirks & MVS_Q_GENI)) 2172207536Smav cpi->max_target = 15; 2173207536Smav else 2174207536Smav cpi->max_target = 0; 2175207536Smav cpi->max_lun = 0; 2176207536Smav cpi->initiator_id = 0; 2177207536Smav cpi->bus_id = cam_sim_bus(sim); 2178207536Smav cpi->base_transfer_speed = 150000; 2179207536Smav strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2180207536Smav strncpy(cpi->hba_vid, "Marvell", HBA_IDLEN); 2181207536Smav strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 2182207536Smav cpi->unit_number = cam_sim_unit(sim); 2183207536Smav cpi->transport = XPORT_SATA; 2184207536Smav cpi->transport_version = XPORT_VERSION_UNSPECIFIED; 2185207536Smav cpi->protocol = PROTO_ATA; 2186207536Smav cpi->protocol_version = PROTO_VERSION_UNSPECIFIED; 2187207536Smav cpi->maxio = MAXPHYS; 2188210471Smav if ((ch->quirks & MVS_Q_SOC) == 0) { 2189210471Smav cpi->hba_vendor = pci_get_vendor(parent); 2190210471Smav cpi->hba_device = pci_get_device(parent); 2191210471Smav cpi->hba_subvendor = pci_get_subvendor(parent); 2192210471Smav cpi->hba_subdevice = pci_get_subdevice(parent); 2193210471Smav } 2194207536Smav cpi->ccb_h.status = CAM_REQ_CMP; 2195207536Smav break; 2196207536Smav } 2197207536Smav default: 2198207536Smav ccb->ccb_h.status = CAM_REQ_INVALID; 2199207536Smav break; 2200207536Smav } 2201207536Smav xpt_done(ccb); 2202207536Smav} 2203207536Smav 2204207536Smavstatic void 2205207536Smavmvspoll(struct cam_sim *sim) 2206207536Smav{ 2207207536Smav struct mvs_channel *ch = (struct mvs_channel *)cam_sim_softc(sim); 2208207536Smav struct mvs_intr_arg arg; 2209207536Smav 2210207536Smav arg.arg = ch->dev; 2211207536Smav arg.cause = 2; /* XXX */ 2212207696Smav mvs_ch_intr(&arg); 2213207536Smav} 2214207536Smav 2215