debuggers.hg
annotate xen/drivers/char/serial.c @ 16679:b0c85bc56f9e
Fix serial output of carriage return when using high-bit stream muxing.
Original patch by Dan Doucette.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Original patch by Dan Doucette.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Wed Dec 19 15:02:05 2007 +0000 (2007-12-19) |
parents | 537b8edb1efa |
children | a7ddd6bcd564 |
rev | line source |
---|---|
kaf24@1142 | 1 /****************************************************************************** |
kaf24@1142 | 2 * serial.c |
kaf24@1142 | 3 * |
kaf24@5233 | 4 * Framework for serial device drivers. |
kaf24@1142 | 5 * |
kaf24@3882 | 6 * Copyright (c) 2003-2005, K A Fraser |
kaf24@1142 | 7 */ |
kaf24@1142 | 8 |
kaf24@1544 | 9 #include <xen/config.h> |
kaf24@9457 | 10 #include <xen/delay.h> |
kaf24@3372 | 11 #include <xen/init.h> |
kaf24@1544 | 12 #include <xen/irq.h> |
kaf24@1248 | 13 #include <xen/keyhandler.h> |
kaf24@1544 | 14 #include <xen/sched.h> |
kaf24@11236 | 15 #include <xen/mm.h> |
kaf24@1248 | 16 #include <xen/serial.h> |
kaf24@1142 | 17 |
kaf24@5233 | 18 static struct serial_port com[2] = { |
kaf24@9457 | 19 { .rx_lock = SPIN_LOCK_UNLOCKED, .tx_lock = SPIN_LOCK_UNLOCKED }, |
kaf24@9457 | 20 { .rx_lock = SPIN_LOCK_UNLOCKED, .tx_lock = SPIN_LOCK_UNLOCKED } |
kaf24@1142 | 21 }; |
kaf24@1142 | 22 |
kaf24@5233 | 23 void serial_rx_interrupt(struct serial_port *port, struct cpu_user_regs *regs) |
kaf24@5233 | 24 { |
kaf24@5233 | 25 char c; |
kaf24@5364 | 26 serial_rx_fn fn = NULL; |
kaf24@5233 | 27 unsigned long flags; |
kaf24@1142 | 28 |
kaf24@9457 | 29 spin_lock_irqsave(&port->rx_lock, flags); |
kaf24@5233 | 30 |
kaf24@5364 | 31 if ( port->driver->getc(port, &c) ) |
kaf24@5243 | 32 { |
kaf24@5233 | 33 if ( port->rx != NULL ) |
kaf24@5233 | 34 fn = port->rx; |
kaf24@5233 | 35 else if ( (c & 0x80) && (port->rx_hi != NULL) ) |
kaf24@5233 | 36 fn = port->rx_hi; |
kaf24@5233 | 37 else if ( !(c & 0x80) && (port->rx_lo != NULL) ) |
kaf24@5233 | 38 fn = port->rx_lo; |
kaf24@5359 | 39 else if ( (port->rxbufp - port->rxbufc) != SERIAL_RXBUFSZ ) |
kaf24@5359 | 40 port->rxbuf[MASK_SERIAL_RXBUF_IDX(port->rxbufp++)] = c; |
kaf24@5233 | 41 } |
kaf24@5233 | 42 |
kaf24@9457 | 43 spin_unlock_irqrestore(&port->rx_lock, flags); |
kaf24@5364 | 44 |
kaf24@5364 | 45 if ( fn != NULL ) |
kaf24@5364 | 46 (*fn)(c & 0x7f, regs); |
kaf24@5233 | 47 } |
kaf24@5233 | 48 |
kaf24@5359 | 49 void serial_tx_interrupt(struct serial_port *port, struct cpu_user_regs *regs) |
kaf24@5359 | 50 { |
kaf24@5359 | 51 int i; |
kaf24@5359 | 52 unsigned long flags; |
kaf24@5359 | 53 |
kaf24@9457 | 54 local_irq_save(flags); |
kaf24@9457 | 55 |
kaf24@9457 | 56 /* |
kaf24@9457 | 57 * Avoid spinning for a long time: if there is a long-term lock holder |
kaf24@9457 | 58 * then we know that they'll be stuffing bytes into the transmitter which |
kaf24@9457 | 59 * will therefore not be empty for long. |
kaf24@9457 | 60 */ |
kaf24@9457 | 61 while ( !spin_trylock(&port->tx_lock) ) |
kaf24@9457 | 62 { |
kaf24@9457 | 63 if ( !port->driver->tx_empty(port) ) |
kaf24@9457 | 64 return; |
kaf24@9457 | 65 cpu_relax(); |
kaf24@9457 | 66 } |
kaf24@5359 | 67 |
kaf24@5364 | 68 if ( port->driver->tx_empty(port) ) |
kaf24@5359 | 69 { |
kaf24@5364 | 70 for ( i = 0; i < port->tx_fifo_size; i++ ) |
kaf24@5364 | 71 { |
kaf24@5364 | 72 if ( port->txbufc == port->txbufp ) |
kaf24@5364 | 73 break; |
kaf24@5364 | 74 port->driver->putc( |
kaf24@5364 | 75 port, port->txbuf[MASK_SERIAL_TXBUF_IDX(port->txbufc++)]); |
kaf24@5364 | 76 } |
kaf24@5359 | 77 } |
kaf24@5359 | 78 |
kaf24@9457 | 79 spin_unlock_irqrestore(&port->tx_lock, flags); |
kaf24@5359 | 80 } |
kaf24@5359 | 81 |
kaf24@5359 | 82 static void __serial_putc(struct serial_port *port, char c) |
kaf24@5359 | 83 { |
kaf24@5359 | 84 int i; |
kaf24@5359 | 85 |
kaf24@5359 | 86 if ( (port->txbuf != NULL) && !port->sync ) |
kaf24@5359 | 87 { |
kaf24@5359 | 88 /* Interrupt-driven (asynchronous) transmitter. */ |
kaf24@5359 | 89 if ( (port->txbufp - port->txbufc) == SERIAL_TXBUFSZ ) |
kaf24@5359 | 90 { |
kaf24@5359 | 91 /* Buffer is full: we spin, but could alternatively drop chars. */ |
kaf24@5359 | 92 while ( !port->driver->tx_empty(port) ) |
kaf24@5359 | 93 cpu_relax(); |
kaf24@5359 | 94 for ( i = 0; i < port->tx_fifo_size; i++ ) |
kaf24@5359 | 95 port->driver->putc( |
kaf24@5359 | 96 port, port->txbuf[MASK_SERIAL_TXBUF_IDX(port->txbufc++)]); |
kaf24@5359 | 97 port->txbuf[MASK_SERIAL_TXBUF_IDX(port->txbufp++)] = c; |
kaf24@5359 | 98 } |
kaf24@5359 | 99 else if ( ((port->txbufp - port->txbufc) == 0) && |
kaf24@5359 | 100 port->driver->tx_empty(port) ) |
kaf24@5359 | 101 { |
kaf24@5359 | 102 /* Buffer and UART FIFO are both empty. */ |
kaf24@5359 | 103 port->driver->putc(port, c); |
kaf24@5359 | 104 } |
kaf24@5359 | 105 else |
kaf24@5359 | 106 { |
kaf24@5359 | 107 /* Normal case: buffer the character. */ |
kaf24@5359 | 108 port->txbuf[MASK_SERIAL_TXBUF_IDX(port->txbufp++)] = c; |
kaf24@5359 | 109 } |
kaf24@5359 | 110 } |
kaf24@5359 | 111 else if ( port->driver->tx_empty ) |
kaf24@5359 | 112 { |
kaf24@5359 | 113 /* Synchronous finite-capacity transmitter. */ |
kaf24@5359 | 114 while ( !port->driver->tx_empty(port) ) |
kaf24@5359 | 115 cpu_relax(); |
kaf24@5359 | 116 port->driver->putc(port, c); |
kaf24@5359 | 117 } |
kaf24@5359 | 118 else |
kaf24@5359 | 119 { |
kaf24@5359 | 120 /* Simple synchronous transmitter. */ |
kaf24@5359 | 121 port->driver->putc(port, c); |
kaf24@5359 | 122 } |
kaf24@5359 | 123 } |
kaf24@5359 | 124 |
kaf24@5233 | 125 void serial_putc(int handle, char c) |
kaf24@1142 | 126 { |
keir@16286 | 127 struct serial_port *port; |
kaf24@5233 | 128 unsigned long flags; |
kaf24@1142 | 129 |
keir@16286 | 130 if ( handle == -1 ) |
keir@16286 | 131 return; |
keir@16286 | 132 |
keir@16286 | 133 port = &com[handle & SERHND_IDX]; |
keir@16286 | 134 if ( !port->driver || !port->driver->putc ) |
kaf24@1142 | 135 return; |
kaf24@1142 | 136 |
kaf24@9457 | 137 spin_lock_irqsave(&port->tx_lock, flags); |
kaf24@2651 | 138 |
kaf24@1142 | 139 if ( (c == '\n') && (handle & SERHND_COOKED) ) |
keir@16679 | 140 __serial_putc(port, '\r' | ((handle & SERHND_HI) ? 0x80 : 0x00)); |
kaf24@1142 | 141 |
kaf24@1142 | 142 if ( handle & SERHND_HI ) |
kaf24@1142 | 143 c |= 0x80; |
kaf24@1142 | 144 else if ( handle & SERHND_LO ) |
kaf24@1194 | 145 c &= 0x7f; |
kaf24@1142 | 146 |
kaf24@5359 | 147 __serial_putc(port, c); |
kaf24@5233 | 148 |
kaf24@9457 | 149 spin_unlock_irqrestore(&port->tx_lock, flags); |
kaf24@5233 | 150 } |
kaf24@5233 | 151 |
kaf24@5233 | 152 void serial_puts(int handle, const char *s) |
kaf24@5233 | 153 { |
keir@16286 | 154 struct serial_port *port; |
kaf24@5364 | 155 unsigned long flags; |
kaf24@5364 | 156 char c; |
kaf24@5364 | 157 |
keir@16286 | 158 if ( handle == -1 ) |
keir@16286 | 159 return; |
keir@16286 | 160 |
keir@16286 | 161 port = &com[handle & SERHND_IDX]; |
keir@16286 | 162 if ( !port->driver || !port->driver->putc ) |
kaf24@5364 | 163 return; |
kaf24@5364 | 164 |
kaf24@9457 | 165 spin_lock_irqsave(&port->tx_lock, flags); |
kaf24@5364 | 166 |
kaf24@5364 | 167 while ( (c = *s++) != '\0' ) |
kaf24@5364 | 168 { |
kaf24@5364 | 169 if ( (c == '\n') && (handle & SERHND_COOKED) ) |
keir@16679 | 170 __serial_putc(port, '\r' | ((handle & SERHND_HI) ? 0x80 : 0x00)); |
kaf24@5364 | 171 |
kaf24@5364 | 172 if ( handle & SERHND_HI ) |
kaf24@5364 | 173 c |= 0x80; |
kaf24@5364 | 174 else if ( handle & SERHND_LO ) |
kaf24@5364 | 175 c &= 0x7f; |
kaf24@5364 | 176 |
kaf24@5364 | 177 __serial_putc(port, c); |
kaf24@5364 | 178 } |
kaf24@5364 | 179 |
kaf24@9457 | 180 spin_unlock_irqrestore(&port->tx_lock, flags); |
kaf24@5233 | 181 } |
kaf24@5233 | 182 |
kaf24@5233 | 183 char serial_getc(int handle) |
kaf24@1142 | 184 { |
keir@16286 | 185 struct serial_port *port; |
kaf24@5261 | 186 char c; |
kaf24@5233 | 187 unsigned long flags; |
kaf24@1142 | 188 |
keir@16286 | 189 if ( handle == -1 ) |
keir@16286 | 190 return '\0'; |
keir@16286 | 191 |
keir@16286 | 192 port = &com[handle & SERHND_IDX]; |
keir@16286 | 193 if ( !port->driver || !port->driver->getc ) |
kaf24@5233 | 194 return '\0'; |
kaf24@1142 | 195 |
kaf24@9457 | 196 do { |
kaf24@5243 | 197 for ( ; ; ) |
kaf24@5243 | 198 { |
kaf24@9457 | 199 spin_lock_irqsave(&port->rx_lock, flags); |
kaf24@5243 | 200 |
kaf24@5243 | 201 if ( port->rxbufp != port->rxbufc ) |
kaf24@5243 | 202 { |
kaf24@5359 | 203 c = port->rxbuf[MASK_SERIAL_RXBUF_IDX(port->rxbufc++)]; |
kaf24@9457 | 204 spin_unlock_irqrestore(&port->rx_lock, flags); |
kaf24@5243 | 205 break; |
kaf24@5243 | 206 } |
kaf24@5243 | 207 |
kaf24@5243 | 208 if ( port->driver->getc(port, &c) ) |
kaf24@5503 | 209 { |
kaf24@9457 | 210 spin_unlock_irqrestore(&port->rx_lock, flags); |
kaf24@5243 | 211 break; |
kaf24@5503 | 212 } |
kaf24@1142 | 213 |
kaf24@9457 | 214 spin_unlock_irqrestore(&port->rx_lock, flags); |
kaf24@5243 | 215 |
kaf24@5243 | 216 cpu_relax(); |
kaf24@9457 | 217 udelay(100); |
kaf24@5243 | 218 } |
kaf24@5243 | 219 } while ( ((handle & SERHND_LO) && (c & 0x80)) || |
kaf24@5243 | 220 ((handle & SERHND_HI) && !(c & 0x80)) ); |
kaf24@5233 | 221 |
kaf24@5243 | 222 return c & 0x7f; |
kaf24@1142 | 223 } |
kaf24@1142 | 224 |
kaf24@5233 | 225 int serial_parse_handle(char *conf) |
kaf24@1142 | 226 { |
kaf24@1142 | 227 int handle; |
kaf24@1142 | 228 |
kaf24@1142 | 229 /* Silently fail if user has explicitly requested no serial I/O. */ |
kaf24@1142 | 230 if ( strcmp(conf, "none") == 0 ) |
kaf24@1142 | 231 return -1; |
kaf24@1142 | 232 |
kaf24@1142 | 233 if ( strncmp(conf, "com", 3) != 0 ) |
kaf24@1142 | 234 goto fail; |
kaf24@1142 | 235 |
kaf24@1142 | 236 switch ( conf[3] ) |
kaf24@1142 | 237 { |
kaf24@1142 | 238 case '1': |
kaf24@1142 | 239 handle = 0; |
kaf24@1142 | 240 break; |
kaf24@1142 | 241 case '2': |
kaf24@1142 | 242 handle = 1; |
kaf24@1142 | 243 break; |
kaf24@1142 | 244 default: |
kaf24@1142 | 245 goto fail; |
kaf24@1142 | 246 } |
kaf24@1142 | 247 |
kaf24@1142 | 248 if ( conf[4] == 'H' ) |
kaf24@1142 | 249 handle |= SERHND_HI; |
kaf24@1142 | 250 else if ( conf[4] == 'L' ) |
kaf24@1142 | 251 handle |= SERHND_LO; |
kaf24@1142 | 252 |
kaf24@1142 | 253 handle |= SERHND_COOKED; |
kaf24@1142 | 254 |
kaf24@1142 | 255 return handle; |
kaf24@1142 | 256 |
kaf24@1142 | 257 fail: |
kaf24@1142 | 258 printk("ERROR: bad serial-interface specification '%s'\n", conf); |
kaf24@1142 | 259 return -1; |
kaf24@1142 | 260 } |
kaf24@1142 | 261 |
kaf24@1142 | 262 void serial_set_rx_handler(int handle, serial_rx_fn fn) |
kaf24@1142 | 263 { |
keir@16286 | 264 struct serial_port *port; |
kaf24@1142 | 265 unsigned long flags; |
kaf24@1142 | 266 |
kaf24@1142 | 267 if ( handle == -1 ) |
kaf24@1142 | 268 return; |
kaf24@1142 | 269 |
keir@16286 | 270 port = &com[handle & SERHND_IDX]; |
keir@16286 | 271 |
kaf24@9457 | 272 spin_lock_irqsave(&port->rx_lock, flags); |
kaf24@1142 | 273 |
kaf24@5233 | 274 if ( port->rx != NULL ) |
kaf24@1142 | 275 goto fail; |
kaf24@1142 | 276 |
kaf24@1142 | 277 if ( handle & SERHND_LO ) |
kaf24@1142 | 278 { |
kaf24@5233 | 279 if ( port->rx_lo != NULL ) |
kaf24@1142 | 280 goto fail; |
kaf24@5233 | 281 port->rx_lo = fn; |
kaf24@1142 | 282 } |
kaf24@1142 | 283 else if ( handle & SERHND_HI ) |
kaf24@1142 | 284 { |
kaf24@5233 | 285 if ( port->rx_hi != NULL ) |
kaf24@1142 | 286 goto fail; |
kaf24@5233 | 287 port->rx_hi = fn; |
kaf24@1142 | 288 } |
kaf24@1142 | 289 else |
kaf24@1142 | 290 { |
kaf24@5233 | 291 if ( (port->rx_hi != NULL) || (port->rx_lo != NULL) ) |
kaf24@1142 | 292 goto fail; |
kaf24@5233 | 293 port->rx = fn; |
kaf24@1142 | 294 } |
kaf24@1142 | 295 |
kaf24@9457 | 296 spin_unlock_irqrestore(&port->rx_lock, flags); |
kaf24@1142 | 297 return; |
kaf24@1142 | 298 |
kaf24@1142 | 299 fail: |
kaf24@9457 | 300 spin_unlock_irqrestore(&port->rx_lock, flags); |
kaf24@1142 | 301 printk("ERROR: Conflicting receive handlers for COM%d\n", |
kaf24@1142 | 302 handle & SERHND_IDX); |
kaf24@1142 | 303 } |
kaf24@1142 | 304 |
kaf24@5233 | 305 void serial_force_unlock(int handle) |
kaf24@1142 | 306 { |
keir@16286 | 307 struct serial_port *port; |
kaf24@9457 | 308 |
kaf24@9457 | 309 if ( handle == -1 ) |
kaf24@9457 | 310 return; |
kaf24@9457 | 311 |
keir@16286 | 312 port = &com[handle & SERHND_IDX]; |
keir@16286 | 313 |
kfraser@11837 | 314 spin_lock_init(&port->rx_lock); |
kfraser@11837 | 315 spin_lock_init(&port->tx_lock); |
kaf24@9457 | 316 |
kaf24@5359 | 317 serial_start_sync(handle); |
kaf24@5359 | 318 } |
kaf24@5359 | 319 |
kaf24@5359 | 320 void serial_start_sync(int handle) |
kaf24@5359 | 321 { |
keir@16286 | 322 struct serial_port *port; |
kaf24@5359 | 323 unsigned long flags; |
kaf24@5359 | 324 |
kaf24@5359 | 325 if ( handle == -1 ) |
kaf24@5359 | 326 return; |
kaf24@5359 | 327 |
keir@16286 | 328 port = &com[handle & SERHND_IDX]; |
keir@16286 | 329 |
kaf24@9457 | 330 spin_lock_irqsave(&port->tx_lock, flags); |
kaf24@5359 | 331 |
kaf24@5359 | 332 if ( port->sync++ == 0 ) |
kaf24@5359 | 333 { |
kaf24@5359 | 334 while ( (port->txbufp - port->txbufc) != 0 ) |
kaf24@5359 | 335 { |
kaf24@5359 | 336 while ( !port->driver->tx_empty(port) ) |
kaf24@5359 | 337 cpu_relax(); |
kaf24@5359 | 338 port->driver->putc( |
kaf24@5359 | 339 port, port->txbuf[MASK_SERIAL_TXBUF_IDX(port->txbufc++)]); |
kaf24@5359 | 340 } |
kaf24@5359 | 341 } |
kaf24@5359 | 342 |
kaf24@9457 | 343 spin_unlock_irqrestore(&port->tx_lock, flags); |
kaf24@5359 | 344 } |
kaf24@5359 | 345 |
kaf24@5359 | 346 void serial_end_sync(int handle) |
kaf24@5359 | 347 { |
keir@16286 | 348 struct serial_port *port; |
kaf24@5359 | 349 unsigned long flags; |
kaf24@5359 | 350 |
kaf24@5359 | 351 if ( handle == -1 ) |
kaf24@5359 | 352 return; |
kaf24@5359 | 353 |
keir@16286 | 354 port = &com[handle & SERHND_IDX]; |
keir@16286 | 355 |
kaf24@9457 | 356 spin_lock_irqsave(&port->tx_lock, flags); |
kaf24@5359 | 357 |
kaf24@5359 | 358 port->sync--; |
kaf24@5359 | 359 |
kaf24@9457 | 360 spin_unlock_irqrestore(&port->tx_lock, flags); |
kaf24@1207 | 361 } |
kaf24@1207 | 362 |
kaf24@5365 | 363 int serial_tx_space(int handle) |
kaf24@5365 | 364 { |
keir@16286 | 365 struct serial_port *port; |
kaf24@5365 | 366 if ( handle == -1 ) |
kaf24@5365 | 367 return SERIAL_TXBUFSZ; |
keir@16286 | 368 port = &com[handle & SERHND_IDX]; |
kaf24@5365 | 369 return SERIAL_TXBUFSZ - (port->txbufp - port->txbufc); |
kaf24@5365 | 370 } |
kaf24@5365 | 371 |
kfraser@15578 | 372 void __devinit serial_init_preirq(void) |
cl349@2990 | 373 { |
kaf24@5233 | 374 int i; |
kaf24@5233 | 375 for ( i = 0; i < ARRAY_SIZE(com); i++ ) |
kaf24@5233 | 376 if ( com[i].driver && com[i].driver->init_preirq ) |
kaf24@5233 | 377 com[i].driver->init_preirq(&com[i]); |
cl349@2990 | 378 } |
cl349@2990 | 379 |
kfraser@15578 | 380 void __devinit serial_init_postirq(void) |
kaf24@1207 | 381 { |
kaf24@5233 | 382 int i; |
kaf24@5233 | 383 for ( i = 0; i < ARRAY_SIZE(com); i++ ) |
kaf24@5233 | 384 if ( com[i].driver && com[i].driver->init_postirq ) |
kaf24@5233 | 385 com[i].driver->init_postirq(&com[i]); |
kaf24@2079 | 386 } |
kaf24@3952 | 387 |
keir@15081 | 388 void __init serial_endboot(void) |
iap10@4325 | 389 { |
iap10@4325 | 390 int i; |
kaf24@4326 | 391 for ( i = 0; i < ARRAY_SIZE(com); i++ ) |
kaf24@5233 | 392 if ( com[i].driver && com[i].driver->endboot ) |
kaf24@5233 | 393 com[i].driver->endboot(&com[i]); |
kaf24@5233 | 394 } |
kaf24@5233 | 395 |
kaf24@9702 | 396 int serial_irq(int idx) |
kaf24@9702 | 397 { |
kaf24@9702 | 398 if ( (idx >= 0) && (idx < ARRAY_SIZE(com)) && |
kaf24@9702 | 399 com[idx].driver && com[idx].driver->irq ) |
kaf24@9702 | 400 return com[idx].driver->irq(&com[idx]); |
kaf24@9702 | 401 |
kaf24@9702 | 402 return -1; |
kaf24@9702 | 403 } |
kaf24@9702 | 404 |
kfraser@15297 | 405 void serial_suspend(void) |
kfraser@15297 | 406 { |
kfraser@15297 | 407 int i, irq; |
kfraser@15297 | 408 for ( i = 0; i < ARRAY_SIZE(com); i++ ) |
kfraser@15297 | 409 if ( (irq = serial_irq(i)) >= 0 ) |
kfraser@15297 | 410 free_irq(irq); |
kfraser@15297 | 411 } |
kfraser@15297 | 412 |
kfraser@15297 | 413 void serial_resume(void) |
kfraser@15297 | 414 { |
kfraser@15297 | 415 serial_init_preirq(); |
kfraser@15297 | 416 serial_init_postirq(); |
kfraser@15297 | 417 } |
kfraser@15297 | 418 |
kaf24@5233 | 419 void serial_register_uart(int idx, struct uart_driver *driver, void *uart) |
kaf24@5233 | 420 { |
kaf24@5359 | 421 /* Store UART-specific info. */ |
kaf24@5233 | 422 com[idx].driver = driver; |
kaf24@5233 | 423 com[idx].uart = uart; |
kaf24@5359 | 424 |
kaf24@5359 | 425 /* Default is no transmit FIFO. */ |
kaf24@5359 | 426 com[idx].tx_fifo_size = 1; |
kaf24@5359 | 427 } |
kaf24@5359 | 428 |
kaf24@5359 | 429 void serial_async_transmit(struct serial_port *port) |
kaf24@5359 | 430 { |
kaf24@5359 | 431 BUG_ON(!port->driver->tx_empty); |
kaf24@6722 | 432 if ( port->txbuf == NULL ) |
kaf24@6722 | 433 port->txbuf = alloc_xenheap_pages( |
kaf24@6722 | 434 get_order_from_bytes(SERIAL_TXBUFSZ)); |
iap10@4325 | 435 } |
iap10@4325 | 436 |
kaf24@3952 | 437 /* |
kaf24@3952 | 438 * Local variables: |
kaf24@3952 | 439 * mode: C |
kaf24@3952 | 440 * c-set-style: "BSD" |
kaf24@3952 | 441 * c-basic-offset: 4 |
kaf24@3952 | 442 * tab-width: 4 |
kaf24@3952 | 443 * indent-tabs-mode: nil |
kaf24@4026 | 444 * End: |
kaf24@3952 | 445 */ |