1 /* $NetBSD: atppc_isa.c,v 1.13 2008/04/15 15:02:28 cegger Exp $ */
4 * Copyright (c) 2001 Alcove - Nicolas Souchu
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * FreeBSD: src/sys/isa/ppc.c,v 1.26.2.5 2001/10/02 05:21:45 nsouch Exp
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: atppc_isa.c,v 1.13 2008/04/15 15:02:28 cegger Exp $");
35 #include "opt_atppc.h"
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/device.h>
46 #include <dev/isa/isareg.h>
47 #include <dev/isa/isavar.h>
48 #include <dev/isa/isadmavar.h>
50 #include <dev/ic/atppcreg.h>
51 #include <dev/ic/atppcvar.h>
52 #include <dev/isa/atppc_isadma.h>
55 * ISA bus attach code for atppc driver.
56 * Note on capabilities: capabilites may exist in the chipset but may not
57 * necessarily be useable. I.e. you may specify an IRQ in the autoconfig, but
58 * will the port actually have an IRQ assigned to it at the hardware level?
59 * How can you test if the capabilites can be used? For interrupts, see if a
60 * handler exists (sc_intr != NULL). For DMA, see if the sc_dma_start() and
61 * sc_dma_finish() function pointers are not NULL.
64 /* Configuration data for atppc on isa bus. */
65 struct atppc_isa_softc
{
66 /* Machine independent device data */
67 struct atppc_softc sc_atppc
;
69 /* IRQ/DRQ/IO Port assignments on ISA bus */
75 isa_chipset_tag_t sc_ic
;
78 /* Probe and attach functions for a atppc device on the ISA bus. */
79 static int atppc_isa_probe(device_t
, cfdata_t
, void *);
80 static void atppc_isa_attach(device_t
, device_t
, void *);
82 static int atppc_isa_dma_start(struct atppc_softc
*, void *, u_int
,
84 static int atppc_isa_dma_finish(struct atppc_softc
*);
85 static int atppc_isa_dma_abort(struct atppc_softc
*);
86 static int atppc_isa_dma_malloc(device_t
, void **, bus_addr_t
*,
88 static void atppc_isa_dma_free(device_t
, void **, bus_addr_t
*,
91 CFATTACH_DECL_NEW(atppc_isa
, sizeof(struct atppc_isa_softc
), atppc_isa_probe
,
92 atppc_isa_attach
, NULL
, NULL
);
95 * Probe function: find parallel port controller on isa bus. Combined from
96 * lpt_isa_probe() in lpt.c and atppc_detect_port() from FreeBSD's ppc.c.
99 atppc_isa_probe(device_t parent
, cfdata_t cf
, void *aux
)
101 bus_space_handle_t ioh
;
102 struct isa_attach_args
*ia
= aux
;
103 bus_space_tag_t iot
= ia
->ia_iot
;
109 /* Disallow wildcarded i/o address */
110 if (ia
->ia_io
[0].ir_addr
== ISA_UNKNOWN_PORT
)
113 if (bus_space_map(iot
, ia
->ia_io
[0].ir_addr
, IO_LPTSIZE
, 0, &ioh
))
116 if (atppc_detect_port(iot
, ioh
) == 0)
119 bus_space_unmap(iot
, ioh
, IO_LPTSIZE
);
123 ia
->ia_io
[0].ir_size
= IO_LPTSIZE
;
131 /* Attach function: attach and configure parallel port controller on isa bus. */
133 atppc_isa_attach(device_t parent
, device_t self
, void *aux
)
135 struct atppc_isa_softc
*sc
= device_private(self
);
136 struct atppc_softc
*lsc
= &sc
->sc_atppc
;
137 struct isa_attach_args
*ia
= aux
;
139 printf(": AT Parallel Port\n");
141 lsc
->sc_iot
= ia
->ia_iot
;
142 lsc
->sc_dmat
= ia
->ia_dmat
;
144 sc
->sc_ic
= ia
->ia_ic
;
145 sc
->sc_iobase
= ia
->ia_io
->ir_addr
;
147 if (bus_space_map(lsc
->sc_iot
, sc
->sc_iobase
, IO_LPTSIZE
, 0,
148 &lsc
->sc_ioh
) != 0) {
149 aprint_error_dev(self
, "attempt to map bus space failed, device not "
150 "properly attached.\n");
151 lsc
->sc_dev_ok
= ATPPC_NOATTACH
;
156 lsc
->sc_dev_ok
= ATPPC_ATTACHED
;
158 /* Assign interrupt handler */
159 if (!(device_cfdata(self
)->cf_flags
& ATPPC_FLAG_DISABLE_INTR
)
160 && ia
->ia_irq
->ir_irq
!= ISA_UNKNOWN_IRQ
161 && ia
->ia_nirq
>= 1) {
162 sc
->sc_irq
= ia
->ia_irq
[0].ir_irq
;
166 if (sc
->sc_irq
> 0) {
167 /* Establish interrupt handler. */
168 lsc
->sc_ieh
= isa_intr_establish(sc
->sc_ic
, sc
->sc_irq
,
169 IST_EDGE
, IPL_ATPPC
, atppcintr
, lsc
->sc_dev
);
171 lsc
->sc_has
|= ATPPC_HAS_INTR
;
175 if (!(device_cfdata(self
)->cf_flags
& ATPPC_FLAG_DISABLE_DMA
)
176 && ia
->ia_drq
->ir_drq
!= ISA_UNKNOWN_DRQ
178 sc
->sc_drq
= ia
->ia_drq
[0].ir_drq
;
183 && atppc_isadma_setup(lsc
, sc
->sc_ic
, sc
->sc_drq
) == 0) {
184 lsc
->sc_has
|= ATPPC_HAS_DMA
;
186 /* setup DMA hooks */
187 lsc
->sc_dma_start
= atppc_isa_dma_start
;
188 lsc
->sc_dma_finish
= atppc_isa_dma_finish
;
189 lsc
->sc_dma_abort
= atppc_isa_dma_abort
;
190 lsc
->sc_dma_malloc
= atppc_isa_dma_malloc
;
191 lsc
->sc_dma_free
= atppc_isa_dma_free
;
194 /* Run soft configuration attach */
195 atppc_sc_attach(lsc
);
200 /* Start DMA operation over ISA bus */
202 atppc_isa_dma_start(struct atppc_softc
*lsc
, void *buf
, u_int nbytes
,
205 struct atppc_isa_softc
*sc
= (struct atppc_isa_softc
*) lsc
;
207 return atppc_isadma_start(sc
->sc_ic
, sc
->sc_drq
, buf
, nbytes
, mode
);
210 /* Stop DMA operation over ISA bus */
212 atppc_isa_dma_finish(struct atppc_softc
*lsc
)
214 struct atppc_isa_softc
*sc
= (struct atppc_isa_softc
*) lsc
;
216 return atppc_isadma_finish(sc
->sc_ic
, sc
->sc_drq
);
219 /* Abort DMA operation over ISA bus */
221 atppc_isa_dma_abort(struct atppc_softc
*lsc
)
223 struct atppc_isa_softc
*sc
= (struct atppc_isa_softc
*) lsc
;
225 return atppc_isadma_abort(sc
->sc_ic
, sc
->sc_drq
);
228 /* Allocate memory for DMA over ISA bus */
230 atppc_isa_dma_malloc(device_t dev
, void **buf
, bus_addr_t
*bus_addr
,
233 struct atppc_isa_softc
*sc
= device_private(dev
);
235 return atppc_isadma_malloc(sc
->sc_ic
, sc
->sc_drq
, buf
, bus_addr
, size
);
238 /* Free memory allocated by atppc_isa_dma_malloc() */
240 atppc_isa_dma_free(device_t dev
, void **buf
, bus_addr_t
*bus_addr
,
243 struct atppc_isa_softc
*sc
= device_private(dev
);
245 return atppc_isadma_free(sc
->sc_ic
, sc
->sc_drq
, buf
, bus_addr
, size
);