/*
 * console device write
 */
static void viocons_write(struct console *co, const char *s, unsigned count)
{
	int index;
	int begin;
	struct port_info *pi;

	static const char cr = '\r';

	/*
	 * Check port data first because the target LP might be valid but
	 * simply not active, in which case we want to hvlog the output.
	 */
	pi = get_port_data(NULL);
	if (pi == NULL) {
		hvlog("\n\rviocons_write: unable to get port data.");
		return;
	}

	hvlogOutput(s, count);

	if (!viopath_isactive(pi->lp)) {
		/*
		 * This is a VERY noisy trace message in the case where the
		 * path manager is not active or in the case where this
		 * function is called prior to viocons initialization.  It is
		 * being commented out for the sake of a clear trace buffer.
		 */
#if 0
		 hvlog("\n\rviocons_write: path not active to lp %d", pi->lp);
#endif
		return;
	}

	/* 
	 * Any newline character found will cause a
	 * carriage return character to be emitted as well. 
	 */
	begin = 0;
	for (index = 0; index < count; index++) {
		if (s[index] == '\n') {
			/* 
			 * Newline found. Print everything up to and 
			 * including the newline
			 */
			internal_write(pi, &s[begin], index - begin + 1,
					NULL);
			begin = index + 1;
			/* Emit a carriage return as well */
			internal_write(pi, &cr, 1, NULL);
		}
	}

	/* If any characters left to write, write them now */
	if ((index - begin) > 0)
		internal_write(pi, &s[begin], index - begin, NULL);
}
Пример #2
0
void Connection::on_ready() {
  if (state_ == CONNECTION_STATE_CONNECTED && listener_->event_types() != 0) {
    set_state(CONNECTION_STATE_REGISTERING_EVENTS);
    internal_write(new StartupHandler(this, new RegisterRequest(listener_->event_types())));
    return;
  }

  if (keyspace_.empty()) {
    notify_ready();
  } else {
    internal_write(new StartupHandler(this, new QueryRequest("USE \"" + keyspace_ + "\"")));
  }
}
Пример #3
0
void eeprom_base_device::erase(offs_t address)
{
	if (!ready())
		logerror("EEPROM: Erase performed before previous operation completed!");
	internal_write(address, ~0);
	m_completion_time = machine().time() + m_operation_time[ERASE_TIME];
}
Пример #4
0
    // ask the general-loader to use this when naming its output
    void GeneralWriter :: setRemotePath ( const std :: string & remote_db )
    {
        stream_state new_state = uninitialized;

        switch ( state )
        {
        case header_written:
            new_state = remote_name_sent;
            break;
        case schema_sent:
            new_state = remote_name_and_schema_sent;
            break;
        case software_name_sent:
            new_state = remote_name_and_software_name_sent;
            break;
        case schema_and_software_name_sent:
            new_state = remote_name_schema_and_software_name_sent;
            break;
        default:
            throw "state violation setting remote path";
        }

        size_t str_size = remote_db . size ();
        if ( str_size > 0x10000 )
            throw "remote path too long";

        gwp_1string_evt_U16 hdr;
        init ( hdr, 0, evt_remote_path2 );
        set_size ( hdr, str_size );
        write_event ( & hdr . dad, sizeof hdr );
        internal_write ( remote_db . data (), str_size );

        state = new_state;
    }
Пример #5
0
bool Connection::write(Handler* handler, bool flush_immediately) {
  bool result = internal_write(handler, flush_immediately);
  if (result) {
    restart_heartbeat_timer();
  }
  return result;
}
Пример #6
0
void Connection::close()
{
    if(!m_connected && !m_connecting)
        return;

    // flush send data before disconnecting on clean connections
    if(m_connected && !m_error && m_outputStream)
        internal_write();

    m_connecting = false;
    m_connected = false;
    m_connectCallback = nullptr;
    m_errorCallback = nullptr;
    m_recvCallback = nullptr;

    m_resolver.cancel();
    m_readTimer.cancel();
    m_writeTimer.cancel();
    m_delayedWriteTimer.cancel();

    if(m_socket.is_open()) {
        boost::system::error_code ec;
        m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
        m_socket.close();
    }
}
Пример #7
0
void eeprom_base_device::write(offs_t address, UINT32 data)
{
	if (!ready())
		logerror("EEPROM: Write performed before previous operation completed!");
	internal_write(address, data);
	m_completion_time = machine().time() + m_operation_time[WRITE_TIME];
}
Пример #8
0
    void GeneralWriter :: logMsg ( const std :: string &msg )
    {
        switch ( state )
        {
        case header_written:
        case remote_name_sent:
        case schema_sent:
        case software_name_sent:
        case remote_name_and_schema_sent:
        case remote_name_and_software_name_sent:
        case schema_and_software_name_sent:
        case remote_name_schema_and_software_name_sent:
        case have_table:
        case have_column:
        case opened:
            break;
        default:
            return;
        }

        size_t str_size = msg . size ();
        if ( str_size == 0 )
            return;

        if ( str_size > 0x10000 )
            str_size = 0x10000;

        gwp_1string_evt_U16 hdr;
        init ( hdr, 0, evt_logmsg );

        set_size ( hdr, str_size );
        write_event ( & hdr . dad, sizeof hdr );
        internal_write ( msg . data (), str_size );
    }
Пример #9
0
void eeprom_base_device::write_all(UINT32 data)
{
	if (!ready())
		logerror("EEPROM: Write all performed before previous operation completed!");
	for (offs_t address = 0; address < (1 << m_address_bits); address++)
		internal_write(address, internal_read(address) & data);
	m_completion_time = machine().time() + m_operation_time[WRITE_ALL_TIME];
}
Пример #10
0
void eeprom_base_device::erase_all()
{
	if (!ready())
		logerror("EEPROM: Erase all performed before previous operation completed!");
	for (offs_t address = 0; address < (1 << m_address_bits); address++)
		internal_write(address, ~0);
	m_completion_time = machine().time() + m_operation_time[ERASE_ALL_TIME];
}
Пример #11
0
    void GeneralWriter :: writeHeader ()
    {
        :: gw_header_v1 hdr;
        init ( hdr );
        internal_write ( & hdr, sizeof hdr );
        state = header_written;

    }
Пример #12
0
void Connection::on_supported(ResponseMessage* response) {
  SupportedResponse* supported =
      static_cast<SupportedResponse*>(response->response_body().get());

  // TODO(mstump) do something with the supported info
  (void)supported;

  internal_write(new StartupHandler(this, new StartupRequest()));
}
Пример #13
0
void Connection::send_credentials(const std::string& class_name) {
  ScopedPtr<V1Authenticator> v1_auth(config_.auth_provider()->new_authenticator_v1(host_, class_name));
  if (v1_auth) {
    V1Authenticator::Credentials credentials;
    v1_auth->get_credentials(&credentials);
    internal_write(new StartupHandler(this, new CredentialsRequest(credentials)));
  } else {
    send_initial_auth_response(class_name);
  }
}
Пример #14
0
void Connection::onCanWrite(const boost::system::error_code& error)
{
    m_delayedWriteTimer.cancel();

    if(error == asio::error::operation_aborted)
        return;

    if(m_connected)
        internal_write();
}
Пример #15
0
    int GeneralWriter :: addTable ( const std :: string &table_name )
    {        
        stream_state new_state = uninitialized;

        switch ( state )
        {
        case schema_sent:
        case remote_name_and_schema_sent:
        case remote_name_schema_and_software_name_sent:
            new_state = have_table;
            break;
        case have_table:
        case have_column:
            new_state = state;
            break;
        default:
            throw "state violation adding table";
        }

        // create a pair between the outer db id ( 0 ) and this table name
        // this pair will act as an unique key of tables, whereas table_name
        // itself can be repeated if multiple databases are in use
        int_dbtbl tbl ( 0, table_name );

        // prediction this is the index
        int id = ( int ) tables.size() + 1;
        if ( id > 256 )
            throw "maximum number of tables exceeded";

        // make sure we never record a table name twice under the same db
        std :: pair < std :: map < int_dbtbl, int > :: iterator, bool > result = 
            table_name_idx.insert ( std :: pair < int_dbtbl, int > ( tbl, id ) );
        
        // if first time
        if ( result.second )
        {
            tables.push_back ( tbl );

            size_t str_size = table_name . size ();
            if ( str_size > 0x10000 )
                throw "maximum table name length exceeded";

            gwp_1string_evt_U16 hdr;
            init ( hdr, id, evt_new_table2 );
            set_size ( hdr, str_size );
            write_event ( & hdr . dad, sizeof hdr );
            internal_write ( table_name.data (), str_size );

            state = new_state;
        }
        
        // 1 based table id
        return result.first->second;
    }
Пример #16
0
void Connection::on_auth_challenge(const AuthResponseRequest* request,
                                   const std::string& token) {
  std::string response;
  if (!request->auth()->evaluate_challenge(token, &response)) {
    notify_error("Failed evaluating challenge token: " + request->auth()->error(), CONNECTION_ERROR_AUTH);
    return;
  }
  AuthResponseRequest* auth_response = new AuthResponseRequest(response,
                                                               request->auth());
  internal_write(new StartupHandler(this, auth_response));
}
Пример #17
0
    void GeneralWriter :: columnDefault ( int stream_id, uint32_t elem_bits, const void *data, uint32_t elem_count )
    {
        switch ( state )
        {
        case opened:
            break;
        default:
            throw "state violation setting column default";
        }

        if ( stream_id < 0 )
            throw "Stream_id is not valid";
        if ( stream_id > ( int ) streams.size () )
            throw "Stream_id is out of bounds";

        if ( elem_bits == 0 )
            return;
        
        if ( data == 0 && elem_count != 0 )
            throw "Invalid data ptr";

        if ( elem_bits != streams [ stream_id - 1 ] . elem_bits )
            throw "Invalid elem_bits";

        size_t num_bytes = ( ( size_t ) elem_bits * elem_count + 7 ) / 8;
        if ( num_bytes == 0 )
        {
            gwp_evt_hdr_v1 eh;
            init ( eh, stream_id, evt_empty_default );
            write_event ( & eh, sizeof eh );
        }
        else
        {
            if ( num_bytes <= 256 )
            {
                gwp_data_evt chunk;
                init ( chunk, stream_id, evt_cell_default );
                set_size ( chunk, num_bytes );
                write_event ( & chunk . dad, sizeof chunk );
            }
            else if ( num_bytes <= 0x10000 )
            {
                gwp_data_evt_U16 chunk;
                init ( chunk, stream_id, evt_cell_default2 );
                set_size ( chunk, num_bytes );
                write_event ( & chunk . dad, sizeof chunk );
            }
            else
            {
                throw "default cell-data exceeds maximum";
            }
            internal_write ( data, num_bytes );
        }
    }
Пример #18
0
    void GeneralWriter :: setSoftwareName ( const std :: string & name,
                                            const std :: string & version )
    {
        stream_state new_state = uninitialized;

        switch ( state )
        {
        case header_written:
            new_state = software_name_sent;
            break;
        case remote_name_sent:
            new_state = remote_name_and_software_name_sent;
            break;
        case schema_sent:
            new_state = schema_and_software_name_sent;
            break;
        case remote_name_and_schema_sent:
            new_state = remote_name_schema_and_software_name_sent;
            break;
        default:
            throw "state violation using schema";
        }

        size_t str1_size = name . size ();
        if ( str1_size > 0x100 )
            throw "name too long";

        size_t str2_size = version . size ();
        if ( str2_size > 0x100 )
            throw "version too long";

        gwp_2string_evt_v1 hdr;
        init ( hdr, 0, evt_software_name );
        set_size1 ( hdr, str1_size );
        set_size2 ( hdr, str2_size );
        write_event ( & hdr . dad, sizeof hdr );
        internal_write ( name . data (), str1_size );
        internal_write ( version . data (), str2_size );

        state = new_state;        
    }
Пример #19
0
    // tell the general-loader to use this pre-defined schema
    void GeneralWriter :: useSchema ( const std :: string & schema_file_name,
                                      const std :: string & schema_db_spec )
    {
        stream_state new_state = uninitialized;

        switch ( state )
        {
        case header_written:
            new_state = schema_sent;
            break;
        case remote_name_sent:
            new_state = remote_name_and_schema_sent;
            break;
        case software_name_sent:
            new_state = schema_and_software_name_sent;
            break;
        case remote_name_and_software_name_sent:
            new_state = remote_name_schema_and_software_name_sent;
            break;
        default:
            throw "state violation using schema";
        }

        size_t str1_size = schema_file_name . size ();
        if ( str1_size > 0x10000 )
            throw "schema path too long";

        size_t str2_size = schema_db_spec . size ();
        if ( str2_size > 0x10000 )
            throw "schema spec too long";

        gwp_2string_evt_U16 hdr;
        init ( hdr, 0, evt_use_schema2 );
        set_size1 ( hdr, str1_size );
        set_size2 ( hdr, str2_size );
        write_event ( & hdr . dad, sizeof hdr );
        internal_write ( schema_file_name . data (), str1_size );
        internal_write ( schema_db_spec . data (), str2_size );

        state = new_state;
    }
Пример #20
0
    void GeneralWriter :: setTblMetadataNode ( int obj_id,
                                            const std :: string & node_path,
                                            const std :: string & value )
    {
        if ( obj_id <= 0 || ( size_t ) obj_id > tables.size () )
            throw "Invalid table id";

        size_t str1_size = node_path . size ();
        if ( str1_size > STRING_LIMIT_16 )
            throw "tbl_path too long";

        size_t str2_size = value . size ();
        if ( str2_size > STRING_LIMIT_16 )
            throw "value too long";

        if ( str1_size <= STRING_LIMIT_8 && str2_size <= STRING_LIMIT_8 )
        {
            // use 8-bit sizes
            gwp_2string_evt_v1 hdr;
            init ( hdr, obj_id, evt_tbl_metadata_node );
            set_size1 ( hdr, str1_size );
            set_size2 ( hdr, str2_size );
            write_event ( & hdr . dad, sizeof hdr );
        }
        else
        {
            // use 16-bit sizes
            gwp_2string_evt_U16_v1 hdr;
            init ( hdr, obj_id, evt_tbl_metadata_node2 );
            set_size1 ( hdr, str1_size );
            set_size2 ( hdr, str2_size );
            write_event ( & hdr . dad, sizeof hdr );
        }

        internal_write ( node_path . data (), str1_size );
        internal_write ( value . data (), str2_size );

    }
Пример #21
0
void Connection::send_initial_auth_response(const std::string& class_name) {
  SharedRefPtr<Authenticator> auth(config_.auth_provider()->new_authenticator(host_, class_name));
  if (!auth) {
    notify_error("Authentication required but no auth provider set", CONNECTION_ERROR_AUTH);
  } else {
    std::string response;
    if (!auth->initial_response(&response)) {
      notify_error("Failed creating initial response token: " + auth->error(), CONNECTION_ERROR_AUTH);
      return;
    }
    AuthResponseRequest* auth_response = new AuthResponseRequest(response, auth);
    internal_write(new StartupHandler(this, auth_response));
  }
}
Пример #22
0
void eeprom_base_device::nvram_default()
{
	uint32_t eeprom_length = 1 << m_address_bits;
	uint32_t eeprom_bytes = eeprom_length * m_data_bits / 8;

	// initialize to the default value
	uint32_t default_value = m_default_value_set ? m_default_value : ~0;
	for (offs_t offs = 0; offs < eeprom_length; offs++)
		internal_write(offs, default_value);

	// handle hard-coded data from the driver
	if (m_default_data.u8 != nullptr)
	{
		osd_printf_verbose("Warning: Driver-specific EEPROM defaults are going away soon.\n");
		for (offs_t offs = 0; offs < m_default_data_size; offs++)
		{
			if (m_data_bits == 8)
				internal_write(offs, m_default_data.u8[offs]);
			else
				internal_write(offs, m_default_data.u16[offs]);
		}
	}

	// populate from a memory region if present
	if (m_region.found())
	{
		if (m_region->bytes() != eeprom_bytes)
			fatalerror("eeprom region '%s' wrong size (expected size = 0x%X)\n", tag(), eeprom_bytes);
		if (m_data_bits == 8 && m_region->bytewidth() != 1)
			fatalerror("eeprom region '%s' needs to be an 8-bit region\n", tag());
		if (m_data_bits == 16 && (m_region->bytewidth() != 2 || m_region->endianness() != ENDIANNESS_BIG))
			fatalerror("eeprom region '%s' needs to be a 16-bit big-endian region\n", tag());
		osd_printf_verbose("Loading data from EEPROM region '%s'\n", tag());

		memcpy(&m_data[0], m_region->base(), eeprom_bytes);
	}
}
Пример #23
0
/*
 * TTY put_char method
 */
static void viotty_put_char(struct tty_struct *tty, unsigned char ch)
{
	struct port_info *pi;

	pi = get_port_data(tty);
	if (pi == NULL)
		return;

	/* This will append '\r' as well if the char is '\n' */
	if (viochar_is_console(pi))
		hvlogOutput(&ch, 1);

	if (viopath_isactive(pi->lp))
		internal_write(pi, &ch, 1, NULL);
}
Пример #24
0
    void GeneralWriter :: write_event ( const gwp_evt_hdr * e, size_t evt_size )
    {
#if PROGRESS_EVENT
        uint64_t ec = evt_count;
        if ( ( ec % 10000 ) == 0 )
        {
            if ( ( ec % 500000 ) == 0 )
                std :: cerr << "\n%  [" << std :: setw ( 12 ) << byte_count << "] " << std :: setw ( 9 ) << ec + 1 << ' ';
            std :: cerr << '.';
        }
#endif
        ++ evt_count;

        assert ( evt ( * e ) != evt_bad_event );
        assert ( evt ( * e ) <  evt_max_id );

        internal_write ( e, evt_size );
    }
Пример #25
0
    void GeneralWriter :: progMsg ( const std :: string & name, uint32_t version,
        uint64_t done, uint64_t total )
    {
        switch ( state )
        {
        case opened:
            break;
        default:
            return;
        }
        
        size_t str_size = name . size ();
        if ( str_size == 0 )
            throw "zero-length app-name";
        if ( str_size > 0x100 )
            str_size = 0x100;

        // timestamp
        time_t timestamp = time ( NULL );

        if ( total == 0 )
            throw "illegal total value: would divide by zero";
        if ( done > total )
            throw "illegal done value: greater than total";
        
        // calculate percentage done
        double fpercent = ( double ) done / total;
        assert ( fpercent >= 0.0 && fpercent <= 100.0 );
        uint8_t percent = ( uint8_t ) ( fpercent * 100 );

        gwp_status_evt_v1 hdr;
        init ( hdr, 0, evt_progmsg );
        set_pid ( hdr, pid );
        set_version ( hdr, version );
        set_timestamp ( hdr, ( uint32_t ) timestamp );
        set_size ( hdr, str_size );
        set_percent ( hdr, percent );

        write_event ( &hdr . dad, sizeof hdr );
        internal_write ( name.data (), str_size );
    }
Пример #26
0
    void GeneralWriter :: logError ( const std :: string & msg )
    {
        switch ( state )
        {
        case header_written:
        case remote_name_sent:
        case schema_sent:
        case software_name_sent:
        case remote_name_and_schema_sent:
        case remote_name_and_software_name_sent:
        case schema_and_software_name_sent:
        case remote_name_schema_and_software_name_sent:
        case have_table:
        case have_column:
        case opened:
        case error:
            break;
        default:
            return;
        }

        gwp_1string_evt_U16 hdr;
        init ( hdr, 0, evt_errmsg2 );

        const char * msg_data = msg . data ();
        size_t str_size = msg . size ();
        if ( str_size == 0 )
        {
            msg_data = "ERROR: (NO MSG)";
            str_size = strlen ( msg_data );
        }
        else if ( str_size > 0x10000 )
            str_size = 0x10000;

        set_size ( hdr, str_size );
        write_event ( & hdr . dad, sizeof hdr );
        internal_write ( msg_data, str_size );
    }
Пример #27
0
    void GeneralWriter :: write ( int stream_id, uint32_t elem_bits, const void *data, uint32_t elem_count )
    {
        switch ( state )
        {
        case opened:
            break;
        default:
            throw "state violation writing column data";
        }

        if ( stream_id < 0 )
            throw "Stream_id is not valid";
        if ( stream_id > ( int ) streams.size () )
            throw "Stream_id is out of bounds";

        if ( elem_bits == 0 || elem_count == 0 )
            return;
        
        if ( data == 0 )
            throw "Invalid data ptr";

        const int_stream & s = streams [ stream_id - 1 ];

        if ( elem_bits != s . elem_bits )
            throw "Invalid elem_bits";

        bool compact_int = ( s . flag_bits & 1 ) != 0;
        
        const uint8_t * dp = ( const uint8_t * ) data;

        if ( compact_int )
        {
            uint32_t elem;
            encode_result rslt;
            encode_result ( * encode ) ( uint8_t * buffer, const void * data, uint32_t first, uint32_t elem_count );

            switch ( elem_bits )
            {
            case 16:
                encode = encode_buffer < uint16_t >;
                break;
            case 32:
                encode = encode_buffer < uint32_t >;
                break;
            case 64:
                encode = encode_buffer < uint64_t >;
                break;
            default:
                throw "INTERNAL ERROR: corrupt element bits";
            }

            for ( elem = 0; elem < elem_count; elem = rslt . num_elems )
            {
                rslt = ( * encode ) ( packing_buffer, data, elem, elem_count );
                if ( rslt . num_bytes <= 256 )
                {
                    assert ( rslt . num_bytes != 0 );
                    gwp_data_evt chunk;
                    init ( chunk, stream_id, evt_cell_data );
                    set_size ( chunk, rslt . num_bytes );
                    write_event ( & chunk . dad, sizeof chunk );
                }
                else
                {
                    gwp_data_evt_U16 chunk;
                    init ( chunk, stream_id, evt_cell_data2 );
                    set_size ( chunk, rslt . num_bytes );
                    write_event ( & chunk . dad, sizeof chunk );
                }
                internal_write ( packing_buffer, rslt . num_bytes );
            }
        }
        else
        {
            size_t num_bytes = ( ( size_t ) elem_bits * elem_count + 7 ) / 8;

            while ( num_bytes >= 0x10000 )
            {
                gwp_data_evt_U16 chunk;
                init ( chunk, stream_id, evt_cell_data2 );
                set_size ( chunk, 0x10000 );
                write_event ( & chunk . dad, sizeof chunk );
                internal_write ( dp, 0x10000 );
                num_bytes -= 0x10000;
                dp += 0x10000;
            }

            if ( num_bytes <= 256 )
            {
                gwp_data_evt chunk;
                init ( chunk, stream_id, evt_cell_data );
                set_size ( chunk, num_bytes );
                write_event ( & chunk . dad, sizeof chunk );
            }
            else
            {
                gwp_data_evt_U16 chunk;
                init ( chunk, stream_id, evt_cell_data2 );
                set_size ( chunk, num_bytes );
                write_event ( & chunk . dad, sizeof chunk );
            }
            
            internal_write ( data, num_bytes );
        }
    }
Пример #28
0
void Connection::on_connected() {
  internal_write(new StartupHandler(this, new OptionsRequest()));
}
Пример #29
0
/*
 * TTY Write method
 */
static int viotty_write(struct tty_struct *tty, int from_user,
			const unsigned char *buf, int count)
{
	int ret;
	int total = 0;
	struct port_info *pi;

	pi = get_port_data(tty);
	if (pi == NULL) {
		hvlog("\n\rviotty_write: no port data.");
		return -ENODEV;
	}

	if (viochar_is_console(pi))
		hvlogOutput(buf, count);

	/*
	 * If the path to this LP is closed, don't bother doing anything more.
	 * just dump the data on the floor and return count.  For some reason
	 * some user level programs will attempt to probe available tty's and
	 * they'll attempt a viotty_write on an invalid port which maps to an
	 * invalid target lp.  If this is the case then ignore the
	 * viotty_write call and, since the viopath isn't active to this
	 * partition, return count.
	 */
	if (!viopath_isactive(pi->lp)) {
		/* Noisy trace.  Commented unless needed. */
#if 0
		 hvlog("\n\rviotty_write: viopath NOT active for lp %d.",pi->lp);
#endif
		return count;
	}

	/*
	 * If the viotty_write is invoked from user space we want to do the
	 * copy_from_user() into an event buffer from the cfu buffer before
	 * internal_write() is called because internal_write may need to buffer
	 * data which will need to grab a spin_lock and we shouldn't
	 * copy_from_user() while holding a spin_lock.  Should internal_write()
	 * not need to buffer data then it'll just use the event we created here
	 * rather than checking one out from vio_get_event_buffer().
	 */
	if (from_user) {
		struct viocharlpevent *viochar;
		int curlen;
		const char *curbuf = buf;

		viochar = viocons_get_cfu_buffer();
		if (viochar == NULL)
			return -EAGAIN;
		initDataEvent(viochar, pi->lp);
		while (count > 0) {
			if (count > VIOCHAR_MAX_DATA)
				curlen = VIOCHAR_MAX_DATA;
			else
				curlen = count;
			viochar->len = curlen;
			ret = copy_from_user(viochar->data, curbuf, curlen);
			if (ret)
				break;
			ret = internal_write(pi, viochar->data,
					viochar->len, viochar);
			total += ret;
			if (ret != curlen)
				break;
			count -= curlen;
			curbuf += curlen;
		}
		viocons_free_cfu_buffer(viochar);
	} else
		total = internal_write(pi, buf, count, NULL);
	return total;
}
Пример #30
0
void write_outchan(out_chan *chan, void *buffer, int size)
{
  push_next_size(&chan->core, size);
  internal_write(&chan->core, buffer, size);
}