/[gxemul]/upstream/0.4.4/src/device.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

Diff of /upstream/0.4.4/src/device.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 12 by dpavlin, Mon Oct 8 16:18:38 2007 UTC revision 34 by dpavlin, Mon Oct 8 16:21:17 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2005-2007  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: device.c,v 1.16 2005/08/10 22:25:50 debug Exp $   *  $Id: device.c,v 1.32 2006/12/30 13:30:51 debug Exp $
29   *   *
30   *  Device registry framework.   *  Device registry framework.
31   */   */
# Line 35  Line 35 
35  #include <string.h>  #include <string.h>
36    
37  #include "device.h"  #include "device.h"
38    #include "machine.h"
39    #include "memory.h"
40  #include "misc.h"  #include "misc.h"
41    
42    
# Line 43  static int device_entries_sorted = 0; Line 45  static int device_entries_sorted = 0;
45  static int n_device_entries = 0;  static int n_device_entries = 0;
46  static int device_exit_on_error = 1;  static int device_exit_on_error = 1;
47    
48    static struct pci_entry *pci_entries = NULL;
49    static int n_pci_entries = 0;
50    
51    
52  /*  /*
53   *  device_entry_compar():   *  device_entry_compar():
# Line 105  int device_register(char *name, int (*in Line 110  int device_register(char *name, int (*in
110    
111    
112  /*  /*
113     *  pci_register():
114     *
115     *  Registers a pci device. The pci device is added to the pci_entries array.
116     *
117     *  Return value is 1 if the pci device was registered. If it was not
118     *  added, this function does not return.
119     */
120    int pci_register(char *name, void (*initf)(struct machine *, struct memory *,
121            struct pci_device *))
122    {
123            pci_entries = realloc(pci_entries, sizeof(struct pci_entry)
124                * (n_pci_entries + 1));
125            if (pci_entries == NULL) {
126                    fprintf(stderr, "pci_register(): out of memory\n");
127                    exit(1);
128            }
129    
130            memset(&pci_entries[n_pci_entries], 0, sizeof(struct pci_entry));
131    
132            pci_entries[n_pci_entries].name = strdup(name);
133            pci_entries[n_pci_entries].initf = initf;
134            n_pci_entries ++;
135            return 1;
136    }
137    
138    
139    /*
140     *  pci_lookup_initf():
141     *
142     *  Find a pci device init function by scanning the pci_entries array.
143     *
144     *  Return value is a function pointer, or NULL if the name was not found.
145     */
146    void (*pci_lookup_initf(const char *name))(struct machine *machine,
147            struct memory *mem, struct pci_device *pd)
148    {
149            int i;
150    
151            if (name == NULL) {
152                    fprintf(stderr, "pci_lookup_initf(): name = NULL\n");
153                    exit(1);
154            }
155    
156            for (i=0; i<n_pci_entries; i++)
157                    if (strcmp(name, pci_entries[i].name) == 0)
158                            return pci_entries[i].initf;
159            return NULL;
160    }
161    
162    
163    /*
164   *  device_lookup():   *  device_lookup():
165   *   *
166   *  Lookup a device name by scanning the device_entries array (as a binary   *  Lookup a device name by scanning the device_entries array (as a binary
# Line 115  int device_register(char *name, int (*in Line 171  int device_register(char *name, int (*in
171   */   */
172  struct device_entry *device_lookup(char *name)  struct device_entry *device_lookup(char *name)
173  {  {
174          int i, step, r, do_return = 0;          int hi, lo;
175    
176          if (name == NULL) {          if (name == NULL) {
177                  fprintf(stderr, "device_lookup(): NULL ptr\n");                  fprintf(stderr, "device_lookup(): NULL ptr\n");
# Line 128  struct device_entry *device_lookup(char Line 184  struct device_entry *device_lookup(char
184          if (n_device_entries == 0)          if (n_device_entries == 0)
185                  return NULL;                  return NULL;
186    
187          i = n_device_entries / 2;          lo = 0; hi = n_device_entries - 1;
         step = i/2 + 1;  
188    
189          for (;;) {          while (lo <= hi) {
190                  if (i < 0)                  int r, i = (lo + hi) / 2;
                         i = 0;  
                 if (i >= n_device_entries)  
                         i = n_device_entries - 1;  
191    
192                  /*  printf("device_lookup(): i=%i step=%i\n", i, step);                  /*  printf("device_lookup(): i=%i (lo=%i hi=%i)\n", i, lo, hi);
193                      printf("  name='%s', '%s'\n", name,                      printf("  name='%s', '%s'\n", name,
194                      device_entries[i].name);  */                      device_entries[i].name);  */
195    
196                  r = strcmp(name, device_entries[i].name);                  r = strcmp(name, device_entries[i].name);
197                    if (r == 0) {
                 if (r < 0) {  
                         /*  Go left:  */  
                         i -= step;  
                         if (step == 0)  
                                 i --;  
                 } else if (r > 0) {  
                         /*  Go right:  */  
                         i += step;  
                         if (step == 0)  
                                 i ++;  
                 } else {  
198                          /*  Found it!  */                          /*  Found it!  */
199                          return &device_entries[i];                          return &device_entries[i];
200                  }                  }
201    
202                  if (do_return)                  /*  Try left or right half:  */
203                          return NULL;                  if (r < 0)
204                            hi = i - 1;
205                  if (step == 0)                  if (r > 0)
206                          do_return = 1;                          lo = i + 1;
   
                 if (step & 1)  
                         step = (step/2) + 1;  
                 else  
                         step /= 2;  
207          }          }
208    
209            return NULL;
210  }  }
211    
212    
# Line 220  int device_unregister(char *name) Line 258  int device_unregister(char *name)
258   *  device called "kn210" at a specific address.   *  device called "kn210" at a specific address.
259   *   *
260   *  TODO: This function is quite ugly, and should be cleaned up.   *  TODO: This function is quite ugly, and should be cleaned up.
261     *  name_and_params should be const.
262   */   */
263  void *device_add(struct machine *machine, char *name_and_params)  void *device_add(struct machine *machine, char *name_and_params)
264  {  {
265          struct device_entry *p;          struct device_entry *p;
266          struct devinit devinit;          struct devinit devinit;
267          char *s2, *s3;          char *s2, *s3;
268          size_t len;          size_t len, interrupt_path_len = strlen(machine->path) + 100;
269            int quoted;
270    
271          memset(&devinit, 0, sizeof(struct devinit));          memset(&devinit, 0, sizeof(struct devinit));
272          devinit.machine = machine;          devinit.machine = machine;
# Line 249  void *device_add(struct machine *machine Line 289  void *device_add(struct machine *machine
289          memcpy(devinit.name, name_and_params, len);          memcpy(devinit.name, name_and_params, len);
290          devinit.name[len] = '\0';          devinit.name[len] = '\0';
291    
292            /*  Allocate space for the default interrupt name:  */
293            devinit.interrupt_path = malloc(interrupt_path_len + 1);
294            if (devinit.interrupt_path == NULL) {
295                    fprintf(stderr, "device_add(): out of memory\n");
296                    exit(1);
297            }
298            snprintf(devinit.interrupt_path, interrupt_path_len,
299                "%s.cpu[%i]", machine->path, machine->bootstrap_cpu);
300    
301          p = device_lookup(devinit.name);          p = device_lookup(devinit.name);
302          if (p == NULL) {          if (p == NULL) {
303                  fatal("no such device (\"%s\")\n", devinit.name);                  fatal("no such device (\"%s\")\n", devinit.name);
# Line 285  void *device_add(struct machine *machine Line 334  void *device_add(struct machine *machine
334    
335                  if (strncmp(s2, "addr=", 5) == 0) {                  if (strncmp(s2, "addr=", 5) == 0) {
336                          devinit.addr = mystrtoull(s3, NULL, 0);                          devinit.addr = mystrtoull(s3, NULL, 0);
337                    } else if (strncmp(s2, "addr2=", 6) == 0) {
338                            devinit.addr2 = mystrtoull(s3, NULL, 0);
339                  } else if (strncmp(s2, "len=", 4) == 0) {                  } else if (strncmp(s2, "len=", 4) == 0) {
340                          devinit.len = mystrtoull(s3, NULL, 0);                          devinit.len = mystrtoull(s3, NULL, 0);
341                  } else if (strncmp(s2, "addr_mult=", 10) == 0) {                  } else if (strncmp(s2, "addr_mult=", 10) == 0) {
342                          devinit.addr_mult = mystrtoull(s3, NULL, 0);                          devinit.addr_mult = mystrtoull(s3, NULL, 0);
343                    } else if (strncmp(s2, "pci_little_endian=", 18) == 0) {
344                            devinit.pci_little_endian = mystrtoull(s3, NULL, 0);
345                            switch (devinit.pci_little_endian) {
346                            case 0: break;
347                            case 1: devinit.pci_little_endian =
348                                        MEM_PCI_LITTLE_ENDIAN;
349                                    break;
350                            default:fatal("Bad pci_little_endian value.\n");
351                                    exit(1);
352                            }
353                  } else if (strncmp(s2, "irq=", 4) == 0) {                  } else if (strncmp(s2, "irq=", 4) == 0) {
354                          devinit.irq_nr = mystrtoull(s3, NULL, 0);                          devinit.irq_nr = mystrtoull(s3, NULL, 0);
355    
356                            /*  New-style interrupt path:  */
357                            snprintf(devinit.interrupt_path, interrupt_path_len,s3);
358                            if (strchr(devinit.interrupt_path, ' ') != NULL)
359                                    *strchr(devinit.interrupt_path, ' ') = '\0';
360    
361                            if (strncmp(s3, "none", 4) == 0)
362                                    devinit.interrupt_path[0] = '\0';
363                  } else if (strncmp(s2, "in_use=", 7) == 0) {                  } else if (strncmp(s2, "in_use=", 7) == 0) {
364                          devinit.in_use = mystrtoull(s3, NULL, 0);                          devinit.in_use = mystrtoull(s3, NULL, 0);
365                  } else if (strncmp(s2, "name2=", 6) == 0) {                  } else if (strncmp(s2, "name2=", 6) == 0) {
366                          char *h = s2 + 6;                          char *h = s2 + 6;
367                          size_t len = 0;                          size_t len = 0;
368                          while (*h && *h != ' ')                          quoted = 0;
369                            while (*h) {
370                                    if (*h == '\'')
371                                            quoted = !quoted;
372                                  h++, len++;                                  h++, len++;
373                                    if (!quoted && *h == ' ')
374                                            break;
375                            }
376                          devinit.name2 = malloc(len + 1);                          devinit.name2 = malloc(len + 1);
377                          if (devinit.name2 == NULL) {                          if (devinit.name2 == NULL) {
378                                  fprintf(stderr, "out of memory\n");                                  fprintf(stderr, "out of memory\n");
379                                  exit(1);                                  exit(1);
380                          }                          }
381                          snprintf(devinit.name2, len + 1, s2 + 6);                          h = s2 + 6;
382                            if (*h == '\'')
383                                    len -= 2, h++;
384                            snprintf(devinit.name2, len + 1, h);
385                  } else {                  } else {
386                          fatal("unknown param: %s\n", s2);                          fatal("unknown param: %s\n", s2);
387                          if (device_exit_on_error)                          if (device_exit_on_error)
# Line 314  void *device_add(struct machine *machine Line 392  void *device_add(struct machine *machine
392    
393                  /*  skip to the next param:  */                  /*  skip to the next param:  */
394                  s2 = s3;                  s2 = s3;
395                  while (*s2 != '\0' && *s2 != ' ' && *s2 != ',' && *s2 != ';')                  quoted = 0;
396                    while (*s2 != '\0' && (*s2 != ' ' || quoted) &&
397                        *s2 != ',' && *s2 != ';') {
398                            if (*s2 == '\'')
399                                    quoted = !quoted;
400                          s2 ++;                          s2 ++;
401                    }
402          }          }
403    
404    
# Line 333  void *device_add(struct machine *machine Line 416  void *device_add(struct machine *machine
416                          goto return_fail;                          goto return_fail;
417          }          }
418    
419            free(devinit.interrupt_path);
420          free(devinit.name);          free(devinit.name);
421          return devinit.return_ptr;          return devinit.return_ptr;
422    

Legend:
Removed from v.12  
changed lines
  Added in v.34

  ViewVC Help
Powered by ViewVC 1.1.26