/[dynamips]/upstream/dynamips-0.2.5/dev_sb1_io.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/dynamips-0.2.5/dev_sb1_io.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Sat Oct 6 16:01:44 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 8613 byte(s)
import 0.2.5 from upstream

1 /*
2 * Cisco 7200 (Predator) simulation platform.
3 * Copyright (c) 2005 Christophe Fillot (cf@utc.fr)
4 *
5 * SB-1 I/O devices.
6 *
7 * XXX: just for tests!
8 */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <sys/types.h>
15 #include <termios.h>
16 #include <fcntl.h>
17 #include <pthread.h>
18
19 #include "utils.h"
20 #include "ptask.h"
21 #include "mips64.h"
22 #include "dynamips.h"
23 #include "memory.h"
24 #include "device.h"
25 #include "dev_c7200.h"
26
27 #define DEBUG_UNKNOWN 1
28
29 /* DUART Status Register */
30 #define DUART_SR_RX_RDY 0x01 /* Receiver ready */
31 #define DUART_SR_RX_FFUL 0x02 /* Receive FIFO full */
32 #define DUART_SR_TX_RDY 0x04 /* Transmitter ready */
33 #define DUART_SR_TX_EMT 0x08 /* Transmitter empty */
34
35 /* DUART Interrupt Status Register */
36 #define DUART_ISR_TXA 0x01 /* Channel A Transmitter Ready */
37 #define DUART_ISR_RXA 0x02 /* Channel A Receiver Ready */
38 #define DUART_ISR_TXB 0x10 /* Channel B Transmitter Ready */
39 #define DUART_ISR_RXB 0x20 /* Channel B Receiver Ready */
40
41 /* DUART Interrupt Mask Register */
42 #define DUART_IMR_TXA 0x01 /* Channel A Transmitter Ready */
43 #define DUART_IMR_RXA 0x02 /* Channel A Receiver Ready */
44 #define DUART_IMR_TXB 0x10 /* Channel B Transmitter Ready */
45 #define DUART_IMR_RXB 0x20 /* Channel B Receiver Ready */
46
47 /* SB-1 DUART channel */
48 struct sb1_duart_channel {
49 m_uint8_t mode;
50 m_uint8_t cmd;
51 };
52
53 /* SB-1 I/O private data */
54 struct sb1_io_data {
55 vm_obj_t vm_obj;
56 struct vdevice dev;
57
58 /* Virtual machine */
59 vm_instance_t *vm;
60
61 /* DUART info */
62 u_int duart_irq,duart_irq_seq;
63 m_uint8_t duart_isr,duart_imr;
64 struct sb1_duart_channel duart_chan[2];
65
66 /* Periodic task to trigger dummy DUART IRQ */
67 ptask_id_t duart_irq_tid;
68 };
69
70 /* Console port input */
71 static void tty_con_input(vtty_t *vtty)
72 {
73 struct sb1_io_data *d = vtty->priv_data;
74
75 if (d->duart_imr & DUART_IMR_RXA) {
76 d->duart_isr |= DUART_ISR_RXA;
77 vm_set_irq(d->vm,d->duart_irq);
78 }
79 }
80
81 /* AUX port input */
82 static void tty_aux_input(vtty_t *vtty)
83 {
84 struct sb1_io_data *d = vtty->priv_data;
85
86 if (d->duart_imr & DUART_IMR_RXB) {
87 d->duart_isr |= DUART_ISR_RXB;
88 vm_set_irq(d->vm,d->duart_irq);
89 }
90 }
91
92 /* IRQ trickery for Console and AUX ports */
93 static int tty_trigger_dummy_irq(struct sb1_io_data *d,void *arg)
94 {
95 u_int mask;
96
97 d->duart_irq_seq++;
98
99 if (d->duart_irq_seq == 2) {
100 mask = DUART_IMR_TXA|DUART_IMR_TXB;
101 if (d->duart_imr & mask) {
102 d->duart_isr |= DUART_ISR_TXA|DUART_ISR_TXB;
103 vm_set_irq(d->vm,d->duart_irq);
104 }
105
106 d->duart_irq_seq = 0;
107 }
108
109 return(0);
110 }
111
112 /*
113 * dev_sb1_io_access()
114 */
115 void *dev_sb1_io_access(cpu_mips_t *cpu,struct vdevice *dev,
116 m_uint32_t offset,u_int op_size,u_int op_type,
117 m_uint64_t *data)
118 {
119 struct sb1_io_data *d = dev->priv_data;
120 u_char odata;
121
122 if (op_type == MTS_READ)
123 *data = 0;
124
125 switch(offset) {
126 case 0x390: /* DUART Interrupt Status Register */
127 if (op_type == MTS_READ)
128 *data = d->duart_isr;
129 break;
130
131 case 0x320: /* DUART Channel A Only Interrupt Status Register */
132 if (op_type == MTS_READ)
133 *data = d->duart_isr & 0x0F;
134 break;
135
136 case 0x340: /* DUART Channel B Only Interrupt Status Register */
137 if (op_type == MTS_READ)
138 *data = (d->duart_isr >> 4) & 0x0F;
139 break;
140
141 case 0x3a0: /* DUART Interrupt Mask Register */
142 if (op_type == MTS_READ)
143 *data = d->duart_imr;
144 else
145 d->duart_imr = *data;
146 break;
147
148 case 0x330: /* DUART Channel A Only Interrupt Mask Register */
149 if (op_type == MTS_READ) {
150 *data = d->duart_imr & 0x0F;
151 } else {
152 d->duart_imr &= ~0x0F;
153 d->duart_imr |= *data & 0x0F;
154 }
155 break;
156
157 case 0x350: /* DUART Channel B Only Interrupt Mask Register */
158 if (op_type == MTS_READ) {
159 *data = (d->duart_imr >> 4) & 0x0F;
160 } else {
161 d->duart_imr &= ~0xF0;
162 d->duart_imr |= (*data & 0x0F) << 4;
163 }
164 break;
165
166 case 0x100: /* DUART Mode (Channel A) */
167 if (op_type == MTS_READ)
168 d->duart_chan[0].mode = *data;
169 else
170 *data = d->duart_chan[0].mode;
171 break;
172
173 case 0x200: /* DUART Mode (Channel B) */
174 if (op_type == MTS_READ)
175 d->duart_chan[1].mode = *data;
176 else
177 *data = d->duart_chan[1].mode;
178 break;
179
180 case 0x150: /* DUART Command Register (Channel A) */
181 if (op_type == MTS_READ)
182 d->duart_chan[0].cmd = *data;
183 else
184 *data = d->duart_chan[0].cmd;
185 break;
186
187 case 0x250: /* DUART Command Register (Channel B) */
188 if (op_type == MTS_READ)
189 d->duart_chan[1].cmd = *data;
190 else
191 *data = d->duart_chan[1].cmd;
192 break;
193
194 case 0x120: /* DUART Status Register (Channel A) */
195 if (op_type == MTS_READ) {
196 odata = 0;
197
198 if (vtty_is_char_avail(d->vm->vtty_con))
199 odata |= DUART_SR_RX_RDY;
200
201 odata |= DUART_SR_TX_RDY;
202
203 vm_clear_irq(d->vm,d->duart_irq);
204 *data = odata;
205 }
206 break;
207
208 case 0x220: /* DUART Status Register (Channel B) */
209 if (op_type == MTS_READ) {
210 odata = 0;
211
212 if (vtty_is_char_avail(d->vm->vtty_aux))
213 odata |= DUART_SR_RX_RDY;
214
215 odata |= DUART_SR_TX_RDY;
216
217 //vm_clear_irq(d->vm,d->duart_irq);
218 *data = odata;
219 }
220 break;
221
222 case 0x160: /* DUART Received Data Register (Channel A) */
223 if (op_type == MTS_READ) {
224 *data = vtty_get_char(d->vm->vtty_con);
225 d->duart_isr &= ~DUART_ISR_RXA;
226 }
227 break;
228
229 case 0x260: /* DUART Received Data Register (Channel B) */
230 if (op_type == MTS_READ) {
231 *data = vtty_get_char(d->vm->vtty_aux);
232 d->duart_isr &= ~DUART_ISR_RXB;
233 }
234 break;
235
236 case 0x170: /* DUART Transmit Data Register (Channel A) */
237 if (op_type == MTS_WRITE) {
238 vtty_put_char(d->vm->vtty_con,(char)*data);
239 d->duart_isr &= ~DUART_ISR_TXA;
240 }
241 break;
242
243 case 0x270: /* DUART Transmit Data Register (Channel B) */
244 if (op_type == MTS_WRITE) {
245 vtty_put_char(d->vm->vtty_aux,(char)*data);
246 d->duart_isr &= ~DUART_ISR_TXB;
247 }
248 break;
249
250 case 0x1a76: /* pcmcia status */
251 if (op_type == MTS_READ)
252 *data = 0xFF;
253 break;
254
255 #if DEBUG_UNKNOWN
256 default:
257 if (op_type == MTS_READ) {
258 cpu_log(cpu,"SB1_IO","read from addr 0x%x, pc=0x%llx\n",
259 offset,cpu->pc);
260 } else {
261 cpu_log(cpu,"SB1_IO","write to addr 0x%x, value=0x%llx, "
262 "pc=0x%llx\n",offset,*data,cpu->pc);
263 }
264 #endif
265 }
266
267 return NULL;
268 }
269
270 /* Shutdown the SB-1 I/O devices */
271 void dev_sb1_io_shutdown(vm_instance_t *vm,struct sb1_io_data *d)
272 {
273 if (d != NULL) {
274 /* Remove the device */
275 dev_remove(vm,&d->dev);
276
277 /* Free the structure itself */
278 free(d);
279 }
280 }
281
282
283 /* Create SB-1 I/O devices */
284 int dev_sb1_io_init(vm_instance_t *vm,u_int duart_irq)
285 {
286 struct sb1_io_data *d;
287
288 /* allocate private data structure */
289 if (!(d = malloc(sizeof(*d)))) {
290 fprintf(stderr,"SB1_IO: out of memory\n");
291 return(-1);
292 }
293
294 memset(d,0,sizeof(*d));
295 d->vm = vm;
296 d->duart_irq = duart_irq;
297
298 vm_object_init(&d->vm_obj);
299 d->vm_obj.name = "sb1_io";
300 d->vm_obj.data = d;
301 d->vm_obj.shutdown = (vm_shutdown_t)dev_sb1_io_shutdown;
302
303 /* Set device properties */
304 dev_init(&d->dev);
305 d->dev.name = "sb1_io";
306 d->dev.priv_data = d;
307 d->dev.phys_addr = 0x10060000ULL;
308 d->dev.phys_len = 0x10000;
309 d->dev.handler = dev_sb1_io_access;
310
311 /* Set console and AUX port notifying functions */
312 vm->vtty_con->priv_data = d;
313 vm->vtty_aux->priv_data = d;
314 vm->vtty_con->read_notifier = tty_con_input;
315 vm->vtty_aux->read_notifier = tty_aux_input;
316
317 /* Trigger periodically a dummy IRQ to flush buffers */
318 d->duart_irq_tid = ptask_add((ptask_callback)tty_trigger_dummy_irq,d,NULL);
319
320 /* Map this device to the VM */
321 vm_bind_device(vm,&d->dev);
322 vm_object_add(vm,&d->vm_obj);
323 return(0);
324 }

  ViewVC Help
Powered by ViewVC 1.1.26