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 */ 53 static char * search_token(char *, int, const char *); 54 #endif 55 56 /* Perform general ppbus I/O request */ 57 int 58 ppbus_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 */ 65 int 66 ppbus_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 */ 73 int 74 ppbus_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 */ 97 int 98 ppbus_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 */ 121 int 122 ppbus_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 */ 165 int 166 ppbus_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. */ 174 int 175 ppbus_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 */ 223 int 224 ppbus_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 */ 240 int 241 ppbus_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 */ 257 int 258 ppbus_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 */ 272 int 273 ppbus_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 */ 287 int 288 ppbus_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() */ 301 int 302 ppbus_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 */ 317 int 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() */ 328 int 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 */ 343 int 344 ppbus_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 */ 359 int 360 ppbus_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 403 end: 404 return error; 405 } 406 407 /* Release the device allocated with ppbus_request_bus() */ 408 int 409 ppbus_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 452 end: 453 return error; 454 } 455 456 457 /* IEEE 1284-based probes */ 458 459 #ifndef DONTPROBE_1284 460 461 static const char *pnp_tokens[] = { 462 "PRINTER", "MODEM", "NET", "HDC", "PCMCIA", "MEDIA", 463 "FDC", "PORTS", "SCANNER", "DIGICAM", "", NULL }; 464 465 /* ??? */ 466 #if 0 467 static 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 */ 478 static char * 479 search_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 */ 510 void 511 ppbus_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 592 end_detect: 593 if(str) 594 free(str, M_DEVBUF); 595 return; 596 } 597 598 /* Scan the ppbus for IEEE1284 compliant devices */ 599 int 600 ppbus_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