if_plip.c (e7153b2583ec32ced588706fe1996d909b23bc3c) if_plip.c (46f3ff79869c85df206f0f7ef81be2e50773b913)
1/*-
2 * Copyright (c) 1997 Poul-Henning Kamp
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 10 unchanged lines hidden (view full) ---

19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * From Id: lpt.c,v 1.55.2.1 1996/11/12 09:08:38 phk Exp
1/*-
2 * Copyright (c) 1997 Poul-Henning Kamp
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 10 unchanged lines hidden (view full) ---

19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * From Id: lpt.c,v 1.55.2.1 1996/11/12 09:08:38 phk Exp
27 * $Id$
27 */
28
28 */
29
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD$");
31
32/*
33 * Parallel port TCP/IP interfaces added. I looked at the driver from
34 * MACH but this is a complete rewrite, and btw. incompatible, and it
35 * should perform better too. I have never run the MACH driver though.
36 *
37 * This driver sends two bytes (0x08, 0x00) in front of each packet,
38 * to allow us to distinguish another format later.
39 *
30/*
31 * Parallel port TCP/IP interfaces added. I looked at the driver from
32 * MACH but this is a complete rewrite, and btw. incompatible, and it
33 * should perform better too. I have never run the MACH driver though.
34 *
35 * This driver sends two bytes (0x08, 0x00) in front of each packet,
36 * to allow us to distinguish another format later.
37 *
40 * Now added a Linux/Crynwr compatibility mode which is enabled using
38 * Now added an Linux/Crynwr compatibility mode which is enabled using
41 * IF_LINK0 - Tim Wilkinson.
42 *
43 * TODO:
44 * Make HDLC/PPP mode, use IF_LLC1 to enable.
45 *
46 * Connect the two computers using a Laplink parallel cable to use this
47 * feature:
48 *

--- 24 unchanged lines hidden (view full) ---

73 * register int port asm("edx")
74 * the code would be cleaner
75 *
76 * Poul-Henning Kamp <phk@freebsd.org>
77 */
78
79/*
80 * Update for ppbus, PLIP support only - Nicolas Souchu
39 * IF_LINK0 - Tim Wilkinson.
40 *
41 * TODO:
42 * Make HDLC/PPP mode, use IF_LLC1 to enable.
43 *
44 * Connect the two computers using a Laplink parallel cable to use this
45 * feature:
46 *

--- 24 unchanged lines hidden (view full) ---

71 * register int port asm("edx")
72 * the code would be cleaner
73 *
74 * Poul-Henning Kamp <phk@freebsd.org>
75 */
76
77/*
78 * Update for ppbus, PLIP support only - Nicolas Souchu
81 */
79 */
82
80
83#include "opt_plip.h"
84
81#ifdef KERNEL
85#include <sys/param.h>
86#include <sys/systm.h>
82#include <sys/param.h>
83#include <sys/systm.h>
87#include <sys/module.h>
88#include <sys/bus.h>
84#include <sys/proc.h>
89#include <sys/mbuf.h>
90#include <sys/socket.h>
85#include <sys/mbuf.h>
86#include <sys/socket.h>
87#include <sys/filio.h>
91#include <sys/sockio.h>
92#include <sys/kernel.h>
88#include <sys/sockio.h>
89#include <sys/kernel.h>
90#include <sys/time.h>
93#include <sys/malloc.h>
94
91#include <sys/malloc.h>
92
95#include <machine/bus.h>
96#include <machine/resource.h>
97#include <sys/rman.h>
98
99#include <net/if.h>
100#include <net/if_types.h>
101#include <net/netisr.h>
93#include <net/if.h>
94#include <net/if_types.h>
95#include <net/netisr.h>
102#include <net/route.h>
103
96
97#endif /* KERNEL */
98#include <sys/mbuf.h>
99#include <sys/socket.h>
100#include <net/netisr.h>
101#include <net/route.h>
104#include <netinet/in.h>
102#include <netinet/in.h>
103#include <netinet/in_systm.h>
105#include <netinet/in_var.h>
104#include <netinet/in_var.h>
105#include <netinet/ip.h>
106#include <netinet/if_ether.h>
106
107
108#include "bpfilter.h"
109#if NBPFILTER > 0
107#include <net/bpf.h>
110#include <net/bpf.h>
111#include <net/bpfdesc.h>
112#endif
108
109#include <dev/ppbus/ppbconf.h>
113
114#include <dev/ppbus/ppbconf.h>
110#include "ppbus_if.h"
111#include <dev/ppbus/ppbio.h>
115#include <dev/ppbus/nlpt.h>
112
113#ifndef LPMTU /* MTU for the lp# interfaces */
116
117#ifndef LPMTU /* MTU for the lp# interfaces */
114#define LPMTU 1500
118#define LPMTU 1500
115#endif
116
117#ifndef LPMAXSPIN1 /* DELAY factor for the lp# interfaces */
118#define LPMAXSPIN1 8000 /* Spinning for remote intr to happen */
119#endif
120
121#ifndef LPMAXSPIN2 /* DELAY factor for the lp# interfaces */
122#define LPMAXSPIN2 500 /* Spinning for remote handshake to happen */
123#endif
124
125#ifndef LPMAXERRS /* Max errors before !RUNNING */
126#define LPMAXERRS 100
127#endif
128
119#endif
120
121#ifndef LPMAXSPIN1 /* DELAY factor for the lp# interfaces */
122#define LPMAXSPIN1 8000 /* Spinning for remote intr to happen */
123#endif
124
125#ifndef LPMAXSPIN2 /* DELAY factor for the lp# interfaces */
126#define LPMAXSPIN2 500 /* Spinning for remote handshake to happen */
127#endif
128
129#ifndef LPMAXERRS /* Max errors before !RUNNING */
130#define LPMAXERRS 100
131#endif
132
129#define CLPIPHDRLEN 14 /* We send dummy ethernet addresses (two) + packet type in front of packet */
133#define CLPIPHDRLEN 14 /* We send dummy ethernet addresses (two) + packet type in front of packet */
130#define CLPIP_SHAKE 0x80 /* This bit toggles between nibble reception */
134#define CLPIP_SHAKE 0x80 /* This bit toggles between nibble reception */
131#define MLPIPHDRLEN CLPIPHDRLEN
135#define MLPIPHDRLEN CLPIPHDRLEN
132
136
133#define LPIPHDRLEN 2 /* We send 0x08, 0x00 in front of packet */
137#define LPIPHDRLEN 2 /* We send 0x08, 0x00 in front of packet */
134#define LPIP_SHAKE 0x40 /* This bit toggles between nibble reception */
135#if !defined(MLPIPHDRLEN) || LPIPHDRLEN > MLPIPHDRLEN
138#define LPIP_SHAKE 0x40 /* This bit toggles between nibble reception */
139#if !defined(MLPIPHDRLEN) || LPIPHDRLEN > MLPIPHDRLEN
136#define MLPIPHDRLEN LPIPHDRLEN
140#define MLPIPHDRLEN LPIPHDRLEN
137#endif
138
139#define LPIPTBLSIZE 256 /* Size of octet translation table */
140
141#endif
142
143#define LPIPTBLSIZE 256 /* Size of octet translation table */
144
141#define lprintf if (lptflag) printf
145#define DEBUG
142
146
143#ifdef PLIP_DEBUG
144static int volatile lptflag = 1;
147#ifndef DEBUG
148#define lprintf (void)
145#else
149#else
146static int volatile lptflag = 0;
150#define lprintf if (lptflag) printf
151static int volatile lptflag = 1;
147#endif
148
152#endif
153
149struct lp_data {
150 struct ifnet *sc_ifp;
151 device_t sc_dev;
154struct lpt_softc {
155 unsigned short lp_unit;
156
157 struct ppb_device lp_dev;
158
159 struct ifnet sc_if;
152 u_char *sc_ifbuf;
153 int sc_iferrs;
160 u_char *sc_ifbuf;
161 int sc_iferrs;
154
155 struct resource *res_irq;
156 void *sc_intr_cookie;
157};
158
162};
163
159static struct mtx lp_tables_lock;
160MTX_SYSINIT(lp_tables, &lp_tables_lock, "plip tables", MTX_DEF);
164static int nlp = 0;
165#define MAXPLIP 8 /* XXX not much better! */
166static struct lpt_softc *lpdata[MAXPLIP];
161
167
168
162/* Tables for the lp# interface */
163static u_char *txmith;
169/* Tables for the lp# interface */
170static u_char *txmith;
164#define txmitl (txmith + (1 * LPIPTBLSIZE))
165#define trecvh (txmith + (2 * LPIPTBLSIZE))
166#define trecvl (txmith + (3 * LPIPTBLSIZE))
171#define txmitl (txmith+(1*LPIPTBLSIZE))
172#define trecvh (txmith+(2*LPIPTBLSIZE))
173#define trecvl (txmith+(3*LPIPTBLSIZE))
167
168static u_char *ctxmith;
174
175static u_char *ctxmith;
169#define ctxmitl (ctxmith + (1 * LPIPTBLSIZE))
170#define ctrecvh (ctxmith + (2 * LPIPTBLSIZE))
171#define ctrecvl (ctxmith + (3 * LPIPTBLSIZE))
176#define ctxmitl (ctxmith+(1*LPIPTBLSIZE))
177#define ctrecvh (ctxmith+(2*LPIPTBLSIZE))
178#define ctrecvl (ctxmith+(3*LPIPTBLSIZE))
172
173/* Functions for the lp# interface */
179
180/* Functions for the lp# interface */
181static struct ppb_device *lpprobe(struct ppb_data *);
182static int lpattach(struct ppb_device *);
183
174static int lpinittables(void);
175static int lpioctl(struct ifnet *, u_long, caddr_t);
176static int lpoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
184static int lpinittables(void);
185static int lpioctl(struct ifnet *, u_long, caddr_t);
186static int lpoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
177 struct route *);
178static void lpstop(struct lp_data *);
179static void lp_intr(void *);
180static int lp_module_handler(module_t, int, void *);
187 struct rtentry *);
188static void lpintr(int);
181
189
182#define DEVTOSOFTC(dev) \
183 ((struct lp_data *)device_get_softc(dev))
190/*
191 * Make ourselves visible as a ppbus driver
192 */
184
193
185static devclass_t lp_devclass;
194static struct ppb_driver lpdriver = {
195 lpprobe, lpattach, "lp"
196};
197DATA_SET(ppbdriver_set, lpdriver);
186
198
187static int
188lp_module_handler(module_t mod, int what, void *arg)
199
200/*
201 * lpprobe()
202 */
203static struct ppb_device *
204lpprobe(struct ppb_data *ppb)
189{
205{
206 struct lpt_softc *lp;
190
207
191 switch (what) {
192 case MOD_UNLOAD:
193 mtx_lock(&lp_tables_lock);
194 if (txmith != NULL) {
195 free(txmith, M_DEVBUF);
196 txmith = NULL;
197 }
198 if (ctxmith != NULL) {
199 free(ctxmith, M_DEVBUF);
200 ctxmith = NULL;
201 }
202 mtx_unlock(&lp_tables_lock);
203 break;
204 case MOD_LOAD:
205 case MOD_QUIESCE:
206 break;
207 default:
208 return (EOPNOTSUPP);
208 /* if we haven't interrupts, the probe fails */
209 if (!ppb->ppb_link->id_irq)
210 return (0);
211
212 lp = (struct lpt_softc *) malloc(sizeof(struct lpt_softc),
213 M_TEMP, M_NOWAIT);
214 if (!lp) {
215 printf("lp: cannot malloc!\n");
216 return (0);
209 }
217 }
210 return (0);
211}
218 bzero(lp, sizeof(struct lpt_softc));
212
219
213static void
214lp_identify(driver_t *driver, device_t parent)
215{
216 device_t dev;
220 lpdata[nlp] = lp;
217
221
218 dev = device_find_child(parent, "plip", -1);
219 if (!dev)
220 BUS_ADD_CHILD(parent, 0, "plip", -1);
221}
222 /*
223 * lp dependent initialisation.
224 */
225 lp->lp_unit = nlp;
222
226
223static int
224lp_probe(device_t dev)
225{
227 if (bootverbose)
228 printf("plip: irq %d", ppb->ppb_link->id_irq);
226
229
227 device_set_desc(dev, "PLIP network interface");
230 /*
231 * ppbus dependent initialisation.
232 */
233 lp->lp_dev.id_unit = lp->lp_unit;
234 lp->lp_dev.name = lpdriver.name;
235 lp->lp_dev.ppb = ppb;
236 lp->lp_dev.intr = lpintr;
228
237
229 return (0);
238 /* Ok, go to next device on next probe */
239 nlp ++;
240
241 return (&lp->lp_dev);
230}
231
232static int
242}
243
244static int
233lp_attach(device_t dev)
245lpattach (struct ppb_device *dev)
234{
246{
235 struct lp_data *lp = DEVTOSOFTC(dev);
236 struct ifnet *ifp;
237 int error, rid = 0;
247 int unit = dev->id_unit;
248 struct lpt_softc *sc = lpdata[unit];
249 struct ifnet *ifp = &sc->sc_if;
238
250
239 lp->sc_dev = dev;
240
241 /*
251 /*
242 * Reserve the interrupt resource. If we don't have one, the
243 * attach fails.
252 * Report ourselves
244 */
253 */
245 lp->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
246 RF_SHAREABLE);
247 if (lp->res_irq == 0) {
248 device_printf(dev, "cannot reserve interrupt, failed.\n");
249 return (ENXIO);
250 }
254 printf("plip%d: <PLIP network interface> on ppbus %d\n",
255 dev->id_unit, dev->ppb->ppb_link->adapter_unit);
251
256
252 ifp = lp->sc_ifp = if_alloc(IFT_PARA);
253 if (ifp == NULL) {
254 return (ENOSPC);
255 }
256
257 ifp->if_softc = lp;
258 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
257 ifp->if_softc = sc;
258 ifp->if_name = "lp";
259 ifp->if_unit = unit;
259 ifp->if_mtu = LPMTU;
260 ifp->if_flags = IFF_SIMPLEX | IFF_POINTOPOINT | IFF_MULTICAST;
261 ifp->if_ioctl = lpioctl;
262 ifp->if_output = lpoutput;
260 ifp->if_mtu = LPMTU;
261 ifp->if_flags = IFF_SIMPLEX | IFF_POINTOPOINT | IFF_MULTICAST;
262 ifp->if_ioctl = lpioctl;
263 ifp->if_output = lpoutput;
264 ifp->if_type = IFT_PARA;
263 ifp->if_hdrlen = 0;
264 ifp->if_addrlen = 0;
265 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
266 if_attach(ifp);
267
265 ifp->if_hdrlen = 0;
266 ifp->if_addrlen = 0;
267 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
268 if_attach(ifp);
269
268 bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
270#if NBPFILTER > 0
271 bpfattach(ifp, DLT_NULL, LPIPHDRLEN);
272#endif
269
273
270 /*
271 * Attach our interrupt handler. It is only called while we
272 * own the ppbus.
273 */
274 error = bus_setup_intr(dev, lp->res_irq, INTR_TYPE_NET | INTR_MPSAFE,
275 NULL, lp_intr, lp, &lp->sc_intr_cookie);
276 if (error) {
277 bpfdetach(ifp);
278 if_detach(ifp);
279 bus_release_resource(dev, SYS_RES_IRQ, 0, lp->res_irq);
280 device_printf(dev, "Unable to register interrupt handler\n");
281 return (error);
282 }
283
284 return (0);
274 return (1);
285}
275}
286
287static int
288lp_detach(device_t dev)
289{
290 struct lp_data *sc = device_get_softc(dev);
291 device_t ppbus = device_get_parent(dev);
292
293 ppb_lock(ppbus);
294 lpstop(sc);
295 ppb_unlock(ppbus);
296 bpfdetach(sc->sc_ifp);
297 if_detach(sc->sc_ifp);
298 bus_teardown_intr(dev, sc->res_irq, sc->sc_intr_cookie);
299 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->res_irq);
300 return (0);
301}
302
303/*
304 * Build the translation tables for the LPIP (BSD unix) protocol.
305 * We don't want to calculate these nasties in our tight loop, so we
306 * precalculate them when we initialize.
307 */
308static int
276/*
277 * Build the translation tables for the LPIP (BSD unix) protocol.
278 * We don't want to calculate these nasties in our tight loop, so we
279 * precalculate them when we initialize.
280 */
281static int
309lpinittables(void)
282lpinittables (void)
310{
283{
311 int i;
284 int i;
312
285
313 mtx_lock(&lp_tables_lock);
314 if (txmith == NULL)
315 txmith = malloc(4 * LPIPTBLSIZE, M_DEVBUF, M_NOWAIT);
286 if (!txmith)
287 txmith = malloc(4*LPIPTBLSIZE, M_DEVBUF, M_NOWAIT);
316
288
317 if (txmith == NULL) {
318 mtx_unlock(&lp_tables_lock);
319 return (1);
320 }
289 if (!txmith)
290 return 1;
321
291
322 if (ctxmith == NULL)
323 ctxmith = malloc(4 * LPIPTBLSIZE, M_DEVBUF, M_NOWAIT);
292 if (!ctxmith)
293 ctxmith = malloc(4*LPIPTBLSIZE, M_DEVBUF, M_NOWAIT);
324
294
325 if (ctxmith == NULL) {
326 mtx_unlock(&lp_tables_lock);
327 return (1);
328 }
295 if (!ctxmith)
296 return 1;
329
297
330 for (i = 0; i < LPIPTBLSIZE; i++) {
331 ctxmith[i] = (i & 0xF0) >> 4;
332 ctxmitl[i] = 0x10 | (i & 0x0F);
333 ctrecvh[i] = (i & 0x78) << 1;
334 ctrecvl[i] = (i & 0x78) >> 3;
335 }
298 for (i=0; i < LPIPTBLSIZE; i++) {
299 ctxmith[i] = (i & 0xF0) >> 4;
300 ctxmitl[i] = 0x10 | (i & 0x0F);
301 ctrecvh[i] = (i & 0x78) << 1;
302 ctrecvl[i] = (i & 0x78) >> 3;
303 }
336
304
337 for (i = 0; i < LPIPTBLSIZE; i++) {
338 txmith[i] = ((i & 0x80) >> 3) | ((i & 0x70) >> 4) | 0x08;
339 txmitl[i] = ((i & 0x08) << 1) | (i & 0x07);
340 trecvh[i] = ((~i) & 0x80) | ((i & 0x38) << 1);
341 trecvl[i] = (((~i) & 0x80) >> 4) | ((i & 0x38) >> 3);
342 }
343 mtx_unlock(&lp_tables_lock);
305 for (i=0; i < LPIPTBLSIZE; i++) {
306 txmith[i] = ((i & 0x80) >> 3) | ((i & 0x70) >> 4) | 0x08;
307 txmitl[i] = ((i & 0x08) << 1) | (i & 0x07);
308 trecvh[i] = ((~i) & 0x80) | ((i & 0x38) << 1);
309 trecvl[i] = (((~i) & 0x80) >> 4) | ((i & 0x38) >> 3);
310 }
344
311
345 return (0);
312 return 0;
346}
347
313}
314
348static void
349lpstop(struct lp_data *sc)
350{
351 device_t ppbus = device_get_parent(sc->sc_dev);
315/*
316 * Process an ioctl request.
317 */
352
318
353 ppb_assert_locked(ppbus);
354 ppb_wctr(ppbus, 0x00);
355 sc->sc_ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
356 free(sc->sc_ifbuf, M_DEVBUF);
357 sc->sc_ifbuf = NULL;
358
359 /* IFF_UP is not set, try to release the bus anyway */
360 ppb_release_bus(ppbus, sc->sc_dev);
361}
362
363static int
319static int
364lpinit_locked(struct ifnet *ifp)
320lpioctl (struct ifnet *ifp, u_long cmd, caddr_t data)
365{
321{
366 struct lp_data *sc = ifp->if_softc;
367 device_t dev = sc->sc_dev;
368 device_t ppbus = device_get_parent(dev);
369 int error;
322 struct lpt_softc *sc = lpdata[ifp->if_unit];
323 struct ifaddr *ifa = (struct ifaddr *)data;
324 struct ifreq *ifr = (struct ifreq *)data;
325 u_char *ptr;
326 int error;
370
327
371 ppb_assert_locked(ppbus);
372 error = ppb_request_bus(ppbus, dev, PPB_DONTWAIT);
373 if (error)
374 return (error);
328 switch (cmd) {
375
329
376 /* Now IFF_UP means that we own the bus */
377 ppb_set_mode(ppbus, PPB_COMPATIBLE);
330 case SIOCSIFDSTADDR:
331 case SIOCAIFADDR:
332 case SIOCSIFADDR:
333 if (ifa->ifa_addr->sa_family != AF_INET)
334 return EAFNOSUPPORT;
378
335
379 if (lpinittables()) {
380 ppb_release_bus(ppbus, dev);
381 return (ENOBUFS);
382 }
336 ifp->if_flags |= IFF_UP;
337 /* FALLTHROUGH */
338 case SIOCSIFFLAGS:
339 if ((!(ifp->if_flags & IFF_UP)) && (ifp->if_flags & IFF_RUNNING)) {
383
340
384 sc->sc_ifbuf = malloc(sc->sc_ifp->if_mtu + MLPIPHDRLEN,
385 M_DEVBUF, M_NOWAIT);
386 if (sc->sc_ifbuf == NULL) {
387 ppb_release_bus(ppbus, dev);
388 return (ENOBUFS);
341 ppb_wctr(&sc->lp_dev, 0x00);
342 ifp->if_flags &= ~IFF_RUNNING;
343
344 /* IFF_UP is not set, try to release the bus anyway */
345 ppb_release_bus(&sc->lp_dev);
346 break;
389 }
347 }
348 if (((ifp->if_flags & IFF_UP)) && (!(ifp->if_flags & IFF_RUNNING))) {
390
349
391 ppb_wctr(ppbus, IRQENABLE);
350 /*
351 * Try to allocate the ppbus as soon as possible
352 * With ppbus allocation, interrupts are enabled
353 * Now IFF_UP means that we own the bus
354 *
355 * XXX
356 * Should the request be interruptible?
357 */
358 if ((error = ppb_request_bus(&sc->lp_dev, PPB_WAIT|PPB_INTR)))
359 return (error);
392
360
393 ifp->if_drv_flags |= IFF_DRV_RUNNING;
394 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
395 return (0);
396}
361 if (lpinittables()) {
362 ppb_release_bus(&sc->lp_dev);
363 return ENOBUFS;
364 }
397
365
398/*
399 * Process an ioctl request.
400 */
401static int
402lpioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
403{
404 struct lp_data *sc = ifp->if_softc;
405 device_t dev = sc->sc_dev;
406 device_t ppbus = device_get_parent(dev);
407 struct ifaddr *ifa = (struct ifaddr *)data;
408 struct ifreq *ifr = (struct ifreq *)data;
409 u_char *ptr;
410 int error;
366 sc->sc_ifbuf = malloc(sc->sc_if.if_mtu + MLPIPHDRLEN,
367 M_DEVBUF, M_WAITOK);
368 if (!sc->sc_ifbuf) {
369 ppb_release_bus(&sc->lp_dev);
370 return ENOBUFS;
371 }
411
372
412 switch (cmd) {
413 case SIOCSIFDSTADDR:
414 case SIOCAIFADDR:
415 case SIOCSIFADDR:
416 if (ifa->ifa_addr->sa_family != AF_INET)
417 return (EAFNOSUPPORT);
373 ppb_wctr(&sc->lp_dev, LPC_ENA);
374 ifp->if_flags |= IFF_RUNNING;
375 }
376 break;
418
377
419 ifp->if_flags |= IFF_UP;
420 /* FALLTHROUGH */
421 case SIOCSIFFLAGS:
422 error = 0;
423 ppb_lock(ppbus);
424 if ((!(ifp->if_flags & IFF_UP)) &&
425 (ifp->if_drv_flags & IFF_DRV_RUNNING))
426 lpstop(sc);
427 else if (((ifp->if_flags & IFF_UP)) &&
428 (!(ifp->if_drv_flags & IFF_DRV_RUNNING)))
429 error = lpinit_locked(ifp);
430 ppb_unlock(ppbus);
431 return (error);
378 case SIOCSIFMTU:
379 ptr = sc->sc_ifbuf;
380 sc->sc_ifbuf = malloc(ifr->ifr_mtu+MLPIPHDRLEN, M_DEVBUF, M_NOWAIT);
381 if (!sc->sc_ifbuf) {
382 sc->sc_ifbuf = ptr;
383 return ENOBUFS;
384 }
385 if (ptr)
386 free(ptr,M_DEVBUF);
387 sc->sc_if.if_mtu = ifr->ifr_mtu;
388 break;
432
389
433 case SIOCSIFMTU:
434 ppb_lock(ppbus);
435 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
436 ptr = malloc(ifr->ifr_mtu + MLPIPHDRLEN, M_DEVBUF,
437 M_NOWAIT);
438 if (ptr == NULL) {
439 ppb_unlock(ppbus);
440 return (ENOBUFS);
441 }
442 if (sc->sc_ifbuf)
443 free(sc->sc_ifbuf, M_DEVBUF);
444 sc->sc_ifbuf = ptr;
445 }
446 sc->sc_ifp->if_mtu = ifr->ifr_mtu;
447 ppb_unlock(ppbus);
448 break;
390 case SIOCGIFMTU:
391 ifr->ifr_mtu = sc->sc_if.if_mtu;
392 break;
449
393
450 case SIOCGIFMTU:
451 ifr->ifr_mtu = sc->sc_ifp->if_mtu;
452 break;
394 case SIOCADDMULTI:
395 case SIOCDELMULTI:
396 if (ifr == 0) {
397 return EAFNOSUPPORT; /* XXX */
398 }
399 switch (ifr->ifr_addr.sa_family) {
453
400
454 case SIOCADDMULTI:
455 case SIOCDELMULTI:
456 if (ifr == 0) {
457 return (EAFNOSUPPORT); /* XXX */
458 }
459 switch (ifr->ifr_addr.sa_family) {
460 case AF_INET:
461 break;
462 default:
463 return (EAFNOSUPPORT);
464 }
465 break;
401 case AF_INET:
402 break;
466
403
467 case SIOCGIFMEDIA:
468 /*
469 * No ifmedia support at this stage; maybe use it
470 * in future for eg. protocol selection.
471 */
472 return (EINVAL);
473
474 default:
404 default:
475 lprintf("LP:ioctl(0x%lx)\n", cmd);
476 return (EINVAL);
405 return EAFNOSUPPORT;
477 }
406 }
478 return (0);
407 break;
408
409 default:
410 lprintf("LP:ioctl(0x%x)\n",cmd);
411 return EINVAL;
412 }
413 return 0;
479}
480
481static __inline int
414}
415
416static __inline int
482clpoutbyte(u_char byte, int spin, device_t ppbus)
417clpoutbyte (u_char byte, int spin, struct ppb_device *dev)
483{
418{
484
485 ppb_wdtr(ppbus, ctxmitl[byte]);
486 while (ppb_rstr(ppbus) & CLPIP_SHAKE)
419 ppb_wdtr(dev, ctxmitl[byte]);
420 while (ppb_rstr(dev) & CLPIP_SHAKE)
487 if (--spin == 0) {
421 if (--spin == 0) {
488 return (1);
422 return 1;
489 }
423 }
490 ppb_wdtr(ppbus, ctxmith[byte]);
491 while (!(ppb_rstr(ppbus) & CLPIP_SHAKE))
424 ppb_wdtr(dev, ctxmith[byte]);
425 while (!(ppb_rstr(dev) & CLPIP_SHAKE))
492 if (--spin == 0) {
426 if (--spin == 0) {
493 return (1);
427 return 1;
494 }
428 }
495 return (0);
429 return 0;
496}
497
498static __inline int
430}
431
432static __inline int
499clpinbyte(int spin, device_t ppbus)
433clpinbyte (int spin, struct ppb_device *dev)
500{
434{
501 u_char c, cl;
435 int c, cl;
502
436
503 while ((ppb_rstr(ppbus) & CLPIP_SHAKE))
504 if (!--spin) {
505 return (-1);
506 }
507 cl = ppb_rstr(ppbus);
508 ppb_wdtr(ppbus, 0x10);
437 while((ppb_rstr(dev) & CLPIP_SHAKE))
438 if(!--spin) {
439 return -1;
440 }
441 cl = ppb_rstr(dev);
442 ppb_wdtr(dev, 0x10);
509
443
510 while (!(ppb_rstr(ppbus) & CLPIP_SHAKE))
511 if (!--spin) {
512 return (-1);
513 }
514 c = ppb_rstr(ppbus);
515 ppb_wdtr(ppbus, 0x00);
444 while(!(ppb_rstr(dev) & CLPIP_SHAKE))
445 if(!--spin) {
446 return -1;
447 }
448 c = ppb_rstr(dev);
449 ppb_wdtr(dev, 0x00);
516
517 return (ctrecvl[cl] | ctrecvh[c]);
518}
519
520static void
450
451 return (ctrecvl[cl] | ctrecvh[c]);
452}
453
454static void
521lptap(struct ifnet *ifp, struct mbuf *m)
455lpintr (int unit)
522{
456{
523 u_int32_t af = AF_INET;
524
525 bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m);
526}
527
528static void
529lp_intr(void *arg)
530{
531 struct lp_data *sc = arg;
532 device_t ppbus = device_get_parent(sc->sc_dev);
533 int len, j;
457 struct lpt_softc *sc = lpdata[unit];
458 int len, s, j;
534 u_char *bp;
535 u_char c, cl;
536 struct mbuf *top;
537
459 u_char *bp;
460 u_char c, cl;
461 struct mbuf *top;
462
538 ppb_assert_locked(ppbus);
539 if (sc->sc_ifp->if_flags & IFF_LINK0) {
463 s = splhigh();
540
464
541 /* Ack. the request */
542 ppb_wdtr(ppbus, 0x01);
465 if (sc->sc_if.if_flags & IFF_LINK0) {
543
466
544 /* Get the packet length */
545 j = clpinbyte(LPMAXSPIN2, ppbus);
546 if (j == -1)
547 goto err;
548 len = j;
549 j = clpinbyte(LPMAXSPIN2, ppbus);
550 if (j == -1)
551 goto err;
552 len = len + (j << 8);
553 if (len > sc->sc_ifp->if_mtu + MLPIPHDRLEN)
554 goto err;
467 /* Ack. the request */
468 ppb_wdtr(&sc->lp_dev, 0x01);
555
469
556 bp = sc->sc_ifbuf;
470 /* Get the packet length */
471 j = clpinbyte(LPMAXSPIN2, &sc->lp_dev);
472 if (j == -1)
473 goto err;
474 len = j;
475 j = clpinbyte(LPMAXSPIN2, &sc->lp_dev);
476 if (j == -1)
477 goto err;
478 len = len + (j << 8);
479 if (len > sc->sc_if.if_mtu + MLPIPHDRLEN)
480 goto err;
557
481
558 while (len--) {
559 j = clpinbyte(LPMAXSPIN2, ppbus);
560 if (j == -1) {
561 goto err;
562 }
563 *bp++ = j;
564 }
482 bp = sc->sc_ifbuf;
483
484 while (len--) {
485 j = clpinbyte(LPMAXSPIN2, &sc->lp_dev);
486 if (j == -1) {
487 goto err;
488 }
489 *bp++ = j;
490 }
491 /* Get and ignore checksum */
492 j = clpinbyte(LPMAXSPIN2, &sc->lp_dev);
493 if (j == -1) {
494 goto err;
495 }
565
496
566 /* Get and ignore checksum */
567 j = clpinbyte(LPMAXSPIN2, ppbus);
568 if (j == -1) {
569 goto err;
570 }
497 len = bp - sc->sc_ifbuf;
498 if (len <= CLPIPHDRLEN)
499 goto err;
571
500
572 len = bp - sc->sc_ifbuf;
573 if (len <= CLPIPHDRLEN)
574 goto err;
501 sc->sc_iferrs = 0;
575
502
576 sc->sc_iferrs = 0;
577
578 len -= CLPIPHDRLEN;
579 sc->sc_ifp->if_ipackets++;
580 sc->sc_ifp->if_ibytes += len;
581 top = m_devget(sc->sc_ifbuf + CLPIPHDRLEN, len, 0, sc->sc_ifp,
582 0);
583 if (top) {
584 ppb_unlock(ppbus);
585 if (bpf_peers_present(sc->sc_ifp->if_bpf))
586 lptap(sc->sc_ifp, top);
587
588 /* mbuf is free'd on failure. */
589 netisr_queue(NETISR_IP, top);
590 ppb_lock(ppbus);
591 }
592 return;
503 if (IF_QFULL(&ipintrq)) {
504 lprintf("DROP");
505 IF_DROP(&ipintrq);
506 goto done;
507 }
508 len -= CLPIPHDRLEN;
509 sc->sc_if.if_ipackets++;
510 sc->sc_if.if_ibytes += len;
511 top = m_devget(sc->sc_ifbuf + CLPIPHDRLEN, len, 0, &sc->sc_if, 0);
512 if (top) {
513 IF_ENQUEUE(&ipintrq, top);
514 schednetisr(NETISR_IP);
515 }
516 goto done;
593 }
517 }
594 while ((ppb_rstr(ppbus) & LPIP_SHAKE)) {
595 len = sc->sc_ifp->if_mtu + LPIPHDRLEN;
596 bp = sc->sc_ifbuf;
597 while (len--) {
518 while ((ppb_rstr(&sc->lp_dev) & LPIP_SHAKE)) {
519 len = sc->sc_if.if_mtu + LPIPHDRLEN;
520 bp = sc->sc_ifbuf;
521 while (len--) {
598
522
599 cl = ppb_rstr(ppbus);
600 ppb_wdtr(ppbus, 8);
523 cl = ppb_rstr(&sc->lp_dev);
524 ppb_wdtr(&sc->lp_dev, 8);
601
525
602 j = LPMAXSPIN2;
603 while ((ppb_rstr(ppbus) & LPIP_SHAKE))
604 if (!--j)
605 goto err;
526 j = LPMAXSPIN2;
527 while((ppb_rstr(&sc->lp_dev) & LPIP_SHAKE))
528 if(!--j) goto err;
606
529
607 c = ppb_rstr(ppbus);
608 ppb_wdtr(ppbus, 0);
530 c = ppb_rstr(&sc->lp_dev);
531 ppb_wdtr(&sc->lp_dev, 0);
609
532
610 *bp++= trecvh[cl] | trecvl[c];
533 *bp++= trecvh[cl] | trecvl[c];
611
534
612 j = LPMAXSPIN2;
613 while (!((cl = ppb_rstr(ppbus)) & LPIP_SHAKE)) {
614 if (cl != c &&
615 (((cl = ppb_rstr(ppbus)) ^ 0xb8) & 0xf8) ==
616 (c & 0xf8))
617 goto end;
618 if (!--j)
619 goto err;
620 }
535 j = LPMAXSPIN2;
536 while (!((cl=ppb_rstr(&sc->lp_dev)) & LPIP_SHAKE)) {
537 if (cl != c &&
538 (((cl = ppb_rstr(&sc->lp_dev)) ^ 0xb8) & 0xf8) ==
539 (c & 0xf8))
540 goto end;
541 if (!--j) goto err;
621 }
542 }
543 }
622
623 end:
544
545 end:
624 len = bp - sc->sc_ifbuf;
625 if (len <= LPIPHDRLEN)
626 goto err;
546 len = bp - sc->sc_ifbuf;
547 if (len <= LPIPHDRLEN)
548 goto err;
627
549
628 sc->sc_iferrs = 0;
550 sc->sc_iferrs = 0;
629
551
630 len -= LPIPHDRLEN;
631 sc->sc_ifp->if_ipackets++;
632 sc->sc_ifp->if_ibytes += len;
633 top = m_devget(sc->sc_ifbuf + LPIPHDRLEN, len, 0, sc->sc_ifp,
634 0);
635 if (top) {
636 ppb_unlock(ppbus);
637 if (bpf_peers_present(sc->sc_ifp->if_bpf))
638 lptap(sc->sc_ifp, top);
639
640 /* mbuf is free'd on failure. */
641 netisr_queue(NETISR_IP, top);
642 ppb_lock(ppbus);
643 }
552 if (IF_QFULL(&ipintrq)) {
553 lprintf("DROP");
554 IF_DROP(&ipintrq);
555 goto done;
556 }
557#if NBPFILTER > 0
558 if (sc->sc_if.if_bpf) {
559 bpf_tap(&sc->sc_if, sc->sc_ifbuf, len);
560 }
561#endif
562 len -= LPIPHDRLEN;
563 sc->sc_if.if_ipackets++;
564 sc->sc_if.if_ibytes += len;
565 top = m_devget(sc->sc_ifbuf + LPIPHDRLEN, len, 0, &sc->sc_if, 0);
566 if (top) {
567 IF_ENQUEUE(&ipintrq, top);
568 schednetisr(NETISR_IP);
569 }
644 }
570 }
645 return;
571 goto done;
646
572
647err:
648 ppb_wdtr(ppbus, 0);
573 err:
574 ppb_wdtr(&sc->lp_dev, 0);
649 lprintf("R");
575 lprintf("R");
650 sc->sc_ifp->if_ierrors++;
576 sc->sc_if.if_ierrors++;
651 sc->sc_iferrs++;
652
653 /*
654 * We are not able to send receive anything for now,
655 * so stop wasting our time
656 */
657 if (sc->sc_iferrs > LPMAXERRS) {
577 sc->sc_iferrs++;
578
579 /*
580 * We are not able to send receive anything for now,
581 * so stop wasting our time
582 */
583 if (sc->sc_iferrs > LPMAXERRS) {
658 if_printf(sc->sc_ifp, "Too many errors, Going off-line.\n");
659 ppb_wctr(ppbus, 0x00);
660 sc->sc_ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
661 sc->sc_iferrs = 0;
584 printf("lp%d: Too many errors, Going off-line.\n", unit);
585 ppb_wctr(&sc->lp_dev, 0x00);
586 sc->sc_if.if_flags &= ~IFF_RUNNING;
587 sc->sc_iferrs=0;
662 }
588 }
589
590 done:
591 splx(s);
592 return;
663}
664
665static __inline int
593}
594
595static __inline int
666lpoutbyte(u_char byte, int spin, device_t ppbus)
596lpoutbyte (u_char byte, int spin, struct ppb_device *dev)
667{
597{
668
669 ppb_wdtr(ppbus, txmith[byte]);
670 while (!(ppb_rstr(ppbus) & LPIP_SHAKE))
671 if (--spin == 0)
672 return (1);
673 ppb_wdtr(ppbus, txmitl[byte]);
674 while (ppb_rstr(ppbus) & LPIP_SHAKE)
675 if (--spin == 0)
676 return (1);
677 return (0);
598 ppb_wdtr(dev, txmith[byte]);
599 while (!(ppb_rstr(dev) & LPIP_SHAKE))
600 if (--spin == 0)
601 return 1;
602 ppb_wdtr(dev, txmitl[byte]);
603 while (ppb_rstr(dev) & LPIP_SHAKE)
604 if (--spin == 0)
605 return 1;
606 return 0;
678}
679
680static int
607}
608
609static int
681lpoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
682 struct route *ro)
610lpoutput (struct ifnet *ifp, struct mbuf *m,
611 struct sockaddr *dst, struct rtentry *rt)
683{
612{
684 struct lp_data *sc = ifp->if_softc;
685 device_t dev = sc->sc_dev;
686 device_t ppbus = device_get_parent(dev);
687 int err;
688 struct mbuf *mm;
689 u_char *cp = "\0\0";
690 u_char chksum = 0;
691 int count = 0;
692 int i, len, spin;
613 struct lpt_softc *sc = lpdata[ifp->if_unit];
614 int s, err;
615 struct mbuf *mm;
616 u_char *cp = "\0\0";
617 u_char chksum = 0;
618 int count = 0;
619 int i;
620 int spin;
693
621
694 /* We need a sensible value if we abort */
695 cp++;
696 ppb_lock(ppbus);
697 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
622 /* We need a sensible value if we abort */
623 cp++;
624 ifp->if_flags |= IFF_RUNNING;
698
625
699 err = 1; /* assume we're aborting because of an error */
626 err = 1; /* assume we're aborting because of an error */
700
627
701 /* Suspend (on laptops) or receive-errors might have taken us offline */
702 ppb_wctr(ppbus, IRQENABLE);
628 s = splhigh();
703
629
704 if (ifp->if_flags & IFF_LINK0) {
705 if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) {
706 lprintf("&");
707 lp_intr(sc);
708 }
630 /* Suspend (on laptops) or receive-errors might have taken us offline */
631 ppb_wctr(&sc->lp_dev, LPC_ENA);
709
632
710 /* Alert other end to pending packet */
711 spin = LPMAXSPIN1;
712 ppb_wdtr(ppbus, 0x08);
713 while ((ppb_rstr(ppbus) & 0x08) == 0)
714 if (--spin == 0) {
715 goto nend;
716 }
633 if (ifp->if_flags & IFF_LINK0) {
717
634
718 /* Calculate length of packet, then send that */
635 if (!(ppb_rstr(&sc->lp_dev) & CLPIP_SHAKE)) {
636 lprintf("&");
637 lpintr(ifp->if_unit);
638 }
719
639
720 count += 14; /* Ethernet header len */
721
722 mm = m;
723 for (mm = m; mm; mm = mm->m_next) {
724 count += mm->m_len;
725 }
726 if (clpoutbyte(count & 0xFF, LPMAXSPIN1, ppbus))
640 /* Alert other end to pending packet */
641 spin = LPMAXSPIN1;
642 ppb_wdtr(&sc->lp_dev, 0x08);
643 while ((ppb_rstr(&sc->lp_dev) & 0x08) == 0)
644 if (--spin == 0) {
727 goto nend;
645 goto nend;
728 if (clpoutbyte((count >> 8) & 0xFF, LPMAXSPIN1, ppbus))
729 goto nend;
730
731 /* Send dummy ethernet header */
732 for (i = 0; i < 12; i++) {
733 if (clpoutbyte(i, LPMAXSPIN1, ppbus))
734 goto nend;
735 chksum += i;
736 }
737
646 }
647
738 if (clpoutbyte(0x08, LPMAXSPIN1, ppbus))
739 goto nend;
740 if (clpoutbyte(0x00, LPMAXSPIN1, ppbus))
741 goto nend;
742 chksum += 0x08 + 0x00; /* Add into checksum */
648 /* Calculate length of packet, then send that */
743
649
744 mm = m;
745 do {
746 cp = mtod(mm, u_char *);
747 len = mm->m_len;
748 while (len--) {
749 chksum += *cp;
750 if (clpoutbyte(*cp++, LPMAXSPIN2, ppbus))
751 goto nend;
752 }
753 } while ((mm = mm->m_next));
650 count += 14; /* Ethernet header len */
754
651
755 /* Send checksum */
756 if (clpoutbyte(chksum, LPMAXSPIN2, ppbus))
757 goto nend;
758
759 /* Go quiescent */
760 ppb_wdtr(ppbus, 0);
761
762 err = 0; /* No errors */
763
764 nend:
765 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
766 if (err) { /* if we didn't timeout... */
767 ifp->if_oerrors++;
768 lprintf("X");
769 } else {
770 ifp->if_opackets++;
771 ifp->if_obytes += m->m_pkthdr.len;
772 if (bpf_peers_present(ifp->if_bpf))
773 lptap(ifp, m);
774 }
775
776 m_freem(m);
777
778 if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) {
779 lprintf("^");
780 lp_intr(sc);
781 }
782 ppb_unlock(ppbus);
783 return (0);
652 mm = m;
653 for (mm = m; mm; mm = mm->m_next) {
654 count += mm->m_len;
784 }
655 }
656 if (clpoutbyte(count & 0xFF, LPMAXSPIN1, &sc->lp_dev))
657 goto nend;
658 if (clpoutbyte((count >> 8) & 0xFF, LPMAXSPIN1, &sc->lp_dev))
659 goto nend;
785
660
786 if (ppb_rstr(ppbus) & LPIP_SHAKE) {
787 lprintf("&");
788 lp_intr(sc);
661 /* Send dummy ethernet header */
662 for (i = 0; i < 12; i++) {
663 if (clpoutbyte(i, LPMAXSPIN1, &sc->lp_dev))
664 goto nend;
665 chksum += i;
789 }
790
666 }
667
791 if (lpoutbyte(0x08, LPMAXSPIN1, ppbus))
792 goto end;
793 if (lpoutbyte(0x00, LPMAXSPIN2, ppbus))
794 goto end;
668 if (clpoutbyte(0x08, LPMAXSPIN1, &sc->lp_dev))
669 goto nend;
670 if (clpoutbyte(0x00, LPMAXSPIN1, &sc->lp_dev))
671 goto nend;
672 chksum += 0x08 + 0x00; /* Add into checksum */
795
796 mm = m;
797 do {
798 cp = mtod(mm, u_char *);
673
674 mm = m;
675 do {
676 cp = mtod(mm, u_char *);
799 len = mm->m_len;
800 while (len--)
801 if (lpoutbyte(*cp++, LPMAXSPIN2, ppbus))
802 goto end;
677 while (mm->m_len--) {
678 chksum += *cp;
679 if (clpoutbyte(*cp++, LPMAXSPIN2, &sc->lp_dev))
680 goto nend;
681 }
803 } while ((mm = mm->m_next));
804
682 } while ((mm = mm->m_next));
683
805 err = 0; /* no errors were encountered */
684 /* Send checksum */
685 if (clpoutbyte(chksum, LPMAXSPIN2, &sc->lp_dev))
686 goto nend;
806
687
807end:
808 --cp;
809 ppb_wdtr(ppbus, txmitl[*cp] ^ 0x17);
688 /* Go quiescent */
689 ppb_wdtr(&sc->lp_dev, 0);
810
690
811 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
812 if (err) { /* if we didn't timeout... */
691 err = 0; /* No errors */
692
693 nend:
694 if (err) { /* if we didn't timeout... */
813 ifp->if_oerrors++;
814 lprintf("X");
815 } else {
816 ifp->if_opackets++;
817 ifp->if_obytes += m->m_pkthdr.len;
695 ifp->if_oerrors++;
696 lprintf("X");
697 } else {
698 ifp->if_opackets++;
699 ifp->if_obytes += m->m_pkthdr.len;
818 if (bpf_peers_present(ifp->if_bpf))
819 lptap(ifp, m);
820 }
821
822 m_freem(m);
823
700 }
701
702 m_freem(m);
703
824 if (ppb_rstr(ppbus) & LPIP_SHAKE) {
704 if (!(ppb_rstr(&sc->lp_dev) & CLPIP_SHAKE)) {
825 lprintf("^");
705 lprintf("^");
826 lp_intr(sc);
706 lpintr(ifp->if_unit);
827 }
707 }
708 (void) splx(s);
709 return 0;
710 }
828
711
829 ppb_unlock(ppbus);
830 return (0);
831}
712 if (ppb_rstr(&sc->lp_dev) & LPIP_SHAKE) {
713 lprintf("&");
714 lpintr(ifp->if_unit);
715 }
832
716
833static device_method_t lp_methods[] = {
834 /* device interface */
835 DEVMETHOD(device_identify, lp_identify),
836 DEVMETHOD(device_probe, lp_probe),
837 DEVMETHOD(device_attach, lp_attach),
838 DEVMETHOD(device_detach, lp_detach),
717 if (lpoutbyte(0x08, LPMAXSPIN1, &sc->lp_dev))
718 goto end;
719 if (lpoutbyte(0x00, LPMAXSPIN2, &sc->lp_dev))
720 goto end;
839
721
840 { 0, 0 }
841};
722 mm = m;
723 do {
724 cp = mtod(mm,u_char *);
725 while (mm->m_len--)
726 if (lpoutbyte(*cp++, LPMAXSPIN2, &sc->lp_dev))
727 goto end;
728 } while ((mm = mm->m_next));
842
729
843static driver_t lp_driver = {
844 "plip",
845 lp_methods,
846 sizeof(struct lp_data),
847};
730 err = 0; /* no errors were encountered */
848
731
849DRIVER_MODULE(plip, ppbus, lp_driver, lp_devclass, lp_module_handler, 0);
850MODULE_DEPEND(plip, ppbus, 1, 1, 1);
732 end:
733 --cp;
734 ppb_wdtr(&sc->lp_dev, txmitl[*cp] ^ 0x17);
735
736 if (err) { /* if we didn't timeout... */
737 ifp->if_oerrors++;
738 lprintf("X");
739 } else {
740 ifp->if_opackets++;
741 ifp->if_obytes += m->m_pkthdr.len;
742#if NBPFILTER > 0
743 if (ifp->if_bpf) {
744 /*
745 * We need to prepend the packet type as
746 * a two byte field. Cons up a dummy header
747 * to pacify bpf. This is safe because bpf
748 * will only read from the mbuf (i.e., it won't
749 * try to free it or keep a pointer to it).
750 */
751 struct mbuf m0;
752 u_short hdr = 0x800;
753
754 m0.m_next = m;
755 m0.m_len = 2;
756 m0.m_data = (char *)&hdr;
757
758 bpf_mtap(ifp, &m0);
759 }
760#endif
761 }
762
763 m_freem(m);
764
765 if (ppb_rstr(&sc->lp_dev) & LPIP_SHAKE) {
766 lprintf("^");
767 lpintr(ifp->if_unit);
768 }
769
770 (void) splx(s);
771 return 0;
772}