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