xref: /netbsd-src/sys/dev/pcmcia/esp_pcmcia.c (revision 8bc54e5be648e06e7c6b48f7611f8bccfda032d4)
1*8bc54e5bSmsaitoh /*	$NetBSD: esp_pcmcia.c,v 1.39 2016/07/07 06:55:42 msaitoh Exp $	*/
2f1ebad18Smycroft 
3f1ebad18Smycroft /*-
403515f2fSmycroft  * Copyright (c) 2000, 2004 The NetBSD Foundation, Inc.
5f1ebad18Smycroft  * All rights reserved.
6f1ebad18Smycroft  *
7f1ebad18Smycroft  * This code is derived from software contributed to The NetBSD Foundation
8f1ebad18Smycroft  * by Charles M. Hannum.
9f1ebad18Smycroft  *
10f1ebad18Smycroft  * Redistribution and use in source and binary forms, with or without
11f1ebad18Smycroft  * modification, are permitted provided that the following conditions
12f1ebad18Smycroft  * are met:
13f1ebad18Smycroft  * 1. Redistributions of source code must retain the above copyright
14f1ebad18Smycroft  *    notice, this list of conditions and the following disclaimer.
15f1ebad18Smycroft  * 2. Redistributions in binary form must reproduce the above copyright
16f1ebad18Smycroft  *    notice, this list of conditions and the following disclaimer in the
17f1ebad18Smycroft  *    documentation and/or other materials provided with the distribution.
18f1ebad18Smycroft  *
19f1ebad18Smycroft  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20f1ebad18Smycroft  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21f1ebad18Smycroft  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22f1ebad18Smycroft  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23f1ebad18Smycroft  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24f1ebad18Smycroft  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25f1ebad18Smycroft  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26f1ebad18Smycroft  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27f1ebad18Smycroft  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28f1ebad18Smycroft  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29f1ebad18Smycroft  * POSSIBILITY OF SUCH DAMAGE.
30f1ebad18Smycroft  */
31f1ebad18Smycroft 
32ab5d9d2bSlukem #include <sys/cdefs.h>
33*8bc54e5bSmsaitoh __KERNEL_RCSID(0, "$NetBSD: esp_pcmcia.c,v 1.39 2016/07/07 06:55:42 msaitoh Exp $");
34ab5d9d2bSlukem 
35f1ebad18Smycroft #include <sys/param.h>
36f1ebad18Smycroft #include <sys/systm.h>
37f1ebad18Smycroft #include <sys/device.h>
38f1ebad18Smycroft #include <sys/buf.h>
39f1ebad18Smycroft 
40a2a38285Sad #include <sys/bus.h>
41a2a38285Sad #include <sys/intr.h>
42f1ebad18Smycroft 
43f1ebad18Smycroft #include <dev/scsipi/scsi_all.h>
44f1ebad18Smycroft #include <dev/scsipi/scsipi_all.h>
45f1ebad18Smycroft #include <dev/scsipi/scsiconf.h>
46f1ebad18Smycroft 
47f1ebad18Smycroft #include <dev/pcmcia/pcmciareg.h>
48f1ebad18Smycroft #include <dev/pcmcia/pcmciavar.h>
49f1ebad18Smycroft #include <dev/pcmcia/pcmciadevs.h>
50f1ebad18Smycroft 
51f1ebad18Smycroft #include <dev/ic/ncr53c9xreg.h>
52f1ebad18Smycroft #include <dev/ic/ncr53c9xvar.h>
53f1ebad18Smycroft 
54f1ebad18Smycroft struct esp_pcmcia_softc {
55f1ebad18Smycroft 	struct ncr53c9x_softc	sc_ncr53c9x;	/* glue to MI code */
56f1ebad18Smycroft 
57f1ebad18Smycroft 	int		sc_active;		/* Pseudo-DMA state vars */
58f1ebad18Smycroft 	int		sc_tc;
59f1ebad18Smycroft 	int		sc_datain;
60f1ebad18Smycroft 	size_t		sc_dmasize;
61f1ebad18Smycroft 	size_t		sc_dmatrans;
6278a1d236Stsutsui 	uint8_t		**sc_dmaaddr;
63f1ebad18Smycroft 	size_t		*sc_pdmalen;
64f1ebad18Smycroft 
65f1ebad18Smycroft 	/* PCMCIA-specific goo. */
66f1ebad18Smycroft 	struct pcmcia_function *sc_pf;		/* our PCMCIA function */
67f1ebad18Smycroft 	void *sc_ih;				/* interrupt handler */
68fc96443dSthorpej #ifdef ESP_PCMCIA_POLL
69fc96443dSthorpej 	struct callout sc_poll_ch;
70fc96443dSthorpej #endif
7103515f2fSmycroft 	bus_space_tag_t	sc_iot;
7203515f2fSmycroft 	bus_space_handle_t sc_ioh;
7303515f2fSmycroft 
7403515f2fSmycroft 	int sc_state;
7503515f2fSmycroft #define ESP_PCMCIA_ATTACHED	3
76f1ebad18Smycroft };
77f1ebad18Smycroft 
7878a1d236Stsutsui int	esp_pcmcia_match(device_t, cfdata_t, void *);
7918db93c7Sperry int	esp_pcmcia_validate_config(struct pcmcia_config_entry *);
8078a1d236Stsutsui void	esp_pcmcia_attach(device_t, device_t, void *);
8118db93c7Sperry void	esp_pcmcia_init(struct esp_pcmcia_softc *);
8278a1d236Stsutsui int	esp_pcmcia_detach(device_t, int);
8378a1d236Stsutsui int	esp_pcmcia_enable(device_t, int);
84f1ebad18Smycroft 
8578a1d236Stsutsui CFATTACH_DECL_NEW(esp_pcmcia, sizeof(struct esp_pcmcia_softc),
86b75a007dSthorpej     esp_pcmcia_match, esp_pcmcia_attach, esp_pcmcia_detach, NULL);
87f1ebad18Smycroft 
88f1ebad18Smycroft /*
89f1ebad18Smycroft  * Functions and the switch for the MI code.
90f1ebad18Smycroft  */
91f1ebad18Smycroft #ifdef ESP_PCMCIA_POLL
9218db93c7Sperry void	esp_pcmcia_poll(void *);
93f1ebad18Smycroft #endif
9478a1d236Stsutsui uint8_t	esp_pcmcia_read_reg(struct ncr53c9x_softc *, int);
9578a1d236Stsutsui void	esp_pcmcia_write_reg(struct ncr53c9x_softc *, int, uint8_t);
9618db93c7Sperry int	esp_pcmcia_dma_isintr(struct ncr53c9x_softc *);
9718db93c7Sperry void	esp_pcmcia_dma_reset(struct ncr53c9x_softc *);
9818db93c7Sperry int	esp_pcmcia_dma_intr(struct ncr53c9x_softc *);
9978a1d236Stsutsui int	esp_pcmcia_dma_setup(struct ncr53c9x_softc *, uint8_t **,
10018db93c7Sperry 	    size_t *, int, size_t *);
10118db93c7Sperry void	esp_pcmcia_dma_go(struct ncr53c9x_softc *);
10218db93c7Sperry void	esp_pcmcia_dma_stop(struct ncr53c9x_softc *);
10318db93c7Sperry int	esp_pcmcia_dma_isactive(struct ncr53c9x_softc *);
104f1ebad18Smycroft 
10596221eb5Smycroft const struct ncr53c9x_glue esp_pcmcia_glue = {
106f1ebad18Smycroft 	esp_pcmcia_read_reg,
107f1ebad18Smycroft 	esp_pcmcia_write_reg,
108f1ebad18Smycroft 	esp_pcmcia_dma_isintr,
109f1ebad18Smycroft 	esp_pcmcia_dma_reset,
110f1ebad18Smycroft 	esp_pcmcia_dma_intr,
111f1ebad18Smycroft 	esp_pcmcia_dma_setup,
112f1ebad18Smycroft 	esp_pcmcia_dma_go,
113f1ebad18Smycroft 	esp_pcmcia_dma_stop,
114f1ebad18Smycroft 	esp_pcmcia_dma_isactive,
115f1ebad18Smycroft 	NULL,			/* gl_clear_latched_intr */
116f1ebad18Smycroft };
117f1ebad18Smycroft 
118adbea351Smycroft const struct pcmcia_product esp_pcmcia_products[] = {
119adbea351Smycroft 	{ PCMCIA_VENDOR_PANASONIC, PCMCIA_PRODUCT_PANASONIC_KXLC002,
120adbea351Smycroft 	  PCMCIA_CIS_PANASONIC_KXLC002 },
121148136c8Sitohy 
122adbea351Smycroft 	{ PCMCIA_VENDOR_RATOC, PCMCIA_PRODUCT_RATOC_REX_9530,
123adbea351Smycroft 	  PCMCIA_CIS_RATOC_REX_9530 },
124f1ebad18Smycroft };
12578a1d236Stsutsui const size_t esp_pcmcia_nproducts = __arraycount(esp_pcmcia_products);
126148136c8Sitohy 
127f1ebad18Smycroft int
esp_pcmcia_match(device_t parent,cfdata_t cf,void * aux)12878a1d236Stsutsui esp_pcmcia_match(device_t parent, cfdata_t cf, void *aux)
129f1ebad18Smycroft {
130f1ebad18Smycroft 	struct pcmcia_attach_args *pa = aux;
131f1ebad18Smycroft 
132adbea351Smycroft 	if (pcmcia_product_lookup(pa, esp_pcmcia_products, esp_pcmcia_nproducts,
133adbea351Smycroft 	    sizeof(esp_pcmcia_products[0]), NULL))
13478a1d236Stsutsui 		return 1;
13578a1d236Stsutsui 	return 0;
136f1ebad18Smycroft }
137f1ebad18Smycroft 
13803515f2fSmycroft int
esp_pcmcia_validate_config(struct pcmcia_config_entry * cfe)13978a1d236Stsutsui esp_pcmcia_validate_config(struct pcmcia_config_entry *cfe)
14003515f2fSmycroft {
14178a1d236Stsutsui 
14203515f2fSmycroft 	if (cfe->iftype != PCMCIA_IFTYPE_IO ||
14303515f2fSmycroft 	    cfe->num_memspace != 0 ||
14403515f2fSmycroft 	    cfe->num_iospace != 1)
14578a1d236Stsutsui 		return EINVAL;
14678a1d236Stsutsui 	return 0;
14703515f2fSmycroft }
14803515f2fSmycroft 
149f1ebad18Smycroft void
esp_pcmcia_attach(device_t parent,device_t self,void * aux)15078a1d236Stsutsui esp_pcmcia_attach(device_t parent, device_t self, void *aux)
151f1ebad18Smycroft {
15278a1d236Stsutsui 	struct esp_pcmcia_softc *esc = device_private(self);
153f1ebad18Smycroft 	struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
154f1ebad18Smycroft 	struct pcmcia_attach_args *pa = aux;
155f1ebad18Smycroft 	struct pcmcia_config_entry *cfe;
156f1ebad18Smycroft 	struct pcmcia_function *pf = pa->pf;
15703515f2fSmycroft 	int error;
158f1ebad18Smycroft 
15978a1d236Stsutsui 	sc->sc_dev = self;
16078a1d236Stsutsui 
161f1ebad18Smycroft 	esc->sc_pf = pf;
162f1ebad18Smycroft 
16303515f2fSmycroft 	error = pcmcia_function_configure(pf, esp_pcmcia_validate_config);
16403515f2fSmycroft 	if (error) {
165*8bc54e5bSmsaitoh 		aprint_error_dev(self, "configure failed, error=%d\n", error);
16603515f2fSmycroft 		return;
167f1ebad18Smycroft 	}
168f1ebad18Smycroft 
16903515f2fSmycroft 	cfe = pf->cfe;
17003515f2fSmycroft 	esc->sc_iot = cfe->iospace[0].handle.iot;
17103515f2fSmycroft 	esc->sc_ioh = cfe->iospace[0].handle.ioh;
172f1ebad18Smycroft 	esp_pcmcia_init(esc);
173f1ebad18Smycroft 
17478a1d236Stsutsui 	aprint_normal("%s", device_xname(self));
17503515f2fSmycroft 
176937a7a3eSbouyer 	sc->sc_adapter.adapt_minphys = minphys;
177937a7a3eSbouyer 	sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request;
1786c334c1eSjdolecek 	sc->sc_adapter.adapt_enable = esp_pcmcia_enable;
17903515f2fSmycroft 
180937a7a3eSbouyer 	ncr53c9x_attach(sc);
18103515f2fSmycroft 	esc->sc_state = ESP_PCMCIA_ATTACHED;
182f1ebad18Smycroft }
183f1ebad18Smycroft 
184f1ebad18Smycroft void
esp_pcmcia_init(struct esp_pcmcia_softc * esc)18578a1d236Stsutsui esp_pcmcia_init(struct esp_pcmcia_softc *esc)
186f1ebad18Smycroft {
187f1ebad18Smycroft 	struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
188f1ebad18Smycroft 
189f1ebad18Smycroft 	/* id 7, clock 40M, parity ON, sync OFF, fast ON, slow ON */
190f1ebad18Smycroft 
191f1ebad18Smycroft 	sc->sc_glue = &esp_pcmcia_glue;
192f1ebad18Smycroft 
193fc96443dSthorpej #ifdef ESP_PCMCIA_POLL
19488ab7da9Sad 	callout_init(&esc->sc_poll_ch, 0);
195fc96443dSthorpej #endif
196fc96443dSthorpej 
197f1ebad18Smycroft 	sc->sc_rev = NCR_VARIANT_ESP406;
198f1ebad18Smycroft 	sc->sc_id = 7;
199f1ebad18Smycroft 	sc->sc_freq = 40;
200df8c3f5cSmycroft 	/* try -PARENB -SLOW */
201f1ebad18Smycroft 	sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB | NCRCFG1_SLOW;
202df8c3f5cSmycroft 	/* try +FE */
203f1ebad18Smycroft 	sc->sc_cfg2 = NCRCFG2_SCSI2;
204df8c3f5cSmycroft 	/* try -IDM -FSCSI -FCLK */
205df8c3f5cSmycroft 	sc->sc_cfg3 = NCRESPCFG3_CDB | NCRESPCFG3_FCLK | NCRESPCFG3_IDM |
206df8c3f5cSmycroft 	    NCRESPCFG3_FSCSI;
207f1ebad18Smycroft 	sc->sc_cfg4 = NCRCFG4_ACTNEG;
208df8c3f5cSmycroft 	/* try +INTP */
209f1ebad18Smycroft 	sc->sc_cfg5 = NCRCFG5_CRS1 | NCRCFG5_AADDR | NCRCFG5_PTRINC;
210f1ebad18Smycroft 	sc->sc_minsync = 0;
211f1ebad18Smycroft 	sc->sc_maxxfer = 64 * 1024;
212f1ebad18Smycroft }
213f1ebad18Smycroft 
214f1ebad18Smycroft int
esp_pcmcia_detach(device_t self,int flags)2157cf29912Scegger esp_pcmcia_detach(device_t self, int flags)
216f1ebad18Smycroft {
21778a1d236Stsutsui 	struct esp_pcmcia_softc *sc = device_private(self);
218f1ebad18Smycroft 	int error;
219f1ebad18Smycroft 
22003515f2fSmycroft 	if (sc->sc_state != ESP_PCMCIA_ATTACHED)
22178a1d236Stsutsui 		return 0;
222f1ebad18Smycroft 
22303515f2fSmycroft 	error = ncr53c9x_detach(&sc->sc_ncr53c9x, flags);
224f1ebad18Smycroft 	if (error)
22578a1d236Stsutsui 		return error;
226f1ebad18Smycroft 
22703515f2fSmycroft 	pcmcia_function_unconfigure(sc->sc_pf);
228f1ebad18Smycroft 
22978a1d236Stsutsui 	return 0;
230f1ebad18Smycroft }
231f1ebad18Smycroft 
232f1ebad18Smycroft int
esp_pcmcia_enable(device_t self,int onoff)2337cf29912Scegger esp_pcmcia_enable(device_t self, int onoff)
234f1ebad18Smycroft {
23578a1d236Stsutsui 	struct esp_pcmcia_softc *sc = device_private(self);
23670ca4b2fSmycroft 	int error;
237f1ebad18Smycroft 
238f1ebad18Smycroft 	if (onoff) {
239f1ebad18Smycroft #ifdef ESP_PCMCIA_POLL
24003515f2fSmycroft 		callout_reset(&sc->sc_poll_ch, 1, esp_pcmcia_poll, sc);
241f1ebad18Smycroft #else
242f1ebad18Smycroft 		/* Establish the interrupt handler. */
24303515f2fSmycroft 		sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_BIO,
24403515f2fSmycroft 		    ncr53c9x_intr, &sc->sc_ncr53c9x);
24570ca4b2fSmycroft 		if (!sc->sc_ih)
24678a1d236Stsutsui 			return EIO;
247f1ebad18Smycroft #endif
248f1ebad18Smycroft 
24970ca4b2fSmycroft 		error = pcmcia_function_enable(sc->sc_pf);
25070ca4b2fSmycroft 		if (error) {
25170ca4b2fSmycroft 			pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
252d11fb31eSmycroft 			sc->sc_ih = 0;
25378a1d236Stsutsui 			return error;
254f1ebad18Smycroft 		}
255f1ebad18Smycroft 
256f1ebad18Smycroft 		/* Initialize only chip.  */
25703515f2fSmycroft 		ncr53c9x_init(&sc->sc_ncr53c9x, 0);
258f1ebad18Smycroft 	} else {
25903515f2fSmycroft 		pcmcia_function_disable(sc->sc_pf);
260f1ebad18Smycroft #ifdef ESP_PCMCIA_POLL
26103515f2fSmycroft 		callout_stop(&sc->sc_poll_ch);
262f1ebad18Smycroft #else
26303515f2fSmycroft 		pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
26403515f2fSmycroft 		sc->sc_ih = 0;
265f1ebad18Smycroft #endif
266f1ebad18Smycroft 	}
267f1ebad18Smycroft 
26878a1d236Stsutsui 	return 0;
269f1ebad18Smycroft }
270f1ebad18Smycroft 
271f1ebad18Smycroft #ifdef ESP_PCMCIA_POLL
272f1ebad18Smycroft void
esp_pcmcia_poll(void * arg)27378a1d236Stsutsui esp_pcmcia_poll(void *arg)
274f1ebad18Smycroft {
275f1ebad18Smycroft 	struct esp_pcmcia_softc *esc = arg;
276f1ebad18Smycroft 
277f1ebad18Smycroft 	(void)ncr53c9x_intr(&esc->sc_ncr53c9x);
278fc96443dSthorpej 	callout_reset(&esc->sc_poll_ch, 1, esp_pcmcia_poll, esc);
279f1ebad18Smycroft }
280f1ebad18Smycroft #endif
281f1ebad18Smycroft 
282f1ebad18Smycroft /*
283f1ebad18Smycroft  * Glue functions.
284f1ebad18Smycroft  */
28578a1d236Stsutsui uint8_t
esp_pcmcia_read_reg(struct ncr53c9x_softc * sc,int reg)28678a1d236Stsutsui esp_pcmcia_read_reg(struct ncr53c9x_softc *sc, int reg)
287f1ebad18Smycroft {
288f1ebad18Smycroft 	struct esp_pcmcia_softc *esc = (struct esp_pcmcia_softc *)sc;
289f1ebad18Smycroft 
29078a1d236Stsutsui 	return bus_space_read_1(esc->sc_iot, esc->sc_ioh, reg);
291f1ebad18Smycroft }
292f1ebad18Smycroft 
293f1ebad18Smycroft void
esp_pcmcia_write_reg(struct ncr53c9x_softc * sc,int reg,uint8_t val)29478a1d236Stsutsui esp_pcmcia_write_reg(struct ncr53c9x_softc *sc, int reg, uint8_t val)
295f1ebad18Smycroft {
296f1ebad18Smycroft 	struct esp_pcmcia_softc *esc = (struct esp_pcmcia_softc *)sc;
29778a1d236Stsutsui 	uint8_t v = val;
298f1ebad18Smycroft 
299f1ebad18Smycroft 	if (reg == NCR_CMD && v == (NCRCMD_TRANS|NCRCMD_DMA))
300f1ebad18Smycroft 		v = NCRCMD_TRANS;
30103515f2fSmycroft 	bus_space_write_1(esc->sc_iot, esc->sc_ioh, reg, v);
302f1ebad18Smycroft }
303f1ebad18Smycroft 
304f1ebad18Smycroft int
esp_pcmcia_dma_isintr(struct ncr53c9x_softc * sc)30578a1d236Stsutsui esp_pcmcia_dma_isintr(struct ncr53c9x_softc *sc)
306f1ebad18Smycroft {
307f1ebad18Smycroft 
308f1ebad18Smycroft 	return NCR_READ_REG(sc, NCR_STAT) & NCRSTAT_INT;
309f1ebad18Smycroft }
310f1ebad18Smycroft 
311f1ebad18Smycroft void
esp_pcmcia_dma_reset(struct ncr53c9x_softc * sc)31278a1d236Stsutsui esp_pcmcia_dma_reset(struct ncr53c9x_softc *sc)
313f1ebad18Smycroft {
314f1ebad18Smycroft 	struct esp_pcmcia_softc *esc = (struct esp_pcmcia_softc *)sc;
315f1ebad18Smycroft 
316f1ebad18Smycroft 	esc->sc_active = 0;
317f1ebad18Smycroft 	esc->sc_tc = 0;
318f1ebad18Smycroft }
319f1ebad18Smycroft 
320f1ebad18Smycroft int
esp_pcmcia_dma_intr(struct ncr53c9x_softc * sc)32178a1d236Stsutsui esp_pcmcia_dma_intr(struct ncr53c9x_softc *sc)
322f1ebad18Smycroft {
323f1ebad18Smycroft 	struct esp_pcmcia_softc *esc = (struct esp_pcmcia_softc *)sc;
32478a1d236Stsutsui 	uint8_t	*p;
325f1ebad18Smycroft 	u_int	espphase, espstat, espintr;
326f1ebad18Smycroft 	int	cnt;
327f1ebad18Smycroft 
328f1ebad18Smycroft 	if (esc->sc_active == 0) {
32978a1d236Stsutsui 		printf("%s: dma_intr--inactive DMA\n",
33078a1d236Stsutsui 		    device_xname(sc->sc_dev));
331f1ebad18Smycroft 		return -1;
332f1ebad18Smycroft 	}
333f1ebad18Smycroft 
334f1ebad18Smycroft 	if ((sc->sc_espintr & NCRINTR_BS) == 0) {
335f1ebad18Smycroft 		esc->sc_active = 0;
336f1ebad18Smycroft 		return 0;
337f1ebad18Smycroft 	}
338f1ebad18Smycroft 
339f1ebad18Smycroft 	cnt = *esc->sc_pdmalen;
340f1ebad18Smycroft 	if (*esc->sc_pdmalen == 0) {
341f1ebad18Smycroft 		printf("%s: data interrupt, but no count left\n",
34278a1d236Stsutsui 		    device_xname(sc->sc_dev));
343f1ebad18Smycroft 	}
344f1ebad18Smycroft 
345f1ebad18Smycroft 	p = *esc->sc_dmaaddr;
346f1ebad18Smycroft 	espphase = sc->sc_phase;
347f1ebad18Smycroft 	espstat = (u_int)sc->sc_espstat;
348f1ebad18Smycroft 	espintr = (u_int)sc->sc_espintr;
349f1ebad18Smycroft 	do {
350f1ebad18Smycroft 		if (esc->sc_datain) {
351f1ebad18Smycroft 			*p++ = NCR_READ_REG(sc, NCR_FIFO);
352f1ebad18Smycroft 			cnt--;
353634d0c97Smycroft 			if (espphase == DATA_IN_PHASE)
354f1ebad18Smycroft 				NCR_WRITE_REG(sc, NCR_CMD, NCRCMD_TRANS);
355634d0c97Smycroft 			else
356f1ebad18Smycroft 				esc->sc_active = 0;
357f1ebad18Smycroft 		} else {
358f1ebad18Smycroft 			if (espphase == DATA_OUT_PHASE ||
359f1ebad18Smycroft 			    espphase == MESSAGE_OUT_PHASE) {
360f1ebad18Smycroft 				NCR_WRITE_REG(sc, NCR_FIFO, *p++);
361f1ebad18Smycroft 				cnt--;
362f1ebad18Smycroft 				NCR_WRITE_REG(sc, NCR_CMD, NCRCMD_TRANS);
363f1ebad18Smycroft 			} else
364f1ebad18Smycroft 				esc->sc_active = 0;
365f1ebad18Smycroft 		}
366f1ebad18Smycroft 
367f1ebad18Smycroft 		if (esc->sc_active) {
36878a1d236Stsutsui 			while ((NCR_READ_REG(sc, NCR_STAT) & NCRSTAT_INT) == 0)
36978a1d236Stsutsui 				;
370f1ebad18Smycroft 			espstat = NCR_READ_REG(sc, NCR_STAT);
371f1ebad18Smycroft 			espintr = NCR_READ_REG(sc, NCR_INTR);
372f1ebad18Smycroft 			espphase = (espintr & NCRINTR_DIS)
373f1ebad18Smycroft 				    ? /* Disconnected */ BUSFREE_PHASE
374f1ebad18Smycroft 				    : espstat & PHASE_MASK;
375f1ebad18Smycroft 		}
376f1ebad18Smycroft 	} while (esc->sc_active && espintr);
377f1ebad18Smycroft 	sc->sc_phase = espphase;
37878a1d236Stsutsui 	sc->sc_espstat = (uint8_t)espstat;
37978a1d236Stsutsui 	sc->sc_espintr = (uint8_t)espintr;
380f1ebad18Smycroft 	*esc->sc_dmaaddr = p;
381f1ebad18Smycroft 	*esc->sc_pdmalen = cnt;
382f1ebad18Smycroft 
383f1ebad18Smycroft 	if (*esc->sc_pdmalen == 0)
384f1ebad18Smycroft 		esc->sc_tc = NCRSTAT_TC;
385f1ebad18Smycroft 	sc->sc_espstat |= esc->sc_tc;
386f1ebad18Smycroft 	return 0;
387f1ebad18Smycroft }
388f1ebad18Smycroft 
389f1ebad18Smycroft int
esp_pcmcia_dma_setup(struct ncr53c9x_softc * sc,uint8_t ** addr,size_t * len,int datain,size_t * dmasize)39078a1d236Stsutsui esp_pcmcia_dma_setup(struct ncr53c9x_softc *sc, uint8_t **addr, size_t *len,
39178a1d236Stsutsui     int datain, size_t *dmasize)
392f1ebad18Smycroft {
393f1ebad18Smycroft 	struct esp_pcmcia_softc *esc = (struct esp_pcmcia_softc *)sc;
394f1ebad18Smycroft 
39578a1d236Stsutsui 	esc->sc_dmaaddr = addr;
396f1ebad18Smycroft 	esc->sc_pdmalen = len;
397f1ebad18Smycroft 	esc->sc_datain = datain;
398f1ebad18Smycroft 	esc->sc_dmasize = *dmasize;
399f1ebad18Smycroft 	esc->sc_tc = 0;
400f1ebad18Smycroft 
401f1ebad18Smycroft 	return 0;
402f1ebad18Smycroft }
403f1ebad18Smycroft 
404f1ebad18Smycroft void
esp_pcmcia_dma_go(struct ncr53c9x_softc * sc)40578a1d236Stsutsui esp_pcmcia_dma_go(struct ncr53c9x_softc *sc)
406f1ebad18Smycroft {
407f1ebad18Smycroft 	struct esp_pcmcia_softc *esc = (struct esp_pcmcia_softc *)sc;
408f1ebad18Smycroft 
409f1ebad18Smycroft 	esc->sc_active = 1;
410f1ebad18Smycroft }
411f1ebad18Smycroft 
412f1ebad18Smycroft void
esp_pcmcia_dma_stop(struct ncr53c9x_softc * sc)413168cd830Schristos esp_pcmcia_dma_stop(struct ncr53c9x_softc *sc)
414f1ebad18Smycroft {
415f1ebad18Smycroft }
416f1ebad18Smycroft 
417f1ebad18Smycroft int
esp_pcmcia_dma_isactive(struct ncr53c9x_softc * sc)418454af1c0Sdsl esp_pcmcia_dma_isactive(struct ncr53c9x_softc *sc)
419f1ebad18Smycroft {
420f1ebad18Smycroft 	struct esp_pcmcia_softc *esc = (struct esp_pcmcia_softc *)sc;
421f1ebad18Smycroft 
42278a1d236Stsutsui 	return esc->sc_active;
423f1ebad18Smycroft }
424