1 /* $NetBSD: lpt_pcc.c,v 1.11 2008/03/07 17:15:51 cube Exp $ */
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Steve C. Woodford.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
33 * Device Driver back-end for the MVME147's parallel printer port
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: lpt_pcc.c,v 1.11 2008/03/07 17:15:51 cube Exp $");
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/device.h>
43 #include <sys/syslog.h>
45 #include <machine/bus.h>
47 #include <dev/mvme/lptvar.h>
49 #include <mvme68k/dev/lpt_pccreg.h>
50 #include <mvme68k/dev/pccreg.h>
51 #include <mvme68k/dev/pccvar.h>
56 static int lpt_pcc_intr(void *);
57 static void lpt_pcc_open(struct lpt_softc
*, int);
58 static void lpt_pcc_close(struct lpt_softc
*);
59 static void lpt_pcc_iprime(struct lpt_softc
*);
60 static void lpt_pcc_speed(struct lpt_softc
*, int);
61 static int lpt_pcc_notrdy(struct lpt_softc
*, int);
62 static void lpt_pcc_wr_data(struct lpt_softc
*, u_char
);
64 struct lpt_funcs lpt_pcc_funcs
= {
76 static int lpt_pcc_match(device_t
, cfdata_t
, void *);
77 static void lpt_pcc_attach(device_t
, device_t
, void *);
79 CFATTACH_DECL_NEW(lpt_pcc
, sizeof(struct lpt_softc
),
80 lpt_pcc_match
, lpt_pcc_attach
, NULL
, NULL
);
85 lpt_pcc_match(device_t parent
, cfdata_t cf
, void *args
)
87 struct pcc_attach_args
*pa
;
91 if (strcmp(pa
->pa_name
, lpt_cd
.cd_name
))
94 pa
->pa_ipl
= cf
->pcccf_ipl
;
100 lpt_pcc_attach(device_t parent
, device_t self
, void *args
)
102 struct lpt_softc
*sc
;
103 struct pcc_attach_args
*pa
;
105 sc
= device_private(self
);
109 sc
->sc_bust
= pa
->pa_bust
;
110 bus_space_map(pa
->pa_bust
, pa
->pa_offset
, LPREG_SIZE
, 0, &sc
->sc_bush
);
112 sc
->sc_ipl
= pa
->pa_ipl
& PCC_IMASK
;
113 sc
->sc_funcs
= &lpt_pcc_funcs
;
114 sc
->sc_laststatus
= 0;
116 aprint_normal(": PCC Parallel Printer\n");
119 * Disable interrupts until device is opened
121 pcc_reg_write(sys_pcc
, PCCREG_PRNT_INTR_CTRL
, 0);
124 * Main attachment code
128 /* Register the event counter */
129 evcnt_attach_dynamic(&sc
->sc_evcnt
, EVCNT_TYPE_INTR
,
130 pccintr_evcnt(sc
->sc_ipl
), "printer", device_xname(sc
->sc_dev
));
133 * Hook into the printer interrupt
135 pccintr_establish(PCCV_PRINTER
, lpt_pcc_intr
, sc
->sc_ipl
, sc
,
140 * Handle printer interrupts which occur when the printer is ready to accept
144 lpt_pcc_intr(void *arg
)
146 struct lpt_softc
*sc
;
151 /* is printer online and ready for output */
152 if (lpt_pcc_notrdy(sc
, 0) && lpt_pcc_notrdy(sc
, 1))
157 if (pcc_reg_read(sys_pcc
, PCCREG_PRNT_INTR_CTRL
) & LPI_ACKINT
) {
158 pcc_reg_write(sys_pcc
, PCCREG_PRNT_INTR_CTRL
,
159 sc
->sc_icr
| LPI_ACKINT
);
167 lpt_pcc_open(struct lpt_softc
*sc
, int int_ena
)
171 pcc_reg_write(sys_pcc
, PCCREG_PRNT_INTR_CTRL
,
172 LPI_ACKINT
| LPI_FAULTINT
);
176 sc
->sc_icr
= sc
->sc_ipl
| LPI_ENABLE
;
177 pcc_reg_write(sys_pcc
, PCCREG_PRNT_INTR_CTRL
, sc
->sc_icr
);
183 lpt_pcc_close(struct lpt_softc
*sc
)
186 pcc_reg_write(sys_pcc
, PCCREG_PRNT_INTR_CTRL
, 0);
187 sc
->sc_icr
= sc
->sc_ipl
;
188 pcc_reg_write(sys_pcc
, PCCREG_PRNT_INTR_CTRL
, sc
->sc_icr
);
193 lpt_pcc_iprime(struct lpt_softc
*sc
)
196 lpt_control_write(LPC_INPUT_PRIME
);
202 lpt_pcc_speed(struct lpt_softc
*sc
, int speed
)
205 if (speed
== LPT_STROBE_FAST
)
206 lpt_control_write(LPC_FAST_STROBE
);
208 lpt_control_write(0);
212 lpt_pcc_notrdy(struct lpt_softc
*sc
, int err
)
217 #define LPS_INVERT (LPS_SELECT)
218 #define LPS_MASK (LPS_SELECT|LPS_FAULT|LPS_BUSY|LPS_PAPER_EMPTY)
220 status
= (lpt_status_read(sc
) ^ LPS_INVERT
) & LPS_MASK
;
223 new = status
& ~sc
->sc_laststatus
;
224 sc
->sc_laststatus
= status
;
226 if (new & LPS_SELECT
)
227 log(LOG_NOTICE
, "%s: offline\n",
228 device_xname(sc
->sc_dev
));
229 else if (new & LPS_PAPER_EMPTY
)
230 log(LOG_NOTICE
, "%s: out of paper\n",
231 device_xname(sc
->sc_dev
));
232 else if (new & LPS_FAULT
)
233 log(LOG_NOTICE
, "%s: output error\n",
234 device_xname(sc
->sc_dev
));
237 pcc_reg_write(sys_pcc
, PCCREG_PRNT_INTR_CTRL
,
238 sc
->sc_icr
| LPI_FAULTINT
);
244 lpt_pcc_wr_data(struct lpt_softc
*sc
, u_char data
)
247 lpt_data_write(sc
, data
);