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: stable/11/sys/dev/mvs/mvs.c 315812 2017-03-23 06:40:20Z 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> 36220615Smav#include <sys/conf.h> 37207536Smav#include <sys/endian.h> 38207536Smav#include <sys/malloc.h> 39207536Smav#include <sys/lock.h> 40207536Smav#include <sys/mutex.h> 41207536Smav#include <vm/uma.h> 42207536Smav#include <machine/stdarg.h> 43207536Smav#include <machine/resource.h> 44207536Smav#include <machine/bus.h> 45207536Smav#include <sys/rman.h> 46210471Smav#include <dev/pci/pcivar.h> 47207536Smav#include "mvs.h" 48207536Smav 49207536Smav#include <cam/cam.h> 50207536Smav#include <cam/cam_ccb.h> 51207536Smav#include <cam/cam_sim.h> 52207536Smav#include <cam/cam_xpt_sim.h> 53207536Smav#include <cam/cam_debug.h> 54207536Smav 55207536Smav/* local prototypes */ 56208393Smavstatic int mvs_ch_init(device_t dev); 57208393Smavstatic int mvs_ch_deinit(device_t dev); 58207536Smavstatic int mvs_ch_suspend(device_t dev); 59207536Smavstatic int mvs_ch_resume(device_t dev); 60207536Smavstatic void mvs_dmainit(device_t dev); 61214099Smavstatic void mvs_dmasetupc_cb(void *xsc, 62214099Smav bus_dma_segment_t *segs, int nsegs, int error); 63207536Smavstatic void mvs_dmafini(device_t dev); 64207536Smavstatic void mvs_slotsalloc(device_t dev); 65207536Smavstatic void mvs_slotsfree(device_t dev); 66207536Smavstatic void mvs_setup_edma_queues(device_t dev); 67207536Smavstatic void mvs_set_edma_mode(device_t dev, enum mvs_edma_mode mode); 68207536Smavstatic void mvs_ch_pm(void *arg); 69207536Smavstatic void mvs_ch_intr_locked(void *data); 70207536Smavstatic void mvs_ch_intr(void *data); 71207536Smavstatic void mvs_reset(device_t dev); 72207536Smavstatic void mvs_softreset(device_t dev, union ccb *ccb); 73207536Smav 74207536Smavstatic int mvs_sata_connect(struct mvs_channel *ch); 75207536Smavstatic int mvs_sata_phy_reset(device_t dev); 76207536Smavstatic int mvs_wait(device_t dev, u_int s, u_int c, int t); 77207536Smavstatic void mvs_tfd_read(device_t dev, union ccb *ccb); 78207536Smavstatic void mvs_tfd_write(device_t dev, union ccb *ccb); 79220615Smavstatic void mvs_legacy_intr(device_t dev, int poll); 80207536Smavstatic void mvs_crbq_intr(device_t dev); 81207536Smavstatic void mvs_begin_transaction(device_t dev, union ccb *ccb); 82207536Smavstatic void mvs_legacy_execute_transaction(struct mvs_slot *slot); 83207536Smavstatic void mvs_timeout(struct mvs_slot *slot); 84214099Smavstatic void mvs_dmasetprd(void *arg, 85214099Smav bus_dma_segment_t *segs, int nsegs, int error); 86207536Smavstatic void mvs_requeue_frozen(device_t dev); 87207536Smavstatic void mvs_execute_transaction(struct mvs_slot *slot); 88207536Smavstatic void mvs_end_transaction(struct mvs_slot *slot, enum mvs_err_type et); 89207536Smav 90220569Smavstatic void mvs_issue_recovery(device_t dev); 91207536Smavstatic void mvs_process_read_log(device_t dev, union ccb *ccb); 92220569Smavstatic void mvs_process_request_sense(device_t dev, union ccb *ccb); 93207536Smav 94207536Smavstatic void mvsaction(struct cam_sim *sim, union ccb *ccb); 95207536Smavstatic void mvspoll(struct cam_sim *sim); 96207536Smav 97227293Sedstatic MALLOC_DEFINE(M_MVS, "MVS driver", "MVS driver data buffers"); 98207536Smav 99220569Smav#define recovery_type spriv_field0 100220569Smav#define RECOVERY_NONE 0 101220569Smav#define RECOVERY_READ_LOG 1 102220569Smav#define RECOVERY_REQUEST_SENSE 2 103220569Smav#define recovery_slot spriv_field1 104220569Smav 105207536Smavstatic int 106207536Smavmvs_ch_probe(device_t dev) 107207536Smav{ 108207536Smav 109207536Smav device_set_desc_copy(dev, "Marvell SATA channel"); 110280393Smav return (BUS_PROBE_DEFAULT); 111207536Smav} 112207536Smav 113207536Smavstatic int 114207536Smavmvs_ch_attach(device_t dev) 115207536Smav{ 116207536Smav struct mvs_controller *ctlr = device_get_softc(device_get_parent(dev)); 117207536Smav struct mvs_channel *ch = device_get_softc(dev); 118207536Smav struct cam_devq *devq; 119207536Smav int rid, error, i, sata_rev = 0; 120207536Smav 121207536Smav ch->dev = dev; 122207536Smav ch->unit = (intptr_t)device_get_ivars(dev); 123207536Smav ch->quirks = ctlr->quirks; 124207536Smav mtx_init(&ch->mtx, "MVS channel lock", NULL, MTX_DEF); 125271461Smav ch->pm_level = 0; 126207536Smav resource_int_value(device_get_name(dev), 127207536Smav device_get_unit(dev), "pm_level", &ch->pm_level); 128207536Smav if (ch->pm_level > 3) 129207536Smav callout_init_mtx(&ch->pm_timer, &ch->mtx, 0); 130220615Smav callout_init_mtx(&ch->reset_timer, &ch->mtx, 0); 131207536Smav resource_int_value(device_get_name(dev), 132207536Smav device_get_unit(dev), "sata_rev", &sata_rev); 133207536Smav for (i = 0; i < 16; i++) { 134207536Smav ch->user[i].revision = sata_rev; 135207536Smav ch->user[i].mode = 0; 136207536Smav ch->user[i].bytecount = (ch->quirks & MVS_Q_GENIIE) ? 8192 : 2048; 137207536Smav ch->user[i].tags = MVS_MAX_SLOTS; 138207536Smav ch->curr[i] = ch->user[i]; 139207536Smav if (ch->pm_level) { 140207536Smav ch->user[i].caps = CTS_SATA_CAPS_H_PMREQ | 141207536Smav CTS_SATA_CAPS_H_APST | 142207536Smav CTS_SATA_CAPS_D_PMREQ | CTS_SATA_CAPS_D_APST; 143207536Smav } 144220602Smav ch->user[i].caps |= CTS_SATA_CAPS_H_AN; 145207536Smav } 146207536Smav rid = ch->unit; 147207536Smav if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 148207536Smav &rid, RF_ACTIVE))) 149207536Smav return (ENXIO); 150207536Smav mvs_dmainit(dev); 151207536Smav mvs_slotsalloc(dev); 152208393Smav mvs_ch_init(dev); 153207536Smav mtx_lock(&ch->mtx); 154207536Smav rid = ATA_IRQ_RID; 155207536Smav if (!(ch->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, 156207536Smav &rid, RF_SHAREABLE | RF_ACTIVE))) { 157207536Smav device_printf(dev, "Unable to map interrupt\n"); 158207536Smav error = ENXIO; 159207536Smav goto err0; 160207536Smav } 161207536Smav if ((bus_setup_intr(dev, ch->r_irq, ATA_INTR_FLAGS, NULL, 162207536Smav mvs_ch_intr_locked, dev, &ch->ih))) { 163207536Smav device_printf(dev, "Unable to setup interrupt\n"); 164207536Smav error = ENXIO; 165207536Smav goto err1; 166207536Smav } 167207536Smav /* Create the device queue for our SIM. */ 168207536Smav devq = cam_simq_alloc(MVS_MAX_SLOTS - 1); 169207536Smav if (devq == NULL) { 170207536Smav device_printf(dev, "Unable to allocate simq\n"); 171207536Smav error = ENOMEM; 172207536Smav goto err1; 173207536Smav } 174207536Smav /* Construct SIM entry */ 175207536Smav ch->sim = cam_sim_alloc(mvsaction, mvspoll, "mvsch", ch, 176207536Smav device_get_unit(dev), &ch->mtx, 177207536Smav 2, (ch->quirks & MVS_Q_GENI) ? 0 : MVS_MAX_SLOTS - 1, 178207536Smav devq); 179207536Smav if (ch->sim == NULL) { 180207536Smav cam_simq_free(devq); 181207536Smav device_printf(dev, "unable to allocate sim\n"); 182207536Smav error = ENOMEM; 183207536Smav goto err1; 184207536Smav } 185207536Smav if (xpt_bus_register(ch->sim, dev, 0) != CAM_SUCCESS) { 186207536Smav device_printf(dev, "unable to register xpt bus\n"); 187207536Smav error = ENXIO; 188207536Smav goto err2; 189207536Smav } 190207536Smav if (xpt_create_path(&ch->path, /*periph*/NULL, cam_sim_path(ch->sim), 191207536Smav CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 192207536Smav device_printf(dev, "unable to create path\n"); 193207536Smav error = ENXIO; 194207536Smav goto err3; 195207536Smav } 196207536Smav if (ch->pm_level > 3) { 197207536Smav callout_reset(&ch->pm_timer, 198207536Smav (ch->pm_level == 4) ? hz / 1000 : hz / 8, 199207536Smav mvs_ch_pm, dev); 200207536Smav } 201207536Smav mtx_unlock(&ch->mtx); 202207536Smav return (0); 203207536Smav 204207536Smaverr3: 205207536Smav xpt_bus_deregister(cam_sim_path(ch->sim)); 206207536Smaverr2: 207207536Smav cam_sim_free(ch->sim, /*free_devq*/TRUE); 208207536Smaverr1: 209207536Smav bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq); 210207536Smaverr0: 211207536Smav bus_release_resource(dev, SYS_RES_MEMORY, ch->unit, ch->r_mem); 212207536Smav mtx_unlock(&ch->mtx); 213207536Smav mtx_destroy(&ch->mtx); 214207536Smav return (error); 215207536Smav} 216207536Smav 217207536Smavstatic int 218207536Smavmvs_ch_detach(device_t dev) 219207536Smav{ 220207536Smav struct mvs_channel *ch = device_get_softc(dev); 221207536Smav 222207536Smav mtx_lock(&ch->mtx); 223207536Smav xpt_async(AC_LOST_DEVICE, ch->path, NULL); 224220615Smav /* Forget about reset. */ 225220615Smav if (ch->resetting) { 226220615Smav ch->resetting = 0; 227220615Smav xpt_release_simq(ch->sim, TRUE); 228220615Smav } 229207536Smav xpt_free_path(ch->path); 230207536Smav xpt_bus_deregister(cam_sim_path(ch->sim)); 231207536Smav cam_sim_free(ch->sim, /*free_devq*/TRUE); 232207536Smav mtx_unlock(&ch->mtx); 233207536Smav 234207536Smav if (ch->pm_level > 3) 235207536Smav callout_drain(&ch->pm_timer); 236220615Smav callout_drain(&ch->reset_timer); 237207536Smav bus_teardown_intr(dev, ch->r_irq, ch->ih); 238207536Smav bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq); 239207536Smav 240208393Smav mvs_ch_deinit(dev); 241207536Smav mvs_slotsfree(dev); 242207536Smav mvs_dmafini(dev); 243207536Smav 244207536Smav bus_release_resource(dev, SYS_RES_MEMORY, ch->unit, ch->r_mem); 245207536Smav mtx_destroy(&ch->mtx); 246207536Smav return (0); 247207536Smav} 248207536Smav 249207536Smavstatic int 250208393Smavmvs_ch_init(device_t dev) 251207536Smav{ 252207536Smav struct mvs_channel *ch = device_get_softc(dev); 253207536Smav uint32_t reg; 254207536Smav 255207536Smav /* Disable port interrupts */ 256207536Smav ATA_OUTL(ch->r_mem, EDMA_IEM, 0); 257207536Smav /* Stop EDMA */ 258207536Smav ch->curr_mode = MVS_EDMA_UNKNOWN; 259207536Smav mvs_set_edma_mode(dev, MVS_EDMA_OFF); 260207536Smav /* Clear and configure FIS interrupts. */ 261207536Smav ATA_OUTL(ch->r_mem, SATA_FISIC, 0); 262207536Smav reg = ATA_INL(ch->r_mem, SATA_FISC); 263207536Smav reg |= SATA_FISC_FISWAIT4HOSTRDYEN_B1; 264207536Smav ATA_OUTL(ch->r_mem, SATA_FISC, reg); 265207536Smav reg = ATA_INL(ch->r_mem, SATA_FISIM); 266207536Smav reg |= SATA_FISC_FISWAIT4HOSTRDYEN_B1; 267207536Smav ATA_OUTL(ch->r_mem, SATA_FISC, reg); 268207536Smav /* Clear SATA error register. */ 269207536Smav ATA_OUTL(ch->r_mem, SATA_SE, 0xffffffff); 270207536Smav /* Clear any outstanding error interrupts. */ 271207536Smav ATA_OUTL(ch->r_mem, EDMA_IEC, 0); 272207536Smav /* Unmask all error interrupts */ 273207536Smav ATA_OUTL(ch->r_mem, EDMA_IEM, ~EDMA_IE_TRANSIENT); 274207536Smav return (0); 275207536Smav} 276207536Smav 277208393Smavstatic int 278208393Smavmvs_ch_deinit(device_t dev) 279208393Smav{ 280208393Smav struct mvs_channel *ch = device_get_softc(dev); 281208393Smav 282208393Smav /* Stop EDMA */ 283208393Smav mvs_set_edma_mode(dev, MVS_EDMA_OFF); 284208393Smav /* Disable port interrupts. */ 285208393Smav ATA_OUTL(ch->r_mem, EDMA_IEM, 0); 286208393Smav return (0); 287208393Smav} 288208393Smav 289208393Smavstatic int 290208393Smavmvs_ch_suspend(device_t dev) 291208393Smav{ 292208393Smav struct mvs_channel *ch = device_get_softc(dev); 293208393Smav 294208393Smav mtx_lock(&ch->mtx); 295208393Smav xpt_freeze_simq(ch->sim, 1); 296208393Smav while (ch->oslots) 297208393Smav msleep(ch, &ch->mtx, PRIBIO, "mvssusp", hz/100); 298220615Smav /* Forget about reset. */ 299220615Smav if (ch->resetting) { 300220615Smav ch->resetting = 0; 301220615Smav callout_stop(&ch->reset_timer); 302220615Smav xpt_release_simq(ch->sim, TRUE); 303220615Smav } 304208393Smav mvs_ch_deinit(dev); 305208393Smav mtx_unlock(&ch->mtx); 306208393Smav return (0); 307208393Smav} 308208393Smav 309208393Smavstatic int 310208393Smavmvs_ch_resume(device_t dev) 311208393Smav{ 312208393Smav struct mvs_channel *ch = device_get_softc(dev); 313208393Smav 314208393Smav mtx_lock(&ch->mtx); 315208393Smav mvs_ch_init(dev); 316208393Smav mvs_reset(dev); 317208393Smav xpt_release_simq(ch->sim, TRUE); 318208393Smav mtx_unlock(&ch->mtx); 319208393Smav return (0); 320208393Smav} 321208393Smav 322207536Smavstruct mvs_dc_cb_args { 323207536Smav bus_addr_t maddr; 324207536Smav int error; 325207536Smav}; 326207536Smav 327207536Smavstatic void 328207536Smavmvs_dmainit(device_t dev) 329207536Smav{ 330207536Smav struct mvs_channel *ch = device_get_softc(dev); 331207536Smav struct mvs_dc_cb_args dcba; 332207536Smav 333207536Smav /* EDMA command request area. */ 334207536Smav if (bus_dma_tag_create(bus_get_dma_tag(dev), 1024, 0, 335207536Smav BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 336207536Smav NULL, NULL, MVS_WORKRQ_SIZE, 1, MVS_WORKRQ_SIZE, 337207536Smav 0, NULL, NULL, &ch->dma.workrq_tag)) 338207536Smav goto error; 339207536Smav if (bus_dmamem_alloc(ch->dma.workrq_tag, (void **)&ch->dma.workrq, 0, 340207536Smav &ch->dma.workrq_map)) 341207536Smav goto error; 342214099Smav if (bus_dmamap_load(ch->dma.workrq_tag, ch->dma.workrq_map, 343214099Smav ch->dma.workrq, MVS_WORKRQ_SIZE, mvs_dmasetupc_cb, &dcba, 0) || 344214099Smav dcba.error) { 345214099Smav bus_dmamem_free(ch->dma.workrq_tag, 346214099Smav ch->dma.workrq, ch->dma.workrq_map); 347207536Smav goto error; 348207536Smav } 349207536Smav ch->dma.workrq_bus = dcba.maddr; 350207536Smav /* EDMA command response area. */ 351207536Smav if (bus_dma_tag_create(bus_get_dma_tag(dev), 256, 0, 352207536Smav BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 353207536Smav NULL, NULL, MVS_WORKRP_SIZE, 1, MVS_WORKRP_SIZE, 354207536Smav 0, NULL, NULL, &ch->dma.workrp_tag)) 355207536Smav goto error; 356207536Smav if (bus_dmamem_alloc(ch->dma.workrp_tag, (void **)&ch->dma.workrp, 0, 357207536Smav &ch->dma.workrp_map)) 358207536Smav goto error; 359214099Smav if (bus_dmamap_load(ch->dma.workrp_tag, ch->dma.workrp_map, 360214099Smav ch->dma.workrp, MVS_WORKRP_SIZE, mvs_dmasetupc_cb, &dcba, 0) || 361214099Smav dcba.error) { 362214099Smav bus_dmamem_free(ch->dma.workrp_tag, 363214099Smav ch->dma.workrp, ch->dma.workrp_map); 364207536Smav goto error; 365207536Smav } 366207536Smav ch->dma.workrp_bus = dcba.maddr; 367207536Smav /* Data area. */ 368207536Smav if (bus_dma_tag_create(bus_get_dma_tag(dev), 2, MVS_EPRD_MAX, 369207536Smav BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 370207536Smav NULL, NULL, 371207536Smav MVS_SG_ENTRIES * PAGE_SIZE * MVS_MAX_SLOTS, 372207536Smav MVS_SG_ENTRIES, MVS_EPRD_MAX, 373207536Smav 0, busdma_lock_mutex, &ch->mtx, &ch->dma.data_tag)) { 374207536Smav goto error; 375207536Smav } 376207536Smav return; 377207536Smav 378207536Smaverror: 379207536Smav device_printf(dev, "WARNING - DMA initialization failed\n"); 380207536Smav mvs_dmafini(dev); 381207536Smav} 382207536Smav 383207536Smavstatic void 384207536Smavmvs_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) 385207536Smav{ 386207536Smav struct mvs_dc_cb_args *dcba = (struct mvs_dc_cb_args *)xsc; 387207536Smav 388207536Smav if (!(dcba->error = error)) 389207536Smav dcba->maddr = segs[0].ds_addr; 390207536Smav} 391207536Smav 392207536Smavstatic void 393207536Smavmvs_dmafini(device_t dev) 394207536Smav{ 395207536Smav struct mvs_channel *ch = device_get_softc(dev); 396207536Smav 397207536Smav if (ch->dma.data_tag) { 398207536Smav bus_dma_tag_destroy(ch->dma.data_tag); 399207536Smav ch->dma.data_tag = NULL; 400207536Smav } 401207536Smav if (ch->dma.workrp_bus) { 402207536Smav bus_dmamap_unload(ch->dma.workrp_tag, ch->dma.workrp_map); 403214099Smav bus_dmamem_free(ch->dma.workrp_tag, 404214099Smav ch->dma.workrp, ch->dma.workrp_map); 405207536Smav ch->dma.workrp_bus = 0; 406207536Smav ch->dma.workrp = NULL; 407207536Smav } 408207536Smav if (ch->dma.workrp_tag) { 409207536Smav bus_dma_tag_destroy(ch->dma.workrp_tag); 410207536Smav ch->dma.workrp_tag = NULL; 411207536Smav } 412207536Smav if (ch->dma.workrq_bus) { 413207536Smav bus_dmamap_unload(ch->dma.workrq_tag, ch->dma.workrq_map); 414214099Smav bus_dmamem_free(ch->dma.workrq_tag, 415214099Smav ch->dma.workrq, ch->dma.workrq_map); 416207536Smav ch->dma.workrq_bus = 0; 417207536Smav ch->dma.workrq = NULL; 418207536Smav } 419207536Smav if (ch->dma.workrq_tag) { 420207536Smav bus_dma_tag_destroy(ch->dma.workrq_tag); 421207536Smav ch->dma.workrq_tag = NULL; 422207536Smav } 423207536Smav} 424207536Smav 425207536Smavstatic void 426207536Smavmvs_slotsalloc(device_t dev) 427207536Smav{ 428207536Smav struct mvs_channel *ch = device_get_softc(dev); 429207536Smav int i; 430207536Smav 431207536Smav /* Alloc and setup command/dma slots */ 432207536Smav bzero(ch->slot, sizeof(ch->slot)); 433207536Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 434207536Smav struct mvs_slot *slot = &ch->slot[i]; 435207536Smav 436207536Smav slot->dev = dev; 437207536Smav slot->slot = i; 438207536Smav slot->state = MVS_SLOT_EMPTY; 439207536Smav slot->ccb = NULL; 440207536Smav callout_init_mtx(&slot->timeout, &ch->mtx, 0); 441207536Smav 442207536Smav if (bus_dmamap_create(ch->dma.data_tag, 0, &slot->dma.data_map)) 443207536Smav device_printf(ch->dev, "FAILURE - create data_map\n"); 444207536Smav } 445207536Smav} 446207536Smav 447207536Smavstatic void 448207536Smavmvs_slotsfree(device_t dev) 449207536Smav{ 450207536Smav struct mvs_channel *ch = device_get_softc(dev); 451207536Smav int i; 452207536Smav 453207536Smav /* Free all dma slots */ 454207536Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 455207536Smav struct mvs_slot *slot = &ch->slot[i]; 456207536Smav 457207536Smav callout_drain(&slot->timeout); 458207536Smav if (slot->dma.data_map) { 459207536Smav bus_dmamap_destroy(ch->dma.data_tag, slot->dma.data_map); 460207536Smav slot->dma.data_map = NULL; 461207536Smav } 462207536Smav } 463207536Smav} 464207536Smav 465207536Smavstatic void 466207536Smavmvs_setup_edma_queues(device_t dev) 467207536Smav{ 468207536Smav struct mvs_channel *ch = device_get_softc(dev); 469207536Smav uint64_t work; 470207536Smav 471207536Smav /* Requests queue. */ 472207536Smav work = ch->dma.workrq_bus; 473207536Smav ATA_OUTL(ch->r_mem, EDMA_REQQBAH, work >> 32); 474207536Smav ATA_OUTL(ch->r_mem, EDMA_REQQIP, work & 0xffffffff); 475207536Smav ATA_OUTL(ch->r_mem, EDMA_REQQOP, work & 0xffffffff); 476214099Smav bus_dmamap_sync(ch->dma.workrq_tag, ch->dma.workrq_map, 477214099Smav BUS_DMASYNC_PREWRITE); 478298955Spfg /* Responses queue. */ 479214102Smav memset(ch->dma.workrp, 0xff, MVS_WORKRP_SIZE); 480207536Smav work = ch->dma.workrp_bus; 481207536Smav ATA_OUTL(ch->r_mem, EDMA_RESQBAH, work >> 32); 482207536Smav ATA_OUTL(ch->r_mem, EDMA_RESQIP, work & 0xffffffff); 483207536Smav ATA_OUTL(ch->r_mem, EDMA_RESQOP, work & 0xffffffff); 484214099Smav bus_dmamap_sync(ch->dma.workrp_tag, ch->dma.workrp_map, 485214099Smav BUS_DMASYNC_PREREAD); 486207536Smav ch->out_idx = 0; 487207536Smav ch->in_idx = 0; 488207536Smav} 489207536Smav 490207536Smavstatic void 491207536Smavmvs_set_edma_mode(device_t dev, enum mvs_edma_mode mode) 492207536Smav{ 493207536Smav struct mvs_channel *ch = device_get_softc(dev); 494207536Smav int timeout; 495207536Smav uint32_t ecfg, fcfg, hc, ltm, unkn; 496207536Smav 497207536Smav if (mode == ch->curr_mode) 498207536Smav return; 499207536Smav /* If we are running, we should stop first. */ 500207536Smav if (ch->curr_mode != MVS_EDMA_OFF) { 501207536Smav ATA_OUTL(ch->r_mem, EDMA_CMD, EDMA_CMD_EDSEDMA); 502207536Smav timeout = 0; 503207536Smav while (ATA_INL(ch->r_mem, EDMA_CMD) & EDMA_CMD_EENEDMA) { 504207536Smav DELAY(1000); 505207536Smav if (timeout++ > 1000) { 506207536Smav device_printf(dev, "stopping EDMA engine failed\n"); 507207536Smav break; 508207536Smav } 509297793Spfg } 510207536Smav } 511207536Smav ch->curr_mode = mode; 512207536Smav ch->fbs_enabled = 0; 513207536Smav ch->fake_busy = 0; 514207536Smav /* Report mode to controller. Needed for correct CCC operation. */ 515207536Smav MVS_EDMA(device_get_parent(dev), dev, mode); 516207536Smav /* Configure new mode. */ 517207536Smav ecfg = EDMA_CFG_RESERVED | EDMA_CFG_RESERVED2 | EDMA_CFG_EHOSTQUEUECACHEEN; 518207536Smav if (ch->pm_present) { 519207536Smav ecfg |= EDMA_CFG_EMASKRXPM; 520207536Smav if (ch->quirks & MVS_Q_GENIIE) { 521207536Smav ecfg |= EDMA_CFG_EEDMAFBS; 522207536Smav ch->fbs_enabled = 1; 523207536Smav } 524207536Smav } 525207536Smav if (ch->quirks & MVS_Q_GENI) 526207536Smav ecfg |= EDMA_CFG_ERDBSZ; 527207536Smav else if (ch->quirks & MVS_Q_GENII) 528207536Smav ecfg |= EDMA_CFG_ERDBSZEXT | EDMA_CFG_EWRBUFFERLEN; 529207536Smav if (ch->quirks & MVS_Q_CT) 530207536Smav ecfg |= EDMA_CFG_ECUTTHROUGHEN; 531207536Smav if (mode != MVS_EDMA_OFF) 532207536Smav ecfg |= EDMA_CFG_EEARLYCOMPLETIONEN; 533207536Smav if (mode == MVS_EDMA_QUEUED) 534207536Smav ecfg |= EDMA_CFG_EQUE; 535207536Smav else if (mode == MVS_EDMA_NCQ) 536207536Smav ecfg |= EDMA_CFG_ESATANATVCMDQUE; 537207536Smav ATA_OUTL(ch->r_mem, EDMA_CFG, ecfg); 538207536Smav mvs_setup_edma_queues(dev); 539207536Smav if (ch->quirks & MVS_Q_GENIIE) { 540207536Smav /* Configure FBS-related registers */ 541207536Smav fcfg = ATA_INL(ch->r_mem, SATA_FISC); 542207536Smav ltm = ATA_INL(ch->r_mem, SATA_LTM); 543207536Smav hc = ATA_INL(ch->r_mem, EDMA_HC); 544207536Smav if (ch->fbs_enabled) { 545207536Smav fcfg |= SATA_FISC_FISDMAACTIVATESYNCRESP; 546207536Smav if (mode == MVS_EDMA_NCQ) { 547207536Smav fcfg &= ~SATA_FISC_FISWAIT4HOSTRDYEN_B0; 548207536Smav hc &= ~EDMA_IE_EDEVERR; 549207536Smav } else { 550207536Smav fcfg |= SATA_FISC_FISWAIT4HOSTRDYEN_B0; 551207536Smav hc |= EDMA_IE_EDEVERR; 552207536Smav } 553207536Smav ltm |= (1 << 8); 554207536Smav } else { 555207536Smav fcfg &= ~SATA_FISC_FISDMAACTIVATESYNCRESP; 556207536Smav fcfg &= ~SATA_FISC_FISWAIT4HOSTRDYEN_B0; 557207536Smav hc |= EDMA_IE_EDEVERR; 558207536Smav ltm &= ~(1 << 8); 559207536Smav } 560207536Smav ATA_OUTL(ch->r_mem, SATA_FISC, fcfg); 561207536Smav ATA_OUTL(ch->r_mem, SATA_LTM, ltm); 562207536Smav ATA_OUTL(ch->r_mem, EDMA_HC, hc); 563207536Smav /* This is some magic, required to handle several DRQs 564207536Smav * with basic DMA. */ 565207536Smav unkn = ATA_INL(ch->r_mem, EDMA_UNKN_RESD); 566207536Smav if (mode == MVS_EDMA_OFF) 567207536Smav unkn |= 1; 568207536Smav else 569207536Smav unkn &= ~1; 570207536Smav ATA_OUTL(ch->r_mem, EDMA_UNKN_RESD, unkn); 571207536Smav } 572207536Smav /* Run EDMA. */ 573207536Smav if (mode != MVS_EDMA_OFF) 574207536Smav ATA_OUTL(ch->r_mem, EDMA_CMD, EDMA_CMD_EENEDMA); 575207536Smav} 576207536Smav 577207536Smavdevclass_t mvs_devclass; 578207536Smavdevclass_t mvsch_devclass; 579207536Smavstatic device_method_t mvsch_methods[] = { 580207536Smav DEVMETHOD(device_probe, mvs_ch_probe), 581207536Smav DEVMETHOD(device_attach, mvs_ch_attach), 582207536Smav DEVMETHOD(device_detach, mvs_ch_detach), 583207536Smav DEVMETHOD(device_suspend, mvs_ch_suspend), 584207536Smav DEVMETHOD(device_resume, mvs_ch_resume), 585207536Smav { 0, 0 } 586207536Smav}; 587207536Smavstatic driver_t mvsch_driver = { 588207536Smav "mvsch", 589207536Smav mvsch_methods, 590207536Smav sizeof(struct mvs_channel) 591207536Smav}; 592207536SmavDRIVER_MODULE(mvsch, mvs, mvsch_driver, mvsch_devclass, 0, 0); 593207536SmavDRIVER_MODULE(mvsch, sata, mvsch_driver, mvsch_devclass, 0, 0); 594207536Smav 595207536Smavstatic void 596207536Smavmvs_phy_check_events(device_t dev, u_int32_t serr) 597207536Smav{ 598207536Smav struct mvs_channel *ch = device_get_softc(dev); 599207536Smav 600207536Smav if (ch->pm_level == 0) { 601207536Smav u_int32_t status = ATA_INL(ch->r_mem, SATA_SS); 602207536Smav union ccb *ccb; 603207536Smav 604207536Smav if (bootverbose) { 605207536Smav if (((status & SATA_SS_DET_MASK) == SATA_SS_DET_PHY_ONLINE) && 606207536Smav ((status & SATA_SS_SPD_MASK) != SATA_SS_SPD_NO_SPEED) && 607207536Smav ((status & SATA_SS_IPM_MASK) == SATA_SS_IPM_ACTIVE)) { 608207536Smav device_printf(dev, "CONNECT requested\n"); 609207536Smav } else 610207536Smav device_printf(dev, "DISCONNECT requested\n"); 611207536Smav } 612207536Smav mvs_reset(dev); 613207536Smav if ((ccb = xpt_alloc_ccb_nowait()) == NULL) 614207536Smav return; 615207536Smav if (xpt_create_path(&ccb->ccb_h.path, NULL, 616207536Smav cam_sim_path(ch->sim), 617207536Smav CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 618207536Smav xpt_free_ccb(ccb); 619207536Smav return; 620207536Smav } 621207536Smav xpt_rescan(ccb); 622207536Smav } 623207536Smav} 624207536Smav 625207536Smavstatic void 626207536Smavmvs_notify_events(device_t dev) 627207536Smav{ 628207536Smav struct mvs_channel *ch = device_get_softc(dev); 629207536Smav struct cam_path *dpath; 630207536Smav uint32_t fis; 631207536Smav int d; 632207536Smav 633207536Smav /* Try to read PMP field from SDB FIS. Present only for Gen-IIe. */ 634207536Smav fis = ATA_INL(ch->r_mem, SATA_FISDW0); 635207536Smav if ((fis & 0x80ff) == 0x80a1) 636207536Smav d = (fis & 0x0f00) >> 8; 637207536Smav else 638207536Smav d = ch->pm_present ? 15 : 0; 639207536Smav if (bootverbose) 640207536Smav device_printf(dev, "SNTF %d\n", d); 641207536Smav if (xpt_create_path(&dpath, NULL, 642207536Smav xpt_path_path_id(ch->path), d, 0) == CAM_REQ_CMP) { 643207536Smav xpt_async(AC_SCSI_AEN, dpath, NULL); 644207536Smav xpt_free_path(dpath); 645207536Smav } 646207536Smav} 647207536Smav 648207536Smavstatic void 649207536Smavmvs_ch_intr_locked(void *data) 650207536Smav{ 651207536Smav struct mvs_intr_arg *arg = (struct mvs_intr_arg *)data; 652207536Smav device_t dev = (device_t)arg->arg; 653207536Smav struct mvs_channel *ch = device_get_softc(dev); 654207536Smav 655207536Smav mtx_lock(&ch->mtx); 656207536Smav mvs_ch_intr(data); 657207536Smav mtx_unlock(&ch->mtx); 658207536Smav} 659207536Smav 660207536Smavstatic void 661207536Smavmvs_ch_pm(void *arg) 662207536Smav{ 663207536Smav device_t dev = (device_t)arg; 664207536Smav struct mvs_channel *ch = device_get_softc(dev); 665207536Smav uint32_t work; 666207536Smav 667207536Smav if (ch->numrslots != 0) 668207536Smav return; 669207536Smav /* If we are idle - request power state transition. */ 670207536Smav work = ATA_INL(ch->r_mem, SATA_SC); 671207536Smav work &= ~SATA_SC_SPM_MASK; 672207536Smav if (ch->pm_level == 4) 673207536Smav work |= SATA_SC_SPM_PARTIAL; 674207536Smav else 675207536Smav work |= SATA_SC_SPM_SLUMBER; 676207536Smav ATA_OUTL(ch->r_mem, SATA_SC, work); 677207536Smav} 678207536Smav 679207536Smavstatic void 680207536Smavmvs_ch_pm_wake(device_t dev) 681207536Smav{ 682207536Smav struct mvs_channel *ch = device_get_softc(dev); 683207536Smav uint32_t work; 684207536Smav int timeout = 0; 685207536Smav 686207536Smav work = ATA_INL(ch->r_mem, SATA_SS); 687207536Smav if (work & SATA_SS_IPM_ACTIVE) 688207536Smav return; 689207536Smav /* If we are not in active state - request power state transition. */ 690207536Smav work = ATA_INL(ch->r_mem, SATA_SC); 691207536Smav work &= ~SATA_SC_SPM_MASK; 692207536Smav work |= SATA_SC_SPM_ACTIVE; 693207536Smav ATA_OUTL(ch->r_mem, SATA_SC, work); 694207536Smav /* Wait for transition to happen. */ 695207536Smav while ((ATA_INL(ch->r_mem, SATA_SS) & SATA_SS_IPM_ACTIVE) == 0 && 696207536Smav timeout++ < 100) { 697207536Smav DELAY(100); 698207536Smav } 699207536Smav} 700207536Smav 701207536Smavstatic void 702207536Smavmvs_ch_intr(void *data) 703207536Smav{ 704207536Smav struct mvs_intr_arg *arg = (struct mvs_intr_arg *)data; 705207536Smav device_t dev = (device_t)arg->arg; 706207536Smav struct mvs_channel *ch = device_get_softc(dev); 707207536Smav uint32_t iec, serr = 0, fisic = 0; 708207536Smav enum mvs_err_type et; 709207536Smav int i, ccs, port = -1, selfdis = 0; 710207536Smav int edma = (ch->numtslots != 0 || ch->numdslots != 0); 711207536Smav 712207536Smav /* New item in response queue. */ 713207536Smav if ((arg->cause & 2) && edma) 714207536Smav mvs_crbq_intr(dev); 715207536Smav /* Some error or special event. */ 716207536Smav if (arg->cause & 1) { 717207536Smav iec = ATA_INL(ch->r_mem, EDMA_IEC); 718207536Smav if (iec & EDMA_IE_SERRINT) { 719207536Smav serr = ATA_INL(ch->r_mem, SATA_SE); 720207536Smav ATA_OUTL(ch->r_mem, SATA_SE, serr); 721207536Smav } 722207536Smav /* EDMA self-disabled due to error. */ 723207536Smav if (iec & EDMA_IE_ESELFDIS) 724207536Smav selfdis = 1; 725207536Smav /* Transport interrupt. */ 726207536Smav if (iec & EDMA_IE_ETRANSINT) { 727207536Smav /* For Gen-I this bit means self-disable. */ 728207536Smav if (ch->quirks & MVS_Q_GENI) 729207536Smav selfdis = 1; 730207536Smav /* For Gen-II this bit means SDB-N. */ 731207536Smav else if (ch->quirks & MVS_Q_GENII) 732207536Smav fisic = SATA_FISC_FISWAIT4HOSTRDYEN_B1; 733207536Smav else /* For Gen-IIe - read FIS interrupt cause. */ 734207536Smav fisic = ATA_INL(ch->r_mem, SATA_FISIC); 735207536Smav } 736207536Smav if (selfdis) 737207536Smav ch->curr_mode = MVS_EDMA_UNKNOWN; 738207536Smav ATA_OUTL(ch->r_mem, EDMA_IEC, ~iec); 739207536Smav /* Interface errors or Device error. */ 740207536Smav if (iec & (0xfc1e9000 | EDMA_IE_EDEVERR)) { 741207536Smav port = -1; 742207536Smav if (ch->numpslots != 0) { 743207536Smav ccs = 0; 744207536Smav } else { 745207536Smav if (ch->quirks & MVS_Q_GENIIE) 746207536Smav ccs = EDMA_S_EIOID(ATA_INL(ch->r_mem, EDMA_S)); 747207536Smav else 748207536Smav ccs = EDMA_S_EDEVQUETAG(ATA_INL(ch->r_mem, EDMA_S)); 749207536Smav /* Check if error is one-PMP-port-specific, */ 750207536Smav if (ch->fbs_enabled) { 751207536Smav /* Which ports were active. */ 752207536Smav for (i = 0; i < 16; i++) { 753207536Smav if (ch->numrslotspd[i] == 0) 754207536Smav continue; 755207536Smav if (port == -1) 756207536Smav port = i; 757207536Smav else if (port != i) { 758207536Smav port = -2; 759207536Smav break; 760207536Smav } 761207536Smav } 762207536Smav /* If several ports were active and EDMA still enabled - 763207536Smav * other ports are probably unaffected and may continue. 764207536Smav */ 765207536Smav if (port == -2 && !selfdis) { 766207536Smav uint16_t p = ATA_INL(ch->r_mem, SATA_SATAITC) >> 16; 767207536Smav port = ffs(p) - 1; 768207536Smav if (port != (fls(p) - 1)) 769207536Smav port = -2; 770207536Smav } 771207536Smav } 772207536Smav } 773207536Smav mvs_requeue_frozen(dev); 774207536Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 775207536Smav /* XXX: reqests in loading state. */ 776207536Smav if (((ch->rslots >> i) & 1) == 0) 777207536Smav continue; 778207536Smav if (port >= 0 && 779207536Smav ch->slot[i].ccb->ccb_h.target_id != port) 780207536Smav continue; 781207536Smav if (iec & EDMA_IE_EDEVERR) { /* Device error. */ 782207536Smav if (port != -2) { 783207536Smav if (ch->numtslots == 0) { 784207536Smav /* Untagged operation. */ 785207536Smav if (i == ccs) 786207536Smav et = MVS_ERR_TFE; 787207536Smav else 788207536Smav et = MVS_ERR_INNOCENT; 789207536Smav } else { 790207536Smav /* Tagged operation. */ 791207536Smav et = MVS_ERR_NCQ; 792207536Smav } 793207536Smav } else { 794207536Smav et = MVS_ERR_TFE; 795207536Smav ch->fatalerr = 1; 796207536Smav } 797207536Smav } else if (iec & 0xfc1e9000) { 798214099Smav if (ch->numtslots == 0 && 799214099Smav i != ccs && port != -2) 800207536Smav et = MVS_ERR_INNOCENT; 801207536Smav else 802207536Smav et = MVS_ERR_SATA; 803207536Smav } else 804207536Smav et = MVS_ERR_INVALID; 805207536Smav mvs_end_transaction(&ch->slot[i], et); 806207536Smav } 807207536Smav } 808207536Smav /* Process SDB-N. */ 809207536Smav if (fisic & SATA_FISC_FISWAIT4HOSTRDYEN_B1) 810207536Smav mvs_notify_events(dev); 811207536Smav if (fisic) 812207536Smav ATA_OUTL(ch->r_mem, SATA_FISIC, ~fisic); 813207536Smav /* Process hot-plug. */ 814207536Smav if ((iec & (EDMA_IE_EDEVDIS | EDMA_IE_EDEVCON)) || 815207536Smav (serr & SATA_SE_PHY_CHANGED)) 816207536Smav mvs_phy_check_events(dev, serr); 817207536Smav } 818207536Smav /* Legacy mode device interrupt. */ 819207536Smav if ((arg->cause & 2) && !edma) 820220615Smav mvs_legacy_intr(dev, arg->cause & 4); 821207536Smav} 822207536Smav 823207536Smavstatic uint8_t 824207536Smavmvs_getstatus(device_t dev, int clear) 825207536Smav{ 826207536Smav struct mvs_channel *ch = device_get_softc(dev); 827207536Smav uint8_t status = ATA_INB(ch->r_mem, clear ? ATA_STATUS : ATA_ALTSTAT); 828207536Smav 829207536Smav if (ch->fake_busy) { 830207536Smav if (status & (ATA_S_BUSY | ATA_S_DRQ | ATA_S_ERROR)) 831207536Smav ch->fake_busy = 0; 832207536Smav else 833207536Smav status |= ATA_S_BUSY; 834207536Smav } 835207536Smav return (status); 836207536Smav} 837207536Smav 838207536Smavstatic void 839220615Smavmvs_legacy_intr(device_t dev, int poll) 840207536Smav{ 841207536Smav struct mvs_channel *ch = device_get_softc(dev); 842207536Smav struct mvs_slot *slot = &ch->slot[0]; /* PIO is always in slot 0. */ 843207536Smav union ccb *ccb = slot->ccb; 844207536Smav enum mvs_err_type et = MVS_ERR_NONE; 845207536Smav int port; 846220569Smav u_int length, resid, size; 847220569Smav uint8_t buf[2]; 848207536Smav uint8_t status, ireason; 849207536Smav 850207536Smav /* Clear interrupt and get status. */ 851207536Smav status = mvs_getstatus(dev, 1); 852207536Smav if (slot->state < MVS_SLOT_RUNNING) 853207536Smav return; 854207536Smav port = ccb->ccb_h.target_id & 0x0f; 855207536Smav /* Wait a bit for late !BUSY status update. */ 856207536Smav if (status & ATA_S_BUSY) { 857220615Smav if (poll) 858220615Smav return; 859207536Smav DELAY(100); 860207536Smav if ((status = mvs_getstatus(dev, 1)) & ATA_S_BUSY) { 861207536Smav DELAY(1000); 862207536Smav if ((status = mvs_getstatus(dev, 1)) & ATA_S_BUSY) 863207536Smav return; 864207536Smav } 865207536Smav } 866207536Smav /* If we got an error, we are done. */ 867207536Smav if (status & ATA_S_ERROR) { 868207536Smav et = MVS_ERR_TFE; 869207536Smav goto end_finished; 870207536Smav } 871207536Smav if (ccb->ccb_h.func_code == XPT_ATA_IO) { /* ATA PIO */ 872207536Smav ccb->ataio.res.status = status; 873207536Smav /* Are we moving data? */ 874207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 875207536Smav /* If data read command - get them. */ 876207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 877207536Smav if (mvs_wait(dev, ATA_S_DRQ, ATA_S_BUSY, 1000) < 0) { 878207536Smav device_printf(dev, "timeout waiting for read DRQ\n"); 879207536Smav et = MVS_ERR_TIMEOUT; 880220602Smav xpt_freeze_simq(ch->sim, 1); 881220602Smav ch->toslots |= (1 << slot->slot); 882207536Smav goto end_finished; 883207536Smav } 884207536Smav ATA_INSW_STRM(ch->r_mem, ATA_DATA, 885207536Smav (uint16_t *)(ccb->ataio.data_ptr + ch->donecount), 886207536Smav ch->transfersize / 2); 887207536Smav } 888207536Smav /* Update how far we've gotten. */ 889207536Smav ch->donecount += ch->transfersize; 890207536Smav /* Do we need more? */ 891207536Smav if (ccb->ataio.dxfer_len > ch->donecount) { 892207536Smav /* Set this transfer size according to HW capabilities */ 893207536Smav ch->transfersize = min(ccb->ataio.dxfer_len - ch->donecount, 894251661Smav ch->transfersize); 895207536Smav /* If data write command - put them */ 896207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 897207536Smav if (mvs_wait(dev, ATA_S_DRQ, ATA_S_BUSY, 1000) < 0) { 898214099Smav device_printf(dev, 899214099Smav "timeout waiting for write DRQ\n"); 900207536Smav et = MVS_ERR_TIMEOUT; 901220602Smav xpt_freeze_simq(ch->sim, 1); 902220602Smav ch->toslots |= (1 << slot->slot); 903207536Smav goto end_finished; 904207536Smav } 905207536Smav ATA_OUTSW_STRM(ch->r_mem, ATA_DATA, 906207536Smav (uint16_t *)(ccb->ataio.data_ptr + ch->donecount), 907207536Smav ch->transfersize / 2); 908207536Smav return; 909207536Smav } 910207536Smav /* If data read command, return & wait for interrupt */ 911207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 912207536Smav return; 913207536Smav } 914207536Smav } 915207536Smav } else if (ch->basic_dma) { /* ATAPI DMA */ 916207536Smav if (status & ATA_S_DWF) 917207536Smav et = MVS_ERR_TFE; 918207536Smav else if (ATA_INL(ch->r_mem, DMA_S) & DMA_S_ERR) 919207536Smav et = MVS_ERR_TFE; 920207536Smav /* Stop basic DMA. */ 921207536Smav ATA_OUTL(ch->r_mem, DMA_C, 0); 922207536Smav goto end_finished; 923207536Smav } else { /* ATAPI PIO */ 924214099Smav length = ATA_INB(ch->r_mem,ATA_CYL_LSB) | 925214099Smav (ATA_INB(ch->r_mem,ATA_CYL_MSB) << 8); 926220569Smav size = min(ch->transfersize, length); 927207536Smav ireason = ATA_INB(ch->r_mem,ATA_IREASON); 928207536Smav switch ((ireason & (ATA_I_CMD | ATA_I_IN)) | 929207536Smav (status & ATA_S_DRQ)) { 930207536Smav 931207536Smav case ATAPI_P_CMDOUT: 932214099Smav device_printf(dev, "ATAPI CMDOUT\n"); 933207536Smav /* Return wait for interrupt */ 934207536Smav return; 935207536Smav 936207536Smav case ATAPI_P_WRITE: 937207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 938207536Smav device_printf(dev, "trying to write on read buffer\n"); 939207536Smav et = MVS_ERR_TFE; 940207536Smav goto end_finished; 941207536Smav break; 942207536Smav } 943207536Smav ATA_OUTSW_STRM(ch->r_mem, ATA_DATA, 944207536Smav (uint16_t *)(ccb->csio.data_ptr + ch->donecount), 945220569Smav (size + 1) / 2); 946220569Smav for (resid = ch->transfersize + (size & 1); 947220569Smav resid < length; resid += sizeof(int16_t)) 948220569Smav ATA_OUTW(ch->r_mem, ATA_DATA, 0); 949207536Smav ch->donecount += length; 950207536Smav /* Set next transfer size according to HW capabilities */ 951207536Smav ch->transfersize = min(ccb->csio.dxfer_len - ch->donecount, 952207536Smav ch->curr[ccb->ccb_h.target_id].bytecount); 953207536Smav /* Return wait for interrupt */ 954207536Smav return; 955207536Smav 956207536Smav case ATAPI_P_READ: 957207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 958207536Smav device_printf(dev, "trying to read on write buffer\n"); 959207536Smav et = MVS_ERR_TFE; 960207536Smav goto end_finished; 961207536Smav } 962220569Smav if (size >= 2) { 963220569Smav ATA_INSW_STRM(ch->r_mem, ATA_DATA, 964220569Smav (uint16_t *)(ccb->csio.data_ptr + ch->donecount), 965220569Smav size / 2); 966220569Smav } 967220569Smav if (size & 1) { 968220569Smav ATA_INSW_STRM(ch->r_mem, ATA_DATA, (void*)buf, 1); 969220569Smav ((uint8_t *)ccb->csio.data_ptr + ch->donecount + 970220569Smav (size & ~1))[0] = buf[0]; 971220569Smav } 972220569Smav for (resid = ch->transfersize + (size & 1); 973220569Smav resid < length; resid += sizeof(int16_t)) 974220569Smav ATA_INW(ch->r_mem, ATA_DATA); 975207536Smav ch->donecount += length; 976207536Smav /* Set next transfer size according to HW capabilities */ 977207536Smav ch->transfersize = min(ccb->csio.dxfer_len - ch->donecount, 978207536Smav ch->curr[ccb->ccb_h.target_id].bytecount); 979207536Smav /* Return wait for interrupt */ 980207536Smav return; 981207536Smav 982207536Smav case ATAPI_P_DONEDRQ: 983207536Smav device_printf(dev, 984207536Smav "WARNING - DONEDRQ non conformant device\n"); 985207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 986207536Smav ATA_INSW_STRM(ch->r_mem, ATA_DATA, 987207536Smav (uint16_t *)(ccb->csio.data_ptr + ch->donecount), 988207536Smav length / 2); 989207536Smav ch->donecount += length; 990207536Smav } 991207536Smav else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 992207536Smav ATA_OUTSW_STRM(ch->r_mem, ATA_DATA, 993207536Smav (uint16_t *)(ccb->csio.data_ptr + ch->donecount), 994207536Smav length / 2); 995207536Smav ch->donecount += length; 996207536Smav } 997207536Smav else 998207536Smav et = MVS_ERR_TFE; 999207536Smav /* FALLTHROUGH */ 1000207536Smav 1001207536Smav case ATAPI_P_ABORT: 1002207536Smav case ATAPI_P_DONE: 1003207536Smav if (status & (ATA_S_ERROR | ATA_S_DWF)) 1004207536Smav et = MVS_ERR_TFE; 1005207536Smav goto end_finished; 1006207536Smav 1007207536Smav default: 1008214099Smav device_printf(dev, "unknown transfer phase" 1009214099Smav " (status %02x, ireason %02x)\n", 1010207536Smav status, ireason); 1011207536Smav et = MVS_ERR_TFE; 1012207536Smav } 1013207536Smav } 1014207536Smav 1015207536Smavend_finished: 1016207536Smav mvs_end_transaction(slot, et); 1017207536Smav} 1018207536Smav 1019207536Smavstatic void 1020207536Smavmvs_crbq_intr(device_t dev) 1021207536Smav{ 1022207536Smav struct mvs_channel *ch = device_get_softc(dev); 1023207536Smav struct mvs_crpb *crpb; 1024207536Smav union ccb *ccb; 1025214102Smav int in_idx, fin_idx, cin_idx, slot; 1026214102Smav uint32_t val; 1027207536Smav uint16_t flags; 1028207536Smav 1029214102Smav val = ATA_INL(ch->r_mem, EDMA_RESQIP); 1030214102Smav if (val == 0) 1031214102Smav val = ATA_INL(ch->r_mem, EDMA_RESQIP); 1032214102Smav in_idx = (val & EDMA_RESQP_ERPQP_MASK) >> 1033207536Smav EDMA_RESQP_ERPQP_SHIFT; 1034207536Smav bus_dmamap_sync(ch->dma.workrp_tag, ch->dma.workrp_map, 1035207536Smav BUS_DMASYNC_POSTREAD); 1036214102Smav fin_idx = cin_idx = ch->in_idx; 1037207536Smav ch->in_idx = in_idx; 1038207536Smav while (in_idx != cin_idx) { 1039207536Smav crpb = (struct mvs_crpb *) 1040214102Smav (ch->dma.workrp + MVS_CRPB_OFFSET + 1041214102Smav (MVS_CRPB_SIZE * cin_idx)); 1042207536Smav slot = le16toh(crpb->id) & MVS_CRPB_TAG_MASK; 1043207536Smav flags = le16toh(crpb->rspflg); 1044207536Smav /* 1045298955Spfg * Handle only successful completions here. 1046207536Smav * Errors will be handled by main intr handler. 1047207536Smav */ 1048236952Smav#if defined(__i386__) || defined(__amd64__) 1049214102Smav if (crpb->id == 0xffff && crpb->rspflg == 0xffff) { 1050214102Smav device_printf(dev, "Unfilled CRPB " 1051214102Smav "%d (%d->%d) tag %d flags %04x rs %08x\n", 1052214102Smav cin_idx, fin_idx, in_idx, slot, flags, ch->rslots); 1053236952Smav } else 1054236952Smav#endif 1055236952Smav if (ch->numtslots != 0 || 1056214102Smav (flags & EDMA_IE_EDEVERR) == 0) { 1057236952Smav#if defined(__i386__) || defined(__amd64__) 1058214102Smav crpb->id = 0xffff; 1059214102Smav crpb->rspflg = 0xffff; 1060236952Smav#endif 1061207536Smav if (ch->slot[slot].state >= MVS_SLOT_RUNNING) { 1062207536Smav ccb = ch->slot[slot].ccb; 1063214102Smav ccb->ataio.res.status = 1064214102Smav (flags & MVS_CRPB_ATASTS_MASK) >> 1065207536Smav MVS_CRPB_ATASTS_SHIFT; 1066207536Smav mvs_end_transaction(&ch->slot[slot], MVS_ERR_NONE); 1067214102Smav } else { 1068214102Smav device_printf(dev, "Unused tag in CRPB " 1069214102Smav "%d (%d->%d) tag %d flags %04x rs %08x\n", 1070214102Smav cin_idx, fin_idx, in_idx, slot, flags, 1071214102Smav ch->rslots); 1072214102Smav } 1073214102Smav } else { 1074214102Smav device_printf(dev, 1075214102Smav "CRPB with error %d tag %d flags %04x\n", 1076214102Smav cin_idx, slot, flags); 1077214102Smav } 1078207536Smav cin_idx = (cin_idx + 1) & (MVS_MAX_SLOTS - 1); 1079207536Smav } 1080207536Smav bus_dmamap_sync(ch->dma.workrp_tag, ch->dma.workrp_map, 1081207536Smav BUS_DMASYNC_PREREAD); 1082207536Smav if (cin_idx == ch->in_idx) { 1083207536Smav ATA_OUTL(ch->r_mem, EDMA_RESQOP, 1084207536Smav ch->dma.workrp_bus | (cin_idx << EDMA_RESQP_ERPQP_SHIFT)); 1085207536Smav } 1086207536Smav} 1087207536Smav 1088207536Smav/* Must be called with channel locked. */ 1089207536Smavstatic int 1090207536Smavmvs_check_collision(device_t dev, union ccb *ccb) 1091207536Smav{ 1092207536Smav struct mvs_channel *ch = device_get_softc(dev); 1093207536Smav 1094207536Smav if (ccb->ccb_h.func_code == XPT_ATA_IO) { 1095207536Smav /* NCQ DMA */ 1096207536Smav if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) { 1097207536Smav /* Can't mix NCQ and non-NCQ DMA commands. */ 1098207536Smav if (ch->numdslots != 0) 1099207536Smav return (1); 1100207536Smav /* Can't mix NCQ and PIO commands. */ 1101207536Smav if (ch->numpslots != 0) 1102207536Smav return (1); 1103207536Smav /* If we have no FBS */ 1104207536Smav if (!ch->fbs_enabled) { 1105207536Smav /* Tagged command while tagged to other target is active. */ 1106207536Smav if (ch->numtslots != 0 && 1107207536Smav ch->taggedtarget != ccb->ccb_h.target_id) 1108207536Smav return (1); 1109207536Smav } 1110207536Smav /* Non-NCQ DMA */ 1111207536Smav } else if (ccb->ataio.cmd.flags & CAM_ATAIO_DMA) { 1112207536Smav /* Can't mix non-NCQ DMA and NCQ commands. */ 1113207536Smav if (ch->numtslots != 0) 1114207536Smav return (1); 1115207536Smav /* Can't mix non-NCQ DMA and PIO commands. */ 1116207536Smav if (ch->numpslots != 0) 1117207536Smav return (1); 1118207536Smav /* PIO */ 1119207536Smav } else { 1120207536Smav /* Can't mix PIO with anything. */ 1121207536Smav if (ch->numrslots != 0) 1122207536Smav return (1); 1123207536Smav } 1124207536Smav if (ccb->ataio.cmd.flags & (CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT)) { 1125207536Smav /* Atomic command while anything active. */ 1126207536Smav if (ch->numrslots != 0) 1127207536Smav return (1); 1128207536Smav } 1129207536Smav } else { /* ATAPI */ 1130207536Smav /* ATAPI goes without EDMA, so can't mix it with anything. */ 1131207536Smav if (ch->numrslots != 0) 1132207536Smav return (1); 1133207536Smav } 1134207536Smav /* We have some atomic command running. */ 1135207536Smav if (ch->aslots != 0) 1136207536Smav return (1); 1137207536Smav return (0); 1138207536Smav} 1139207536Smav 1140207536Smavstatic void 1141207536Smavmvs_tfd_read(device_t dev, union ccb *ccb) 1142207536Smav{ 1143207536Smav struct mvs_channel *ch = device_get_softc(dev); 1144207536Smav struct ata_res *res = &ccb->ataio.res; 1145207536Smav 1146207536Smav res->status = ATA_INB(ch->r_mem, ATA_ALTSTAT); 1147207536Smav res->error = ATA_INB(ch->r_mem, ATA_ERROR); 1148207536Smav res->device = ATA_INB(ch->r_mem, ATA_DRIVE); 1149207536Smav ATA_OUTB(ch->r_mem, ATA_CONTROL, ATA_A_HOB); 1150207536Smav res->sector_count_exp = ATA_INB(ch->r_mem, ATA_COUNT); 1151207536Smav res->lba_low_exp = ATA_INB(ch->r_mem, ATA_SECTOR); 1152207536Smav res->lba_mid_exp = ATA_INB(ch->r_mem, ATA_CYL_LSB); 1153207536Smav res->lba_high_exp = ATA_INB(ch->r_mem, ATA_CYL_MSB); 1154207536Smav ATA_OUTB(ch->r_mem, ATA_CONTROL, 0); 1155207536Smav res->sector_count = ATA_INB(ch->r_mem, ATA_COUNT); 1156207536Smav res->lba_low = ATA_INB(ch->r_mem, ATA_SECTOR); 1157207536Smav res->lba_mid = ATA_INB(ch->r_mem, ATA_CYL_LSB); 1158207536Smav res->lba_high = ATA_INB(ch->r_mem, ATA_CYL_MSB); 1159207536Smav} 1160207536Smav 1161207536Smavstatic void 1162207536Smavmvs_tfd_write(device_t dev, union ccb *ccb) 1163207536Smav{ 1164207536Smav struct mvs_channel *ch = device_get_softc(dev); 1165207536Smav struct ata_cmd *cmd = &ccb->ataio.cmd; 1166207536Smav 1167207536Smav ATA_OUTB(ch->r_mem, ATA_DRIVE, cmd->device); 1168207536Smav ATA_OUTB(ch->r_mem, ATA_CONTROL, cmd->control); 1169207536Smav ATA_OUTB(ch->r_mem, ATA_FEATURE, cmd->features_exp); 1170207536Smav ATA_OUTB(ch->r_mem, ATA_FEATURE, cmd->features); 1171207536Smav ATA_OUTB(ch->r_mem, ATA_COUNT, cmd->sector_count_exp); 1172207536Smav ATA_OUTB(ch->r_mem, ATA_COUNT, cmd->sector_count); 1173207536Smav ATA_OUTB(ch->r_mem, ATA_SECTOR, cmd->lba_low_exp); 1174207536Smav ATA_OUTB(ch->r_mem, ATA_SECTOR, cmd->lba_low); 1175207536Smav ATA_OUTB(ch->r_mem, ATA_CYL_LSB, cmd->lba_mid_exp); 1176207536Smav ATA_OUTB(ch->r_mem, ATA_CYL_LSB, cmd->lba_mid); 1177207536Smav ATA_OUTB(ch->r_mem, ATA_CYL_MSB, cmd->lba_high_exp); 1178207536Smav ATA_OUTB(ch->r_mem, ATA_CYL_MSB, cmd->lba_high); 1179207536Smav ATA_OUTB(ch->r_mem, ATA_COMMAND, cmd->command); 1180207536Smav} 1181207536Smav 1182207536Smav 1183207536Smav/* Must be called with channel locked. */ 1184207536Smavstatic void 1185207536Smavmvs_begin_transaction(device_t dev, union ccb *ccb) 1186207536Smav{ 1187207536Smav struct mvs_channel *ch = device_get_softc(dev); 1188207536Smav struct mvs_slot *slot; 1189207536Smav int slotn, tag; 1190207536Smav 1191207536Smav if (ch->pm_level > 0) 1192207536Smav mvs_ch_pm_wake(dev); 1193207536Smav /* Softreset is a special case. */ 1194207536Smav if (ccb->ccb_h.func_code == XPT_ATA_IO && 1195207536Smav (ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL)) { 1196207536Smav mvs_softreset(dev, ccb); 1197207536Smav return; 1198207536Smav } 1199207536Smav /* Choose empty slot. */ 1200207536Smav slotn = ffs(~ch->oslots) - 1; 1201207536Smav if ((ccb->ccb_h.func_code == XPT_ATA_IO) && 1202207536Smav (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) { 1203207536Smav if (ch->quirks & MVS_Q_GENIIE) 1204207536Smav tag = ffs(~ch->otagspd[ccb->ccb_h.target_id]) - 1; 1205207536Smav else 1206207536Smav tag = slotn; 1207207536Smav } else 1208207536Smav tag = 0; 1209207536Smav /* Occupy chosen slot. */ 1210207536Smav slot = &ch->slot[slotn]; 1211207536Smav slot->ccb = ccb; 1212207536Smav slot->tag = tag; 1213207536Smav /* Stop PM timer. */ 1214207536Smav if (ch->numrslots == 0 && ch->pm_level > 3) 1215207536Smav callout_stop(&ch->pm_timer); 1216207536Smav /* Update channel stats. */ 1217207536Smav ch->oslots |= (1 << slot->slot); 1218207536Smav ch->numrslots++; 1219207536Smav ch->numrslotspd[ccb->ccb_h.target_id]++; 1220207536Smav if (ccb->ccb_h.func_code == XPT_ATA_IO) { 1221207536Smav if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) { 1222207536Smav ch->otagspd[ccb->ccb_h.target_id] |= (1 << slot->tag); 1223207536Smav ch->numtslots++; 1224207536Smav ch->numtslotspd[ccb->ccb_h.target_id]++; 1225207536Smav ch->taggedtarget = ccb->ccb_h.target_id; 1226207536Smav mvs_set_edma_mode(dev, MVS_EDMA_NCQ); 1227207536Smav } else if (ccb->ataio.cmd.flags & CAM_ATAIO_DMA) { 1228207536Smav ch->numdslots++; 1229207536Smav mvs_set_edma_mode(dev, MVS_EDMA_ON); 1230207536Smav } else { 1231207536Smav ch->numpslots++; 1232207536Smav mvs_set_edma_mode(dev, MVS_EDMA_OFF); 1233207536Smav } 1234207536Smav if (ccb->ataio.cmd.flags & 1235207536Smav (CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT)) { 1236207536Smav ch->aslots |= (1 << slot->slot); 1237207536Smav } 1238207536Smav } else { 1239207536Smav uint8_t *cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ? 1240207536Smav ccb->csio.cdb_io.cdb_ptr : ccb->csio.cdb_io.cdb_bytes; 1241207536Smav ch->numpslots++; 1242207536Smav /* Use ATAPI DMA only for commands without under-/overruns. */ 1243207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE && 1244207536Smav ch->curr[ccb->ccb_h.target_id].mode >= ATA_DMA && 1245207536Smav (ch->quirks & MVS_Q_SOC) == 0 && 1246207536Smav (cdb[0] == 0x08 || 1247207536Smav cdb[0] == 0x0a || 1248207536Smav cdb[0] == 0x28 || 1249207536Smav cdb[0] == 0x2a || 1250207536Smav cdb[0] == 0x88 || 1251207536Smav cdb[0] == 0x8a || 1252207536Smav cdb[0] == 0xa8 || 1253207536Smav cdb[0] == 0xaa || 1254207536Smav cdb[0] == 0xbe)) { 1255207536Smav ch->basic_dma = 1; 1256207536Smav } 1257207536Smav mvs_set_edma_mode(dev, MVS_EDMA_OFF); 1258207536Smav } 1259207536Smav if (ch->numpslots == 0 || ch->basic_dma) { 1260207536Smav slot->state = MVS_SLOT_LOADING; 1261246713Skib bus_dmamap_load_ccb(ch->dma.data_tag, slot->dma.data_map, 1262246713Skib ccb, mvs_dmasetprd, slot, 0); 1263207536Smav } else 1264207536Smav mvs_legacy_execute_transaction(slot); 1265207536Smav} 1266207536Smav 1267207536Smav/* Locked by busdma engine. */ 1268207536Smavstatic void 1269207536Smavmvs_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 1270207536Smav{ 1271207536Smav struct mvs_slot *slot = arg; 1272207536Smav struct mvs_channel *ch = device_get_softc(slot->dev); 1273207536Smav struct mvs_eprd *eprd; 1274207536Smav int i; 1275207536Smav 1276207536Smav if (error) { 1277207536Smav device_printf(slot->dev, "DMA load error\n"); 1278207536Smav mvs_end_transaction(slot, MVS_ERR_INVALID); 1279207536Smav return; 1280207536Smav } 1281207536Smav KASSERT(nsegs <= MVS_SG_ENTRIES, ("too many DMA segment entries\n")); 1282207536Smav /* If there is only one segment - no need to use S/G table on Gen-IIe. */ 1283207536Smav if (nsegs == 1 && ch->basic_dma == 0 && (ch->quirks & MVS_Q_GENIIE)) { 1284207536Smav slot->dma.addr = segs[0].ds_addr; 1285207536Smav slot->dma.len = segs[0].ds_len; 1286207536Smav } else { 1287207536Smav slot->dma.addr = 0; 1288207536Smav /* Get a piece of the workspace for this EPRD */ 1289207536Smav eprd = (struct mvs_eprd *) 1290207536Smav (ch->dma.workrq + MVS_EPRD_OFFSET + (MVS_EPRD_SIZE * slot->slot)); 1291207536Smav /* Fill S/G table */ 1292207536Smav for (i = 0; i < nsegs; i++) { 1293207536Smav eprd[i].prdbal = htole32(segs[i].ds_addr); 1294207536Smav eprd[i].bytecount = htole32(segs[i].ds_len & MVS_EPRD_MASK); 1295207536Smav eprd[i].prdbah = htole32((segs[i].ds_addr >> 16) >> 16); 1296207536Smav } 1297207536Smav eprd[i - 1].bytecount |= htole32(MVS_EPRD_EOF); 1298207536Smav } 1299207536Smav bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map, 1300207536Smav ((slot->ccb->ccb_h.flags & CAM_DIR_IN) ? 1301207536Smav BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE)); 1302207536Smav if (ch->basic_dma) 1303207536Smav mvs_legacy_execute_transaction(slot); 1304207536Smav else 1305207536Smav mvs_execute_transaction(slot); 1306207536Smav} 1307207536Smav 1308207536Smavstatic void 1309207536Smavmvs_legacy_execute_transaction(struct mvs_slot *slot) 1310207536Smav{ 1311207536Smav device_t dev = slot->dev; 1312207536Smav struct mvs_channel *ch = device_get_softc(dev); 1313207536Smav bus_addr_t eprd; 1314207536Smav union ccb *ccb = slot->ccb; 1315207536Smav int port = ccb->ccb_h.target_id & 0x0f; 1316207536Smav int timeout; 1317207536Smav 1318207536Smav slot->state = MVS_SLOT_RUNNING; 1319207536Smav ch->rslots |= (1 << slot->slot); 1320207536Smav ATA_OUTB(ch->r_mem, SATA_SATAICTL, port << SATA_SATAICTL_PMPTX_SHIFT); 1321207536Smav if (ccb->ccb_h.func_code == XPT_ATA_IO) { 1322207536Smav mvs_tfd_write(dev, ccb); 1323207536Smav /* Device reset doesn't interrupt. */ 1324207536Smav if (ccb->ataio.cmd.command == ATA_DEVICE_RESET) { 1325207536Smav int timeout = 1000000; 1326207536Smav do { 1327207536Smav DELAY(10); 1328207536Smav ccb->ataio.res.status = ATA_INB(ch->r_mem, ATA_STATUS); 1329207536Smav } while (ccb->ataio.res.status & ATA_S_BUSY && timeout--); 1330220615Smav mvs_legacy_intr(dev, 1); 1331207536Smav return; 1332207536Smav } 1333207536Smav ch->donecount = 0; 1334251661Smav if (ccb->ataio.cmd.command == ATA_READ_MUL || 1335251661Smav ccb->ataio.cmd.command == ATA_READ_MUL48 || 1336251661Smav ccb->ataio.cmd.command == ATA_WRITE_MUL || 1337251661Smav ccb->ataio.cmd.command == ATA_WRITE_MUL48) { 1338251661Smav ch->transfersize = min(ccb->ataio.dxfer_len, 1339251661Smav ch->curr[port].bytecount); 1340251661Smav } else 1341251661Smav ch->transfersize = min(ccb->ataio.dxfer_len, 512); 1342207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) 1343207536Smav ch->fake_busy = 1; 1344207536Smav /* If data write command - output the data */ 1345207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 1346207536Smav if (mvs_wait(dev, ATA_S_DRQ, ATA_S_BUSY, 1000) < 0) { 1347214099Smav device_printf(dev, 1348214099Smav "timeout waiting for write DRQ\n"); 1349220602Smav xpt_freeze_simq(ch->sim, 1); 1350220602Smav ch->toslots |= (1 << slot->slot); 1351207536Smav mvs_end_transaction(slot, MVS_ERR_TIMEOUT); 1352207536Smav return; 1353207536Smav } 1354207536Smav ATA_OUTSW_STRM(ch->r_mem, ATA_DATA, 1355207536Smav (uint16_t *)(ccb->ataio.data_ptr + ch->donecount), 1356207536Smav ch->transfersize / 2); 1357207536Smav } 1358207536Smav } else { 1359207536Smav ch->donecount = 0; 1360207536Smav ch->transfersize = min(ccb->csio.dxfer_len, 1361207536Smav ch->curr[port].bytecount); 1362207536Smav /* Write ATA PACKET command. */ 1363207536Smav if (ch->basic_dma) { 1364207536Smav ATA_OUTB(ch->r_mem, ATA_FEATURE, ATA_F_DMA); 1365207536Smav ATA_OUTB(ch->r_mem, ATA_CYL_LSB, 0); 1366207536Smav ATA_OUTB(ch->r_mem, ATA_CYL_MSB, 0); 1367207536Smav } else { 1368207536Smav ATA_OUTB(ch->r_mem, ATA_FEATURE, 0); 1369207536Smav ATA_OUTB(ch->r_mem, ATA_CYL_LSB, ch->transfersize); 1370207536Smav ATA_OUTB(ch->r_mem, ATA_CYL_MSB, ch->transfersize >> 8); 1371207536Smav } 1372207536Smav ATA_OUTB(ch->r_mem, ATA_COMMAND, ATA_PACKET_CMD); 1373207536Smav ch->fake_busy = 1; 1374207536Smav /* Wait for ready to write ATAPI command block */ 1375207536Smav if (mvs_wait(dev, 0, ATA_S_BUSY, 1000) < 0) { 1376207536Smav device_printf(dev, "timeout waiting for ATAPI !BUSY\n"); 1377220602Smav xpt_freeze_simq(ch->sim, 1); 1378220602Smav ch->toslots |= (1 << slot->slot); 1379207536Smav mvs_end_transaction(slot, MVS_ERR_TIMEOUT); 1380207536Smav return; 1381207536Smav } 1382207536Smav timeout = 5000; 1383207536Smav while (timeout--) { 1384207536Smav int reason = ATA_INB(ch->r_mem, ATA_IREASON); 1385207536Smav int status = ATA_INB(ch->r_mem, ATA_STATUS); 1386207536Smav 1387207536Smav if (((reason & (ATA_I_CMD | ATA_I_IN)) | 1388207536Smav (status & (ATA_S_DRQ | ATA_S_BUSY))) == ATAPI_P_CMDOUT) 1389207536Smav break; 1390207536Smav DELAY(20); 1391207536Smav } 1392207536Smav if (timeout <= 0) { 1393214099Smav device_printf(dev, 1394214099Smav "timeout waiting for ATAPI command ready\n"); 1395220602Smav xpt_freeze_simq(ch->sim, 1); 1396220602Smav ch->toslots |= (1 << slot->slot); 1397207536Smav mvs_end_transaction(slot, MVS_ERR_TIMEOUT); 1398207536Smav return; 1399207536Smav } 1400207536Smav /* Write ATAPI command. */ 1401207536Smav ATA_OUTSW_STRM(ch->r_mem, ATA_DATA, 1402207536Smav (uint16_t *)((ccb->ccb_h.flags & CAM_CDB_POINTER) ? 1403207536Smav ccb->csio.cdb_io.cdb_ptr : ccb->csio.cdb_io.cdb_bytes), 1404207536Smav ch->curr[port].atapi / 2); 1405207536Smav DELAY(10); 1406207536Smav if (ch->basic_dma) { 1407207536Smav /* Start basic DMA. */ 1408207536Smav eprd = ch->dma.workrq_bus + MVS_EPRD_OFFSET + 1409207536Smav (MVS_EPRD_SIZE * slot->slot); 1410207536Smav ATA_OUTL(ch->r_mem, DMA_DTLBA, eprd); 1411207536Smav ATA_OUTL(ch->r_mem, DMA_DTHBA, (eprd >> 16) >> 16); 1412207536Smav ATA_OUTL(ch->r_mem, DMA_C, DMA_C_START | 1413207536Smav (((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) ? 1414207536Smav DMA_C_READ : 0)); 1415220569Smav } 1416207536Smav } 1417207536Smav /* Start command execution timeout */ 1418274819Ssmh callout_reset_sbt(&slot->timeout, SBT_1MS * ccb->ccb_h.timeout, 0, 1419274819Ssmh (timeout_t*)mvs_timeout, slot, 0); 1420207536Smav} 1421207536Smav 1422207536Smav/* Must be called with channel locked. */ 1423207536Smavstatic void 1424207536Smavmvs_execute_transaction(struct mvs_slot *slot) 1425207536Smav{ 1426207536Smav device_t dev = slot->dev; 1427207536Smav struct mvs_channel *ch = device_get_softc(dev); 1428207536Smav bus_addr_t eprd; 1429207536Smav struct mvs_crqb *crqb; 1430207536Smav struct mvs_crqb_gen2e *crqb2e; 1431207536Smav union ccb *ccb = slot->ccb; 1432207536Smav int port = ccb->ccb_h.target_id & 0x0f; 1433207536Smav int i; 1434207536Smav 1435207536Smav /* Get address of the prepared EPRD */ 1436207536Smav eprd = ch->dma.workrq_bus + MVS_EPRD_OFFSET + (MVS_EPRD_SIZE * slot->slot); 1437207536Smav /* Prepare CRQB. Gen IIe uses different CRQB format. */ 1438207536Smav if (ch->quirks & MVS_Q_GENIIE) { 1439207536Smav crqb2e = (struct mvs_crqb_gen2e *) 1440207536Smav (ch->dma.workrq + MVS_CRQB_OFFSET + (MVS_CRQB_SIZE * ch->out_idx)); 1441207536Smav crqb2e->ctrlflg = htole32( 1442207536Smav ((ccb->ccb_h.flags & CAM_DIR_IN) ? MVS_CRQB2E_READ : 0) | 1443207536Smav (slot->tag << MVS_CRQB2E_DTAG_SHIFT) | 1444207536Smav (port << MVS_CRQB2E_PMP_SHIFT) | 1445207536Smav (slot->slot << MVS_CRQB2E_HTAG_SHIFT)); 1446207536Smav /* If there is only one segment - no need to use S/G table. */ 1447207536Smav if (slot->dma.addr != 0) { 1448207536Smav eprd = slot->dma.addr; 1449207536Smav crqb2e->ctrlflg |= htole32(MVS_CRQB2E_CPRD); 1450207536Smav crqb2e->drbc = slot->dma.len; 1451207536Smav } 1452207536Smav crqb2e->cprdbl = htole32(eprd); 1453207536Smav crqb2e->cprdbh = htole32((eprd >> 16) >> 16); 1454207536Smav crqb2e->cmd[0] = 0; 1455207536Smav crqb2e->cmd[1] = 0; 1456207536Smav crqb2e->cmd[2] = ccb->ataio.cmd.command; 1457207536Smav crqb2e->cmd[3] = ccb->ataio.cmd.features; 1458207536Smav crqb2e->cmd[4] = ccb->ataio.cmd.lba_low; 1459207536Smav crqb2e->cmd[5] = ccb->ataio.cmd.lba_mid; 1460207536Smav crqb2e->cmd[6] = ccb->ataio.cmd.lba_high; 1461207536Smav crqb2e->cmd[7] = ccb->ataio.cmd.device; 1462207536Smav crqb2e->cmd[8] = ccb->ataio.cmd.lba_low_exp; 1463207536Smav crqb2e->cmd[9] = ccb->ataio.cmd.lba_mid_exp; 1464207536Smav crqb2e->cmd[10] = ccb->ataio.cmd.lba_high_exp; 1465207536Smav crqb2e->cmd[11] = ccb->ataio.cmd.features_exp; 1466207536Smav if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) { 1467207536Smav crqb2e->cmd[12] = slot->tag << 3; 1468207536Smav crqb2e->cmd[13] = 0; 1469207536Smav } else { 1470207536Smav crqb2e->cmd[12] = ccb->ataio.cmd.sector_count; 1471207536Smav crqb2e->cmd[13] = ccb->ataio.cmd.sector_count_exp; 1472207536Smav } 1473207536Smav crqb2e->cmd[14] = 0; 1474207536Smav crqb2e->cmd[15] = 0; 1475207536Smav } else { 1476207536Smav crqb = (struct mvs_crqb *) 1477207536Smav (ch->dma.workrq + MVS_CRQB_OFFSET + (MVS_CRQB_SIZE * ch->out_idx)); 1478207536Smav crqb->cprdbl = htole32(eprd); 1479207536Smav crqb->cprdbh = htole32((eprd >> 16) >> 16); 1480207536Smav crqb->ctrlflg = htole16( 1481207536Smav ((ccb->ccb_h.flags & CAM_DIR_IN) ? MVS_CRQB_READ : 0) | 1482207536Smav (slot->slot << MVS_CRQB_TAG_SHIFT) | 1483207536Smav (port << MVS_CRQB_PMP_SHIFT)); 1484207536Smav i = 0; 1485207536Smav /* 1486207536Smav * Controller can handle only 11 of 12 ATA registers, 1487207536Smav * so we have to choose which one to skip. 1488207536Smav */ 1489207536Smav if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) { 1490207536Smav crqb->cmd[i++] = ccb->ataio.cmd.features_exp; 1491207536Smav crqb->cmd[i++] = 0x11; 1492207536Smav } 1493207536Smav crqb->cmd[i++] = ccb->ataio.cmd.features; 1494207536Smav crqb->cmd[i++] = 0x11; 1495207536Smav if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) { 1496207536Smav crqb->cmd[i++] = slot->tag << 3; 1497207536Smav crqb->cmd[i++] = 0x12; 1498207536Smav } else { 1499207536Smav crqb->cmd[i++] = ccb->ataio.cmd.sector_count_exp; 1500207536Smav crqb->cmd[i++] = 0x12; 1501207536Smav crqb->cmd[i++] = ccb->ataio.cmd.sector_count; 1502207536Smav crqb->cmd[i++] = 0x12; 1503207536Smav } 1504207536Smav crqb->cmd[i++] = ccb->ataio.cmd.lba_low_exp; 1505207536Smav crqb->cmd[i++] = 0x13; 1506207536Smav crqb->cmd[i++] = ccb->ataio.cmd.lba_low; 1507207536Smav crqb->cmd[i++] = 0x13; 1508207536Smav crqb->cmd[i++] = ccb->ataio.cmd.lba_mid_exp; 1509207536Smav crqb->cmd[i++] = 0x14; 1510207536Smav crqb->cmd[i++] = ccb->ataio.cmd.lba_mid; 1511207536Smav crqb->cmd[i++] = 0x14; 1512207536Smav crqb->cmd[i++] = ccb->ataio.cmd.lba_high_exp; 1513207536Smav crqb->cmd[i++] = 0x15; 1514207536Smav crqb->cmd[i++] = ccb->ataio.cmd.lba_high; 1515207536Smav crqb->cmd[i++] = 0x15; 1516207536Smav crqb->cmd[i++] = ccb->ataio.cmd.device; 1517207536Smav crqb->cmd[i++] = 0x16; 1518207536Smav crqb->cmd[i++] = ccb->ataio.cmd.command; 1519207536Smav crqb->cmd[i++] = 0x97; 1520207536Smav } 1521207536Smav bus_dmamap_sync(ch->dma.workrq_tag, ch->dma.workrq_map, 1522207536Smav BUS_DMASYNC_PREWRITE); 1523207536Smav bus_dmamap_sync(ch->dma.workrp_tag, ch->dma.workrp_map, 1524207536Smav BUS_DMASYNC_PREREAD); 1525207536Smav slot->state = MVS_SLOT_RUNNING; 1526207536Smav ch->rslots |= (1 << slot->slot); 1527207536Smav /* Issue command to the controller. */ 1528207536Smav ch->out_idx = (ch->out_idx + 1) & (MVS_MAX_SLOTS - 1); 1529207536Smav ATA_OUTL(ch->r_mem, EDMA_REQQIP, 1530207536Smav ch->dma.workrq_bus + MVS_CRQB_OFFSET + (MVS_CRQB_SIZE * ch->out_idx)); 1531207536Smav /* Start command execution timeout */ 1532274819Ssmh callout_reset_sbt(&slot->timeout, SBT_1MS * ccb->ccb_h.timeout, 0, 1533274819Ssmh (timeout_t*)mvs_timeout, slot, 0); 1534207536Smav return; 1535207536Smav} 1536207536Smav 1537207536Smav/* Must be called with channel locked. */ 1538207536Smavstatic void 1539207536Smavmvs_process_timeout(device_t dev) 1540207536Smav{ 1541207536Smav struct mvs_channel *ch = device_get_softc(dev); 1542207536Smav int i; 1543207536Smav 1544207536Smav mtx_assert(&ch->mtx, MA_OWNED); 1545207536Smav /* Handle the rest of commands. */ 1546207536Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 1547207536Smav /* Do we have a running request on slot? */ 1548207536Smav if (ch->slot[i].state < MVS_SLOT_RUNNING) 1549207536Smav continue; 1550207536Smav mvs_end_transaction(&ch->slot[i], MVS_ERR_TIMEOUT); 1551207536Smav } 1552207536Smav} 1553207536Smav 1554207536Smav/* Must be called with channel locked. */ 1555207536Smavstatic void 1556207536Smavmvs_rearm_timeout(device_t dev) 1557207536Smav{ 1558207536Smav struct mvs_channel *ch = device_get_softc(dev); 1559207536Smav int i; 1560207536Smav 1561207536Smav mtx_assert(&ch->mtx, MA_OWNED); 1562207536Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 1563207536Smav struct mvs_slot *slot = &ch->slot[i]; 1564207536Smav 1565207536Smav /* Do we have a running request on slot? */ 1566207536Smav if (slot->state < MVS_SLOT_RUNNING) 1567207536Smav continue; 1568207536Smav if ((ch->toslots & (1 << i)) == 0) 1569207536Smav continue; 1570274819Ssmh callout_reset_sbt(&slot->timeout, 1571274819Ssmh SBT_1MS * slot->ccb->ccb_h.timeout / 2, 0, 1572274819Ssmh (timeout_t*)mvs_timeout, slot, 0); 1573207536Smav } 1574207536Smav} 1575207536Smav 1576207536Smav/* Locked by callout mechanism. */ 1577207536Smavstatic void 1578207536Smavmvs_timeout(struct mvs_slot *slot) 1579207536Smav{ 1580207536Smav device_t dev = slot->dev; 1581207536Smav struct mvs_channel *ch = device_get_softc(dev); 1582207536Smav 1583207536Smav /* Check for stale timeout. */ 1584207536Smav if (slot->state < MVS_SLOT_RUNNING) 1585207536Smav return; 1586207536Smav device_printf(dev, "Timeout on slot %d\n", slot->slot); 1587207536Smav device_printf(dev, "iec %08x sstat %08x serr %08x edma_s %08x " 1588207536Smav "dma_c %08x dma_s %08x rs %08x status %02x\n", 1589207536Smav ATA_INL(ch->r_mem, EDMA_IEC), 1590207536Smav ATA_INL(ch->r_mem, SATA_SS), ATA_INL(ch->r_mem, SATA_SE), 1591207536Smav ATA_INL(ch->r_mem, EDMA_S), ATA_INL(ch->r_mem, DMA_C), 1592207536Smav ATA_INL(ch->r_mem, DMA_S), ch->rslots, 1593207536Smav ATA_INB(ch->r_mem, ATA_ALTSTAT)); 1594207536Smav /* Handle frozen command. */ 1595207536Smav mvs_requeue_frozen(dev); 1596207536Smav /* We wait for other commands timeout and pray. */ 1597207536Smav if (ch->toslots == 0) 1598207536Smav xpt_freeze_simq(ch->sim, 1); 1599207536Smav ch->toslots |= (1 << slot->slot); 1600207536Smav if ((ch->rslots & ~ch->toslots) == 0) 1601207536Smav mvs_process_timeout(dev); 1602207536Smav else 1603207536Smav device_printf(dev, " ... waiting for slots %08x\n", 1604207536Smav ch->rslots & ~ch->toslots); 1605207536Smav} 1606207536Smav 1607207536Smav/* Must be called with channel locked. */ 1608207536Smavstatic void 1609207536Smavmvs_end_transaction(struct mvs_slot *slot, enum mvs_err_type et) 1610207536Smav{ 1611207536Smav device_t dev = slot->dev; 1612207536Smav struct mvs_channel *ch = device_get_softc(dev); 1613207536Smav union ccb *ccb = slot->ccb; 1614212732Smav int lastto; 1615207536Smav 1616207536Smav bus_dmamap_sync(ch->dma.workrq_tag, ch->dma.workrq_map, 1617207536Smav BUS_DMASYNC_POSTWRITE); 1618207536Smav /* Read result registers to the result struct 1619207536Smav * May be incorrect if several commands finished same time, 1620207536Smav * so read only when sure or have to. 1621207536Smav */ 1622207536Smav if (ccb->ccb_h.func_code == XPT_ATA_IO) { 1623207536Smav struct ata_res *res = &ccb->ataio.res; 1624207536Smav 1625207536Smav if ((et == MVS_ERR_TFE) || 1626207536Smav (ccb->ataio.cmd.flags & CAM_ATAIO_NEEDRESULT)) { 1627207536Smav mvs_tfd_read(dev, ccb); 1628207536Smav } else 1629207536Smav bzero(res, sizeof(*res)); 1630220569Smav } else { 1631220569Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE && 1632220569Smav ch->basic_dma == 0) 1633220569Smav ccb->csio.resid = ccb->csio.dxfer_len - ch->donecount; 1634207536Smav } 1635207536Smav if (ch->numpslots == 0 || ch->basic_dma) { 1636207536Smav if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 1637207536Smav bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map, 1638207536Smav (ccb->ccb_h.flags & CAM_DIR_IN) ? 1639207536Smav BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 1640207536Smav bus_dmamap_unload(ch->dma.data_tag, slot->dma.data_map); 1641207536Smav } 1642207536Smav } 1643207536Smav if (et != MVS_ERR_NONE) 1644207536Smav ch->eslots |= (1 << slot->slot); 1645207536Smav /* In case of error, freeze device for proper recovery. */ 1646220569Smav if ((et != MVS_ERR_NONE) && (!ch->recoverycmd) && 1647207536Smav !(ccb->ccb_h.status & CAM_DEV_QFRZN)) { 1648207536Smav xpt_freeze_devq(ccb->ccb_h.path, 1); 1649207536Smav ccb->ccb_h.status |= CAM_DEV_QFRZN; 1650207536Smav } 1651207536Smav /* Set proper result status. */ 1652207536Smav ccb->ccb_h.status &= ~CAM_STATUS_MASK; 1653207536Smav switch (et) { 1654207536Smav case MVS_ERR_NONE: 1655207536Smav ccb->ccb_h.status |= CAM_REQ_CMP; 1656207536Smav if (ccb->ccb_h.func_code == XPT_SCSI_IO) 1657207536Smav ccb->csio.scsi_status = SCSI_STATUS_OK; 1658207536Smav break; 1659207536Smav case MVS_ERR_INVALID: 1660207536Smav ch->fatalerr = 1; 1661207536Smav ccb->ccb_h.status |= CAM_REQ_INVALID; 1662207536Smav break; 1663207536Smav case MVS_ERR_INNOCENT: 1664207536Smav ccb->ccb_h.status |= CAM_REQUEUE_REQ; 1665207536Smav break; 1666207536Smav case MVS_ERR_TFE: 1667207536Smav case MVS_ERR_NCQ: 1668207536Smav if (ccb->ccb_h.func_code == XPT_SCSI_IO) { 1669207536Smav ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 1670207536Smav ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 1671207536Smav } else { 1672207536Smav ccb->ccb_h.status |= CAM_ATA_STATUS_ERROR; 1673207536Smav } 1674207536Smav break; 1675207536Smav case MVS_ERR_SATA: 1676207536Smav ch->fatalerr = 1; 1677220569Smav if (!ch->recoverycmd) { 1678207536Smav xpt_freeze_simq(ch->sim, 1); 1679207536Smav ccb->ccb_h.status &= ~CAM_STATUS_MASK; 1680207536Smav ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 1681207536Smav } 1682207536Smav ccb->ccb_h.status |= CAM_UNCOR_PARITY; 1683207536Smav break; 1684207536Smav case MVS_ERR_TIMEOUT: 1685220569Smav if (!ch->recoverycmd) { 1686207536Smav xpt_freeze_simq(ch->sim, 1); 1687207536Smav ccb->ccb_h.status &= ~CAM_STATUS_MASK; 1688207536Smav ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 1689207536Smav } 1690207536Smav ccb->ccb_h.status |= CAM_CMD_TIMEOUT; 1691207536Smav break; 1692207536Smav default: 1693207536Smav ch->fatalerr = 1; 1694207536Smav ccb->ccb_h.status |= CAM_REQ_CMP_ERR; 1695207536Smav } 1696207536Smav /* Free slot. */ 1697207536Smav ch->oslots &= ~(1 << slot->slot); 1698207536Smav ch->rslots &= ~(1 << slot->slot); 1699207536Smav ch->aslots &= ~(1 << slot->slot); 1700207536Smav slot->state = MVS_SLOT_EMPTY; 1701207536Smav slot->ccb = NULL; 1702207536Smav /* Update channel stats. */ 1703207536Smav ch->numrslots--; 1704207536Smav ch->numrslotspd[ccb->ccb_h.target_id]--; 1705207536Smav if (ccb->ccb_h.func_code == XPT_ATA_IO) { 1706207536Smav if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) { 1707207536Smav ch->otagspd[ccb->ccb_h.target_id] &= ~(1 << slot->tag); 1708207536Smav ch->numtslots--; 1709207536Smav ch->numtslotspd[ccb->ccb_h.target_id]--; 1710207536Smav } else if (ccb->ataio.cmd.flags & CAM_ATAIO_DMA) { 1711207536Smav ch->numdslots--; 1712207536Smav } else { 1713207536Smav ch->numpslots--; 1714207536Smav } 1715207536Smav } else { 1716207536Smav ch->numpslots--; 1717207536Smav ch->basic_dma = 0; 1718207536Smav } 1719212732Smav /* Cancel timeout state if request completed normally. */ 1720212732Smav if (et != MVS_ERR_TIMEOUT) { 1721212732Smav lastto = (ch->toslots == (1 << slot->slot)); 1722212732Smav ch->toslots &= ~(1 << slot->slot); 1723212732Smav if (lastto) 1724212732Smav xpt_release_simq(ch->sim, TRUE); 1725212732Smav } 1726207536Smav /* If it was our READ LOG command - process it. */ 1727220569Smav if (ccb->ccb_h.recovery_type == RECOVERY_READ_LOG) { 1728207536Smav mvs_process_read_log(dev, ccb); 1729220569Smav /* If it was our REQUEST SENSE command - process it. */ 1730220569Smav } else if (ccb->ccb_h.recovery_type == RECOVERY_REQUEST_SENSE) { 1731220569Smav mvs_process_request_sense(dev, ccb); 1732220569Smav /* If it was NCQ or ATAPI command error, put result on hold. */ 1733220569Smav } else if (et == MVS_ERR_NCQ || 1734220569Smav ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR && 1735220569Smav (ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0)) { 1736207536Smav ch->hold[slot->slot] = ccb; 1737207536Smav ch->holdtag[slot->slot] = slot->tag; 1738207536Smav ch->numhslots++; 1739207536Smav } else 1740207536Smav xpt_done(ccb); 1741207536Smav /* If we have no other active commands, ... */ 1742207536Smav if (ch->rslots == 0) { 1743207536Smav /* if there was fatal error - reset port. */ 1744207536Smav if (ch->toslots != 0 || ch->fatalerr) { 1745207536Smav mvs_reset(dev); 1746207536Smav } else { 1747207536Smav /* if we have slots in error, we can reinit port. */ 1748207536Smav if (ch->eslots != 0) { 1749207536Smav mvs_set_edma_mode(dev, MVS_EDMA_OFF); 1750207536Smav ch->eslots = 0; 1751207536Smav } 1752207536Smav /* if there commands on hold, we can do READ LOG. */ 1753220569Smav if (!ch->recoverycmd && ch->numhslots) 1754220569Smav mvs_issue_recovery(dev); 1755207536Smav } 1756207536Smav /* If all the rest of commands are in timeout - give them chance. */ 1757207536Smav } else if ((ch->rslots & ~ch->toslots) == 0 && 1758207536Smav et != MVS_ERR_TIMEOUT) 1759207536Smav mvs_rearm_timeout(dev); 1760222285Smav /* Unfreeze frozen command. */ 1761222285Smav if (ch->frozen && !mvs_check_collision(dev, ch->frozen)) { 1762222285Smav union ccb *fccb = ch->frozen; 1763222285Smav ch->frozen = NULL; 1764222285Smav mvs_begin_transaction(dev, fccb); 1765222285Smav xpt_release_simq(ch->sim, TRUE); 1766222285Smav } 1767207536Smav /* Start PM timer. */ 1768207536Smav if (ch->numrslots == 0 && ch->pm_level > 3 && 1769207536Smav (ch->curr[ch->pm_present ? 15 : 0].caps & CTS_SATA_CAPS_D_PMREQ)) { 1770207536Smav callout_schedule(&ch->pm_timer, 1771207536Smav (ch->pm_level == 4) ? hz / 1000 : hz / 8); 1772207536Smav } 1773207536Smav} 1774207536Smav 1775207536Smavstatic void 1776220569Smavmvs_issue_recovery(device_t dev) 1777207536Smav{ 1778207536Smav struct mvs_channel *ch = device_get_softc(dev); 1779207536Smav union ccb *ccb; 1780207536Smav struct ccb_ataio *ataio; 1781220569Smav struct ccb_scsiio *csio; 1782207536Smav int i; 1783207536Smav 1784220830Smav /* Find some held command. */ 1785207536Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 1786207536Smav if (ch->hold[i]) 1787207536Smav break; 1788207536Smav } 1789207536Smav ccb = xpt_alloc_ccb_nowait(); 1790207536Smav if (ccb == NULL) { 1791220830Smav device_printf(dev, "Unable to allocate recovery command\n"); 1792220822Smavcompleteall: 1793220830Smav /* We can't do anything -- complete held commands. */ 1794220822Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 1795220822Smav if (ch->hold[i] == NULL) 1796220822Smav continue; 1797220822Smav ch->hold[i]->ccb_h.status &= ~CAM_STATUS_MASK; 1798220822Smav ch->hold[i]->ccb_h.status |= CAM_RESRC_UNAVAIL; 1799220822Smav xpt_done(ch->hold[i]); 1800220822Smav ch->hold[i] = NULL; 1801220822Smav ch->numhslots--; 1802220822Smav } 1803220822Smav mvs_reset(dev); 1804220822Smav return; 1805207536Smav } 1806207536Smav ccb->ccb_h = ch->hold[i]->ccb_h; /* Reuse old header. */ 1807220569Smav if (ccb->ccb_h.func_code == XPT_ATA_IO) { 1808220569Smav /* READ LOG */ 1809220569Smav ccb->ccb_h.recovery_type = RECOVERY_READ_LOG; 1810220569Smav ccb->ccb_h.func_code = XPT_ATA_IO; 1811220569Smav ccb->ccb_h.flags = CAM_DIR_IN; 1812220569Smav ccb->ccb_h.timeout = 1000; /* 1s should be enough. */ 1813220569Smav ataio = &ccb->ataio; 1814220569Smav ataio->data_ptr = malloc(512, M_MVS, M_NOWAIT); 1815220569Smav if (ataio->data_ptr == NULL) { 1816220569Smav xpt_free_ccb(ccb); 1817220822Smav device_printf(dev, 1818220830Smav "Unable to allocate memory for READ LOG command\n"); 1819220822Smav goto completeall; 1820220569Smav } 1821220569Smav ataio->dxfer_len = 512; 1822220569Smav bzero(&ataio->cmd, sizeof(ataio->cmd)); 1823220569Smav ataio->cmd.flags = CAM_ATAIO_48BIT; 1824220569Smav ataio->cmd.command = 0x2F; /* READ LOG EXT */ 1825220569Smav ataio->cmd.sector_count = 1; 1826220569Smav ataio->cmd.sector_count_exp = 0; 1827220569Smav ataio->cmd.lba_low = 0x10; 1828220569Smav ataio->cmd.lba_mid = 0; 1829220569Smav ataio->cmd.lba_mid_exp = 0; 1830220569Smav } else { 1831220569Smav /* REQUEST SENSE */ 1832220569Smav ccb->ccb_h.recovery_type = RECOVERY_REQUEST_SENSE; 1833220569Smav ccb->ccb_h.recovery_slot = i; 1834220569Smav ccb->ccb_h.func_code = XPT_SCSI_IO; 1835220569Smav ccb->ccb_h.flags = CAM_DIR_IN; 1836220569Smav ccb->ccb_h.status = 0; 1837220569Smav ccb->ccb_h.timeout = 1000; /* 1s should be enough. */ 1838220569Smav csio = &ccb->csio; 1839220569Smav csio->data_ptr = (void *)&ch->hold[i]->csio.sense_data; 1840220569Smav csio->dxfer_len = ch->hold[i]->csio.sense_len; 1841220569Smav csio->cdb_len = 6; 1842220569Smav bzero(&csio->cdb_io, sizeof(csio->cdb_io)); 1843220569Smav csio->cdb_io.cdb_bytes[0] = 0x03; 1844220569Smav csio->cdb_io.cdb_bytes[4] = csio->dxfer_len; 1845207536Smav } 1846220822Smav /* Freeze SIM while doing recovery. */ 1847220822Smav ch->recoverycmd = 1; 1848207536Smav xpt_freeze_simq(ch->sim, 1); 1849207536Smav mvs_begin_transaction(dev, ccb); 1850207536Smav} 1851207536Smav 1852207536Smavstatic void 1853207536Smavmvs_process_read_log(device_t dev, union ccb *ccb) 1854207536Smav{ 1855207536Smav struct mvs_channel *ch = device_get_softc(dev); 1856207536Smav uint8_t *data; 1857207536Smav struct ata_res *res; 1858207536Smav int i; 1859207536Smav 1860220569Smav ch->recoverycmd = 0; 1861207536Smav 1862207536Smav data = ccb->ataio.data_ptr; 1863207536Smav if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP && 1864207536Smav (data[0] & 0x80) == 0) { 1865207536Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 1866207536Smav if (!ch->hold[i]) 1867207536Smav continue; 1868207536Smav if (ch->hold[i]->ccb_h.target_id != ccb->ccb_h.target_id) 1869207536Smav continue; 1870207536Smav if ((data[0] & 0x1F) == ch->holdtag[i]) { 1871207536Smav res = &ch->hold[i]->ataio.res; 1872207536Smav res->status = data[2]; 1873207536Smav res->error = data[3]; 1874207536Smav res->lba_low = data[4]; 1875207536Smav res->lba_mid = data[5]; 1876207536Smav res->lba_high = data[6]; 1877207536Smav res->device = data[7]; 1878207536Smav res->lba_low_exp = data[8]; 1879207536Smav res->lba_mid_exp = data[9]; 1880207536Smav res->lba_high_exp = data[10]; 1881207536Smav res->sector_count = data[12]; 1882207536Smav res->sector_count_exp = data[13]; 1883207536Smav } else { 1884207536Smav ch->hold[i]->ccb_h.status &= ~CAM_STATUS_MASK; 1885207536Smav ch->hold[i]->ccb_h.status |= CAM_REQUEUE_REQ; 1886207536Smav } 1887207536Smav xpt_done(ch->hold[i]); 1888207536Smav ch->hold[i] = NULL; 1889207536Smav ch->numhslots--; 1890207536Smav } 1891207536Smav } else { 1892207536Smav if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 1893207536Smav device_printf(dev, "Error while READ LOG EXT\n"); 1894207536Smav else if ((data[0] & 0x80) == 0) { 1895214099Smav device_printf(dev, 1896214099Smav "Non-queued command error in READ LOG EXT\n"); 1897207536Smav } 1898207536Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 1899207536Smav if (!ch->hold[i]) 1900207536Smav continue; 1901207536Smav if (ch->hold[i]->ccb_h.target_id != ccb->ccb_h.target_id) 1902207536Smav continue; 1903207536Smav xpt_done(ch->hold[i]); 1904207536Smav ch->hold[i] = NULL; 1905207536Smav ch->numhslots--; 1906207536Smav } 1907207536Smav } 1908207536Smav free(ccb->ataio.data_ptr, M_MVS); 1909207536Smav xpt_free_ccb(ccb); 1910207536Smav xpt_release_simq(ch->sim, TRUE); 1911207536Smav} 1912207536Smav 1913220569Smavstatic void 1914220569Smavmvs_process_request_sense(device_t dev, union ccb *ccb) 1915220569Smav{ 1916220569Smav struct mvs_channel *ch = device_get_softc(dev); 1917220569Smav int i; 1918220569Smav 1919220569Smav ch->recoverycmd = 0; 1920220569Smav 1921220569Smav i = ccb->ccb_h.recovery_slot; 1922220569Smav if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { 1923220569Smav ch->hold[i]->ccb_h.status |= CAM_AUTOSNS_VALID; 1924220569Smav } else { 1925220569Smav ch->hold[i]->ccb_h.status &= ~CAM_STATUS_MASK; 1926220569Smav ch->hold[i]->ccb_h.status |= CAM_AUTOSENSE_FAIL; 1927220569Smav } 1928220569Smav xpt_done(ch->hold[i]); 1929220569Smav ch->hold[i] = NULL; 1930220569Smav ch->numhslots--; 1931220569Smav xpt_free_ccb(ccb); 1932220569Smav xpt_release_simq(ch->sim, TRUE); 1933220569Smav} 1934220569Smav 1935207536Smavstatic int 1936207536Smavmvs_wait(device_t dev, u_int s, u_int c, int t) 1937207536Smav{ 1938207536Smav int timeout = 0; 1939207536Smav uint8_t st; 1940207536Smav 1941207536Smav while (((st = mvs_getstatus(dev, 0)) & (s | c)) != s) { 1942220615Smav if (timeout >= t) { 1943220615Smav if (t != 0) 1944220615Smav device_printf(dev, "Wait status %02x\n", st); 1945207536Smav return (-1); 1946207536Smav } 1947220615Smav DELAY(1000); 1948220615Smav timeout++; 1949207536Smav } 1950207536Smav return (timeout); 1951207536Smav} 1952207536Smav 1953207536Smavstatic void 1954207536Smavmvs_requeue_frozen(device_t dev) 1955207536Smav{ 1956207536Smav struct mvs_channel *ch = device_get_softc(dev); 1957207536Smav union ccb *fccb = ch->frozen; 1958207536Smav 1959207536Smav if (fccb) { 1960207536Smav ch->frozen = NULL; 1961207536Smav fccb->ccb_h.status = CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ; 1962207536Smav if (!(fccb->ccb_h.status & CAM_DEV_QFRZN)) { 1963207536Smav xpt_freeze_devq(fccb->ccb_h.path, 1); 1964207536Smav fccb->ccb_h.status |= CAM_DEV_QFRZN; 1965207536Smav } 1966207536Smav xpt_done(fccb); 1967207536Smav } 1968207536Smav} 1969207536Smav 1970207536Smavstatic void 1971220615Smavmvs_reset_to(void *arg) 1972220615Smav{ 1973220615Smav device_t dev = arg; 1974220615Smav struct mvs_channel *ch = device_get_softc(dev); 1975220615Smav int t; 1976220615Smav 1977220615Smav if (ch->resetting == 0) 1978220615Smav return; 1979220615Smav ch->resetting--; 1980220615Smav if ((t = mvs_wait(dev, 0, ATA_S_BUSY | ATA_S_DRQ, 0)) >= 0) { 1981220615Smav if (bootverbose) { 1982220615Smav device_printf(dev, 1983220615Smav "MVS reset: device ready after %dms\n", 1984220615Smav (310 - ch->resetting) * 100); 1985220615Smav } 1986220615Smav ch->resetting = 0; 1987220615Smav xpt_release_simq(ch->sim, TRUE); 1988220615Smav return; 1989220615Smav } 1990220615Smav if (ch->resetting == 0) { 1991220615Smav device_printf(dev, 1992220615Smav "MVS reset: device not ready after 31000ms\n"); 1993220615Smav xpt_release_simq(ch->sim, TRUE); 1994220615Smav return; 1995220615Smav } 1996220615Smav callout_schedule(&ch->reset_timer, hz / 10); 1997220615Smav} 1998220615Smav 1999220615Smavstatic void 2000236952Smavmvs_errata(device_t dev) 2001236952Smav{ 2002236952Smav struct mvs_channel *ch = device_get_softc(dev); 2003236952Smav uint32_t val; 2004236952Smav 2005236952Smav if (ch->quirks & MVS_Q_SOC65) { 2006236952Smav val = ATA_INL(ch->r_mem, SATA_PHYM3); 2007236952Smav val &= ~(0x3 << 27); /* SELMUPF = 1 */ 2008236952Smav val |= (0x1 << 27); 2009236952Smav val &= ~(0x3 << 29); /* SELMUPI = 1 */ 2010236952Smav val |= (0x1 << 29); 2011236952Smav ATA_OUTL(ch->r_mem, SATA_PHYM3, val); 2012236952Smav 2013236952Smav val = ATA_INL(ch->r_mem, SATA_PHYM4); 2014236952Smav val &= ~0x1; /* SATU_OD8 = 0 */ 2015236952Smav val |= (0x1 << 16); /* reserved bit 16 = 1 */ 2016236952Smav ATA_OUTL(ch->r_mem, SATA_PHYM4, val); 2017236952Smav 2018236952Smav val = ATA_INL(ch->r_mem, SATA_PHYM9_GEN2); 2019236952Smav val &= ~0xf; /* TXAMP[3:0] = 8 */ 2020236952Smav val |= 0x8; 2021236952Smav val &= ~(0x1 << 14); /* TXAMP[4] = 0 */ 2022236952Smav ATA_OUTL(ch->r_mem, SATA_PHYM9_GEN2, val); 2023236952Smav 2024236952Smav val = ATA_INL(ch->r_mem, SATA_PHYM9_GEN1); 2025236952Smav val &= ~0xf; /* TXAMP[3:0] = 8 */ 2026236952Smav val |= 0x8; 2027236952Smav val &= ~(0x1 << 14); /* TXAMP[4] = 0 */ 2028236952Smav ATA_OUTL(ch->r_mem, SATA_PHYM9_GEN1, val); 2029236952Smav } 2030236952Smav} 2031236952Smav 2032236952Smavstatic void 2033207536Smavmvs_reset(device_t dev) 2034207536Smav{ 2035207536Smav struct mvs_channel *ch = device_get_softc(dev); 2036207536Smav int i; 2037207536Smav 2038207536Smav xpt_freeze_simq(ch->sim, 1); 2039207536Smav if (bootverbose) 2040207536Smav device_printf(dev, "MVS reset...\n"); 2041220615Smav /* Forget about previous reset. */ 2042220615Smav if (ch->resetting) { 2043220615Smav ch->resetting = 0; 2044220615Smav callout_stop(&ch->reset_timer); 2045220615Smav xpt_release_simq(ch->sim, TRUE); 2046220615Smav } 2047207536Smav /* Requeue freezed command. */ 2048207536Smav mvs_requeue_frozen(dev); 2049207536Smav /* Kill the engine and requeue all running commands. */ 2050207536Smav mvs_set_edma_mode(dev, MVS_EDMA_OFF); 2051207536Smav ATA_OUTL(ch->r_mem, DMA_C, 0); 2052207536Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 2053207536Smav /* Do we have a running request on slot? */ 2054207536Smav if (ch->slot[i].state < MVS_SLOT_RUNNING) 2055207536Smav continue; 2056207536Smav /* XXX; Commands in loading state. */ 2057207536Smav mvs_end_transaction(&ch->slot[i], MVS_ERR_INNOCENT); 2058207536Smav } 2059207536Smav for (i = 0; i < MVS_MAX_SLOTS; i++) { 2060207536Smav if (!ch->hold[i]) 2061207536Smav continue; 2062207536Smav xpt_done(ch->hold[i]); 2063207536Smav ch->hold[i] = NULL; 2064207536Smav ch->numhslots--; 2065207536Smav } 2066207536Smav if (ch->toslots != 0) 2067207536Smav xpt_release_simq(ch->sim, TRUE); 2068207536Smav ch->eslots = 0; 2069207536Smav ch->toslots = 0; 2070207536Smav ch->fatalerr = 0; 2071220615Smav ch->fake_busy = 0; 2072207536Smav /* Tell the XPT about the event */ 2073207536Smav xpt_async(AC_BUS_RESET, ch->path, NULL); 2074207536Smav ATA_OUTL(ch->r_mem, EDMA_IEM, 0); 2075207536Smav ATA_OUTL(ch->r_mem, EDMA_CMD, EDMA_CMD_EATARST); 2076207536Smav DELAY(25); 2077207536Smav ATA_OUTL(ch->r_mem, EDMA_CMD, 0); 2078236952Smav mvs_errata(dev); 2079207536Smav /* Reset and reconnect PHY, */ 2080207536Smav if (!mvs_sata_phy_reset(dev)) { 2081207536Smav if (bootverbose) 2082220615Smav device_printf(dev, "MVS reset: device not found\n"); 2083207536Smav ch->devices = 0; 2084207536Smav ATA_OUTL(ch->r_mem, SATA_SE, 0xffffffff); 2085207536Smav ATA_OUTL(ch->r_mem, EDMA_IEC, 0); 2086207536Smav ATA_OUTL(ch->r_mem, EDMA_IEM, ~EDMA_IE_TRANSIENT); 2087207536Smav xpt_release_simq(ch->sim, TRUE); 2088207536Smav return; 2089207536Smav } 2090220615Smav if (bootverbose) 2091220615Smav device_printf(dev, "MVS reset: device found\n"); 2092207536Smav /* Wait for clearing busy status. */ 2093220615Smav if ((i = mvs_wait(dev, 0, ATA_S_BUSY | ATA_S_DRQ, 2094220615Smav dumping ? 31000 : 0)) < 0) { 2095220615Smav if (dumping) { 2096220615Smav device_printf(dev, 2097220615Smav "MVS reset: device not ready after 31000ms\n"); 2098220615Smav } else 2099220615Smav ch->resetting = 310; 2100220615Smav } else if (bootverbose) 2101220615Smav device_printf(dev, "MVS reset: device ready after %dms\n", i); 2102207536Smav ch->devices = 1; 2103207536Smav ATA_OUTL(ch->r_mem, SATA_SE, 0xffffffff); 2104207536Smav ATA_OUTL(ch->r_mem, EDMA_IEC, 0); 2105207536Smav ATA_OUTL(ch->r_mem, EDMA_IEM, ~EDMA_IE_TRANSIENT); 2106220615Smav if (ch->resetting) 2107220615Smav callout_reset(&ch->reset_timer, hz / 10, mvs_reset_to, dev); 2108220615Smav else 2109220615Smav xpt_release_simq(ch->sim, TRUE); 2110207536Smav} 2111207536Smav 2112207536Smavstatic void 2113207536Smavmvs_softreset(device_t dev, union ccb *ccb) 2114207536Smav{ 2115207536Smav struct mvs_channel *ch = device_get_softc(dev); 2116207536Smav int port = ccb->ccb_h.target_id & 0x0f; 2117222285Smav int i, stuck; 2118222285Smav uint8_t status; 2119207536Smav 2120207536Smav mvs_set_edma_mode(dev, MVS_EDMA_OFF); 2121207536Smav ATA_OUTB(ch->r_mem, SATA_SATAICTL, port << SATA_SATAICTL_PMPTX_SHIFT); 2122207536Smav ATA_OUTB(ch->r_mem, ATA_CONTROL, ATA_A_RESET); 2123207536Smav DELAY(10000); 2124207536Smav ATA_OUTB(ch->r_mem, ATA_CONTROL, 0); 2125207536Smav ccb->ccb_h.status &= ~CAM_STATUS_MASK; 2126207536Smav /* Wait for clearing busy status. */ 2127222285Smav if ((i = mvs_wait(dev, 0, ATA_S_BUSY, ccb->ccb_h.timeout)) < 0) { 2128207536Smav ccb->ccb_h.status |= CAM_CMD_TIMEOUT; 2129222285Smav stuck = 1; 2130207536Smav } else { 2131222285Smav status = mvs_getstatus(dev, 0); 2132222285Smav if (status & ATA_S_ERROR) 2133222285Smav ccb->ccb_h.status |= CAM_ATA_STATUS_ERROR; 2134222285Smav else 2135222285Smav ccb->ccb_h.status |= CAM_REQ_CMP; 2136222285Smav if (status & ATA_S_DRQ) 2137222285Smav stuck = 1; 2138222285Smav else 2139222285Smav stuck = 0; 2140207536Smav } 2141207536Smav mvs_tfd_read(dev, ccb); 2142222285Smav 2143222285Smav /* 2144222285Smav * XXX: If some device on PMP failed to soft-reset, 2145222285Smav * try to recover by sending dummy soft-reset to PMP. 2146222285Smav */ 2147222285Smav if (stuck && ch->pm_present && port != 15) { 2148222285Smav ATA_OUTB(ch->r_mem, SATA_SATAICTL, 2149222285Smav 15 << SATA_SATAICTL_PMPTX_SHIFT); 2150222285Smav ATA_OUTB(ch->r_mem, ATA_CONTROL, ATA_A_RESET); 2151222285Smav DELAY(10000); 2152222285Smav ATA_OUTB(ch->r_mem, ATA_CONTROL, 0); 2153222285Smav mvs_wait(dev, 0, ATA_S_BUSY | ATA_S_DRQ, ccb->ccb_h.timeout); 2154222285Smav } 2155222285Smav 2156207536Smav xpt_done(ccb); 2157207536Smav} 2158207536Smav 2159207536Smavstatic int 2160207536Smavmvs_sata_connect(struct mvs_channel *ch) 2161207536Smav{ 2162207536Smav u_int32_t status; 2163220829Smav int timeout, found = 0; 2164207536Smav 2165207536Smav /* Wait up to 100ms for "connect well" */ 2166220829Smav for (timeout = 0; timeout < 1000 ; timeout++) { 2167207536Smav status = ATA_INL(ch->r_mem, SATA_SS); 2168220829Smav if ((status & SATA_SS_DET_MASK) != SATA_SS_DET_NO_DEVICE) 2169220829Smav found = 1; 2170207536Smav if (((status & SATA_SS_DET_MASK) == SATA_SS_DET_PHY_ONLINE) && 2171207536Smav ((status & SATA_SS_SPD_MASK) != SATA_SS_SPD_NO_SPEED) && 2172207536Smav ((status & SATA_SS_IPM_MASK) == SATA_SS_IPM_ACTIVE)) 2173207536Smav break; 2174207536Smav if ((status & SATA_SS_DET_MASK) == SATA_SS_DET_PHY_OFFLINE) { 2175207536Smav if (bootverbose) { 2176207536Smav device_printf(ch->dev, "SATA offline status=%08x\n", 2177207536Smav status); 2178207536Smav } 2179207536Smav return (0); 2180207536Smav } 2181220829Smav if (found == 0 && timeout >= 100) 2182220829Smav break; 2183220829Smav DELAY(100); 2184207536Smav } 2185220829Smav if (timeout >= 1000 || !found) { 2186207536Smav if (bootverbose) { 2187220829Smav device_printf(ch->dev, 2188220829Smav "SATA connect timeout time=%dus status=%08x\n", 2189220829Smav timeout * 100, status); 2190207536Smav } 2191207536Smav return (0); 2192207536Smav } 2193207536Smav if (bootverbose) { 2194220829Smav device_printf(ch->dev, "SATA connect time=%dus status=%08x\n", 2195220829Smav timeout * 100, status); 2196207536Smav } 2197207536Smav /* Clear SATA error register */ 2198207536Smav ATA_OUTL(ch->r_mem, SATA_SE, 0xffffffff); 2199207536Smav return (1); 2200207536Smav} 2201207536Smav 2202207536Smavstatic int 2203207536Smavmvs_sata_phy_reset(device_t dev) 2204207536Smav{ 2205207536Smav struct mvs_channel *ch = device_get_softc(dev); 2206207536Smav int sata_rev; 2207207536Smav uint32_t val; 2208207536Smav 2209207536Smav sata_rev = ch->user[ch->pm_present ? 15 : 0].revision; 2210207536Smav if (sata_rev == 1) 2211207536Smav val = SATA_SC_SPD_SPEED_GEN1; 2212207536Smav else if (sata_rev == 2) 2213207536Smav val = SATA_SC_SPD_SPEED_GEN2; 2214207536Smav else if (sata_rev == 3) 2215207536Smav val = SATA_SC_SPD_SPEED_GEN3; 2216207536Smav else 2217207536Smav val = 0; 2218207536Smav ATA_OUTL(ch->r_mem, SATA_SC, 2219207536Smav SATA_SC_DET_RESET | val | 2220207536Smav SATA_SC_IPM_DIS_PARTIAL | SATA_SC_IPM_DIS_SLUMBER); 2221220829Smav DELAY(1000); 2222207536Smav ATA_OUTL(ch->r_mem, SATA_SC, 2223207536Smav SATA_SC_DET_IDLE | val | ((ch->pm_level > 0) ? 0 : 2224207536Smav (SATA_SC_IPM_DIS_PARTIAL | SATA_SC_IPM_DIS_SLUMBER))); 2225207536Smav if (!mvs_sata_connect(ch)) { 2226207536Smav if (ch->pm_level > 0) 2227207536Smav ATA_OUTL(ch->r_mem, SATA_SC, SATA_SC_DET_DISABLE); 2228207536Smav return (0); 2229207536Smav } 2230207536Smav return (1); 2231207536Smav} 2232207536Smav 2233207536Smavstatic int 2234207536Smavmvs_check_ids(device_t dev, union ccb *ccb) 2235207536Smav{ 2236207536Smav struct mvs_channel *ch = device_get_softc(dev); 2237207536Smav 2238207536Smav if (ccb->ccb_h.target_id > ((ch->quirks & MVS_Q_GENI) ? 0 : 15)) { 2239207536Smav ccb->ccb_h.status = CAM_TID_INVALID; 2240207536Smav xpt_done(ccb); 2241207536Smav return (-1); 2242207536Smav } 2243207536Smav if (ccb->ccb_h.target_lun != 0) { 2244207536Smav ccb->ccb_h.status = CAM_LUN_INVALID; 2245207536Smav xpt_done(ccb); 2246207536Smav return (-1); 2247207536Smav } 2248298143Simp /* 2249298143Simp * It's a programming error to see AUXILIARY register requests. 2250298143Simp */ 2251298143Simp KASSERT(ccb->ccb_h.func_code != XPT_ATA_IO || 2252298143Simp ((ccb->ataio.ata_flags & ATA_FLAG_AUX) == 0), 2253298143Simp ("AUX register unsupported")); 2254207536Smav return (0); 2255207536Smav} 2256207536Smav 2257207536Smavstatic void 2258207536Smavmvsaction(struct cam_sim *sim, union ccb *ccb) 2259207536Smav{ 2260210471Smav device_t dev, parent; 2261207536Smav struct mvs_channel *ch; 2262207536Smav 2263207536Smav CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("mvsaction func_code=%x\n", 2264207536Smav ccb->ccb_h.func_code)); 2265207536Smav 2266207536Smav ch = (struct mvs_channel *)cam_sim_softc(sim); 2267207536Smav dev = ch->dev; 2268207536Smav switch (ccb->ccb_h.func_code) { 2269207536Smav /* Common cases first */ 2270207536Smav case XPT_ATA_IO: /* Execute the requested I/O operation */ 2271207536Smav case XPT_SCSI_IO: 2272207536Smav if (mvs_check_ids(dev, ccb)) 2273207536Smav return; 2274207536Smav if (ch->devices == 0 || 2275207536Smav (ch->pm_present == 0 && 2276207536Smav ccb->ccb_h.target_id > 0 && ccb->ccb_h.target_id < 15)) { 2277207536Smav ccb->ccb_h.status = CAM_SEL_TIMEOUT; 2278207536Smav break; 2279207536Smav } 2280220569Smav ccb->ccb_h.recovery_type = RECOVERY_NONE; 2281207536Smav /* Check for command collision. */ 2282207536Smav if (mvs_check_collision(dev, ccb)) { 2283207536Smav /* Freeze command. */ 2284207536Smav ch->frozen = ccb; 2285207536Smav /* We have only one frozen slot, so freeze simq also. */ 2286207536Smav xpt_freeze_simq(ch->sim, 1); 2287207536Smav return; 2288207536Smav } 2289207536Smav mvs_begin_transaction(dev, ccb); 2290207536Smav return; 2291207536Smav case XPT_ABORT: /* Abort the specified CCB */ 2292207536Smav /* XXX Implement */ 2293207536Smav ccb->ccb_h.status = CAM_REQ_INVALID; 2294207536Smav break; 2295207536Smav case XPT_SET_TRAN_SETTINGS: 2296207536Smav { 2297207536Smav struct ccb_trans_settings *cts = &ccb->cts; 2298207536Smav struct mvs_device *d; 2299207536Smav 2300207536Smav if (mvs_check_ids(dev, ccb)) 2301207536Smav return; 2302207536Smav if (cts->type == CTS_TYPE_CURRENT_SETTINGS) 2303207536Smav d = &ch->curr[ccb->ccb_h.target_id]; 2304207536Smav else 2305207536Smav d = &ch->user[ccb->ccb_h.target_id]; 2306207536Smav if (cts->xport_specific.sata.valid & CTS_SATA_VALID_REVISION) 2307207536Smav d->revision = cts->xport_specific.sata.revision; 2308207536Smav if (cts->xport_specific.sata.valid & CTS_SATA_VALID_MODE) 2309207536Smav d->mode = cts->xport_specific.sata.mode; 2310207536Smav if (cts->xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) { 2311207536Smav d->bytecount = min((ch->quirks & MVS_Q_GENIIE) ? 8192 : 2048, 2312207536Smav cts->xport_specific.sata.bytecount); 2313207536Smav } 2314207536Smav if (cts->xport_specific.sata.valid & CTS_SATA_VALID_TAGS) 2315207536Smav d->tags = min(MVS_MAX_SLOTS, cts->xport_specific.sata.tags); 2316207536Smav if (cts->xport_specific.sata.valid & CTS_SATA_VALID_PM) 2317207536Smav ch->pm_present = cts->xport_specific.sata.pm_present; 2318207536Smav if (cts->xport_specific.sata.valid & CTS_SATA_VALID_ATAPI) 2319207536Smav d->atapi = cts->xport_specific.sata.atapi; 2320207536Smav if (cts->xport_specific.sata.valid & CTS_SATA_VALID_CAPS) 2321207536Smav d->caps = cts->xport_specific.sata.caps; 2322207536Smav ccb->ccb_h.status = CAM_REQ_CMP; 2323207536Smav break; 2324207536Smav } 2325207536Smav case XPT_GET_TRAN_SETTINGS: 2326207536Smav /* Get default/user set transfer settings for the target */ 2327207536Smav { 2328207536Smav struct ccb_trans_settings *cts = &ccb->cts; 2329207536Smav struct mvs_device *d; 2330207536Smav uint32_t status; 2331207536Smav 2332207536Smav if (mvs_check_ids(dev, ccb)) 2333207536Smav return; 2334207536Smav if (cts->type == CTS_TYPE_CURRENT_SETTINGS) 2335207536Smav d = &ch->curr[ccb->ccb_h.target_id]; 2336207536Smav else 2337207536Smav d = &ch->user[ccb->ccb_h.target_id]; 2338236666Smav cts->protocol = PROTO_UNSPECIFIED; 2339207536Smav cts->protocol_version = PROTO_VERSION_UNSPECIFIED; 2340207536Smav cts->transport = XPORT_SATA; 2341207536Smav cts->transport_version = XPORT_VERSION_UNSPECIFIED; 2342207536Smav cts->proto_specific.valid = 0; 2343207536Smav cts->xport_specific.sata.valid = 0; 2344207536Smav if (cts->type == CTS_TYPE_CURRENT_SETTINGS && 2345207536Smav (ccb->ccb_h.target_id == 15 || 2346207536Smav (ccb->ccb_h.target_id == 0 && !ch->pm_present))) { 2347207536Smav status = ATA_INL(ch->r_mem, SATA_SS) & SATA_SS_SPD_MASK; 2348207536Smav if (status & 0x0f0) { 2349207536Smav cts->xport_specific.sata.revision = 2350207536Smav (status & 0x0f0) >> 4; 2351207536Smav cts->xport_specific.sata.valid |= 2352207536Smav CTS_SATA_VALID_REVISION; 2353207536Smav } 2354207536Smav cts->xport_specific.sata.caps = d->caps & CTS_SATA_CAPS_D; 2355207536Smav// if (ch->pm_level) 2356207536Smav// cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_PMREQ; 2357220602Smav cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_AN; 2358207536Smav cts->xport_specific.sata.caps &= 2359207536Smav ch->user[ccb->ccb_h.target_id].caps; 2360207536Smav cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS; 2361207536Smav } else { 2362207536Smav cts->xport_specific.sata.revision = d->revision; 2363207536Smav cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION; 2364207536Smav cts->xport_specific.sata.caps = d->caps; 2365220602Smav if (cts->type == CTS_TYPE_CURRENT_SETTINGS/* && 2366220602Smav (ch->quirks & MVS_Q_GENIIE) == 0*/) 2367220602Smav cts->xport_specific.sata.caps &= ~CTS_SATA_CAPS_H_AN; 2368207536Smav cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS; 2369207536Smav } 2370207536Smav cts->xport_specific.sata.mode = d->mode; 2371207536Smav cts->xport_specific.sata.valid |= CTS_SATA_VALID_MODE; 2372207536Smav cts->xport_specific.sata.bytecount = d->bytecount; 2373207536Smav cts->xport_specific.sata.valid |= CTS_SATA_VALID_BYTECOUNT; 2374207536Smav cts->xport_specific.sata.pm_present = ch->pm_present; 2375207536Smav cts->xport_specific.sata.valid |= CTS_SATA_VALID_PM; 2376207536Smav cts->xport_specific.sata.tags = d->tags; 2377207536Smav cts->xport_specific.sata.valid |= CTS_SATA_VALID_TAGS; 2378207536Smav cts->xport_specific.sata.atapi = d->atapi; 2379207536Smav cts->xport_specific.sata.valid |= CTS_SATA_VALID_ATAPI; 2380207536Smav ccb->ccb_h.status = CAM_REQ_CMP; 2381207536Smav break; 2382207536Smav } 2383207536Smav case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 2384207536Smav case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 2385207536Smav mvs_reset(dev); 2386207536Smav ccb->ccb_h.status = CAM_REQ_CMP; 2387207536Smav break; 2388207536Smav case XPT_TERM_IO: /* Terminate the I/O process */ 2389207536Smav /* XXX Implement */ 2390207536Smav ccb->ccb_h.status = CAM_REQ_INVALID; 2391207536Smav break; 2392207536Smav case XPT_PATH_INQ: /* Path routing inquiry */ 2393207536Smav { 2394207536Smav struct ccb_pathinq *cpi = &ccb->cpi; 2395207536Smav 2396210471Smav parent = device_get_parent(dev); 2397207536Smav cpi->version_num = 1; /* XXX??? */ 2398207536Smav cpi->hba_inquiry = PI_SDTR_ABLE; 2399207536Smav if (!(ch->quirks & MVS_Q_GENI)) { 2400207536Smav cpi->hba_inquiry |= PI_SATAPM; 2401207536Smav /* Gen-II is extremely slow with NCQ on PMP. */ 2402207536Smav if ((ch->quirks & MVS_Q_GENIIE) || ch->pm_present == 0) 2403207536Smav cpi->hba_inquiry |= PI_TAG_ABLE; 2404207536Smav } 2405207536Smav cpi->target_sprt = 0; 2406207536Smav cpi->hba_misc = PIM_SEQSCAN; 2407207536Smav cpi->hba_eng_cnt = 0; 2408207536Smav if (!(ch->quirks & MVS_Q_GENI)) 2409207536Smav cpi->max_target = 15; 2410207536Smav else 2411207536Smav cpi->max_target = 0; 2412207536Smav cpi->max_lun = 0; 2413207536Smav cpi->initiator_id = 0; 2414207536Smav cpi->bus_id = cam_sim_bus(sim); 2415207536Smav cpi->base_transfer_speed = 150000; 2416315812Smav strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2417315812Smav strlcpy(cpi->hba_vid, "Marvell", HBA_IDLEN); 2418315812Smav strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 2419207536Smav cpi->unit_number = cam_sim_unit(sim); 2420207536Smav cpi->transport = XPORT_SATA; 2421207536Smav cpi->transport_version = XPORT_VERSION_UNSPECIFIED; 2422236847Smav cpi->protocol = PROTO_ATA; 2423207536Smav cpi->protocol_version = PROTO_VERSION_UNSPECIFIED; 2424207536Smav cpi->maxio = MAXPHYS; 2425210471Smav if ((ch->quirks & MVS_Q_SOC) == 0) { 2426210471Smav cpi->hba_vendor = pci_get_vendor(parent); 2427210471Smav cpi->hba_device = pci_get_device(parent); 2428210471Smav cpi->hba_subvendor = pci_get_subvendor(parent); 2429210471Smav cpi->hba_subdevice = pci_get_subdevice(parent); 2430210471Smav } 2431207536Smav cpi->ccb_h.status = CAM_REQ_CMP; 2432207536Smav break; 2433207536Smav } 2434207536Smav default: 2435207536Smav ccb->ccb_h.status = CAM_REQ_INVALID; 2436207536Smav break; 2437207536Smav } 2438207536Smav xpt_done(ccb); 2439207536Smav} 2440207536Smav 2441207536Smavstatic void 2442207536Smavmvspoll(struct cam_sim *sim) 2443207536Smav{ 2444207536Smav struct mvs_channel *ch = (struct mvs_channel *)cam_sim_softc(sim); 2445207536Smav struct mvs_intr_arg arg; 2446207536Smav 2447207536Smav arg.arg = ch->dev; 2448220615Smav arg.cause = 2 | 4; /* XXX */ 2449207696Smav mvs_ch_intr(&arg); 2450220615Smav if (ch->resetting != 0 && 2451220615Smav (--ch->resetpolldiv <= 0 || !callout_pending(&ch->reset_timer))) { 2452220615Smav ch->resetpolldiv = 1000; 2453220615Smav mvs_reset_to(ch->dev); 2454220615Smav } 2455207536Smav} 2456207536Smav 2457