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
ppbus_io(device_t dev,int iop,u_char * addr,int cnt,u_char byte)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
ppbus_exec_microseq(device_t dev,struct ppbus_microseq ** sequence)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
ppbus_read_ivar(device_t dev,int index,unsigned int * val)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
ppbus_write_ivar(device_t dev,int index,unsigned int * val)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
ppbus_poll_bus(device_t dev,int maxp,char mask,char status,int how)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
ppbus_get_mode(device_t dev)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
ppbus_set_mode(device_t dev,int mode,int options)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
ppbus_write(device_t dev,char * buf,int len,int how,size_t * cnt)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
ppbus_read(device_t dev,char * buf,int len,int how,size_t * cnt)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
ppbus_reset_epp_timeout(device_t dev)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
ppbus_ecp_sync(device_t dev)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
ppbus_dma_malloc(device_t dev,void ** buf,bus_addr_t * addr,bus_size_t size)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
ppbus_dma_free(device_t dev,void ** buf,bus_addr_t * addr,bus_size_t size)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 */
ppbus_add_handler(device_t dev,void (* func)(void *),void * arg)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() */
ppbus_remove_handler(device_t dev,void (* func)(void *))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
ppbus_get_status(device_t dev,struct ppbus_status * status)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
ppbus_request_bus(device_t dev,device_t busdev,int how,unsigned int timeout)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
ppbus_release_bus(device_t dev,device_t busdev,int how,unsigned int timeout)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 *
search_token(char * str,int slen,const char * token)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
ppbus_pnp_detect(device_t dev)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
ppbus_scan_bus(device_t dev)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