1 1.37 thorpej /* $NetBSD: adb.c,v 1.37 2021/08/07 16:18:57 thorpej Exp $ */ 2 1.1 tsubai 3 1.1 tsubai /*- 4 1.1 tsubai * Copyright (C) 1994 Bradley A. Grantham 5 1.1 tsubai * All rights reserved. 6 1.1 tsubai * 7 1.1 tsubai * Redistribution and use in source and binary forms, with or without 8 1.1 tsubai * modification, are permitted provided that the following conditions 9 1.1 tsubai * are met: 10 1.1 tsubai * 1. Redistributions of source code must retain the above copyright 11 1.1 tsubai * notice, this list of conditions and the following disclaimer. 12 1.1 tsubai * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 tsubai * notice, this list of conditions and the following disclaimer in the 14 1.1 tsubai * documentation and/or other materials provided with the distribution. 15 1.1 tsubai * 16 1.1 tsubai * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.1 tsubai * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.1 tsubai * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.1 tsubai * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.1 tsubai * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 1.1 tsubai * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 1.1 tsubai * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 1.1 tsubai * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 1.1 tsubai * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 1.1 tsubai * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 1.1 tsubai */ 27 1.15 lukem 28 1.15 lukem #include <sys/cdefs.h> 29 1.37 thorpej __KERNEL_RCSID(0, "$NetBSD: adb.c,v 1.37 2021/08/07 16:18:57 thorpej Exp $"); 30 1.1 tsubai 31 1.1 tsubai #include <sys/param.h> 32 1.1 tsubai #include <sys/device.h> 33 1.1 tsubai #include <sys/fcntl.h> 34 1.1 tsubai #include <sys/poll.h> 35 1.1 tsubai #include <sys/select.h> 36 1.1 tsubai #include <sys/proc.h> 37 1.1 tsubai #include <sys/signalvar.h> 38 1.1 tsubai #include <sys/systm.h> 39 1.1 tsubai 40 1.32 dyoung #include <sys/bus.h> 41 1.1 tsubai #include <machine/autoconf.h> 42 1.23 garbled #include <machine/pio.h> 43 1.1 tsubai 44 1.1 tsubai #include <macppc/dev/adbvar.h> 45 1.3 tsubai #include <macppc/dev/akbdvar.h> 46 1.17 briggs #include <macppc/dev/pm_direct.h> 47 1.1 tsubai #include <macppc/dev/viareg.h> 48 1.1 tsubai 49 1.20 gdamore #include <dev/clock_subr.h> 50 1.9 matt #include <dev/ofw/openfirm.h> 51 1.9 matt 52 1.4 tsubai #include "aed.h" 53 1.11 itojun #include "apm.h" 54 1.4 tsubai 55 1.1 tsubai /* 56 1.1 tsubai * Function declarations. 57 1.1 tsubai */ 58 1.30 matt static int adbmatch(device_t, cfdata_t, void *); 59 1.30 matt static void adbattach(device_t, device_t, void *); 60 1.25 dsl static int adbprint(void *, const char *); 61 1.20 gdamore static void adb_todr_init(void); 62 1.1 tsubai 63 1.1 tsubai /* 64 1.1 tsubai * Global variables. 65 1.1 tsubai */ 66 1.1 tsubai int adb_polling = 0; /* Are we polling? (Debugger mode) */ 67 1.1 tsubai int adb_initted = 0; /* adb_init() has completed successfully */ 68 1.1 tsubai #ifdef ADB_DEBUG 69 1.1 tsubai int adb_debug = 0; /* Output debugging messages */ 70 1.1 tsubai #endif /* ADB_DEBUG */ 71 1.1 tsubai 72 1.1 tsubai /* 73 1.3 tsubai * Driver definition. 74 1.1 tsubai */ 75 1.34 chs CFATTACH_DECL_NEW(adb, sizeof(struct adb_softc), 76 1.13 thorpej adbmatch, adbattach, NULL, NULL); 77 1.5 tsubai 78 1.1 tsubai static int 79 1.30 matt adbmatch(device_t parent, cfdata_t cf, void *aux) 80 1.1 tsubai { 81 1.1 tsubai struct confargs *ca = aux; 82 1.1 tsubai 83 1.1 tsubai if (ca->ca_nreg < 8) 84 1.1 tsubai return 0; 85 1.1 tsubai 86 1.1 tsubai if (ca->ca_nintr < 4) 87 1.1 tsubai return 0; 88 1.1 tsubai 89 1.5 tsubai if (strcmp(ca->ca_name, "via-cuda") == 0) 90 1.5 tsubai return 1; 91 1.5 tsubai 92 1.5 tsubai if (strcmp(ca->ca_name, "via-pmu") == 0) 93 1.5 tsubai return 1; 94 1.5 tsubai 95 1.5 tsubai return 0; 96 1.1 tsubai } 97 1.1 tsubai 98 1.1 tsubai static void 99 1.30 matt adbattach(device_t parent, device_t self, void *aux) 100 1.1 tsubai { 101 1.30 matt struct adb_softc *sc = device_private(self); 102 1.1 tsubai struct confargs *ca = aux; 103 1.8 tsubai int irq = ca->ca_intr[0]; 104 1.8 tsubai int node; 105 1.3 tsubai ADBDataBlock adbdata; 106 1.3 tsubai struct adb_attach_args aa_args; 107 1.3 tsubai int totaladbs; 108 1.21 macallan int adbindex, adbaddr, adb_node; 109 1.3 tsubai 110 1.33 matt extern volatile uint8_t *Via1Base; 111 1.1 tsubai 112 1.1 tsubai ca->ca_reg[0] += ca->ca_baseaddr; 113 1.1 tsubai 114 1.31 matt sc->sc_regbase = mapiodev(ca->ca_reg[0], ca->ca_reg[1], false); 115 1.1 tsubai Via1Base = sc->sc_regbase; 116 1.1 tsubai 117 1.5 tsubai if (strcmp(ca->ca_name, "via-cuda") == 0) 118 1.5 tsubai adbHardware = ADB_HW_CUDA; 119 1.5 tsubai else if (strcmp(ca->ca_name, "via-pmu") == 0) 120 1.16 briggs adbHardware = ADB_HW_PMU; 121 1.5 tsubai 122 1.24 garbled node = of_getnode_byname(OF_parent(ca->ca_node), "extint-gpio1"); 123 1.8 tsubai if (node) 124 1.8 tsubai OF_getprop(node, "interrupts", &irq, 4); 125 1.8 tsubai 126 1.8 tsubai printf(" irq %d: ", irq); 127 1.8 tsubai 128 1.1 tsubai adb_polling = 1; 129 1.24 garbled adb_node = of_getnode_byname(ca->ca_node, "adb"); 130 1.21 macallan if (adb_node) 131 1.21 macallan ADBReInit(); 132 1.1 tsubai 133 1.18 briggs switch (adbHardware) { 134 1.18 briggs case ADB_HW_CUDA: 135 1.35 rin intr_establish_xname(irq, IST_LEVEL, IPL_TTY, adb_intr_cuda, sc, 136 1.35 rin device_xname(self)); 137 1.18 briggs break; 138 1.18 briggs case ADB_HW_PMU: 139 1.35 rin intr_establish_xname(irq, IST_LEVEL, IPL_TTY, pm_intr, sc, 140 1.35 rin device_xname(self)); 141 1.17 briggs pm_init(); 142 1.18 briggs break; 143 1.17 briggs } 144 1.1 tsubai 145 1.21 macallan adb_todr_init(); 146 1.21 macallan 147 1.21 macallan #if NAPM > 0 148 1.21 macallan /* Magic for signalling the apm driver to match. */ 149 1.21 macallan aa_args.origaddr = ADBADDR_APM; 150 1.21 macallan aa_args.adbaddr = ADBADDR_APM; 151 1.21 macallan aa_args.handler_id = ADBADDR_APM; 152 1.21 macallan 153 1.37 thorpej (void)config_found(self, &aa_args, NULL, CFARGS_NONE); 154 1.21 macallan #endif 155 1.21 macallan 156 1.21 macallan /* 157 1.21 macallan * see if we're supposed to have an ADB bus 158 1.21 macallan * since some PowerBooks don't have one and their PMUs barf on ADB 159 1.21 macallan * commands we bail here if there's no adb node 160 1.21 macallan */ 161 1.21 macallan if (!adb_node) 162 1.21 macallan return; 163 1.21 macallan 164 1.3 tsubai #ifdef ADB_DEBUG 165 1.3 tsubai if (adb_debug) 166 1.3 tsubai printf("adb: done with ADBReInit\n"); 167 1.1 tsubai #endif 168 1.3 tsubai totaladbs = CountADBs(); 169 1.1 tsubai 170 1.8 tsubai printf("%d targets\n", totaladbs); 171 1.1 tsubai 172 1.4 tsubai #if NAED > 0 173 1.3 tsubai /* ADB event device for compatibility */ 174 1.3 tsubai aa_args.origaddr = 0; 175 1.3 tsubai aa_args.adbaddr = 0; 176 1.3 tsubai aa_args.handler_id = 0; 177 1.37 thorpej (void)config_found(self, &aa_args, adbprint, CFARGS_NONE); 178 1.4 tsubai #endif 179 1.1 tsubai 180 1.3 tsubai /* for each ADB device */ 181 1.3 tsubai for (adbindex = 1; adbindex <= totaladbs; adbindex++) { 182 1.3 tsubai /* Get the ADB information */ 183 1.3 tsubai adbaddr = GetIndADB(&adbdata, adbindex); 184 1.1 tsubai 185 1.3 tsubai aa_args.origaddr = adbdata.origADBAddr; 186 1.3 tsubai aa_args.adbaddr = adbaddr; 187 1.3 tsubai aa_args.handler_id = adbdata.devType; 188 1.1 tsubai 189 1.37 thorpej (void)config_found(self, &aa_args, adbprint, CFARGS_NONE); 190 1.1 tsubai } 191 1.11 itojun 192 1.5 tsubai if (adbHardware == ADB_HW_CUDA) 193 1.5 tsubai adb_cuda_autopoll(); 194 1.3 tsubai adb_polling = 0; 195 1.20 gdamore 196 1.1 tsubai } 197 1.1 tsubai 198 1.3 tsubai int 199 1.26 dsl adbprint(void *args, const char *name) 200 1.3 tsubai { 201 1.3 tsubai struct adb_attach_args *aa_args = (struct adb_attach_args *)args; 202 1.3 tsubai int rv = UNCONF; 203 1.3 tsubai 204 1.3 tsubai if (name) { /* no configured device matched */ 205 1.3 tsubai rv = UNSUPP; /* most ADB device types are unsupported */ 206 1.3 tsubai 207 1.3 tsubai /* print out what kind of ADB device we have found */ 208 1.14 thorpej aprint_normal("%s addr %d: ", name, aa_args->adbaddr); 209 1.3 tsubai switch(aa_args->origaddr) { 210 1.3 tsubai #ifdef DIAGNOSTIC 211 1.3 tsubai case 0: 212 1.14 thorpej aprint_normal("ADB event device"); 213 1.3 tsubai rv = UNCONF; 214 1.3 tsubai break; 215 1.3 tsubai case ADBADDR_SECURE: 216 1.14 thorpej aprint_normal("security dongle (%d)", 217 1.14 thorpej aa_args->handler_id); 218 1.3 tsubai break; 219 1.1 tsubai #endif 220 1.3 tsubai case ADBADDR_MAP: 221 1.14 thorpej aprint_normal("mapped device (%d)", 222 1.14 thorpej aa_args->handler_id); 223 1.3 tsubai rv = UNCONF; 224 1.3 tsubai break; 225 1.3 tsubai case ADBADDR_REL: 226 1.14 thorpej aprint_normal("relative positioning device (%d)", 227 1.3 tsubai aa_args->handler_id); 228 1.3 tsubai rv = UNCONF; 229 1.3 tsubai break; 230 1.3 tsubai #ifdef DIAGNOSTIC 231 1.3 tsubai case ADBADDR_ABS: 232 1.3 tsubai switch (aa_args->handler_id) { 233 1.3 tsubai case ADB_ARTPAD: 234 1.14 thorpej aprint_normal("WACOM ArtPad II"); 235 1.3 tsubai break; 236 1.3 tsubai default: 237 1.14 thorpej aprint_normal("absolute positioning device (%d)", 238 1.3 tsubai aa_args->handler_id); 239 1.3 tsubai break; 240 1.3 tsubai } 241 1.3 tsubai break; 242 1.3 tsubai case ADBADDR_DATATX: 243 1.14 thorpej aprint_normal("data transfer device (modem?) (%d)", 244 1.3 tsubai aa_args->handler_id); 245 1.1 tsubai break; 246 1.3 tsubai case ADBADDR_MISC: 247 1.3 tsubai switch (aa_args->handler_id) { 248 1.3 tsubai case ADB_POWERKEY: 249 1.14 thorpej aprint_normal("Sophisticated Circuits PowerKey"); 250 1.3 tsubai break; 251 1.3 tsubai default: 252 1.14 thorpej aprint_normal("misc. device (remote control?) (%d)", 253 1.3 tsubai aa_args->handler_id); 254 1.3 tsubai break; 255 1.3 tsubai } 256 1.1 tsubai break; 257 1.1 tsubai default: 258 1.14 thorpej aprint_normal("unknown type device, (handler %d)", 259 1.3 tsubai aa_args->handler_id); 260 1.1 tsubai break; 261 1.3 tsubai #endif /* DIAGNOSTIC */ 262 1.1 tsubai } 263 1.3 tsubai } else /* a device matched and was configured */ 264 1.14 thorpej aprint_normal(" addr %d: ", aa_args->adbaddr); 265 1.1 tsubai 266 1.7 tsubai return rv; 267 1.1 tsubai } 268 1.20 gdamore 269 1.20 gdamore #define DIFF19041970 2082844800 270 1.20 gdamore 271 1.20 gdamore static int 272 1.29 tsutsui adb_todr_get(todr_chip_handle_t tch, struct timeval *tvp) 273 1.20 gdamore { 274 1.20 gdamore unsigned long sec; 275 1.20 gdamore 276 1.20 gdamore if (adb_read_date_time(&sec) != 0) 277 1.20 gdamore return EIO; 278 1.20 gdamore tvp->tv_sec = sec - DIFF19041970; 279 1.20 gdamore tvp->tv_usec = 0; 280 1.20 gdamore return 0; 281 1.20 gdamore } 282 1.20 gdamore 283 1.20 gdamore static int 284 1.29 tsutsui adb_todr_set(todr_chip_handle_t tch, struct timeval *tvp) 285 1.20 gdamore { 286 1.20 gdamore unsigned long sec; 287 1.20 gdamore 288 1.20 gdamore sec = tvp->tv_sec + DIFF19041970; 289 1.20 gdamore return adb_set_date_time(sec) ? EIO : 0; 290 1.20 gdamore } 291 1.20 gdamore 292 1.20 gdamore void 293 1.20 gdamore adb_todr_init(void) 294 1.20 gdamore { 295 1.20 gdamore static struct todr_chip_handle tch = { 296 1.20 gdamore .todr_gettime = adb_todr_get, 297 1.20 gdamore .todr_settime = adb_todr_set 298 1.20 gdamore }; 299 1.20 gdamore 300 1.20 gdamore todr_attach(&tch); 301 1.20 gdamore } 302