kernels/linux-2.4.0/drivers/s390/char/con3215.c
/*
 * Interrupt routine, called from Ingo's I/O layer
 */
Interrupt routine, called from Ingo's I/O layer
Interrupt routine called from Ingo ' s I / O layer
static void raw3215_irq(int irq, void *int_parm, struct pt_regs *regs)
{
	raw3215_info *raw;
	raw3215_req *req;
	struct tty_struct *tty;
	devstat_t *stat;
        int cstat, dstat;
	int count, slen;
	stat = (devstat_t *) int_parm;
	req = (raw3215_req *) stat->intparm;
	cstat = stat->cstat;
	dstat = stat->dstat;
	if (cstat != 0) {
		raw = raw3215_find_info(irq);
		if (raw != NULL) {
			raw->message = KERN_WARNING
				"Got nonzero channel status in raw3215_irq "
				"(dev %i, dev sts 0x%2x, sch sts 0x%2x)";
			raw->msg_dstat = dstat;
			raw->msg_cstat = cstat;
                        raw3215_sched_bh(raw);
		}
	}
        if (dstat & 0x01) { 
		dstat &= ~0x01;  
        }
	switch (dstat) {
	case 0x80:
		if (cstat != 0)
			break;
		if ((raw = raw3215_find_info(irq)) == NULL)
			return;              
		req = raw3215_mk_read_req(raw);
		raw3215_mk_read_ccw(raw, req);
		raw->queued_read = req;
                if (MACHINE_IS_P390)
                        memset(raw->inbuf, 0, RAW3215_INBUF_SIZE);
                raw3215_sched_bh(raw);
		break;
	case 0x08:
	case 0x0C:
		raw = req->info;
		if (req->type == RAW3215_READ) {
			req->residual = stat->rescnt;
		}
		if (dstat == 0x08)
			break;
	case 0x04:
		raw = req->info;
		if (req->type == RAW3215_READ && raw->tty != NULL) {
			tty = raw->tty;
                        count = 160 - req->residual;
                        if (MACHINE_IS_P390) {
                                slen = strnlen(raw->inbuf, RAW3215_INBUF_SIZE);
                                if (count > slen)
                                        count = slen;
                        } else
			if (count >= TTY_FLIPBUF_SIZE - tty->flip.count)
				count = TTY_FLIPBUF_SIZE - tty->flip.count - 1;
			EBCASC(raw->inbuf, count);
			if (count == 2 && (
                            strncmp(raw->inbuf, "^c", 2) == 0 ||
                            strncmp(raw->inbuf, "\252c", 2) == 0) ) {
				tty->flip.count++;
				*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
				*tty->flip.char_buf_ptr++ = INTR_CHAR(tty);
				tty_flip_buffer_push(raw->tty);
			} else if (count == 2 && (
                                   strncmp(raw->inbuf, "^d", 2) == 0 ||
                                    strncmp(raw->inbuf, "\252d", 2) == 0) ) {
				tty->flip.count++;
				*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
				*tty->flip.char_buf_ptr++ = EOF_CHAR(tty);
				tty_flip_buffer_push(raw->tty);
			} else if (count == 2 && (
                                   strncmp(raw->inbuf, "^z", 2) == 0 ||
                                    strncmp(raw->inbuf, "\252z", 2) == 0) ) {
				tty->flip.count++;
				*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
				*tty->flip.char_buf_ptr++ = SUSP_CHAR(tty);
				tty_flip_buffer_push(raw->tty);
			} else {
				memcpy(tty->flip.char_buf_ptr,
				       raw->inbuf, count);
				if (count < 2 ||
                                    (strncmp(raw->inbuf+count-2, "^n", 2) ||
                                    strncmp(raw->inbuf+count-2, "\252n", 2)) ) {					
					tty->flip.char_buf_ptr[count] = '\n';
					memset(tty->flip.flag_buf_ptr,
					       TTY_NORMAL, count + 1);
					count++;
				} else
					count-=2;
				tty->flip.char_buf_ptr += count;
				tty->flip.flag_buf_ptr += count;
				tty->flip.count += count;
				tty_flip_buffer_push(raw->tty);
			}
		} else if (req->type == RAW3215_WRITE) {
			raw->count -= ((req->end - req->start) &
				       (RAW3215_BUFFER_SIZE - 1)) + 1;
		}
		raw->flags &= ~RAW3215_WORKING;
		raw3215_free_req(req);
		if (waitqueue_active(&raw->empty_wait) &&
		    raw->queued_write == NULL &&
		    raw->queued_read == NULL) {
			wake_up_interruptible(&raw->empty_wait);
		}
                raw3215_sched_bh(raw);
		break;
	default:
                if ((raw = raw3215_find_info(irq)) == NULL)
                        return;              
                if (raw == NULL) break;
		if (req != NULL && req->type != RAW3215_FREE) {
		        if (req->type == RAW3215_WRITE) 
			        raw->count -= ((req->end - req->start) &
				              (RAW3215_BUFFER_SIZE-1))+1;
                        raw->flags &= ~RAW3215_WORKING;
                        raw3215_free_req(req);
		}
		raw->message = KERN_WARNING
			"Spurious interrupt in in raw3215_irq "
			"(dev %i, dev sts 0x%2x, sch sts 0x%2x)";
		raw->msg_dstat = dstat;
		raw->msg_cstat = cstat;
                raw3215_sched_bh(raw);
	}
	return;
}
static void raw3215_irq ( int irq , void * int_parm , struct pt_regs * regs ) { raw3215_info * raw ; raw3215_req * req ; struct tty_struct * tty ; devstat_t * stat ; int cstat , dstat ; int count , slen ; stat = ( devstat_t * ) int_parm ; req = ( raw3215_req * ) stat -> intparm ; cstat = stat -> cstat ; dstat = stat -> dstat ; if ( cstat != 0 ) { raw = raw3215_find_info ( irq ) ; if ( raw != NULL ) { raw -> message = KERN_WARNING " " " " ; raw -> msg_dstat = dstat ; raw -> msg_cstat = cstat ; raw3215_sched_bh ( raw ) ; } } if ( dstat & 0x01 ) { dstat &= ~ 0x01 ; } switch ( dstat ) { case 0x80 : if ( cstat != 0 ) break ; if ( ( raw = raw3215_find_info ( irq ) ) == NULL ) return ; req = raw3215_mk_read_req ( raw ) ; raw3215_mk_read_ccw ( raw , req ) ; raw -> queued_read = req ; if ( MACHINE_IS_P390 ) memset ( raw -> inbuf , 0 , RAW3215_INBUF_SIZE ) ; raw3215_sched_bh ( raw ) ; break ; case 0x08 : case 0x0C : raw = req -> info ; if ( req -> type == RAW3215_READ ) { req -> residual = stat -> rescnt ; } if ( dstat == 0x08 ) break ; case 0x04 : raw = req -> info ; if ( req -> type == RAW3215_READ && raw -> tty != NULL ) { tty = raw -> tty ; count = 160 - req -> residual ; if ( MACHINE_IS_P390 ) { slen = strnlen ( raw -> inbuf , RAW3215_INBUF_SIZE ) ; if ( count > slen ) count = slen ; } else if ( count >= TTY_FLIPBUF_SIZE - tty -> flip . count ) count = TTY_FLIPBUF_SIZE - tty -> flip . count - 1 ; EBCASC ( raw -> inbuf , count ) ; if ( count == 2 && ( strncmp ( raw -> inbuf , " " , 2 ) == 0 || strncmp ( raw -> inbuf , " \252 " , 2 ) == 0 ) ) { tty -> flip . count ++ ; * tty -> flip . flag_buf_ptr ++ = TTY_NORMAL ; * tty -> flip . char_buf_ptr ++ = INTR_CHAR ( tty ) ; tty_flip_buffer_push ( raw -> tty ) ; } else if ( count == 2 && ( strncmp ( raw -> inbuf , " " , 2 ) == 0 || strncmp ( raw -> inbuf , " \252 " , 2 ) == 0 ) ) { tty -> flip . count ++ ; * tty -> flip . flag_buf_ptr ++ = TTY_NORMAL ; * tty -> flip . char_buf_ptr ++ = EOF_CHAR ( tty ) ; tty_flip_buffer_push ( raw -> tty ) ; } else if ( count == 2 && ( strncmp ( raw -> inbuf , " " , 2 ) == 0 || strncmp ( raw -> inbuf , " \252 " , 2 ) == 0 ) ) { tty -> flip . count ++ ; * tty -> flip . flag_buf_ptr ++ = TTY_NORMAL ; * tty -> flip . char_buf_ptr ++ = SUSP_CHAR ( tty ) ; tty_flip_buffer_push ( raw -> tty ) ; } else { memcpy ( tty -> flip . char_buf_ptr , raw -> inbuf , count ) ; if ( count < 2 || ( strncmp ( raw -> inbuf + count - 2 , " " , 2 ) || strncmp ( raw -> inbuf + count - 2 , " \252 " , 2 ) ) ) { tty -> flip . char_buf_ptr [ count ] = ' \n ' ; memset ( tty -> flip . flag_buf_ptr , TTY_NORMAL , count + 1 ) ; count ++ ; } else count -= 2 ; tty -> flip . char_buf_ptr += count ; tty -> flip . flag_buf_ptr += count ; tty -> flip . count += count ; tty_flip_buffer_push ( raw -> tty ) ; } } else if ( req -> type == RAW3215_WRITE ) { raw -> count -= ( ( req -> end - req -> start ) & ( RAW3215_BUFFER_SIZE - 1 ) ) + 1 ; } raw -> flags &= ~ RAW3215_WORKING ; raw3215_free_req ( req ) ; if ( waitqueue_active ( & raw -> empty_wait ) && raw -> queued_write == NULL && raw -> queued_read == NULL ) { wake_up_interruptible ( & raw -> empty_wait ) ; } raw3215_sched_bh ( raw ) ; break ; default : if ( ( raw = raw3215_find_info ( irq ) ) == NULL ) return ; if ( raw == NULL ) break ; if ( req != NULL && req -> type != RAW3215_FREE ) { if ( req -> type == RAW3215_WRITE ) raw -> count -= ( ( req -> end - req -> start ) & ( RAW3215_BUFFER_SIZE - 1 ) ) + 1 ; raw -> flags &= ~ RAW3215_WORKING ; raw3215_free_req ( req ) ; } raw -> message = KERN_WARNING " " " " ; raw -> msg_dstat = dstat ; raw -> msg_cstat = cstat ; raw3215_sched_bh ( raw ) ; } return ; }
Interrupt routine, called from Ingo's I/O layer
Interrupt routine called from Ingo ' s I / O layer
/* we got a unit exception */ /* we can ignore it */ /* Attention interrupt, someone hit the enter key */ /* That shouldn't happen ... */ /* Setup a read request */ /* Channel end interrupt. */ /* store residual count, then wait for device end */ /* Device end interrupt. */ /* hat is 0xb0 in codepage 037 (US etc.) and thus */ /* converted to 0x5e in ascii ('^') */ /* hat is 0xb0 in several other codepages (German,*/ /* UK, ...) and thus converted to ascii octal 252 */ /* emulate a control C = break */ /* emulate a control D = end of file */ /* emulate a control Z = suspend */ /* don't add the auto \n */ /* check for empty wait */ /* Strange interrupt, I'll do my best to clean up */ /* That shouldn't happen ... */