kernels/linux-2.4.0/drivers/s390/char/con3215.c
/*
 * String write routine for 3215 devices
 */
String write routine for 3215 devices
String write routine for 3215 devices
static int
raw3215_write(raw3215_info *raw, const char *str,
	      int from_user, unsigned int length)
{
	raw3215_req *req;
	unsigned long flags;
	int ret, c;
	int count;
	ret = 0;
	while (length > 0) {
		s390irq_spin_lock_irqsave(raw->irq, flags);
		count = (length > RAW3215_BUFFER_SIZE) ?
					     RAW3215_BUFFER_SIZE : length;
		length -= count;
		while (RAW3215_BUFFER_SIZE - raw->count < count) {
			raw3215_try_io(raw);
			if (wait_cons_dev(raw->irq) != 0) {
				raw->count = 0;
			} 
		}
		req = raw3215_mk_write_req(raw);
		if (from_user) {
			while (1) {
				c = MIN(count,
					MIN(RAW3215_BUFFER_SIZE - raw->count,
					    RAW3215_BUFFER_SIZE - raw->head));
				if (c <= 0)
					break;
				c -= copy_from_user(raw->buffer + raw->head,
						    str, c);
				if (c == 0) {
					if (!ret)
						ret = -EFAULT;
					break;
				}
				ASCEBC(raw->buffer + raw->head, c);
				raw->head = (raw->head + c) &
					    (RAW3215_BUFFER_SIZE - 1);
				raw->count += c;
				str += c;
				count -= c;
				ret += c;
			}
		} else {
			while (1) {
				c = MIN(count,
					MIN(RAW3215_BUFFER_SIZE - raw->count,
					    RAW3215_BUFFER_SIZE - raw->head));
				if (c <= 0)
					break;
				memcpy(raw->buffer + raw->head, str, c);
				ASCEBC(raw->buffer + raw->head, c);
				raw->head = (raw->head + c) &
					    (RAW3215_BUFFER_SIZE - 1);
				raw->count += c;
				str += c;
				count -= c;
				ret += c;
			}
		}
		raw3215_mk_write_ccw(raw, req);
		raw->queued_write = req;
		raw3215_try_io(raw);
		s390irq_spin_unlock_irqrestore(raw->irq, flags);
	}
	return ret;
}
static int raw3215_write ( raw3215_info * raw , const char * str , int from_user , unsigned int length ) { raw3215_req * req ; unsigned long flags ; int ret , c ; int count ; ret = 0 ; while ( length > 0 ) { s390irq_spin_lock_irqsave ( raw -> irq , flags ) ; count = ( length > RAW3215_BUFFER_SIZE ) ? RAW3215_BUFFER_SIZE : length ; length -= count ; while ( RAW3215_BUFFER_SIZE - raw -> count < count ) { raw3215_try_io ( raw ) ; if ( wait_cons_dev ( raw -> irq ) != 0 ) { raw -> count = 0 ; } } req = raw3215_mk_write_req ( raw ) ; if ( from_user ) { while ( 1 ) { c = MIN ( count , MIN ( RAW3215_BUFFER_SIZE - raw -> count , RAW3215_BUFFER_SIZE - raw -> head ) ) ; if ( c <= 0 ) break ; c -= copy_from_user ( raw -> buffer + raw -> head , str , c ) ; if ( c == 0 ) { if ( ! ret ) ret = - EFAULT ; break ; } ASCEBC ( raw -> buffer + raw -> head , c ) ; raw -> head = ( raw -> head + c ) & ( RAW3215_BUFFER_SIZE - 1 ) ; raw -> count += c ; str += c ; count -= c ; ret += c ; } } else { while ( 1 ) { c = MIN ( count , MIN ( RAW3215_BUFFER_SIZE - raw -> count , RAW3215_BUFFER_SIZE - raw -> head ) ) ; if ( c <= 0 ) break ; memcpy ( raw -> buffer + raw -> head , str , c ) ; ASCEBC ( raw -> buffer + raw -> head , c ) ; raw -> head = ( raw -> head + c ) & ( RAW3215_BUFFER_SIZE - 1 ) ; raw -> count += c ; str += c ; count -= c ; ret += c ; } } raw3215_mk_write_ccw ( raw , req ) ; raw -> queued_write = req ; raw3215_try_io ( raw ) ; s390irq_spin_unlock_irqrestore ( raw -> irq , flags ) ; } return ret ; }
String write routine for 3215 devices
String write routine for 3215 devices
/* there might be a request pending */ /* that shouldn't happen */ /* copy string to output buffer and convert it to EBCDIC */ /* start or queue request */