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