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