1 /******************************************************************************
2  * serial.c
3  *
4  * Framework for serial device drivers.
5  *
6  * Copyright (c) 2003-2008, K A Fraser
7  */
8 
9 #include <xen/delay.h>
10 #include <xen/init.h>
11 #include <xen/mm.h>
12 #include <xen/param.h>
13 #include <xen/serial.h>
14 #include <xen/cache.h>
15 
16 /* Never drop characters, even if the async transmit buffer fills. */
17 /* #define SERIAL_NEVER_DROP_CHARS 1 */
18 
19 unsigned int __read_mostly serial_txbufsz = 16384;
20 size_param("serial_tx_buffer", serial_txbufsz);
21 
22 #define mask_serial_rxbuf_idx(_i) ((_i)&(serial_rxbufsz-1))
23 #define mask_serial_txbuf_idx(_i) ((_i)&(serial_txbufsz-1))
24 
25 static struct serial_port com[SERHND_IDX + 1] = {
26     [0 ... SERHND_IDX] = {
27         .rx_lock = SPIN_LOCK_UNLOCKED,
28         .tx_lock = SPIN_LOCK_UNLOCKED
29     }
30 };
31 
32 static bool_t __read_mostly post_irq;
33 
serial_start_tx(struct serial_port * port)34 static inline void serial_start_tx(struct serial_port *port)
35 {
36     if ( port->driver->start_tx != NULL )
37         port->driver->start_tx(port);
38 }
39 
serial_stop_tx(struct serial_port * port)40 static inline void serial_stop_tx(struct serial_port *port)
41 {
42     if ( port->driver->stop_tx != NULL )
43         port->driver->stop_tx(port);
44 }
45 
serial_rx_interrupt(struct serial_port * port,struct cpu_user_regs * regs)46 void serial_rx_interrupt(struct serial_port *port, struct cpu_user_regs *regs)
47 {
48     char c;
49     serial_rx_fn fn = NULL;
50     unsigned long flags;
51 
52     spin_lock_irqsave(&port->rx_lock, flags);
53 
54     if ( port->driver->getc(port, &c) )
55     {
56         if ( port->rx != NULL )
57             fn = port->rx;
58         else if ( (c & 0x80) && (port->rx_hi != NULL) )
59             fn = port->rx_hi;
60         else if ( !(c & 0x80) && (port->rx_lo != NULL) )
61             fn = port->rx_lo;
62         else if ( (port->rxbufp - port->rxbufc) != serial_rxbufsz )
63             port->rxbuf[mask_serial_rxbuf_idx(port->rxbufp++)] = c;
64     }
65 
66     spin_unlock_irqrestore(&port->rx_lock, flags);
67 
68     if ( fn != NULL )
69         (*fn)(c & 0x7f, regs);
70 }
71 
serial_tx_interrupt(struct serial_port * port,struct cpu_user_regs * regs)72 void serial_tx_interrupt(struct serial_port *port, struct cpu_user_regs *regs)
73 {
74     int i, n;
75     unsigned long flags;
76 
77     local_irq_save(flags);
78 
79     /*
80      * Avoid spinning for a long time: if there is a long-term lock holder
81      * then we know that they'll be stuffing bytes into the transmitter which
82      * will therefore not be empty for long.
83      */
84     while ( !spin_trylock(&port->tx_lock) )
85     {
86         if ( port->driver->tx_ready(port) <= 0 )
87             goto out;
88         cpu_relax();
89     }
90 
91     if ( port->txbufc == port->txbufp )
92     {
93         /* Disable TX. nothing to send */
94         serial_stop_tx(port);
95         spin_unlock(&port->tx_lock);
96         goto out;
97     }
98     else
99     {
100         if ( port->driver->tx_ready(port) )
101             serial_start_tx(port);
102     }
103     for ( i = 0, n = port->driver->tx_ready(port); i < n; i++ )
104     {
105         if ( port->txbufc == port->txbufp )
106             break;
107         port->driver->putc(
108             port, port->txbuf[mask_serial_txbuf_idx(port->txbufc++)]);
109     }
110     if ( i && port->driver->flush )
111         port->driver->flush(port);
112 
113     spin_unlock(&port->tx_lock);
114 
115  out:
116     local_irq_restore(flags);
117 }
118 
__serial_putc(struct serial_port * port,char c)119 static void __serial_putc(struct serial_port *port, char c)
120 {
121     if ( (port->txbuf != NULL) && !port->sync )
122     {
123         /* Interrupt-driven (asynchronous) transmitter. */
124 
125         if ( port->tx_quench )
126         {
127             /* Buffer filled and we are dropping characters. */
128             if ( (port->txbufp - port->txbufc) > (serial_txbufsz / 2) )
129                 return;
130             port->tx_quench = 0;
131         }
132 
133         if ( (port->txbufp - port->txbufc) == serial_txbufsz )
134         {
135             if ( port->tx_log_everything )
136             {
137                 /* Buffer is full: we spin waiting for space to appear. */
138                 int n;
139 
140                 while ( (n = port->driver->tx_ready(port)) == 0 )
141                     cpu_relax();
142                 if ( n > 0 )
143                 {
144                     /* Enable TX before sending chars */
145                     serial_start_tx(port);
146                     while ( n-- )
147                         port->driver->putc(
148                             port,
149                             port->txbuf[mask_serial_txbuf_idx(port->txbufc++)]);
150                     port->txbuf[mask_serial_txbuf_idx(port->txbufp++)] = c;
151                 }
152             }
153             else
154             {
155                 /* Buffer is full: drop chars until buffer is half empty. */
156                 port->tx_quench = 1;
157             }
158             return;
159         }
160 
161         if ( ((port->txbufp - port->txbufc) == 0) &&
162              port->driver->tx_ready(port) > 0 )
163         {
164             /* Enable TX before sending chars */
165             serial_start_tx(port);
166             /* Buffer and UART FIFO are both empty, and port is available. */
167             port->driver->putc(port, c);
168         }
169         else
170         {
171             /* Normal case: buffer the character. */
172             port->txbuf[mask_serial_txbuf_idx(port->txbufp++)] = c;
173         }
174     }
175     else if ( port->driver->tx_ready )
176     {
177         int n;
178 
179         /* Synchronous finite-capacity transmitter. */
180         while ( !(n = port->driver->tx_ready(port)) )
181             cpu_relax();
182         if ( n > 0 )
183         {
184             /* Enable TX before sending chars */
185             serial_start_tx(port);
186             port->driver->putc(port, c);
187         }
188     }
189     else
190     {
191         /* Simple synchronous transmitter. */
192         serial_start_tx(port);
193         port->driver->putc(port, c);
194     }
195 }
196 
serial_putc(int handle,char c)197 void serial_putc(int handle, char c)
198 {
199     struct serial_port *port;
200     unsigned long flags;
201 
202     if ( handle == -1 )
203         return;
204 
205     port = &com[handle & SERHND_IDX];
206     if ( !port->driver || !port->driver->putc )
207         return;
208 
209     spin_lock_irqsave(&port->tx_lock, flags);
210 
211     if ( (c == '\n') && (handle & SERHND_COOKED) )
212         __serial_putc(port, '\r' | ((handle & SERHND_HI) ? 0x80 : 0x00));
213 
214     if ( handle & SERHND_HI )
215         c |= 0x80;
216     else if ( handle & SERHND_LO )
217         c &= 0x7f;
218 
219     __serial_putc(port, c);
220 
221     if ( port->driver->flush )
222         port->driver->flush(port);
223 
224     spin_unlock_irqrestore(&port->tx_lock, flags);
225 }
226 
serial_puts(int handle,const char * s,size_t nr)227 void serial_puts(int handle, const char *s, size_t nr)
228 {
229     struct serial_port *port;
230     unsigned long flags;
231 
232     if ( handle == -1 )
233         return;
234 
235     port = &com[handle & SERHND_IDX];
236     if ( !port->driver || !port->driver->putc )
237         return;
238 
239     spin_lock_irqsave(&port->tx_lock, flags);
240 
241     for ( ; nr > 0; nr--, s++ )
242     {
243         char c = *s;
244 
245         if ( (c == '\n') && (handle & SERHND_COOKED) )
246             __serial_putc(port, '\r' | ((handle & SERHND_HI) ? 0x80 : 0x00));
247 
248         if ( handle & SERHND_HI )
249             c |= 0x80;
250         else if ( handle & SERHND_LO )
251             c &= 0x7f;
252 
253         __serial_putc(port, c);
254     }
255 
256     if ( port->driver->flush )
257         port->driver->flush(port);
258 
259     spin_unlock_irqrestore(&port->tx_lock, flags);
260 }
261 
serial_getc(int handle)262 char serial_getc(int handle)
263 {
264     struct serial_port *port;
265     char c;
266     unsigned long flags;
267 
268     if ( handle == -1 )
269         return '\0';
270 
271     port = &com[handle & SERHND_IDX];
272     if ( !port->driver || !port->driver->getc )
273         return '\0';
274 
275     do {
276         for ( ; ; )
277         {
278             spin_lock_irqsave(&port->rx_lock, flags);
279 
280             if ( port->rxbufp != port->rxbufc )
281             {
282                 c = port->rxbuf[mask_serial_rxbuf_idx(port->rxbufc++)];
283                 spin_unlock_irqrestore(&port->rx_lock, flags);
284                 break;
285             }
286 
287             if ( port->driver->getc(port, &c) )
288             {
289                 spin_unlock_irqrestore(&port->rx_lock, flags);
290                 break;
291             }
292 
293             spin_unlock_irqrestore(&port->rx_lock, flags);
294 
295             cpu_relax();
296             udelay(100);
297         }
298     } while ( ((handle & SERHND_LO) &&  (c & 0x80)) ||
299               ((handle & SERHND_HI) && !(c & 0x80)) );
300 
301     return c & 0x7f;
302 }
303 
serial_parse_handle(char * conf)304 int __init serial_parse_handle(char *conf)
305 {
306     int handle, flags = 0;
307 
308     if ( !strncmp(conf, "dbgp", 4) && (!conf[4] || conf[4] == ',') )
309     {
310         handle = SERHND_DBGP;
311         goto common;
312     }
313 
314     if ( !strncmp(conf, "dtuart", 6) )
315     {
316         handle = SERHND_DTUART;
317         goto common;
318     }
319 
320     if ( strncmp(conf, "com", 3) )
321         goto fail;
322 
323     switch ( conf[3] )
324     {
325     case '1':
326         handle = SERHND_COM1;
327         break;
328     case '2':
329         handle = SERHND_COM2;
330         break;
331     default:
332         goto fail;
333     }
334 
335     if ( conf[4] == 'H' )
336         flags |= SERHND_HI;
337     else if ( conf[4] == 'L' )
338         flags |= SERHND_LO;
339 
340  common:
341     if ( !com[handle].driver )
342         goto fail;
343 
344     if ( !post_irq )
345         com[handle].state = serial_parsed;
346     else if ( com[handle].state != serial_initialized )
347     {
348         if ( com[handle].driver->init_postirq )
349             com[handle].driver->init_postirq(&com[handle]);
350         com[handle].state = serial_initialized;
351     }
352 
353     return handle | flags | SERHND_COOKED;
354 
355  fail:
356     return -1;
357 }
358 
serial_set_rx_handler(int handle,serial_rx_fn fn)359 void __init serial_set_rx_handler(int handle, serial_rx_fn fn)
360 {
361     struct serial_port *port;
362     unsigned long flags;
363 
364     if ( handle == -1 )
365         return;
366 
367     port = &com[handle & SERHND_IDX];
368 
369     spin_lock_irqsave(&port->rx_lock, flags);
370 
371     if ( port->rx != NULL )
372         goto fail;
373 
374     if ( handle & SERHND_LO )
375     {
376         if ( port->rx_lo != NULL )
377             goto fail;
378         port->rx_lo = fn;
379     }
380     else if ( handle & SERHND_HI )
381     {
382         if ( port->rx_hi != NULL )
383             goto fail;
384         port->rx_hi = fn;
385     }
386     else
387     {
388         if ( (port->rx_hi != NULL) || (port->rx_lo != NULL) )
389             goto fail;
390         port->rx = fn;
391     }
392 
393     spin_unlock_irqrestore(&port->rx_lock, flags);
394     return;
395 
396  fail:
397     spin_unlock_irqrestore(&port->rx_lock, flags);
398     printk("ERROR: Conflicting receive handlers for COM%d\n",
399            handle & SERHND_IDX);
400 }
401 
serial_force_unlock(int handle)402 void serial_force_unlock(int handle)
403 {
404     struct serial_port *port;
405 
406     if ( handle == -1 )
407         return;
408 
409     port = &com[handle & SERHND_IDX];
410 
411     spin_lock_init(&port->rx_lock);
412     spin_lock_init(&port->tx_lock);
413 
414     serial_start_sync(handle);
415 }
416 
serial_start_sync(int handle)417 void serial_start_sync(int handle)
418 {
419     struct serial_port *port;
420     unsigned long flags;
421 
422     if ( handle == -1 )
423         return;
424 
425     port = &com[handle & SERHND_IDX];
426 
427     spin_lock_irqsave(&port->tx_lock, flags);
428 
429     if ( port->sync++ == 0 )
430     {
431         while ( (port->txbufp - port->txbufc) != 0 )
432         {
433             int n;
434 
435             while ( !(n = port->driver->tx_ready(port)) )
436                 cpu_relax();
437             if ( n < 0 )
438                 /* port is unavailable and might not come up until reenabled by
439                    dom0, we can't really do proper sync */
440                 break;
441             serial_start_tx(port);
442             port->driver->putc(
443                 port, port->txbuf[mask_serial_txbuf_idx(port->txbufc++)]);
444         }
445         if ( port->driver->flush )
446             port->driver->flush(port);
447     }
448 
449     spin_unlock_irqrestore(&port->tx_lock, flags);
450 }
451 
serial_end_sync(int handle)452 void serial_end_sync(int handle)
453 {
454     struct serial_port *port;
455     unsigned long flags;
456 
457     if ( handle == -1 )
458         return;
459 
460     port = &com[handle & SERHND_IDX];
461 
462     spin_lock_irqsave(&port->tx_lock, flags);
463 
464     port->sync--;
465 
466     spin_unlock_irqrestore(&port->tx_lock, flags);
467 }
468 
serial_start_log_everything(int handle)469 void serial_start_log_everything(int handle)
470 {
471     struct serial_port *port;
472     unsigned long flags;
473 
474     if ( handle == -1 )
475         return;
476 
477     port = &com[handle & SERHND_IDX];
478 
479     spin_lock_irqsave(&port->tx_lock, flags);
480     port->tx_log_everything++;
481     port->tx_quench = 0;
482     spin_unlock_irqrestore(&port->tx_lock, flags);
483 }
484 
serial_end_log_everything(int handle)485 void serial_end_log_everything(int handle)
486 {
487     struct serial_port *port;
488     unsigned long flags;
489 
490     if ( handle == -1 )
491         return;
492 
493     port = &com[handle & SERHND_IDX];
494 
495     spin_lock_irqsave(&port->tx_lock, flags);
496     port->tx_log_everything--;
497     spin_unlock_irqrestore(&port->tx_lock, flags);
498 }
499 
serial_init_preirq(void)500 void __init serial_init_preirq(void)
501 {
502     int i;
503     for ( i = 0; i < ARRAY_SIZE(com); i++ )
504         if ( com[i].driver && com[i].driver->init_preirq )
505             com[i].driver->init_preirq(&com[i]);
506 }
507 
serial_init_irq(void)508 void __init serial_init_irq(void)
509 {
510     unsigned int i;
511 
512     for ( i = 0; i < ARRAY_SIZE(com); i++ )
513         if ( com[i].driver && com[i].driver->init_irq )
514             com[i].driver->init_irq(&com[i]);
515 }
516 
serial_init_postirq(void)517 void __init serial_init_postirq(void)
518 {
519     int i;
520     for ( i = 0; i < ARRAY_SIZE(com); i++ )
521         if ( com[i].state == serial_parsed )
522         {
523             if ( com[i].driver->init_postirq )
524                 com[i].driver->init_postirq(&com[i]);
525             com[i].state = serial_initialized;
526         }
527     post_irq = 1;
528 }
529 
serial_endboot(void)530 void __init serial_endboot(void)
531 {
532     int i;
533     for ( i = 0; i < ARRAY_SIZE(com); i++ )
534         if ( com[i].driver && com[i].driver->endboot )
535             com[i].driver->endboot(&com[i]);
536 }
537 
serial_irq(int idx)538 int __init serial_irq(int idx)
539 {
540     if ( (idx >= 0) && (idx < ARRAY_SIZE(com)) &&
541          com[idx].driver && com[idx].driver->irq )
542         return com[idx].driver->irq(&com[idx]);
543 
544     return -1;
545 }
546 
serial_vuart_info(int idx)547 const struct vuart_info *serial_vuart_info(int idx)
548 {
549     if ( (idx >= 0) && (idx < ARRAY_SIZE(com)) &&
550          com[idx].driver && com[idx].driver->vuart_info )
551         return com[idx].driver->vuart_info(&com[idx]);
552 
553     return NULL;
554 }
555 
serial_suspend(void)556 void serial_suspend(void)
557 {
558     int i;
559     for ( i = 0; i < ARRAY_SIZE(com); i++ )
560         if ( com[i].state == serial_initialized && com[i].driver->suspend )
561             com[i].driver->suspend(&com[i]);
562 }
563 
serial_resume(void)564 void serial_resume(void)
565 {
566     int i;
567     for ( i = 0; i < ARRAY_SIZE(com); i++ )
568         if ( com[i].state == serial_initialized && com[i].driver->resume )
569             com[i].driver->resume(&com[i]);
570 }
571 
serial_register_uart(int idx,struct uart_driver * driver,void * uart)572 void __init serial_register_uart(int idx, struct uart_driver *driver,
573                                  void *uart)
574 {
575     /* Store UART-specific info. */
576     com[idx].driver = driver;
577     com[idx].uart   = uart;
578 }
579 
serial_async_transmit(struct serial_port * port)580 void __init serial_async_transmit(struct serial_port *port)
581 {
582     BUG_ON(!port->driver->tx_ready);
583     if ( port->txbuf != NULL )
584         return;
585     if ( serial_txbufsz < PAGE_SIZE )
586         serial_txbufsz = PAGE_SIZE;
587     while ( serial_txbufsz & (serial_txbufsz - 1) )
588         serial_txbufsz &= serial_txbufsz - 1;
589     port->txbuf = alloc_xenheap_pages(
590         get_order_from_bytes(serial_txbufsz), 0);
591 }
592 
593 /*
594  * Local variables:
595  * mode: C
596  * c-file-style: "BSD"
597  * c-basic-offset: 4
598  * tab-width: 4
599  * indent-tabs-mode: nil
600  * End:
601  */
602