Home | History | Annotate | Line # | Download | only in mvme
lpt_pcctwo.c revision 1.4.2.2
      1 /*	$NetBSD: lpt_pcctwo.c,v 1.4.2.2 2002/10/10 18:40:14 jdolecek Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Steve C. Woodford.
      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  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *	This product includes software developed by the NetBSD
     21  *	Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 /*
     40  * Device Driver back-end for the PCCChip2's parallel printer port
     41  */
     42 
     43 #include <sys/param.h>
     44 #include <sys/kernel.h>
     45 #include <sys/systm.h>
     46 #include <sys/device.h>
     47 #include <sys/syslog.h>
     48 
     49 #include <machine/cpu.h>
     50 #include <machine/bus.h>
     51 
     52 #include <dev/mvme/lptvar.h>
     53 #include <dev/mvme/pcctworeg.h>
     54 #include <dev/mvme/pcctwovar.h>
     55 
     56 /*
     57  * Autoconfig stuff
     58  */
     59 int lpt_pcctwo_match __P((struct device *, struct cfdata *, void *));
     60 void lpt_pcctwo_attach __P((struct device *, struct device *, void *));
     61 
     62 CFATTACH_DECL(lpt_pcctwo, sizeof(struct lpt_softc),
     63     lpt_pcctwo_match, lpt_pcctwo_attach, NULL, NULL);
     64 
     65 extern struct cfdriver lpt_cd;
     66 
     67 
     68 int lpt_pcctwo_intr __P((void *));
     69 void lpt_pcctwo_open __P((struct lpt_softc *, int));
     70 void lpt_pcctwo_close __P((struct lpt_softc *));
     71 void lpt_pcctwo_iprime __P((struct lpt_softc *));
     72 void lpt_pcctwo_speed __P((struct lpt_softc *, int));
     73 int lpt_pcctwo_notrdy __P((struct lpt_softc *, int));
     74 void lpt_pcctwo_wr_data __P((struct lpt_softc *, u_char));
     75 
     76 struct lpt_funcs lpt_pcctwo_funcs = {
     77 	lpt_pcctwo_open,
     78 	lpt_pcctwo_close,
     79 	lpt_pcctwo_iprime,
     80 	lpt_pcctwo_speed,
     81 	lpt_pcctwo_notrdy,
     82 	lpt_pcctwo_wr_data
     83 };
     84 
     85 /* ARGSUSED */
     86 int
     87 lpt_pcctwo_match(parent, cf, args)
     88 	struct device *parent;
     89 	struct cfdata *cf;
     90 	void *args;
     91 {
     92 	struct pcctwo_attach_args *pa;
     93 
     94 	pa = args;
     95 
     96 	if (strcmp(pa->pa_name, lpt_cd.cd_name))
     97 		return (0);
     98 
     99 #ifdef MVME68K
    100 	if (machineid != MVME_167 && machineid != MVME_177)
    101 		return (0);
    102 #endif
    103 
    104 #ifdef MVME88K
    105 	if (machineid != MVME_187)
    106 		return (0);
    107 #endif
    108 
    109 	pa->pa_ipl = cf->pcctwocf_ipl;
    110 
    111 	return (1);
    112 }
    113 
    114 /* ARGSUSED */
    115 void
    116 lpt_pcctwo_attach(parent, self, args)
    117 	struct device *parent;
    118 	struct device *self;
    119 	void *args;
    120 {
    121 	struct pcctwo_attach_args *pa;
    122 	struct lpt_softc *sc;
    123 
    124 	pa = (struct pcctwo_attach_args *) args;
    125 	sc = (struct lpt_softc *) self;
    126 
    127 	/* The printer registers are part of the PCCChip2's own registers. */
    128 	sc->sc_bust = pa->pa_bust;
    129 	bus_space_map(pa->pa_bust, pa->pa_offset, PCC2REG_SIZE, 0,
    130 	    &sc->sc_bush);
    131 
    132 	sc->sc_ipl = pa->pa_ipl & PCCTWO_ICR_LEVEL_MASK;
    133 	sc->sc_laststatus = 0;
    134 	sc->sc_funcs = &lpt_pcctwo_funcs;
    135 
    136 	printf(": PCCchip2 Parallel Printer\n");
    137 
    138 	/*
    139 	 * Disable interrupts until device is opened
    140 	 */
    141 	pcc2_reg_write(sc, PCC2REG_PRT_ACK_ICSR, 0);
    142 	pcc2_reg_write(sc, PCC2REG_PRT_FAULT_ICSR, 0);
    143 	pcc2_reg_write(sc, PCC2REG_PRT_SEL_ICSR, 0);
    144 	pcc2_reg_write(sc, PCC2REG_PRT_PE_ICSR, 0);
    145 	pcc2_reg_write(sc, PCC2REG_PRT_BUSY_ICSR, 0);
    146 	pcc2_reg_write(sc, PCC2REG_PRT_CONTROL, 0);
    147 
    148 	/*
    149 	 * Main attachment code
    150 	 */
    151 	lpt_attach_subr(sc);
    152 
    153 	/* Register the event counter */
    154 	evcnt_attach_dynamic(&sc->sc_evcnt, EVCNT_TYPE_INTR,
    155 	    pcctwointr_evcnt(sc->sc_ipl), "printer", sc->sc_dev.dv_xname);
    156 
    157 	/*
    158 	 * Hook into the printer interrupt
    159 	 */
    160 	pcctwointr_establish(PCCTWOV_PRT_ACK, lpt_pcctwo_intr, sc->sc_ipl, sc,
    161 	    &sc->sc_evcnt);
    162 }
    163 
    164 /*
    165  * Handle printer interrupts
    166  */
    167 int
    168 lpt_pcctwo_intr(arg)
    169 	void *arg;
    170 {
    171 	struct lpt_softc *sc;
    172 	int i;
    173 
    174 	sc = (struct lpt_softc *) arg;
    175 
    176 	/* is printer online and ready for output */
    177 	if (lpt_pcctwo_notrdy(sc, 0) || lpt_pcctwo_notrdy(sc, 1))
    178 		return (0);
    179 
    180 	i = lpt_intr(sc);
    181 
    182 	if (pcc2_reg_read(sc, PCC2REG_PRT_INPUT_STATUS) & PCCTWO_PRT_IN_SR_PINT)
    183 		pcc2_reg_write(sc, PCC2REG_PRT_ACK_ICSR,
    184 		    sc->sc_icr | PCCTWO_ICR_ICLR);
    185 
    186 	return (i);
    187 }
    188 
    189 void
    190 lpt_pcctwo_open(sc, int_ena)
    191 	struct lpt_softc *sc;
    192 	int int_ena;
    193 {
    194 	int sps;
    195 
    196 	pcc2_reg_write(sc, PCC2REG_PRT_ACK_ICSR,
    197 	    PCCTWO_ICR_ICLR | PCCTWO_ICR_EDGE);
    198 
    199 	pcc2_reg_write(sc, PCC2REG_PRT_CONTROL,
    200 	    pcc2_reg_read(sc, PCC2REG_PRT_CONTROL) | PCCTWO_PRT_CTRL_DOEN);
    201 
    202 	if (int_ena == 0) {
    203 		sps = splhigh();
    204 		sc->sc_icr = sc->sc_ipl | PCCTWO_ICR_EDGE;
    205 		pcc2_reg_write(sc, PCC2REG_PRT_ACK_ICSR, sc->sc_icr);
    206 		splx(sps);
    207 	}
    208 }
    209 
    210 void
    211 lpt_pcctwo_close(sc)
    212 	struct lpt_softc *sc;
    213 {
    214 
    215 	pcc2_reg_write(sc, PCC2REG_PRT_ACK_ICSR,
    216 	    PCCTWO_ICR_ICLR | PCCTWO_ICR_EDGE);
    217 	pcc2_reg_write(sc, PCC2REG_PRT_CONTROL, 0);
    218 }
    219 
    220 void
    221 lpt_pcctwo_iprime(sc)
    222 	struct lpt_softc *sc;
    223 {
    224 
    225 	pcc2_reg_write(sc, PCC2REG_PRT_CONTROL,
    226 	    pcc2_reg_read(sc, PCC2REG_PRT_CONTROL) | PCCTWO_PRT_CTRL_INP);
    227 
    228 	delay(100);
    229 
    230 	pcc2_reg_write(sc, PCC2REG_PRT_CONTROL,
    231 	    pcc2_reg_read(sc, PCC2REG_PRT_CONTROL) & ~PCCTWO_PRT_CTRL_INP);
    232 
    233 	delay(100);
    234 }
    235 
    236 void
    237 lpt_pcctwo_speed(sc, speed)
    238 	struct lpt_softc *sc;
    239 	int speed;
    240 {
    241 	u_int8_t reg;
    242 
    243 	reg = pcc2_reg_read(sc, PCC2REG_PRT_CONTROL);
    244 
    245 	if (speed == LPT_STROBE_FAST)
    246 		reg |= PCCTWO_PRT_CTRL_FAST;
    247 	else
    248 		reg &= ~PCCTWO_PRT_CTRL_FAST;
    249 
    250 	pcc2_reg_write(sc, PCC2REG_PRT_CONTROL, reg);
    251 }
    252 
    253 int
    254 lpt_pcctwo_notrdy(sc, err)
    255 	struct lpt_softc *sc;
    256 	int err;
    257 {
    258 	u_int8_t status;
    259 	u_int8_t new;
    260 
    261 #define	LPS_INVERT	(PCCTWO_PRT_IN_SR_SEL)
    262 #define	LPS_MASK	(PCCTWO_PRT_IN_SR_SEL | PCCTWO_PRT_IN_SR_FLT | \
    263 			 PCCTWO_PRT_IN_SR_BSY | PCCTWO_PRT_IN_SR_PE)
    264 
    265 	status = pcc2_reg_read(sc, PCC2REG_PRT_INPUT_STATUS) ^ LPS_INVERT;
    266 	status &= LPS_MASK;
    267 
    268 	if (err) {
    269 		new = status & ~sc->sc_laststatus;
    270 		sc->sc_laststatus = status;
    271 
    272 		if (new & PCCTWO_PRT_IN_SR_SEL)
    273 			log(LOG_NOTICE, "%s: offline\n",
    274 			    sc->sc_dev.dv_xname);
    275 		else if (new & PCCTWO_PRT_IN_SR_PE)
    276 			log(LOG_NOTICE, "%s: out of paper\n",
    277 			    sc->sc_dev.dv_xname);
    278 		else if (new & PCCTWO_PRT_IN_SR_FLT)
    279 			log(LOG_NOTICE, "%s: output error\n",
    280 			    sc->sc_dev.dv_xname);
    281 	}
    282 
    283 	return (status);
    284 }
    285 
    286 void
    287 lpt_pcctwo_wr_data(sc, data)
    288 	struct lpt_softc *sc;
    289 	u_char data;
    290 {
    291 
    292 	pcc2_reg_write16(sc, PCC2REG_PRT_DATA, (u_int16_t) data);
    293 }
    294