1 /* $NetBSD: lpt_gsc.c,v 1.1 2014/02/24 07:23:43 skrll Exp $ */ 2 3 /* $OpenBSD: lpt_gsc.c,v 1.6 2000/07/21 17:41:06 mickey Exp $ */ 4 5 /* 6 * Copyright (c) 1998 Michael Shalayeff 7 * Copyright (c) 1993, 1994 Charles Hannum. 8 * Copyright (c) 1990 William F. Jolitz, TeleMuse 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This software is a component of "386BSD" developed by 22 * William F. Jolitz, TeleMuse. 23 * 4. Neither the name of the developer nor the name "386BSD" 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ 28 * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS 29 * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT. 30 * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT 31 * NOT MAKE USE OF THIS WORK. 32 * 33 * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED 34 * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN 35 * REFERENCES SUCH AS THE "PORTING UNIX TO THE 386" SERIES 36 * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING 37 * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND 38 * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE 39 * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS 40 * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992. 41 * 42 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND 43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 45 * ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER BE LIABLE 46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 52 * SUCH DAMAGE. 53 */ 54 55 #include <sys/cdefs.h> 56 __KERNEL_RCSID(0, "$NetBSD: lpt_gsc.c,v 1.1 2014/02/24 07:23:43 skrll Exp $"); 57 58 #include <sys/param.h> 59 #include <sys/systm.h> 60 #include <sys/device.h> 61 62 #include <sys/bus.h> 63 #include <machine/intr.h> 64 #include <machine/iomod.h> 65 #include <machine/autoconf.h> 66 67 #include <dev/ic/lptreg.h> 68 #include <dev/ic/lptvar.h> 69 70 #include <hppa/dev/cpudevs.h> 71 72 #include <hppa/gsc/gscbusvar.h> 73 74 #define LPTGSC_OFFSET 0x800 75 76 #ifndef LPTDEBUG 77 #define LPRINTF(a) 78 #else 79 #define LPRINTF(a) if (lpt_isa_debug) printf a 80 int lpt_isa_debug = 0; 81 #endif 82 83 int lpt_gsc_probe(device_t, cfdata_t , void *); 84 void lpt_gsc_attach(device_t, device_t, void *); 85 86 CFATTACH_DECL_NEW(lpt_gsc, sizeof(struct lpt_softc), 87 lpt_gsc_probe, lpt_gsc_attach, NULL, NULL); 88 89 int lpt_port_test(bus_space_tag_t, bus_space_handle_t, bus_addr_t, 90 bus_size_t, u_char, u_char); 91 92 /* 93 * Internal routine to lptprobe to do port tests of one byte value. 94 */ 95 int 96 lpt_port_test(bus_space_tag_t iot, bus_space_handle_t ioh, bus_addr_t base, 97 bus_size_t off, u_char data, u_char mask) 98 { 99 int timeout; 100 u_char temp; 101 102 data &= mask; 103 bus_space_write_1(iot, ioh, off, data); 104 timeout = 1000; 105 do { 106 delay(10); 107 temp = bus_space_read_1(iot, ioh, off) & mask; 108 } while (temp != data && --timeout); 109 LPRINTF(("lpt: port=0x%x out=0x%x in=0x%x timeout=%d\n", 110 (unsigned)(base + off), (unsigned)data, (unsigned)temp, timeout)); 111 return (temp == data); 112 } 113 114 /* 115 * Logic: 116 * 1) You should be able to write to and read back the same value 117 * to the data port. Do an alternating zeros, alternating ones, 118 * walking zero, and walking one test to check for stuck bits. 119 * 120 * 2) You should be able to write to and read back the same value 121 * to the control port lower 5 bits, the upper 3 bits are reserved 122 * per the IBM PC technical reference manauls and different boards 123 * do different things with them. Do an alternating zeros, alternating 124 * ones, walking zero, and walking one test to check for stuck bits. 125 * 126 * Some printers drag the strobe line down when the are powered off 127 * so this bit has been masked out of the control port test. 128 * 129 * XXX Some printers may not like a fast pulse on init or strobe, I 130 * don't know at this point, if that becomes a problem these bits 131 * should be turned off in the mask byte for the control port test. 132 * 133 * 3) Set the data and control ports to a value of 0 134 */ 135 int 136 lpt_gsc_probe(device_t parent, cfdata_t match, void *aux) 137 { 138 struct gsc_attach_args *ga = aux; 139 bus_space_handle_t ioh; 140 bus_addr_t base; 141 uint8_t mask, data; 142 int i; 143 144 if (ga->ga_type.iodc_type != HPPA_TYPE_FIO || 145 ga->ga_type.iodc_sv_model != HPPA_FIO_CENT) 146 return 0; 147 148 #ifdef DEBUG 149 #define ABORT \ 150 do { \ 151 printf("lpt_gsc_probe: mask %x data %x failed\n", mask, \ 152 data); \ 153 bus_space_unmap(ga->ga_iot, ioh, LPT_NPORTS); \ 154 return 0; \ 155 } while (0) 156 #else 157 #define ABORT \ 158 do { \ 159 bus_space_unmap(ga->ga_iot, ioh, LPT_NPORTS); \ 160 return 0; \ 161 } while (0) 162 #endif 163 164 base = ga->ga_hpa + LPTGSC_OFFSET; 165 if (bus_space_map(ga->ga_iot, base, LPT_NPORTS, 0, &ioh)) 166 return 0; 167 168 mask = 0xff; 169 170 data = 0x55; /* Alternating zeros */ 171 if (!lpt_port_test(ga->ga_iot, ioh, base, lpt_data, data, mask)) 172 ABORT; 173 174 data = 0xaa; /* Alternating ones */ 175 if (!lpt_port_test(ga->ga_iot, ioh, base, lpt_data, data, mask)) 176 ABORT; 177 178 for (i = 0; i < CHAR_BIT; i++) { /* Walking zero */ 179 data = ~(1 << i); 180 if (!lpt_port_test(ga->ga_iot, ioh, base, lpt_data, data, mask)) 181 ABORT; 182 } 183 184 for (i = 0; i < CHAR_BIT; i++) { /* Walking one */ 185 data = (1 << i); 186 if (!lpt_port_test(ga->ga_iot, ioh, base, lpt_data, data, mask)) 187 ABORT; 188 } 189 190 bus_space_write_1(ga->ga_iot, ioh, lpt_data, 0); 191 bus_space_write_1(ga->ga_iot, ioh, lpt_control, 0); 192 bus_space_unmap(ga->ga_iot, ioh, LPT_NPORTS); 193 194 return 1; 195 } 196 197 void 198 lpt_gsc_attach(device_t parent, device_t self, void *aux) 199 { 200 struct lpt_softc *sc = device_private(self); 201 struct gsc_attach_args *ga = aux; 202 203 /* sc->sc_flags |= LPT_POLLED; */ 204 205 sc->sc_dev = self; 206 sc->sc_state = 0; 207 sc->sc_iot = ga->ga_iot; 208 if (bus_space_map(sc->sc_iot, ga->ga_hpa + LPTGSC_OFFSET, 209 LPT_NPORTS, 0, &sc->sc_ioh)) { 210 aprint_error(": can't map i/o ports\n"); 211 return; 212 } 213 214 lpt_attach_subr(sc); 215 216 sc->sc_ih = hppa_intr_establish(IPL_TTY, lptintr, sc, ga->ga_ir, 217 ga->ga_irq); 218 aprint_normal("\n"); 219 } 220