amps.c revision 1.8
11.8Sthorpej/*	$NetBSD: amps.c,v 1.8 2003/01/01 00:25:02 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.7Schsint	amps_probe(struct device *, struct cfdata *, void *);
941.7Schsvoid	amps_attach(struct device *, struct device *, void *);
951.1Sreinoud
961.5SthorpejCFATTACH_DECL(amps, sizeof(struct amps_softc),
971.6Sthorpej    amps_probe, amps_attach, NULL, NULL);
981.7Schs
991.7Schsint	amps_print(void *, const char *);
1001.7Schsvoid	amps_shutdown(void *);
1011.1Sreinoud
1021.1Sreinoud/*
1031.1Sreinoud * Attach arguments for child devices.
1041.1Sreinoud * Pass the podule details, the parent softc and the channel
1051.1Sreinoud */
1061.1Sreinoud
1071.1Sreinoudstruct amps_attach_args {
1081.1Sreinoud	bus_space_tag_t aa_iot;			/* bus space tag */
1091.1Sreinoud	unsigned int aa_base;			/* base address for port */
1101.1Sreinoud	int aa_port;      			/* serial port number */
1111.1Sreinoud	podulebus_intr_handle_t aa_irq;		/* IRQ number */
1121.1Sreinoud};
1131.1Sreinoud
1141.1Sreinoud/*
1151.1Sreinoud * Define prototypes for custom bus space functions.
1161.1Sreinoud */
1171.1Sreinoud
1181.1Sreinoud/* Print function used during child config */
1191.1Sreinoud
1201.1Sreinoudint
1211.1Sreinoudamps_print(aux, name)
1221.1Sreinoud	void *aux;
1231.1Sreinoud	const char *name;
1241.1Sreinoud{
1251.1Sreinoud	struct amps_attach_args *aa = aux;
1261.1Sreinoud
1271.1Sreinoud	if (!name)
1281.8Sthorpej		aprint_normal(", port %d", aa->aa_port);
1291.1Sreinoud
1301.1Sreinoud	return(QUIET);
1311.1Sreinoud}
1321.1Sreinoud
1331.1Sreinoud/*
1341.1Sreinoud * Card probe function
1351.1Sreinoud *
1361.1Sreinoud * Just match the manufacturer and podule ID's
1371.1Sreinoud */
1381.1Sreinoud
1391.1Sreinoudint
1401.1Sreinoudamps_probe(parent, cf, aux)
1411.1Sreinoud	struct device *parent;
1421.1Sreinoud	struct cfdata *cf;
1431.1Sreinoud	void *aux;
1441.1Sreinoud{
1451.1Sreinoud	struct podule_attach_args *pa = (void *)aux;
1461.1Sreinoud
1471.3Sbjh21	return (pa->pa_product == PODULE_ATOMWIDE_SERIAL);
1481.1Sreinoud}
1491.1Sreinoud
1501.1Sreinoud/*
1511.1Sreinoud * Card attach function
1521.1Sreinoud *
1531.1Sreinoud * Identify the card version and configure any children.
1541.1Sreinoud * Install a shutdown handler to kill interrupts on shutdown
1551.1Sreinoud */
1561.1Sreinoud
1571.1Sreinoudvoid
1581.1Sreinoudamps_attach(parent, self, aux)
1591.1Sreinoud	struct device *parent, *self;
1601.1Sreinoud	void *aux;
1611.1Sreinoud{
1621.1Sreinoud	struct amps_softc *sc = (void *)self;
1631.1Sreinoud	struct podule_attach_args *pa = (void *)aux;
1641.1Sreinoud	struct amps_attach_args aa;
1651.1Sreinoud
1661.1Sreinoud	/* Note the podule number and validate */
1671.1Sreinoud
1681.1Sreinoud	if (pa->pa_podule_number == -1)
1691.1Sreinoud		panic("Podule has disappeared !");
1701.1Sreinoud
1711.1Sreinoud	sc->sc_podule_number = pa->pa_podule_number;
1721.1Sreinoud	sc->sc_podule = pa->pa_podule;
1731.1Sreinoud	podules[sc->sc_podule_number].attached = 1;
1741.1Sreinoud
1751.1Sreinoud	sc->sc_iot = pa->pa_iot;
1761.1Sreinoud
1771.1Sreinoud	/* Install a clean up handler to make sure IRQ's are disabled */
1781.1Sreinoud/*	if (shutdownhook_establish(amps_shutdown, (void *)sc) == NULL)
1791.1Sreinoud		panic("%s: Cannot install shutdown handler", self->dv_xname);*/
1801.1Sreinoud
1811.1Sreinoud	/* Set the interrupt info for this podule */
1821.1Sreinoud
1831.1Sreinoud/*	sc->sc_podule->irq_addr = pa->pa_podule->slow_base +;*/	/* XXX */
1841.1Sreinoud/*	sc->sc_podule->irq_mask = ;*/
1851.1Sreinoud
1861.1Sreinoud	printf("\n");
1871.1Sreinoud
1881.1Sreinoud	/* Configure the children */
1891.1Sreinoud
1901.1Sreinoud	aa.aa_iot = sc->sc_iot;
1911.1Sreinoud	aa.aa_base = pa->pa_podule->slow_base + AMPS_BASE_OFFSET;
1921.1Sreinoud	aa.aa_base += MAX_AMPS_PORTS * AMPS_PORT_SPACING;
1931.1Sreinoud	aa.aa_irq = pa->pa_podule->interrupt;
1941.1Sreinoud	for (aa.aa_port = 0; aa.aa_port < MAX_AMPS_PORTS; ++aa.aa_port) {
1951.1Sreinoud		aa.aa_base -= AMPS_PORT_SPACING;
1961.1Sreinoud		config_found_sm(self, &aa, amps_print, NULL);
1971.1Sreinoud	}
1981.1Sreinoud}
1991.1Sreinoud
2001.1Sreinoud/*
2011.1Sreinoud * Card shutdown function
2021.1Sreinoud *
2031.1Sreinoud * Called via do_shutdown_hooks() during kernel shutdown.
2041.1Sreinoud * Clear the cards's interrupt mask to stop any podule interrupts.
2051.1Sreinoud */
2061.1Sreinoud
2071.1Sreinoud/*void
2081.1Sreinoudamps_shutdown(arg)
2091.1Sreinoud	void *arg;
2101.1Sreinoud{
2111.1Sreinoud}*/
2121.1Sreinoud
2131.1Sreinoud/*
2141.1Sreinoud * Atomwide Multi-Port Serial probe and attach code for the com device.
2151.1Sreinoud *
2161.1Sreinoud * This provides a different pair of probe and attach functions
2171.1Sreinoud * for attaching the com device (dev/ic/com.c) to the Atomwide serial card.
2181.1Sreinoud */
2191.1Sreinoud
2201.1Sreinoudstruct com_amps_softc {
2211.1Sreinoud	struct	com_softc sc_com;	/* real "com" softc */
2221.1Sreinoud	void	*sc_ih;			/* interrupt handler */
2231.1Sreinoud	struct	evcnt sc_intrcnt;	/* interrupt count */
2241.1Sreinoud};
2251.1Sreinoud
2261.1Sreinoud/* Prototypes for functions */
2271.1Sreinoud
2281.1Sreinoudstatic int  com_amps_probe   __P((struct device *, struct cfdata *, void *));
2291.1Sreinoudstatic void com_amps_attach  __P((struct device *, struct device *, void *));
2301.1Sreinoud
2311.1Sreinoud/* device attach structure */
2321.1Sreinoud
2331.5SthorpejCFATTACH_DECL(com_amps, sizeof(struct com_amps_softc),
2341.5Sthorpej	com_amps_probe, com_amps_attach, NULL, NULL);
2351.1Sreinoud
2361.1Sreinoud/*
2371.1Sreinoud * Controller probe function
2381.1Sreinoud *
2391.1Sreinoud * Map all the required I/O space for this channel, make sure interrupts
2401.1Sreinoud * are disabled and probe the bus.
2411.1Sreinoud */
2421.1Sreinoud
2431.1Sreinoudint
2441.1Sreinoudcom_amps_probe(parent, cf, aux)
2451.1Sreinoud	struct device *parent;
2461.1Sreinoud	struct cfdata *cf;
2471.1Sreinoud	void *aux;
2481.1Sreinoud{
2491.1Sreinoud	bus_space_tag_t iot;
2501.1Sreinoud	bus_space_handle_t ioh;
2511.1Sreinoud	int iobase;
2521.1Sreinoud	int rv = 1;
2531.1Sreinoud	struct amps_attach_args *aa = aux;
2541.1Sreinoud
2551.1Sreinoud	iot = aa->aa_iot;
2561.1Sreinoud	iobase = aa->aa_base;
2571.1Sreinoud
2581.1Sreinoud	/* if it's in use as console, it's there. */
2591.1Sreinoud	if (!com_is_console(iot, iobase, 0)) {
2601.1Sreinoud		if (bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh)) {
2611.1Sreinoud			return 0;
2621.1Sreinoud		}
2631.1Sreinoud		/*
2641.1Sreinoud		 * We don't use the generic comprobe1() function as it
2651.1Sreinoud		 * is not good enough to identify which ports are present.
2661.1Sreinoud		 *
2671.1Sreinoud		 * Instead test for the presence of the scratch register
2681.1Sreinoud		 */
2691.1Sreinoud
2701.1Sreinoud		bus_space_write_1(iot, ioh, com_scratch, 0x55);
2711.1Sreinoud		bus_space_write_1(iot, ioh, com_ier, 0);
2721.1Sreinoud		(void)bus_space_read_1(iot, ioh, com_data);
2731.1Sreinoud		if (bus_space_read_1(iot, ioh, com_scratch) != 0x55)
2741.1Sreinoud			rv = 0;
2751.1Sreinoud		bus_space_write_1(iot, ioh, com_scratch, 0xaa);
2761.1Sreinoud		bus_space_write_1(iot, ioh, com_ier, 0);
2771.1Sreinoud		(void)bus_space_read_1(iot, ioh, com_data);
2781.1Sreinoud		if (bus_space_read_1(iot, ioh, com_scratch) != 0xaa)
2791.1Sreinoud			rv = 0;
2801.1Sreinoud
2811.1Sreinoud		bus_space_unmap(iot, ioh, COM_NPORTS);
2821.1Sreinoud	}
2831.1Sreinoud	return (rv);
2841.1Sreinoud}
2851.1Sreinoud
2861.1Sreinoud/*
2871.1Sreinoud * Controller attach function
2881.1Sreinoud *
2891.1Sreinoud * Map all the required I/O space for this port and attach the driver
2901.1Sreinoud * The generic attach will probe and attach any device.
2911.1Sreinoud * Install an interrupt handler and we are ready to rock.
2921.1Sreinoud */
2931.1Sreinoud
2941.1Sreinoudvoid
2951.1Sreinoudcom_amps_attach(parent, self, aux)
2961.1Sreinoud	struct device *parent, *self;
2971.1Sreinoud	void *aux;
2981.1Sreinoud{
2991.1Sreinoud	struct com_amps_softc *asc = (void *)self;
3001.1Sreinoud	struct com_softc *sc = &asc->sc_com;
3011.1Sreinoud	u_int iobase;
3021.1Sreinoud	bus_space_tag_t iot;
3031.1Sreinoud	struct amps_attach_args *aa = aux;
3041.1Sreinoud
3051.1Sreinoud	iot = sc->sc_iot = aa->aa_iot;
3061.1Sreinoud	iobase = sc->sc_iobase = aa->aa_base;
3071.1Sreinoud
3081.1Sreinoud	if (!com_is_console(iot, iobase, &sc->sc_ioh)
3091.1Sreinoud		&& bus_space_map(iot, iobase, COM_NPORTS, 0, &sc->sc_ioh))
3101.1Sreinoud			panic("comattach: io mapping failed");
3111.1Sreinoud
3121.1Sreinoud	sc->sc_frequency = AMPS_FREQ;
3131.1Sreinoud	com_attach_subr(sc);
3141.1Sreinoud
3151.1Sreinoud	evcnt_attach_dynamic(&asc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
3161.1Sreinoud	    self->dv_xname, "intr");
3171.1Sreinoud	asc->sc_ih = podulebus_irq_establish(aa->aa_irq, IPL_SERIAL, comintr,
3181.1Sreinoud	    sc, &asc->sc_intrcnt);
3191.1Sreinoud}
320