/[dynamips]/trunk/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 /trunk/dev_sb1_io.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (hide annotations)
Sat Oct 6 16:45:40 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 8632 byte(s)
make working copy

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

  ViewVC Help
Powered by ViewVC 1.1.26