1 /* $OpenBSD: apio.c,v 1.9 2022/03/13 13:34:54 mpi Exp $ */ 2 3 /* 4 * Copyright (c) 2002 Jason L. Wright (jason@thought.net) 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Effort sponsored in part by the Defense Advanced Research Projects 29 * Agency (DARPA) and Air Force Research Laboratory, Air Force 30 * Materiel Command, USAF, under agreement number F30602-01-2-0537. 31 * 32 */ 33 34 /* 35 * Driver for Aurora 210SJ parallel ports. 36 */ 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/kernel.h> 41 #include <sys/device.h> 42 #include <sys/conf.h> 43 #include <sys/timeout.h> 44 #include <sys/tty.h> 45 46 #include <machine/bus.h> 47 #include <machine/autoconf.h> 48 #include <machine/openfirm.h> 49 50 #include <dev/sbus/sbusvar.h> 51 #include <dev/sbus/asioreg.h> 52 #include <dev/ic/lptvar.h> 53 #include "apio.h" 54 #include "lpt.h" 55 56 struct apio_softc { 57 struct device sc_dev; 58 bus_space_tag_t sc_bt; 59 bus_space_handle_t sc_csr_h; 60 bus_space_handle_t sc_clk_h; 61 bus_space_handle_t sc_lpt_h; 62 void *sc_ih; 63 struct device *sc_port; 64 }; 65 66 struct apio_attach_args { 67 char *aaa_name; 68 bus_space_tag_t aaa_iot; 69 bus_space_handle_t aaa_ioh; 70 bus_space_handle_t aaa_clkh; 71 u_int32_t aaa_pri; 72 u_int8_t aaa_inten; 73 }; 74 75 int apio_match(struct device *, void *, void *); 76 void apio_attach(struct device *, struct device *, void *); 77 int apio_print(void *, const char *); 78 void apio_intr_enable(struct device *, u_int8_t); 79 80 const struct cfattach apio_ca = { 81 sizeof(struct apio_softc), apio_match, apio_attach 82 }; 83 84 struct cfdriver apio_cd = { 85 NULL, "apio", DV_DULL 86 }; 87 88 int 89 apio_match(struct device *parent, void *match, void *aux) 90 { 91 struct sbus_attach_args *sa = aux; 92 93 if (strcmp(sa->sa_name, "pio1") == 0) 94 return (1); 95 return (0); 96 } 97 98 void 99 apio_attach(struct device *parent, struct device *self, void *aux) 100 { 101 struct apio_softc *sc = (void *)self; 102 struct sbus_attach_args *sa = aux; 103 struct apio_attach_args aaa; 104 char *model; 105 106 sc->sc_bt = sa->sa_bustag; 107 108 model = getpropstring(sa->sa_node, "model"); 109 if (model == NULL) { 110 printf(": empty model, unsupported\n"); 111 return; 112 } 113 if (strcmp(model, "210sj") != 0) { 114 printf(": unsupported model %s\n", model); 115 return; 116 } 117 118 if (sa->sa_nreg < 3) { 119 printf(": %d registers expected, got %d\n", 120 3, sa->sa_nreg); 121 return; 122 } 123 124 if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot, 125 sa->sa_reg[0].sbr_offset, sa->sa_reg[0].sbr_size, 126 0, 0, &sc->sc_csr_h)) { 127 printf(": couldn't map csr\n"); 128 return; 129 } 130 131 if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[1].sbr_slot, 132 sa->sa_reg[1].sbr_offset, sa->sa_reg[1].sbr_size, 133 0, 0, &sc->sc_clk_h)) { 134 printf(": couldn't map clk\n"); 135 return; 136 } 137 138 if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[2].sbr_slot, 139 sa->sa_reg[2].sbr_offset, sa->sa_reg[2].sbr_size, 140 0, 0, &sc->sc_lpt_h)) { 141 printf(": couldn't map clk\n"); 142 return; 143 } 144 145 printf(": %s\n", model); 146 147 aaa.aaa_name = "lpt"; 148 aaa.aaa_iot = sc->sc_bt; 149 aaa.aaa_ioh = sc->sc_lpt_h; 150 aaa.aaa_clkh = sc->sc_clk_h; 151 aaa.aaa_inten = ASIO_CSR_SJ_PAR_INTEN; 152 aaa.aaa_pri = sa->sa_intr[0].sbi_pri; 153 sc->sc_port = config_found(self, &aaa, apio_print); 154 } 155 156 int 157 apio_print(void *aux, const char *name) 158 { 159 struct apio_attach_args *aaa = aux; 160 161 if (name != NULL) 162 printf("%s at %s", aaa->aaa_name, name); 163 return (UNCONF); 164 } 165 166 #if NLPT_APIO > 0 167 int lpt_apio_match(struct device *, void *, void *); 168 void lpt_apio_attach(struct device *, struct device *, void *); 169 int lpt_apio_intr(void *); 170 171 struct lpt_apio_softc { 172 struct lpt_softc sc_lpt; 173 bus_space_handle_t sc_clk_h; 174 void *sc_ih; 175 }; 176 177 const struct cfattach lpt_apio_ca = { 178 sizeof(struct lpt_apio_softc), lpt_apio_match, lpt_apio_attach 179 }; 180 181 void 182 apio_intr_enable(struct device *dv, u_int8_t en) 183 { 184 struct apio_softc *sc = (struct apio_softc *)dv; 185 u_int8_t csr; 186 187 csr = bus_space_read_1(sc->sc_bt, sc->sc_csr_h, 0); 188 csr &= ~(ASIO_CSR_SBUS_INT7 | ASIO_CSR_SBUS_INT6); 189 csr |= ASIO_CSR_SBUS_INT5 | en; 190 bus_space_write_1(sc->sc_bt, sc->sc_csr_h, 0, csr); 191 } 192 193 int 194 lpt_apio_match(struct device *parent, void *match, void *aux) 195 { 196 return (1); 197 } 198 199 void 200 lpt_apio_attach(struct device *parent, struct device *self, void *aux) 201 { 202 struct lpt_apio_softc *sc = (struct lpt_apio_softc *)self; 203 struct apio_attach_args *aaa = aux; 204 205 sc->sc_lpt.sc_state = 0; 206 sc->sc_lpt.sc_iot = aaa->aaa_iot; 207 sc->sc_lpt.sc_ioh = aaa->aaa_ioh; 208 sc->sc_clk_h = aaa->aaa_clkh; 209 sc->sc_ih = bus_intr_establish(aaa->aaa_iot, aaa->aaa_pri, 210 IPL_TTY, 0, lpt_apio_intr, sc, self->dv_xname); 211 if (sc->sc_ih == NULL) { 212 printf(": cannot allocate intr\n"); 213 return; 214 } 215 apio_intr_enable(parent, aaa->aaa_inten); 216 217 lpt_attach_common(&sc->sc_lpt); 218 } 219 220 int 221 lpt_apio_intr(void *vsc) 222 { 223 struct lpt_apio_softc *sc = vsc; 224 int r; 225 226 r = lptintr(&sc->sc_lpt); 227 bus_space_read_1(sc->sc_lpt.sc_iot, sc->sc_clk_h, 0); 228 return (r); 229 } 230 #endif 231