Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.15 1056 lines 29 kB view raw
1/* 2 * drivers/char/vme_scc.c: MVME147, MVME162, BVME6000 SCC serial ports 3 * implementation. 4 * Copyright 1999 Richard Hirst <richard@sleepie.demon.co.uk> 5 * 6 * Based on atari_SCC.c which was 7 * Copyright 1994-95 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> 8 * Partially based on PC-Linux serial.c by Linus Torvalds and Theodore Ts'o 9 * 10 * This file is subject to the terms and conditions of the GNU General Public 11 * License. See the file COPYING in the main directory of this archive 12 * for more details. 13 * 14 */ 15 16#include <linux/module.h> 17#include <linux/config.h> 18#include <linux/kdev_t.h> 19#include <asm/io.h> 20#include <linux/kernel.h> 21#include <linux/sched.h> 22#include <linux/ioport.h> 23#include <linux/interrupt.h> 24#include <linux/errno.h> 25#include <linux/tty.h> 26#include <linux/tty_flip.h> 27#include <linux/mm.h> 28#include <linux/serial.h> 29#include <linux/fcntl.h> 30#include <linux/major.h> 31#include <linux/delay.h> 32#include <linux/slab.h> 33#include <linux/miscdevice.h> 34#include <linux/console.h> 35#include <linux/init.h> 36#include <asm/setup.h> 37#include <asm/bootinfo.h> 38 39#ifdef CONFIG_MVME147_SCC 40#include <asm/mvme147hw.h> 41#endif 42#ifdef CONFIG_MVME162_SCC 43#include <asm/mvme16xhw.h> 44#endif 45#ifdef CONFIG_BVME6000_SCC 46#include <asm/bvme6000hw.h> 47#endif 48 49#include <linux/generic_serial.h> 50#include "scc.h" 51 52 53#define CHANNEL_A 0 54#define CHANNEL_B 1 55 56#define SCC_MINOR_BASE 64 57 58/* Shadows for all SCC write registers */ 59static unsigned char scc_shadow[2][16]; 60 61/* Location to access for SCC register access delay */ 62static volatile unsigned char *scc_del = NULL; 63 64/* To keep track of STATUS_REG state for detection of Ext/Status int source */ 65static unsigned char scc_last_status_reg[2]; 66 67/***************************** Prototypes *****************************/ 68 69/* Function prototypes */ 70static void scc_disable_tx_interrupts(void * ptr); 71static void scc_enable_tx_interrupts(void * ptr); 72static void scc_disable_rx_interrupts(void * ptr); 73static void scc_enable_rx_interrupts(void * ptr); 74static int scc_get_CD(void * ptr); 75static void scc_shutdown_port(void * ptr); 76static int scc_set_real_termios(void *ptr); 77static void scc_hungup(void *ptr); 78static void scc_close(void *ptr); 79static int scc_chars_in_buffer(void * ptr); 80static int scc_open(struct tty_struct * tty, struct file * filp); 81static int scc_ioctl(struct tty_struct * tty, struct file * filp, 82 unsigned int cmd, unsigned long arg); 83static void scc_throttle(struct tty_struct *tty); 84static void scc_unthrottle(struct tty_struct *tty); 85static irqreturn_t scc_tx_int(int irq, void *data, struct pt_regs *fp); 86static irqreturn_t scc_rx_int(int irq, void *data, struct pt_regs *fp); 87static irqreturn_t scc_stat_int(int irq, void *data, struct pt_regs *fp); 88static irqreturn_t scc_spcond_int(int irq, void *data, struct pt_regs *fp); 89static void scc_setsignals(struct scc_port *port, int dtr, int rts); 90static void scc_break_ctl(struct tty_struct *tty, int break_state); 91 92static struct tty_driver *scc_driver; 93 94struct scc_port scc_ports[2]; 95 96int scc_initialized = 0; 97 98/*--------------------------------------------------------------------------- 99 * Interface from generic_serial.c back here 100 *--------------------------------------------------------------------------*/ 101 102static struct real_driver scc_real_driver = { 103 scc_disable_tx_interrupts, 104 scc_enable_tx_interrupts, 105 scc_disable_rx_interrupts, 106 scc_enable_rx_interrupts, 107 scc_get_CD, 108 scc_shutdown_port, 109 scc_set_real_termios, 110 scc_chars_in_buffer, 111 scc_close, 112 scc_hungup, 113 NULL 114}; 115 116 117static struct tty_operations scc_ops = { 118 .open = scc_open, 119 .close = gs_close, 120 .write = gs_write, 121 .put_char = gs_put_char, 122 .flush_chars = gs_flush_chars, 123 .write_room = gs_write_room, 124 .chars_in_buffer = gs_chars_in_buffer, 125 .flush_buffer = gs_flush_buffer, 126 .ioctl = scc_ioctl, 127 .throttle = scc_throttle, 128 .unthrottle = scc_unthrottle, 129 .set_termios = gs_set_termios, 130 .stop = gs_stop, 131 .start = gs_start, 132 .hangup = gs_hangup, 133 .break_ctl = scc_break_ctl, 134}; 135 136/*---------------------------------------------------------------------------- 137 * vme_scc_init() and support functions 138 *---------------------------------------------------------------------------*/ 139 140static int scc_init_drivers(void) 141{ 142 int error; 143 144 scc_driver = alloc_tty_driver(2); 145 if (!scc_driver) 146 return -ENOMEM; 147 scc_driver->owner = THIS_MODULE; 148 scc_driver->driver_name = "scc"; 149 scc_driver->name = "ttyS"; 150 scc_driver->devfs_name = "tts/"; 151 scc_driver->major = TTY_MAJOR; 152 scc_driver->minor_start = SCC_MINOR_BASE; 153 scc_driver->type = TTY_DRIVER_TYPE_SERIAL; 154 scc_driver->subtype = SERIAL_TYPE_NORMAL; 155 scc_driver->init_termios = tty_std_termios; 156 scc_driver->init_termios.c_cflag = 157 B9600 | CS8 | CREAD | HUPCL | CLOCAL; 158 scc_driver->flags = TTY_DRIVER_REAL_RAW; 159 tty_set_operations(scc_driver, &scc_ops); 160 161 if ((error = tty_register_driver(scc_driver))) { 162 printk(KERN_ERR "scc: Couldn't register scc driver, error = %d\n", 163 error); 164 put_tty_driver(scc_driver); 165 return 1; 166 } 167 168 return 0; 169} 170 171 172/* ports[] array is indexed by line no (i.e. [0] for ttyS0, [1] for ttyS1). 173 */ 174 175static void scc_init_portstructs(void) 176{ 177 struct scc_port *port; 178 int i; 179 180 for (i = 0; i < 2; i++) { 181 port = scc_ports + i; 182 port->gs.magic = SCC_MAGIC; 183 port->gs.close_delay = HZ/2; 184 port->gs.closing_wait = 30 * HZ; 185 port->gs.rd = &scc_real_driver; 186#ifdef NEW_WRITE_LOCKING 187 port->gs.port_write_sem = MUTEX; 188#endif 189 init_waitqueue_head(&port->gs.open_wait); 190 init_waitqueue_head(&port->gs.close_wait); 191 } 192} 193 194 195#ifdef CONFIG_MVME147_SCC 196static int mvme147_scc_init(void) 197{ 198 struct scc_port *port; 199 200 printk(KERN_INFO "SCC: MVME147 Serial Driver\n"); 201 /* Init channel A */ 202 port = &scc_ports[0]; 203 port->channel = CHANNEL_A; 204 port->ctrlp = (volatile unsigned char *)M147_SCC_A_ADDR; 205 port->datap = port->ctrlp + 1; 206 port->port_a = &scc_ports[0]; 207 port->port_b = &scc_ports[1]; 208 request_irq(MVME147_IRQ_SCCA_TX, scc_tx_int, SA_INTERRUPT, 209 "SCC-A TX", port); 210 request_irq(MVME147_IRQ_SCCA_STAT, scc_stat_int, SA_INTERRUPT, 211 "SCC-A status", port); 212 request_irq(MVME147_IRQ_SCCA_RX, scc_rx_int, SA_INTERRUPT, 213 "SCC-A RX", port); 214 request_irq(MVME147_IRQ_SCCA_SPCOND, scc_spcond_int, SA_INTERRUPT, 215 "SCC-A special cond", port); 216 { 217 SCC_ACCESS_INIT(port); 218 219 /* disable interrupts for this channel */ 220 SCCwrite(INT_AND_DMA_REG, 0); 221 /* Set the interrupt vector */ 222 SCCwrite(INT_VECTOR_REG, MVME147_IRQ_SCC_BASE); 223 /* Interrupt parameters: vector includes status, status low */ 224 SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT); 225 SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB); 226 } 227 228 /* Init channel B */ 229 port = &scc_ports[1]; 230 port->channel = CHANNEL_B; 231 port->ctrlp = (volatile unsigned char *)M147_SCC_B_ADDR; 232 port->datap = port->ctrlp + 1; 233 port->port_a = &scc_ports[0]; 234 port->port_b = &scc_ports[1]; 235 request_irq(MVME147_IRQ_SCCB_TX, scc_tx_int, SA_INTERRUPT, 236 "SCC-B TX", port); 237 request_irq(MVME147_IRQ_SCCB_STAT, scc_stat_int, SA_INTERRUPT, 238 "SCC-B status", port); 239 request_irq(MVME147_IRQ_SCCB_RX, scc_rx_int, SA_INTERRUPT, 240 "SCC-B RX", port); 241 request_irq(MVME147_IRQ_SCCB_SPCOND, scc_spcond_int, SA_INTERRUPT, 242 "SCC-B special cond", port); 243 { 244 SCC_ACCESS_INIT(port); 245 246 /* disable interrupts for this channel */ 247 SCCwrite(INT_AND_DMA_REG, 0); 248 } 249 250 /* Ensure interrupts are enabled in the PCC chip */ 251 m147_pcc->serial_cntrl=PCC_LEVEL_SERIAL|PCC_INT_ENAB; 252 253 /* Initialise the tty driver structures and register */ 254 scc_init_portstructs(); 255 scc_init_drivers(); 256 257 return 0; 258} 259#endif 260 261 262#ifdef CONFIG_MVME162_SCC 263static int mvme162_scc_init(void) 264{ 265 struct scc_port *port; 266 267 if (!(mvme16x_config & MVME16x_CONFIG_GOT_SCCA)) 268 return (-ENODEV); 269 270 printk(KERN_INFO "SCC: MVME162 Serial Driver\n"); 271 /* Init channel A */ 272 port = &scc_ports[0]; 273 port->channel = CHANNEL_A; 274 port->ctrlp = (volatile unsigned char *)MVME_SCC_A_ADDR; 275 port->datap = port->ctrlp + 2; 276 port->port_a = &scc_ports[0]; 277 port->port_b = &scc_ports[1]; 278 request_irq(MVME162_IRQ_SCCA_TX, scc_tx_int, SA_INTERRUPT, 279 "SCC-A TX", port); 280 request_irq(MVME162_IRQ_SCCA_STAT, scc_stat_int, SA_INTERRUPT, 281 "SCC-A status", port); 282 request_irq(MVME162_IRQ_SCCA_RX, scc_rx_int, SA_INTERRUPT, 283 "SCC-A RX", port); 284 request_irq(MVME162_IRQ_SCCA_SPCOND, scc_spcond_int, SA_INTERRUPT, 285 "SCC-A special cond", port); 286 { 287 SCC_ACCESS_INIT(port); 288 289 /* disable interrupts for this channel */ 290 SCCwrite(INT_AND_DMA_REG, 0); 291 /* Set the interrupt vector */ 292 SCCwrite(INT_VECTOR_REG, MVME162_IRQ_SCC_BASE); 293 /* Interrupt parameters: vector includes status, status low */ 294 SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT); 295 SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB); 296 } 297 298 /* Init channel B */ 299 port = &scc_ports[1]; 300 port->channel = CHANNEL_B; 301 port->ctrlp = (volatile unsigned char *)MVME_SCC_B_ADDR; 302 port->datap = port->ctrlp + 2; 303 port->port_a = &scc_ports[0]; 304 port->port_b = &scc_ports[1]; 305 request_irq(MVME162_IRQ_SCCB_TX, scc_tx_int, SA_INTERRUPT, 306 "SCC-B TX", port); 307 request_irq(MVME162_IRQ_SCCB_STAT, scc_stat_int, SA_INTERRUPT, 308 "SCC-B status", port); 309 request_irq(MVME162_IRQ_SCCB_RX, scc_rx_int, SA_INTERRUPT, 310 "SCC-B RX", port); 311 request_irq(MVME162_IRQ_SCCB_SPCOND, scc_spcond_int, SA_INTERRUPT, 312 "SCC-B special cond", port); 313 314 { 315 SCC_ACCESS_INIT(port); /* Either channel will do */ 316 317 /* disable interrupts for this channel */ 318 SCCwrite(INT_AND_DMA_REG, 0); 319 } 320 321 /* Ensure interrupts are enabled in the MC2 chip */ 322 *(volatile char *)0xfff4201d = 0x14; 323 324 /* Initialise the tty driver structures and register */ 325 scc_init_portstructs(); 326 scc_init_drivers(); 327 328 return 0; 329} 330#endif 331 332 333#ifdef CONFIG_BVME6000_SCC 334static int bvme6000_scc_init(void) 335{ 336 struct scc_port *port; 337 338 printk(KERN_INFO "SCC: BVME6000 Serial Driver\n"); 339 /* Init channel A */ 340 port = &scc_ports[0]; 341 port->channel = CHANNEL_A; 342 port->ctrlp = (volatile unsigned char *)BVME_SCC_A_ADDR; 343 port->datap = port->ctrlp + 4; 344 port->port_a = &scc_ports[0]; 345 port->port_b = &scc_ports[1]; 346 request_irq(BVME_IRQ_SCCA_TX, scc_tx_int, SA_INTERRUPT, 347 "SCC-A TX", port); 348 request_irq(BVME_IRQ_SCCA_STAT, scc_stat_int, SA_INTERRUPT, 349 "SCC-A status", port); 350 request_irq(BVME_IRQ_SCCA_RX, scc_rx_int, SA_INTERRUPT, 351 "SCC-A RX", port); 352 request_irq(BVME_IRQ_SCCA_SPCOND, scc_spcond_int, SA_INTERRUPT, 353 "SCC-A special cond", port); 354 { 355 SCC_ACCESS_INIT(port); 356 357 /* disable interrupts for this channel */ 358 SCCwrite(INT_AND_DMA_REG, 0); 359 /* Set the interrupt vector */ 360 SCCwrite(INT_VECTOR_REG, BVME_IRQ_SCC_BASE); 361 /* Interrupt parameters: vector includes status, status low */ 362 SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT); 363 SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB); 364 } 365 366 /* Init channel B */ 367 port = &scc_ports[1]; 368 port->channel = CHANNEL_B; 369 port->ctrlp = (volatile unsigned char *)BVME_SCC_B_ADDR; 370 port->datap = port->ctrlp + 4; 371 port->port_a = &scc_ports[0]; 372 port->port_b = &scc_ports[1]; 373 request_irq(BVME_IRQ_SCCB_TX, scc_tx_int, SA_INTERRUPT, 374 "SCC-B TX", port); 375 request_irq(BVME_IRQ_SCCB_STAT, scc_stat_int, SA_INTERRUPT, 376 "SCC-B status", port); 377 request_irq(BVME_IRQ_SCCB_RX, scc_rx_int, SA_INTERRUPT, 378 "SCC-B RX", port); 379 request_irq(BVME_IRQ_SCCB_SPCOND, scc_spcond_int, SA_INTERRUPT, 380 "SCC-B special cond", port); 381 382 { 383 SCC_ACCESS_INIT(port); /* Either channel will do */ 384 385 /* disable interrupts for this channel */ 386 SCCwrite(INT_AND_DMA_REG, 0); 387 } 388 389 /* Initialise the tty driver structures and register */ 390 scc_init_portstructs(); 391 scc_init_drivers(); 392 393 return 0; 394} 395#endif 396 397 398static int vme_scc_init(void) 399{ 400 int res = -ENODEV; 401 402#ifdef CONFIG_MVME147_SCC 403 if (MACH_IS_MVME147) 404 res = mvme147_scc_init(); 405#endif 406#ifdef CONFIG_MVME162_SCC 407 if (MACH_IS_MVME16x) 408 res = mvme162_scc_init(); 409#endif 410#ifdef CONFIG_BVME6000_SCC 411 if (MACH_IS_BVME6000) 412 res = bvme6000_scc_init(); 413#endif 414 return res; 415} 416 417module_init(vme_scc_init); 418 419 420/*--------------------------------------------------------------------------- 421 * Interrupt handlers 422 *--------------------------------------------------------------------------*/ 423 424static irqreturn_t scc_rx_int(int irq, void *data, struct pt_regs *fp) 425{ 426 unsigned char ch; 427 struct scc_port *port = data; 428 struct tty_struct *tty = port->gs.tty; 429 SCC_ACCESS_INIT(port); 430 431 ch = SCCread_NB(RX_DATA_REG); 432 if (!tty) { 433 printk(KERN_WARNING "scc_rx_int with NULL tty!\n"); 434 SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); 435 return IRQ_HANDLED; 436 } 437 if (tty->flip.count < TTY_FLIPBUF_SIZE) { 438 *tty->flip.char_buf_ptr = ch; 439 *tty->flip.flag_buf_ptr = 0; 440 tty->flip.flag_buf_ptr++; 441 tty->flip.char_buf_ptr++; 442 tty->flip.count++; 443 } 444 445 /* Check if another character is already ready; in that case, the 446 * spcond_int() function must be used, because this character may have an 447 * error condition that isn't signalled by the interrupt vector used! 448 */ 449 if (SCCread(INT_PENDING_REG) & 450 (port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX)) { 451 scc_spcond_int (irq, data, fp); 452 return IRQ_HANDLED; 453 } 454 455 SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); 456 457 tty_flip_buffer_push(tty); 458 return IRQ_HANDLED; 459} 460 461 462static irqreturn_t scc_spcond_int(int irq, void *data, struct pt_regs *fp) 463{ 464 struct scc_port *port = data; 465 struct tty_struct *tty = port->gs.tty; 466 unsigned char stat, ch, err; 467 int int_pending_mask = port->channel == CHANNEL_A ? 468 IPR_A_RX : IPR_B_RX; 469 SCC_ACCESS_INIT(port); 470 471 if (!tty) { 472 printk(KERN_WARNING "scc_spcond_int with NULL tty!\n"); 473 SCCwrite(COMMAND_REG, CR_ERROR_RESET); 474 SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); 475 return IRQ_HANDLED; 476 } 477 do { 478 stat = SCCread(SPCOND_STATUS_REG); 479 ch = SCCread_NB(RX_DATA_REG); 480 481 if (stat & SCSR_RX_OVERRUN) 482 err = TTY_OVERRUN; 483 else if (stat & SCSR_PARITY_ERR) 484 err = TTY_PARITY; 485 else if (stat & SCSR_CRC_FRAME_ERR) 486 err = TTY_FRAME; 487 else 488 err = 0; 489 490 if (tty->flip.count < TTY_FLIPBUF_SIZE) { 491 *tty->flip.char_buf_ptr = ch; 492 *tty->flip.flag_buf_ptr = err; 493 tty->flip.flag_buf_ptr++; 494 tty->flip.char_buf_ptr++; 495 tty->flip.count++; 496 } 497 498 /* ++TeSche: *All* errors have to be cleared manually, 499 * else the condition persists for the next chars 500 */ 501 if (err) 502 SCCwrite(COMMAND_REG, CR_ERROR_RESET); 503 504 } while(SCCread(INT_PENDING_REG) & int_pending_mask); 505 506 SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); 507 508 tty_flip_buffer_push(tty); 509 return IRQ_HANDLED; 510} 511 512 513static irqreturn_t scc_tx_int(int irq, void *data, struct pt_regs *fp) 514{ 515 struct scc_port *port = data; 516 SCC_ACCESS_INIT(port); 517 518 if (!port->gs.tty) { 519 printk(KERN_WARNING "scc_tx_int with NULL tty!\n"); 520 SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); 521 SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET); 522 SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); 523 return IRQ_HANDLED; 524 } 525 while ((SCCread_NB(STATUS_REG) & SR_TX_BUF_EMPTY)) { 526 if (port->x_char) { 527 SCCwrite(TX_DATA_REG, port->x_char); 528 port->x_char = 0; 529 } 530 else if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped || 531 port->gs.tty->hw_stopped) 532 break; 533 else { 534 SCCwrite(TX_DATA_REG, port->gs.xmit_buf[port->gs.xmit_tail++]); 535 port->gs.xmit_tail = port->gs.xmit_tail & (SERIAL_XMIT_SIZE-1); 536 if (--port->gs.xmit_cnt <= 0) 537 break; 538 } 539 } 540 if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped || 541 port->gs.tty->hw_stopped) { 542 /* disable tx interrupts */ 543 SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); 544 SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET); /* disable tx_int on next tx underrun? */ 545 port->gs.flags &= ~GS_TX_INTEN; 546 } 547 if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) 548 tty_wakeup(port->gs.tty); 549 550 SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); 551 return IRQ_HANDLED; 552} 553 554 555static irqreturn_t scc_stat_int(int irq, void *data, struct pt_regs *fp) 556{ 557 struct scc_port *port = data; 558 unsigned channel = port->channel; 559 unsigned char last_sr, sr, changed; 560 SCC_ACCESS_INIT(port); 561 562 last_sr = scc_last_status_reg[channel]; 563 sr = scc_last_status_reg[channel] = SCCread_NB(STATUS_REG); 564 changed = last_sr ^ sr; 565 566 if (changed & SR_DCD) { 567 port->c_dcd = !!(sr & SR_DCD); 568 if (!(port->gs.flags & ASYNC_CHECK_CD)) 569 ; /* Don't report DCD changes */ 570 else if (port->c_dcd) { 571 wake_up_interruptible(&port->gs.open_wait); 572 } 573 else { 574 if (port->gs.tty) 575 tty_hangup (port->gs.tty); 576 } 577 } 578 SCCwrite(COMMAND_REG, CR_EXTSTAT_RESET); 579 SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); 580 return IRQ_HANDLED; 581} 582 583 584/*--------------------------------------------------------------------------- 585 * generic_serial.c callback funtions 586 *--------------------------------------------------------------------------*/ 587 588static void scc_disable_tx_interrupts(void *ptr) 589{ 590 struct scc_port *port = ptr; 591 unsigned long flags; 592 SCC_ACCESS_INIT(port); 593 594 local_irq_save(flags); 595 SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); 596 port->gs.flags &= ~GS_TX_INTEN; 597 local_irq_restore(flags); 598} 599 600 601static void scc_enable_tx_interrupts(void *ptr) 602{ 603 struct scc_port *port = ptr; 604 unsigned long flags; 605 SCC_ACCESS_INIT(port); 606 607 local_irq_save(flags); 608 SCCmod(INT_AND_DMA_REG, 0xff, IDR_TX_INT_ENAB); 609 /* restart the transmitter */ 610 scc_tx_int (0, port, 0); 611 local_irq_restore(flags); 612} 613 614 615static void scc_disable_rx_interrupts(void *ptr) 616{ 617 struct scc_port *port = ptr; 618 unsigned long flags; 619 SCC_ACCESS_INIT(port); 620 621 local_irq_save(flags); 622 SCCmod(INT_AND_DMA_REG, 623 ~(IDR_RX_INT_MASK|IDR_PARERR_AS_SPCOND|IDR_EXTSTAT_INT_ENAB), 0); 624 local_irq_restore(flags); 625} 626 627 628static void scc_enable_rx_interrupts(void *ptr) 629{ 630 struct scc_port *port = ptr; 631 unsigned long flags; 632 SCC_ACCESS_INIT(port); 633 634 local_irq_save(flags); 635 SCCmod(INT_AND_DMA_REG, 0xff, 636 IDR_EXTSTAT_INT_ENAB|IDR_PARERR_AS_SPCOND|IDR_RX_INT_ALL); 637 local_irq_restore(flags); 638} 639 640 641static int scc_get_CD(void *ptr) 642{ 643 struct scc_port *port = ptr; 644 unsigned channel = port->channel; 645 646 return !!(scc_last_status_reg[channel] & SR_DCD); 647} 648 649 650static void scc_shutdown_port(void *ptr) 651{ 652 struct scc_port *port = ptr; 653 654 port->gs.flags &= ~ GS_ACTIVE; 655 if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) { 656 scc_setsignals (port, 0, 0); 657 } 658} 659 660 661static int scc_set_real_termios (void *ptr) 662{ 663 /* the SCC has char sizes 5,7,6,8 in that order! */ 664 static int chsize_map[4] = { 0, 2, 1, 3 }; 665 unsigned cflag, baud, chsize, channel, brgval = 0; 666 unsigned long flags; 667 struct scc_port *port = ptr; 668 SCC_ACCESS_INIT(port); 669 670 if (!port->gs.tty || !port->gs.tty->termios) return 0; 671 672 channel = port->channel; 673 674 if (channel == CHANNEL_A) 675 return 0; /* Settings controlled by boot PROM */ 676 677 cflag = port->gs.tty->termios->c_cflag; 678 baud = port->gs.baud; 679 chsize = (cflag & CSIZE) >> 4; 680 681 if (baud == 0) { 682 /* speed == 0 -> drop DTR */ 683 local_irq_save(flags); 684 SCCmod(TX_CTRL_REG, ~TCR_DTR, 0); 685 local_irq_restore(flags); 686 return 0; 687 } 688 else if ((MACH_IS_MVME16x && (baud < 50 || baud > 38400)) || 689 (MACH_IS_MVME147 && (baud < 50 || baud > 19200)) || 690 (MACH_IS_BVME6000 &&(baud < 50 || baud > 76800))) { 691 printk(KERN_NOTICE "SCC: Bad speed requested, %d\n", baud); 692 return 0; 693 } 694 695 if (cflag & CLOCAL) 696 port->gs.flags &= ~ASYNC_CHECK_CD; 697 else 698 port->gs.flags |= ASYNC_CHECK_CD; 699 700#ifdef CONFIG_MVME147_SCC 701 if (MACH_IS_MVME147) 702 brgval = (M147_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2; 703#endif 704#ifdef CONFIG_MVME162_SCC 705 if (MACH_IS_MVME16x) 706 brgval = (MVME_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2; 707#endif 708#ifdef CONFIG_BVME6000_SCC 709 if (MACH_IS_BVME6000) 710 brgval = (BVME_SCC_RTxC + baud/2) / (16 * 2 * baud) - 2; 711#endif 712 /* Now we have all parameters and can go to set them: */ 713 local_irq_save(flags); 714 715 /* receiver's character size and auto-enables */ 716 SCCmod(RX_CTRL_REG, ~(RCR_CHSIZE_MASK|RCR_AUTO_ENAB_MODE), 717 (chsize_map[chsize] << 6) | 718 ((cflag & CRTSCTS) ? RCR_AUTO_ENAB_MODE : 0)); 719 /* parity and stop bits (both, Tx and Rx), clock mode never changes */ 720 SCCmod (AUX1_CTRL_REG, 721 ~(A1CR_PARITY_MASK | A1CR_MODE_MASK), 722 ((cflag & PARENB 723 ? (cflag & PARODD ? A1CR_PARITY_ODD : A1CR_PARITY_EVEN) 724 : A1CR_PARITY_NONE) 725 | (cflag & CSTOPB ? A1CR_MODE_ASYNC_2 : A1CR_MODE_ASYNC_1))); 726 /* sender's character size, set DTR for valid baud rate */ 727 SCCmod(TX_CTRL_REG, ~TCR_CHSIZE_MASK, chsize_map[chsize] << 5 | TCR_DTR); 728 /* clock sources never change */ 729 /* disable BRG before changing the value */ 730 SCCmod(DPLL_CTRL_REG, ~DCR_BRG_ENAB, 0); 731 /* BRG value */ 732 SCCwrite(TIMER_LOW_REG, brgval & 0xff); 733 SCCwrite(TIMER_HIGH_REG, (brgval >> 8) & 0xff); 734 /* BRG enable, and clock source never changes */ 735 SCCmod(DPLL_CTRL_REG, 0xff, DCR_BRG_ENAB); 736 737 local_irq_restore(flags); 738 739 return 0; 740} 741 742 743static int scc_chars_in_buffer (void *ptr) 744{ 745 struct scc_port *port = ptr; 746 SCC_ACCESS_INIT(port); 747 748 return (SCCread (SPCOND_STATUS_REG) & SCSR_ALL_SENT) ? 0 : 1; 749} 750 751 752/* Comment taken from sx.c (2.4.0): 753 I haven't the foggiest why the decrement use count has to happen 754 here. The whole linux serial drivers stuff needs to be redesigned. 755 My guess is that this is a hack to minimize the impact of a bug 756 elsewhere. Thinking about it some more. (try it sometime) Try 757 running minicom on a serial port that is driven by a modularized 758 driver. Have the modem hangup. Then remove the driver module. Then 759 exit minicom. I expect an "oops". -- REW */ 760 761static void scc_hungup(void *ptr) 762{ 763 scc_disable_tx_interrupts(ptr); 764 scc_disable_rx_interrupts(ptr); 765} 766 767 768static void scc_close(void *ptr) 769{ 770 scc_disable_tx_interrupts(ptr); 771 scc_disable_rx_interrupts(ptr); 772} 773 774 775/*--------------------------------------------------------------------------- 776 * Internal support functions 777 *--------------------------------------------------------------------------*/ 778 779static void scc_setsignals(struct scc_port *port, int dtr, int rts) 780{ 781 unsigned long flags; 782 unsigned char t; 783 SCC_ACCESS_INIT(port); 784 785 local_irq_save(flags); 786 t = SCCread(TX_CTRL_REG); 787 if (dtr >= 0) t = dtr? (t | TCR_DTR): (t & ~TCR_DTR); 788 if (rts >= 0) t = rts? (t | TCR_RTS): (t & ~TCR_RTS); 789 SCCwrite(TX_CTRL_REG, t); 790 local_irq_restore(flags); 791} 792 793 794static void scc_send_xchar(struct tty_struct *tty, char ch) 795{ 796 struct scc_port *port = (struct scc_port *)tty->driver_data; 797 798 port->x_char = ch; 799 if (ch) 800 scc_enable_tx_interrupts(port); 801} 802 803 804/*--------------------------------------------------------------------------- 805 * Driver entrypoints referenced from above 806 *--------------------------------------------------------------------------*/ 807 808static int scc_open (struct tty_struct * tty, struct file * filp) 809{ 810 int line = tty->index; 811 int retval; 812 struct scc_port *port = &scc_ports[line]; 813 int i, channel = port->channel; 814 unsigned long flags; 815 SCC_ACCESS_INIT(port); 816#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_MVME147_SCC) 817 static const struct { 818 unsigned reg, val; 819 } mvme_init_tab[] = { 820 /* Values for MVME162 and MVME147 */ 821 /* no parity, 1 stop bit, async, 1:16 */ 822 { AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 }, 823 /* parity error is special cond, ints disabled, no DMA */ 824 { INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB }, 825 /* Rx 8 bits/char, no auto enable, Rx off */ 826 { RX_CTRL_REG, RCR_CHSIZE_8 }, 827 /* DTR off, Tx 8 bits/char, RTS off, Tx off */ 828 { TX_CTRL_REG, TCR_CHSIZE_8 }, 829 /* special features off */ 830 { AUX2_CTRL_REG, 0 }, 831 { CLK_CTRL_REG, CCR_RXCLK_BRG | CCR_TXCLK_BRG }, 832 { DPLL_CTRL_REG, DCR_BRG_ENAB | DCR_BRG_USE_PCLK }, 833 /* Start Rx */ 834 { RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 }, 835 /* Start Tx */ 836 { TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 }, 837 /* Ext/Stat ints: DCD only */ 838 { INT_CTRL_REG, ICR_ENAB_DCD_INT }, 839 /* Reset Ext/Stat ints */ 840 { COMMAND_REG, CR_EXTSTAT_RESET }, 841 /* ...again */ 842 { COMMAND_REG, CR_EXTSTAT_RESET }, 843 }; 844#endif 845#if defined(CONFIG_BVME6000_SCC) 846 static const struct { 847 unsigned reg, val; 848 } bvme_init_tab[] = { 849 /* Values for BVME6000 */ 850 /* no parity, 1 stop bit, async, 1:16 */ 851 { AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 }, 852 /* parity error is special cond, ints disabled, no DMA */ 853 { INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB }, 854 /* Rx 8 bits/char, no auto enable, Rx off */ 855 { RX_CTRL_REG, RCR_CHSIZE_8 }, 856 /* DTR off, Tx 8 bits/char, RTS off, Tx off */ 857 { TX_CTRL_REG, TCR_CHSIZE_8 }, 858 /* special features off */ 859 { AUX2_CTRL_REG, 0 }, 860 { CLK_CTRL_REG, CCR_RTxC_XTAL | CCR_RXCLK_BRG | CCR_TXCLK_BRG }, 861 { DPLL_CTRL_REG, DCR_BRG_ENAB }, 862 /* Start Rx */ 863 { RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 }, 864 /* Start Tx */ 865 { TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 }, 866 /* Ext/Stat ints: DCD only */ 867 { INT_CTRL_REG, ICR_ENAB_DCD_INT }, 868 /* Reset Ext/Stat ints */ 869 { COMMAND_REG, CR_EXTSTAT_RESET }, 870 /* ...again */ 871 { COMMAND_REG, CR_EXTSTAT_RESET }, 872 }; 873#endif 874 if (!(port->gs.flags & ASYNC_INITIALIZED)) { 875 local_irq_save(flags); 876#if defined(CONFIG_MVME147_SCC) || defined(CONFIG_MVME162_SCC) 877 if (MACH_IS_MVME147 || MACH_IS_MVME16x) { 878 for (i=0; i<sizeof(mvme_init_tab)/sizeof(*mvme_init_tab); ++i) 879 SCCwrite(mvme_init_tab[i].reg, mvme_init_tab[i].val); 880 } 881#endif 882#if defined(CONFIG_BVME6000_SCC) 883 if (MACH_IS_BVME6000) { 884 for (i=0; i<sizeof(bvme_init_tab)/sizeof(*bvme_init_tab); ++i) 885 SCCwrite(bvme_init_tab[i].reg, bvme_init_tab[i].val); 886 } 887#endif 888 889 /* remember status register for detection of DCD and CTS changes */ 890 scc_last_status_reg[channel] = SCCread(STATUS_REG); 891 892 port->c_dcd = 0; /* Prevent initial 1->0 interrupt */ 893 scc_setsignals (port, 1,1); 894 local_irq_restore(flags); 895 } 896 897 tty->driver_data = port; 898 port->gs.tty = tty; 899 port->gs.count++; 900 retval = gs_init_port(&port->gs); 901 if (retval) { 902 port->gs.count--; 903 return retval; 904 } 905 port->gs.flags |= GS_ACTIVE; 906 retval = gs_block_til_ready(port, filp); 907 908 if (retval) { 909 port->gs.count--; 910 return retval; 911 } 912 913 port->c_dcd = scc_get_CD (port); 914 915 scc_enable_rx_interrupts(port); 916 917 return 0; 918} 919 920 921static void scc_throttle (struct tty_struct * tty) 922{ 923 struct scc_port *port = (struct scc_port *)tty->driver_data; 924 unsigned long flags; 925 SCC_ACCESS_INIT(port); 926 927 if (tty->termios->c_cflag & CRTSCTS) { 928 local_irq_save(flags); 929 SCCmod(TX_CTRL_REG, ~TCR_RTS, 0); 930 local_irq_restore(flags); 931 } 932 if (I_IXOFF(tty)) 933 scc_send_xchar(tty, STOP_CHAR(tty)); 934} 935 936 937static void scc_unthrottle (struct tty_struct * tty) 938{ 939 struct scc_port *port = (struct scc_port *)tty->driver_data; 940 unsigned long flags; 941 SCC_ACCESS_INIT(port); 942 943 if (tty->termios->c_cflag & CRTSCTS) { 944 local_irq_save(flags); 945 SCCmod(TX_CTRL_REG, 0xff, TCR_RTS); 946 local_irq_restore(flags); 947 } 948 if (I_IXOFF(tty)) 949 scc_send_xchar(tty, START_CHAR(tty)); 950} 951 952 953static int scc_ioctl(struct tty_struct *tty, struct file *file, 954 unsigned int cmd, unsigned long arg) 955{ 956 return -ENOIOCTLCMD; 957} 958 959 960static void scc_break_ctl(struct tty_struct *tty, int break_state) 961{ 962 struct scc_port *port = (struct scc_port *)tty->driver_data; 963 unsigned long flags; 964 SCC_ACCESS_INIT(port); 965 966 local_irq_save(flags); 967 SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK, 968 break_state ? TCR_SEND_BREAK : 0); 969 local_irq_restore(flags); 970} 971 972 973/*--------------------------------------------------------------------------- 974 * Serial console stuff... 975 *--------------------------------------------------------------------------*/ 976 977#define scc_delay() do { __asm__ __volatile__ (" nop; nop"); } while (0) 978 979static void scc_ch_write (char ch) 980{ 981 volatile char *p = NULL; 982 983#ifdef CONFIG_MVME147_SCC 984 if (MACH_IS_MVME147) 985 p = (volatile char *)M147_SCC_A_ADDR; 986#endif 987#ifdef CONFIG_MVME162_SCC 988 if (MACH_IS_MVME16x) 989 p = (volatile char *)MVME_SCC_A_ADDR; 990#endif 991#ifdef CONFIG_BVME6000_SCC 992 if (MACH_IS_BVME6000) 993 p = (volatile char *)BVME_SCC_A_ADDR; 994#endif 995 996 do { 997 scc_delay(); 998 } 999 while (!(*p & 4)); 1000 scc_delay(); 1001 *p = 8; 1002 scc_delay(); 1003 *p = ch; 1004} 1005 1006/* The console must be locked when we get here. */ 1007 1008static void scc_console_write (struct console *co, const char *str, unsigned count) 1009{ 1010 unsigned long flags; 1011 1012 local_irq_save(flags); 1013 1014 while (count--) 1015 { 1016 if (*str == '\n') 1017 scc_ch_write ('\r'); 1018 scc_ch_write (*str++); 1019 } 1020 local_irq_restore(flags); 1021} 1022 1023static struct tty_driver *scc_console_device(struct console *c, int *index) 1024{ 1025 *index = c->index; 1026 return scc_driver; 1027} 1028 1029 1030static int __init scc_console_setup(struct console *co, char *options) 1031{ 1032 return 0; 1033} 1034 1035 1036static struct console sercons = { 1037 .name = "ttyS", 1038 .write = scc_console_write, 1039 .device = scc_console_device, 1040 .setup = scc_console_setup, 1041 .flags = CON_PRINTBUFFER, 1042 .index = -1, 1043}; 1044 1045 1046static int __init vme_scc_console_init(void) 1047{ 1048 if (vme_brdtype == VME_TYPE_MVME147 || 1049 vme_brdtype == VME_TYPE_MVME162 || 1050 vme_brdtype == VME_TYPE_MVME172 || 1051 vme_brdtype == VME_TYPE_BVME4000 || 1052 vme_brdtype == VME_TYPE_BVME6000) 1053 register_console(&sercons); 1054 return 0; 1055} 1056console_initcall(vme_scc_console_init);