Merge branch '3.3-urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target...
[deliverable/linux.git] / drivers / staging / cxt1e1 / hwprobe.c
CommitLineData
50ee11fe
BB
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
e6e4d05d
JP
15#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16
50ee11fe
BB
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
b8b73994 40extern int cxt1e1_log_level;
50ee11fe
BB
41extern int error_flag;
42extern int drvr_state;
43
44/* forward references */
45void c4_stopwd (ci_t *);
46struct net_device * __init c4_add_dev (hdw_info_t *, int, unsigned long, unsigned long, int, int);
47
48
49struct s_hdw_info hdw_info[MAX_BOARDS];
50
51
52void __init
53show_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
694a9807 86 pr_info("%s\n", banner);
50ee11fe
BB
87
88 pdev = hi->pdev[0];
694a9807 89 pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
50ee11fe
BB
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];
694a9807 96 pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
50ee11fe
BB
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
104void __init
105hdw_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
694a9807 119 pr_info("eeprom[00]: %02x %02x %02x %02x %02x %02x %02x %02x\n",
50ee11fe 120 *(ucp + 0), *(ucp + 1), *(ucp + 2), *(ucp + 3), *(ucp + 4), *(ucp + 5), *(ucp + 6), *(ucp + 7));
694a9807 121 pr_info("eeprom[08]: %02x %02x %02x %02x %02x %02x %02x %02x\n",
50ee11fe 122 *(ucp + 8), *(ucp + 9), *(ucp + 10), *(ucp + 11), *(ucp + 12), *(ucp + 13), *(ucp + 14), *(ucp + 15));
694a9807 123 pr_info("eeprom[16]: %02x %02x %02x %02x %02x %02x %02x %02x\n",
50ee11fe 124 *(ucp + 16), *(ucp + 17), *(ucp + 18), *(ucp + 19), *(ucp + 20), *(ucp + 21), *(ucp + 22), *(ucp + 23));
694a9807 125 pr_info("eeprom[24]: %02x %02x %02x %02x %02x %02x %02x %02x\n",
50ee11fe 126 *(ucp + 24), *(ucp + 25), *(ucp + 26), *(ucp + 27), *(ucp + 28), *(ucp + 29), *(ucp + 30), *(ucp + 31));
694a9807 127 pr_info("eeprom[32]: %02x %02x %02x %02x %02x %02x %02x %02x\n",
50ee11fe 128 *(ucp + 32), *(ucp + 33), *(ucp + 34), *(ucp + 35), *(ucp + 36), *(ucp + 37), *(ucp + 38), *(ucp + 39));
694a9807 129 pr_info("eeprom[40]: %02x %02x %02x %02x %02x %02x %02x %02x\n",
50ee11fe
BB
130 *(ucp + 40), *(ucp + 41), *(ucp + 42), *(ucp + 43), *(ucp + 44), *(ucp + 45), *(ucp + 46), *(ucp + 47));
131 }
132#endif
133#if 0
694a9807 134 pr_info("sn: %x %x %x %x %x %x\n",
50ee11fe
BB
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 */
b8b73994 146 if (cxt1e1_log_level >= LOG_WARN)
694a9807 147 pr_info("%s: EEPROM cksum error\n", hi->devname);
50ee11fe
BB
148 hi->mfg_info_sts = EEPROM_CRCERR;
149 } else
150 hi->mfg_info_sts = EEPROM_OK;
151}
152
153
154void __init
155prep_hdw_info (void)
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
174void
175cleanup_ioremap (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
200void
201cleanup_devs (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
224STATIC int __init
225c4_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 {
e6e4d05d 235 pr_warning("unexpected devfun: 0x%x\n", pdev->devfn);
50ee11fe
BB
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 {
e6e4d05d 264 pr_warning("exceeded number of allowed devices (>%d)?\n", MAX_BOARDS);
50ee11fe
BB
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
40447df8 286 strcpy (cp, KBUILD_MODNAME);
50ee11fe
BB
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
298status_t __init
299c4hw_attach_all (void)
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 */
50ee11fe 308 while ((pdev = pci_get_device (PCI_VENDOR_ID_CONEXANT,
50ee11fe
BB
309 PCI_DEVICE_ID_CN8474,
310 pdev)))
50ee11fe
BB
311 {
312 if (c4_hdw_init (pdev, found))
313 found++;
314 }
315 if (!found)
316 {
e6e4d05d 317 pr_warning("No boards found\n");
50ee11fe
BB
318 return ENODEV;
319 }
9e36261d 320 /* sanity check for consistent hardware found */
50ee11fe
BB
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 {
e6e4d05d
JP
325 pr_warning("%s: something very wrong with pci_get_device\n",
326 hi->devname);
50ee11fe
BB
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 {
e6e4d05d
JP
339 pr_warning("%s: memory in use, addr=0x%lx, len=0x%lx ?\n",
340 hi->devname, hi->addr[j], hi->len[j]);
50ee11fe
BB
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 {
e6e4d05d
JP
347 pr_warning("%s: ioremap fails, addr=0x%lx, len=0x%lx ?\n",
348 hi->devname, hi->addr[j], hi->len[j]);
50ee11fe
BB
349 cleanup_ioremap ();
350 return ENOMEM;
351 }
352#ifdef SBE_MAP_DEBUG
e6e4d05d
JP
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]);
50ee11fe
BB
355#endif
356 }
357 }
358
359 drvr_state = SBE_DRVR_AVAILABLE;
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 {
369 drvr_state = SBE_DRVR_DOWN;
e6e4d05d
JP
370 pr_warning("%s: failed to enable card %d slot %d\n",
371 hi->devname, i, hi->pci_slot);
50ee11fe
BB
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 {
383 drvr_state = SBE_DRVR_DOWN;
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 ***/
This page took 0.193473 seconds and 5 git commands to generate.