amps.c revision 1.6
11.6Sthorpej/*	$NetBSD: amps.c,v 1.6 2002/10/02 03:31:59 thorpej Exp $	*/
21.1Sreinoud
31.1Sreinoud/*-
41.1Sreinoud * Copyright (c) 1997 The NetBSD Foundation, Inc.
51.1Sreinoud * All rights reserved.
61.1Sreinoud *
71.1Sreinoud * This code is derived from software contributed to The NetBSD Foundation
81.1Sreinoud * by Mark Brinicombe of Causality Limited.
91.1Sreinoud *
101.1Sreinoud * Redistribution and use in source and binary forms, with or without
111.1Sreinoud * modification, are permitted provided that the following conditions
121.1Sreinoud * are met:
131.1Sreinoud * 1. Redistributions of source code must retain the above copyright
141.1Sreinoud *    notice, this list of conditions and the following disclaimer.
151.1Sreinoud * 2. Redistributions in binary form must reproduce the above copyright
161.1Sreinoud *    notice, this list of conditions and the following disclaimer in the
171.1Sreinoud *    documentation and/or other materials provided with the distribution.
181.1Sreinoud * 3. All advertising materials mentioning features or use of this software
191.1Sreinoud *    must display the following acknowledgement:
201.1Sreinoud *	This product includes software developed by the NetBSD
211.1Sreinoud *	Foundation, Inc. and its contributors.
221.1Sreinoud * 4. Neither the name of The NetBSD Foundation nor the names of its
231.1Sreinoud *    contributors may be used to endorse or promote products derived
241.1Sreinoud *    from this software without specific prior written permission.
251.1Sreinoud *
261.1Sreinoud * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
271.1Sreinoud * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
281.1Sreinoud * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
291.1Sreinoud * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
301.1Sreinoud * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
311.1Sreinoud * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
321.1Sreinoud * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
331.1Sreinoud * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
341.1Sreinoud * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
351.1Sreinoud * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
361.1Sreinoud * POSSIBILITY OF SUCH DAMAGE.
371.1Sreinoud *
381.1Sreinoud * Card driver and probe and attach functions to use generic 16550 com
391.1Sreinoud * driver for the Atomwide multiport serial podule
401.1Sreinoud */
411.1Sreinoud
421.1Sreinoud/*
431.1Sreinoud * Thanks to Martin Coulson, Atomwide, for providing the hardware
441.1Sreinoud */
451.1Sreinoud
461.1Sreinoud#include <sys/param.h>
471.1Sreinoud#include <sys/systm.h>
481.1Sreinoud#include <sys/ioctl.h>
491.1Sreinoud#include <sys/select.h>
501.1Sreinoud#include <sys/tty.h>
511.1Sreinoud#include <sys/proc.h>
521.1Sreinoud#include <sys/user.h>
531.1Sreinoud#include <sys/conf.h>
541.1Sreinoud#include <sys/file.h>
551.1Sreinoud#include <sys/uio.h>
561.1Sreinoud#include <sys/kernel.h>
571.1Sreinoud#include <sys/syslog.h>
581.1Sreinoud#include <sys/types.h>
591.1Sreinoud#include <sys/device.h>
601.1Sreinoud
611.2Sthorpej#include <machine/intr.h>
621.1Sreinoud#include <machine/io.h>
631.1Sreinoud#include <machine/bus.h>
641.1Sreinoud#include <acorn32/podulebus/podulebus.h>
651.1Sreinoud#include <acorn32/podulebus/ampsreg.h>
661.1Sreinoud#include <dev/ic/comreg.h>
671.1Sreinoud#include <dev/ic/comvar.h>
681.1Sreinoud#include <dev/podulebus/podules.h>
691.1Sreinoud
701.1Sreinoud#include "locators.h"
711.1Sreinoud
721.1Sreinoud/*
731.1Sreinoud * Atomwide Mulit-port serial podule device.
741.1Sreinoud *
751.1Sreinoud * This probes and attaches the top level multi-port serial device to the
761.1Sreinoud * podulebus. It then configures the child com devices.
771.1Sreinoud */
781.1Sreinoud
791.1Sreinoud/*
801.1Sreinoud * Atomwide Multi-port serial card softc structure.
811.1Sreinoud *
821.1Sreinoud * Contains the device node, podule information and global information
831.1Sreinoud * required by the driver such as the card version and the interrupt mask.
841.1Sreinoud */
851.1Sreinoud
861.1Sreinoudstruct amps_softc {
871.1Sreinoud	struct device		sc_dev;			/* device node */
881.1Sreinoud	podule_t 		*sc_podule;		/* Our podule info */
891.1Sreinoud	int 			sc_podule_number;	/* Our podule number */
901.1Sreinoud	bus_space_tag_t		sc_iot;			/* Bus tag */
911.1Sreinoud};
921.1Sreinoud
931.1Sreinoudint	amps_probe	__P((struct device *, struct cfdata *, void *));
941.1Sreinoudvoid	amps_attach	__P((struct device *, struct device *, void *));
951.1Sreinoudvoid	amps_shutdown	__P((void *arg));
961.1Sreinoud
971.5SthorpejCFATTACH_DECL(amps, sizeof(struct amps_softc),
981.6Sthorpej    amps_probe, amps_attach, NULL, NULL);
991.1Sreinoud
1001.1Sreinoud/*
1011.1Sreinoud * Attach arguments for child devices.
1021.1Sreinoud * Pass the podule details, the parent softc and the channel
1031.1Sreinoud */
1041.1Sreinoud
1051.1Sreinoudstruct amps_attach_args {
1061.1Sreinoud	bus_space_tag_t aa_iot;			/* bus space tag */
1071.1Sreinoud	unsigned int aa_base;			/* base address for port */
1081.1Sreinoud	int aa_port;      			/* serial port number */
1091.1Sreinoud	podulebus_intr_handle_t aa_irq;		/* IRQ number */
1101.1Sreinoud};
1111.1Sreinoud
1121.1Sreinoud/*
1131.1Sreinoud * Define prototypes for custom bus space functions.
1141.1Sreinoud */
1151.1Sreinoud
1161.1Sreinoud/* Print function used during child config */
1171.1Sreinoud
1181.1Sreinoudint
1191.1Sreinoudamps_print(aux, name)
1201.1Sreinoud	void *aux;
1211.1Sreinoud	const char *name;
1221.1Sreinoud{
1231.1Sreinoud	struct amps_attach_args *aa = aux;
1241.1Sreinoud
1251.1Sreinoud	if (!name)
1261.1Sreinoud		printf(", port %d", aa->aa_port);
1271.1Sreinoud
1281.1Sreinoud	return(QUIET);
1291.1Sreinoud}
1301.1Sreinoud
1311.1Sreinoud/*
1321.1Sreinoud * Card probe function
1331.1Sreinoud *
1341.1Sreinoud * Just match the manufacturer and podule ID's
1351.1Sreinoud */
1361.1Sreinoud
1371.1Sreinoudint
1381.1Sreinoudamps_probe(parent, cf, aux)
1391.1Sreinoud	struct device *parent;
1401.1Sreinoud	struct cfdata *cf;
1411.1Sreinoud	void *aux;
1421.1Sreinoud{
1431.1Sreinoud	struct podule_attach_args *pa = (void *)aux;
1441.1Sreinoud
1451.3Sbjh21	return (pa->pa_product == PODULE_ATOMWIDE_SERIAL);
1461.1Sreinoud}
1471.1Sreinoud
1481.1Sreinoud/*
1491.1Sreinoud * Card attach function
1501.1Sreinoud *
1511.1Sreinoud * Identify the card version and configure any children.
1521.1Sreinoud * Install a shutdown handler to kill interrupts on shutdown
1531.1Sreinoud */
1541.1Sreinoud
1551.1Sreinoudvoid
1561.1Sreinoudamps_attach(parent, self, aux)
1571.1Sreinoud	struct device *parent, *self;
1581.1Sreinoud	void *aux;
1591.1Sreinoud{
1601.1Sreinoud	struct amps_softc *sc = (void *)self;
1611.1Sreinoud	struct podule_attach_args *pa = (void *)aux;
1621.1Sreinoud	struct amps_attach_args aa;
1631.1Sreinoud
1641.1Sreinoud	/* Note the podule number and validate */
1651.1Sreinoud
1661.1Sreinoud	if (pa->pa_podule_number == -1)
1671.1Sreinoud		panic("Podule has disappeared !");
1681.1Sreinoud
1691.1Sreinoud	sc->sc_podule_number = pa->pa_podule_number;
1701.1Sreinoud	sc->sc_podule = pa->pa_podule;
1711.1Sreinoud	podules[sc->sc_podule_number].attached = 1;
1721.1Sreinoud
1731.1Sreinoud	sc->sc_iot = pa->pa_iot;
1741.1Sreinoud
1751.1Sreinoud	/* Install a clean up handler to make sure IRQ's are disabled */
1761.1Sreinoud/*	if (shutdownhook_establish(amps_shutdown, (void *)sc) == NULL)
1771.1Sreinoud		panic("%s: Cannot install shutdown handler", self->dv_xname);*/
1781.1Sreinoud
1791.1Sreinoud	/* Set the interrupt info for this podule */
1801.1Sreinoud
1811.1Sreinoud/*	sc->sc_podule->irq_addr = pa->pa_podule->slow_base +;*/	/* XXX */
1821.1Sreinoud/*	sc->sc_podule->irq_mask = ;*/
1831.1Sreinoud
1841.1Sreinoud	printf("\n");
1851.1Sreinoud
1861.1Sreinoud	/* Configure the children */
1871.1Sreinoud
1881.1Sreinoud	aa.aa_iot = sc->sc_iot;
1891.1Sreinoud	aa.aa_base = pa->pa_podule->slow_base + AMPS_BASE_OFFSET;
1901.1Sreinoud	aa.aa_base += MAX_AMPS_PORTS * AMPS_PORT_SPACING;
1911.1Sreinoud	aa.aa_irq = pa->pa_podule->interrupt;
1921.1Sreinoud	for (aa.aa_port = 0; aa.aa_port < MAX_AMPS_PORTS; ++aa.aa_port) {
1931.1Sreinoud		aa.aa_base -= AMPS_PORT_SPACING;
1941.1Sreinoud		config_found_sm(self, &aa, amps_print, NULL);
1951.1Sreinoud	}
1961.1Sreinoud}
1971.1Sreinoud
1981.1Sreinoud/*
1991.1Sreinoud * Card shutdown function
2001.1Sreinoud *
2011.1Sreinoud * Called via do_shutdown_hooks() during kernel shutdown.
2021.1Sreinoud * Clear the cards's interrupt mask to stop any podule interrupts.
2031.1Sreinoud */
2041.1Sreinoud
2051.1Sreinoud/*void
2061.1Sreinoudamps_shutdown(arg)
2071.1Sreinoud	void *arg;
2081.1Sreinoud{
2091.1Sreinoud}*/
2101.1Sreinoud
2111.1Sreinoud/*
2121.1Sreinoud * Atomwide Multi-Port Serial probe and attach code for the com device.
2131.1Sreinoud *
2141.1Sreinoud * This provides a different pair of probe and attach functions
2151.1Sreinoud * for attaching the com device (dev/ic/com.c) to the Atomwide serial card.
2161.1Sreinoud */
2171.1Sreinoud
2181.1Sreinoudstruct com_amps_softc {
2191.1Sreinoud	struct	com_softc sc_com;	/* real "com" softc */
2201.1Sreinoud	void	*sc_ih;			/* interrupt handler */
2211.1Sreinoud	struct	evcnt sc_intrcnt;	/* interrupt count */
2221.1Sreinoud};
2231.1Sreinoud
2241.1Sreinoud/* Prototypes for functions */
2251.1Sreinoud
2261.1Sreinoudstatic int  com_amps_probe   __P((struct device *, struct cfdata *, void *));
2271.1Sreinoudstatic void com_amps_attach  __P((struct device *, struct device *, void *));
2281.1Sreinoud
2291.1Sreinoud/* device attach structure */
2301.1Sreinoud
2311.5SthorpejCFATTACH_DECL(com_amps, sizeof(struct com_amps_softc),
2321.5Sthorpej	com_amps_probe, com_amps_attach, NULL, NULL);
2331.1Sreinoud
2341.1Sreinoud/*
2351.1Sreinoud * Controller probe function
2361.1Sreinoud *
2371.1Sreinoud * Map all the required I/O space for this channel, make sure interrupts
2381.1Sreinoud * are disabled and probe the bus.
2391.1Sreinoud */
2401.1Sreinoud
2411.1Sreinoudint
2421.1Sreinoudcom_amps_probe(parent, cf, aux)
2431.1Sreinoud	struct device *parent;
2441.1Sreinoud	struct cfdata *cf;
2451.1Sreinoud	void *aux;
2461.1Sreinoud{
2471.1Sreinoud	bus_space_tag_t iot;
2481.1Sreinoud	bus_space_handle_t ioh;
2491.1Sreinoud	int iobase;
2501.1Sreinoud	int rv = 1;
2511.1Sreinoud	struct amps_attach_args *aa = aux;
2521.1Sreinoud
2531.1Sreinoud	iot = aa->aa_iot;
2541.1Sreinoud	iobase = aa->aa_base;
2551.1Sreinoud
2561.1Sreinoud	/* if it's in use as console, it's there. */
2571.1Sreinoud	if (!com_is_console(iot, iobase, 0)) {
2581.1Sreinoud		if (bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh)) {
2591.1Sreinoud			return 0;
2601.1Sreinoud		}
2611.1Sreinoud		/*
2621.1Sreinoud		 * We don't use the generic comprobe1() function as it
2631.1Sreinoud		 * is not good enough to identify which ports are present.
2641.1Sreinoud		 *
2651.1Sreinoud		 * Instead test for the presence of the scratch register
2661.1Sreinoud		 */
2671.1Sreinoud
2681.1Sreinoud		bus_space_write_1(iot, ioh, com_scratch, 0x55);
2691.1Sreinoud		bus_space_write_1(iot, ioh, com_ier, 0);
2701.1Sreinoud		(void)bus_space_read_1(iot, ioh, com_data);
2711.1Sreinoud		if (bus_space_read_1(iot, ioh, com_scratch) != 0x55)
2721.1Sreinoud			rv = 0;
2731.1Sreinoud		bus_space_write_1(iot, ioh, com_scratch, 0xaa);
2741.1Sreinoud		bus_space_write_1(iot, ioh, com_ier, 0);
2751.1Sreinoud		(void)bus_space_read_1(iot, ioh, com_data);
2761.1Sreinoud		if (bus_space_read_1(iot, ioh, com_scratch) != 0xaa)
2771.1Sreinoud			rv = 0;
2781.1Sreinoud
2791.1Sreinoud		bus_space_unmap(iot, ioh, COM_NPORTS);
2801.1Sreinoud	}
2811.1Sreinoud	return (rv);
2821.1Sreinoud}
2831.1Sreinoud
2841.1Sreinoud/*
2851.1Sreinoud * Controller attach function
2861.1Sreinoud *
2871.1Sreinoud * Map all the required I/O space for this port and attach the driver
2881.1Sreinoud * The generic attach will probe and attach any device.
2891.1Sreinoud * Install an interrupt handler and we are ready to rock.
2901.1Sreinoud */
2911.1Sreinoud
2921.1Sreinoudvoid
2931.1Sreinoudcom_amps_attach(parent, self, aux)
2941.1Sreinoud	struct device *parent, *self;
2951.1Sreinoud	void *aux;
2961.1Sreinoud{
2971.1Sreinoud	struct com_amps_softc *asc = (void *)self;
2981.1Sreinoud	struct com_softc *sc = &asc->sc_com;
2991.1Sreinoud	u_int iobase;
3001.1Sreinoud	bus_space_tag_t iot;
3011.1Sreinoud	struct amps_attach_args *aa = aux;
3021.1Sreinoud
3031.1Sreinoud	iot = sc->sc_iot = aa->aa_iot;
3041.1Sreinoud	iobase = sc->sc_iobase = aa->aa_base;
3051.1Sreinoud
3061.1Sreinoud	if (!com_is_console(iot, iobase, &sc->sc_ioh)
3071.1Sreinoud		&& bus_space_map(iot, iobase, COM_NPORTS, 0, &sc->sc_ioh))
3081.1Sreinoud			panic("comattach: io mapping failed");
3091.1Sreinoud
3101.1Sreinoud	sc->sc_frequency = AMPS_FREQ;
3111.1Sreinoud	com_attach_subr(sc);
3121.1Sreinoud
3131.1Sreinoud	evcnt_attach_dynamic(&asc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
3141.1Sreinoud	    self->dv_xname, "intr");
3151.1Sreinoud	asc->sc_ih = podulebus_irq_establish(aa->aa_irq, IPL_SERIAL, comintr,
3161.1Sreinoud	    sc, &asc->sc_intrcnt);
3171.1Sreinoud}
318