Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / dev / serial / src / SS_Serial.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: SS_Serial.cc
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21
22#include "SS_Serial.h"
23#include <sys/socket.h>
24#include <sys/stat.h>
25#include <unistd.h>
26#include <fcntl.h>
27#include <errno.h>
28
29SS_Serial::SS_Serial( SS_AddressMap* map, SS_Paddr lo, SS_Paddr hi )/*{{{*/
30 :
31 line_status(LINE_TX_EMPTY | LINE_TX_HOLD),
32 buffer_len(0),
33 buffer_ptr(0),
34 serial_rd(0),
35 serial_wr(0)
36{
37 map->add(lo,hi,this,SS_AddressMap::REL,SS_Serial::access);
38}
39/*}}}*/
40SS_Serial::~SS_Serial()/*{{{*/
41{
42 if (serial_rd)
43 close(serial_rd);
44 if (serial_wr)
45 close(serial_wr);
46}
47/*}}}*/
48
49int SS_Serial::connect( const char* term )/*{{{*/
50{
51 char command[1024];
52 char hostname[256];
53 struct sockaddr_in server, client;
54 int client_size = sizeof(client);
55 int fd, on;
56
57 if ((fd = socket(AF_INET,SOCK_STREAM,0)) < 0)
58 return 1;
59
60 if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(uint8_t*)&on,sizeof(on)) < 0)
61 return 2;
62
63 server.sin_family = AF_INET;
64 server.sin_addr.s_addr = INADDR_ANY;
65 server.sin_port = htons(0);
66
67 while (bind(fd,(struct sockaddr*)&server,sizeof(server)) < 0)
68 if (errno != EAGAIN)
69 return 3;
70
71 int length = sizeof(server);
72 if (getsockname(fd,(struct sockaddr*)&server,&length) == -1)
73 return 4;
74
75 listen(fd,1);
76
77 gethostname(hostname,256);
78 sprintf(command,term,hostname,ntohs(server.sin_port));
79 system(command);
80
81 if ((serial_rd = accept(fd,(struct sockaddr*)&client,&client_size)) < 0)
82 return 5;
83
84 // Put the accepted socket in non-blocking mode
85
86 int fl = fcntl(serial_rd,F_GETFL);
87 if (fl < 0)
88 return 6;
89 if (fcntl(serial_rd,F_SETFL,fl|O_NONBLOCK) < 0)
90 return 6;
91
92 serial_wr = dup(serial_rd);
93
94 close(fd);
95
96 return 0;
97}
98/*}}}*/
99int SS_Serial::file_io( const char* input, const char* output )/*{{{*/
100{
101 mode_t mode = S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP;
102 int flag = O_WRONLY|O_CREAT|O_TRUNC;
103
104 if ((serial_wr = open(output,flag,mode)) < 0)
105 return serial_wr;
106
107 if ((serial_rd = open(input,O_RDONLY)) < 0)
108 return serial_rd;
109
110 return 0;
111}
112/*}}}*/
113
114void SS_Serial::access( void* obj, uint_t sid, SS_Access::Type type, SS_Paddr pa, uint_t size, uint64_t* data )/*{{{*/
115{
116 SS_Serial* self = (SS_Serial*)obj;
117
118 switch (type)
119 {
120 case SS_Access::LOAD:
121 if (size != 1)
122 {
123 *data = 0;
124 return;
125 }
126 switch(pa)
127 {
128 case INPUT:
129 if (self->buffer_len)
130 {
131 *data = self->buffer[self->buffer_ptr++];
132 self->buffer_len--;
133 }
134 else
135 {
136 *data = 0;
137 }
138 if (self->buffer_len == 0)
139 {
140 int n = read(self->serial_rd,self->buffer,BUFFER_SIZE);
141 self->buffer_len = (n > 0) ? n : 0;
142 self->buffer_ptr = 0;
143 }
144 if (self->buffer_len)
145 self->line_status |= LINE_DATA_READY;
146 else
147 self->line_status &= ~LINE_DATA_READY;
148 break;
149
150 case LINE_STATUS:
151 if (self->buffer_len == 0)
152 {
153 int n = read(self->serial_rd,self->buffer,BUFFER_SIZE);
154 self->buffer_len = (n > 0) ? n : 0;
155 self->buffer_ptr = 0;
156 }
157 if (self->buffer_len)
158 self->line_status |= LINE_DATA_READY;
159 *data = self->line_status;
160 break;
161
162 default:
163 *data = 0;
164 break;
165 }
166 break;
167
168 case SS_Access::STORE:
169 if (size != 1)
170 return;
171
172 switch (pa)
173 {
174 case OUTPUT:
175 {
176 char c = *data;
177 write(self->serial_wr,&c,1);
178 break;
179 }
180 case LINE_STATUS:
181 self->line_status = *data | LINE_TX_EMPTY | LINE_TX_HOLD;
182 break;
183
184 default:
185 break;
186 }
187 break;
188
189 default:
190 fprintf(stderr,"Serial: Unsupported access type\n");
191 }
192
193}
194/*}}}*/
195
196
197
198
199
200