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