xref: /onnv-gate/usr/src/uts/intel/io/dktp/controller/ata/ata_dma.c (revision 1709:39a1331cb1e3)
1*1709Smlf /*
2*1709Smlf  * CDDL HEADER START
3*1709Smlf  *
4*1709Smlf  * The contents of this file are subject to the terms of the
5*1709Smlf  * Common Development and Distribution License (the "License").
6*1709Smlf  * You may not use this file except in compliance with the License.
7*1709Smlf  *
8*1709Smlf  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*1709Smlf  * or http://www.opensolaris.org/os/licensing.
10*1709Smlf  * See the License for the specific language governing permissions
11*1709Smlf  * and limitations under the License.
12*1709Smlf  *
13*1709Smlf  * When distributing Covered Code, include this CDDL HEADER in each
14*1709Smlf  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*1709Smlf  * If applicable, add the following below this CDDL HEADER, with the
16*1709Smlf  * fields enclosed by brackets "[]" replaced with your own identifying
17*1709Smlf  * information: Portions Copyright [yyyy] [name of copyright owner]
18*1709Smlf  *
19*1709Smlf  * CDDL HEADER END
20*1709Smlf  */
21*1709Smlf 
22*1709Smlf /*
23*1709Smlf  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*1709Smlf  * Use is subject to license terms.
25*1709Smlf  */
26*1709Smlf 
27*1709Smlf #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*1709Smlf 
29*1709Smlf #include <sys/types.h>
30*1709Smlf #include <sys/debug.h>
31*1709Smlf 
32*1709Smlf #include "ata_common.h"
33*1709Smlf #include "ata_disk.h"
34*1709Smlf #include "atapi.h"
35*1709Smlf #include "pciide.h"
36*1709Smlf 
37*1709Smlf /*
38*1709Smlf  * grap the PCI-IDE status byte
39*1709Smlf  */
40*1709Smlf #define	PCIIDE_STATUS_GET(hdl, addr)	\
41*1709Smlf 	ddi_get8((hdl), ((uchar_t *)(addr) + PCIIDE_BMISX_REG))
42*1709Smlf 
43*1709Smlf /*
44*1709Smlf  * DMA attributes for device I/O
45*1709Smlf  */
46*1709Smlf 
47*1709Smlf ddi_dma_attr_t ata_pciide_dma_attr = {
48*1709Smlf 	DMA_ATTR_V0,		/* dma_attr_version */
49*1709Smlf 	0,			/* dma_attr_addr_lo */
50*1709Smlf 	0xffffffffU,		/* dma_attr_addr_hi */
51*1709Smlf 	0xffff,			/* dma_attr_count_max */
52*1709Smlf 	sizeof (int),		/* dma_attr_align */
53*1709Smlf 	1,			/* dma_attr_burstsizes */
54*1709Smlf 	1,			/* dma_attr_minxfer */
55*1709Smlf 	0x100 << SCTRSHFT,	/* dma_attr_maxxfer */
56*1709Smlf 				/* note that this value can change */
57*1709Smlf 				/* based on max_transfer property */
58*1709Smlf 	0xffff,			/* dma_attr_seg */
59*1709Smlf 	ATA_DMA_NSEGS,		/* dma_attr_sgllen */
60*1709Smlf 	512,			/* dma_attr_granular */
61*1709Smlf 	0			/* dma_attr_flags */
62*1709Smlf };
63*1709Smlf 
64*1709Smlf /*
65*1709Smlf  * DMA attributes for the Bus Mastering PRD table
66*1709Smlf  *
67*1709Smlf  * PRD table Must not cross 4k boundary.
68*1709Smlf  *
69*1709Smlf  * NOTE: the SFF-8038i spec says don't cross a 64k boundary but
70*1709Smlf  * some chip specs seem to think the spec says 4k boundary, Intel
71*1709Smlf  * 82371AB, section 5.2.3. I don't know whether the 4k restriction
72*1709Smlf  * is for real or just a typo. I've specified 4k just to be safe.
73*1709Smlf  * The same Intel spec says the buffer must be 64K aligned, I don't
74*1709Smlf  * believe that and have specified 4 byte alignment.
75*1709Smlf  *
76*1709Smlf  */
77*1709Smlf 
78*1709Smlf #define	PCIIDE_BOUNDARY	(0x1000)
79*1709Smlf 
80*1709Smlf ddi_dma_attr_t ata_prd_dma_attr = {
81*1709Smlf 	DMA_ATTR_V0,		/* dma_attr_version */
82*1709Smlf 	0,			/* dma_attr_addr_lo */
83*1709Smlf 	0xffffffffU,		/* dma_attr_addr_hi */
84*1709Smlf 	PCIIDE_BOUNDARY - 1,	/* dma_attr_count_max */
85*1709Smlf 	sizeof (int),		/* dma_attr_align */
86*1709Smlf 	1,			/* dma_attr_burstsizes */
87*1709Smlf 	1,			/* dma_attr_minxfer */
88*1709Smlf 	PCIIDE_BOUNDARY,	/* dma_attr_maxxfer */
89*1709Smlf 	PCIIDE_BOUNDARY - 1,	/* dma_attr_seg */
90*1709Smlf 	1,			/* dma_attr_sgllen */
91*1709Smlf 	1,			/* dma_attr_granular */
92*1709Smlf 	0			/* dma_attr_flags */
93*1709Smlf };
94*1709Smlf 
95*1709Smlf 
96*1709Smlf 
97*1709Smlf size_t	prd_size = sizeof (prde_t) * ATA_DMA_NSEGS;
98*1709Smlf 
99*1709Smlf int
ata_pciide_alloc(dev_info_t * dip,ata_ctl_t * ata_ctlp)100*1709Smlf ata_pciide_alloc(
101*1709Smlf 	dev_info_t *dip,
102*1709Smlf 	ata_ctl_t *ata_ctlp)
103*1709Smlf {
104*1709Smlf 	ddi_device_acc_attr_t	dev_attr;
105*1709Smlf 	ddi_dma_cookie_t	cookie;
106*1709Smlf 	size_t			buf_size;
107*1709Smlf 	uint_t			count;
108*1709Smlf 	int			rc;
109*1709Smlf 
110*1709Smlf 	dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
111*1709Smlf 	dev_attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
112*1709Smlf 	dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
113*1709Smlf 
114*1709Smlf 
115*1709Smlf 	rc = ddi_dma_alloc_handle(dip, &ata_prd_dma_attr, DDI_DMA_SLEEP, NULL,
116*1709Smlf 		&ata_ctlp->ac_sg_handle);
117*1709Smlf 	if (rc != DDI_SUCCESS) {
118*1709Smlf 		ADBG_ERROR(("ata_pciide_alloc 0x%p handle %d\n",
119*1709Smlf 		    (void *)ata_ctlp, rc));
120*1709Smlf 		goto err3;
121*1709Smlf 	}
122*1709Smlf 
123*1709Smlf 	rc = ddi_dma_mem_alloc(ata_ctlp->ac_sg_handle, prd_size, &dev_attr,
124*1709Smlf 	    DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
125*1709Smlf 	    &ata_ctlp->ac_sg_list, &buf_size, &ata_ctlp->ac_sg_acc_handle);
126*1709Smlf 	if (rc != DDI_SUCCESS) {
127*1709Smlf 		ADBG_ERROR(("ata_pciide_alloc 0x%p mem %d\n",
128*1709Smlf 		    (void *)ata_ctlp, rc));
129*1709Smlf 		goto err2;
130*1709Smlf 	}
131*1709Smlf 
132*1709Smlf 	rc = ddi_dma_addr_bind_handle(ata_ctlp->ac_sg_handle, NULL,
133*1709Smlf 	    ata_ctlp->ac_sg_list, buf_size,
134*1709Smlf 	    DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
135*1709Smlf 	    DDI_DMA_SLEEP, NULL, &cookie, &count);
136*1709Smlf 	if (rc != DDI_DMA_MAPPED) {
137*1709Smlf 		ADBG_ERROR(("ata_pciide_alloc 0x%p bind %d\n",
138*1709Smlf 		    (void *)ata_ctlp, rc));
139*1709Smlf 		goto err1;
140*1709Smlf 	}
141*1709Smlf 
142*1709Smlf 	ASSERT(count == 1);
143*1709Smlf 	ASSERT((cookie.dmac_address & (sizeof (int) - 1)) == 0);
144*1709Smlf #define	Mask4K	0xfffff000
145*1709Smlf 	ASSERT((cookie.dmac_address & Mask4K)
146*1709Smlf 		== ((cookie.dmac_address + cookie.dmac_size - 1) & Mask4K));
147*1709Smlf 
148*1709Smlf 	ata_ctlp->ac_sg_paddr = cookie.dmac_address;
149*1709Smlf 	return (TRUE);
150*1709Smlf err1:
151*1709Smlf 	ddi_dma_mem_free(&ata_ctlp->ac_sg_acc_handle);
152*1709Smlf 	ata_ctlp->ac_sg_acc_handle = NULL;
153*1709Smlf err2:
154*1709Smlf 	ddi_dma_free_handle(&ata_ctlp->ac_sg_handle);
155*1709Smlf 	ata_ctlp->ac_sg_handle = NULL;
156*1709Smlf err3:
157*1709Smlf 	return (FALSE);
158*1709Smlf }
159*1709Smlf 
160*1709Smlf 
161*1709Smlf void
ata_pciide_free(ata_ctl_t * ata_ctlp)162*1709Smlf ata_pciide_free(ata_ctl_t *ata_ctlp)
163*1709Smlf {
164*1709Smlf 	if (ata_ctlp->ac_sg_handle == NULL)
165*1709Smlf 		return;
166*1709Smlf 
167*1709Smlf 	(void) ddi_dma_unbind_handle(ata_ctlp->ac_sg_handle);
168*1709Smlf 	ddi_dma_mem_free(&ata_ctlp->ac_sg_acc_handle);
169*1709Smlf 	ddi_dma_free_handle(&ata_ctlp->ac_sg_handle);
170*1709Smlf 	ata_ctlp->ac_sg_handle = NULL;
171*1709Smlf 	ata_ctlp->ac_sg_acc_handle = NULL;
172*1709Smlf }
173*1709Smlf 
174*1709Smlf 
175*1709Smlf 
176*1709Smlf void
ata_pciide_dma_setup(ata_ctl_t * ata_ctlp,prde_t * srcp,int sg_cnt)177*1709Smlf ata_pciide_dma_setup(
178*1709Smlf 	ata_ctl_t *ata_ctlp,
179*1709Smlf 	prde_t	  *srcp,
180*1709Smlf 	int	   sg_cnt)
181*1709Smlf {
182*1709Smlf 	ddi_acc_handle_t bmhandle = ata_ctlp->ac_bmhandle;
183*1709Smlf 	caddr_t		 bmaddr = ata_ctlp->ac_bmaddr;
184*1709Smlf 	ddi_acc_handle_t sg_acc_handle = ata_ctlp->ac_sg_acc_handle;
185*1709Smlf 	uint_t		*dstp = (uint_t *)ata_ctlp->ac_sg_list;
186*1709Smlf 	int		 idx;
187*1709Smlf 
188*1709Smlf 	ASSERT(dstp != 0);
189*1709Smlf 	ASSERT(sg_cnt != 0);
190*1709Smlf 
191*1709Smlf 	ADBG_DMA(("ata dma_setup 0x%p 0x%p %d\n", ata_ctlp, srcp, sg_cnt));
192*1709Smlf 	/*
193*1709Smlf 	 * Copy the PRD list to controller's phys buffer.
194*1709Smlf 	 * Copying to a fixed location avoids having to check
195*1709Smlf 	 * every ata_pkt for alignment and page boundaries.
196*1709Smlf 	 */
197*1709Smlf 	for (idx = 0; idx < sg_cnt - 1; idx++, srcp++) {
198*1709Smlf 		ddi_put32(sg_acc_handle, dstp++, srcp->p_address);
199*1709Smlf 		ddi_put32(sg_acc_handle, dstp++, srcp->p_count);
200*1709Smlf 	}
201*1709Smlf 
202*1709Smlf 	/*
203*1709Smlf 	 * set the end of table flag in the last entry
204*1709Smlf 	 */
205*1709Smlf 	srcp->p_count |= PCIIDE_PRDE_EOT;
206*1709Smlf 	ddi_put32(sg_acc_handle, dstp++, srcp->p_address);
207*1709Smlf 	ddi_put32(sg_acc_handle, dstp++, srcp->p_count);
208*1709Smlf 
209*1709Smlf 	/*
210*1709Smlf 	 * give the pciide chip the physical address of the PRDE table
211*1709Smlf 	 */
212*1709Smlf 	ddi_put32(bmhandle, (uint_t *)(bmaddr + PCIIDE_BMIDTPX_REG),
213*1709Smlf 		ata_ctlp->ac_sg_paddr);
214*1709Smlf 
215*1709Smlf 	ADBG_DMA(("ata dma_setup 0x%p 0x%llx\n",
216*1709Smlf 		bmaddr, (unsigned long long)ata_ctlp->ac_sg_paddr));
217*1709Smlf }
218*1709Smlf 
219*1709Smlf 
220*1709Smlf 
221*1709Smlf void
ata_pciide_dma_start(ata_ctl_t * ata_ctlp,uchar_t direction)222*1709Smlf ata_pciide_dma_start(
223*1709Smlf 	ata_ctl_t *ata_ctlp,
224*1709Smlf 	uchar_t direction)
225*1709Smlf {
226*1709Smlf 	ddi_acc_handle_t bmhandle = ata_ctlp->ac_bmhandle;
227*1709Smlf 	caddr_t		 bmaddr = ata_ctlp->ac_bmaddr;
228*1709Smlf 	uchar_t		 tmp;
229*1709Smlf 
230*1709Smlf 	ASSERT((ata_ctlp->ac_sg_paddr & PCIIDE_BMIDTPX_MASK) == 0);
231*1709Smlf 	ASSERT((direction == PCIIDE_BMICX_RWCON_WRITE_TO_MEMORY) ||
232*1709Smlf 		(direction == PCIIDE_BMICX_RWCON_READ_FROM_MEMORY));
233*1709Smlf 
234*1709Smlf 	/*
235*1709Smlf 	 * Set the direction control and start the PCIIDE DMA controller
236*1709Smlf 	 */
237*1709Smlf 	tmp = ddi_get8(bmhandle, (uchar_t *)bmaddr + PCIIDE_BMICX_REG);
238*1709Smlf 	tmp &= PCIIDE_BMICX_MASK;
239*1709Smlf 	ddi_put8(bmhandle, (uchar_t *)bmaddr + PCIIDE_BMICX_REG,
240*1709Smlf 		(tmp |  direction));
241*1709Smlf 
242*1709Smlf 	ddi_put8(bmhandle, (uchar_t *)bmaddr + PCIIDE_BMICX_REG,
243*1709Smlf 		(tmp | PCIIDE_BMICX_SSBM_E | direction));
244*1709Smlf 
245*1709Smlf 	return;
246*1709Smlf 
247*1709Smlf }
248*1709Smlf 
249*1709Smlf 
250*1709Smlf void
ata_pciide_dma_stop(ata_ctl_t * ata_ctlp)251*1709Smlf ata_pciide_dma_stop(
252*1709Smlf 	ata_ctl_t *ata_ctlp)
253*1709Smlf {
254*1709Smlf 	ddi_acc_handle_t bmhandle = ata_ctlp->ac_bmhandle;
255*1709Smlf 	caddr_t		 bmaddr = ata_ctlp->ac_bmaddr;
256*1709Smlf 	uchar_t		 tmp;
257*1709Smlf 
258*1709Smlf 	/*
259*1709Smlf 	 * Stop the PCIIDE DMA controller
260*1709Smlf 	 */
261*1709Smlf 	tmp = ddi_get8(bmhandle, (uchar_t *)bmaddr + PCIIDE_BMICX_REG);
262*1709Smlf 	tmp &= (PCIIDE_BMICX_MASK & (~PCIIDE_BMICX_SSBM));
263*1709Smlf 
264*1709Smlf 	ADBG_DMA(("ata_pciide_dma_stop 0x%p 0x%x\n", bmaddr, tmp));
265*1709Smlf 
266*1709Smlf 	ddi_put8(bmhandle, (uchar_t *)bmaddr + PCIIDE_BMICX_REG, tmp);
267*1709Smlf }
268*1709Smlf 
269*1709Smlf /* ARGSUSED */
270*1709Smlf void
ata_pciide_dma_sg_func(gcmd_t * gcmdp,ddi_dma_cookie_t * dmackp,int single_segment,int seg_index)271*1709Smlf ata_pciide_dma_sg_func(
272*1709Smlf 	gcmd_t	*gcmdp,
273*1709Smlf 	ddi_dma_cookie_t *dmackp,
274*1709Smlf 	int	 single_segment,
275*1709Smlf 	int	 seg_index)
276*1709Smlf {
277*1709Smlf 	ata_pkt_t *ata_pktp = GCMD2APKT(gcmdp);
278*1709Smlf 	prde_t	  *dmap;
279*1709Smlf 
280*1709Smlf 	ASSERT(seg_index < ATA_DMA_NSEGS);
281*1709Smlf 	ASSERT(((uint_t)dmackp->dmac_address & PCIIDE_PRDE_ADDR_MASK) == 0);
282*1709Smlf 	ASSERT((dmackp->dmac_size & PCIIDE_PRDE_CNT_MASK) == 0);
283*1709Smlf 	ASSERT(dmackp->dmac_size <= PCIIDE_PRDE_CNT_MAX);
284*1709Smlf 
285*1709Smlf 	ADBG_TRACE(("adp_dma_sg_func: gcmdp 0x%p dmackp 0x%p s %d idx %d\n",
286*1709Smlf 		    gcmdp, dmackp, single_segment, seg_index));
287*1709Smlf 
288*1709Smlf 	/* set address of current entry in scatter/gather list */
289*1709Smlf 	dmap = ata_pktp->ap_sg_list + seg_index;
290*1709Smlf 
291*1709Smlf 	/* store the phys addr and count from the cookie */
292*1709Smlf 	dmap->p_address = (uint_t)dmackp->dmac_address;
293*1709Smlf 	dmap->p_count = (uint_t)dmackp->dmac_size;
294*1709Smlf 
295*1709Smlf 	/* save the count of scatter/gather segments */
296*1709Smlf 	ata_pktp->ap_sg_cnt = seg_index + 1;
297*1709Smlf 
298*1709Smlf 	/* compute the total bytes in this request */
299*1709Smlf 	if (seg_index == 0)
300*1709Smlf 		ata_pktp->ap_bcount = 0;
301*1709Smlf 	ata_pktp->ap_bcount += dmackp->dmac_size;
302*1709Smlf }
303*1709Smlf 
304*1709Smlf 
305*1709Smlf 
306*1709Smlf int
ata_pciide_status_clear(ata_ctl_t * ata_ctlp)307*1709Smlf ata_pciide_status_clear(
308*1709Smlf 	ata_ctl_t *ata_ctlp)
309*1709Smlf {
310*1709Smlf 	ddi_acc_handle_t bmhandle = ata_ctlp->ac_bmhandle;
311*1709Smlf 	caddr_t		 bmaddr = ata_ctlp->ac_bmaddr;
312*1709Smlf 	uchar_t		 status;
313*1709Smlf 	uchar_t		 tmp;
314*1709Smlf 
315*1709Smlf 	/*
316*1709Smlf 	 * Get the current PCIIDE status
317*1709Smlf 	 */
318*1709Smlf 	status = PCIIDE_STATUS_GET(ata_ctlp->ac_bmhandle, ata_ctlp->ac_bmaddr);
319*1709Smlf 	tmp = status & PCIIDE_BMISX_MASK;
320*1709Smlf 	tmp |= (PCIIDE_BMISX_IDERR | PCIIDE_BMISX_IDEINTS);
321*1709Smlf 
322*1709Smlf 	ADBG_DMA(("ata_pciide_status_clear 0x%p 0x%x\n",
323*1709Smlf 		bmaddr, status));
324*1709Smlf 
325*1709Smlf 	/*
326*1709Smlf 	 * Clear the latches (and preserve the other bits)
327*1709Smlf 	 */
328*1709Smlf 	ddi_put8(bmhandle, (uchar_t *)bmaddr + PCIIDE_BMISX_REG, tmp);
329*1709Smlf 
330*1709Smlf #ifdef NAT_SEMI_PC87415_BUG
331*1709Smlf 	/* ??? chip errata ??? */
332*1709Smlf 	if (ata_ctlp->ac_nat_semi_bug) {
333*1709Smlf 		tmp = ddi_get8(bmhandle, bmaddr + PCIIDE_BMICX_REG);
334*1709Smlf 		tmp &= PCIIDE_BMICX_MASK;
335*1709Smlf 		ddi_put8(bmhandle, bmaddr + PCIIDE_BMICX_REG,
336*1709Smlf 			(tmp | PCIIDE_BMISX_IDERR | PCIIDE_BMISX_IDEINTS));
337*1709Smlf 	}
338*1709Smlf #endif
339*1709Smlf 	return (status);
340*1709Smlf }
341*1709Smlf 
342*1709Smlf int
ata_pciide_status_dmacheck_clear(ata_ctl_t * ata_ctlp)343*1709Smlf ata_pciide_status_dmacheck_clear(
344*1709Smlf 	ata_ctl_t *ata_ctlp)
345*1709Smlf {
346*1709Smlf 	uchar_t		 status;
347*1709Smlf 
348*1709Smlf 	/*
349*1709Smlf 	 * Get the PCIIDE DMA controller's current status
350*1709Smlf 	 */
351*1709Smlf 	status = ata_pciide_status_clear(ata_ctlp);
352*1709Smlf 
353*1709Smlf 	ADBG_DMA(("ata_pciide_status_dmacheck_clear 0x%p 0x%x\n",
354*1709Smlf 		ata_ctlp->ac_bmaddr, status));
355*1709Smlf 	/*
356*1709Smlf 	 * check for errors
357*1709Smlf 	 */
358*1709Smlf 	if (status & PCIIDE_BMISX_IDERR) {
359*1709Smlf 		ADBG_WARN(("ata_pciide_status: 0x%x\n", status));
360*1709Smlf 		return (TRUE);
361*1709Smlf 	}
362*1709Smlf 	return (FALSE);
363*1709Smlf }
364*1709Smlf 
365*1709Smlf 
366*1709Smlf 
367*1709Smlf /*
368*1709Smlf  * Check for a pending PCI-IDE interrupt
369*1709Smlf  */
370*1709Smlf 
371*1709Smlf int
ata_pciide_status_pending(ata_ctl_t * ata_ctlp)372*1709Smlf ata_pciide_status_pending(
373*1709Smlf 	ata_ctl_t *ata_ctlp)
374*1709Smlf {
375*1709Smlf 	uchar_t status;
376*1709Smlf 
377*1709Smlf 	status = PCIIDE_STATUS_GET(ata_ctlp->ac_bmhandle, ata_ctlp->ac_bmaddr);
378*1709Smlf 	ADBG_DMA(("ata_pciide_status_pending 0x%p 0x%x\n",
379*1709Smlf 		ata_ctlp->ac_bmaddr, status));
380*1709Smlf 	if (status & PCIIDE_BMISX_IDEINTS)
381*1709Smlf 		return (TRUE);
382*1709Smlf 	return (FALSE);
383*1709Smlf }
384