1 /*
2  * Cisco router simulation platform.
3  * Copyright (c) 2007 Christophe Fillot (cf@utc.fr)
4  *
5  * Generic Cisco card routines and definitions.
6  */
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <sys/types.h>
13 #include <assert.h>
14 
15 #include "cpu.h"
16 #include "vm.h"
17 #include "dynamips.h"
18 #include "memory.h"
19 #include "device.h"
20 #include "cisco_card.h"
21 
22 /* Get cisco card type description */
cisco_card_get_type_desc(int dev_type)23 char *cisco_card_get_type_desc(int dev_type)
24 {
25    switch(dev_type) {
26       case CISCO_CARD_TYPE_PA:
27          return("Port Adapter (PA)");
28       case CISCO_CARD_TYPE_NM:
29          return("Network Module (NM)");
30       case CISCO_CARD_TYPE_WIC:
31          return("WAN Interface Card (WIC)");
32       default:
33          return("Unknown");
34    }
35 }
36 
37 /* Set EEPROM definition for the specified Cisco card */
cisco_card_set_eeprom(vm_instance_t * vm,struct cisco_card * card,const struct cisco_eeprom * eeprom)38 int cisco_card_set_eeprom(vm_instance_t *vm,struct cisco_card *card,
39                           const struct cisco_eeprom *eeprom)
40 {
41    if (!eeprom)
42       return(0);
43 
44    if (cisco_eeprom_copy(&card->eeprom,eeprom) == -1) {
45       vm_error(vm,"cisco_card_set_eeprom: no memory (eeprom=%p).\n",eeprom);
46       return(-1);
47    }
48 
49    return(0);
50 }
51 
52 /* Unset EEPROM definition */
cisco_card_unset_eeprom(struct cisco_card * card)53 int cisco_card_unset_eeprom(struct cisco_card *card)
54 {
55    cisco_eeprom_free(&card->eeprom);
56    return(0);
57 }
58 
59 /* Check if a card has a valid EEPROM defined */
cisco_card_check_eeprom(struct cisco_card * card)60 int cisco_card_check_eeprom(struct cisco_card *card)
61 {
62    return(cisco_eeprom_valid(&card->eeprom));
63 }
64 
65 /* Create a card structure */
cisco_card_create(u_int card_type)66 static inline struct cisco_card *cisco_card_create(u_int card_type)
67 {
68    struct cisco_card *card;
69 
70    if ((card = malloc(sizeof(*card))) != NULL) {
71       memset(card,0,sizeof(*card));
72       card->card_type = card_type;
73    }
74 
75    return card;
76 }
77 
78 /* Find a NIO binding */
79 static struct cisco_nio_binding *
cisco_card_find_nio_binding(struct cisco_card * card,u_int port_id)80 cisco_card_find_nio_binding(struct cisco_card *card,u_int port_id)
81 {
82    struct cisco_nio_binding *nb;
83 
84    if (!card)
85       return NULL;
86 
87    for(nb=card->nio_list;nb;nb=nb->next)
88       if (nb->port_id == port_id)
89          return nb;
90 
91    return NULL;
92 }
93 
94 /* Remove all NIO bindings */
95 static void
cisco_card_remove_all_nio_bindings(vm_instance_t * vm,struct cisco_card * card)96 cisco_card_remove_all_nio_bindings(vm_instance_t *vm,struct cisco_card *card)
97 {
98    struct cisco_nio_binding *nb,*next;
99 
100    for(nb=card->nio_list;nb;nb=next) {
101       next = nb->next;
102 
103       /* tell the slot driver to stop using this NIO */
104       if (card->driver)
105          card->driver->card_unset_nio(vm,card,nb->port_id);
106 
107       /* unreference NIO object */
108       netio_release(nb->nio->name);
109       free(nb);
110    }
111 
112    card->nio_list = NULL;
113 }
114 
115 /* Enable all NIO for the specified card */
116 static inline
cisco_card_enable_all_nio(vm_instance_t * vm,struct cisco_card * card)117 void cisco_card_enable_all_nio(vm_instance_t *vm,struct cisco_card *card)
118 {
119    struct cisco_nio_binding *nb;
120 
121    if (card && card->driver && card->drv_info)
122       for(nb=card->nio_list;nb;nb=nb->next)
123          card->driver->card_set_nio(vm,card,nb->port_id,nb->nio);
124 }
125 
126 /* Disable all NIO for the specified card */
127 static inline
cisco_card_disable_all_nio(vm_instance_t * vm,struct cisco_card * card)128 void cisco_card_disable_all_nio(vm_instance_t *vm,struct cisco_card *card)
129 {
130    struct cisco_nio_binding *nb;
131 
132    if (card && card->driver && card->drv_info)
133       for(nb=card->nio_list;nb;nb=nb->next)
134          card->driver->card_unset_nio(vm,card,nb->port_id);
135 }
136 
137 /* Initialize a card */
138 static inline
cisco_card_init(vm_instance_t * vm,struct cisco_card * card,u_int id)139 int cisco_card_init(vm_instance_t *vm,struct cisco_card *card,u_int id)
140 {
141    size_t len;
142 
143    /* Check that a device type is defined for this card */
144    if (!card || !card->dev_type || !card->driver)
145       return(-1);
146 
147    /* Allocate device name */
148    len = strlen(card->dev_type) + 10;
149    if (!(card->dev_name = malloc(len))) {
150       vm_error(vm,"unable to allocate device name.\n");
151       return(-1);
152    }
153 
154    snprintf(card->dev_name,len,"%s(%u)",card->dev_type,id);
155 
156    /* Initialize card driver */
157    if (card->driver->card_init(vm,card) == -1) {
158       vm_error(vm,"unable to initialize card type '%s' (id %u)\n",
159                card->dev_type,id);
160       return(-1);
161    }
162 
163    return(0);
164 }
165 
166 /* Shutdown card */
cisco_card_shutdown(vm_instance_t * vm,struct cisco_card * card)167 static int cisco_card_shutdown(vm_instance_t *vm,struct cisco_card *card)
168 {
169    /* Check that a device type is defined for this card */
170    if (!card || !card->dev_type || !card->driver)
171       return(-1);
172 
173    /* Shutdown the NM driver */
174    if (card->drv_info && (card->driver->card_shutdown(vm,card) == -1)) {
175       vm_error(vm,"unable to shutdown card type '%s' (slot %u/%u)\n",
176                card->dev_type,card->slot_id,card->subslot_id);
177       return(-1);
178    }
179 
180    free(card->dev_name);
181    card->dev_name = NULL;
182    card->drv_info = NULL;
183    return(0);
184 }
185 
186 /* Show info for the specified card */
cisco_card_show_info(vm_instance_t * vm,struct cisco_card * card)187 static int cisco_card_show_info(vm_instance_t *vm,struct cisco_card *card)
188 {
189    /* Check that a device type is defined for this card */
190    if (!card || !card->driver || !card->driver->card_show_info)
191       return(-1);
192 
193    card->driver->card_show_info(vm,card);
194    return(0);
195 }
196 
197 /* Save config for the specified card */
cisco_card_save_config(vm_instance_t * vm,struct cisco_card * card,FILE * fd)198 static int cisco_card_save_config(vm_instance_t *vm,struct cisco_card *card,
199                                   FILE *fd)
200 {
201    struct cisco_nio_binding *nb;
202 
203    if (card != NULL) {
204       fprintf(fd,"vm add_slot_binding %s %u %u %s\n",
205               vm->name,card->slot_id,card->subslot_id,card->dev_type);
206 
207       for(nb=card->nio_list;nb;nb=nb->next) {
208          fprintf(fd,"vm add_nio_binding %s %u %u %s\n",
209                  vm->name,card->slot_id,nb->orig_port_id,nb->nio->name);
210       }
211    }
212 
213    return(0);
214 }
215 
216 /* Find a driver in a driver array */
217 static struct cisco_card_driver *
cisco_card_find_driver(struct cisco_card_driver ** array,char * dev_type)218 cisco_card_find_driver(struct cisco_card_driver **array,char *dev_type)
219 {
220    int i;
221 
222    for(i=0;array[i]!=NULL;i++)
223       if (!strcmp(array[i]->dev_type,dev_type))
224          return array[i];
225 
226    return NULL;
227 }
228 
229 /* ======================================================================== */
230 /* High level routines for managing VM slots.                               */
231 /* ======================================================================== */
232 
233 /* Get slot info */
vm_slot_get_card_ptr(vm_instance_t * vm,u_int slot_id)234 struct cisco_card *vm_slot_get_card_ptr(vm_instance_t *vm,u_int slot_id)
235 {
236    if (slot_id >= vm->nr_slots)
237       return NULL;
238 
239    return(vm->slots[slot_id]);
240 }
241 
242 /* Get info for a slot/port (with sub-cards) */
vm_slot_get_info(vm_instance_t * vm,u_int slot_id,u_int port_id,struct cisco_card *** rc,u_int * real_port_id)243 static int vm_slot_get_info(vm_instance_t *vm,u_int slot_id,u_int port_id,
244                             struct cisco_card ***rc,u_int *real_port_id)
245 {
246    struct cisco_card *card;
247    u_int wic_id,card_type;
248 
249    if (slot_id >= VM_MAX_SLOTS) {
250       *rc = NULL;
251       return(-1);
252    }
253 
254    *rc = &vm->slots[slot_id];
255    card = vm->slots[slot_id];
256 
257    card_type = (card != NULL) ? card->card_type : CISCO_CARD_TYPE_UNDEF;
258 
259    switch(card_type) {
260       /*
261        * Handle WICs which are sub-slots for Network Modules (NM).
262        * Numbering: wic #0 => port_id = 0x10
263        *            wic #1 => port_id = 0x20
264        */
265       case CISCO_CARD_TYPE_NM:
266          if (card->driver->wic_slots > 0) {
267             wic_id = port_id >> 4;
268 
269             if (wic_id >= (CISCO_CARD_MAX_WIC+1)) {
270                vm_error(vm,"Invalid wic_id %u (slot %u)\n",wic_id,slot_id);
271                return(-1);
272             }
273 
274             if (wic_id >= 0x01) {
275                /* wic card */
276                *rc = &card->sub_slots[wic_id - 1];
277                *real_port_id = port_id & 0x0F;
278             } else {
279                /* main card */
280                *real_port_id = port_id;
281             }
282          } else {
283             *real_port_id = port_id;
284          }
285          return(0);
286 
287       /* No translation for Cisco 7200 Port Adapters and WICs */
288       case CISCO_CARD_TYPE_PA:
289       case CISCO_CARD_TYPE_WIC:
290          *real_port_id = port_id;
291          return(0);
292 
293       /* Not initialized yet */
294       default:
295          *real_port_id = port_id;
296          return(0);
297    }
298 }
299 
300 /* Translate a port ID (for sub-cards) */
301 static u_int
vm_slot_translate_port_id(vm_instance_t * vm,u_int slot_id,u_int port_id,struct cisco_card ** rc)302 vm_slot_translate_port_id(vm_instance_t *vm,u_int slot_id,u_int port_id,
303                           struct cisco_card **rc)
304 {
305    struct cisco_card **tmp;
306    u_int real_port_id = 0;
307 
308    vm_slot_get_info(vm,slot_id,port_id,&tmp,&real_port_id);
309    *rc = *tmp;
310    return(real_port_id);
311 }
312 
313 /* Check if a slot has an active card */
vm_slot_active(vm_instance_t * vm,u_int slot_id,u_int port_id)314 int vm_slot_active(vm_instance_t *vm,u_int slot_id,u_int port_id)
315 {
316    struct cisco_card **rc;
317    u_int real_port_id;
318 
319    if (vm_slot_get_info(vm,slot_id,port_id,&rc,&real_port_id) == -1)
320       return(FALSE);
321 
322    if ((*rc == NULL) || ((*rc)->dev_type == NULL))
323       return(FALSE);
324 
325    return(TRUE);
326 }
327 
328 /* Set a flag for a card */
vm_slot_set_flag(vm_instance_t * vm,u_int slot_id,u_int port_id,u_int flag)329 int vm_slot_set_flag(vm_instance_t *vm,u_int slot_id,u_int port_id,u_int flag)
330 {
331    struct cisco_card **rc;
332    u_int real_port_id;
333 
334    if (vm_slot_get_info(vm,slot_id,port_id,&rc,&real_port_id) == -1)
335       return(FALSE);
336 
337    if (*rc == NULL)
338       return(FALSE);
339 
340    (*rc)->card_flags |= flag;
341    return(TRUE);
342 }
343 
344 /* Add a slot binding */
vm_slot_add_binding(vm_instance_t * vm,char * dev_type,u_int slot_id,u_int port_id)345 int vm_slot_add_binding(vm_instance_t *vm,char *dev_type,
346                         u_int slot_id,u_int port_id)
347 {
348    struct cisco_card_driver *driver,**drv_array;
349    struct cisco_card **rc,*card,*nc,*parent;
350    u_int real_port_id,card_type,card_id;
351 
352    if (vm_slot_get_info(vm,slot_id,port_id,&rc,&real_port_id) == -1)
353       return(-1);
354 
355    /* check that this bay is empty */
356    if (*rc != NULL) {
357       if ((*rc)->card_flags & CISCO_CARD_FLAG_OVERRIDE) {
358          vm_slot_remove_binding(vm,slot_id,port_id);
359       } else {
360          vm_error(vm,"a card already exists in slot %u/%u (%s)\n",
361                   slot_id,port_id,(*rc)->dev_type);
362          return(-1);
363       }
364    }
365 
366    card = vm->slots[slot_id];
367 
368    if (!card || (card == *rc)) {
369       /* Main slot */
370       drv_array = vm->slots_drivers;
371       card_type = vm->slots_type;
372       card_id   = slot_id;
373       parent    = NULL;
374    } else {
375       /* Subslot */
376       if (!card->driver->card_get_sub_info) {
377          vm_error(vm,"no sub-slot possible for slot %u/%u.\n",slot_id,port_id);
378          return(-1);
379       }
380 
381       if (card->driver->card_get_sub_info(vm,card,port_id,
382                                           &drv_array,&card_type) == -1)
383       {
384          vm_error(vm,"no sub-slot info for slot %u/%u.\n",slot_id,port_id);
385          return(-1);
386       }
387 
388       card_id = port_id;
389       parent  = card;
390    }
391 
392    assert(drv_array != NULL);
393 
394    /* Find the card driver */
395    if (!(driver = cisco_card_find_driver(drv_array,dev_type))) {
396       vm_error(vm,"unknown card type '%s' for slot %u/%u.\n",
397                dev_type,slot_id,port_id);
398       return(-1);
399    }
400 
401    /* Allocate new card info */
402    if (!(nc = cisco_card_create(card_type)))
403       return(-1);
404 
405    nc->slot_id    = slot_id;
406    nc->subslot_id = port_id;
407    nc->card_id    = card_id;
408    nc->dev_type   = driver->dev_type;
409    nc->driver     = driver;
410    nc->parent     = parent;
411    *rc = nc;
412    return(0);
413 }
414 
415 /* Remove a slot binding */
vm_slot_remove_binding(vm_instance_t * vm,u_int slot_id,u_int port_id)416 int vm_slot_remove_binding(vm_instance_t *vm,u_int slot_id,u_int port_id)
417 {
418    struct cisco_card **rc,*sc;
419    u_int i,real_port_id;
420 
421    if (vm_slot_get_info(vm,slot_id,port_id,&rc,&real_port_id) == -1)
422       return(-1);
423 
424    if (*rc == NULL)
425       return(-1);
426 
427    if ((*rc)->drv_info != NULL) {
428       vm_error(vm,"slot %u/%u is still active\n",slot_id,port_id);
429       return(-1);
430    }
431 
432    for(i=0;i<CISCO_CARD_MAX_SUBSLOTS;i++) {
433       if ((sc = (*rc)->sub_slots[i]) != NULL) {
434          vm_error(vm,"sub-slot %u/%u is still active\n",
435                   slot_id,sc->subslot_id);
436          return(-1);
437       }
438    }
439 
440    /* Remove all NIOs bindings */
441    vm_slot_remove_all_nio_bindings(vm,slot_id);
442 
443    /* Free the card info structure */
444    free(*rc);
445    *rc = NULL;
446    return(0);
447 }
448 
449 /* Add a network IO binding */
vm_slot_add_nio_binding(vm_instance_t * vm,u_int slot_id,u_int port_id,char * nio_name)450 int vm_slot_add_nio_binding(vm_instance_t *vm,u_int slot_id,u_int port_id,
451                             char *nio_name)
452 {
453    struct cisco_nio_binding *nb;
454    struct cisco_card *card,*rc;
455    u_int real_port_id;
456    netio_desc_t *nio;
457 
458    if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
459       return(-1);
460 
461    /* Get the real card (in case this is a sub-slot) */
462    real_port_id = vm_slot_translate_port_id(vm,slot_id,port_id,&rc);
463 
464    if (rc == NULL)
465       return(-1);
466 
467    /* check that a NIO is not already bound to this port */
468    if (cisco_card_find_nio_binding(rc,real_port_id) != NULL) {
469       vm_error(vm,"a NIO already exists for interface %u/%u.\n",
470                slot_id,port_id);
471       return(-1);
472    }
473 
474    /* acquire a reference on the NIO object */
475    if (!(nio = netio_acquire(nio_name))) {
476       vm_error(vm,"unable to find NIO '%s'.\n",nio_name);
477       return(-1);
478    }
479 
480    /* create a new binding */
481    if (!(nb = malloc(sizeof(*nb)))) {
482       vm_error(vm,"unable to create NIO binding for interface %u/%u.\n",
483                slot_id,port_id);
484       netio_release(nio_name);
485       return(-1);
486    }
487 
488    memset(nb,0,sizeof(*nb));
489    nb->nio          = nio;
490    nb->port_id      = real_port_id;
491    nb->orig_port_id = port_id;
492 
493    nb->next = rc->nio_list;
494    if (nb->next) nb->next->prev = nb;
495    rc->nio_list = nb;
496    return(0);
497 }
498 
499 /* Remove a NIO binding */
vm_slot_remove_nio_binding(vm_instance_t * vm,u_int slot_id,u_int port_id)500 int vm_slot_remove_nio_binding(vm_instance_t *vm,u_int slot_id,u_int port_id)
501 {
502    struct cisco_nio_binding *nb;
503    struct cisco_card *card,*rc;
504    u_int real_port_id;
505 
506    if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
507       return(-1);
508 
509    /* Get the real card (in case this is a sub-slot) */
510    real_port_id = vm_slot_translate_port_id(vm,slot_id,port_id,&rc);
511 
512    if (rc == NULL)
513       return(-1);
514 
515    /* no nio binding for this slot/port ? */
516    if (!(nb = cisco_card_find_nio_binding(rc,real_port_id)))
517       return(-1);
518 
519    /* tell the NM driver to stop using this NIO */
520    if (rc->driver)
521       rc->driver->card_unset_nio(vm,rc,port_id);
522 
523    /* remove this entry from the double linked list */
524    if (nb->next)
525       nb->next->prev = nb->prev;
526 
527    if (nb->prev) {
528       nb->prev->next = nb->next;
529    } else {
530       rc->nio_list = nb->next;
531    }
532 
533    /* unreference NIO object */
534    netio_release(nb->nio->name);
535    free(nb);
536    return(0);
537 }
538 
539 /* Remove all NIO bindings for the specified slot (sub-slots included) */
vm_slot_remove_all_nio_bindings(vm_instance_t * vm,u_int slot_id)540 int vm_slot_remove_all_nio_bindings(vm_instance_t *vm,u_int slot_id)
541 {
542    struct cisco_card *card,*sc;
543    int i;
544 
545    if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
546       return(-1);
547 
548    /* Remove NIO bindings for the main slot */
549    cisco_card_remove_all_nio_bindings(vm,card);
550 
551    /* Remove NIO bindings for all sub-slots */
552    for(i=0;i<CISCO_CARD_MAX_SUBSLOTS;i++) {
553       if ((sc = card->sub_slots[i]) != NULL)
554          cisco_card_remove_all_nio_bindings(vm,sc);
555    }
556 
557    return(0);
558 }
559 
560 /* Enable a Network IO descriptor for the specified slot */
vm_slot_enable_nio(vm_instance_t * vm,u_int slot_id,u_int port_id)561 int vm_slot_enable_nio(vm_instance_t *vm,u_int slot_id,u_int port_id)
562 {
563    struct cisco_nio_binding *nb;
564    struct cisco_card *card,*rc;
565    u_int real_port_id;
566 
567    if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
568       return(-1);
569 
570    /* Get the real card (in case this is a sub-slot) */
571    real_port_id = vm_slot_translate_port_id(vm,slot_id,port_id,&rc);
572 
573    if (rc == NULL)
574       return(-1);
575 
576    /* no nio binding for this slot/port ? */
577    if (!(nb = cisco_card_find_nio_binding(rc,real_port_id)))
578       return(-1);
579 
580    /* check that the driver is defined and successfully initialized */
581    if (!rc->driver || !rc->drv_info)
582       return(-1);
583 
584    return(rc->driver->card_set_nio(vm,rc,real_port_id,nb->nio));
585 }
586 
587 /* Disable Network IO descriptor for the specified slot */
vm_slot_disable_nio(vm_instance_t * vm,u_int slot_id,u_int port_id)588 int vm_slot_disable_nio(vm_instance_t *vm,u_int slot_id,u_int port_id)
589 {
590    struct cisco_nio_binding *nb;
591    struct cisco_card *card,*rc;
592    u_int real_port_id;
593 
594    if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
595       return(-1);
596 
597    /* Get the real card (in case this is a sub-slot) */
598    real_port_id = vm_slot_translate_port_id(vm,slot_id,port_id,&rc);
599 
600    if (rc == NULL)
601       return(-1);
602 
603    /* no nio binding for this slot/port ? */
604    if (!(nb = cisco_card_find_nio_binding(rc,real_port_id)))
605       return(-1);
606 
607    /* check that the driver is defined and successfully initialized */
608    if (!rc->driver || !rc->drv_info)
609       return(-1);
610 
611    return(rc->driver->card_unset_nio(vm,rc,real_port_id));
612 }
613 
614 /* Enable all NIO for the specified slot (sub-slots included) */
vm_slot_enable_all_nio(vm_instance_t * vm,u_int slot_id)615 int vm_slot_enable_all_nio(vm_instance_t *vm,u_int slot_id)
616 {
617    struct cisco_card *card;
618    int i;
619 
620    if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
621       return(-1);
622 
623    /* Enable slot NIOs */
624    cisco_card_enable_all_nio(vm,card);
625 
626    /* Enable NIO of sub-slots */
627    for(i=0;i<CISCO_CARD_MAX_SUBSLOTS;i++)
628       cisco_card_enable_all_nio(vm,card->sub_slots[i]);
629 
630    return(0);
631 }
632 
633 /* Disable all NIO for the specified slot (sub-slots included) */
vm_slot_disable_all_nio(vm_instance_t * vm,u_int slot_id)634 int vm_slot_disable_all_nio(vm_instance_t *vm,u_int slot_id)
635 {
636    struct cisco_card *card;
637    int i;
638 
639    if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
640       return(-1);
641 
642    /* Disable slot NIOs */
643    cisco_card_disable_all_nio(vm,card);
644 
645    /* Disable NIO of sub-slots */
646    for(i=0;i<CISCO_CARD_MAX_SUBSLOTS;i++)
647       cisco_card_disable_all_nio(vm,card->sub_slots[i]);
648 
649    return(0);
650 }
651 
652 /* Initialize the specified slot (sub-slots included) */
vm_slot_init(vm_instance_t * vm,u_int slot_id)653 int vm_slot_init(vm_instance_t *vm,u_int slot_id)
654 {
655    struct cisco_card *card;
656    int i;
657 
658    if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
659       return(0);
660 
661    /* Initialize card main module */
662    cisco_card_init(vm,card,slot_id);
663 
664    /* Initialize sub-slots */
665    for(i=0;i<CISCO_CARD_MAX_SUBSLOTS;i++)
666       cisco_card_init(vm,card->sub_slots[i],slot_id);
667 
668    /* Enable all NIO */
669    vm_slot_enable_all_nio(vm,slot_id);
670    return(0);
671 }
672 
673 /* Initialize all slots of a VM */
vm_slot_init_all(vm_instance_t * vm)674 int vm_slot_init_all(vm_instance_t *vm)
675 {
676    int i;
677 
678    for(i=0;i<vm->nr_slots;i++) {
679       if (vm_slot_init(vm,i) == -1) {
680          vm_error(vm,"unable to initialize slot %u\n",i);
681          return(-1);
682       }
683    }
684 
685    return(0);
686 }
687 
688 /* Shutdown the specified slot (sub-slots included) */
vm_slot_shutdown(vm_instance_t * vm,u_int slot_id)689 int vm_slot_shutdown(vm_instance_t *vm,u_int slot_id)
690 {
691    struct cisco_card *card;
692    int i;
693 
694    if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
695       return(-1);
696 
697    /* Disable all NIO */
698    vm_slot_disable_all_nio(vm,slot_id);
699 
700    /* Shutdown sub-slots */
701    for(i=0;i<CISCO_CARD_MAX_SUBSLOTS;i++)
702       cisco_card_shutdown(vm,card->sub_slots[i]);
703 
704    /* Shutdown card main module */
705    cisco_card_shutdown(vm,card);
706    return(0);
707 }
708 
709 /* Shutdown all slots of a VM */
vm_slot_shutdown_all(vm_instance_t * vm)710 int vm_slot_shutdown_all(vm_instance_t *vm)
711 {
712    int i;
713 
714    for(i=0;i<vm->nr_slots;i++)
715       vm_slot_shutdown(vm,i);
716 
717    return(0);
718 }
719 
720 /* Show info about the specified slot (sub-slots included) */
vm_slot_show_info(vm_instance_t * vm,u_int slot_id)721 int vm_slot_show_info(vm_instance_t *vm,u_int slot_id)
722 {
723    struct cisco_card *card;
724 
725    if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
726       return(-1);
727 
728    cisco_card_show_info(vm,card);
729    return(0);
730 }
731 
732 /* Show info about all slots */
vm_slot_show_all_info(vm_instance_t * vm)733 int vm_slot_show_all_info(vm_instance_t *vm)
734 {
735    int i;
736 
737    for(i=0;i<vm->nr_slots;i++)
738       vm_slot_show_info(vm,i);
739 
740    return(0);
741 }
742 
743 /* Check if the specified slot has a valid EEPROM defined */
vm_slot_check_eeprom(vm_instance_t * vm,u_int slot_id,u_int port_id)744 int vm_slot_check_eeprom(vm_instance_t *vm,u_int slot_id,u_int port_id)
745 {
746    struct cisco_card *card,*rc;
747 
748    if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
749       return(FALSE);
750 
751    /* Get the real card (in case this is a sub-slot) */
752    vm_slot_translate_port_id(vm,slot_id,port_id,&rc);
753 
754    if (rc == NULL)
755       return(FALSE);
756 
757    return(cisco_card_check_eeprom(rc));
758 }
759 
760 /* Returns the EEPROM data of the specified slot */
761 struct cisco_eeprom *
vm_slot_get_eeprom(vm_instance_t * vm,u_int slot_id,u_int port_id)762 vm_slot_get_eeprom(vm_instance_t *vm,u_int slot_id,u_int port_id)
763 {
764    struct cisco_card *card,*rc;
765 
766    if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
767       return NULL;
768 
769    /* Get the real card (in case this is a sub-slot) */
770    vm_slot_translate_port_id(vm,slot_id,port_id,&rc);
771 
772    if (rc == NULL)
773       return NULL;
774 
775    return(&rc->eeprom);
776 }
777 
778 /* Save config for the specified slot (sub-slots included) */
vm_slot_save_config(vm_instance_t * vm,u_int slot_id,FILE * fd)779 int vm_slot_save_config(vm_instance_t *vm,u_int slot_id,FILE *fd)
780 {
781    struct cisco_card *card;
782    int i;
783 
784    if (!(card = vm_slot_get_card_ptr(vm,slot_id)))
785       return(-1);
786 
787    /* Main slot info */
788    cisco_card_save_config(vm,card,fd);
789 
790    /* Shutdown sub-slots */
791    for(i=0;i<CISCO_CARD_MAX_SUBSLOTS;i++)
792       cisco_card_save_config(vm,card->sub_slots[i],fd);
793 
794    return(0);
795 }
796 
797 /* Save config for all slots */
vm_slot_save_all_config(vm_instance_t * vm,FILE * fd)798 int vm_slot_save_all_config(vm_instance_t *vm,FILE *fd)
799 {
800    int i;
801 
802    for(i=0;i<vm->nr_slots;i++)
803       vm_slot_save_config(vm,i,fd);
804 
805    return(0);
806 }
807 
808 /* Show slot drivers */
vm_slot_show_drivers(vm_instance_t * vm)809 int vm_slot_show_drivers(vm_instance_t *vm)
810 {
811    char *slot_type;
812    int i;
813 
814    if (!vm->slots_drivers)
815       return(-1);
816 
817    slot_type = cisco_card_get_type_desc(vm->slots_type);
818 
819    printf("Available %s %s drivers:\n",vm->platform->log_name,slot_type);
820 
821    for(i=0;vm->slots_drivers[i];i++) {
822       printf("  * %s %s\n",
823              vm->slots_drivers[i]->dev_type,
824              !vm->slots_drivers[i]->supported ? "(NOT WORKING)" : "");
825    }
826 
827    printf("\n");
828    return(0);
829 }
830 
831 /* Maximum number of tokens in a slot description */
832 #define SLOT_DESC_MAX_TOKENS  8
833 
834 /* Create a Network Module (command line) */
vm_slot_cmd_create(vm_instance_t * vm,char * str)835 int vm_slot_cmd_create(vm_instance_t *vm,char *str)
836 {
837    char *tokens[SLOT_DESC_MAX_TOKENS];
838    int i,count,res;
839    u_int slot_id,port_id;
840 
841    /* A port adapter description is like "1:0:NM-1FE" */
842    count = m_strsplit(str,':',tokens,SLOT_DESC_MAX_TOKENS);
843 
844    if ((count < 2) || (count > 3)) {
845       vm_error(vm,"unable to parse slot description '%s'.\n",str);
846       return(-1);
847    }
848 
849    /* Parse the slot id */
850    slot_id = atoi(tokens[0]);
851 
852    /* Parse the sub-slot id */
853    if (count == 3)
854       port_id = atoi(tokens[1]);
855    else
856       port_id = 0;
857 
858    /* Add this new slot to the current slot list */
859    res = vm_slot_add_binding(vm,tokens[count-1],slot_id,port_id);
860 
861    /* The complete array was cleaned by strsplit */
862    for(i=0;i<SLOT_DESC_MAX_TOKENS;i++)
863       free(tokens[i]);
864 
865    return(res);
866 }
867 
868 /* Add a Network IO descriptor binding (command line) */
vm_slot_cmd_add_nio(vm_instance_t * vm,char * str)869 int vm_slot_cmd_add_nio(vm_instance_t *vm,char *str)
870 {
871    char *tokens[SLOT_DESC_MAX_TOKENS];
872    int i,count,nio_type,res=-1;
873    u_int slot_id,port_id;
874    netio_desc_t *nio;
875    char nio_name[128];
876 
877    /* A NIO binding description is like "1:3:tap:tap0" */
878    if ((count = m_strsplit(str,':',tokens,SLOT_DESC_MAX_TOKENS)) < 3) {
879       vm_error(vm,"unable to parse NIO description '%s'.\n",str);
880       return(-1);
881    }
882 
883    /* Parse the slot id */
884    slot_id = atoi(tokens[0]);
885 
886    /* Parse the port id */
887    port_id = atoi(tokens[1]);
888 
889    /* Autogenerate a NIO name */
890    snprintf(nio_name,sizeof(nio_name),"%s-i%u/%u/%u",
891             vm_get_type(vm),vm->instance_id,slot_id,port_id);
892 
893    /* Create the Network IO descriptor */
894    nio = NULL;
895    nio_type = netio_get_type(tokens[2]);
896 
897    switch(nio_type) {
898       case NETIO_TYPE_UNIX:
899          if (count != 5) {
900             vm_error(vm,"invalid number of arguments for UNIX NIO '%s'\n",str);
901             goto done;
902          }
903 
904          nio = netio_desc_create_unix(nio_name,tokens[3],tokens[4]);
905          break;
906 
907       case NETIO_TYPE_VDE:
908          if (count != 5) {
909             vm_error(vm,"invalid number of arguments for VDE NIO '%s'\n",str);
910             goto done;
911          }
912 
913          nio = netio_desc_create_vde(nio_name,tokens[3],tokens[4]);
914          break;
915 
916       case NETIO_TYPE_TAP:
917          if (count != 4) {
918             vm_error(vm,"invalid number of arguments for TAP NIO '%s'\n",str);
919             goto done;
920          }
921 
922          nio = netio_desc_create_tap(nio_name,tokens[3]);
923          break;
924 
925       case NETIO_TYPE_UDP:
926          if (count != 6) {
927             vm_error(vm,"invalid number of arguments for UDP NIO '%s'\n",str);
928             goto done;
929          }
930 
931          nio = netio_desc_create_udp(nio_name,atoi(tokens[3]),
932                                      tokens[4],atoi(tokens[5]));
933          break;
934 
935       case NETIO_TYPE_TCP_CLI:
936          if (count != 5) {
937             vm_error(vm,"invalid number of arguments for TCP CLI NIO '%s'\n",
938                      str);
939             goto done;
940          }
941 
942          nio = netio_desc_create_tcp_cli(nio_name,tokens[3],tokens[4]);
943          break;
944 
945       case NETIO_TYPE_TCP_SER:
946          if (count != 4) {
947             vm_error(vm,"invalid number of arguments for TCP SER NIO '%s'\n",
948                      str);
949             goto done;
950          }
951 
952          nio = netio_desc_create_tcp_ser(nio_name,tokens[3]);
953          break;
954 
955       case NETIO_TYPE_NULL:
956          nio = netio_desc_create_null(nio_name);
957          break;
958 
959 #ifdef LINUX_ETH
960       case NETIO_TYPE_LINUX_ETH:
961          if (count != 4) {
962             vm_error(vm,"invalid number of arguments for Linux Eth NIO '%s'\n",
963                      str);
964             goto done;
965          }
966 
967          nio = netio_desc_create_lnxeth(nio_name,tokens[3]);
968          break;
969 #endif
970 
971 #ifdef GEN_ETH
972       case NETIO_TYPE_GEN_ETH:
973          if (count != 4) {
974             vm_error(vm,
975                      "invalid number of arguments for Generic Eth NIO '%s'\n",
976                      str);
977             goto done;
978          }
979 
980          nio = netio_desc_create_geneth(nio_name,tokens[3]);
981          break;
982 #endif
983 
984       default:
985          vm_error(vm,"unknown NETIO type '%s'\n",tokens[2]);
986          goto done;
987    }
988 
989    if (!nio) {
990       vm_error(vm,"unable to create NETIO descriptor for slot %u\n",slot_id);
991       goto done;
992    }
993 
994    if (vm_slot_add_nio_binding(vm,slot_id,port_id,nio_name) == -1) {
995       vm_error(vm,"unable to add NETIO binding for slot %u\n",slot_id);
996       netio_release(nio_name);
997       netio_delete(nio_name);
998       goto done;
999    }
1000 
1001    netio_release(nio_name);
1002    res = 0;
1003 
1004  done:
1005    /* The complete array was cleaned by strsplit */
1006    for(i=0;i<SLOT_DESC_MAX_TOKENS;i++)
1007       free(tokens[i]);
1008 
1009    return(res);
1010 }
1011