Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / dev / serial / src / SS_Serial.cc
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: SS_Serial.cc
// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
//
// The above named program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License version 2 as published by the Free Software Foundation.
//
// The above named program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
// ========== Copyright Header End ============================================
#include "SS_Serial.h"
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
SS_Serial::SS_Serial( SS_AddressMap* map, SS_Paddr lo, SS_Paddr hi )/*{{{*/
:
line_status(LINE_TX_EMPTY | LINE_TX_HOLD),
buffer_len(0),
buffer_ptr(0),
serial_rd(0),
serial_wr(0)
{
map->add(lo,hi,this,SS_AddressMap::REL,SS_Serial::access);
}
/*}}}*/
SS_Serial::~SS_Serial()/*{{{*/
{
if (serial_rd)
close(serial_rd);
if (serial_wr)
close(serial_wr);
}
/*}}}*/
int SS_Serial::connect( const char* term )/*{{{*/
{
char command[1024];
char hostname[256];
struct sockaddr_in server, client;
int client_size = sizeof(client);
int fd, on;
if ((fd = socket(AF_INET,SOCK_STREAM,0)) < 0)
return 1;
if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(uint8_t*)&on,sizeof(on)) < 0)
return 2;
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(0);
while (bind(fd,(struct sockaddr*)&server,sizeof(server)) < 0)
if (errno != EAGAIN)
return 3;
int length = sizeof(server);
if (getsockname(fd,(struct sockaddr*)&server,&length) == -1)
return 4;
listen(fd,1);
gethostname(hostname,256);
sprintf(command,term,hostname,ntohs(server.sin_port));
system(command);
if ((serial_rd = accept(fd,(struct sockaddr*)&client,&client_size)) < 0)
return 5;
// Put the accepted socket in non-blocking mode
int fl = fcntl(serial_rd,F_GETFL);
if (fl < 0)
return 6;
if (fcntl(serial_rd,F_SETFL,fl|O_NONBLOCK) < 0)
return 6;
serial_wr = dup(serial_rd);
close(fd);
return 0;
}
/*}}}*/
int SS_Serial::file_io( const char* input, const char* output )/*{{{*/
{
mode_t mode = S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP;
int flag = O_WRONLY|O_CREAT|O_TRUNC;
if ((serial_wr = open(output,flag,mode)) < 0)
return serial_wr;
if ((serial_rd = open(input,O_RDONLY)) < 0)
return serial_rd;
return 0;
}
/*}}}*/
void SS_Serial::access( void* obj, uint_t sid, SS_Access::Type type, SS_Paddr pa, uint_t size, uint64_t* data )/*{{{*/
{
SS_Serial* self = (SS_Serial*)obj;
switch (type)
{
case SS_Access::LOAD:
if (size != 1)
{
*data = 0;
return;
}
switch(pa)
{
case INPUT:
if (self->buffer_len)
{
*data = self->buffer[self->buffer_ptr++];
self->buffer_len--;
}
else
{
*data = 0;
}
if (self->buffer_len == 0)
{
int n = read(self->serial_rd,self->buffer,BUFFER_SIZE);
self->buffer_len = (n > 0) ? n : 0;
self->buffer_ptr = 0;
}
if (self->buffer_len)
self->line_status |= LINE_DATA_READY;
else
self->line_status &= ~LINE_DATA_READY;
break;
case LINE_STATUS:
if (self->buffer_len == 0)
{
int n = read(self->serial_rd,self->buffer,BUFFER_SIZE);
self->buffer_len = (n > 0) ? n : 0;
self->buffer_ptr = 0;
}
if (self->buffer_len)
self->line_status |= LINE_DATA_READY;
*data = self->line_status;
break;
default:
*data = 0;
break;
}
break;
case SS_Access::STORE:
if (size != 1)
return;
switch (pa)
{
case OUTPUT:
{
char c = *data;
write(self->serial_wr,&c,1);
break;
}
case LINE_STATUS:
self->line_status = *data | LINE_TX_EMPTY | LINE_TX_HOLD;
break;
default:
break;
}
break;
default:
fprintf(stderr,"Serial: Unsupported access type\n");
}
}
/*}}}*/