1 /* $NetBSD: intio.c,v 1.28 2008/04/28 20:23:19 martin Exp $ */ 2 3 /*- 4 * Copyright (c) 1996, 1998, 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Autoconfiguration support for hp300 internal i/o space. 34 */ 35 36 #include <sys/cdefs.h> 37 __KERNEL_RCSID(0, "$NetBSD: intio.c,v 1.28 2008/04/28 20:23:19 martin Exp $"); 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/device.h> 42 43 #include <machine/hp300spu.h> 44 45 #include <hp300/dev/intioreg.h> 46 #include <hp300/dev/intiovar.h> 47 48 struct intio_softc { 49 device_t sc_dev; 50 struct bus_space_tag sc_tag; 51 }; 52 53 static int intiomatch(device_t, cfdata_t, void *); 54 static void intioattach(device_t, device_t, void *); 55 static int intioprint(void *, const char *); 56 57 CFATTACH_DECL_NEW(intio, sizeof(struct intio_softc), 58 intiomatch, intioattach, NULL, NULL); 59 60 #if defined(HP320) || defined(HP330) || defined(HP340) || defined(HP345) || \ 61 defined(HP350) || defined(HP360) || defined(HP370) || defined(HP375) || \ 62 defined(HP380) || defined(HP385) 63 static const struct intio_builtins intio_3xx_builtins[] = { 64 { "rtc", RTC_BASE, -1}, 65 { "hil", HIL_BASE, 1}, 66 { "hpib", HPIB_BASE, 3}, 67 { "dma", DMA_BASE, 1}, 68 { "fb", FB_BASE, -1}, 69 }; 70 #define nintio_3xx_builtins __arraycount(intio_3xx_builtins) 71 #endif 72 73 #if defined(HP362) || defined(HP382) 74 static const struct intio_builtins intio_3x2_builtins[] = { 75 { "rtc", RTC_BASE, -1}, 76 { "frodo", FRODO_BASE, 5}, 77 { "hil", HIL_BASE, 1}, 78 { "hpib", HPIB_BASE, 3}, 79 { "dma", DMA_BASE, 1}, 80 }; 81 #define nintio_3x2_builtins __arraycount(intio_3x2_builtins) 82 #endif 83 84 #if defined(HP400) || defined(HP425) || defined(HP433) 85 static const struct intio_builtins intio_4xx_builtins[] = { 86 { "rtc", RTC_BASE, -1}, 87 { "frodo", FRODO_BASE, 5}, 88 { "hil", HIL_BASE, 1}, 89 { "hpib", HPIB_BASE, 3}, 90 { "dma", DMA_BASE, 1}, 91 }; 92 #define nintio_4xx_builtins __arraycount(intio_4xx_builtins) 93 #endif 94 95 static int intio_matched = 0; 96 extern void *internalhpib; 97 98 static int 99 intiomatch(device_t parent, cfdata_t cf, void *aux) 100 { 101 102 /* Allow only one instance. */ 103 if (intio_matched) 104 return 0; 105 106 intio_matched = 1; 107 return 1; 108 } 109 110 static void 111 intioattach(device_t parent, device_t self, void *aux) 112 { 113 struct intio_softc *sc = device_private(self); 114 struct intio_attach_args ia; 115 const struct intio_builtins *ib; 116 bus_space_tag_t bst = &sc->sc_tag; 117 int ndevs; 118 int i; 119 120 sc->sc_dev = self; 121 aprint_normal("\n"); 122 123 memset(bst, 0, sizeof(struct bus_space_tag)); 124 bst->bustype = HP300_BUS_SPACE_INTIO; 125 126 switch (machineid) { 127 #if defined(HP320) || defined(HP330) || defined(HP340) || defined(HP345) || \ 128 defined(HP350) || defined(HP360) || defined(HP370) || defined(HP375) || \ 129 defined(HP380) || defined(HP385) 130 case HP_320: 131 case HP_330: 132 case HP_340: 133 case HP_345: 134 case HP_350: 135 case HP_360: 136 case HP_370: 137 case HP_375: 138 case HP_380: 139 case HP_385: 140 ib = intio_3xx_builtins; 141 ndevs = nintio_3xx_builtins; 142 break; 143 #endif 144 #if defined(HP362) || defined(HP382) 145 case HP_362: 146 case HP_382: 147 ib = intio_3x2_builtins; 148 ndevs = nintio_3x2_builtins; 149 break; 150 #endif 151 #if defined(HP400) || defined(HP425) || defined(HP433) 152 case HP_400: 153 case HP_425: 154 case HP_433: 155 ib = intio_4xx_builtins; 156 ndevs = nintio_4xx_builtins; 157 break; 158 #endif 159 default: 160 return; 161 } 162 163 memset(&ia, 0, sizeof(ia)); 164 165 for (i = 0; i < ndevs; i++) { 166 167 /* 168 * Internal HP-IB doesn't always return a device ID, 169 * so we rely on the sysflags. 170 */ 171 if (ib[i].ib_offset == HPIB_BASE && !internalhpib) 172 continue; 173 174 strlcpy(ia.ia_modname, ib[i].ib_modname, 175 sizeof(ia.ia_modname)); 176 ia.ia_bst = bst; 177 ia.ia_iobase = ib[i].ib_offset; 178 ia.ia_addr = (bus_addr_t)(intiobase + ib[i].ib_offset); 179 ia.ia_ipl = ib[i].ib_ipl; 180 config_found(self, &ia, intioprint); 181 } 182 } 183 184 static int 185 intioprint(void *aux, const char *pnp) 186 { 187 struct intio_attach_args *ia = aux; 188 189 if (pnp != NULL) 190 aprint_normal("%s at %s", ia->ia_modname, pnp); 191 if (ia->ia_iobase != 0 && pnp == NULL) { 192 aprint_normal(" addr 0x%lx", INTIOBASE + ia->ia_iobase); 193 if (ia->ia_ipl != -1) 194 aprint_normal(" ipl %d", ia->ia_ipl); 195 } 196 return UNCONF; 197 } 198