/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 dpavlin 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