Home | History | Annotate | Line # | Download | only in ppbus
ppbus_conf.c revision 1.2
      1 /* $NetBSD: ppbus_conf.c,v 1.2 2004/01/21 00:33:37 bjh21 Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 1997, 1998, 1999 Nicolas Souchu
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     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.
     15  *
     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
     26  * SUCH DAMAGE.
     27  *
     28  * $FreeBSD: src/sys/dev/ppbus/ppbconf.c,v 1.17.2.1 2000/05/24 00:20:57 n_hibma Exp $
     29  *
     30  */
     31 #include "opt_ppbus.h"
     32 
     33 #include <sys/param.h>
     34 #include <sys/systm.h>
     35 #include <sys/kernel.h>
     36 #include <sys/device.h>
     37 #include <sys/proc.h>
     38 
     39 #include <dev/ppbus/ppbus_1284.h>
     40 #include <dev/ppbus/ppbus_base.h>
     41 #include <dev/ppbus/ppbus_conf.h>
     42 #include <dev/ppbus/ppbus_device.h>
     43 #include <dev/ppbus/ppbus_var.h>
     44 
     45 /* Probe, attach, and detach functions for ppbus. */
     46 static int ppbus_probe __P((struct device *, struct cfdata *, void *));
     47 static void ppbus_attach __P((struct device *, struct device *, void *));
     48 static int ppbus_detach __P((struct device *, int));
     49 
     50 /* Utility function prototypes */
     51 static int ppbus_print_child(void *, const char *);
     52 static int ppbus_search_children(struct device *, struct cfdata *, void *);
     53 
     54 
     55 CFATTACH_DECL(ppbus, sizeof(struct ppbus_softc), ppbus_probe, ppbus_attach,
     56 	ppbus_detach, NULL);
     57 
     58 /* Probe function for ppbus. */
     59 static int
     60 ppbus_probe(struct device * parent, struct cfdata * cf, void * aux)
     61 {
     62 	struct parport_adapter * sc_link = aux;
     63 
     64 	/* Check adapter for consistency */
     65 	if(
     66 		/* Required methods for all parports */
     67 		sc_link->parport_io == NULL ||
     68 		sc_link->parport_exec_microseq == NULL ||
     69 		sc_link->parport_setmode == NULL ||
     70 		sc_link->parport_getmode == NULL ||
     71 		sc_link->parport_read == NULL ||
     72 		sc_link->parport_write == NULL ||
     73 		sc_link->parport_read_ivar == NULL ||
     74 		sc_link->parport_write_ivar == NULL ||
     75 		/* Methods which conditional exist based on capabilities */
     76 		((sc_link->capabilities & PPBUS_HAS_EPP) &&
     77 		(sc_link->parport_reset_epp_timeout == NULL)) ||
     78 		((sc_link->capabilities & PPBUS_HAS_ECP) &&
     79 		(sc_link->parport_ecp_sync == NULL)) ||
     80 		((sc_link->capabilities & PPBUS_HAS_DMA) &&
     81 		(sc_link->parport_dma_malloc == NULL ||
     82 		sc_link->parport_dma_free == NULL)) ||
     83 		((sc_link->capabilities & PPBUS_HAS_INTR) &&
     84 		(sc_link->parport_add_handler == NULL ||
     85 		sc_link->parport_remove_handler == NULL))
     86 		) {
     87 
     88 #ifdef PPBUS_DEBUG
     89 		printf("%s(%s): parport_adaptor is incomplete. Child device "
     90 			"probe failed.\n", __func__, parent->dv_xname);
     91 #endif
     92 		return 0;
     93 	}
     94 	else {
     95 		return 1;
     96 	}
     97 }
     98 
     99 /* Attach function for ppbus. */
    100 static void
    101 ppbus_attach(struct device * parent, struct device * self, void * aux)
    102 {
    103 	struct ppbus_softc * ppbus = (struct ppbus_softc *) self;
    104 	struct parport_adapter * sc_link = aux;
    105 	struct ppbus_attach_args args;
    106 
    107 	printf("\n");
    108 
    109 	/* Initialize config data from adapter (bus + device methods) */
    110 	args.capabilities = ppbus->sc_capabilities = sc_link->capabilities;
    111 	ppbus->ppbus_io = sc_link->parport_io;
    112 	ppbus->ppbus_exec_microseq = sc_link->parport_exec_microseq;
    113 	ppbus->ppbus_reset_epp_timeout = sc_link->
    114 		parport_reset_epp_timeout;
    115 	ppbus->ppbus_setmode = sc_link->parport_setmode;
    116 	ppbus->ppbus_getmode = sc_link->parport_getmode;
    117 	ppbus->ppbus_ecp_sync = sc_link->parport_ecp_sync;
    118 	ppbus->ppbus_read = sc_link->parport_read;
    119 	ppbus->ppbus_write = sc_link->parport_write;
    120         ppbus->ppbus_read_ivar = sc_link->parport_read_ivar;
    121 	ppbus->ppbus_write_ivar = sc_link->parport_write_ivar;
    122 	ppbus->ppbus_dma_malloc = sc_link->parport_dma_malloc;
    123 	ppbus->ppbus_dma_free = sc_link->parport_dma_free;
    124 	ppbus->ppbus_add_handler = sc_link->parport_add_handler;
    125 	ppbus->ppbus_remove_handler = sc_link->parport_remove_handler;
    126 
    127 	/* Initially there is no device owning the bus */
    128 	ppbus->ppbus_owner = NULL;
    129 
    130 	/* Initialize locking structures */
    131 	lockinit(&(ppbus->sc_lock), PPBUSPRI | PCATCH, "ppbuslock", 0,
    132 		LK_NOWAIT);
    133 
    134 	/* Set up bus mode and ieee state */
    135 	ppbus->sc_mode = ppbus->ppbus_getmode(self->dv_parent);
    136 	ppbus->sc_use_ieee = 1;
    137 	ppbus->sc_1284_state = PPBUS_FORWARD_IDLE;
    138 	ppbus->sc_1284_error = PPBUS_NO_ERROR;
    139 
    140 	/* Record device's sucessful attachment */
    141 	ppbus->sc_dev_ok = PPBUS_OK;
    142 
    143 #ifndef DONTPROBE_1284
    144 	/* detect IEEE1284 compliant devices */
    145 	if(ppbus_scan_bus(self)) {
    146 		printf("%s: No IEEE1284 device found.\n", self->dv_xname);
    147 	}
    148 	else {
    149 		printf("%s: IEEE1284 device found.\n", self->dv_xname);
    150 		/*
    151 		 * Detect device ID (interrupts must be disabled because we
    152 		 * cannot do a ltsleep() to wait for it - no context)
    153 		 */
    154 		if(args.capabilities & PPBUS_HAS_INTR) {
    155 			int val = 0;
    156 			if(ppbus_write_ivar(self, PPBUS_IVAR_INTR, &val) != 0) {
    157 				printf(" <problem initializing interrupt "
    158 					"usage>");
    159 			}
    160 		}
    161 		ppbus_pnp_detect(self);
    162 	}
    163 #endif /* !DONTPROBE_1284 */
    164 
    165 	/* Configure child devices */
    166 	SLIST_INIT(&(ppbus->sc_childlist_head));
    167 	config_search(ppbus_search_children, self, &args);
    168 
    169 	return;
    170 }
    171 
    172 /* Detach function for ppbus. */
    173 static int
    174 ppbus_detach(struct device * self, int flag)
    175 {
    176 	struct ppbus_softc * ppbus = (struct ppbus_softc *) self;
    177 	struct ppbus_device_softc * child;
    178 
    179 	if(ppbus->sc_dev_ok != PPBUS_OK) {
    180 		if(!(flag & DETACH_QUIET))
    181 			printf("%s: detach called on unattached device.\n",
    182 				ppbus->sc_dev.dv_xname);
    183 		if(!(flag & DETACH_FORCE))
    184 			return 0;
    185 		if(!(flag & DETACH_QUIET))
    186 			printf("%s: continuing detach (DETACH_FORCE).\n",
    187 				ppbus->sc_dev.dv_xname);
    188 	}
    189 
    190 	if(lockmgr(&(ppbus->sc_lock), LK_DRAIN, NULL)) {
    191 		if(!(flag & DETACH_QUIET))
    192 			printf("%s: error while waiting for lock activity to "
    193 				"end.\n", ppbus->sc_dev.dv_xname);
    194 		if(!(flag & DETACH_FORCE))
    195 			return 0;
    196 		if(!(flag & DETACH_QUIET))
    197 			printf("%s: continuing detach (DETACH_FORCE).\n",
    198 				ppbus->sc_dev.dv_xname);
    199 	}
    200 
    201 	/* Detach children devices */
    202 	while(!SLIST_EMPTY(&(ppbus->sc_childlist_head))) {
    203 		child = SLIST_FIRST(&(ppbus->sc_childlist_head));
    204 		config_deactivate((struct device *)child);
    205 		if(config_detach((struct device *)child, flag)) {
    206 			if(!(flag & DETACH_QUIET))
    207 				printf("%s: error detaching %s.",
    208 					ppbus->sc_dev.dv_xname,
    209 					child->sc_dev.dv_xname);
    210 			if(!(flag & DETACH_FORCE))
    211 				return 0;
    212 			if(!(flag & DETACH_QUIET))
    213 				printf("%s: continuing (DETACH_FORCE).\n",
    214 					ppbus->sc_dev.dv_xname);
    215 		}
    216 		SLIST_REMOVE_HEAD(&(ppbus->sc_childlist_head), entries);
    217 	}
    218 
    219 	if(!(flag & DETACH_QUIET))
    220 		printf("%s: detached.\n", ppbus->sc_dev.dv_xname);
    221 
    222 	return 1;
    223 }
    224 
    225 
    226 /* Utility functions */
    227 
    228 /* Used by config_found_sm() to print out result of child probe */
    229 static int
    230 ppbus_print_child(void * aux, const char * name)
    231 {
    232 	if(name != NULL) {
    233 		printf("%s: child devices", name);
    234 		return UNCONF;
    235 	}
    236 	else {
    237 		return QUIET;
    238 	}
    239 }
    240 
    241 /* Search for children device and add to list */
    242 static int
    243 ppbus_search_children(struct device * parent, struct cfdata * cf, void * aux)
    244 {
    245 	struct ppbus_softc * ppbus = (struct ppbus_softc *) parent;
    246 	struct ppbus_device_softc * child;
    247 	int rval = 0;
    248 
    249 	if(config_match(parent, cf, aux) > 0) {
    250 		child = (struct ppbus_device_softc *) config_attach(parent,
    251 			cf, aux, ppbus_print_child);
    252 		if(child) {
    253 			SLIST_INSERT_HEAD(&(ppbus->sc_childlist_head), child,
    254 				entries);
    255 			rval = 1;
    256 		}
    257 	}
    258 
    259 	return rval;
    260 }
    261 
    262