Deleted Added
full compact
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);