Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hwprobe.c
Go to the documentation of this file.
1 /* Copyright (C) 2007 One Stop Systems
2  * Copyright (C) 2003-2005 SBE, Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  */
14 
15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16 
17 #include <linux/netdevice.h>
18 #include <linux/hdlc.h>
19 #include <linux/if_arp.h>
20 #include <asm/uaccess.h>
21 #include <linux/rtnetlink.h>
22 #include <linux/pci.h>
23 #include "pmcc4_sysdep.h"
24 #include "sbecom_inline_linux.h"
25 #include "libsbew.h"
26 #include "pmcc4_private.h"
27 #include "pmcc4.h"
28 #include "pmcc4_ioctls.h"
29 #include "pmc93x6_eeprom.h"
30 #ifdef CONFIG_PROC_FS
31 #include "sbeproc.h"
32 #endif
33 
34 #ifdef SBE_INCLUDE_SYMBOLS
35 #define STATIC
36 #else
37 #define STATIC static
38 #endif
39 
40 extern int cxt1e1_log_level;
41 extern int error_flag;
42 extern int drvr_state;
43 
44 /* forward references */
45 void c4_stopwd (ci_t *);
46 struct net_device * __init c4_add_dev (hdw_info_t *, int, unsigned long, unsigned long, int, int);
47 
48 
50 
51 
52 void __init
53 show_two (hdw_info_t * hi, int brdno)
54 {
55  ci_t *ci;
56  struct pci_dev *pdev;
57  char *bid;
58  char *bp, banner[80];
59  char sn[6];
60 
61  bp = banner;
62  memset (banner, 0, 80); /* clear print buffer */
63 
64  ci = (ci_t *)(netdev_priv(hi->ndev));
65  bid = sbeid_get_bdname (ci);
66  switch (hi->promfmt)
67  {
68  case PROM_FORMAT_TYPE1:
69  memcpy (sn, (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
70  break;
71  case PROM_FORMAT_TYPE2:
72  memcpy (sn, (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
73  break;
74  default:
75  memset (sn, 0, 6);
76  break;
77  }
78 
79  sprintf (banner, "%s: %s S/N %06X, MUSYCC Rev %02X",
80  hi->devname, bid,
81  ((sn[3] << 16) & 0xff0000) |
82  ((sn[4] << 8) & 0x00ff00) |
83  (sn[5] & 0x0000ff),
84  (u_int8_t) hi->revid[0]);
85 
86  pr_info("%s\n", banner);
87 
88  pdev = hi->pdev[0];
89  pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
90  hi->devname, "MUSYCC",
91  (unsigned long) hi->addr_mapped[0], hi->addr[0],
92  hi->pci_busno, (u_int8_t) PCI_SLOT (pdev->devfn),
93  (u_int8_t) PCI_FUNC (pdev->devfn), pdev->irq);
94 
95  pdev = hi->pdev[1];
96  pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
97  hi->devname, "EBUS ",
98  (unsigned long) hi->addr_mapped[1], hi->addr[1],
99  hi->pci_busno, (u_int8_t) PCI_SLOT (pdev->devfn),
100  (u_int8_t) PCI_FUNC (pdev->devfn), pdev->irq);
101 }
102 
103 
104 void __init
105 hdw_sn_get (hdw_info_t * hi, int brdno)
106 {
107  /* obtain hardware EEPROM information */
108  long addr;
109 
110  addr = (long) hi->addr_mapped[1] + EEPROM_OFFSET;
111 
112  /* read EEPROM with largest known format size... */
113  pmc_eeprom_read_buffer (addr, 0, (char *) hi->mfg_info.data, sizeof (FLD_TYPE2));
114 
115 #if 0
116  {
117  unsigned char *ucp = (unsigned char *) &hi->mfg_info.data;
118 
119  pr_info("eeprom[00]: %02x %02x %02x %02x %02x %02x %02x %02x\n",
120  *(ucp + 0), *(ucp + 1), *(ucp + 2), *(ucp + 3), *(ucp + 4), *(ucp + 5), *(ucp + 6), *(ucp + 7));
121  pr_info("eeprom[08]: %02x %02x %02x %02x %02x %02x %02x %02x\n",
122  *(ucp + 8), *(ucp + 9), *(ucp + 10), *(ucp + 11), *(ucp + 12), *(ucp + 13), *(ucp + 14), *(ucp + 15));
123  pr_info("eeprom[16]: %02x %02x %02x %02x %02x %02x %02x %02x\n",
124  *(ucp + 16), *(ucp + 17), *(ucp + 18), *(ucp + 19), *(ucp + 20), *(ucp + 21), *(ucp + 22), *(ucp + 23));
125  pr_info("eeprom[24]: %02x %02x %02x %02x %02x %02x %02x %02x\n",
126  *(ucp + 24), *(ucp + 25), *(ucp + 26), *(ucp + 27), *(ucp + 28), *(ucp + 29), *(ucp + 30), *(ucp + 31));
127  pr_info("eeprom[32]: %02x %02x %02x %02x %02x %02x %02x %02x\n",
128  *(ucp + 32), *(ucp + 33), *(ucp + 34), *(ucp + 35), *(ucp + 36), *(ucp + 37), *(ucp + 38), *(ucp + 39));
129  pr_info("eeprom[40]: %02x %02x %02x %02x %02x %02x %02x %02x\n",
130  *(ucp + 40), *(ucp + 41), *(ucp + 42), *(ucp + 43), *(ucp + 44), *(ucp + 45), *(ucp + 46), *(ucp + 47));
131  }
132 #endif
133 #if 0
134  pr_info("sn: %x %x %x %x %x %x\n",
135  hi->mfg_info.Serial[0],
136  hi->mfg_info.Serial[1],
137  hi->mfg_info.Serial[2],
138  hi->mfg_info.Serial[3],
139  hi->mfg_info.Serial[4],
140  hi->mfg_info.Serial[5]);
141 #endif
142 
143  if ((hi->promfmt = pmc_verify_cksum (&hi->mfg_info.data)) == PROM_FORMAT_Unk)
144  {
145  /* bad crc, data is suspect */
146  if (cxt1e1_log_level >= LOG_WARN)
147  pr_info("%s: EEPROM cksum error\n", hi->devname);
149  } else
150  hi->mfg_info_sts = EEPROM_OK;
151 }
152 
153 
154 void __init
156 {
157  hdw_info_t *hi;
158  int i;
159 
160  for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
161  {
162  hi->pci_busno = 0xff;
163  hi->pci_slot = 0xff;
164  hi->pci_pin[0] = 0;
165  hi->pci_pin[1] = 0;
166  hi->ndev = 0;
167  hi->addr[0] = 0L;
168  hi->addr[1] = 0L;
169  hi->addr_mapped[0] = 0L;
170  hi->addr_mapped[1] = 0L;
171  }
172 }
173 
174 void
176 {
177  hdw_info_t *hi;
178  int i;
179 
180  for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
181  {
182  if (hi->pci_slot == 0xff)
183  break;
184  if (hi->addr_mapped[0])
185  {
186  iounmap ((void *) (hi->addr_mapped[0]));
187  release_mem_region ((long) hi->addr[0], hi->len[0]);
188  hi->addr_mapped[0] = 0;
189  }
190  if (hi->addr_mapped[1])
191  {
192  iounmap ((void *) (hi->addr_mapped[1]));
193  release_mem_region ((long) hi->addr[1], hi->len[1]);
194  hi->addr_mapped[1] = 0;
195  }
196  }
197 }
198 
199 
200 void
202 {
203  hdw_info_t *hi;
204  int i;
205 
206  for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
207  {
208  if (hi->pci_slot == 0xff || !hi->ndev)
209  break;
210  c4_stopwd(netdev_priv(hi->ndev));
211 #ifdef CONFIG_PROC_FS
212  sbecom_proc_brd_cleanup(netdev_priv(hi->ndev));
213 #endif
214  unregister_netdev (hi->ndev);
215  free_irq (hi->pdev[0]->irq, hi->ndev);
216 #ifdef CONFIG_SBE_PMCC4_NCOMM
217  free_irq (hi->pdev[1]->irq, hi->ndev);
218 #endif
219  OS_kfree (hi->ndev);
220  }
221 }
222 
223 
224 STATIC int __init
225 c4_hdw_init (struct pci_dev * pdev, int found)
226 {
227  hdw_info_t *hi;
228  int i;
229  int fun, slot;
230  unsigned char busno = 0xff;
231 
232  /* our MUSYCC chip supports two functions, 0 & 1 */
233  if ((fun = PCI_FUNC (pdev->devfn)) > 1)
234  {
235  pr_warning("unexpected devfun: 0x%x\n", pdev->devfn);
236  return 0;
237  }
238  if (pdev->bus) /* obtain bus number */
239  busno = pdev->bus->number;
240  else
241  busno = 0; /* default for system PCI inconsistency */
242  slot = pdev->devfn & ~0x07;
243 
244  /*
245  * Functions 0 & 1 for a given board (identified by same bus(busno) and
246  * slot(slot)) are placed into the same 'hardware' structure. The first
247  * part of the board's functionality will be placed into an unpopulated
248  * element, identified by "slot==(0xff)". The second part of a board's
249  * functionality will match the previously loaded slot/busno.
250  */
251  for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
252  {
253  /*
254  * match with board's first found interface, otherwise this is first
255  * found
256  */
257  if ((hi->pci_slot == 0xff) || /* new board */
258  ((hi->pci_slot == slot) && (hi->bus == pdev->bus)))
259  break; /* found for-loop exit */
260  }
261  if (i == MAX_BOARDS) /* no match in above loop means MAX
262  * exceeded */
263  {
264  pr_warning("exceeded number of allowed devices (>%d)?\n", MAX_BOARDS);
265  return 0;
266  }
267  if (pdev->bus)
268  hi->pci_busno = pdev->bus->number;
269  else
270  hi->pci_busno = 0; /* default for system PCI inconsistency */
271  hi->pci_slot = slot;
272  pci_read_config_byte (pdev, PCI_INTERRUPT_PIN, &hi->pci_pin[fun]);
273  pci_read_config_byte (pdev, PCI_REVISION_ID, &hi->revid[fun]);
274  hi->bus = pdev->bus;
275  hi->addr[fun] = pci_resource_start (pdev, 0);
276  hi->len[fun] = pci_resource_end (pdev, 0) - hi->addr[fun] + 1;
277  hi->pdev[fun] = pdev;
278 
279  {
280  /*
281  * create device name from module name, plus add the appropriate
282  * board number
283  */
284  char *cp = hi->devname;
285 
286  strcpy (cp, KBUILD_MODNAME);
287  cp += strlen (cp); /* reposition */
288  *cp++ = '-';
289  *cp++ = '0' + (found / 2); /* there are two found interfaces per
290  * board */
291  *cp = 0; /* termination */
292  }
293 
294  return 1;
295 }
296 
297 
300 {
301  hdw_info_t *hi;
302  struct pci_dev *pdev = NULL;
303  int found = 0, i, j;
304 
305  error_flag = 0;
306  prep_hdw_info ();
307  /*** scan PCI bus for all possible boards */
308  while ((pdev = pci_get_device (PCI_VENDOR_ID_CONEXANT,
310  pdev)))
311  {
312  if (c4_hdw_init (pdev, found))
313  found++;
314  }
315  if (!found)
316  {
317  pr_warning("No boards found\n");
318  return ENODEV;
319  }
320  /* sanity check for consistent hardware found */
321  for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
322  {
323  if (hi->pci_slot != 0xff && (!hi->addr[0] || !hi->addr[1]))
324  {
325  pr_warning("%s: something very wrong with pci_get_device\n",
326  hi->devname);
327  return EIO;
328  }
329  }
330  /* bring board's memory regions on/line */
331  for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
332  {
333  if (hi->pci_slot == 0xff)
334  break;
335  for (j = 0; j < 2; j++)
336  {
337  if (request_mem_region (hi->addr[j], hi->len[j], hi->devname) == 0)
338  {
339  pr_warning("%s: memory in use, addr=0x%lx, len=0x%lx ?\n",
340  hi->devname, hi->addr[j], hi->len[j]);
341  cleanup_ioremap ();
342  return ENOMEM;
343  }
344  hi->addr_mapped[j] = (unsigned long) ioremap (hi->addr[j], hi->len[j]);
345  if (!hi->addr_mapped[j])
346  {
347  pr_warning("%s: ioremap fails, addr=0x%lx, len=0x%lx ?\n",
348  hi->devname, hi->addr[j], hi->len[j]);
349  cleanup_ioremap ();
350  return ENOMEM;
351  }
352 #ifdef SBE_MAP_DEBUG
353  pr_warning("%s: io remapped from phys %x to virt %x\n",
354  hi->devname, (u_int32_t) hi->addr[j], (u_int32_t) hi->addr_mapped[j]);
355 #endif
356  }
357  }
358 
360 
361  /* Have now memory mapped all boards. Now allow board's access to system */
362  for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
363  {
364  if (hi->pci_slot == 0xff)
365  break;
366  if (pci_enable_device (hi->pdev[0]) ||
367  pci_enable_device (hi->pdev[1]))
368  {
370  pr_warning("%s: failed to enable card %d slot %d\n",
371  hi->devname, i, hi->pci_slot);
372  cleanup_devs ();
373  cleanup_ioremap ();
374  return EIO;
375  }
376  pci_set_master (hi->pdev[0]);
377  pci_set_master (hi->pdev[1]);
378  if (!(hi->ndev = c4_add_dev (hi, i, (long) hi->addr_mapped[0],
379  (long) hi->addr_mapped[1],
380  hi->pdev[0]->irq,
381  hi->pdev[1]->irq)))
382  {
384  cleanup_ioremap ();
385  /* NOTE: c4_add_dev() does its own device cleanup */
386 #if 0
387  cleanup_devs ();
388 #endif
389  return error_flag; /* error_flag set w/in add_dev() */
390  }
391  show_two (hi, i); /* displays found information */
392  }
393  return 0;
394 }
395 
396 /*** End-of-File ***/