1183724Ssos/*- 2230132Suqs * Copyright (c) 1998 - 2008 S��ren Schmidt <sos@FreeBSD.org> 3183724Ssos * All rights reserved. 4183724Ssos * 5183724Ssos * Redistribution and use in source and binary forms, with or without 6183724Ssos * modification, are permitted provided that the following conditions 7183724Ssos * are met: 8183724Ssos * 1. Redistributions of source code must retain the above copyright 9183724Ssos * notice, this list of conditions and the following disclaimer, 10183724Ssos * without modification, immediately at the beginning of the file. 11183724Ssos * 2. Redistributions in binary form must reproduce the above copyright 12183724Ssos * notice, this list of conditions and the following disclaimer in the 13183724Ssos * documentation and/or other materials provided with the distribution. 14183724Ssos * 15183724Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16183724Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17183724Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18183724Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19183724Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20183724Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21183724Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22183724Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23183724Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24183724Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25183724Ssos */ 26183724Ssos 27183724Ssos#include <sys/cdefs.h> 28183724Ssos__FBSDID("$FreeBSD$"); 29183724Ssos 30183724Ssos#include <sys/param.h> 31183724Ssos#include <sys/module.h> 32183724Ssos#include <sys/systm.h> 33183724Ssos#include <sys/kernel.h> 34183724Ssos#include <sys/ata.h> 35183724Ssos#include <sys/bus.h> 36183724Ssos#include <sys/endian.h> 37183724Ssos#include <sys/malloc.h> 38183724Ssos#include <sys/lock.h> 39183724Ssos#include <sys/mutex.h> 40183724Ssos#include <sys/sema.h> 41183724Ssos#include <sys/taskqueue.h> 42183724Ssos#include <vm/uma.h> 43183724Ssos#include <machine/stdarg.h> 44183724Ssos#include <machine/resource.h> 45183724Ssos#include <machine/bus.h> 46183724Ssos#include <sys/rman.h> 47183724Ssos#include <dev/pci/pcivar.h> 48183724Ssos#include <dev/pci/pcireg.h> 49183724Ssos#include <dev/ata/ata-all.h> 50183724Ssos#include <dev/ata/ata-pci.h> 51183724Ssos#include <ata_if.h> 52183724Ssos 53183724Ssos/* local prototypes */ 54199259Smavstatic int ata_marvell_chipinit(device_t dev); 55199259Smavstatic int ata_marvell_ch_attach(device_t dev); 56200171Smavstatic int ata_marvell_setmode(device_t dev, int target, int mode); 57203030Smavstatic int ata_marvell_dummy_chipinit(device_t dev); 58188765Smavstatic int ata_marvell_edma_ch_attach(device_t dev); 59188769Smavstatic int ata_marvell_edma_ch_detach(device_t dev); 60183724Ssosstatic int ata_marvell_edma_status(device_t dev); 61183724Ssosstatic int ata_marvell_edma_begin_transaction(struct ata_request *request); 62183724Ssosstatic int ata_marvell_edma_end_transaction(struct ata_request *request); 63183724Ssosstatic void ata_marvell_edma_reset(device_t dev); 64183724Ssosstatic void ata_marvell_edma_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error); 65183724Ssosstatic void ata_marvell_edma_dmainit(device_t dev); 66183724Ssos 67183724Ssos/* misc defines */ 68183724Ssos#define MV_50XX 50 69183724Ssos#define MV_60XX 60 70198700Smav#define MV_6042 62 71198700Smav#define MV_7042 72 72183724Ssos#define MV_61XX 61 73203030Smav#define MV_91XX 91 74183724Ssos 75183724Ssos/* 76183724Ssos * Marvell chipset support functions 77183724Ssos */ 78183724Ssos#define ATA_MV_HOST_BASE(ch) \ 79183724Ssos ((ch->unit & 3) * 0x0100) + (ch->unit > 3 ? 0x30000 : 0x20000) 80183724Ssos#define ATA_MV_EDMA_BASE(ch) \ 81183724Ssos ((ch->unit & 3) * 0x2000) + (ch->unit > 3 ? 0x30000 : 0x20000) 82183724Ssos 83183724Ssosstruct ata_marvell_response { 84183724Ssos u_int16_t tag; 85183724Ssos u_int8_t edma_status; 86183724Ssos u_int8_t dev_status; 87183724Ssos u_int32_t timestamp; 88183724Ssos}; 89183724Ssos 90183724Ssosstruct ata_marvell_dma_prdentry { 91183724Ssos u_int32_t addrlo; 92183724Ssos u_int32_t count; 93183724Ssos u_int32_t addrhi; 94183724Ssos u_int32_t reserved; 95183724Ssos}; 96183724Ssos 97183724Ssosstatic int 98183724Ssosata_marvell_probe(device_t dev) 99183724Ssos{ 100183724Ssos struct ata_pci_controller *ctlr = device_get_softc(dev); 101242625Sdim static const struct ata_chip_id ids[] = 102183724Ssos {{ ATA_M88SX5040, 0, 4, MV_50XX, ATA_SA150, "88SX5040" }, 103183724Ssos { ATA_M88SX5041, 0, 4, MV_50XX, ATA_SA150, "88SX5041" }, 104183724Ssos { ATA_M88SX5080, 0, 8, MV_50XX, ATA_SA150, "88SX5080" }, 105183724Ssos { ATA_M88SX5081, 0, 8, MV_50XX, ATA_SA150, "88SX5081" }, 106183724Ssos { ATA_M88SX6041, 0, 4, MV_60XX, ATA_SA300, "88SX6041" }, 107198700Smav { ATA_M88SX6042, 0, 4, MV_6042, ATA_SA300, "88SX6042" }, 108183724Ssos { ATA_M88SX6081, 0, 8, MV_60XX, ATA_SA300, "88SX6081" }, 109198700Smav { ATA_M88SX7042, 0, 4, MV_7042, ATA_SA300, "88SX7042" }, 110232380Smav { ATA_M88SE6101, 0, 0, MV_61XX, ATA_UDMA6, "88SE6101" }, 111232380Smav { ATA_M88SE6102, 0, 0, MV_61XX, ATA_UDMA6, "88SE6102" }, 112232380Smav { ATA_M88SE6111, 0, 1, MV_61XX, ATA_UDMA6, "88SE6111" }, 113232380Smav { ATA_M88SE6121, 0, 2, MV_61XX, ATA_UDMA6, "88SE6121" }, 114232380Smav { ATA_M88SE6141, 0, 4, MV_61XX, ATA_UDMA6, "88SE6141" }, 115232380Smav { ATA_M88SE6145, 0, 4, MV_61XX, ATA_UDMA6, "88SE6145" }, 116203030Smav { 0x91a41b4b, 0, 0, MV_91XX, ATA_UDMA6, "88SE912x" }, 117183724Ssos { 0, 0, 0, 0, 0, 0}}; 118183724Ssos 119203030Smav if (pci_get_vendor(dev) != ATA_MARVELL_ID && 120203030Smav pci_get_vendor(dev) != ATA_MARVELL2_ID) 121183724Ssos return ENXIO; 122183724Ssos 123183724Ssos if (!(ctlr->chip = ata_match_chip(dev, ids))) 124183724Ssos return ENXIO; 125183724Ssos 126183724Ssos ata_set_desc(dev); 127183724Ssos 128183724Ssos switch (ctlr->chip->cfg2) { 129183724Ssos case MV_50XX: 130183724Ssos case MV_60XX: 131198700Smav case MV_6042: 132198700Smav case MV_7042: 133183724Ssos ctlr->chipinit = ata_marvell_edma_chipinit; 134183724Ssos break; 135183724Ssos case MV_61XX: 136199259Smav ctlr->chipinit = ata_marvell_chipinit; 137183724Ssos break; 138203030Smav case MV_91XX: 139203030Smav ctlr->chipinit = ata_marvell_dummy_chipinit; 140203030Smav break; 141183724Ssos } 142194893Smav return (BUS_PROBE_DEFAULT); 143183724Ssos} 144183724Ssos 145183724Ssosstatic int 146199259Smavata_marvell_chipinit(device_t dev) 147183724Ssos{ 148199322Smav struct ata_pci_controller *ctlr = device_get_softc(dev); 149199322Smav device_t child; 150183724Ssos 151199322Smav if (ata_setup_interrupt(dev, ata_generic_intr)) 152199322Smav return ENXIO; 153199322Smav /* Create AHCI subdevice if AHCI part present. */ 154199322Smav if (ctlr->chip->cfg1) { 155199322Smav child = device_add_child(dev, NULL, -1); 156199322Smav if (child != NULL) { 157199322Smav device_set_ivars(child, (void *)(intptr_t)-1); 158199322Smav bus_generic_attach(dev); 159199322Smav } 160199322Smav } 161199322Smav ctlr->ch_attach = ata_marvell_ch_attach; 162199322Smav ctlr->ch_detach = ata_pci_ch_detach; 163199322Smav ctlr->reset = ata_generic_reset; 164199322Smav ctlr->setmode = ata_marvell_setmode; 165199322Smav ctlr->channels = 1; 166199322Smav return (0); 167183724Ssos} 168183724Ssos 169183724Ssosstatic int 170199259Smavata_marvell_ch_attach(device_t dev) 171183724Ssos{ 172199322Smav struct ata_channel *ch = device_get_softc(dev); 173199322Smav int error; 174183724Ssos 175199259Smav error = ata_pci_ch_attach(dev); 176199259Smav /* dont use 32 bit PIO transfers */ 177196970Sphk ch->flags |= ATA_USE_16BIT; 178200171Smav ch->flags |= ATA_CHECKS_CABLE; 179199322Smav return (error); 180199259Smav} 181183724Ssos 182200171Smavstatic int 183200171Smavata_marvell_setmode(device_t dev, int target, int mode) 184199259Smav{ 185200171Smav struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 186200171Smav struct ata_channel *ch = device_get_softc(dev); 187183724Ssos 188200171Smav mode = min(mode, ctlr->chip->max_dma); 189200171Smav /* Check for 80pin cable present. */ 190209872Smav if (ata_dma_check_80pin && mode > ATA_UDMA2 && 191209872Smav ATA_IDX_INB(ch, ATA_BMDEVSPEC_0) & 0x01) { 192200171Smav ata_print_cable(dev, "controller"); 193200171Smav mode = ATA_UDMA2; 194200171Smav } 195200171Smav /* Nothing to do to setup mode, the controller snoop SET_FEATURE cmd. */ 196200171Smav return (mode); 197183724Ssos} 198183724Ssos 199203030Smavstatic int 200203030Smavata_marvell_dummy_chipinit(device_t dev) 201203030Smav{ 202203030Smav struct ata_pci_controller *ctlr = device_get_softc(dev); 203203030Smav 204203030Smav ctlr->channels = 0; 205203030Smav return (0); 206203030Smav} 207203030Smav 208183724Ssosint 209183724Ssosata_marvell_edma_chipinit(device_t dev) 210183724Ssos{ 211183724Ssos struct ata_pci_controller *ctlr = device_get_softc(dev); 212183724Ssos 213183724Ssos if (ata_setup_interrupt(dev, ata_generic_intr)) 214183724Ssos return ENXIO; 215183724Ssos 216183724Ssos ctlr->r_type1 = SYS_RES_MEMORY; 217183724Ssos ctlr->r_rid1 = PCIR_BAR(0); 218183724Ssos if (!(ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1, 219183724Ssos &ctlr->r_rid1, RF_ACTIVE))) 220183724Ssos return ENXIO; 221183724Ssos 222183724Ssos /* mask all host controller interrupts */ 223183724Ssos ATA_OUTL(ctlr->r_res1, 0x01d64, 0x00000000); 224183724Ssos 225183724Ssos /* mask all PCI interrupts */ 226183724Ssos ATA_OUTL(ctlr->r_res1, 0x01d5c, 0x00000000); 227183724Ssos 228188765Smav ctlr->ch_attach = ata_marvell_edma_ch_attach; 229188769Smav ctlr->ch_detach = ata_marvell_edma_ch_detach; 230183724Ssos ctlr->reset = ata_marvell_edma_reset; 231183724Ssos ctlr->setmode = ata_sata_setmode; 232200171Smav ctlr->getrev = ata_sata_getrev; 233183724Ssos ctlr->channels = ctlr->chip->cfg1; 234183724Ssos 235183724Ssos /* clear host controller interrupts */ 236183724Ssos ATA_OUTL(ctlr->r_res1, 0x20014, 0x00000000); 237183724Ssos if (ctlr->chip->cfg1 > 4) 238183724Ssos ATA_OUTL(ctlr->r_res1, 0x30014, 0x00000000); 239183724Ssos 240183724Ssos /* clear PCI interrupts */ 241183724Ssos ATA_OUTL(ctlr->r_res1, 0x01d58, 0x00000000); 242183724Ssos 243183724Ssos /* unmask PCI interrupts we want */ 244183724Ssos ATA_OUTL(ctlr->r_res1, 0x01d5c, 0x007fffff); 245183724Ssos 246183724Ssos /* unmask host controller interrupts we want */ 247183724Ssos ATA_OUTL(ctlr->r_res1, 0x01d64, 0x000000ff/*HC0*/ | 0x0001fe00/*HC1*/ | 248183724Ssos /*(1<<19) | (1<<20) | (1<<21) |*/(1<<22) | (1<<24) | (0x7f << 25)); 249183724Ssos 250183724Ssos return 0; 251183724Ssos} 252183724Ssos 253183724Ssosstatic int 254188765Smavata_marvell_edma_ch_attach(device_t dev) 255183724Ssos{ 256183724Ssos struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 257183724Ssos struct ata_channel *ch = device_get_softc(dev); 258195659Smav u_int64_t work; 259183724Ssos int i; 260183724Ssos 261188765Smav ata_marvell_edma_dmainit(dev); 262195659Smav work = ch->dma.work_bus; 263183724Ssos /* clear work area */ 264183724Ssos bzero(ch->dma.work, 1024+256); 265197402Smarius bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, 266197402Smarius BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 267183724Ssos 268183724Ssos /* set legacy ATA resources */ 269183724Ssos for (i = ATA_DATA; i <= ATA_COMMAND; i++) { 270183724Ssos ch->r_io[i].res = ctlr->r_res1; 271183724Ssos ch->r_io[i].offset = 0x02100 + (i << 2) + ATA_MV_EDMA_BASE(ch); 272183724Ssos } 273183724Ssos ch->r_io[ATA_CONTROL].res = ctlr->r_res1; 274183724Ssos ch->r_io[ATA_CONTROL].offset = 0x02120 + ATA_MV_EDMA_BASE(ch); 275183724Ssos ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res1; 276183724Ssos ata_default_registers(dev); 277183724Ssos 278183724Ssos /* set SATA resources */ 279183724Ssos switch (ctlr->chip->cfg2) { 280183724Ssos case MV_50XX: 281183724Ssos ch->r_io[ATA_SSTATUS].res = ctlr->r_res1; 282183724Ssos ch->r_io[ATA_SSTATUS].offset = 0x00100 + ATA_MV_HOST_BASE(ch); 283183724Ssos ch->r_io[ATA_SERROR].res = ctlr->r_res1; 284183724Ssos ch->r_io[ATA_SERROR].offset = 0x00104 + ATA_MV_HOST_BASE(ch); 285183724Ssos ch->r_io[ATA_SCONTROL].res = ctlr->r_res1; 286183724Ssos ch->r_io[ATA_SCONTROL].offset = 0x00108 + ATA_MV_HOST_BASE(ch); 287183724Ssos break; 288183724Ssos case MV_60XX: 289198700Smav case MV_6042: 290198700Smav case MV_7042: 291183724Ssos ch->r_io[ATA_SSTATUS].res = ctlr->r_res1; 292183724Ssos ch->r_io[ATA_SSTATUS].offset = 0x02300 + ATA_MV_EDMA_BASE(ch); 293183724Ssos ch->r_io[ATA_SERROR].res = ctlr->r_res1; 294183724Ssos ch->r_io[ATA_SERROR].offset = 0x02304 + ATA_MV_EDMA_BASE(ch); 295183724Ssos ch->r_io[ATA_SCONTROL].res = ctlr->r_res1; 296183724Ssos ch->r_io[ATA_SCONTROL].offset = 0x02308 + ATA_MV_EDMA_BASE(ch); 297183724Ssos ch->r_io[ATA_SACTIVE].res = ctlr->r_res1; 298183724Ssos ch->r_io[ATA_SACTIVE].offset = 0x02350 + ATA_MV_EDMA_BASE(ch); 299183724Ssos break; 300183724Ssos } 301183724Ssos 302183724Ssos ch->flags |= ATA_NO_SLAVE; 303183724Ssos ch->flags |= ATA_USE_16BIT; /* XXX SOS needed ? */ 304200171Smav ch->flags |= ATA_SATA; 305183724Ssos ata_generic_hw(dev); 306183724Ssos ch->hw.begin_transaction = ata_marvell_edma_begin_transaction; 307183724Ssos ch->hw.end_transaction = ata_marvell_edma_end_transaction; 308183724Ssos ch->hw.status = ata_marvell_edma_status; 309183724Ssos 310183724Ssos /* disable the EDMA machinery */ 311183724Ssos ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000002); 312183724Ssos DELAY(100000); /* SOS should poll for disabled */ 313183724Ssos 314183724Ssos /* set configuration to non-queued 128b read transfers stop on error */ 315183724Ssos ATA_OUTL(ctlr->r_res1, 0x02000 + ATA_MV_EDMA_BASE(ch), (1<<11) | (1<<13)); 316183724Ssos 317183724Ssos /* request queue base high */ 318183724Ssos ATA_OUTL(ctlr->r_res1, 0x02010 + ATA_MV_EDMA_BASE(ch), work >> 32); 319183724Ssos 320183724Ssos /* request queue in ptr */ 321183724Ssos ATA_OUTL(ctlr->r_res1, 0x02014 + ATA_MV_EDMA_BASE(ch), work & 0xffffffff); 322183724Ssos 323183724Ssos /* request queue out ptr */ 324183724Ssos ATA_OUTL(ctlr->r_res1, 0x02018 + ATA_MV_EDMA_BASE(ch), 0x0); 325183724Ssos 326183724Ssos /* response queue base high */ 327183724Ssos work += 1024; 328183724Ssos ATA_OUTL(ctlr->r_res1, 0x0201c + ATA_MV_EDMA_BASE(ch), work >> 32); 329183724Ssos 330183724Ssos /* response queue in ptr */ 331183724Ssos ATA_OUTL(ctlr->r_res1, 0x02020 + ATA_MV_EDMA_BASE(ch), 0x0); 332183724Ssos 333183724Ssos /* response queue out ptr */ 334183724Ssos ATA_OUTL(ctlr->r_res1, 0x02024 + ATA_MV_EDMA_BASE(ch), work & 0xffffffff); 335183724Ssos 336183724Ssos /* clear SATA error register */ 337183724Ssos ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR)); 338183724Ssos 339183724Ssos /* clear any outstanding error interrupts */ 340183724Ssos ATA_OUTL(ctlr->r_res1, 0x02008 + ATA_MV_EDMA_BASE(ch), 0x0); 341183724Ssos 342183724Ssos /* unmask all error interrupts */ 343183724Ssos ATA_OUTL(ctlr->r_res1, 0x0200c + ATA_MV_EDMA_BASE(ch), ~0x0); 344183724Ssos 345183724Ssos /* enable EDMA machinery */ 346183724Ssos ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000001); 347183724Ssos return 0; 348183724Ssos} 349183724Ssos 350183724Ssosstatic int 351188769Smavata_marvell_edma_ch_detach(device_t dev) 352188769Smav{ 353197402Smarius struct ata_channel *ch = device_get_softc(dev); 354188769Smav 355197402Smarius if (ch->dma.work_tag && ch->dma.work_map) 356197402Smarius bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, 357197402Smarius BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 358188769Smav ata_dmafini(dev); 359188769Smav return (0); 360188769Smav} 361188769Smav 362188769Smavstatic int 363183724Ssosata_marvell_edma_status(device_t dev) 364183724Ssos{ 365183724Ssos struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 366183724Ssos struct ata_channel *ch = device_get_softc(dev); 367183724Ssos u_int32_t cause = ATA_INL(ctlr->r_res1, 0x01d60); 368183724Ssos int shift = (ch->unit << 1) + (ch->unit > 3); 369183724Ssos 370183724Ssos if (cause & (1 << shift)) { 371183724Ssos 372183724Ssos /* clear interrupt(s) */ 373183724Ssos ATA_OUTL(ctlr->r_res1, 0x02008 + ATA_MV_EDMA_BASE(ch), 0x0); 374183724Ssos 375183724Ssos /* do we have any PHY events ? */ 376214016Smav ata_sata_phy_check_events(dev, -1); 377183724Ssos } 378183724Ssos 379183724Ssos /* do we have any device action ? */ 380183724Ssos return (cause & (2 << shift)); 381183724Ssos} 382183724Ssos 383183724Ssos/* must be called with ATA channel locked and state_mtx held */ 384183724Ssosstatic int 385183724Ssosata_marvell_edma_begin_transaction(struct ata_request *request) 386183724Ssos{ 387198717Smav struct ata_pci_controller *ctlr=device_get_softc(device_get_parent(request->parent)); 388183724Ssos struct ata_channel *ch = device_get_softc(request->parent); 389183724Ssos u_int32_t req_in; 390183724Ssos u_int8_t *bytep; 391183724Ssos int i; 392183724Ssos int error, slot; 393183724Ssos 394183724Ssos /* only DMA R/W goes through the EMDA machine */ 395183724Ssos if (request->u.ata.command != ATA_READ_DMA && 396198717Smav request->u.ata.command != ATA_WRITE_DMA && 397198717Smav request->u.ata.command != ATA_READ_DMA48 && 398198717Smav request->u.ata.command != ATA_WRITE_DMA48) { 399183724Ssos 400183724Ssos /* disable the EDMA machinery */ 401183724Ssos if (ATA_INL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch)) & 0x00000001) 402183724Ssos ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000002); 403183724Ssos return ata_begin_transaction(request); 404183724Ssos } 405183724Ssos 406183724Ssos /* check sanity, setup SG list and DMA engine */ 407183724Ssos if ((error = ch->dma.load(request, NULL, NULL))) { 408198717Smav device_printf(request->parent, "setting up DMA failed\n"); 409183724Ssos request->result = error; 410183724Ssos return ATA_OP_FINISHED; 411183724Ssos } 412183724Ssos 413183724Ssos /* get next free request queue slot */ 414183724Ssos req_in = ATA_INL(ctlr->r_res1, 0x02014 + ATA_MV_EDMA_BASE(ch)); 415183724Ssos slot = (((req_in & ~0xfffffc00) >> 5) + 0) & 0x1f; 416183724Ssos bytep = (u_int8_t *)(ch->dma.work); 417183724Ssos bytep += (slot << 5); 418183724Ssos 419183724Ssos /* fill in this request */ 420197402Smarius le32enc(bytep + 0 * sizeof(u_int32_t), 421197402Smarius request->dma->sg_bus & 0xffffffff); 422197402Smarius le32enc(bytep + 1 * sizeof(u_int32_t), 423197402Smarius (u_int64_t)request->dma->sg_bus >> 32); 424198700Smav if (ctlr->chip->cfg2 != MV_6042 && ctlr->chip->cfg2 != MV_7042) { 425198700Smav le16enc(bytep + 4 * sizeof(u_int16_t), 426198700Smav (request->flags & ATA_R_READ ? 0x01 : 0x00) | (request->tag << 1)); 427183724Ssos 428198700Smav i = 10; 429198700Smav bytep[i++] = (request->u.ata.count >> 8) & 0xff; 430198700Smav bytep[i++] = 0x10 | ATA_COUNT; 431198700Smav bytep[i++] = request->u.ata.count & 0xff; 432198700Smav bytep[i++] = 0x10 | ATA_COUNT; 433183724Ssos 434198700Smav bytep[i++] = (request->u.ata.lba >> 24) & 0xff; 435198700Smav bytep[i++] = 0x10 | ATA_SECTOR; 436198700Smav bytep[i++] = request->u.ata.lba & 0xff; 437198700Smav bytep[i++] = 0x10 | ATA_SECTOR; 438183724Ssos 439198700Smav bytep[i++] = (request->u.ata.lba >> 32) & 0xff; 440198700Smav bytep[i++] = 0x10 | ATA_CYL_LSB; 441198700Smav bytep[i++] = (request->u.ata.lba >> 8) & 0xff; 442198700Smav bytep[i++] = 0x10 | ATA_CYL_LSB; 443183724Ssos 444198700Smav bytep[i++] = (request->u.ata.lba >> 40) & 0xff; 445198700Smav bytep[i++] = 0x10 | ATA_CYL_MSB; 446198700Smav bytep[i++] = (request->u.ata.lba >> 16) & 0xff; 447198700Smav bytep[i++] = 0x10 | ATA_CYL_MSB; 448183724Ssos 449198700Smav bytep[i++] = ATA_D_LBA | ATA_D_IBM | ((request->u.ata.lba >> 24) & 0xf); 450198700Smav bytep[i++] = 0x10 | ATA_DRIVE; 451183724Ssos 452198700Smav bytep[i++] = request->u.ata.command; 453198700Smav bytep[i++] = 0x90 | ATA_COMMAND; 454198700Smav } else { 455198700Smav le32enc(bytep + 2 * sizeof(u_int32_t), 456198700Smav (request->flags & ATA_R_READ ? 0x01 : 0x00) | (request->tag << 1)); 457183724Ssos 458198700Smav i = 16; 459198700Smav bytep[i++] = 0; 460198700Smav bytep[i++] = 0; 461198700Smav bytep[i++] = request->u.ata.command; 462198700Smav bytep[i++] = request->u.ata.feature & 0xff; 463198700Smav 464198700Smav bytep[i++] = request->u.ata.lba & 0xff; 465198700Smav bytep[i++] = (request->u.ata.lba >> 8) & 0xff; 466198700Smav bytep[i++] = (request->u.ata.lba >> 16) & 0xff; 467198700Smav bytep[i++] = ATA_D_LBA | ATA_D_IBM | ((request->u.ata.lba >> 24) & 0x0f); 468198700Smav 469198700Smav bytep[i++] = (request->u.ata.lba >> 24) & 0xff; 470198700Smav bytep[i++] = (request->u.ata.lba >> 32) & 0xff; 471198700Smav bytep[i++] = (request->u.ata.lba >> 40) & 0xff; 472198700Smav bytep[i++] = (request->u.ata.feature >> 8) & 0xff; 473198700Smav 474198700Smav bytep[i++] = request->u.ata.count & 0xff; 475198700Smav bytep[i++] = (request->u.ata.count >> 8) & 0xff; 476198700Smav bytep[i++] = 0; 477198700Smav bytep[i++] = 0; 478198700Smav } 479198700Smav 480197402Smarius bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, 481197402Smarius BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 482197402Smarius 483183724Ssos /* enable EDMA machinery if needed */ 484183724Ssos if (!(ATA_INL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch)) & 0x00000001)) { 485183724Ssos ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000001); 486183724Ssos while (!(ATA_INL(ctlr->r_res1, 487183724Ssos 0x02028 + ATA_MV_EDMA_BASE(ch)) & 0x00000001)) 488183724Ssos DELAY(10); 489183724Ssos } 490183724Ssos 491183724Ssos /* tell EDMA it has a new request */ 492183724Ssos slot = (((req_in & ~0xfffffc00) >> 5) + 1) & 0x1f; 493183724Ssos req_in &= 0xfffffc00; 494183724Ssos req_in += (slot << 5); 495183724Ssos ATA_OUTL(ctlr->r_res1, 0x02014 + ATA_MV_EDMA_BASE(ch), req_in); 496183724Ssos 497183724Ssos return ATA_OP_CONTINUES; 498183724Ssos} 499183724Ssos 500183724Ssos/* must be called with ATA channel locked and state_mtx held */ 501183724Ssosstatic int 502183724Ssosata_marvell_edma_end_transaction(struct ata_request *request) 503183724Ssos{ 504198717Smav struct ata_pci_controller *ctlr=device_get_softc(device_get_parent(request->parent)); 505183724Ssos struct ata_channel *ch = device_get_softc(request->parent); 506183724Ssos int offset = (ch->unit > 3 ? 0x30014 : 0x20014); 507183724Ssos u_int32_t icr = ATA_INL(ctlr->r_res1, offset); 508183724Ssos int res; 509183724Ssos 510183724Ssos /* EDMA interrupt */ 511183724Ssos if ((icr & (0x0001 << (ch->unit & 3)))) { 512183724Ssos struct ata_marvell_response *response; 513183724Ssos u_int32_t rsp_in, rsp_out; 514183724Ssos int slot; 515183724Ssos 516183724Ssos /* stop timeout */ 517183724Ssos callout_stop(&request->callout); 518183724Ssos 519183724Ssos /* get response ptr's */ 520183724Ssos rsp_in = ATA_INL(ctlr->r_res1, 0x02020 + ATA_MV_EDMA_BASE(ch)); 521183724Ssos rsp_out = ATA_INL(ctlr->r_res1, 0x02024 + ATA_MV_EDMA_BASE(ch)); 522183724Ssos slot = (((rsp_in & ~0xffffff00) >> 3)) & 0x1f; 523183724Ssos rsp_out &= 0xffffff00; 524183724Ssos rsp_out += (slot << 3); 525197402Smarius bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, 526197402Smarius BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 527183724Ssos response = (struct ata_marvell_response *) 528183724Ssos (ch->dma.work + 1024 + (slot << 3)); 529183724Ssos 530183724Ssos /* record status for this request */ 531183724Ssos request->status = response->dev_status; 532183724Ssos request->error = 0; 533183724Ssos 534183724Ssos /* ack response */ 535183724Ssos ATA_OUTL(ctlr->r_res1, 0x02024 + ATA_MV_EDMA_BASE(ch), rsp_out); 536183724Ssos 537183724Ssos /* update progress */ 538183724Ssos if (!(request->status & ATA_S_ERROR) && 539183724Ssos !(request->flags & ATA_R_TIMEOUT)) 540183724Ssos request->donecount = request->bytecount; 541183724Ssos 542183724Ssos /* unload SG list */ 543183724Ssos ch->dma.unload(request); 544183724Ssos 545183724Ssos res = ATA_OP_FINISHED; 546183724Ssos } 547183724Ssos 548183724Ssos /* legacy ATA interrupt */ 549183724Ssos else { 550183724Ssos res = ata_end_transaction(request); 551183724Ssos } 552183724Ssos 553183724Ssos /* ack interrupt */ 554183724Ssos ATA_OUTL(ctlr->r_res1, offset, ~(icr & (0x0101 << (ch->unit & 3)))); 555183724Ssos return res; 556183724Ssos} 557183724Ssos 558183724Ssosstatic void 559183724Ssosata_marvell_edma_reset(device_t dev) 560183724Ssos{ 561183724Ssos struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 562183724Ssos struct ata_channel *ch = device_get_softc(dev); 563183724Ssos 564183724Ssos /* disable the EDMA machinery */ 565183724Ssos ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000002); 566183724Ssos while ((ATA_INL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch)) & 0x00000001)) 567183724Ssos DELAY(10); 568183724Ssos 569183724Ssos /* clear SATA error register */ 570183724Ssos ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR)); 571183724Ssos 572183724Ssos /* clear any outstanding error interrupts */ 573183724Ssos ATA_OUTL(ctlr->r_res1, 0x02008 + ATA_MV_EDMA_BASE(ch), 0x0); 574183724Ssos 575183724Ssos /* unmask all error interrupts */ 576183724Ssos ATA_OUTL(ctlr->r_res1, 0x0200c + ATA_MV_EDMA_BASE(ch), ~0x0); 577183724Ssos 578183724Ssos /* enable channel and test for devices */ 579190581Smav if (ata_sata_phy_reset(dev, -1, 1)) 580183724Ssos ata_generic_reset(dev); 581209884Smav else 582209884Smav ch->devices = 0; 583183724Ssos 584183724Ssos /* enable EDMA machinery */ 585183724Ssos ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000001); 586183724Ssos} 587183724Ssos 588183724Ssosstatic void 589183724Ssosata_marvell_edma_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, 590183724Ssos int error) 591183724Ssos{ 592183724Ssos struct ata_dmasetprd_args *args = xsc; 593183724Ssos struct ata_marvell_dma_prdentry *prd = args->dmatab; 594183724Ssos int i; 595183724Ssos 596183724Ssos if ((args->error = error)) 597183724Ssos return; 598183724Ssos 599183724Ssos for (i = 0; i < nsegs; i++) { 600183724Ssos prd[i].addrlo = htole32(segs[i].ds_addr); 601183724Ssos prd[i].count = htole32(segs[i].ds_len); 602183724Ssos prd[i].addrhi = htole32((u_int64_t)segs[i].ds_addr >> 32); 603197402Smarius prd[i].reserved = 0; 604183724Ssos } 605183724Ssos prd[i - 1].count |= htole32(ATA_DMA_EOT); 606183724Ssos KASSERT(nsegs <= ATA_DMA_ENTRIES, ("too many DMA segment entries\n")); 607183724Ssos args->nsegs = nsegs; 608183724Ssos} 609183724Ssos 610183724Ssosstatic void 611183724Ssosata_marvell_edma_dmainit(device_t dev) 612183724Ssos{ 613183724Ssos struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 614183724Ssos struct ata_channel *ch = device_get_softc(dev); 615183724Ssos 616183724Ssos /* note start and stop are not used here */ 617183724Ssos ch->dma.setprd = ata_marvell_edma_dmasetprd; 618183724Ssos 619183724Ssos /* if 64bit support present adjust max address used */ 620183724Ssos if (ATA_INL(ctlr->r_res1, 0x00d00) & 0x00000004) 621183724Ssos ch->dma.max_address = BUS_SPACE_MAXADDR; 622183724Ssos 623183724Ssos /* chip does not reliably do 64K DMA transfers */ 624198700Smav if (ctlr->chip->cfg2 == MV_50XX || ctlr->chip->cfg2 == MV_60XX) 625198718Smav ch->dma.max_iosize = 64 * DEV_BSIZE; 626216013Smarius ata_dmainit(dev); 627183724Ssos} 628183724Ssos 629183724SsosATA_DECLARE_DRIVER(ata_marvell); 630