1 /*- 2 * Copyright (c) 1997, 1998, 1999 Nicolas Souchu 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 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 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 * $Id: ppbconf.c,v 1.10 1999/01/10 12:04:55 nsouch Exp $ 27 * 28 */ 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/kernel.h> 32 #include <sys/malloc.h> 33 34 #include <vm/vm.h> 35 #include <vm/pmap.h> 36 37 #include <dev/ppbus/ppbconf.h> 38 #include <dev/ppbus/ppb_1284.h> 39 40 #include "opt_ppb_1284.h" 41 42 LIST_HEAD(, ppb_data) ppbdata; /* list of existing ppbus */ 43 44 /* 45 * Add a null driver so that the linker set always exists. 46 */ 47 48 static struct ppb_driver nulldriver = { 49 NULL, NULL, "null" 50 }; 51 DATA_SET(ppbdriver_set, nulldriver); 52 53 54 /* 55 * ppb_alloc_bus() 56 * 57 * Allocate area to store the ppbus description. 58 */ 59 struct ppb_data * 60 ppb_alloc_bus(void) 61 { 62 struct ppb_data *ppb; 63 static int ppbdata_initted = 0; /* done-init flag */ 64 65 ppb = (struct ppb_data *) malloc(sizeof(struct ppb_data), 66 M_TEMP, M_NOWAIT); 67 68 /* 69 * Add the new parallel port bus to the list of existing ppbus. 70 */ 71 if (ppb) { 72 bzero(ppb, sizeof(struct ppb_data)); 73 74 if (!ppbdata_initted) { /* list not initialised */ 75 LIST_INIT(&ppbdata); 76 ppbdata_initted = 1; 77 } 78 LIST_INSERT_HEAD(&ppbdata, ppb, ppb_chain); 79 } else { 80 printf("ppb_alloc_bus: cannot malloc!\n"); 81 } 82 return(ppb); 83 } 84 85 #define PPB_PNP_PRINTER 0 86 #define PPB_PNP_MODEM 1 87 #define PPB_PNP_NET 2 88 #define PPB_PNP_HDC 3 89 #define PPB_PNP_PCMCIA 4 90 #define PPB_PNP_MEDIA 5 91 #define PPB_PNP_FDC 6 92 #define PPB_PNP_PORTS 7 93 #define PPB_PNP_SCANNER 8 94 #define PPB_PNP_DIGICAM 9 95 96 #ifndef DONTPROBE_1284 97 98 static char *pnp_tokens[] = { 99 "PRINTER", "MODEM", "NET", "HDC", "PCMCIA", "MEDIA", 100 "FDC", "PORTS", "SCANNER", "DIGICAM", "", NULL }; 101 102 #if 0 103 static char *pnp_classes[] = { 104 "printer", "modem", "network device", 105 "hard disk", "PCMCIA", "multimedia device", 106 "floppy disk", "ports", "scanner", 107 "digital camera", "unknown device", NULL }; 108 #endif 109 110 /* 111 * search_token() 112 * 113 * Search the first occurence of a token within a string 114 * 115 * XXX should use strxxx() calls 116 */ 117 static char * 118 search_token(char *str, int slen, char *token) 119 { 120 char *p; 121 int tlen, i, j; 122 123 #define UNKNOWN_LENGTH -1 124 125 if (slen == UNKNOWN_LENGTH) 126 /* get string's length */ 127 for (slen = 0, p = str; *p != '\0'; p++) 128 slen ++; 129 130 /* get token's length */ 131 for (tlen = 0, p = token; *p != '\0'; p++) 132 tlen ++; 133 134 if (tlen == 0) 135 return (str); 136 137 for (i = 0; i <= slen-tlen; i++) { 138 for (j = 0; j < tlen; j++) 139 if (str[i+j] != token[j]) 140 break; 141 if (j == tlen) 142 return (&str[i]); 143 } 144 145 return (NULL); 146 } 147 148 /* 149 * ppb_pnp_detect() 150 * 151 * Returns the class id. of the peripherial, -1 otherwise 152 */ 153 static int 154 ppb_pnp_detect(struct ppb_data *ppb, struct ppb_device *pnpdev) 155 { 156 char *token, *class = 0; 157 int i, len, error; 158 int class_id = -1; 159 char str[PPB_PnP_STRING_SIZE+1]; 160 161 printf("Probing for PnP devices on ppbus%d:\n", 162 ppb->ppb_link->adapter_unit); 163 164 if ((error = ppb_1284_read_id(pnpdev, PPB_NIBBLE, str, 165 PPB_PnP_STRING_SIZE, &len))) 166 goto end_detect; 167 168 #ifdef DEBUG_1284 169 printf("ppb: <PnP> %d characters: ", len); 170 for (i = 0; i < len; i++) 171 printf("%c(0x%x) ", str[i], str[i]); 172 printf("\n"); 173 #endif 174 175 /* replace ';' characters by '\0' */ 176 for (i = 0; i < len; i++) 177 str[i] = (str[i] == ';') ? '\0' : str[i]; 178 179 if ((token = search_token(str, len, "MFG")) != NULL || 180 (token = search_token(str, len, "MANUFACTURER")) != NULL) 181 printf("ppbus%d: <%s", ppb->ppb_link->adapter_unit, 182 search_token(token, UNKNOWN_LENGTH, ":") + 1); 183 else 184 printf("ppbus%d: <unknown", ppb->ppb_link->adapter_unit); 185 186 if ((token = search_token(str, len, "MDL")) != NULL || 187 (token = search_token(str, len, "MODEL")) != NULL) 188 printf(" %s", 189 search_token(token, UNKNOWN_LENGTH, ":") + 1); 190 else 191 printf(" unknown"); 192 193 if ((token = search_token(str, len, "VER")) != NULL) 194 printf("/%s", 195 search_token(token, UNKNOWN_LENGTH, ":") + 1); 196 197 if ((token = search_token(str, len, "REV")) != NULL) 198 printf(".%s", 199 search_token(token, UNKNOWN_LENGTH, ":") + 1); 200 201 printf(">"); 202 203 if ((token = search_token(str, len, "CLS")) != NULL) { 204 class = search_token(token, UNKNOWN_LENGTH, ":") + 1; 205 printf(" %s", class); 206 } 207 208 if ((token = search_token(str, len, "CMD")) != NULL || 209 (token = search_token(str, len, "COMMAND")) != NULL) 210 printf(" %s", 211 search_token(token, UNKNOWN_LENGTH, ":") + 1); 212 213 printf("\n"); 214 215 if (class) 216 /* identify class ident */ 217 for (i = 0; pnp_tokens[i] != NULL; i++) { 218 if (search_token(class, len, pnp_tokens[i]) != NULL) { 219 class_id = i; 220 goto end_detect; 221 } 222 } 223 224 class_id = PPB_PnP_UNKNOWN; 225 226 end_detect: 227 return (class_id); 228 } 229 230 /* 231 * ppb_scan_bus() 232 * 233 * Scan the ppbus for IEEE1284 compliant devices 234 */ 235 static int 236 ppb_scan_bus(struct ppb_data *ppb) 237 { 238 struct ppb_device pnpdev; /* temporary device to perform I/O */ 239 int error = 0; 240 241 /* initialize the pnpdev structure for future use */ 242 bzero(&pnpdev, sizeof(pnpdev)); 243 pnpdev.ppb = ppb; 244 245 if ((error = ppb_request_bus(&pnpdev, PPB_DONTWAIT))) { 246 if (bootverbose) 247 printf("ppb: cannot allocate ppbus!\n"); 248 249 return (error); 250 } 251 252 /* try all IEEE1284 modes, for one device only 253 * 254 * XXX We should implement the IEEE1284.3 standard to detect 255 * daisy chained devices 256 */ 257 258 error = ppb_1284_negociate(&pnpdev, PPB_NIBBLE, PPB_REQUEST_ID); 259 260 if ((ppb->state == PPB_ERROR) && (ppb->error == PPB_NOT_IEEE1284)) 261 goto end_scan; 262 263 ppb_1284_terminate(&pnpdev); 264 265 printf("ppb%d: IEEE1284 device found ", ppb->ppb_link->adapter_unit); 266 267 if (!(error = ppb_1284_negociate(&pnpdev, PPB_NIBBLE, 0))) { 268 printf("/NIBBLE"); 269 ppb_1284_terminate(&pnpdev); 270 } 271 272 if (!(error = ppb_1284_negociate(&pnpdev, PPB_PS2, 0))) { 273 printf("/PS2"); 274 ppb_1284_terminate(&pnpdev); 275 } 276 277 if (!(error = ppb_1284_negociate(&pnpdev, PPB_ECP, 0))) { 278 printf("/ECP"); 279 ppb_1284_terminate(&pnpdev); 280 } 281 282 if (!(error = ppb_1284_negociate(&pnpdev, PPB_ECP, PPB_USE_RLE))) { 283 printf("/ECP_RLE"); 284 ppb_1284_terminate(&pnpdev); 285 } 286 287 if (!(error = ppb_1284_negociate(&pnpdev, PPB_EPP, 0))) { 288 printf("/EPP"); 289 ppb_1284_terminate(&pnpdev); 290 } 291 292 #if 0 293 if (!(error = ppb_1284_negociate(&pnpdev, PPB_NIBBLE, PPB_REQUEST_ID))) { 294 printf("/NIBBLE_ID"); 295 ppb_1284_terminate(&pnpdev); 296 } 297 298 if (!(error = ppb_1284_negociate(&pnpdev, PPB_PS2, PPB_REQUEST_ID))) { 299 printf("/PS2_ID"); 300 ppb_1284_terminate(&pnpdev); 301 } 302 303 if (!(error = ppb_1284_negociate(&pnpdev, PPB_ECP, PPB_REQUEST_ID))) { 304 printf("/ECP_ID"); 305 ppb_1284_terminate(&pnpdev); 306 } 307 308 if (!(error = ppb_1284_negociate(&pnpdev, PPB_ECP, 309 PPB_REQUEST_ID | PPB_USE_RLE))) { 310 printf("/ECP_RLE_ID"); 311 ppb_1284_terminate(&pnpdev); 312 } 313 #endif 314 315 if (!(error = ppb_1284_negociate(&pnpdev, PPB_COMPATIBLE, 316 PPB_EXTENSIBILITY_LINK))) { 317 printf("/Extensibility Link"); 318 ppb_1284_terminate(&pnpdev); 319 } 320 321 /* detect PnP devices */ 322 ppb->class_id = ppb_pnp_detect(ppb, &pnpdev); 323 324 ppb_release_bus(&pnpdev); 325 326 return (0); 327 328 end_scan: 329 ppb_release_bus(&pnpdev); 330 return (error); 331 } 332 333 #endif /* !DONTPROBE_1284 */ 334 335 /* 336 * ppb_attachdevs() 337 * 338 * Called by ppcattach(), this function probes the ppbus and 339 * attaches found devices. 340 */ 341 int 342 ppb_attachdevs(struct ppb_data *ppb) 343 { 344 struct ppb_device *dev; 345 struct ppb_driver **p_drvpp, *p_drvp; 346 347 LIST_INIT(&ppb->ppb_devs); /* initialise device/driver list */ 348 p_drvpp = (struct ppb_driver **)ppbdriver_set.ls_items; 349 350 #ifndef DONTPROBE_1284 351 /* detect IEEE1284 compliant devices */ 352 ppb_scan_bus(ppb); 353 #endif /* !DONTPROBE_1284 */ 354 355 /* 356 * Blindly try all probes here. Later we should look at 357 * the parallel-port PnP standard, and intelligently seek 358 * drivers based on configuration first. 359 */ 360 while ((p_drvp = *p_drvpp++) != NULL) { 361 if (p_drvp->probe && (dev = (p_drvp->probe(ppb))) != NULL) { 362 /* 363 * Add the device to the list of probed devices. 364 */ 365 LIST_INSERT_HEAD(&ppb->ppb_devs, dev, chain); 366 367 /* Call the device's attach routine */ 368 (void)p_drvp->attach(dev); 369 } 370 } 371 return (0); 372 } 373 374 /* 375 * ppb_next_bus() 376 * 377 * Return the next bus in ppbus queue 378 */ 379 struct ppb_data * 380 ppb_next_bus(struct ppb_data *ppb) 381 { 382 383 if (ppb == NULL) 384 return (ppbdata.lh_first); 385 386 return (ppb->ppb_chain.le_next); 387 } 388 389 /* 390 * ppb_lookup_bus() 391 * 392 * Get ppb_data structure pointer according to the base address of the ppbus 393 */ 394 struct ppb_data * 395 ppb_lookup_bus(int base_port) 396 { 397 struct ppb_data *ppb; 398 399 for (ppb = ppbdata.lh_first; ppb; ppb = ppb->ppb_chain.le_next) 400 if (ppb->ppb_link->base == base_port) 401 break; 402 403 return (ppb); 404 } 405 406 /* 407 * ppb_lookup_link() 408 * 409 * Get ppb_data structure pointer according to the unit value 410 * of the corresponding link structure 411 */ 412 struct ppb_data * 413 ppb_lookup_link(int unit) 414 { 415 struct ppb_data *ppb; 416 417 for (ppb = ppbdata.lh_first; ppb; ppb = ppb->ppb_chain.le_next) 418 if (ppb->ppb_link->adapter_unit == unit) 419 break; 420 421 return (ppb); 422 } 423 424 /* 425 * ppb_attach_device() 426 * 427 * Called by loadable kernel modules to add a device 428 */ 429 int 430 ppb_attach_device(struct ppb_device *dev) 431 { 432 struct ppb_data *ppb = dev->ppb; 433 434 /* add the device to the list of probed devices */ 435 LIST_INSERT_HEAD(&ppb->ppb_devs, dev, chain); 436 437 return (0); 438 } 439 440 /* 441 * ppb_remove_device() 442 * 443 * Called by loadable kernel modules to remove a device 444 */ 445 void 446 ppb_remove_device(struct ppb_device *dev) 447 { 448 449 /* remove the device from the list of probed devices */ 450 LIST_REMOVE(dev, chain); 451 452 return; 453 } 454 455 /* 456 * ppb_request_bus() 457 * 458 * Allocate the device to perform transfers. 459 * 460 * how : PPB_WAIT or PPB_DONTWAIT 461 */ 462 int 463 ppb_request_bus(struct ppb_device *dev, int how) 464 { 465 int s, error = 0; 466 struct ppb_data *ppb = dev->ppb; 467 468 while (!error) { 469 s = splhigh(); 470 if (ppb->ppb_owner) { 471 splx(s); 472 473 switch (how) { 474 case (PPB_WAIT | PPB_INTR): 475 error = tsleep(ppb, PPBPRI|PCATCH, "ppbreq", 0); 476 break; 477 478 case (PPB_WAIT | PPB_NOINTR): 479 error = tsleep(ppb, PPBPRI, "ppbreq", 0); 480 break; 481 482 default: 483 return (EWOULDBLOCK); 484 break; 485 } 486 487 } else { 488 ppb->ppb_owner = dev; 489 490 /* restore the context of the device 491 * The first time, ctx.valid is certainly false 492 * then do not change anything. This is usefull for 493 * drivers that do not set there operating mode 494 * during attachement 495 */ 496 if (dev->ctx.valid) 497 ppb_set_mode(dev, dev->ctx.mode); 498 499 splx(s); 500 return (0); 501 } 502 } 503 504 return (error); 505 } 506 507 /* 508 * ppb_release_bus() 509 * 510 * Release the device allocated with ppb_request_dev() 511 */ 512 int 513 ppb_release_bus(struct ppb_device *dev) 514 { 515 int s; 516 struct ppb_data *ppb = dev->ppb; 517 518 s = splhigh(); 519 if (ppb->ppb_owner != dev) { 520 splx(s); 521 return (EACCES); 522 } 523 524 ppb->ppb_owner = 0; 525 splx(s); 526 527 /* save the context of the device */ 528 dev->ctx.mode = ppb_get_mode(dev); 529 530 /* ok, now the context of the device is valid */ 531 dev->ctx.valid = 1; 532 533 /* wakeup waiting processes */ 534 wakeup(ppb); 535 536 return (0); 537 } 538