1 /*
2  * Cisco router simulation platform.
3  * Copyright (c) 2007 Christophe Fillot (cf@utc.fr)
4  *
5  * WIC Modules.
6  */
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <stdarg.h>
12 #include <unistd.h>
13 #include <time.h>
14 #include <errno.h>
15 #include <assert.h>
16 
17 #include "utils.h"
18 #include "net.h"
19 #include "net_io.h"
20 #include "ptask.h"
21 #include "vm.h"
22 #include "dev_nm_16esw.h"
23 #include "dev_mpc860.h"
24 #include "dev_c1700.h"
25 #include "dev_wic_serial.h"
26 
27 /* Get the SCC channel associated to a WIC sub-slot */
dev_c1700_mb_wic_get_scc_chan(struct cisco_card * card,u_int port_id,u_int * scc_chan)28 static int dev_c1700_mb_wic_get_scc_chan(struct cisco_card *card,u_int port_id,
29                                          u_int *scc_chan)
30 {
31    u_int cid;
32 
33    cid = card->subslot_id + port_id;
34 
35    switch(cid) {
36       /* WIC 0 port 0 mapped to MPC860 SCC1 */
37       case 0x10:
38          *scc_chan = 0;
39          break;
40 
41       /* WIC 0 port 1 mapped to MPC860 SCC4 */
42       case 0x11:
43          *scc_chan = 3;
44          break;
45 
46       /* WIC 1 port 0 mapped to MPC860 SCC2 */
47       case 0x20:
48          *scc_chan = 1;
49          break;
50 
51       /* WIC 1 port 1 mapped to MPC860 SCC3 */
52       case 0x21:
53          *scc_chan = 2;
54          break;
55 
56       default:
57          return(-1);
58    }
59 
60    return(0);
61 }
62 
63 /* ======================================================================== */
64 /* WIC-1T                                                                   */
65 /* ======================================================================== */
66 
67 /* Initialize a WIC-1T in the specified slot */
dev_c1700_mb_wic1t_init(vm_instance_t * vm,struct cisco_card * card)68 static int dev_c1700_mb_wic1t_init(vm_instance_t *vm,struct cisco_card *card)
69 {
70    struct wic_serial_data *wic_data;
71    m_uint64_t phys_addr;
72    u_int wic_id;
73 
74    /* Create the WIC device */
75    wic_id = (card->subslot_id >> 4) - 1;
76 
77    if (c1700_get_onboard_wic_addr(wic_id,&phys_addr) == -1) {
78       vm_error(vm,"WIC","invalid slot %u (subslot_id=%u)\n",
79                wic_id,card->subslot_id);
80       return(-1);
81    }
82 
83    wic_data = dev_wic_serial_init(vm,card->dev_name,WIC_SERIAL_MODEL_1T,
84                                   phys_addr,C1700_WIC_SIZE);
85 
86    if (!wic_data)
87       return(-1);
88 
89    /* Set the EEPROM */
90    cisco_card_set_eeprom(vm,card,cisco_eeprom_find_wic("WIC-1T"));
91 
92    /* Store device info into the router structure */
93    card->drv_info = wic_data;
94    return(0);
95 }
96 
97 /* Remove a WIC-1T from the specified slot */
98 static int
dev_c1700_mb_wic1t_shutdown(vm_instance_t * vm,struct cisco_card * card)99 dev_c1700_mb_wic1t_shutdown(vm_instance_t *vm,struct cisco_card *card)
100 {
101    /* Remove the WIC device */
102    dev_wic_serial_remove(card->drv_info);
103 
104    /* Remove the WIC EEPROM */
105    cisco_card_unset_eeprom(card);
106    return(0);
107 }
108 
109 /* Bind a Network IO descriptor */
110 static int
dev_c1700_mb_wic1t_set_nio(vm_instance_t * vm,struct cisco_card * card,u_int port_id,netio_desc_t * nio)111 dev_c1700_mb_wic1t_set_nio(vm_instance_t *vm,struct cisco_card *card,
112                            u_int port_id,netio_desc_t *nio)
113 {
114    u_int scc_chan;
115 
116    if ((port_id > 0) ||
117        (dev_c1700_mb_wic_get_scc_chan(card,port_id,&scc_chan) == -1))
118       return(-1);
119 
120    return(mpc860_scc_set_nio(VM_C1700(vm)->mpc_data,scc_chan,nio));
121 }
122 
123 /* Unbind a Network IO descriptor */
124 static int
dev_c1700_mb_wic1t_unset_nio(vm_instance_t * vm,struct cisco_card * card,u_int port_id)125 dev_c1700_mb_wic1t_unset_nio(vm_instance_t *vm,struct cisco_card *card,
126                              u_int port_id)
127 {
128    u_int scc_chan;
129 
130    if ((port_id > 0) ||
131        (dev_c1700_mb_wic_get_scc_chan(card,port_id,&scc_chan) == -1))
132       return(-1);
133 
134    return(mpc860_scc_unset_nio(VM_C1700(vm)->mpc_data,scc_chan));
135 }
136 
137 /* ======================================================================== */
138 /* WIC-2T                                                                   */
139 /* ======================================================================== */
140 
141 /* Initialize a WIC-2T in the specified slot */
dev_c1700_mb_wic2t_init(vm_instance_t * vm,struct cisco_card * card)142 static int dev_c1700_mb_wic2t_init(vm_instance_t *vm,struct cisco_card *card)
143 {
144    struct wic_serial_data *wic_data;
145    m_uint64_t phys_addr;
146    u_int wic_id;
147 
148    /* Create the WIC device */
149    wic_id = (card->subslot_id >> 4) - 1;
150 
151    if (c1700_get_onboard_wic_addr(wic_id,&phys_addr) == -1) {
152       vm_error(vm,"WIC","invalid slot %u (subslot_id=%u)\n",
153                wic_id,card->subslot_id);
154       return(-1);
155    }
156 
157    wic_data = dev_wic_serial_init(vm,card->dev_name,WIC_SERIAL_MODEL_2T,
158                                   phys_addr,C1700_WIC_SIZE);
159 
160    if (!wic_data)
161       return(-1);
162 
163    /* Set the EEPROM */
164    cisco_card_set_eeprom(vm,card,cisco_eeprom_find_wic("WIC-2T"));
165 
166    /* Store device info into the router structure */
167    card->drv_info = wic_data;
168    return(0);
169 }
170 
171 /* Remove a WIC-2T from the specified slot */
172 static int
dev_c1700_mb_wic2t_shutdown(vm_instance_t * vm,struct cisco_card * card)173 dev_c1700_mb_wic2t_shutdown(vm_instance_t *vm,struct cisco_card *card)
174 {
175    /* Remove the WIC device */
176    dev_wic_serial_remove(card->drv_info);
177 
178    /* Remove the WIC EEPROM */
179    cisco_card_unset_eeprom(card);
180    return(0);
181 }
182 
183 /* Bind a Network IO descriptor */
184 static int
dev_c1700_mb_wic2t_set_nio(vm_instance_t * vm,struct cisco_card * card,u_int port_id,netio_desc_t * nio)185 dev_c1700_mb_wic2t_set_nio(vm_instance_t *vm,struct cisco_card *card,
186                            u_int port_id,netio_desc_t *nio)
187 {
188    u_int scc_chan;
189 
190    if ((port_id > 1) ||
191        (dev_c1700_mb_wic_get_scc_chan(card,port_id,&scc_chan) == -1))
192       return(-1);
193 
194    return(mpc860_scc_set_nio(VM_C1700(vm)->mpc_data,scc_chan,nio));
195 }
196 
197 /* Unbind a Network IO descriptor */
198 static int
dev_c1700_mb_wic2t_unset_nio(vm_instance_t * vm,struct cisco_card * card,u_int port_id)199 dev_c1700_mb_wic2t_unset_nio(vm_instance_t *vm,struct cisco_card *card,
200                              u_int port_id)
201 {
202    u_int scc_chan;
203 
204    if ((port_id > 1) ||
205        (dev_c1700_mb_wic_get_scc_chan(card,port_id,&scc_chan) == -1))
206       return(-1);
207 
208    return(mpc860_scc_unset_nio(VM_C1700(vm)->mpc_data,scc_chan));
209 }
210 
211 /* ======================================================================== */
212 /* WIC-1ENET                                                                */
213 /* ======================================================================== */
214 
215 /* Initialize a WIC-1ENET in the specified slot */
216 static int
dev_c1700_mb_wic1enet_init(vm_instance_t * vm,struct cisco_card * card)217 dev_c1700_mb_wic1enet_init(vm_instance_t *vm,struct cisco_card *card)
218 {
219    m_uint8_t eeprom_ver;
220    size_t offset;
221    n_eth_addr_t addr;
222    m_uint16_t pid;
223 
224    pid = (m_uint16_t)getpid();
225 
226    /* Generate automatically the MAC address */
227    addr.eth_addr_byte[0] = vm_get_mac_addr_msb(vm);
228    addr.eth_addr_byte[1] = vm->instance_id & 0xFF;
229    addr.eth_addr_byte[2] = pid >> 8;
230    addr.eth_addr_byte[3] = pid & 0xFF;
231    addr.eth_addr_byte[4] = card->subslot_id;
232    addr.eth_addr_byte[5] = 0x00;
233 
234    /* Set the EEPROM */
235    cisco_card_set_eeprom(vm,card,cisco_eeprom_find_wic("WIC-1ENET"));
236 
237    /* Read EEPROM format version */
238    cisco_eeprom_get_byte(&card->eeprom,0,&eeprom_ver);
239 
240    if (eeprom_ver != 4)
241       return(-1);
242 
243    if (cisco_eeprom_v4_find_field(&card->eeprom,0xCF,&offset) == -1)
244       return(-1);
245 
246    cisco_eeprom_set_region(&card->eeprom,offset,addr.eth_addr_byte,6);
247 
248    /* Store device info into the router structure */
249    card->drv_info = VM_C1700(vm)->mpc_data;
250    return(0);
251 }
252 
253 /* Remove a WIC-1ENET from the specified slot */
254 static int
dev_c1700_mb_wic1enet_shutdown(vm_instance_t * vm,struct cisco_card * card)255 dev_c1700_mb_wic1enet_shutdown(vm_instance_t *vm,struct cisco_card *card)
256 {
257    /* Remove the WIC EEPROM */
258    cisco_card_unset_eeprom(card);
259    return(0);
260 }
261 
262 /* Bind a Network IO descriptor */
263 static int
dev_c1700_mb_wic1enet_set_nio(vm_instance_t * vm,struct cisco_card * card,u_int port_id,netio_desc_t * nio)264 dev_c1700_mb_wic1enet_set_nio(vm_instance_t *vm,struct cisco_card *card,
265                            u_int port_id,netio_desc_t *nio)
266 {
267    struct mpc860_data *mpc_data = card->drv_info;
268    u_int scc_chan;
269 
270    if ((port_id > 0) ||
271        (dev_c1700_mb_wic_get_scc_chan(card,port_id,&scc_chan) == -1))
272       return(-1);
273 
274    return(mpc860_scc_set_nio(mpc_data,scc_chan,nio));
275 }
276 
277 /* Unbind a Network IO descriptor */
278 static int
dev_c1700_mb_wic1enet_unset_nio(vm_instance_t * vm,struct cisco_card * card,u_int port_id)279 dev_c1700_mb_wic1enet_unset_nio(vm_instance_t *vm,struct cisco_card *card,
280                                 u_int port_id)
281 {
282    struct mpc860_data *mpc_data = card->drv_info;
283    u_int scc_chan;
284 
285    if ((port_id > 0) ||
286        (dev_c1700_mb_wic_get_scc_chan(card,port_id,&scc_chan) == -1))
287       return(-1);
288 
289    return(mpc860_scc_unset_nio(mpc_data,scc_chan));
290 }
291 
292 /* ======================================================================== */
293 
294 /* Cisco 1700 WIC-1T driver */
295 struct cisco_card_driver dev_c1700_mb_wic1t_driver = {
296    "WIC-1T", 1, 0,
297    dev_c1700_mb_wic1t_init,
298    dev_c1700_mb_wic1t_shutdown,
299    NULL,
300    dev_c1700_mb_wic1t_set_nio,
301    dev_c1700_mb_wic1t_unset_nio,
302    NULL,
303 };
304 
305 /* Cisco 1700 WIC-2T driver */
306 struct cisco_card_driver dev_c1700_mb_wic2t_driver = {
307    "WIC-2T", 1, 0,
308    dev_c1700_mb_wic2t_init,
309    dev_c1700_mb_wic2t_shutdown,
310    NULL,
311    dev_c1700_mb_wic2t_set_nio,
312    dev_c1700_mb_wic2t_unset_nio,
313    NULL,
314 };
315 
316 /* Cisco 1700 WIC-1ENET driver */
317 struct cisco_card_driver dev_c1700_mb_wic1enet_driver = {
318    "WIC-1ENET", 1, 0,
319    dev_c1700_mb_wic1enet_init,
320    dev_c1700_mb_wic1enet_shutdown,
321    NULL,
322    dev_c1700_mb_wic1enet_set_nio,
323    dev_c1700_mb_wic1enet_unset_nio,
324    NULL,
325 };
326 
327 /* WIC drivers (mainbord slots) */
328 struct cisco_card_driver *dev_c1700_mb_wic_drivers[] = {
329    &dev_c1700_mb_wic1t_driver,
330    &dev_c1700_mb_wic2t_driver,
331    &dev_c1700_mb_wic1enet_driver,
332    NULL,
333 };
334