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 * $FreeBSD$
27 *
28 */
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/linker_set.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 /* try more IEEE1284 modes */
293 if (bootverbose) {
294 if (!(error = ppb_1284_negociate(&pnpdev, PPB_NIBBLE,
295 PPB_REQUEST_ID))) {
296 printf("/NIBBLE_ID");
297 ppb_1284_terminate(&pnpdev);
298 }
299
300 if (!(error = ppb_1284_negociate(&pnpdev, PPB_PS2,
301 PPB_REQUEST_ID))) {
302 printf("/PS2_ID");
303 ppb_1284_terminate(&pnpdev);
304 }
305
306 if (!(error = ppb_1284_negociate(&pnpdev, PPB_ECP,
307 PPB_REQUEST_ID))) {
308 printf("/ECP_ID");
309 ppb_1284_terminate(&pnpdev);
310 }
311
312 if (!(error = ppb_1284_negociate(&pnpdev, PPB_ECP,
313 PPB_REQUEST_ID | PPB_USE_RLE))) {
314 printf("/ECP_RLE_ID");
315 ppb_1284_terminate(&pnpdev);
316 }
317
318 if (!(error = ppb_1284_negociate(&pnpdev, PPB_COMPATIBLE,
319 PPB_EXTENSIBILITY_LINK))) {
320 printf("/Extensibility Link");
321 ppb_1284_terminate(&pnpdev);
322 }
323 }
324
325 printf("\n");
326
327 /* detect PnP devices */
328 ppb->class_id = ppb_pnp_detect(ppb, &pnpdev);
329
330 ppb_release_bus(&pnpdev);
331
332 return (0);
333
334 end_scan:
335 ppb_release_bus(&pnpdev);
336 return (error);
337 }
338
339 #endif /* !DONTPROBE_1284 */
340
341 /*
342 * ppb_attachdevs()
343 *
344 * Called by ppcattach(), this function probes the ppbus and
345 * attaches found devices.
346 */
347 int
348 ppb_attachdevs(struct ppb_data *ppb)
349 {
350 struct ppb_device *dev;
351 struct ppb_driver **p_drvpp, *p_drvp;
352
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 /*
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.
365 */
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 }
376 }
377 return (0);
378 }
379
380 /*
381 * ppb_next_bus()
382 *
383 * Return the next bus in ppbus queue
384 */
385 struct ppb_data *
386 ppb_next_bus(struct ppb_data *ppb)
387 {
388
389 if (ppb == NULL)
390 return (ppbdata.lh_first);
391
392 return (ppb->ppb_chain.le_next);
393 }
394
395 /*
396 * ppb_lookup_bus()
397 *
398 * Get ppb_data structure pointer according to the base address of the ppbus
399 */
400 struct ppb_data *
401 ppb_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);
410 }
411
412 /*
413 * ppb_lookup_link()
414 *
415 * Get ppb_data structure pointer according to the unit value
416 * of the corresponding link structure
417 */
418 struct ppb_data *
419 ppb_lookup_link(int unit)
420 {
421 struct ppb_data *ppb;
422
423 for (ppb = ppbdata.lh_first; ppb; ppb = ppb->ppb_chain.le_next)
424 if (ppb->ppb_link->adapter_unit == unit)
425 break;
426
427 return (ppb);
428 }
429
430 /*
431 * ppb_attach_device()
432 *
433 * Called by loadable kernel modules to add a device
434 */
435 int
436 ppb_attach_device(struct ppb_device *dev)
437 {
438 struct ppb_data *ppb = dev->ppb;
439
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
446 /*
447 * ppb_remove_device()
448 *
449 * Called by loadable kernel modules to remove a device
450 */
451 void
452 ppb_remove_device(struct ppb_device *dev)
453 {
454
455 /* remove the device from the list of probed devices */
456 LIST_REMOVE(dev, chain);
457
458 return;
459 }
460
461 /*
462 * ppb_request_bus()
463 *
464 * Allocate the device to perform transfers.
465 *
466 * how : PPB_WAIT or PPB_DONTWAIT
467 */
468 int
469 ppb_request_bus(struct ppb_device *dev, int how)
470 {
471 int s, error = 0;
472 struct ppb_data *ppb = dev->ppb;
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):
481 error = tsleep(ppb, PPBPRI|PCATCH, "ppbreq", 0);
482 break;
483
484 case (PPB_WAIT | PPB_NOINTR):
485 error = tsleep(ppb, PPBPRI, "ppbreq", 0);
486 break;
487
488 default:
489 return (EWOULDBLOCK);
490 break;
491 }
492
493 } else {
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 */
502 if (dev->ctx.valid)
503 ppb_set_mode(dev, dev->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 */
518 int
519 ppb_release_bus(struct ppb_device *dev)
520 {
521 int s;
522 struct ppb_data *ppb = dev->ppb;
523
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 */
534 dev->ctx.mode = ppb_get_mode(dev);
535
536 /* ok, now the context of the device is valid */
537 dev->ctx.valid = 1;
538
539 /* wakeup waiting processes */
540 wakeup(ppb);
541
542 return (0);
543 }
Cache object: 2d74347ab74f9e10fdf345675d227c37
|