Home | History | Annotate | Line # | Download | only in ppbus
ppbus_base.c revision 1.4
      1 /* $NetBSD: ppbus_base.c,v 1.4 2004/01/25 00:28:01 bjh21 Exp $ */
      2 
      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  * FreeBSD: src/sys/dev/ppbus/ppb_base.c,v 1.10.2.1 2000/08/01 23:26:26 n_hibma Exp
     29  *
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __KERNEL_RCSID(0, "$NetBSD: ppbus_base.c,v 1.4 2004/01/25 00:28:01 bjh21 Exp $");
     34 
     35 #include "opt_ppbus_1284.h"
     36 #include "opt_ppbus.h"
     37 
     38 #include <sys/param.h>
     39 #include <sys/kernel.h>
     40 #include <sys/malloc.h>
     41 #include <sys/proc.h>
     42 #include <sys/lock.h>
     43 #include <sys/systm.h>
     44 
     45 #include <dev/ppbus/ppbus_1284.h>
     46 #include <dev/ppbus/ppbus_conf.h>
     47 #include <dev/ppbus/ppbus_base.h>
     48 #include <dev/ppbus/ppbus_device.h>
     49 #include <dev/ppbus/ppbus_io.h>
     50 #include <dev/ppbus/ppbus_var.h>
     51 
     52 /* Utility functions */
     53 static char * search_token(char *, int, char *);
     54 
     55 
     56 /* Perform general ppbus I/O request */
     57 int
     58 ppbus_io(struct device * dev, int iop, u_char * addr, int cnt, u_char byte)
     59 {
     60 	struct ppbus_softc * bus = (struct ppbus_softc *) dev;
     61 	return (bus->ppbus_io(dev->dv_parent, iop, addr, cnt, byte));
     62 }
     63 
     64 /* Execute microsequence */
     65 int
     66 ppbus_exec_microseq(struct device * dev, struct ppbus_microseq ** sequence)
     67 {
     68 	struct ppbus_softc * bus = (struct ppbus_softc *) dev;
     69 	return (bus->ppbus_exec_microseq(dev->dv_parent, sequence));
     70 }
     71 
     72 /* Read instance variables of ppbus */
     73 int
     74 ppbus_read_ivar(struct device * dev, int index, unsigned int * val)
     75 
     76 {
     77 	struct ppbus_softc * bus = (struct ppbus_softc *) dev;
     78 
     79 	switch (index) {
     80 	case PPBUS_IVAR_INTR:
     81 	case PPBUS_IVAR_EPP_PROTO:
     82 	case PPBUS_IVAR_DMA:
     83 		return (bus->ppbus_read_ivar(dev->dv_parent, index, val));
     84 
     85 	case PPBUS_IVAR_IEEE:
     86 		*val = (bus->sc_use_ieee == PPBUS_ENABLE_IEEE) ? 1 : 0;
     87 		break;
     88 
     89 	default:
     90 		return (ENOENT);
     91 	}
     92 
     93 	return 0;
     94 }
     95 
     96 /* Write an instance variable */
     97 int
     98 ppbus_write_ivar(struct device * dev, int index, unsigned int * val)
     99 {
    100 	struct ppbus_softc * bus = (struct ppbus_softc *) dev;
    101 
    102 	switch (index) {
    103 	case PPBUS_IVAR_INTR:
    104 	case PPBUS_IVAR_EPP_PROTO:
    105 	case PPBUS_IVAR_DMA:
    106 		return (bus->ppbus_write_ivar(dev->dv_parent, index, val));
    107 
    108 	case PPBUS_IVAR_IEEE:
    109 		bus->sc_use_ieee = ((*val != 0) ? PPBUS_ENABLE_IEEE :
    110 			PPBUS_DISABLE_IEEE);
    111 		break;
    112 
    113 	default:
    114 		return (ENOENT);
    115 	}
    116 
    117 	return 0;
    118 }
    119 
    120 /* Polls the bus for a max of 10-milliseconds */
    121 int
    122 ppbus_poll_bus(struct device * dev, int max, char mask, char status,
    123 	int how)
    124 {
    125 	int i, j, error;
    126 	char r;
    127 
    128 	/* try at least up to 10ms */
    129 	for (j = 0; j < ((how & PPBUS_POLL) ? max : 1); j++) {
    130 		for (i = 0; i < 10000; i++) {
    131 			r = ppbus_rstr(dev);
    132 			DELAY(1);
    133 			if ((r & mask) == status)
    134 				return (0);
    135 		}
    136 	}
    137 
    138 	if (!(how & PPBUS_POLL)) {
    139 	   for (i = 0; max == PPBUS_FOREVER || i < max-1; i++) {
    140 		if ((ppbus_rstr(dev) & mask) == status)
    141 			return (0);
    142 
    143 		switch (how) {
    144 		case PPBUS_NOINTR:
    145 			/* wait 10 ms */
    146 			tsleep((caddr_t)dev, PPBUSPRI, "ppbuspoll", hz/100);
    147 			break;
    148 
    149 		case PPBUS_INTR:
    150 		default:
    151 			/* wait 10 ms */
    152 			if (((error = tsleep((caddr_t)dev, PPBUSPRI | PCATCH,
    153 			    "ppbuspoll", hz/100)) != EWOULDBLOCK) != 0) {
    154 				return (error);
    155 			}
    156 			break;
    157 		}
    158 	   }
    159 	}
    160 
    161 	return (EWOULDBLOCK);
    162 }
    163 
    164 /* Get operating mode of the chipset */
    165 int
    166 ppbus_get_mode(struct device * dev)
    167 {
    168 	struct ppbus_softc * bus = (struct ppbus_softc *) dev;
    169 
    170 	return (bus->sc_mode);
    171 }
    172 
    173 /* Set the operating mode of the chipset, return 0 on success. */
    174 int
    175 ppbus_set_mode(struct device * dev, int mode, int options)
    176 {
    177 	struct ppbus_softc * bus = (struct ppbus_softc *) dev;
    178 	int error = 0;
    179 
    180 	/* If no mode change, do nothing */
    181 	if(bus->sc_mode == mode)
    182 		return error;
    183 
    184 	/* Do necessary negociations */
    185 	if(bus->sc_use_ieee == PPBUS_ENABLE_IEEE) {
    186 		/* Cannot negociate standard mode */
    187 		if(!(mode & (PPBUS_FAST | PPBUS_COMPATIBLE))) {
    188  			error = ppbus_1284_negociate(dev, mode, options);
    189 		}
    190 		/* Termination is unnecessary for standard<->fast */
    191 		else if(!(bus->sc_mode & (PPBUS_FAST | PPBUS_COMPATIBLE))) {
    192 			ppbus_1284_terminate(dev);
    193 		}
    194 	}
    195 
    196 	if(!error) {
    197 		/* Set mode and update mode of ppbus to actual mode */
    198 		error = bus->ppbus_setmode(dev->dv_parent, mode);
    199 		bus->sc_mode = bus->ppbus_getmode(dev->dv_parent);
    200 	}
    201 
    202 	/* Update host state if necessary */
    203 	if(!(error) && (bus->sc_use_ieee == PPBUS_ENABLE_IEEE)) {
    204 		switch(mode) {
    205 		case PPBUS_COMPATIBLE:
    206 		case PPBUS_FAST:
    207 		case PPBUS_EPP:
    208 		case PPBUS_ECP:
    209 			ppbus_1284_set_state(dev, PPBUS_FORWARD_IDLE);
    210 			break;
    211 
    212 		case PPBUS_NIBBLE:
    213 		case PPBUS_PS2:
    214 			ppbus_1284_set_state(dev, PPBUS_REVERSE_IDLE);
    215 			break;
    216 		}
    217 	}
    218 
    219 	return error;
    220 }
    221 
    222 /* Write charaters to the port */
    223 int
    224 ppbus_write(struct device * dev, char * buf, int len, int how, size_t * cnt)
    225 {
    226 	struct ppbus_softc * bus = (struct ppbus_softc *) dev;
    227 
    228 	if(bus->sc_use_ieee == PPBUS_ENABLE_IEEE) {
    229 		if(bus->sc_1284_state != PPBUS_FORWARD_IDLE) {
    230 			printf("%s(%s): bus not in forward idle mode.\n",
    231 				__func__, dev->dv_xname);
    232 			return ENODEV;
    233 		}
    234 	}
    235 
    236 	return (bus->ppbus_write(bus->sc_dev.dv_parent, buf, len, how, cnt));
    237 }
    238 
    239 /* Read charaters from the port */
    240 int
    241 ppbus_read(struct device * dev, char * buf, int len, int how, size_t * cnt)
    242 {
    243 	struct ppbus_softc * bus = (struct ppbus_softc *) dev;
    244 
    245 	if(bus->sc_use_ieee == PPBUS_ENABLE_IEEE) {
    246 		if(bus->sc_1284_state != PPBUS_REVERSE_IDLE) {
    247 			printf("%s(%s): bus not in reverse idle mode.\n",
    248 				__func__, dev->dv_xname);
    249 			return ENODEV;
    250 		}
    251 	}
    252 
    253 	return (bus->ppbus_read(dev->dv_parent, buf, len, how, cnt));
    254 }
    255 
    256 /* Reset the EPP timeout bit in the status register */
    257 int
    258 ppbus_reset_epp_timeout(struct device * dev)
    259 {
    260 	struct ppbus_softc * bus = (struct ppbus_softc *) dev;
    261 
    262 	if(bus->sc_capabilities & PPBUS_HAS_EPP) {
    263 		bus->ppbus_reset_epp_timeout(dev->dv_parent);
    264 		return 0;
    265 	}
    266 	else {
    267 		return ENODEV;
    268 	}
    269 }
    270 
    271 /* Wait for the ECP FIFO to be empty */
    272 int
    273 ppbus_ecp_sync(struct device * dev)
    274 {
    275 	struct ppbus_softc * bus = (struct ppbus_softc *) dev;
    276 
    277 	if(bus->sc_capabilities & PPBUS_HAS_ECP) {
    278 		bus->ppbus_ecp_sync(dev->dv_parent);
    279 		return 0;
    280 	}
    281 	else {
    282 		return ENODEV;
    283 	}
    284 }
    285 
    286 /* Allocate DMA for use with ppbus */
    287 int
    288 ppbus_dma_malloc(struct device * dev, caddr_t * buf, bus_addr_t * addr,
    289 	bus_size_t size)
    290 {
    291 	struct ppbus_softc * ppbus = (struct ppbus_softc *) dev;
    292 
    293 	if(ppbus->sc_capabilities & PPBUS_HAS_DMA)
    294 		return (ppbus->ppbus_dma_malloc(dev->dv_parent, buf, addr,
    295 			size));
    296 	else
    297 		return ENODEV;
    298 }
    299 
    300 /* Free memory allocated with ppbus_dma_malloc() */
    301 int
    302 ppbus_dma_free(struct device * dev, caddr_t * buf, bus_addr_t * addr,
    303 	bus_size_t size)
    304 {
    305 	struct ppbus_softc * ppbus = (struct ppbus_softc *) dev;
    306 
    307 	if(ppbus->sc_capabilities & PPBUS_HAS_DMA) {
    308 		ppbus->ppbus_dma_free(dev->dv_parent, buf, addr, size);
    309 		return 0;
    310 	}
    311 	else {
    312 		return ENODEV;
    313 	}
    314 }
    315 
    316 /* Install a handler to be called by hardware interrupt handler */
    317 int ppbus_add_handler(struct device * dev, void (*func)(void *), void * arg)
    318 {
    319 	struct ppbus_softc * bus = (struct ppbus_softc *) dev;
    320 
    321 	if(bus->sc_capabilities & PPBUS_HAS_INTR)
    322 		return bus->ppbus_add_handler(dev->dv_parent, func, arg);
    323 	else
    324 		return ENODEV;
    325 }
    326 
    327 /* Remove a handler registered with ppbus_add_handler() */
    328 int ppbus_remove_handler(struct device * dev, void (*func)(void *))
    329 {
    330 	struct ppbus_softc * bus = (struct ppbus_softc *) dev;
    331 
    332 	if(bus->sc_capabilities & PPBUS_HAS_INTR)
    333 		return bus->ppbus_remove_handler(dev->dv_parent, func);
    334 	else
    335 		return ENODEV;
    336 }
    337 
    338 /*
    339  * ppbus_get_status()
    340  *
    341  * Read the status register and update the status info
    342  */
    343 int
    344 ppbus_get_status(struct device * dev, struct ppbus_status * status)
    345 {
    346 	register char r = status->status = ppbus_rstr(dev);
    347 
    348 	status->timeout	= r & TIMEOUT;
    349 	status->error	= !(r & nFAULT);
    350 	status->select	= r & SELECT;
    351 	status->paper_end = r & PERROR;
    352 	status->ack	= !(r & nACK);
    353 	status->busy	= !(r & nBUSY);
    354 
    355 	return (0);
    356 }
    357 
    358 /* Allocate the device to perform transfers */
    359 int
    360 ppbus_request_bus(struct device * dev, struct device * busdev, int how,
    361 	unsigned int timeout)
    362 {
    363 	struct ppbus_softc * bus = (struct ppbus_softc *) dev;
    364 	unsigned int counter = timeout;
    365 	int priority = PPBUSPRI;
    366 	int error;
    367 
    368 	if(how & PPBUS_INTR)
    369 		priority |= PCATCH;
    370 
    371 	/* Loop until lock acquired (if PPBUS_WAIT) or an error occurs */
    372 	for(;;) {
    373 		error = lockmgr(&(bus->sc_lock), LK_EXCLUSIVE | LK_RECURSEFAIL,
    374 			NULL);
    375 		if(!error)
    376 			break;
    377 
    378 		if(how & PPBUS_WAIT) {
    379 			error = ltsleep(bus, priority, __func__, hz/2, NULL);
    380 			counter -= (hz/2);
    381 			if(!(error))
    382 				continue;
    383 			else if(error != EWOULDBLOCK)
    384 				goto end;
    385 			if(counter == 0) {
    386 				error = ETIMEDOUT;
    387 				goto end;
    388 			}
    389 		}
    390 		else {
    391 			goto end;
    392 		}
    393 	}
    394 
    395 	/* Set bus owner or return error if bus is taken */
    396 	if(bus->ppbus_owner == NULL) {
    397 		bus->ppbus_owner = busdev;
    398 		error = 0;
    399 	}
    400 	else {
    401 		error = EBUSY;
    402 	}
    403 
    404 	/* Release lock */
    405 	lockmgr(&(bus->sc_lock), LK_RELEASE, NULL);
    406 
    407 end:
    408 	return error;
    409 }
    410 
    411 /* Release the device allocated with ppbus_request_bus() */
    412 int
    413 ppbus_release_bus(struct device * dev, struct device * busdev, int how,
    414 	unsigned int timeout)
    415 {
    416 	struct ppbus_softc * bus = (struct ppbus_softc *) dev;
    417 	unsigned int counter = timeout;
    418 	int priority = PPBUSPRI;
    419 	int error;
    420 
    421 	if(how & PPBUS_INTR)
    422 		priority |= PCATCH;
    423 
    424 	/* Loop until lock acquired (if PPBUS_WAIT) or an error occurs */
    425 	for(;;) {
    426 		error = lockmgr(&(bus->sc_lock), LK_EXCLUSIVE | LK_RECURSEFAIL,
    427 			NULL);
    428 		if(!error)
    429 			break;
    430 
    431 		if(how & PPBUS_WAIT) {
    432 			error = ltsleep(bus, priority, __func__, hz/2, NULL);
    433 			counter -= (hz/2);
    434 			if(!(error))
    435 				continue;
    436 			else if(error != EWOULDBLOCK)
    437 				goto end;
    438 			if(counter == 0) {
    439 				error = ETIMEDOUT;
    440 				goto end;
    441 			}
    442 		}
    443 		else {
    444 			goto end;
    445 		}
    446 	}
    447 
    448 	/* If the device is the owner, release bus */
    449 	if(bus->ppbus_owner != busdev) {
    450 		error = EINVAL;
    451 	}
    452 	else {
    453 		bus->ppbus_owner = NULL;
    454 		error = 0;
    455 	}
    456 
    457 	/* Release lock */
    458 	lockmgr(&(bus->sc_lock), LK_RELEASE, NULL);
    459 
    460 end:
    461 	return error;
    462 }
    463 
    464 
    465 /* IEEE 1284-based probes */
    466 
    467 #ifndef DONTPROBE_1284
    468 
    469 static char *pnp_tokens[] = {
    470 	"PRINTER", "MODEM", "NET", "HDC", "PCMCIA", "MEDIA",
    471 	"FDC", "PORTS", "SCANNER", "DIGICAM", "", NULL };
    472 
    473 /* ??? */
    474 #if 0
    475 static char *pnp_classes[] = {
    476 	"printer", "modem", "network device",
    477 	"hard disk", "PCMCIA", "multimedia device",
    478 	"floppy disk", "ports", "scanner",
    479 	"digital camera", "unknown device", NULL };
    480 #endif
    481 
    482 /*
    483  * Search the first occurence of a token within a string
    484  * XXX should use strxxx() calls
    485  */
    486 static char *
    487 search_token(char *str, int slen, char *token)
    488 {
    489 	char *p;
    490 	int tlen, i, j;
    491 
    492 #define UNKNOWN_LENGTH  -1
    493 
    494 	if (slen == UNKNOWN_LENGTH)
    495 	       /* get string's length */
    496 	       for (slen = 0, p = str; *p != '\0'; p++)
    497 		       slen ++;
    498 
    499        /* get token's length */
    500        for (tlen = 0, p = token; *p != '\0'; p++)
    501 	       tlen ++;
    502 
    503        if (tlen == 0)
    504 	       return (str);
    505 
    506        for (i = 0; i <= slen-tlen; i++) {
    507 	       for (j = 0; j < tlen; j++)
    508 		       if (str[i+j] != token[j])
    509 			       break;
    510 	       if (j == tlen)
    511 		       return (&str[i]);
    512        }
    513 
    514 	return (NULL);
    515 }
    516 
    517 /* Stores the class ID of the peripherial in soft config data */
    518 void
    519 ppbus_pnp_detect(struct device * dev)
    520 {
    521 	struct ppbus_softc * bus = (struct ppbus_softc *) dev;
    522 	int i;
    523 	int error;
    524 	size_t len = 0;
    525 	size_t str_sz = 0;
    526 	char * str = NULL;
    527 	char * class = NULL;
    528 	char * token;
    529 
    530 #ifdef PPBUS_VERBOSE
    531 	printf("%s: Probing for PnP devices.\n", dev->dv_xname);
    532 #endif
    533 
    534 	error = ppbus_1284_read_id(dev, PPBUS_NIBBLE, &str, &str_sz, &len);
    535 	if(str_sz != len) {
    536 #ifdef DEBUG_1284
    537 		printf("%s(%s): device returned less characters than expected "
    538 			"in device ID.\n", __func__, dev->dv_xname);
    539 #endif
    540 	}
    541 	if(error) {
    542 		printf("%s: Error getting device ID (errno = %d)\n",
    543 			dev->dv_xname, error);
    544 		goto end_detect;
    545 	}
    546 
    547 #ifdef DEBUG_1284
    548 	printf("%s: <PnP> %d characters: ", dev->dv_xname, len);
    549 	for (i = 0; i < len; i++)
    550 		printf("%c(0x%x) ", str[i], str[i]);
    551 	printf("\n");
    552 #endif
    553 
    554 	/* replace ';' characters by '\0' */
    555 	for (i = 0; i < len; i++)
    556 		if(str[i] == ';') str[i] = '\0';
    557 		/* str[i] = (str[i] == ';') ? '\0' : str[i]; */
    558 
    559 	if ((token = search_token(str, len, "MFG")) != NULL ||
    560 		(token = search_token(str, len, "MANUFACTURER")) != NULL)
    561 		printf("%s: <%s", dev->dv_xname,
    562 			search_token(token, UNKNOWN_LENGTH, ":") + 1);
    563 	else
    564 		printf("%s: <unknown", dev->dv_xname);
    565 
    566 	if ((token = search_token(str, len, "MDL")) != NULL ||
    567 		(token = search_token(str, len, "MODEL")) != NULL)
    568 		printf(" %s",
    569 			search_token(token, UNKNOWN_LENGTH, ":") + 1);
    570 
    571 	if ((token = search_token(str, len, "REV")) != NULL)
    572 		printf(".%s",
    573 			search_token(token, UNKNOWN_LENGTH, ":") + 1);
    574 
    575 	printf(">");
    576 
    577 	if ((token = search_token(str, len, "CLS")) != NULL) {
    578 		class = search_token(token, UNKNOWN_LENGTH, ":") + 1;
    579 		printf(" %s", class);
    580 	}
    581 
    582 	if ((token = search_token(str, len, "CMD")) != NULL ||
    583 		(token = search_token(str, len, "COMMAND")) != NULL)
    584 		printf(" %s",
    585 			search_token(token, UNKNOWN_LENGTH, ":") + 1);
    586 
    587 	printf("\n");
    588 
    589 	if (class) {
    590 		/* identify class ident */
    591 		for (i = 0; pnp_tokens[i] != NULL; i++) {
    592 			if (search_token(class, len, pnp_tokens[i]) != NULL) {
    593 				bus->sc_class_id = i;
    594 				goto end_detect;
    595 			}
    596 		}
    597 	}
    598 	bus->sc_class_id = PPBUS_PNP_UNKNOWN;
    599 
    600 end_detect:
    601 	if(str)
    602 		free(str, M_DEVBUF);
    603         return;
    604 }
    605 
    606 /* Scan the ppbus for IEEE1284 compliant devices */
    607 int
    608 ppbus_scan_bus(struct device * dev)
    609 {
    610 	struct ppbus_softc * bus = (struct ppbus_softc *) dev;
    611 	int error;
    612 
    613 	/* Try IEEE1284 modes, one device only (no IEEE1284.3 support) */
    614 
    615 	error = ppbus_1284_negociate(dev, PPBUS_NIBBLE, 0);
    616 	if(!(error))
    617 		printf("/NIBBLE");
    618 	else if((bus->sc_1284_state == PPBUS_ERROR) && (bus->sc_1284_error ==
    619 		PPBUS_NOT_IEEE1284))
    620 		goto end_scan;
    621 	ppbus_1284_terminate(dev);
    622 
    623 	error = ppbus_1284_negociate(dev, PPBUS_PS2, 0);
    624 	if(!(error))
    625 		printf("/PS2");
    626 	ppbus_1284_terminate(dev);
    627 
    628 	error = ppbus_1284_negociate(dev, PPBUS_ECP, 0);
    629 	if(!(error))
    630 		printf("/ECP");
    631 	ppbus_1284_terminate(dev);
    632 
    633 	error = ppbus_1284_negociate(dev, PPBUS_ECP, PPBUS_USE_RLE);
    634 	if(!(error))
    635 		printf("/ECP_RLE");
    636 	ppbus_1284_terminate(dev);
    637 
    638 	error = ppbus_1284_negociate(dev, PPBUS_EPP, 0);
    639 	if(!(error))
    640 		printf("/EPP");
    641 	ppbus_1284_terminate(dev);
    642 
    643 	printf("\n");
    644 
    645 	return 0;
    646 
    647 end_scan:
    648 	return error;
    649 }
    650 
    651 #endif /* !DONTPROBE_1284 */
    652 
    653