1 /* $NetBSD: ppbus_conf.c,v 1.17 2009/11/07 00:05:49 dyoung Exp $ */
4 * Copyright (c) 1997, 1998, 1999 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/dev/ppbus/ppbconf.c,v 1.17.2.1 2000/05/24 00:20:57 n_hibma Exp
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: ppbus_conf.c,v 1.17 2009/11/07 00:05:49 dyoung Exp $");
35 #include "opt_ppbus.h"
36 #include "opt_ppbus_1284.h"
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/device.h>
46 #include <dev/ppbus/ppbus_1284.h>
47 #include <dev/ppbus/ppbus_base.h>
48 #include <dev/ppbus/ppbus_conf.h>
49 #include <dev/ppbus/ppbus_device.h>
50 #include <dev/ppbus/ppbus_var.h>
52 /* Probe, attach, and detach functions for ppbus. */
53 static int ppbus_probe(device_t
, cfdata_t
, void *);
54 static void ppbus_attach(device_t
, device_t
, void *);
55 static void ppbus_childdet(device_t
, device_t
);
56 static int ppbus_detach(device_t
, int);
58 /* Utility function prototypes */
59 static int ppbus_search_children(device_t
, cfdata_t
,
63 CFATTACH_DECL2_NEW(ppbus
, sizeof(struct ppbus_softc
), ppbus_probe
, ppbus_attach
,
64 ppbus_detach
, NULL
, NULL
, ppbus_childdet
);
66 /* Probe function for ppbus. */
68 ppbus_probe(device_t parent
, cfdata_t cf
, void *aux
)
70 struct parport_adapter
*sc_link
= aux
;
72 /* Check adapter for consistency */
74 /* Required methods for all parports */
75 sc_link
->parport_io
== NULL
||
76 sc_link
->parport_exec_microseq
== NULL
||
77 sc_link
->parport_setmode
== NULL
||
78 sc_link
->parport_getmode
== NULL
||
79 sc_link
->parport_read
== NULL
||
80 sc_link
->parport_write
== NULL
||
81 sc_link
->parport_read_ivar
== NULL
||
82 sc_link
->parport_write_ivar
== NULL
||
83 /* Methods which conditional exist based on capabilities */
84 ((sc_link
->capabilities
& PPBUS_HAS_EPP
) &&
85 (sc_link
->parport_reset_epp_timeout
== NULL
)) ||
86 ((sc_link
->capabilities
& PPBUS_HAS_ECP
) &&
87 (sc_link
->parport_ecp_sync
== NULL
)) ||
88 ((sc_link
->capabilities
& PPBUS_HAS_DMA
) &&
89 (sc_link
->parport_dma_malloc
== NULL
||
90 sc_link
->parport_dma_free
== NULL
)) ||
91 ((sc_link
->capabilities
& PPBUS_HAS_INTR
) &&
92 (sc_link
->parport_add_handler
== NULL
||
93 sc_link
->parport_remove_handler
== NULL
))
97 printf("%s(%s): parport_adaptor is incomplete. Child device "
98 "probe failed.\n", __func__
, device_xname(parent
));
106 /* Attach function for ppbus. */
108 ppbus_attach(device_t parent
, device_t self
, void *aux
)
110 struct ppbus_softc
*ppbus
= device_private(self
);
111 struct parport_adapter
*sc_link
= aux
;
112 struct ppbus_attach_args args
;
116 /* Initialize config data from adapter (bus + device methods) */
117 ppbus
->sc_dev
= self
;
118 args
.capabilities
= ppbus
->sc_capabilities
= sc_link
->capabilities
;
119 ppbus
->ppbus_io
= sc_link
->parport_io
;
120 ppbus
->ppbus_exec_microseq
= sc_link
->parport_exec_microseq
;
121 ppbus
->ppbus_reset_epp_timeout
= sc_link
->
122 parport_reset_epp_timeout
;
123 ppbus
->ppbus_setmode
= sc_link
->parport_setmode
;
124 ppbus
->ppbus_getmode
= sc_link
->parport_getmode
;
125 ppbus
->ppbus_ecp_sync
= sc_link
->parport_ecp_sync
;
126 ppbus
->ppbus_read
= sc_link
->parport_read
;
127 ppbus
->ppbus_write
= sc_link
->parport_write
;
128 ppbus
->ppbus_read_ivar
= sc_link
->parport_read_ivar
;
129 ppbus
->ppbus_write_ivar
= sc_link
->parport_write_ivar
;
130 ppbus
->ppbus_dma_malloc
= sc_link
->parport_dma_malloc
;
131 ppbus
->ppbus_dma_free
= sc_link
->parport_dma_free
;
132 ppbus
->ppbus_add_handler
= sc_link
->parport_add_handler
;
133 ppbus
->ppbus_remove_handler
= sc_link
->parport_remove_handler
;
135 /* Initially there is no device owning the bus */
136 ppbus
->ppbus_owner
= NULL
;
138 /* Initialize locking structures */
139 mutex_init(&(ppbus
->sc_lock
), MUTEX_DEFAULT
, IPL_NONE
);
141 /* Set up bus mode and ieee state */
142 ppbus
->sc_mode
= ppbus
->ppbus_getmode(device_parent(self
));
143 ppbus
->sc_use_ieee
= 1;
144 ppbus
->sc_1284_state
= PPBUS_FORWARD_IDLE
;
145 ppbus
->sc_1284_error
= PPBUS_NO_ERROR
;
147 /* Record device's sucessful attachment */
148 ppbus
->sc_dev_ok
= PPBUS_OK
;
150 #ifndef DONTPROBE_1284
151 /* detect IEEE1284 compliant devices */
152 if (ppbus_scan_bus(self
)) {
153 printf("%s: No IEEE1284 device found.\n", device_xname(self
));
155 printf("%s: IEEE1284 device found.\n", device_xname(self
));
157 * Detect device ID (interrupts must be disabled because we
158 * cannot do a ltsleep() to wait for it - no context)
160 if (args
.capabilities
& PPBUS_HAS_INTR
) {
162 if(ppbus_write_ivar(self
, PPBUS_IVAR_INTR
, &val
) != 0) {
163 printf(" <problem initializing interrupt "
167 ppbus_pnp_detect(self
);
169 #endif /* !DONTPROBE_1284 */
171 /* Configure child devices */
172 SLIST_INIT(&(ppbus
->sc_childlist_head
));
173 config_search_ia(ppbus_search_children
, self
, "ppbus", &args
);
176 gpio_ppbus_attach(ppbus
);
182 ppbus_childdet(device_t self
, device_t target
)
184 struct ppbus_softc
* ppbus
= device_private(self
);
185 struct ppbus_device_softc
* child
;
187 SLIST_FOREACH(child
, &ppbus
->sc_childlist_head
, entries
) {
188 if (child
->sc_dev
== target
)
192 SLIST_REMOVE(&ppbus
->sc_childlist_head
, child
,
193 ppbus_device_softc
, entries
);
196 /* Detach function for ppbus. */
198 ppbus_detach(device_t self
, int flag
)
200 struct ppbus_softc
* ppbus
= device_private(self
);
201 struct ppbus_device_softc
* child
;
203 if (ppbus
->sc_dev_ok
!= PPBUS_OK
) {
204 if (!(flag
& DETACH_QUIET
))
205 printf("%s: detach called on unattached device.\n",
206 device_xname(ppbus
->sc_dev
));
207 if (!(flag
& DETACH_FORCE
))
209 if (!(flag
& DETACH_QUIET
))
210 printf("%s: continuing detach (DETACH_FORCE).\n",
211 device_xname(ppbus
->sc_dev
));
214 mutex_destroy(&(ppbus
->sc_lock
));
216 /* Detach children devices */
217 while ((child
= SLIST_FIRST(&ppbus
->sc_childlist_head
)) != NULL
) {
218 if (config_detach(child
->sc_dev
, flag
)) {
219 if(!(flag
& DETACH_QUIET
))
220 aprint_error_dev(ppbus
->sc_dev
, "error detaching %s.",
221 device_xname(child
->sc_dev
));
222 if(!(flag
& DETACH_FORCE
))
224 if(!(flag
& DETACH_QUIET
))
225 printf("%s: continuing (DETACH_FORCE).\n",
226 device_xname(ppbus
->sc_dev
));
230 if (!(flag
& DETACH_QUIET
))
231 printf("%s: detached.\n", device_xname(ppbus
->sc_dev
));
236 /* Search for children device and add to list */
238 ppbus_search_children(device_t parent
, cfdata_t cf
,
239 const int *ldesc
, void *aux
)
241 struct ppbus_softc
*ppbus
= device_private(parent
);
242 struct ppbus_device_softc
*child
;
245 if (config_match(parent
, cf
, aux
) > 0) {
246 child
= (struct ppbus_device_softc
*) config_attach(parent
,
249 SLIST_INSERT_HEAD(&(ppbus
->sc_childlist_head
), child
,