ppbconf.c (50477) | ppbconf.c (55939) |
---|---|
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 unchanged lines hidden (view full) --- 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 * | 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 unchanged lines hidden (view full) --- 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 * $FreeBSD: head/sys/dev/ppbus/ppbconf.c 50477 1999-08-28 01:08:13Z peter $ | 26 * $FreeBSD: head/sys/dev/ppbus/ppbconf.c 55939 2000-01-14 00:18:06Z nsouch $ |
27 * 28 */ | 27 * 28 */ |
29#include "opt_ppb_1284.h" 30 |
|
29#include <sys/param.h> 30#include <sys/systm.h> | 31#include <sys/param.h> 32#include <sys/systm.h> |
31#include <sys/linker_set.h> | 33#include <sys/kernel.h> 34#include <sys/module.h> 35#include <sys/bus.h> |
32#include <sys/malloc.h> 33 | 36#include <sys/malloc.h> 37 |
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 | 38#include <dev/ppbus/ppbconf.h> 39#include <dev/ppbus/ppb_1284.h> 40 |
40#include "opt_ppb_1284.h" | 41#include "ppbus_if.h" 42 43#define DEVTOSOFTC(dev) ((struct ppb_data *)device_get_softc(dev)) 44 45MALLOC_DEFINE(M_PPBUSDEV, "ppbusdev", "Parallel Port bus device"); |
41 | 46 |
42static LIST_HEAD(, ppb_data) ppbdata; /* list of existing ppbus */ | 47static devclass_t ppbus_devclass; |
43 44/* | 48 49/* |
45 * Add a null driver so that the linker set always exists. | 50 * Device methods |
46 */ | 51 */ |
52static int ppbus_probe(device_t); 53static int ppbus_attach(device_t); 54static void ppbus_print_child(device_t bus, device_t dev); 55static int ppbus_read_ivar(device_t, device_t, int, uintptr_t *); 56static int ppbus_write_ivar(device_t, device_t, int, u_long); 57static int ppbus_setup_intr(device_t, device_t, struct resource *, int, 58 void (*)(void *), void *, void **); 59static int ppbus_teardown_intr(device_t, device_t, struct resource *, void *); |
|
47 | 60 |
48static struct ppb_driver nulldriver = { 49 NULL, NULL, "null" | 61static device_method_t ppbus_methods[] = { 62 /* device interface */ 63 DEVMETHOD(device_probe, ppbus_probe), 64 DEVMETHOD(device_attach, ppbus_attach), 65 66 /* bus interface */ 67 DEVMETHOD(bus_print_child, ppbus_print_child), 68 DEVMETHOD(bus_read_ivar, ppbus_read_ivar), 69 DEVMETHOD(bus_write_ivar, ppbus_write_ivar), 70 DEVMETHOD(bus_setup_intr, ppbus_setup_intr), 71 DEVMETHOD(bus_teardown_intr, ppbus_teardown_intr), 72 DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), 73 74 { 0, 0 } |
50}; | 75}; |
51DATA_SET(ppbdriver_set, nulldriver); | |
52 | 76 |
77static driver_t ppbus_driver = { 78 "ppbus", 79 ppbus_methods, 80 sizeof(struct ppb_data), 81 }; 82 83static void 84ppbus_print_child(device_t bus, device_t dev) 85{ 86 struct ppb_device *ppbdev; |
|
53 | 87 |
88 bus_print_child_header(bus, dev); 89 90 ppbdev = (struct ppb_device *)device_get_ivars(dev); 91 92 if (ppbdev->flags != 0) 93 printf(" flags 0x%x", ppbdev->flags); 94 95 printf(" on %s%d\n", device_get_name(bus), device_get_unit(bus)); 96 97 return; 98} 99 100static int 101ppbus_probe(device_t dev) 102{ 103 device_set_desc(dev, "Parallel port bus"); 104 105 return (0); 106} 107 |
|
54/* | 108/* |
55 * ppb_alloc_bus() | 109 * ppb_add_device() |
56 * | 110 * |
57 * Allocate area to store the ppbus description. | 111 * Add a ppbus device, allocate/initialize the ivars |
58 */ | 112 */ |
59struct ppb_data * 60ppb_alloc_bus(void) | 113static void 114ppbus_add_device(device_t dev, const char *name, int unit) |
61{ | 115{ |
62 struct ppb_data *ppb; 63 static int ppbdata_initted = 0; /* done-init flag */ | 116 struct ppb_device *ppbdev; 117 device_t child; 118 119 /* allocate ivars for the new ppbus child */ 120 ppbdev = malloc(sizeof(struct ppb_device), M_PPBUSDEV, M_NOWAIT); 121 if (!ppbdev) 122 return; 123 bzero(ppbdev, sizeof *ppbdev); |
64 | 124 |
65 ppb = (struct ppb_data *) malloc(sizeof(struct ppb_data), 66 M_TEMP, M_NOWAIT); | 125 /* initialize the ivars */ 126 ppbdev->name = name; |
67 | 127 |
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)); | 128 /* add the device as a child to the ppbus bus with the allocated 129 * ivars */ 130 child = device_add_child(dev, name, unit); 131 device_set_ivars(child, ppbdev); |
73 | 132 |
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"); | 133 return; 134} 135 136static int 137ppbus_read_ivar(device_t bus, device_t dev, int index, uintptr_t* val) 138 { 139 struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(dev); 140 141 switch (index) { 142 case PPBUS_IVAR_MODE: 143 /* XXX yet device mode = ppbus mode = chipset mode */ 144 *val = (u_long)ppb_get_mode(bus); 145 ppbdev->mode = (u_short)*val; 146 break; 147 case PPBUS_IVAR_AVM: 148 *val = (u_long)ppbdev->avm; 149 break; 150 case PPBUS_IVAR_IRQ: 151 BUS_READ_IVAR(device_get_parent(bus), bus, PPC_IVAR_IRQ, val); 152 break; 153 default: 154 return (ENOENT); |
81 } | 155 } |
82 return(ppb); | 156 157 return (0); |
83} | 158} |
159 160static int 161ppbus_write_ivar(device_t bus, device_t dev, int index, u_long val) 162{ 163 struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(dev); |
|
84 | 164 |
165 switch (index) { 166 case PPBUS_IVAR_MODE: 167 /* XXX yet device mode = ppbus mode = chipset mode */ 168 ppb_set_mode(bus,val); 169 ppbdev->mode = ppb_get_mode(bus); 170 break; 171 default: 172 return (ENOENT); 173 } 174 175 return (0); 176 } 177 |
|
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 --- 53 unchanged lines hidden (view full) --- 146} 147 148/* 149 * ppb_pnp_detect() 150 * 151 * Returns the class id. of the peripherial, -1 otherwise 152 */ 153static int | 178#define PPB_PNP_PRINTER 0 179#define PPB_PNP_MODEM 1 180#define PPB_PNP_NET 2 181#define PPB_PNP_HDC 3 182#define PPB_PNP_PCMCIA 4 183#define PPB_PNP_MEDIA 5 184#define PPB_PNP_FDC 6 185#define PPB_PNP_PORTS 7 --- 53 unchanged lines hidden (view full) --- 239} 240 241/* 242 * ppb_pnp_detect() 243 * 244 * Returns the class id. of the peripherial, -1 otherwise 245 */ 246static int |
154ppb_pnp_detect(struct ppb_data *ppb, struct ppb_device *pnpdev) | 247ppb_pnp_detect(device_t bus) |
155{ 156 char *token, *class = 0; 157 int i, len, error; 158 int class_id = -1; 159 char str[PPB_PnP_STRING_SIZE+1]; | 248{ 249 char *token, *class = 0; 250 int i, len, error; 251 int class_id = -1; 252 char str[PPB_PnP_STRING_SIZE+1]; |
253 int unit = device_get_unit(bus); |
|
160 | 254 |
161 printf("Probing for PnP devices on ppbus%d:\n", 162 ppb->ppb_link->adapter_unit); | 255 printf("Probing for PnP devices on ppbus%d:\n", unit); |
163 | 256 |
164 if ((error = ppb_1284_read_id(pnpdev, PPB_NIBBLE, str, | 257 if ((error = ppb_1284_read_id(bus, 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) | 258 PPB_PnP_STRING_SIZE, &len))) 259 goto end_detect; 260 261#ifdef DEBUG_1284 262 printf("ppb: <PnP> %d characters: ", len); 263 for (i = 0; i < len; i++) 264 printf("%c(0x%x) ", str[i], str[i]); 265 printf("\n"); 266#endif 267 268 /* replace ';' characters by '\0' */ 269 for (i = 0; i < len; i++) 270 str[i] = (str[i] == ';') ? '\0' : str[i]; 271 272 if ((token = search_token(str, len, "MFG")) != NULL || 273 (token = search_token(str, len, "MANUFACTURER")) != NULL) |
181 printf("ppbus%d: <%s", ppb->ppb_link->adapter_unit, | 274 printf("ppbus%d: <%s", unit, |
182 search_token(token, UNKNOWN_LENGTH, ":") + 1); 183 else | 275 search_token(token, UNKNOWN_LENGTH, ":") + 1); 276 else |
184 printf("ppbus%d: <unknown", ppb->ppb_link->adapter_unit); | 277 printf("ppbus%d: |
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 --- 35 unchanged lines hidden (view full) --- 228} 229 230/* 231 * ppb_scan_bus() 232 * 233 * Scan the ppbus for IEEE1284 compliant devices 234 */ 235static int | 278 279 if ((token = search_token(str, len, "MDL")) != NULL || 280 (token = search_token(str, len, "MODEL")) != NULL) 281 printf(" %s", 282 search_token(token, UNKNOWN_LENGTH, ":") + 1); 283 else 284 printf(" unknown"); 285 --- 35 unchanged lines hidden (view full) --- 321} 322 323/* 324 * ppb_scan_bus() 325 * 326 * Scan the ppbus for IEEE1284 compliant devices 327 */ 328static int |
236ppb_scan_bus(struct ppb_data *ppb) | 329ppb_scan_bus(device_t bus) |
237{ | 330{ |
238 struct ppb_device pnpdev; /* temporary device to perform I/O */ | 331 struct ppb_data * ppb = (struct ppb_data *)device_get_softc(bus); |
239 int error = 0; | 332 int error = 0; |
333 int unit = device_get_unit(bus); |
|
240 | 334 |
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 | 335 /* try all IEEE1284 modes, for one device only 336 * 337 * XXX We should implement the IEEE1284.3 standard to detect 338 * daisy chained devices 339 */ 340 |
258 error = ppb_1284_negociate(&pnpdev, PPB_NIBBLE, PPB_REQUEST_ID); | 341 error = ppb_1284_negociate(bus, PPB_NIBBLE, PPB_REQUEST_ID); |
259 260 if ((ppb->state == PPB_ERROR) && (ppb->error == PPB_NOT_IEEE1284)) 261 goto end_scan; 262 | 342 343 if ((ppb->state == PPB_ERROR) && (ppb->error == PPB_NOT_IEEE1284)) 344 goto end_scan; 345 |
263 ppb_1284_terminate(&pnpdev); | 346 ppb_1284_terminate(bus); |
264 | 347 |
265 printf("ppb%d: IEEE1284 device found ", ppb->ppb_link->adapter_unit); | 348 printf("ppbus%d: IEEE1284 device found ", unit); |
266 | 349 |
267 if (!(error = ppb_1284_negociate(&pnpdev, PPB_NIBBLE, 0))) { | 350 if (!(error = ppb_1284_negociate(bus, PPB_NIBBLE, 0))) { |
268 printf("/NIBBLE"); | 351 printf("/NIBBLE"); |
269 ppb_1284_terminate(&pnpdev); | 352 ppb_1284_terminate(bus); |
270 } 271 | 353 } 354 |
272 if (!(error = ppb_1284_negociate(&pnpdev, PPB_PS2, 0))) { | 355 if (!(error = ppb_1284_negociate(bus, PPB_PS2, 0))) { |
273 printf("/PS2"); | 356 printf("/PS2"); |
274 ppb_1284_terminate(&pnpdev); | 357 ppb_1284_terminate(bus); |
275 } 276 | 358 } 359 |
277 if (!(error = ppb_1284_negociate(&pnpdev, PPB_ECP, 0))) { | 360 if (!(error = ppb_1284_negociate(bus, PPB_ECP, 0))) { |
278 printf("/ECP"); | 361 printf("/ECP"); |
279 ppb_1284_terminate(&pnpdev); | 362 ppb_1284_terminate(bus); |
280 } 281 | 363 } 364 |
282 if (!(error = ppb_1284_negociate(&pnpdev, PPB_ECP, PPB_USE_RLE))) { | 365 if (!(error = ppb_1284_negociate(bus, PPB_ECP, PPB_USE_RLE))) { |
283 printf("/ECP_RLE"); | 366 printf("/ECP_RLE"); |
284 ppb_1284_terminate(&pnpdev); | 367 ppb_1284_terminate(bus); |
285 } 286 | 368 } 369 |
287 if (!(error = ppb_1284_negociate(&pnpdev, PPB_EPP, 0))) { | 370 if (!(error = ppb_1284_negociate(bus, PPB_EPP, 0))) { |
288 printf("/EPP"); | 371 printf("/EPP"); |
289 ppb_1284_terminate(&pnpdev); | 372 ppb_1284_terminate(bus); |
290 } 291 292 /* try more IEEE1284 modes */ 293 if (bootverbose) { | 373 } 374 375 /* try more IEEE1284 modes */ 376 if (bootverbose) { |
294 if (!(error = ppb_1284_negociate(&pnpdev, PPB_NIBBLE, | 377 if (!(error = ppb_1284_negociate(bus, PPB_NIBBLE, |
295 PPB_REQUEST_ID))) { 296 printf("/NIBBLE_ID"); | 378 PPB_REQUEST_ID))) { 379 printf("/NIBBLE_ID"); |
297 ppb_1284_terminate(&pnpdev); | 380 ppb_1284_terminate(bus); |
298 } 299 | 381 } 382 |
300 if (!(error = ppb_1284_negociate(&pnpdev, PPB_PS2, | 383 if (!(error = ppb_1284_negociate(bus, PPB_PS2, |
301 PPB_REQUEST_ID))) { 302 printf("/PS2_ID"); | 384 PPB_REQUEST_ID))) { 385 printf("/PS2_ID"); |
303 ppb_1284_terminate(&pnpdev); | 386 ppb_1284_terminate(bus); |
304 } 305 | 387 } 388 |
306 if (!(error = ppb_1284_negociate(&pnpdev, PPB_ECP, | 389 if (!(error = ppb_1284_negociate(bus, PPB_ECP, |
307 PPB_REQUEST_ID))) { 308 printf("/ECP_ID"); | 390 PPB_REQUEST_ID))) { 391 printf("/ECP_ID"); |
309 ppb_1284_terminate(&pnpdev); | 392 ppb_1284_terminate(bus); |
310 } 311 | 393 } 394 |
312 if (!(error = ppb_1284_negociate(&pnpdev, PPB_ECP, | 395 if (!(error = ppb_1284_negociate(bus, PPB_ECP, |
313 PPB_REQUEST_ID | PPB_USE_RLE))) { 314 printf("/ECP_RLE_ID"); | 396 PPB_REQUEST_ID | PPB_USE_RLE))) { 397 printf("/ECP_RLE_ID"); |
315 ppb_1284_terminate(&pnpdev); | 398 ppb_1284_terminate(bus); |
316 } 317 | 399 } 400 |
318 if (!(error = ppb_1284_negociate(&pnpdev, PPB_COMPATIBLE, | 401 if (!(error = ppb_1284_negociate(bus, PPB_COMPATIBLE, |
319 PPB_EXTENSIBILITY_LINK))) { 320 printf("/Extensibility Link"); | 402 PPB_EXTENSIBILITY_LINK))) { 403 printf("/Extensibility Link"); |
321 ppb_1284_terminate(&pnpdev); | 404 ppb_1284_terminate(bus); |
322 } 323 } 324 325 printf("\n"); 326 327 /* detect PnP devices */ | 405 } 406 } 407 408 printf("\n"); 409 410 /* detect PnP devices */ |
328 ppb->class_id = ppb_pnp_detect(ppb, &pnpdev); | 411 ppb->class_id = ppb_pnp_detect(bus); |
329 | 412 |
330 ppb_release_bus(&pnpdev); 331 | |
332 return (0); 333 334end_scan: | 413 return (0); 414 415end_scan: |
335 ppb_release_bus(&pnpdev); | |
336 return (error); 337} 338 339#endif /* !DONTPROBE_1284 */ 340 | 416 return (error); 417} 418 419#endif /* !DONTPROBE_1284 */ 420 |
341/* 342 * ppb_attachdevs() 343 * 344 * Called by ppcattach(), this function probes the ppbus and 345 * attaches found devices. 346 */ 347int 348ppb_attachdevs(struct ppb_data *ppb) | 421static int 422ppbus_attach(device_t dev) |
349{ | 423{ |
350 struct ppb_device *dev; 351 struct ppb_driver **p_drvpp, *p_drvp; | 424 int i; 425 int unit, disabled; 426 char *name; |
352 | 427 |
353 LIST_INIT(&ppb->ppb_devs); /* initialise device/driver list */ 354 p_drvpp = (struct ppb_driver **)ppbdriver_set.ls_items; 355 356#ifndef DONTPROBE_1284 357 /* detect IEEE1284 compliant devices */ 358 ppb_scan_bus(ppb); 359#endif /* !DONTPROBE_1284 */ 360 | |
361 /* | 428 /* |
362 * Blindly try all probes here. Later we should look at 363 * the parallel-port PnP standard, and intelligently seek 364 * drivers based on configuration first. | 429 * Add all devices configured to be attached to ppbus0. |
365 */ | 430 */ |
366 while ((p_drvp = *p_drvpp++) != NULL) { 367 if (p_drvp->probe && (dev = (p_drvp->probe(ppb))) != NULL) { 368 /* 369 * Add the device to the list of probed devices. 370 */ 371 LIST_INSERT_HEAD(&ppb->ppb_devs, dev, chain); 372 373 /* Call the device's attach routine */ 374 (void)p_drvp->attach(dev); 375 } | 431 for (i = resource_query_string(-1, "at", "ppbus0"); 432 i != -1; 433 i = resource_query_string(i, "at", "ppbus0")) { 434 unit = resource_query_unit(i); 435 name = resource_query_name(i); 436 if (resource_int_value(name, unit, "disabled", &disabled) == 0) { 437 if (disabled) 438 continue; 439 } 440 ppbus_add_device(dev, name, unit); |
376 } | 441 } |
377 return (0); 378} | |
379 | 442 |
380/* 381 * ppb_next_bus() 382 * 383 * Return the next bus in ppbus queue 384 */ 385struct ppb_data * 386ppb_next_bus(struct ppb_data *ppb) 387{ | 443 /* 444 * and ppbus? 445 */ 446 for (i = resource_query_string(-1, "at", "ppbus"); 447 i != -1; 448 i = resource_query_string(i, "at", "ppbus")) { 449 unit = resource_query_unit(i); 450 name = resource_query_name(i); 451 if (resource_int_value(name, unit, "disabled", &disabled) == 0) { 452 if (disabled) 453 continue; 454 } 455 ppbus_add_device(dev, name, unit); 456 } |
388 | 457 |
389 if (ppb == NULL) 390 return (ppbdata.lh_first); | 458#ifndef DONTPROBE_1284 459 /* detect IEEE1284 compliant devices */ 460 ppb_scan_bus(dev); 461#endif /* !DONTPROBE_1284 */ |
391 | 462 |
392 return (ppb->ppb_chain.le_next); 393} | 463 /* launch attachement of the added children */ 464 bus_generic_attach(dev); |
394 | 465 |
395/* 396 * ppb_lookup_bus() 397 * 398 * Get ppb_data structure pointer according to the base address of the ppbus 399 */ 400struct ppb_data * 401ppb_lookup_bus(int base_port) 402{ 403 struct ppb_data *ppb; 404 405 for (ppb = ppbdata.lh_first; ppb; ppb = ppb->ppb_chain.le_next) 406 if (ppb->ppb_link->base == base_port) 407 break; 408 409 return (ppb); | 466 return 0; |
410} 411 | 467} 468 |
412/* 413 * ppb_lookup_link() 414 * 415 * Get ppb_data structure pointer according to the unit value 416 * of the corresponding link structure 417 */ 418struct ppb_data * 419ppb_lookup_link(int unit) | 469static int 470ppbus_setup_intr(device_t bus, device_t child, struct resource *r, int flags, 471 void (*ihand)(void *), void *arg, void **cookiep) |
420{ | 472{ |
421 struct ppb_data *ppb; | 473 int error; 474 struct ppb_data *ppb = DEVTOSOFTC(bus); 475 struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(child); |
422 | 476 |
423 for (ppb = ppbdata.lh_first; ppb; ppb = ppb->ppb_chain.le_next) 424 if (ppb->ppb_link->adapter_unit == unit) 425 break; | 477 /* a device driver must own the bus to register an interrupt */ 478 if (ppb->ppb_owner != child) 479 return (EINVAL); |
426 | 480 |
427 return (ppb); 428} | 481 if ((error = BUS_SETUP_INTR(device_get_parent(bus), child, r, flags, 482 ihand, arg, cookiep))) 483 return (error); |
429 | 484 |
430/* 431 * ppb_attach_device() 432 * 433 * Called by loadable kernel modules to add a device 434 */ 435int 436ppb_attach_device(struct ppb_device *dev) 437{ 438 struct ppb_data *ppb = dev->ppb; | 485 /* store the resource and the cookie for eventually forcing 486 * handler unregistration 487 */ 488 ppbdev->intr_cookie = *cookiep; 489 ppbdev->intr_resource = r; |
439 | 490 |
440 /* add the device to the list of probed devices */ 441 LIST_INSERT_HEAD(&ppb->ppb_devs, dev, chain); 442 | |
443 return (0); 444} 445 | 491 return (0); 492} 493 |
446/* 447 * ppb_remove_device() 448 * 449 * Called by loadable kernel modules to remove a device 450 */ 451void 452ppb_remove_device(struct ppb_device *dev) | 494static int 495ppbus_teardown_intr(device_t bus, device_t child, struct resource *r, void *ih) |
453{ | 496{ |
497 struct ppb_data *ppb = DEVTOSOFTC(bus); 498 struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(child); 499 500 /* a device driver must own the bus to unregister an interrupt */ 501 if ((ppb->ppb_owner != child) || (ppbdev->intr_cookie != ih) || 502 (ppbdev->intr_resource != r)) 503 return (EINVAL); |
|
454 | 504 |
455 /* remove the device from the list of probed devices */ 456 LIST_REMOVE(dev, chain); | 505 ppbdev->intr_cookie = 0; 506 ppbdev->intr_resource = 0; |
457 | 507 |
458 return; | 508 /* pass unregistration to the upper layer */ 509 return (BUS_TEARDOWN_INTR(device_get_parent(bus), child, r, ih)); |
459} 460 461/* 462 * ppb_request_bus() 463 * 464 * Allocate the device to perform transfers. 465 * 466 * how : PPB_WAIT or PPB_DONTWAIT 467 */ 468int | 510} 511 512/* 513 * ppb_request_bus() 514 * 515 * Allocate the device to perform transfers. 516 * 517 * how : PPB_WAIT or PPB_DONTWAIT 518 */ 519int |
469ppb_request_bus(struct ppb_device *dev, int how) | 520ppb_request_bus(device_t bus, device_t dev, int how) |
470{ 471 int s, error = 0; | 521{ 522 int s, error = 0; |
472 struct ppb_data *ppb = dev->ppb; | 523 struct ppb_data *ppb = DEVTOSOFTC(bus); 524 struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(dev); |
473 474 while (!error) { 475 s = splhigh(); 476 if (ppb->ppb_owner) { 477 splx(s); 478 479 switch (how) { 480 case (PPB_WAIT | PPB_INTR): --- 13 unchanged lines hidden (view full) --- 494 ppb->ppb_owner = dev; 495 496 /* restore the context of the device 497 * The first time, ctx.valid is certainly false 498 * then do not change anything. This is usefull for 499 * drivers that do not set there operating mode 500 * during attachement 501 */ | 525 526 while (!error) { 527 s = splhigh(); 528 if (ppb->ppb_owner) { 529 splx(s); 530 531 switch (how) { 532 case (PPB_WAIT | PPB_INTR): --- 13 unchanged lines hidden (view full) --- 546 ppb->ppb_owner = dev; 547 548 /* restore the context of the device 549 * The first time, ctx.valid is certainly false 550 * then do not change anything. This is usefull for 551 * drivers that do not set there operating mode 552 * during attachement 553 */ |
502 if (dev->ctx.valid) 503 ppb_set_mode(dev, dev->ctx.mode); | 554 if (ppbdev->ctx.valid) 555 ppb_set_mode(bus, ppbdev->ctx.mode); |
504 505 splx(s); 506 return (0); 507 } 508 } 509 510 return (error); 511} 512 513/* 514 * ppb_release_bus() 515 * 516 * Release the device allocated with ppb_request_dev() 517 */ 518int | 556 557 splx(s); 558 return (0); 559 } 560 } 561 562 return (error); 563} 564 565/* 566 * ppb_release_bus() 567 * 568 * Release the device allocated with ppb_request_dev() 569 */ 570int |
519ppb_release_bus(struct ppb_device *dev) | 571ppb_release_bus(device_t bus, device_t dev) |
520{ | 572{ |
521 int s; 522 struct ppb_data *ppb = dev->ppb; | 573 int s, error; 574 struct ppb_data *ppb = DEVTOSOFTC(bus); 575 struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(dev); |
523 | 576 |
577 if (ppbdev->intr_resource != 0) 578 /* force interrupt handler unregistration when the ppbus is released */ 579 if ((error = BUS_TEARDOWN_INTR(bus, dev, ppbdev->intr_resource, 580 ppbdev->intr_cookie))) 581 return (error); 582 |
|
524 s = splhigh(); 525 if (ppb->ppb_owner != dev) { 526 splx(s); 527 return (EACCES); 528 } 529 530 ppb->ppb_owner = 0; 531 splx(s); 532 533 /* save the context of the device */ | 583 s = splhigh(); 584 if (ppb->ppb_owner != dev) { 585 splx(s); 586 return (EACCES); 587 } 588 589 ppb->ppb_owner = 0; 590 splx(s); 591 592 /* save the context of the device */ |
534 dev->ctx.mode = ppb_get_mode(dev); | 593 ppbdev->ctx.mode = ppb_get_mode(bus); |
535 536 /* ok, now the context of the device is valid */ | 594 595 /* ok, now the context of the device is valid */ |
537 dev->ctx.valid = 1; | 596 ppbdev->ctx.valid = 1; |
538 539 /* wakeup waiting processes */ 540 wakeup(ppb); 541 542 return (0); 543} | 597 598 /* wakeup waiting processes */ 599 wakeup(ppb); 600 601 return (0); 602} |
603 604DRIVER_MODULE(ppbus, ppc, ppbus_driver, ppbus_devclass, 0, 0); |
|