Beispiel #1
0
__initfunc(static enum uart check_uart(unsigned int iobase))
{
    unsigned char b1,b2,b3;
    enum uart u;
    enum uart uart_tab[] = { c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A };

    if (iobase <= 0 || iobase > 0x1000-SER_EXTENT)
        return c_uart_unknown;
    if (check_region(iobase, SER_EXTENT))
        return c_uart_unknown;
    b1 = inb(UART_MCR(iobase));
    outb(b1 | 0x10, UART_MCR(iobase));      /* loopback mode */
    b2 = inb(UART_MSR(iobase));
    outb(0x1a, UART_MCR(iobase));
    b3 = inb(UART_MSR(iobase)) & 0xf0;
    outb(b1, UART_MCR(iobase));        /* restore old values */
    outb(b2, UART_MSR(iobase));
    if (b3 != 0x90)
        return c_uart_unknown;
    inb(UART_RBR(iobase));
    inb(UART_RBR(iobase));
    outb(0x01, UART_FCR(iobase));           /* enable FIFOs */
    u = uart_tab[(inb(UART_IIR(iobase)) >> 6) & 3];
    if (u == c_uart_16450) {
        outb(0x5a, UART_SCR(iobase));
        b1 = inb(UART_SCR(iobase));
        outb(0xa5, UART_SCR(iobase));
        b2 = inb(UART_SCR(iobase));
        if ((b1 != 0x5a) || (b2 != 0xa5))
            u = c_uart_8250;
    }
    return u;
}
/*
 * This is the serial driver's generic interrupt routine
 * Note: Generally it should be attached to general interrupt 10, responsile 
 *       for UART0&1 RCV and XMT interrupt, to make sure the invoked interrupt
 *       source, look into bit 10-13 of SIC_ISR(peripheral interrupt status reg.
 *       Finally, to see what can be done about request_irq(......)
 */
void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
	struct bf535_serial *info; // = &bf535_soft[CONFIG_SERIAL_CONSOLE_PORT];
	unsigned short iir; /* Interrupt Identification Register */
	unsigned short rx, idx;
	unsigned int sic_status = SIC_ISR;

	for (idx = 0; idx < NR_PORTS; idx++){
	   if (sic_status & (UART_INVOKED << 2*(idx + 5))){ 
	   	/* test bit 10-11 and 12-13 */
		iir = UART_IIR(idx);
		info = &bf535_soft[idx];

		if (!(iir & UART_IIR_NOINT)){
		   switch (iir & UART_IIR_STATUS){
		   case UART_IIR_LSR:
				printk("Line status changed for serial port %d.\n", idx);
				break;
		   case UART_IIR_RBR:
		   		/* Change access to IER & data port */
				ACCESS_PORT_IER(idx) 
				if (UART_LSR(idx) & UART_LSR_DR){
				   rx = UART_RBR(idx);
				   receive_chars(info, regs, rx);
				}
				break;
		   case UART_IIR_THR:
		   		/* Change access to IER & data port */
				ACCESS_PORT_IER(idx) 
				if (UART_LSR(idx) & UART_LSR_THRE){
				    transmit_chars(info);
//				    do{
//					transmit_chars(info);
//				    }while(info->xmit_cnt > 0);
				}
				break;
		   case UART_IIR_MSR:
				printk("Modem status changed for serial port.\n");
			
	   	   }
		}
	   }
	}