ata-marvell.c revision 198718
1210008Srdivacky/*- 2210008Srdivacky * Copyright (c) 1998 - 2008 S�ren Schmidt <sos@FreeBSD.org> 3210008Srdivacky * All rights reserved. 4210008Srdivacky * 5210008Srdivacky * Redistribution and use in source and binary forms, with or without 6210008Srdivacky * modification, are permitted provided that the following conditions 7210008Srdivacky * are met: 8210008Srdivacky * 1. Redistributions of source code must retain the above copyright 9210008Srdivacky * notice, this list of conditions and the following disclaimer, 10210008Srdivacky * without modification, immediately at the beginning of the file. 11210008Srdivacky * 2. Redistributions in binary form must reproduce the above copyright 12249423Sdim * notice, this list of conditions and the following disclaimer in the 13210008Srdivacky * documentation and/or other materials provided with the distribution. 14210008Srdivacky * 15210008Srdivacky * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16226633Sdim * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17210008Srdivacky * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18210008Srdivacky * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19210008Srdivacky * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20210008Srdivacky * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21249423Sdim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22249423Sdim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23224145Sdim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24249423Sdim * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25210008Srdivacky */ 26210008Srdivacky 27210008Srdivacky#include <sys/cdefs.h> 28226633Sdim__FBSDID("$FreeBSD: head/sys/dev/ata/chipsets/ata-marvell.c 198718 2009-10-31 14:19:50Z mav $"); 29210008Srdivacky 30210008Srdivacky#include "opt_ata.h" 31226633Sdim#include <sys/param.h> 32210008Srdivacky#include <sys/module.h> 33210008Srdivacky#include <sys/systm.h> 34226633Sdim#include <sys/kernel.h> 35226633Sdim#include <sys/ata.h> 36249423Sdim#include <sys/bus.h> 37249423Sdim#include <sys/endian.h> 38226633Sdim#include <sys/malloc.h> 39210008Srdivacky#include <sys/lock.h> 40210008Srdivacky#include <sys/mutex.h> 41210008Srdivacky#include <sys/sema.h> 42210008Srdivacky#include <sys/taskqueue.h> 43210008Srdivacky#include <vm/uma.h> 44210008Srdivacky#include <machine/stdarg.h> 45226633Sdim#include <machine/resource.h> 46210008Srdivacky#include <machine/bus.h> 47234353Sdim#include <sys/rman.h> 48224145Sdim#include <dev/pci/pcivar.h> 49210008Srdivacky#include <dev/pci/pcireg.h> 50210008Srdivacky#include <dev/ata/ata-all.h> 51210008Srdivacky#include <dev/ata/ata-pci.h> 52210008Srdivacky#include <ata_if.h> 53218893Sdim 54210008Srdivacky/* local prototypes */ 55210008Srdivackystatic int ata_marvell_pata_chipinit(device_t dev); 56210008Srdivackystatic int ata_marvell_pata_ch_attach(device_t dev); 57210008Srdivackystatic void ata_marvell_pata_setmode(device_t dev, int mode); 58243830Sdimstatic int ata_marvell_edma_ch_attach(device_t dev); 59210008Srdivackystatic int ata_marvell_edma_ch_detach(device_t dev); 60218893Sdimstatic int ata_marvell_edma_status(device_t dev); 61243830Sdimstatic int ata_marvell_edma_begin_transaction(struct ata_request *request); 62249423Sdimstatic int ata_marvell_edma_end_transaction(struct ata_request *request); 63249423Sdimstatic void ata_marvell_edma_reset(device_t dev); 64210008Srdivackystatic void ata_marvell_edma_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error); 65210008Srdivackystatic void ata_marvell_edma_dmainit(device_t dev); 66210008Srdivacky 67210008Srdivacky/* misc defines */ 68243830Sdim#define MV_50XX 50 69210008Srdivacky#define MV_60XX 60 70210008Srdivacky#define MV_6042 62 71243830Sdim#define MV_7042 72 72249423Sdim#define MV_61XX 61 73249423Sdim 74210008Srdivacky 75210008Srdivacky/* 76210008Srdivacky * Marvell chipset support functions 77210008Srdivacky */ 78243830Sdim#define ATA_MV_HOST_BASE(ch) \ 79210008Srdivacky ((ch->unit & 3) * 0x0100) + (ch->unit > 3 ? 0x30000 : 0x20000) 80210008Srdivacky#define ATA_MV_EDMA_BASE(ch) \ 81243830Sdim ((ch->unit & 3) * 0x2000) + (ch->unit > 3 ? 0x30000 : 0x20000) 82249423Sdim 83249423Sdimstruct ata_marvell_response { 84210008Srdivacky u_int16_t tag; 85210008Srdivacky u_int8_t edma_status; 86210008Srdivacky u_int8_t dev_status; 87210008Srdivacky u_int32_t timestamp; 88210008Srdivacky}; 89243830Sdim 90243830Sdimstruct ata_marvell_dma_prdentry { 91243830Sdim u_int32_t addrlo; 92243830Sdim u_int32_t count; 93243830Sdim u_int32_t addrhi; 94243830Sdim u_int32_t reserved; 95243830Sdim}; 96243830Sdim 97243830Sdimstatic int 98243830Sdimata_marvell_probe(device_t dev) 99243830Sdim{ 100243830Sdim struct ata_pci_controller *ctlr = device_get_softc(dev); 101210008Srdivacky static struct ata_chip_id ids[] = 102210008Srdivacky {{ ATA_M88SX5040, 0, 4, MV_50XX, ATA_SA150, "88SX5040" }, 103210008Srdivacky { ATA_M88SX5041, 0, 4, MV_50XX, ATA_SA150, "88SX5041" }, 104243830Sdim { ATA_M88SX5080, 0, 8, MV_50XX, ATA_SA150, "88SX5080" }, 105243830Sdim { ATA_M88SX5081, 0, 8, MV_50XX, ATA_SA150, "88SX5081" }, 106210008Srdivacky { ATA_M88SX6041, 0, 4, MV_60XX, ATA_SA300, "88SX6041" }, 107210008Srdivacky { ATA_M88SX6042, 0, 4, MV_6042, ATA_SA300, "88SX6042" }, 108226633Sdim { ATA_M88SX6081, 0, 8, MV_60XX, ATA_SA300, "88SX6081" }, 109234353Sdim { ATA_M88SX7042, 0, 4, MV_7042, ATA_SA300, "88SX7042" }, 110234353Sdim { ATA_M88SX6101, 0, 1, MV_61XX, ATA_UDMA6, "88SX6101" }, 111224145Sdim { ATA_M88SX6121, 0, 1, MV_61XX, ATA_UDMA6, "88SX6121" }, 112210008Srdivacky { ATA_M88SX6145, 0, 2, MV_61XX, ATA_UDMA6, "88SX6145" }, 113224145Sdim { 0, 0, 0, 0, 0, 0}}; 114210008Srdivacky 115210008Srdivacky if (pci_get_vendor(dev) != ATA_MARVELL_ID) 116210008Srdivacky return ENXIO; 117210008Srdivacky 118210008Srdivacky if (!(ctlr->chip = ata_match_chip(dev, ids))) 119210008Srdivacky return ENXIO; 120210008Srdivacky 121210008Srdivacky ata_set_desc(dev); 122210008Srdivacky 123210008Srdivacky switch (ctlr->chip->cfg2) { 124210008Srdivacky case MV_50XX: 125210008Srdivacky case MV_60XX: 126249423Sdim case MV_6042: 127249423Sdim case MV_7042: 128249423Sdim ctlr->chipinit = ata_marvell_edma_chipinit; 129249423Sdim break; 130249423Sdim case MV_61XX: 131249423Sdim ctlr->chipinit = ata_marvell_pata_chipinit; 132249423Sdim break; 133249423Sdim } 134249423Sdim return (BUS_PROBE_DEFAULT); 135249423Sdim} 136249423Sdim 137249423Sdimstatic int 138249423Sdimata_marvell_pata_chipinit(device_t dev) 139249423Sdim{ 140210008Srdivacky struct ata_pci_controller *ctlr = device_get_softc(dev); 141210008Srdivacky 142234353Sdim if (ata_setup_interrupt(dev, ata_generic_intr)) 143234353Sdim return ENXIO; 144234353Sdim 145234353Sdim ctlr->ch_attach = ata_marvell_pata_ch_attach; 146234353Sdim ctlr->ch_detach = ata_pci_ch_detach; 147224145Sdim ctlr->setmode = ata_marvell_pata_setmode; 148224145Sdim ctlr->channels = ctlr->chip->cfg1; 149224145Sdim return 0; 150224145Sdim} 151224145Sdim 152224145Sdimstatic int 153224145Sdimata_marvell_pata_ch_attach(device_t dev) 154224145Sdim{ 155224145Sdim struct ata_channel *ch = device_get_softc(dev); 156224145Sdim 157239462Sdim /* setup the usual register normal pci style */ 158239462Sdim if (ata_pci_ch_attach(dev)) 159249423Sdim return ENXIO; 160239462Sdim 161239462Sdim /* dont use 32 bit PIO transfers */ 162249423Sdim ch->flags |= ATA_USE_16BIT; 163249423Sdim 164249423Sdim return 0; 165249423Sdim} 166249423Sdim 167249423Sdimstatic void 168249423Sdimata_marvell_pata_setmode(device_t dev, int mode) 169249423Sdim{ 170249423Sdim device_t gparent = GRANDPARENT(dev); 171249423Sdim struct ata_pci_controller *ctlr = device_get_softc(gparent); 172249423Sdim struct ata_device *atadev = device_get_softc(dev); 173249423Sdim 174249423Sdim mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma); 175249423Sdim mode = ata_check_80pin(dev, mode); 176249423Sdim if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode)) 177249423Sdim atadev->mode = mode; 178234353Sdim} 179234353Sdim 180249423Sdimint 181249423Sdimata_marvell_edma_chipinit(device_t dev) 182249423Sdim{ 183249423Sdim struct ata_pci_controller *ctlr = device_get_softc(dev); 184249423Sdim 185249423Sdim if (ata_setup_interrupt(dev, ata_generic_intr)) 186249423Sdim return ENXIO; 187249423Sdim 188249423Sdim ctlr->r_type1 = SYS_RES_MEMORY; 189249423Sdim ctlr->r_rid1 = PCIR_BAR(0); 190249423Sdim if (!(ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1, 191249423Sdim &ctlr->r_rid1, RF_ACTIVE))) 192249423Sdim return ENXIO; 193249423Sdim 194249423Sdim /* mask all host controller interrupts */ 195249423Sdim ATA_OUTL(ctlr->r_res1, 0x01d64, 0x00000000); 196249423Sdim 197249423Sdim /* mask all PCI interrupts */ 198249423Sdim ATA_OUTL(ctlr->r_res1, 0x01d5c, 0x00000000); 199249423Sdim 200249423Sdim ctlr->ch_attach = ata_marvell_edma_ch_attach; 201234353Sdim ctlr->ch_detach = ata_marvell_edma_ch_detach; 202234353Sdim ctlr->reset = ata_marvell_edma_reset; 203249423Sdim ctlr->setmode = ata_sata_setmode; 204249423Sdim ctlr->channels = ctlr->chip->cfg1; 205249423Sdim 206249423Sdim /* clear host controller interrupts */ 207234353Sdim ATA_OUTL(ctlr->r_res1, 0x20014, 0x00000000); 208234353Sdim if (ctlr->chip->cfg1 > 4) 209243830Sdim ATA_OUTL(ctlr->r_res1, 0x30014, 0x00000000); 210210008Srdivacky 211243830Sdim /* clear PCI interrupts */ 212210008Srdivacky ATA_OUTL(ctlr->r_res1, 0x01d58, 0x00000000); 213210008Srdivacky 214210008Srdivacky /* unmask PCI interrupts we want */ 215210008Srdivacky ATA_OUTL(ctlr->r_res1, 0x01d5c, 0x007fffff); 216210008Srdivacky 217210008Srdivacky /* unmask host controller interrupts we want */ 218210008Srdivacky ATA_OUTL(ctlr->r_res1, 0x01d64, 0x000000ff/*HC0*/ | 0x0001fe00/*HC1*/ | 219249423Sdim /*(1<<19) | (1<<20) | (1<<21) |*/(1<<22) | (1<<24) | (0x7f << 25)); 220249423Sdim 221223017Sdim return 0; 222223017Sdim} 223221345Sdim 224223017Sdimstatic int 225223017Sdimata_marvell_edma_ch_attach(device_t dev) 226223017Sdim{ 227224145Sdim struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 228224145Sdim struct ata_channel *ch = device_get_softc(dev); 229224145Sdim u_int64_t work; 230224145Sdim int i; 231224145Sdim 232234353Sdim ata_marvell_edma_dmainit(dev); 233234353Sdim work = ch->dma.work_bus; 234224145Sdim /* clear work area */ 235224145Sdim bzero(ch->dma.work, 1024+256); 236224145Sdim bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, 237234353Sdim BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 238249423Sdim 239239462Sdim /* set legacy ATA resources */ 240239462Sdim for (i = ATA_DATA; i <= ATA_COMMAND; i++) { 241239462Sdim ch->r_io[i].res = ctlr->r_res1; 242239462Sdim ch->r_io[i].offset = 0x02100 + (i << 2) + ATA_MV_EDMA_BASE(ch); 243239462Sdim } 244239462Sdim ch->r_io[ATA_CONTROL].res = ctlr->r_res1; 245249423Sdim ch->r_io[ATA_CONTROL].offset = 0x02120 + ATA_MV_EDMA_BASE(ch); 246243830Sdim ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res1; 247249423Sdim ata_default_registers(dev); 248234353Sdim 249249423Sdim /* set SATA resources */ 250234353Sdim switch (ctlr->chip->cfg2) { 251234353Sdim case MV_50XX: 252249423Sdim ch->r_io[ATA_SSTATUS].res = ctlr->r_res1; 253234353Sdim ch->r_io[ATA_SSTATUS].offset = 0x00100 + ATA_MV_HOST_BASE(ch); 254249423Sdim ch->r_io[ATA_SERROR].res = ctlr->r_res1; 255249423Sdim ch->r_io[ATA_SERROR].offset = 0x00104 + ATA_MV_HOST_BASE(ch); 256249423Sdim ch->r_io[ATA_SCONTROL].res = ctlr->r_res1; 257249423Sdim ch->r_io[ATA_SCONTROL].offset = 0x00108 + ATA_MV_HOST_BASE(ch); 258249423Sdim break; 259249423Sdim case MV_60XX: 260249423Sdim case MV_6042: 261234353Sdim case MV_7042: 262234353Sdim ch->r_io[ATA_SSTATUS].res = ctlr->r_res1; 263234353Sdim ch->r_io[ATA_SSTATUS].offset = 0x02300 + ATA_MV_EDMA_BASE(ch); 264234353Sdim ch->r_io[ATA_SERROR].res = ctlr->r_res1; 265234353Sdim ch->r_io[ATA_SERROR].offset = 0x02304 + ATA_MV_EDMA_BASE(ch); 266223017Sdim ch->r_io[ATA_SCONTROL].res = ctlr->r_res1; 267223017Sdim ch->r_io[ATA_SCONTROL].offset = 0x02308 + ATA_MV_EDMA_BASE(ch); 268223017Sdim ch->r_io[ATA_SACTIVE].res = ctlr->r_res1; 269218893Sdim ch->r_io[ATA_SACTIVE].offset = 0x02350 + ATA_MV_EDMA_BASE(ch); 270223017Sdim break; 271223017Sdim } 272210008Srdivacky 273210008Srdivacky ch->flags |= ATA_NO_SLAVE; 274210008Srdivacky ch->flags |= ATA_USE_16BIT; /* XXX SOS needed ? */ 275210008Srdivacky ata_generic_hw(dev); 276210008Srdivacky ch->hw.begin_transaction = ata_marvell_edma_begin_transaction; 277223017Sdim ch->hw.end_transaction = ata_marvell_edma_end_transaction; 278210008Srdivacky ch->hw.status = ata_marvell_edma_status; 279223017Sdim 280221345Sdim /* disable the EDMA machinery */ 281210008Srdivacky ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000002); 282210008Srdivacky DELAY(100000); /* SOS should poll for disabled */ 283223017Sdim 284210008Srdivacky /* set configuration to non-queued 128b read transfers stop on error */ 285210008Srdivacky ATA_OUTL(ctlr->r_res1, 0x02000 + ATA_MV_EDMA_BASE(ch), (1<<11) | (1<<13)); 286210008Srdivacky 287223017Sdim /* request queue base high */ 288234353Sdim ATA_OUTL(ctlr->r_res1, 0x02010 + ATA_MV_EDMA_BASE(ch), work >> 32); 289234353Sdim 290234353Sdim /* request queue in ptr */ 291234353Sdim ATA_OUTL(ctlr->r_res1, 0x02014 + ATA_MV_EDMA_BASE(ch), work & 0xffffffff); 292234353Sdim 293210008Srdivacky /* request queue out ptr */ 294210008Srdivacky ATA_OUTL(ctlr->r_res1, 0x02018 + ATA_MV_EDMA_BASE(ch), 0x0); 295210008Srdivacky 296223017Sdim /* response queue base high */ 297243830Sdim work += 1024; 298223017Sdim ATA_OUTL(ctlr->r_res1, 0x0201c + ATA_MV_EDMA_BASE(ch), work >> 32); 299223017Sdim 300223017Sdim /* response queue in ptr */ 301223017Sdim ATA_OUTL(ctlr->r_res1, 0x02020 + ATA_MV_EDMA_BASE(ch), 0x0); 302223017Sdim 303243830Sdim /* response queue out ptr */ 304221345Sdim ATA_OUTL(ctlr->r_res1, 0x02024 + ATA_MV_EDMA_BASE(ch), work & 0xffffffff); 305249423Sdim 306249423Sdim /* clear SATA error register */ 307249423Sdim ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR)); 308249423Sdim 309249423Sdim /* clear any outstanding error interrupts */ 310249423Sdim ATA_OUTL(ctlr->r_res1, 0x02008 + ATA_MV_EDMA_BASE(ch), 0x0); 311249423Sdim 312249423Sdim /* unmask all error interrupts */ 313249423Sdim ATA_OUTL(ctlr->r_res1, 0x0200c + ATA_MV_EDMA_BASE(ch), ~0x0); 314249423Sdim 315249423Sdim /* enable EDMA machinery */ 316249423Sdim ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000001); 317249423Sdim return 0; 318243830Sdim} 319221345Sdim 320221345Sdimstatic int 321243830Sdimata_marvell_edma_ch_detach(device_t dev) 322223017Sdim{ 323210008Srdivacky struct ata_channel *ch = device_get_softc(dev); 324210008Srdivacky 325243830Sdim if (ch->dma.work_tag && ch->dma.work_map) 326210008Srdivacky bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, 327210008Srdivacky BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 328210008Srdivacky ata_dmafini(dev); 329210008Srdivacky return (0); 330210008Srdivacky} 331243830Sdim 332243830Sdimstatic int 333243830Sdimata_marvell_edma_status(device_t dev) 334210008Srdivacky{ 335210008Srdivacky struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 336210008Srdivacky struct ata_channel *ch = device_get_softc(dev); 337210008Srdivacky u_int32_t cause = ATA_INL(ctlr->r_res1, 0x01d60); 338210008Srdivacky int shift = (ch->unit << 1) + (ch->unit > 3); 339210008Srdivacky 340210008Srdivacky if (cause & (1 << shift)) { 341210008Srdivacky 342210008Srdivacky /* clear interrupt(s) */ 343210008Srdivacky ATA_OUTL(ctlr->r_res1, 0x02008 + ATA_MV_EDMA_BASE(ch), 0x0); 344210008Srdivacky 345210008Srdivacky /* do we have any PHY events ? */ 346226633Sdim ata_sata_phy_check_events(dev); 347210008Srdivacky } 348226633Sdim 349210008Srdivacky /* do we have any device action ? */ 350226633Sdim return (cause & (2 << shift)); 351210008Srdivacky} 352226633Sdim 353210008Srdivacky/* must be called with ATA channel locked and state_mtx held */ 354226633Sdimstatic int 355210008Srdivackyata_marvell_edma_begin_transaction(struct ata_request *request) 356210008Srdivacky{ 357226633Sdim struct ata_pci_controller *ctlr=device_get_softc(device_get_parent(request->parent)); 358210008Srdivacky struct ata_channel *ch = device_get_softc(request->parent); 359210008Srdivacky u_int32_t req_in; 360234353Sdim u_int8_t *bytep; 361210008Srdivacky int i; 362210008Srdivacky int error, slot; 363210008Srdivacky 364210008Srdivacky /* only DMA R/W goes through the EMDA machine */ 365210008Srdivacky if (request->u.ata.command != ATA_READ_DMA && 366210008Srdivacky request->u.ata.command != ATA_WRITE_DMA && 367210008Srdivacky request->u.ata.command != ATA_READ_DMA48 && 368210008Srdivacky request->u.ata.command != ATA_WRITE_DMA48) { 369210008Srdivacky 370210008Srdivacky /* disable the EDMA machinery */ 371210008Srdivacky if (ATA_INL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch)) & 0x00000001) 372221345Sdim ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000002); 373221345Sdim return ata_begin_transaction(request); 374226633Sdim } 375226633Sdim 376210008Srdivacky /* check sanity, setup SG list and DMA engine */ 377210008Srdivacky if ((error = ch->dma.load(request, NULL, NULL))) { 378234353Sdim device_printf(request->parent, "setting up DMA failed\n"); 379210008Srdivacky request->result = error; 380210008Srdivacky return ATA_OP_FINISHED; 381224145Sdim } 382210008Srdivacky 383210008Srdivacky /* get next free request queue slot */ 384210008Srdivacky req_in = ATA_INL(ctlr->r_res1, 0x02014 + ATA_MV_EDMA_BASE(ch)); 385210008Srdivacky slot = (((req_in & ~0xfffffc00) >> 5) + 0) & 0x1f; 386210008Srdivacky bytep = (u_int8_t *)(ch->dma.work); 387210008Srdivacky bytep += (slot << 5); 388210008Srdivacky 389226633Sdim /* fill in this request */ 390226633Sdim le32enc(bytep + 0 * sizeof(u_int32_t), 391226633Sdim request->dma->sg_bus & 0xffffffff); 392226633Sdim le32enc(bytep + 1 * sizeof(u_int32_t), 393226633Sdim (u_int64_t)request->dma->sg_bus >> 32); 394226633Sdim if (ctlr->chip->cfg2 != MV_6042 && ctlr->chip->cfg2 != MV_7042) { 395226633Sdim le16enc(bytep + 4 * sizeof(u_int16_t), 396226633Sdim (request->flags & ATA_R_READ ? 0x01 : 0x00) | (request->tag << 1)); 397226633Sdim 398226633Sdim i = 10; 399226633Sdim bytep[i++] = (request->u.ata.count >> 8) & 0xff; 400226633Sdim bytep[i++] = 0x10 | ATA_COUNT; 401234353Sdim bytep[i++] = request->u.ata.count & 0xff; 402234353Sdim bytep[i++] = 0x10 | ATA_COUNT; 403234353Sdim 404234353Sdim bytep[i++] = (request->u.ata.lba >> 24) & 0xff; 405234353Sdim bytep[i++] = 0x10 | ATA_SECTOR; 406234353Sdim bytep[i++] = request->u.ata.lba & 0xff; 407234353Sdim bytep[i++] = 0x10 | ATA_SECTOR; 408234353Sdim 409234353Sdim bytep[i++] = (request->u.ata.lba >> 32) & 0xff; 410234353Sdim bytep[i++] = 0x10 | ATA_CYL_LSB; 411234353Sdim bytep[i++] = (request->u.ata.lba >> 8) & 0xff; 412234353Sdim bytep[i++] = 0x10 | ATA_CYL_LSB; 413234353Sdim 414234353Sdim bytep[i++] = (request->u.ata.lba >> 40) & 0xff; 415234353Sdim bytep[i++] = 0x10 | ATA_CYL_MSB; 416234353Sdim bytep[i++] = (request->u.ata.lba >> 16) & 0xff; 417234353Sdim bytep[i++] = 0x10 | ATA_CYL_MSB; 418234353Sdim 419234353Sdim bytep[i++] = ATA_D_LBA | ATA_D_IBM | ((request->u.ata.lba >> 24) & 0xf); 420234353Sdim bytep[i++] = 0x10 | ATA_DRIVE; 421234353Sdim 422239462Sdim bytep[i++] = request->u.ata.command; 423239462Sdim bytep[i++] = 0x90 | ATA_COMMAND; 424239462Sdim } else { 425234353Sdim le32enc(bytep + 2 * sizeof(u_int32_t), 426234353Sdim (request->flags & ATA_R_READ ? 0x01 : 0x00) | (request->tag << 1)); 427234353Sdim 428234353Sdim i = 16; 429234353Sdim bytep[i++] = 0; 430234353Sdim bytep[i++] = 0; 431234353Sdim bytep[i++] = request->u.ata.command; 432234353Sdim bytep[i++] = request->u.ata.feature & 0xff; 433234353Sdim 434234353Sdim bytep[i++] = request->u.ata.lba & 0xff; 435239462Sdim bytep[i++] = (request->u.ata.lba >> 8) & 0xff; 436249423Sdim bytep[i++] = (request->u.ata.lba >> 16) & 0xff; 437249423Sdim bytep[i++] = ATA_D_LBA | ATA_D_IBM | ((request->u.ata.lba >> 24) & 0x0f); 438239462Sdim 439239462Sdim bytep[i++] = (request->u.ata.lba >> 24) & 0xff; 440249423Sdim bytep[i++] = (request->u.ata.lba >> 32) & 0xff; 441239462Sdim bytep[i++] = (request->u.ata.lba >> 40) & 0xff; 442239462Sdim bytep[i++] = (request->u.ata.feature >> 8) & 0xff; 443249423Sdim 444239462Sdim bytep[i++] = request->u.ata.count & 0xff; 445243830Sdim bytep[i++] = (request->u.ata.count >> 8) & 0xff; 446239462Sdim bytep[i++] = 0; 447239462Sdim bytep[i++] = 0; 448234353Sdim } 449234353Sdim 450234353Sdim bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, 451234353Sdim BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 452234353Sdim 453234353Sdim /* enable EDMA machinery if needed */ 454234353Sdim if (!(ATA_INL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch)) & 0x00000001)) { 455234353Sdim ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000001); 456234353Sdim while (!(ATA_INL(ctlr->r_res1, 457234353Sdim 0x02028 + ATA_MV_EDMA_BASE(ch)) & 0x00000001)) 458234353Sdim DELAY(10); 459243830Sdim } 460249423Sdim 461234353Sdim /* tell EDMA it has a new request */ 462224145Sdim slot = (((req_in & ~0xfffffc00) >> 5) + 1) & 0x1f; 463234353Sdim req_in &= 0xfffffc00; 464234353Sdim req_in += (slot << 5); 465210008Srdivacky ATA_OUTL(ctlr->r_res1, 0x02014 + ATA_MV_EDMA_BASE(ch), req_in); 466210008Srdivacky 467210008Srdivacky return ATA_OP_CONTINUES; 468221345Sdim} 469221345Sdim 470221345Sdim/* must be called with ATA channel locked and state_mtx held */ 471221345Sdimstatic int 472234353Sdimata_marvell_edma_end_transaction(struct ata_request *request) 473234353Sdim{ 474224145Sdim struct ata_pci_controller *ctlr=device_get_softc(device_get_parent(request->parent)); 475224145Sdim struct ata_channel *ch = device_get_softc(request->parent); 476210008Srdivacky int offset = (ch->unit > 3 ? 0x30014 : 0x20014); 477243830Sdim u_int32_t icr = ATA_INL(ctlr->r_res1, offset); 478243830Sdim int res; 479243830Sdim 480243830Sdim /* EDMA interrupt */ 481243830Sdim if ((icr & (0x0001 << (ch->unit & 3)))) { 482243830Sdim struct ata_marvell_response *response; 483243830Sdim u_int32_t rsp_in, rsp_out; 484210008Srdivacky int slot; 485243830Sdim 486210008Srdivacky /* stop timeout */ 487234353Sdim callout_stop(&request->callout); 488243830Sdim 489243830Sdim /* get response ptr's */ 490234353Sdim rsp_in = ATA_INL(ctlr->r_res1, 0x02020 + ATA_MV_EDMA_BASE(ch)); 491234353Sdim rsp_out = ATA_INL(ctlr->r_res1, 0x02024 + ATA_MV_EDMA_BASE(ch)); 492234353Sdim slot = (((rsp_in & ~0xffffff00) >> 3)) & 0x1f; 493210008Srdivacky rsp_out &= 0xffffff00; 494249423Sdim rsp_out += (slot << 3); 495249423Sdim bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, 496243830Sdim BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 497210008Srdivacky response = (struct ata_marvell_response *) 498210008Srdivacky (ch->dma.work + 1024 + (slot << 3)); 499210008Srdivacky 500210008Srdivacky /* record status for this request */ 501210008Srdivacky request->status = response->dev_status; 502210008Srdivacky request->error = 0; 503210008Srdivacky 504210008Srdivacky /* ack response */ 505210008Srdivacky ATA_OUTL(ctlr->r_res1, 0x02024 + ATA_MV_EDMA_BASE(ch), rsp_out); 506224145Sdim 507224145Sdim /* update progress */ 508224145Sdim if (!(request->status & ATA_S_ERROR) && 509224145Sdim !(request->flags & ATA_R_TIMEOUT)) 510234353Sdim request->donecount = request->bytecount; 511234353Sdim 512224145Sdim /* unload SG list */ 513224145Sdim ch->dma.unload(request); 514234353Sdim 515210008Srdivacky res = ATA_OP_FINISHED; 516210008Srdivacky } 517210008Srdivacky 518210008Srdivacky /* legacy ATA interrupt */ 519210008Srdivacky else { 520210008Srdivacky res = ata_end_transaction(request); 521210008Srdivacky } 522210008Srdivacky 523210008Srdivacky /* ack interrupt */ 524210008Srdivacky ATA_OUTL(ctlr->r_res1, offset, ~(icr & (0x0101 << (ch->unit & 3)))); 525210008Srdivacky return res; 526210008Srdivacky} 527243830Sdim 528243830Sdimstatic void 529243830Sdimata_marvell_edma_reset(device_t dev) 530243830Sdim{ 531249423Sdim struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 532243830Sdim struct ata_channel *ch = device_get_softc(dev); 533243830Sdim 534210008Srdivacky /* disable the EDMA machinery */ 535210008Srdivacky ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000002); 536210008Srdivacky while ((ATA_INL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch)) & 0x00000001)) 537210008Srdivacky DELAY(10); 538210008Srdivacky 539243830Sdim /* clear SATA error register */ 540210008Srdivacky ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR)); 541210008Srdivacky 542210008Srdivacky /* clear any outstanding error interrupts */ 543210008Srdivacky ATA_OUTL(ctlr->r_res1, 0x02008 + ATA_MV_EDMA_BASE(ch), 0x0); 544243830Sdim 545210008Srdivacky /* unmask all error interrupts */ 546210008Srdivacky ATA_OUTL(ctlr->r_res1, 0x0200c + ATA_MV_EDMA_BASE(ch), ~0x0); 547210008Srdivacky 548210008Srdivacky /* enable channel and test for devices */ 549243830Sdim if (ata_sata_phy_reset(dev, -1, 1)) 550210008Srdivacky ata_generic_reset(dev); 551210008Srdivacky 552210008Srdivacky /* enable EDMA machinery */ 553221345Sdim ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000001); 554221345Sdim} 555221345Sdim 556210008Srdivackystatic void 557210008Srdivackyata_marvell_edma_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, 558210008Srdivacky int error) 559210008Srdivacky{ 560210008Srdivacky struct ata_dmasetprd_args *args = xsc; 561210008Srdivacky struct ata_marvell_dma_prdentry *prd = args->dmatab; 562210008Srdivacky int i; 563210008Srdivacky 564210008Srdivacky if ((args->error = error)) 565210008Srdivacky return; 566210008Srdivacky 567210008Srdivacky for (i = 0; i < nsegs; i++) { 568210008Srdivacky prd[i].addrlo = htole32(segs[i].ds_addr); 569210008Srdivacky prd[i].count = htole32(segs[i].ds_len); 570210008Srdivacky prd[i].addrhi = htole32((u_int64_t)segs[i].ds_addr >> 32); 571210008Srdivacky prd[i].reserved = 0; 572210008Srdivacky } 573210008Srdivacky prd[i - 1].count |= htole32(ATA_DMA_EOT); 574210008Srdivacky KASSERT(nsegs <= ATA_DMA_ENTRIES, ("too many DMA segment entries\n")); 575210008Srdivacky args->nsegs = nsegs; 576210008Srdivacky} 577218893Sdim 578210008Srdivackystatic void 579210008Srdivackyata_marvell_edma_dmainit(device_t dev) 580210008Srdivacky{ 581226633Sdim struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 582226633Sdim struct ata_channel *ch = device_get_softc(dev); 583234353Sdim 584224145Sdim ata_dmainit(dev); 585224145Sdim /* note start and stop are not used here */ 586210008Srdivacky ch->dma.setprd = ata_marvell_edma_dmasetprd; 587224145Sdim 588210008Srdivacky /* if 64bit support present adjust max address used */ 589210008Srdivacky if (ATA_INL(ctlr->r_res1, 0x00d00) & 0x00000004) 590210008Srdivacky ch->dma.max_address = BUS_SPACE_MAXADDR; 591 592 /* chip does not reliably do 64K DMA transfers */ 593 if (ctlr->chip->cfg2 == MV_50XX || ctlr->chip->cfg2 == MV_60XX) 594 ch->dma.max_iosize = 64 * DEV_BSIZE; 595 else 596 ch->dma.max_iosize = (ATA_DMA_ENTRIES - 1) * PAGE_SIZE; 597} 598 599ATA_DECLARE_DRIVER(ata_marvell); 600