1/* $NetBSD: ppbus_base.c,v 1.23 2023/02/13 22:44:52 andvar 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.23 2023/02/13 22:44:52 andvar 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/systm.h> 43 44#include <dev/ppbus/ppbus_1284.h> 45#include <dev/ppbus/ppbus_conf.h> 46#include <dev/ppbus/ppbus_base.h> 47#include <dev/ppbus/ppbus_device.h> 48#include <dev/ppbus/ppbus_io.h> 49#include <dev/ppbus/ppbus_var.h> 50 51#ifndef DONTPROBE_1284 52/* Utility functions */ 53static char * search_token(char *, int, const char *); 54#endif 55 56/* Perform general ppbus I/O request */ 57int 58ppbus_io(device_t dev, int iop, u_char * addr, int cnt, u_char byte) 59{ 60 struct ppbus_softc * bus = device_private(dev); 61 return (bus->ppbus_io(device_parent(dev), iop, addr, cnt, byte)); 62} 63 64/* Execute microsequence */ 65int 66ppbus_exec_microseq(device_t dev, struct ppbus_microseq ** sequence) 67{ 68 struct ppbus_softc * bus = device_private(dev); 69 return (bus->ppbus_exec_microseq(device_parent(dev), sequence)); 70} 71 72/* Read instance variables of ppbus */ 73int 74ppbus_read_ivar(device_t dev, int index, unsigned int * val) 75 76{ 77 struct ppbus_softc * bus = device_private(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(device_parent(dev), 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 */ 97int 98ppbus_write_ivar(device_t dev, int index, unsigned int * val) 99{ 100 struct ppbus_softc * bus = device_private(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(device_parent(dev), 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 */ 121int 122ppbus_poll_bus(device_t dev, int maxp, 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) ? maxp : 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; maxp == PPBUS_FOREVER || i < maxp-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 kpause("ppbuspoll", false, hz / 100, NULL); 147 break; 148 149 case PPBUS_INTR: 150 default: 151 /* wait 10 ms */ 152 error = kpause("ppbuspoll", true, hz / 100, NULL); 153 if (error != EWOULDBLOCK) { 154 return error; 155 } 156 break; 157 } 158 } 159 } 160 161 return (EWOULDBLOCK); 162} 163 164/* Get operating mode of the chipset */ 165int 166ppbus_get_mode(device_t dev) 167{ 168 struct ppbus_softc * bus = device_private(dev); 169 170 return (bus->sc_mode); 171} 172 173/* Set the operating mode of the chipset, return 0 on success. */ 174int 175ppbus_set_mode(device_t dev, int mode, int options) 176{ 177 struct ppbus_softc * bus = device_private(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 negotiations */ 185 if(bus->sc_use_ieee == PPBUS_ENABLE_IEEE) { 186 /* Cannot negotiate standard mode */ 187 if(!(mode & (PPBUS_FAST | PPBUS_COMPATIBLE))) { 188 error = ppbus_1284_negotiate(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(device_parent(dev), mode); 199 bus->sc_mode = bus->ppbus_getmode(device_parent(dev)); 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 characters to the port */ 223int 224ppbus_write(device_t dev, char * buf, int len, int how, size_t * cnt) 225{ 226 struct ppbus_softc * bus = device_private(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__, device_xname(dev)); 232 return ENODEV; 233 } 234 } 235 236 return (bus->ppbus_write(device_parent(bus->sc_dev), buf, len, how, cnt)); 237} 238 239/* Read characters from the port */ 240int 241ppbus_read(device_t dev, char * buf, int len, int how, size_t * cnt) 242{ 243 struct ppbus_softc * bus = device_private(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__, device_xname(dev)); 249 return ENODEV; 250 } 251 } 252 253 return (bus->ppbus_read(device_parent(dev), buf, len, how, cnt)); 254} 255 256/* Reset the EPP timeout bit in the status register */ 257int 258ppbus_reset_epp_timeout(device_t dev) 259{ 260 struct ppbus_softc * bus = device_private(dev); 261 262 if(bus->sc_capabilities & PPBUS_HAS_EPP) { 263 bus->ppbus_reset_epp_timeout(device_parent(dev)); 264 return 0; 265 } 266 else { 267 return ENODEV; 268 } 269} 270 271/* Wait for the ECP FIFO to be empty */ 272int 273ppbus_ecp_sync(device_t dev) 274{ 275 struct ppbus_softc * bus = device_private(dev); 276 277 if(bus->sc_capabilities & PPBUS_HAS_ECP) { 278 bus->ppbus_ecp_sync(device_parent(dev)); 279 return 0; 280 } 281 else { 282 return ENODEV; 283 } 284} 285 286/* Allocate DMA for use with ppbus */ 287int 288ppbus_dma_malloc(device_t dev, void ** buf, bus_addr_t * addr, 289 bus_size_t size) 290{ 291 struct ppbus_softc * ppbus = device_private(dev); 292 293 if(ppbus->sc_capabilities & PPBUS_HAS_DMA) 294 return (ppbus->ppbus_dma_malloc(device_parent(dev), buf, addr, 295 size)); 296 else 297 return ENODEV; 298} 299 300/* Free memory allocated with ppbus_dma_malloc() */ 301int 302ppbus_dma_free(device_t dev, void ** buf, bus_addr_t * addr, 303 bus_size_t size) 304{ 305 struct ppbus_softc * ppbus = device_private(dev); 306 307 if(ppbus->sc_capabilities & PPBUS_HAS_DMA) { 308 ppbus->ppbus_dma_free(device_parent(dev), 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 */ 317int ppbus_add_handler(device_t dev, void (*func)(void *), void *arg) 318{ 319 struct ppbus_softc * bus = device_private(dev); 320 321 if(bus->sc_capabilities & PPBUS_HAS_INTR) 322 return bus->ppbus_add_handler(device_parent(dev), func, arg); 323 else 324 return ENODEV; 325} 326 327/* Remove a handler registered with ppbus_add_handler() */ 328int ppbus_remove_handler(device_t dev, void (*func)(void *)) 329{ 330 struct ppbus_softc * bus = device_private(dev); 331 332 if(bus->sc_capabilities & PPBUS_HAS_INTR) 333 return bus->ppbus_remove_handler(device_parent(dev), 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 */ 343int 344ppbus_get_status(device_t 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 */ 359int 360ppbus_request_bus(device_t dev, device_t busdev, int how, 361 unsigned int timeout) 362{ 363 struct ppbus_softc * bus = device_private(dev); 364 unsigned int counter = timeout; 365 bool intr = (how & PPBUS_INTR) != 0; 366 int error; 367 368 /* Loop until lock acquired (if PPBUS_WAIT) or an error occurs */ 369 for(;;) { 370 if (mutex_tryenter(&(bus->sc_lock))) 371 break; 372 373 if(how & PPBUS_WAIT) { 374 error = kpause("ppbusreq", intr, hz / 2, NULL); 375 counter -= (hz/2); 376 if(!(error)) 377 continue; 378 else if(error != EWOULDBLOCK) 379 goto end; 380 if(counter == 0) { 381 error = ETIMEDOUT; 382 goto end; 383 } 384 } 385 else { 386 error = EWOULDBLOCK; 387 goto end; 388 } 389 } 390 391 /* Set bus owner or return error if bus is taken */ 392 if(bus->ppbus_owner == NULL) { 393 bus->ppbus_owner = busdev; 394 error = 0; 395 } 396 else { 397 error = EBUSY; 398 } 399 400 /* Release lock */ 401 mutex_exit(&(bus->sc_lock)); 402 403end: 404 return error; 405} 406 407/* Release the device allocated with ppbus_request_bus() */ 408int 409ppbus_release_bus(device_t dev, device_t busdev, int how, 410 unsigned int timeout) 411{ 412 struct ppbus_softc * bus = device_private(dev); 413 unsigned int counter = timeout; 414 bool intr = (how & PPBUS_INTR) != 0; 415 int error; 416 417 /* Loop until lock acquired (if PPBUS_WAIT) or an error occurs */ 418 for(;;) { 419 if (mutex_tryenter(&(bus->sc_lock))) 420 break; 421 422 if(how & PPBUS_WAIT) { 423 error = kpause("ppbusrel", intr, hz / 2, NULL); 424 counter -= (hz/2); 425 if(!(error)) 426 continue; 427 else if(error != EWOULDBLOCK) 428 goto end; 429 if(counter == 0) { 430 error = ETIMEDOUT; 431 goto end; 432 } 433 } 434 else { 435 error = EWOULDBLOCK; 436 goto end; 437 } 438 } 439 440 /* If the device is the owner, release bus */ 441 if(bus->ppbus_owner != busdev) { 442 error = EINVAL; 443 } 444 else { 445 bus->ppbus_owner = NULL; 446 error = 0; 447 } 448 449 /* Release lock */ 450 mutex_exit(&(bus->sc_lock)); 451 452end: 453 return error; 454} 455 456 457/* IEEE 1284-based probes */ 458 459#ifndef DONTPROBE_1284 460 461static const char *pnp_tokens[] = { 462 "PRINTER", "MODEM", "NET", "HDC", "PCMCIA", "MEDIA", 463 "FDC", "PORTS", "SCANNER", "DIGICAM", "", NULL }; 464 465/* ??? */ 466#if 0 467static char *pnp_classes[] = { 468 "printer", "modem", "network device", 469 "hard disk", "PCMCIA", "multimedia device", 470 "floppy disk", "ports", "scanner", 471 "digital camera", "unknown device", NULL }; 472#endif 473 474/* 475 * Search the first occurrence of a token within a string 476 * XXX should use strxxx() calls 477 */ 478static char * 479search_token(char *str, int slen, const char *token) 480{ 481 const char *p; 482 int tlen, i, j; 483 484#define UNKNOWN_LENGTH -1 485 486 if (slen == UNKNOWN_LENGTH) 487 /* get string's length */ 488 for (slen = 0, p = str; *p != '\0'; p++) 489 slen++; 490 491 /* get token's length */ 492 for (tlen = 0, p = token; *p != '\0'; p++) 493 tlen++; 494 495 if (tlen == 0) 496 return (str); 497 498 for (i = 0; i <= slen-tlen; i++) { 499 for (j = 0; j < tlen; j++) 500 if (str[i+j] != token[j]) 501 break; 502 if (j == tlen) 503 return (&str[i]); 504 } 505 506 return (NULL); 507} 508 509/* Stores the class ID of the peripheral in soft config data */ 510void 511ppbus_pnp_detect(device_t dev) 512{ 513 struct ppbus_softc * bus = device_private(dev); 514 int i; 515 int error; 516 size_t len = 0; 517 size_t str_sz = 0; 518 char * str = NULL; 519 char * class = NULL; 520 char * token; 521 522#ifdef PPBUS_VERBOSE 523 printf("%s: Probing for PnP devices.\n", device_xname(dev)); 524#endif 525 526 error = ppbus_1284_read_id(dev, PPBUS_NIBBLE, &str, &str_sz, &len); 527 if(str_sz != len) { 528#ifdef DEBUG_1284 529 printf("%s(%s): device returned less characters than expected " 530 "in device ID.\n", __func__, device_xname(dev)); 531#endif 532 } 533 if(error) { 534 printf("%s: Error getting device ID (errno = %d)\n", 535 device_xname(dev), error); 536 goto end_detect; 537 } 538 539#ifdef DEBUG_1284 540 printf("%s: <PnP> %zu characters: ", device_xname(dev), len); 541 for (i = 0; i < len; i++) 542 printf("%c(0x%x) ", str[i], str[i]); 543 printf("\n"); 544#endif 545 546 /* replace ';' characters by '\0' */ 547 for (i = 0; i < len; i++) 548 if(str[i] == ';') str[i] = '\0'; 549 /* str[i] = (str[i] == ';') ? '\0' : str[i]; */ 550 551 if ((token = search_token(str, len, "MFG")) != NULL || 552 (token = search_token(str, len, "MANUFACTURER")) != NULL) 553 printf("%s: <%s", device_xname(dev), 554 search_token(token, UNKNOWN_LENGTH, ":") + 1); 555 else 556 printf("%s: <unknown", device_xname(dev)); 557 558 if ((token = search_token(str, len, "MDL")) != NULL || 559 (token = search_token(str, len, "MODEL")) != NULL) 560 printf(" %s", 561 search_token(token, UNKNOWN_LENGTH, ":") + 1); 562 563 if ((token = search_token(str, len, "REV")) != NULL) 564 printf(".%s", 565 search_token(token, UNKNOWN_LENGTH, ":") + 1); 566 567 printf(">"); 568 569 if ((token = search_token(str, len, "CLS")) != NULL) { 570 class = search_token(token, UNKNOWN_LENGTH, ":") + 1; 571 printf(" %s", class); 572 } 573 574 if ((token = search_token(str, len, "CMD")) != NULL || 575 (token = search_token(str, len, "COMMAND")) != NULL) 576 printf(" %s", 577 search_token(token, UNKNOWN_LENGTH, ":") + 1); 578 579 printf("\n"); 580 581 if (class) { 582 /* identify class ident */ 583 for (i = 0; pnp_tokens[i] != NULL; i++) { 584 if (search_token(class, len, pnp_tokens[i]) != NULL) { 585 bus->sc_class_id = i; 586 goto end_detect; 587 } 588 } 589 } 590 bus->sc_class_id = PPBUS_PNP_UNKNOWN; 591 592end_detect: 593 if(str) 594 free(str, M_DEVBUF); 595 return; 596} 597 598/* Scan the ppbus for IEEE1284 compliant devices */ 599int 600ppbus_scan_bus(device_t dev) 601{ 602 struct ppbus_softc * bus = device_private(dev); 603 int error; 604 605 /* Try IEEE1284 modes, one device only (no IEEE1284.3 support) */ 606 607 error = ppbus_1284_negotiate(dev, PPBUS_NIBBLE, 0); 608 if (error && bus->sc_1284_state == PPBUS_ERROR 609 && bus->sc_1284_error == PPBUS_NOT_IEEE1284) 610 return (error); 611 ppbus_1284_terminate(dev); 612 613#if defined(PPBUS_VERBOSE) || defined(PPBUS_DEBUG) 614 /* IEEE1284 supported, print info */ 615 printf("%s: IEEE1284 negotiation: modes %s", 616 device_xname(dev), "NIBBLE"); 617 618 error = ppbus_1284_negotiate(dev, PPBUS_PS2, 0); 619 if (!error) 620 printf("/PS2"); 621 ppbus_1284_terminate(dev); 622 623 error = ppbus_1284_negotiate(dev, PPBUS_ECP, 0); 624 if (!error) 625 printf("/ECP"); 626 ppbus_1284_terminate(dev); 627 628 error = ppbus_1284_negotiate(dev, PPBUS_ECP, PPBUS_USE_RLE); 629 if (!error) 630 printf("/ECP_RLE"); 631 ppbus_1284_terminate(dev); 632 633 error = ppbus_1284_negotiate(dev, PPBUS_EPP, 0); 634 if (!error) 635 printf("/EPP"); 636 ppbus_1284_terminate(dev); 637 638 printf("\n"); 639#endif /* PPBUS_VERBOSE || PPBUS_DEBUG */ 640 641 return 0; 642} 643 644#endif /* !DONTPROBE_1284 */ 645 646