1a1917f14Szrj /*-
2a1917f14Szrj  * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
3a1917f14Szrj  * All rights reserved.
4a1917f14Szrj  *
5a1917f14Szrj  * Redistribution and use in source and binary forms, with or without
6a1917f14Szrj  * modification, are permitted provided that the following conditions
7a1917f14Szrj  * are met:
8a1917f14Szrj  * 1. Redistributions of source code must retain the above copyright
9a1917f14Szrj  *    notice, this list of conditions and the following disclaimer,
10a1917f14Szrj  *    without modification, immediately at the beginning of the file.
11a1917f14Szrj  * 2. Redistributions in binary form must reproduce the above copyright
12a1917f14Szrj  *    notice, this list of conditions and the following disclaimer in the
13a1917f14Szrj  *    documentation and/or other materials provided with the distribution.
14a1917f14Szrj  *
15a1917f14Szrj  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16a1917f14Szrj  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17a1917f14Szrj  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18a1917f14Szrj  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19a1917f14Szrj  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20a1917f14Szrj  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21a1917f14Szrj  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22a1917f14Szrj  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23a1917f14Szrj  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24a1917f14Szrj  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25a1917f14Szrj  */
26a1917f14Szrj 
27a1917f14Szrj /* local prototypes */
28a1917f14Szrj static int ata_marvell_pata_chipinit(device_t dev);
29a1917f14Szrj static int ata_marvell_pata_allocate(device_t dev);
30a1917f14Szrj static void ata_marvell_pata_setmode(device_t dev, int mode);
31a1917f14Szrj static int ata_marvell_edma_allocate(device_t dev);
32a1917f14Szrj static int ata_marvell_edma_status(device_t dev);
33a1917f14Szrj static int ata_marvell_edma_begin_transaction(struct ata_request *request);
34a1917f14Szrj static int ata_marvell_edma_end_transaction(struct ata_request *request);
35a1917f14Szrj static void ata_marvell_edma_reset(device_t dev);
36a1917f14Szrj static void ata_marvell_edma_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
37a1917f14Szrj static void ata_marvell_edma_dmainit(device_t dev);
38a1917f14Szrj 
39853eb30dSzrj /* misc defines */
40560012aaSzrj #undef MV_60XX
41560012aaSzrj #undef MV_7042
42853eb30dSzrj #define MV_50XX		50
43853eb30dSzrj #define MV_60XX		60
44560012aaSzrj #define MV_6042		62
45560012aaSzrj #define MV_7042		72
46853eb30dSzrj #define MV_61XX		61
47853eb30dSzrj 
48a1917f14Szrj #define ATA_MV_HOST_BASE(ch) \
49a1917f14Szrj 	((ch->unit & 3) * 0x0100) + (ch->unit > 3 ? 0x30000 : 0x20000)
50a1917f14Szrj #define ATA_MV_EDMA_BASE(ch) \
51a1917f14Szrj 	((ch->unit & 3) * 0x2000) + (ch->unit > 3 ? 0x30000 : 0x20000)
52a1917f14Szrj 
53a1917f14Szrj struct ata_marvell_response {
54a1917f14Szrj     u_int16_t   tag;
55a1917f14Szrj     u_int8_t    edma_status;
56a1917f14Szrj     u_int8_t    dev_status;
57a1917f14Szrj     u_int32_t   timestamp;
58a1917f14Szrj };
59a1917f14Szrj 
60a1917f14Szrj struct ata_marvell_dma_prdentry {
61a1917f14Szrj     u_int32_t addrlo;
62a1917f14Szrj     u_int32_t count;
63a1917f14Szrj     u_int32_t addrhi;
64a1917f14Szrj     u_int32_t reserved;
65a1917f14Szrj };
66a1917f14Szrj 
67a1917f14Szrj /*
68a1917f14Szrj  * Marvell chipset support functions
69a1917f14Szrj  */
70a1917f14Szrj int
ata_marvell_ident(device_t dev)71a1917f14Szrj ata_marvell_ident(device_t dev)
72a1917f14Szrj {
73a1917f14Szrj     struct ata_pci_controller *ctlr = device_get_softc(dev);
7459503772Szrj     static const struct ata_chip_id ids[] =
75853eb30dSzrj     {{ ATA_M88SX5040, 0, 4, MV_50XX, ATA_SA150, "88SX5040" },
76853eb30dSzrj      { ATA_M88SX5041, 0, 4, MV_50XX, ATA_SA150, "88SX5041" },
77853eb30dSzrj      { ATA_M88SX5080, 0, 8, MV_50XX, ATA_SA150, "88SX5080" },
78853eb30dSzrj      { ATA_M88SX5081, 0, 8, MV_50XX, ATA_SA150, "88SX5081" },
79853eb30dSzrj      { ATA_M88SX6041, 0, 4, MV_60XX, ATA_SA300, "88SX6041" },
80560012aaSzrj      { ATA_M88SX6042, 0, 4, MV_6042, ATA_SA300, "88SX6042" },
81853eb30dSzrj      { ATA_M88SX6081, 0, 8, MV_60XX, ATA_SA300, "88SX6081" },
82560012aaSzrj      { ATA_M88SX7042, 0, 4, MV_7042, ATA_SA300, "88SX7042" },
83853eb30dSzrj      { ATA_M88SX6101, 0, 1, MV_61XX, ATA_UDMA6, "88SX6101" },
84878a3234Szrj      { ATA_M88SX6121, 0, 1, MV_61XX, ATA_UDMA6, "88SX6121" },
85853eb30dSzrj      { ATA_M88SX6145, 0, 2, MV_61XX, ATA_UDMA6, "88SX6145" },
86a1917f14Szrj      { 0, 0, 0, 0, 0, 0}};
87a1917f14Szrj 
8859503772Szrj     if (pci_get_vendor(dev) != ATA_MARVELL_ID)
89a1917f14Szrj 	return ENXIO;
90a1917f14Szrj 
9159503772Szrj     if (!(ctlr->chip = ata_match_chip(dev, ids)))
9259503772Szrj 	return ENXIO;
9359503772Szrj 
9459503772Szrj     ata_set_desc(dev);
9559503772Szrj 
96a1917f14Szrj     switch (ctlr->chip->cfg2) {
97853eb30dSzrj     case MV_50XX:
98853eb30dSzrj     case MV_60XX:
99560012aaSzrj     case MV_6042:
100560012aaSzrj     case MV_7042:
101a1917f14Szrj 	ctlr->chipinit = ata_marvell_edma_chipinit;
102a1917f14Szrj 	break;
103853eb30dSzrj     case MV_61XX:
104a1917f14Szrj 	ctlr->chipinit = ata_marvell_pata_chipinit;
105a1917f14Szrj 	break;
106a1917f14Szrj     }
107a1917f14Szrj     return 0;
108a1917f14Szrj }
109a1917f14Szrj 
110a1917f14Szrj static int
ata_marvell_pata_chipinit(device_t dev)111a1917f14Szrj ata_marvell_pata_chipinit(device_t dev)
112a1917f14Szrj {
113a1917f14Szrj     struct ata_pci_controller *ctlr = device_get_softc(dev);
114a1917f14Szrj 
11543156ad7Szrj     if (ata_setup_interrupt(dev, ata_generic_intr))
116a1917f14Szrj 	return ENXIO;
117a1917f14Szrj 
118a1917f14Szrj     ctlr->allocate = ata_marvell_pata_allocate;
119a1917f14Szrj     ctlr->setmode = ata_marvell_pata_setmode;
120a1917f14Szrj     ctlr->channels = ctlr->chip->cfg1;
121a1917f14Szrj     return 0;
122a1917f14Szrj }
123a1917f14Szrj 
124a1917f14Szrj static int
ata_marvell_pata_allocate(device_t dev)125a1917f14Szrj ata_marvell_pata_allocate(device_t dev)
126a1917f14Szrj {
127a1917f14Szrj     struct ata_channel *ch = device_get_softc(dev);
128a1917f14Szrj 
129a1917f14Szrj     /* setup the usual register normal pci style */
130a1917f14Szrj     if (ata_pci_allocate(dev))
131a1917f14Szrj 	return ENXIO;
132a1917f14Szrj 
133a1917f14Szrj     /* dont use 32 bit PIO transfers */
134a1917f14Szrj     ch->flags |= ATA_USE_16BIT;
135a1917f14Szrj 
136a1917f14Szrj     return 0;
137a1917f14Szrj }
138a1917f14Szrj 
139a1917f14Szrj static void
ata_marvell_pata_setmode(device_t dev,int mode)140a1917f14Szrj ata_marvell_pata_setmode(device_t dev, int mode)
141a1917f14Szrj {
142a1917f14Szrj     device_t gparent = GRANDPARENT(dev);
143a1917f14Szrj     struct ata_pci_controller *ctlr = device_get_softc(gparent);
144a1917f14Szrj     struct ata_device *atadev = device_get_softc(dev);
145a1917f14Szrj 
146a1917f14Szrj     mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma);
147a1917f14Szrj     mode = ata_check_80pin(dev, mode);
148a1917f14Szrj     if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode))
149a1917f14Szrj 	atadev->mode = mode;
150a1917f14Szrj }
151a1917f14Szrj 
152a1917f14Szrj static int
ata_marvell_edma_chipinit(device_t dev)153a1917f14Szrj ata_marvell_edma_chipinit(device_t dev)
154a1917f14Szrj {
155a1917f14Szrj     struct ata_pci_controller *ctlr = device_get_softc(dev);
156a1917f14Szrj 
15743156ad7Szrj     if (ata_setup_interrupt(dev, ata_generic_intr))
158a1917f14Szrj 	return ENXIO;
159a1917f14Szrj 
160a1917f14Szrj     ctlr->r_type1 = SYS_RES_MEMORY;
161a1917f14Szrj     ctlr->r_rid1 = PCIR_BAR(0);
162a1917f14Szrj     if (!(ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1,
163a1917f14Szrj 						&ctlr->r_rid1, RF_ACTIVE))) {
164a1917f14Szrj 	ata_teardown_interrupt(dev);
165a1917f14Szrj 	return ENXIO;
166a1917f14Szrj     }
167a1917f14Szrj 
168a1917f14Szrj     /* mask all host controller interrupts */
169a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x01d64, 0x00000000);
170a1917f14Szrj 
171a1917f14Szrj     /* mask all PCI interrupts */
172a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x01d5c, 0x00000000);
173a1917f14Szrj 
174a1917f14Szrj     ctlr->allocate = ata_marvell_edma_allocate;
175a1917f14Szrj     ctlr->reset = ata_marvell_edma_reset;
176a1917f14Szrj     ctlr->dmainit = ata_marvell_edma_dmainit;
177a1917f14Szrj     ctlr->setmode = ata_sata_setmode;
178a1917f14Szrj     ctlr->channels = ctlr->chip->cfg1;
179a1917f14Szrj 
180a1917f14Szrj     /* clear host controller interrupts */
181a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x20014, 0x00000000);
182a1917f14Szrj     if (ctlr->chip->cfg1 > 4)
183a1917f14Szrj 	ATA_OUTL(ctlr->r_res1, 0x30014, 0x00000000);
184a1917f14Szrj 
185a1917f14Szrj     /* clear PCI interrupts */
186a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x01d58, 0x00000000);
187a1917f14Szrj 
188a1917f14Szrj     /* unmask PCI interrupts we want */
189a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x01d5c, 0x007fffff);
190a1917f14Szrj 
191a1917f14Szrj     /* unmask host controller interrupts we want */
192a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x01d64, 0x000000ff/*HC0*/ | 0x0001fe00/*HC1*/ |
193a1917f14Szrj 	     /*(1<<19) | (1<<20) | (1<<21) |*/(1<<22) | (1<<24) | (0x7f << 25));
194a1917f14Szrj 
195a1917f14Szrj     /* enable PCI interrupt */
196a1917f14Szrj     pci_write_config(dev, PCIR_COMMAND,
197a1917f14Szrj 		     pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2);
198a1917f14Szrj     return 0;
199a1917f14Szrj }
200a1917f14Szrj 
201a1917f14Szrj static int
ata_marvell_edma_allocate(device_t dev)202a1917f14Szrj ata_marvell_edma_allocate(device_t dev)
203a1917f14Szrj {
204a1917f14Szrj     struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
205a1917f14Szrj     struct ata_channel *ch = device_get_softc(dev);
206560012aaSzrj     u_int64_t work;
207a1917f14Szrj     int i;
208a1917f14Szrj 
209560012aaSzrj     work = ch->dma->work_bus;
210a1917f14Szrj     /* clear work area */
211a1917f14Szrj     bzero(ch->dma->work, 1024+256);
212560012aaSzrj     bus_dmamap_sync(ch->dma->work_tag, ch->dma->work_map,
213560012aaSzrj 	BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
214a1917f14Szrj 
215a1917f14Szrj     /* set legacy ATA resources */
216a1917f14Szrj     for (i = ATA_DATA; i <= ATA_COMMAND; i++) {
217a1917f14Szrj 	ch->r_io[i].res = ctlr->r_res1;
218a1917f14Szrj 	ch->r_io[i].offset = 0x02100 + (i << 2) + ATA_MV_EDMA_BASE(ch);
219a1917f14Szrj     }
220a1917f14Szrj     ch->r_io[ATA_CONTROL].res = ctlr->r_res1;
221a1917f14Szrj     ch->r_io[ATA_CONTROL].offset = 0x02120 + ATA_MV_EDMA_BASE(ch);
222a1917f14Szrj     ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res1;
223a1917f14Szrj     ata_default_registers(dev);
224a1917f14Szrj 
225a1917f14Szrj     /* set SATA resources */
226a1917f14Szrj     switch (ctlr->chip->cfg2) {
227853eb30dSzrj     case MV_50XX:
228a1917f14Szrj 	ch->r_io[ATA_SSTATUS].res = ctlr->r_res1;
229a1917f14Szrj 	ch->r_io[ATA_SSTATUS].offset =  0x00100 + ATA_MV_HOST_BASE(ch);
230a1917f14Szrj 	ch->r_io[ATA_SERROR].res = ctlr->r_res1;
231a1917f14Szrj 	ch->r_io[ATA_SERROR].offset = 0x00104 + ATA_MV_HOST_BASE(ch);
232a1917f14Szrj 	ch->r_io[ATA_SCONTROL].res = ctlr->r_res1;
233a1917f14Szrj 	ch->r_io[ATA_SCONTROL].offset = 0x00108 + ATA_MV_HOST_BASE(ch);
234a1917f14Szrj 	break;
235853eb30dSzrj     case MV_60XX:
236560012aaSzrj     case MV_6042:
237560012aaSzrj     case MV_7042:
238a1917f14Szrj 	ch->r_io[ATA_SSTATUS].res = ctlr->r_res1;
239a1917f14Szrj 	ch->r_io[ATA_SSTATUS].offset =  0x02300 + ATA_MV_EDMA_BASE(ch);
240a1917f14Szrj 	ch->r_io[ATA_SERROR].res = ctlr->r_res1;
241a1917f14Szrj 	ch->r_io[ATA_SERROR].offset = 0x02304 + ATA_MV_EDMA_BASE(ch);
242a1917f14Szrj 	ch->r_io[ATA_SCONTROL].res = ctlr->r_res1;
243a1917f14Szrj 	ch->r_io[ATA_SCONTROL].offset = 0x02308 + ATA_MV_EDMA_BASE(ch);
244a1917f14Szrj 	ch->r_io[ATA_SACTIVE].res = ctlr->r_res1;
245a1917f14Szrj 	ch->r_io[ATA_SACTIVE].offset = 0x02350 + ATA_MV_EDMA_BASE(ch);
246a1917f14Szrj 	break;
247a1917f14Szrj     }
248a1917f14Szrj 
249a1917f14Szrj     ch->flags |= ATA_NO_SLAVE;
250a1917f14Szrj     ch->flags |= ATA_USE_16BIT; /* XXX SOS needed ? */
251a1917f14Szrj     ata_generic_hw(dev);
252a1917f14Szrj     ch->hw.begin_transaction = ata_marvell_edma_begin_transaction;
253a1917f14Szrj     ch->hw.end_transaction = ata_marvell_edma_end_transaction;
254a1917f14Szrj     ch->hw.status = ata_marvell_edma_status;
255a1917f14Szrj 
256a1917f14Szrj     /* disable the EDMA machinery */
257a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000002);
258a1917f14Szrj     DELAY(100000);       /* SOS should poll for disabled */
259a1917f14Szrj 
260a1917f14Szrj     /* set configuration to non-queued 128b read transfers stop on error */
261a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x02000 + ATA_MV_EDMA_BASE(ch), (1<<11) | (1<<13));
262a1917f14Szrj 
263a1917f14Szrj     /* request queue base high */
264a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x02010 + ATA_MV_EDMA_BASE(ch), work >> 32);
265a1917f14Szrj 
266a1917f14Szrj     /* request queue in ptr */
267a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x02014 + ATA_MV_EDMA_BASE(ch), work & 0xffffffff);
268a1917f14Szrj 
269a1917f14Szrj     /* request queue out ptr */
270a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x02018 + ATA_MV_EDMA_BASE(ch), 0x0);
271a1917f14Szrj 
272a1917f14Szrj     /* response queue base high */
273a1917f14Szrj     work += 1024;
274a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x0201c + ATA_MV_EDMA_BASE(ch), work >> 32);
275a1917f14Szrj 
276a1917f14Szrj     /* response queue in ptr */
277a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x02020 + ATA_MV_EDMA_BASE(ch), 0x0);
278a1917f14Szrj 
279a1917f14Szrj     /* response queue out ptr */
280a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x02024 + ATA_MV_EDMA_BASE(ch), work & 0xffffffff);
281a1917f14Szrj 
282a1917f14Szrj     /* clear SATA error register */
283a1917f14Szrj     ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR));
284a1917f14Szrj 
285a1917f14Szrj     /* clear any outstanding error interrupts */
286a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x02008 + ATA_MV_EDMA_BASE(ch), 0x0);
287a1917f14Szrj 
288a1917f14Szrj     /* unmask all error interrupts */
289a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x0200c + ATA_MV_EDMA_BASE(ch), ~0x0);
290a1917f14Szrj 
291a1917f14Szrj     /* enable EDMA machinery */
292a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000001);
293a1917f14Szrj     return 0;
294a1917f14Szrj }
295a1917f14Szrj 
296a1917f14Szrj static int
ata_marvell_edma_status(device_t dev)297a1917f14Szrj ata_marvell_edma_status(device_t dev)
298a1917f14Szrj {
299a1917f14Szrj     struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
300a1917f14Szrj     struct ata_channel *ch = device_get_softc(dev);
301a1917f14Szrj     u_int32_t cause = ATA_INL(ctlr->r_res1, 0x01d60);
302a1917f14Szrj     int shift = (ch->unit << 1) + (ch->unit > 3);
303a1917f14Szrj 
304a1917f14Szrj     if (cause & (1 << shift)) {
305a1917f14Szrj 
306a1917f14Szrj 	/* clear interrupt(s) */
307a1917f14Szrj 	ATA_OUTL(ctlr->r_res1, 0x02008 + ATA_MV_EDMA_BASE(ch), 0x0);
308a1917f14Szrj 
309a1917f14Szrj 	/* do we have any PHY events ? */
310a1917f14Szrj 	ata_sata_phy_check_events(dev);
311a1917f14Szrj     }
312a1917f14Szrj 
313a1917f14Szrj     /* do we have any device action ? */
314a1917f14Szrj     return (cause & (2 << shift));
315a1917f14Szrj }
316a1917f14Szrj 
317a1917f14Szrj /* must be called with ATA channel locked and state_mtx held */
318a1917f14Szrj static int
ata_marvell_edma_begin_transaction(struct ata_request * request)319a1917f14Szrj ata_marvell_edma_begin_transaction(struct ata_request *request)
320a1917f14Szrj {
321a1917f14Szrj     struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev));
322c04da965Szrj     struct ata_channel *ch = device_get_softc(request->parent);
323a1917f14Szrj     u_int32_t req_in;
324a1917f14Szrj     u_int8_t *bytep;
325560012aaSzrj     int i, tag = 0x07;	/* XXX why 0x07 ? */
326a1917f14Szrj     int dummy, error, slot;
327a1917f14Szrj 
328a1917f14Szrj     /* only DMA R/W goes through the EMDA machine */
329a1917f14Szrj     if (request->u.ata.command != ATA_READ_DMA &&
330560012aaSzrj 	request->u.ata.command != ATA_WRITE_DMA &&
331560012aaSzrj 	request->u.ata.command != ATA_READ_DMA48 &&
332560012aaSzrj 	request->u.ata.command != ATA_WRITE_DMA48) {
333a1917f14Szrj 
334a1917f14Szrj 	/* disable the EDMA machinery */
335a1917f14Szrj 	if (ATA_INL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch)) & 0x00000001)
336a1917f14Szrj 	    ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000002);
337a1917f14Szrj 	return ata_begin_transaction(request);
338a1917f14Szrj     }
339a1917f14Szrj 
340a1917f14Szrj     /* check for 48 bit access and convert if needed */
341a1917f14Szrj     ata_modify_if_48bit(request);
342a1917f14Szrj 
343a1917f14Szrj     /* check sanity, setup SG list and DMA engine */
344a1917f14Szrj     if ((error = ch->dma->load(ch->dev, request->data, request->bytecount,
345a1917f14Szrj 			       request->flags & ATA_R_READ, ch->dma->sg,
346a1917f14Szrj 			       &dummy))) {
347a1917f14Szrj 	device_printf(request->dev, "setting up DMA failed\n");
348a1917f14Szrj 	request->result = error;
349a1917f14Szrj 	return ATA_OP_FINISHED;
350a1917f14Szrj     }
351a1917f14Szrj 
352a1917f14Szrj     /* get next free request queue slot */
353a1917f14Szrj     req_in = ATA_INL(ctlr->r_res1, 0x02014 + ATA_MV_EDMA_BASE(ch));
354a1917f14Szrj     slot = (((req_in & ~0xfffffc00) >> 5) + 0) & 0x1f;
355a1917f14Szrj     bytep = (u_int8_t *)(ch->dma->work);
356a1917f14Szrj     bytep += (slot << 5);
357a1917f14Szrj 
358a1917f14Szrj     /* fill in this request */
359560012aaSzrj     le32enc(bytep + 0 * sizeof(u_int32_t),
360560012aaSzrj 	(long)ch->dma->sg_bus & 0xffffffff);
361560012aaSzrj     le32enc(bytep + 1 * sizeof(u_int32_t),
362560012aaSzrj 	(u_int64_t)ch->dma->sg_bus >> 32);
363560012aaSzrj     if (ctlr->chip->cfg2 != MV_6042 && ctlr->chip->cfg2 != MV_7042) {
364560012aaSzrj 	    le16enc(bytep + 4 * sizeof(u_int16_t),
365560012aaSzrj 		(request->flags & ATA_R_READ ? 0x01 : 0x00) | (tag<<1));
366a1917f14Szrj 
367a1917f14Szrj 	    i = 10;
368a1917f14Szrj 	    bytep[i++] = (request->u.ata.count >> 8) & 0xff;
369a1917f14Szrj 	    bytep[i++] = 0x10 | ATA_COUNT;
370a1917f14Szrj 	    bytep[i++] = request->u.ata.count & 0xff;
371a1917f14Szrj 	    bytep[i++] = 0x10 | ATA_COUNT;
372a1917f14Szrj 
373a1917f14Szrj 	    bytep[i++] = (request->u.ata.lba >> 24) & 0xff;
374a1917f14Szrj 	    bytep[i++] = 0x10 | ATA_SECTOR;
375a1917f14Szrj 	    bytep[i++] = request->u.ata.lba & 0xff;
376a1917f14Szrj 	    bytep[i++] = 0x10 | ATA_SECTOR;
377a1917f14Szrj 
378a1917f14Szrj 	    bytep[i++] = (request->u.ata.lba >> 32) & 0xff;
379a1917f14Szrj 	    bytep[i++] = 0x10 | ATA_CYL_LSB;
380a1917f14Szrj 	    bytep[i++] = (request->u.ata.lba >> 8) & 0xff;
381a1917f14Szrj 	    bytep[i++] = 0x10 | ATA_CYL_LSB;
382a1917f14Szrj 
383a1917f14Szrj 	    bytep[i++] = (request->u.ata.lba >> 40) & 0xff;
384a1917f14Szrj 	    bytep[i++] = 0x10 | ATA_CYL_MSB;
385a1917f14Szrj 	    bytep[i++] = (request->u.ata.lba >> 16) & 0xff;
386a1917f14Szrj 	    bytep[i++] = 0x10 | ATA_CYL_MSB;
387a1917f14Szrj 
388a1917f14Szrj 	    bytep[i++] = ATA_D_LBA | ATA_D_IBM | ((request->u.ata.lba >> 24) & 0xf);
389a1917f14Szrj 	    bytep[i++] = 0x10 | ATA_DRIVE;
390a1917f14Szrj 
391a1917f14Szrj 	    bytep[i++] = request->u.ata.command;
392a1917f14Szrj 	    bytep[i++] = 0x90 | ATA_COMMAND;
393560012aaSzrj     } else {
394560012aaSzrj 	    le32enc(bytep + 2 * sizeof(u_int32_t),
395560012aaSzrj 		(request->flags & ATA_R_READ ? 0x01 : 0x00) | (tag<<1));
396560012aaSzrj 
397560012aaSzrj 	    i = 16;
398560012aaSzrj 	    bytep[i++] = 0;
399560012aaSzrj 	    bytep[i++] = 0;
400560012aaSzrj 	    bytep[i++] = request->u.ata.command;
401560012aaSzrj 	    bytep[i++] = request->u.ata.feature & 0xff;
402560012aaSzrj 
403560012aaSzrj 	    bytep[i++] = request->u.ata.lba & 0xff;
404560012aaSzrj 	    bytep[i++] = (request->u.ata.lba >> 8) & 0xff;
405560012aaSzrj 	    bytep[i++] = (request->u.ata.lba >> 16) & 0xff;
406560012aaSzrj 	    bytep[i++] = ATA_D_LBA | ATA_D_IBM | ((request->u.ata.lba >> 24) & 0x0f);
407560012aaSzrj 
408560012aaSzrj 	    bytep[i++] = (request->u.ata.lba >> 24) & 0xff;
409560012aaSzrj 	    bytep[i++] = (request->u.ata.lba >> 32) & 0xff;
410560012aaSzrj 	    bytep[i++] = (request->u.ata.lba >> 40) & 0xff;
411560012aaSzrj 	    bytep[i++] = (request->u.ata.feature >> 8) & 0xff;
412560012aaSzrj 
413560012aaSzrj 	    bytep[i++] = request->u.ata.count & 0xff;
414560012aaSzrj 	    bytep[i++] = (request->u.ata.count >> 8) & 0xff;
415560012aaSzrj 	    bytep[i++] = 0;
416560012aaSzrj 	    bytep[i++] = 0;
417560012aaSzrj     }
418560012aaSzrj 
419560012aaSzrj     bus_dmamap_sync(ch->dma->work_tag, ch->dma->work_map,
420560012aaSzrj 	BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
421a1917f14Szrj 
422a1917f14Szrj     /* enable EDMA machinery if needed */
423a1917f14Szrj     if (!(ATA_INL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch)) & 0x00000001)) {
424a1917f14Szrj 	ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000001);
425a1917f14Szrj 	while (!(ATA_INL(ctlr->r_res1,
426a1917f14Szrj 			 0x02028 + ATA_MV_EDMA_BASE(ch)) & 0x00000001))
427a1917f14Szrj 	    DELAY(10);
428a1917f14Szrj     }
429a1917f14Szrj 
430a1917f14Szrj     /* tell EDMA it has a new request */
431a1917f14Szrj     slot = (((req_in & ~0xfffffc00) >> 5) + 1) & 0x1f;
432a1917f14Szrj     req_in &= 0xfffffc00;
433a1917f14Szrj     req_in += (slot << 5);
434a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x02014 + ATA_MV_EDMA_BASE(ch), req_in);
435a1917f14Szrj 
436a1917f14Szrj     return ATA_OP_CONTINUES;
437a1917f14Szrj }
438a1917f14Szrj 
439a1917f14Szrj /* must be called with ATA channel locked and state_mtx held */
440a1917f14Szrj static int
ata_marvell_edma_end_transaction(struct ata_request * request)441a1917f14Szrj ata_marvell_edma_end_transaction(struct ata_request *request)
442a1917f14Szrj {
443a1917f14Szrj     struct ata_pci_controller *ctlr=device_get_softc(GRANDPARENT(request->dev));
444c04da965Szrj     struct ata_channel *ch = device_get_softc(request->parent);
445a1917f14Szrj     int offset = (ch->unit > 3 ? 0x30014 : 0x20014);
446a1917f14Szrj     u_int32_t icr = ATA_INL(ctlr->r_res1, offset);
447a1917f14Szrj     int res;
448a1917f14Szrj 
449a1917f14Szrj     /* EDMA interrupt */
450a1917f14Szrj     if ((icr & (0x0001 << (ch->unit & 3)))) {
451a1917f14Szrj 	struct ata_marvell_response *response;
452a1917f14Szrj 	u_int32_t rsp_in, rsp_out;
453a1917f14Szrj 	int slot;
454a1917f14Szrj 
455a1917f14Szrj 	/* stop timeout */
456*eb67213aSMatthew Dillon 	callout_cancel(&request->callout);
457a1917f14Szrj 
458a1917f14Szrj 	/* get response ptr's */
459a1917f14Szrj 	rsp_in = ATA_INL(ctlr->r_res1, 0x02020 + ATA_MV_EDMA_BASE(ch));
460a1917f14Szrj 	rsp_out = ATA_INL(ctlr->r_res1, 0x02024 + ATA_MV_EDMA_BASE(ch));
461a1917f14Szrj 	slot = (((rsp_in & ~0xffffff00) >> 3)) & 0x1f;
462a1917f14Szrj 	rsp_out &= 0xffffff00;
463a1917f14Szrj 	rsp_out += (slot << 3);
464560012aaSzrj 	bus_dmamap_sync(ch->dma->work_tag, ch->dma->work_map,
465560012aaSzrj 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
466a1917f14Szrj 	response = (struct ata_marvell_response *)
467a1917f14Szrj 		   (ch->dma->work + 1024 + (slot << 3));
468a1917f14Szrj 
469a1917f14Szrj 	/* record status for this request */
470a1917f14Szrj 	request->status = response->dev_status;
471a1917f14Szrj 	request->error = 0;
472a1917f14Szrj 
473a1917f14Szrj 	/* ack response */
474a1917f14Szrj 	ATA_OUTL(ctlr->r_res1, 0x02024 + ATA_MV_EDMA_BASE(ch), rsp_out);
475a1917f14Szrj 
476a1917f14Szrj 	/* update progress */
477a1917f14Szrj 	if (!(request->status & ATA_S_ERROR) &&
478a1917f14Szrj 	    !(request->flags & ATA_R_TIMEOUT))
479a1917f14Szrj 	    request->donecount = request->bytecount;
480a1917f14Szrj 
481a1917f14Szrj 	/* unload SG list */
482a1917f14Szrj 	ch->dma->unload(ch->dev);
483a1917f14Szrj 
484a1917f14Szrj 	res = ATA_OP_FINISHED;
485a1917f14Szrj     }
486a1917f14Szrj 
487a1917f14Szrj     /* legacy ATA interrupt */
488a1917f14Szrj     else {
489a1917f14Szrj 	res = ata_end_transaction(request);
490a1917f14Szrj     }
491a1917f14Szrj 
492a1917f14Szrj     /* ack interrupt */
493a1917f14Szrj     ATA_OUTL(ctlr->r_res1, offset, ~(icr & (0x0101 << (ch->unit & 3))));
494a1917f14Szrj     return res;
495a1917f14Szrj }
496a1917f14Szrj 
497a1917f14Szrj static void
ata_marvell_edma_reset(device_t dev)498a1917f14Szrj ata_marvell_edma_reset(device_t dev)
499a1917f14Szrj {
500a1917f14Szrj     struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
501a1917f14Szrj     struct ata_channel *ch = device_get_softc(dev);
502a1917f14Szrj 
503a1917f14Szrj     /* disable the EDMA machinery */
504a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000002);
505a1917f14Szrj     while ((ATA_INL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch)) & 0x00000001))
506a1917f14Szrj 	DELAY(10);
507a1917f14Szrj 
508a1917f14Szrj     /* clear SATA error register */
509a1917f14Szrj     ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR));
510a1917f14Szrj 
511a1917f14Szrj     /* clear any outstanding error interrupts */
512a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x02008 + ATA_MV_EDMA_BASE(ch), 0x0);
513a1917f14Szrj 
514a1917f14Szrj     /* unmask all error interrupts */
515a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x0200c + ATA_MV_EDMA_BASE(ch), ~0x0);
516a1917f14Szrj 
517a1917f14Szrj     /* enable channel and test for devices */
518a1917f14Szrj     if (ata_sata_phy_reset(dev))
519a1917f14Szrj 	ata_generic_reset(dev);
520a1917f14Szrj 
521a1917f14Szrj     /* enable EDMA machinery */
522a1917f14Szrj     ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000001);
523a1917f14Szrj }
524a1917f14Szrj 
525a1917f14Szrj static void
ata_marvell_edma_dmasetprd(void * xsc,bus_dma_segment_t * segs,int nsegs,int error)526a1917f14Szrj ata_marvell_edma_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs,
527a1917f14Szrj 			   int error)
528a1917f14Szrj {
529a1917f14Szrj     struct ata_dmasetprd_args *args = xsc;
530a1917f14Szrj     struct ata_marvell_dma_prdentry *prd = args->dmatab;
531a1917f14Szrj     int i;
532a1917f14Szrj 
533a1917f14Szrj     if ((args->error = error))
534a1917f14Szrj 	return;
535a1917f14Szrj 
536a1917f14Szrj     for (i = 0; i < nsegs; i++) {
537a1917f14Szrj 	prd[i].addrlo = htole32(segs[i].ds_addr);
538a1917f14Szrj 	prd[i].count = htole32(segs[i].ds_len);
539a1917f14Szrj 	prd[i].addrhi = htole32((u_int64_t)segs[i].ds_addr >> 32);
540560012aaSzrj 	prd[i].reserved = 0;
541a1917f14Szrj     }
542a1917f14Szrj     prd[i - 1].count |= htole32(ATA_DMA_EOT);
54343156ad7Szrj     KASSERT(nsegs <= ATA_DMA_ENTRIES, ("too many DMA segment entries\n"));
54443156ad7Szrj     args->nsegs = nsegs;
545a1917f14Szrj }
546a1917f14Szrj 
547a1917f14Szrj static void
ata_marvell_edma_dmainit(device_t dev)548a1917f14Szrj ata_marvell_edma_dmainit(device_t dev)
549a1917f14Szrj {
550a1917f14Szrj     struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
551a1917f14Szrj     struct ata_channel *ch = device_get_softc(dev);
552a1917f14Szrj 
553a1917f14Szrj     ata_dmainit(dev);
554a1917f14Szrj     if (ch->dma) {
555a1917f14Szrj 	/* note start and stop are not used here */
556a1917f14Szrj 	ch->dma->setprd = ata_marvell_edma_dmasetprd;
557a1917f14Szrj 
558a1917f14Szrj 	if (ATA_INL(ctlr->r_res1, 0x00d00) & 0x00000004)
559a1917f14Szrj 	    ch->dma->max_address = BUS_SPACE_MAXADDR;
560a1917f14Szrj 
561a1917f14Szrj 	/* chip does not reliably do 64K DMA transfers */
562560012aaSzrj 	if (ctlr->chip->cfg2 == MV_50XX || ctlr->chip->cfg2 == MV_60XX)
563878a3234Szrj 	    ch->dma->max_iosize = 64 * DEV_BSIZE;
564560012aaSzrj 	else
565560012aaSzrj 	    ch->dma->max_iosize = (ATA_DMA_ENTRIES - 1) * PAGE_SIZE;
566a1917f14Szrj     }
567a1917f14Szrj }
568