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