| 1 | /*- |
| 2 | * SPDX-License-Identifier: BSD-2-Clause |
| 3 | * |
| 4 | * Copyright (c) 1997, 1998, 1999 Nicolas Souchu |
| 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 AND CONTRIBUTORS ``AS IS'' AND |
| 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 26 | * SUCH DAMAGE. |
| 27 | * |
| 28 | */ |
| 29 | #ifndef __PPBCONF_H |
| 30 | #define __PPBCONF_H |
| 31 | |
| 32 | #define n(flags) (~(flags) & (flags)) |
| 33 | |
| 34 | /* |
| 35 | * Parallel Port Chipset control bits. |
| 36 | */ |
| 37 | #define STROBE		0x01 |
| 38 | #define AUTOFEED	0x02 |
| 39 | #define nINIT		0x04 |
| 40 | #define SELECTIN	0x08 |
| 41 | #define IRQENABLE	0x10 |
| 42 | #define PCD		0x20 |
| 43 | |
| 44 | #define nSTROBE		n(STROBE) |
| 45 | #define nAUTOFEED	n(AUTOFEED) |
| 46 | #define INIT		n(nINIT) |
| 47 | #define nSELECTIN	n(SELECTIN) |
| 48 | #define nPCD		n(PCD) |
| 49 | |
| 50 | /* |
| 51 | * Parallel Port Chipset status bits. |
| 52 | */ |
| 53 | #define TIMEOUT		0x01 |
| 54 | #define nFAULT		0x08 |
| 55 | #define SELECT		0x10 |
| 56 | #define PERROR		0x20 |
| 57 | #define nACK		0x40 |
| 58 | #define nBUSY		0x80 |
| 59 | |
| 60 | #ifdef _KERNEL |
| 61 | #include <sys/queue.h> |
| 62 | |
| 63 | /* |
| 64 | * Parallel Port Bus sleep/wakeup queue. |
| 65 | */ |
| 66 | #define PPBPRI	(PWAIT) |
| 67 | |
| 68 | /* |
| 69 | * Parallel Port Chipset mode masks. |
| 70 | * NIBBLE mode is supposed to be available under each other modes. |
| 71 | */ |
| 72 | #define PPB_COMPATIBLE	0x0	/* Centronics compatible mode */ |
| 73 | |
| 74 | #define PPB_NIBBLE	0x1	/* reverse 4 bit mode */ |
| 75 | #define PPB_PS2		0x2	/* PS/2 byte mode */ |
| 76 | #define PPB_EPP		0x4	/* EPP mode, 32 bit */ |
| 77 | #define PPB_ECP		0x8	/* ECP mode */ |
| 78 | |
| 79 | /* mode aliases */ |
| 80 | #define PPB_SPP		PPB_NIBBLE|PPB_PS2 |
| 81 | #define PPB_BYTE	PPB_PS2 |
| 82 | |
| 83 | #define PPB_MASK		0x0f |
| 84 | #define PPB_OPTIONS_MASK	0xf0 |
| 85 | |
| 86 | #define PPB_IS_EPP(mode) (mode & PPB_EPP) |
| 87 | #define PPB_IN_EPP_MODE(bus) (PPB_IS_EPP (ppb_get_mode (bus))) |
| 88 | #define PPB_IN_NIBBLE_MODE(bus) (ppb_get_mode (bus) & PPB_NIBBLE) |
| 89 | #define PPB_IN_PS2_MODE(bus) (ppb_get_mode (bus) & PPB_PS2) |
| 90 | |
| 91 | /* |
| 92 | * Structure to store status information. |
| 93 | */ |
| 94 | struct ppb_status { |
| 95 | 	unsigned char status; |
| 96 | |
| 97 | 	unsigned int timeout:1; |
| 98 | 	unsigned int error:1; |
| 99 | 	unsigned int select:1; |
| 100 | 	unsigned int paper_end:1; |
| 101 | 	unsigned int ack:1; |
| 102 | 	unsigned int busy:1; |
| 103 | }; |
| 104 | |
| 105 | /* Parallel port bus I/O opcodes */ |
| 106 | #define PPB_OUTSB_EPP	1 |
| 107 | #define PPB_OUTSW_EPP	2 |
| 108 | #define PPB_OUTSL_EPP	3 |
| 109 | #define PPB_INSB_EPP	4 |
| 110 | #define PPB_INSW_EPP	5 |
| 111 | #define PPB_INSL_EPP	6 |
| 112 | #define PPB_RDTR	7 |
| 113 | #define PPB_RSTR	8 |
| 114 | #define PPB_RCTR	9 |
| 115 | #define PPB_REPP_A	10 |
| 116 | #define PPB_REPP_D	11 |
| 117 | #define PPB_RECR	12 |
| 118 | #define PPB_RFIFO	13 |
| 119 | #define PPB_WDTR	14 |
| 120 | #define PPB_WSTR	15 |
| 121 | #define PPB_WCTR	16 |
| 122 | #define PPB_WEPP_A	17 |
| 123 | #define PPB_WEPP_D	18 |
| 124 | #define PPB_WECR	19 |
| 125 | #define PPB_WFIFO	20 |
| 126 | |
| 127 | /* |
| 128 | * How tsleep() is called in ppb_request_bus(). |
| 129 | */ |
| 130 | #define PPB_DONTWAIT	0 |
| 131 | #define PPB_NOINTR	0 |
| 132 | #define PPB_WAIT	0x1 |
| 133 | #define PPB_INTR	0x2 |
| 134 | #define PPB_POLL	0x4 |
| 135 | #define PPB_FOREVER	-1 |
| 136 | |
| 137 | /* |
| 138 | * Microsequence stuff. |
| 139 | */ |
| 140 | #define PPB_MS_MAXLEN	64		/* XXX according to MS_INS_MASK */ |
| 141 | #define PPB_MS_MAXARGS	3		/* according to MS_ARG_MASK */ |
| 142 | |
| 143 | /* maximum number of mode dependent |
| 144 | * submicrosequences for in/out operations |
| 145 | */ |
| 146 | #define PPB_MAX_XFER	6 |
| 147 | |
| 148 | union ppb_insarg { |
| 149 | 	int	i; |
| 150 | 	void	*p; |
| 151 | 	char	*c; |
| 152 | 	int	(* f)(void *, char *); |
| 153 | }; |
| 154 | |
| 155 | struct ppb_microseq { |
| 156 | 	int			opcode;			/* microins. opcode */ |
| 157 | 	union ppb_insarg	arg[PPB_MS_MAXARGS];	/* arguments */ |
| 158 | }; |
| 159 | |
| 160 | /* microseqences used for GET/PUT operations */ |
| 161 | struct ppb_xfer { |
| 162 | 	struct ppb_microseq *loop;		/* the loop microsequence */ |
| 163 | }; |
| 164 | |
| 165 | /* |
| 166 | * Parallel Port Bus Device structure. |
| 167 | */ |
| 168 | struct ppb_data;			/* see below */ |
| 169 | |
| 170 | struct ppb_context { |
| 171 | 	int valid;			/* 1 if the struct is valid */ |
| 172 | 	int mode;			/* XXX chipset operating mode */ |
| 173 | |
| 174 | 	struct microseq *curpc;		/* pc in curmsq */ |
| 175 | 	struct microseq *curmsq;	/* currently executed microseqence */ |
| 176 | }; |
| 177 | |
| 178 | /* |
| 179 | * List of IVARS available to ppb device drivers |
| 180 | */ |
| 181 | #define PPBUS_IVAR_MODE 0 |
| 182 | |
| 183 | /* other fields are reserved to the ppbus internals */ |
| 184 | |
| 185 | struct ppb_device { |
| 186 | 	const char *name;		/* name of the device */ |
| 187 | |
| 188 | 	u_int flags;			/* flags */ |
| 189 | |
| 190 | 	struct ppb_context ctx;		/* context of the device */ |
| 191 | |
| 192 | 					/* mode dependent get msq. If NULL, |
| 193 | 					 * IEEE1284 code is used */ |
| 194 | 	struct ppb_xfer |
| 195 | 		get_xfer[PPB_MAX_XFER]; |
| 196 | |
| 197 | 					/* mode dependent put msq. If NULL, |
| 198 | 					 * IEEE1284 code is used */ |
| 199 | 	struct ppb_xfer |
| 200 | 		put_xfer[PPB_MAX_XFER]; |
| 201 | |
| 202 | 	driver_intr_t *intr_hook; |
| 203 | 	void *intr_arg; |
| 204 | }; |
| 205 | |
| 206 | /* EPP standards */ |
| 207 | #define EPP_1_9		0x0			/* default */ |
| 208 | #define EPP_1_7		0x1 |
| 209 | |
| 210 | /* Parallel Port Chipset IVARS */		/* elsewhere XXX */ |
| 211 | #define PPC_IVAR_EPP_PROTO	0 |
| 212 | #define PPC_IVAR_LOCK		1 |
| 213 | #define PPC_IVAR_INTR_HANDLER	2 |
| 214 | |
| 215 | /* |
| 216 | * Maximum size of the PnP info string |
| 217 | */ |
| 218 | #define PPB_PnP_STRING_SIZE	256			/* XXX */ |
| 219 | |
| 220 | /* |
| 221 | * Parallel Port Bus structure. |
| 222 | */ |
| 223 | struct ppb_data { |
| 224 | #define PPB_PnP_PRINTER	0 |
| 225 | #define PPB_PnP_MODEM	1 |
| 226 | #define PPB_PnP_NET	2 |
| 227 | #define PPB_PnP_HDC	3 |
| 228 | #define PPB_PnP_PCMCIA	4 |
| 229 | #define PPB_PnP_MEDIA	5 |
| 230 | #define PPB_PnP_FDC	6 |
| 231 | #define PPB_PnP_PORTS	7 |
| 232 | #define PPB_PnP_SCANNER	8 |
| 233 | #define PPB_PnP_DIGICAM	9 |
| 234 | #define PPB_PnP_UNKNOWN	10 |
| 235 | 	int class_id;		/* not a PnP device if class_id < 0 */ |
| 236 | |
| 237 | 	int state;		/* current IEEE1284 state */ |
| 238 | 	int error;		/* last IEEE1284 error */ |
| 239 | |
| 240 | 	int mode;		/* IEEE 1284-1994 mode |
| 241 | 				 * NIBBLE, PS2, EPP or ECP */ |
| 242 | |
| 243 | 	device_t ppb_owner;	/* device which owns the bus */ |
| 244 | |
| 245 | 	struct mtx *ppc_lock;	/* lock of parent device */ |
| 246 | 	struct resource *ppc_irq_res; |
| 247 | }; |
| 248 | |
| 249 | struct callout; |
| 250 | |
| 251 | typedef int (*ppc_intr_handler)(void *); |
| 252 | |
| 253 | extern int ppb_attach_device(device_t); |
| 254 | extern int ppb_request_bus(device_t, device_t, int); |
| 255 | extern int ppb_release_bus(device_t, device_t); |
| 256 | |
| 257 | /* bus related functions */ |
| 258 | extern void ppb_lock(device_t); |
| 259 | extern void ppb_unlock(device_t); |
| 260 | extern struct mtx *ppb_get_lock(device_t); |
| 261 | extern void _ppb_assert_locked(device_t, const char *, int); |
| 262 | extern void ppb_init_callout(device_t, struct callout *, int); |
| 263 | extern int ppb_sleep(device_t, void *, int, const char *, int); |
| 264 | extern int ppb_get_status(device_t, struct ppb_status *); |
| 265 | extern int ppb_poll_bus(device_t, int, uint8_t, uint8_t, int); |
| 266 | extern int ppb_reset_epp_timeout(device_t); |
| 267 | extern int ppb_ecp_sync(device_t); |
| 268 | extern int ppb_get_epp_protocol(device_t); |
| 269 | extern int ppb_set_mode(device_t, int);		/* returns old mode */ |
| 270 | extern int ppb_get_mode(device_t);		/* returns current mode */ |
| 271 | extern int ppb_write(device_t, char *, int, int); |
| 272 | |
| 273 | #ifdef INVARIANTS |
| 274 | #define ppb_assert_locked(dev)	_ppb_assert_locked(dev, __FILE__, __LINE__) |
| 275 | #else |
| 276 | #define ppb_assert_locked(dev) |
| 277 | #endif |
| 278 | #endif /* _KERNEL */ |
| 279 | |
| 280 | #endif /* !__PPBCONF_H */ |