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