1 /* Copyright (C) 2007 One Stop Systems
2 * Copyright (C) 2003-2005 SBE, Inc.
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.
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.
15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
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"
26 #include "pmcc4_private.h"
28 #include "pmcc4_ioctls.h"
29 #include "pmc93x6_eeprom.h"
34 #ifdef SBE_INCLUDE_SYMBOLS
41 extern int error_flag
;
42 extern int drvr_state
;
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);
49 struct s_hdw_info hdw_info
[MAX_BOARDS
];
53 show_two (hdw_info_t
* hi
, int brdno
)
62 memset (banner
, 0, 80); /* clear print buffer */
64 ci
= (ci_t
*)(netdev_priv(hi
->ndev
));
65 bid
= sbeid_get_bdname (ci
);
68 case PROM_FORMAT_TYPE1
:
69 memcpy (sn
, (FLD_TYPE1
*) (hi
->mfg_info
.pft1
.Serial
), 6);
71 case PROM_FORMAT_TYPE2
:
72 memcpy (sn
, (FLD_TYPE2
*) (hi
->mfg_info
.pft2
.Serial
), 6);
79 sprintf (banner
, "%s: %s S/N %06X, MUSYCC Rev %02X",
81 ((sn
[3] << 16) & 0xff0000) |
82 ((sn
[4] << 8) & 0x00ff00) |
84 (u_int8_t
) hi
->revid
[0]);
86 pr_info("%s\n", banner
);
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
);
96 pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
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
);
105 hdw_sn_get (hdw_info_t
* hi
, int brdno
)
107 /* obtain hardware EEPROM information */
110 addr
= (long) hi
->addr_mapped
[1] + EEPROM_OFFSET
;
112 /* read EEPROM with largest known format size... */
113 pmc_eeprom_read_buffer (addr
, 0, (char *) hi
->mfg_info
.data
, sizeof (FLD_TYPE2
));
116 if ((hi
->promfmt
= pmc_verify_cksum (&hi
->mfg_info
.data
)) == PROM_FORMAT_Unk
)
118 /* bad crc, data is suspect */
119 if (log_level
>= LOG_WARN
)
120 pr_info("%s: EEPROM cksum error\n", hi
->devname
);
121 hi
->mfg_info_sts
= EEPROM_CRCERR
;
123 hi
->mfg_info_sts
= EEPROM_OK
;
133 for (i
= 0, hi
= hdw_info
; i
< MAX_BOARDS
; i
++, hi
++)
135 hi
->pci_busno
= 0xff;
142 hi
->addr_mapped
[0] = 0L;
143 hi
->addr_mapped
[1] = 0L;
148 cleanup_ioremap (void)
153 for (i
= 0, hi
= hdw_info
; i
< MAX_BOARDS
; i
++, hi
++)
155 if (hi
->pci_slot
== 0xff)
157 if (hi
->addr_mapped
[0])
159 iounmap ((void *) (hi
->addr_mapped
[0]));
160 release_mem_region ((long) hi
->addr
[0], hi
->len
[0]);
161 hi
->addr_mapped
[0] = 0;
163 if (hi
->addr_mapped
[1])
165 iounmap ((void *) (hi
->addr_mapped
[1]));
166 release_mem_region ((long) hi
->addr
[1], hi
->len
[1]);
167 hi
->addr_mapped
[1] = 0;
179 for (i
= 0, hi
= hdw_info
; i
< MAX_BOARDS
; i
++, hi
++)
181 if (hi
->pci_slot
== 0xff || !hi
->ndev
)
183 c4_stopwd(netdev_priv(hi
->ndev
));
184 #ifdef CONFIG_PROC_FS
185 sbecom_proc_brd_cleanup(netdev_priv(hi
->ndev
));
187 unregister_netdev (hi
->ndev
);
188 free_irq (hi
->pdev
[0]->irq
, hi
->ndev
);
189 #ifdef CONFIG_SBE_PMCC4_NCOMM
190 free_irq (hi
->pdev
[1]->irq
, hi
->ndev
);
198 c4_hdw_init (struct pci_dev
* pdev
, int found
)
203 unsigned char busno
= 0xff;
205 /* our MUSYCC chip supports two functions, 0 & 1 */
206 if ((fun
= PCI_FUNC (pdev
->devfn
)) > 1)
208 pr_warning("unexpected devfun: 0x%x\n", pdev
->devfn
);
211 if (pdev
->bus
) /* obtain bus number */
212 busno
= pdev
->bus
->number
;
214 busno
= 0; /* default for system PCI inconsistency */
215 slot
= pdev
->devfn
& ~0x07;
218 * Functions 0 & 1 for a given board (identified by same bus(busno) and
219 * slot(slot)) are placed into the same 'hardware' structure. The first
220 * part of the board's functionality will be placed into an unpopulated
221 * element, identified by "slot==(0xff)". The second part of a board's
222 * functionality will match the previously loaded slot/busno.
224 for (i
= 0, hi
= hdw_info
; i
< MAX_BOARDS
; i
++, hi
++)
227 * match with board's first found interface, otherwise this is first
230 if ((hi
->pci_slot
== 0xff) || /* new board */
231 ((hi
->pci_slot
== slot
) && (hi
->bus
== pdev
->bus
)))
232 break; /* found for-loop exit */
234 if (i
== MAX_BOARDS
) /* no match in above loop means MAX
237 pr_warning("exceeded number of allowed devices (>%d)?\n", MAX_BOARDS
);
241 hi
->pci_busno
= pdev
->bus
->number
;
243 hi
->pci_busno
= 0; /* default for system PCI inconsistency */
245 pci_read_config_byte (pdev
, PCI_INTERRUPT_PIN
, &hi
->pci_pin
[fun
]);
246 pci_read_config_byte (pdev
, PCI_REVISION_ID
, &hi
->revid
[fun
]);
248 hi
->addr
[fun
] = pci_resource_start (pdev
, 0);
249 hi
->len
[fun
] = pci_resource_end (pdev
, 0) - hi
->addr
[fun
] + 1;
250 hi
->pdev
[fun
] = pdev
;
254 * create device name from module name, plus add the appropriate
257 char *cp
= hi
->devname
;
259 strcpy (cp
, KBUILD_MODNAME
);
260 cp
+= strlen (cp
); /* reposition */
262 *cp
++ = '0' + (found
/ 2); /* there are two found interfaces per
264 *cp
= 0; /* termination */
272 c4hw_attach_all (void)
275 struct pci_dev
*pdev
= NULL
;
280 /*** scan PCI bus for all possible boards */
281 while ((pdev
= pci_get_device (PCI_VENDOR_ID_CONEXANT
,
282 PCI_DEVICE_ID_CN8474
,
285 if (c4_hdw_init (pdev
, found
))
290 pr_warning("No boards found\n");
293 /* sanity check for consistant hardware found */
294 for (i
= 0, hi
= hdw_info
; i
< MAX_BOARDS
; i
++, hi
++)
296 if (hi
->pci_slot
!= 0xff && (!hi
->addr
[0] || !hi
->addr
[1]))
298 pr_warning("%s: something very wrong with pci_get_device\n",
303 /* bring board's memory regions on/line */
304 for (i
= 0, hi
= hdw_info
; i
< MAX_BOARDS
; i
++, hi
++)
306 if (hi
->pci_slot
== 0xff)
308 for (j
= 0; j
< 2; j
++)
310 if (request_mem_region (hi
->addr
[j
], hi
->len
[j
], hi
->devname
) == 0)
312 pr_warning("%s: memory in use, addr=0x%lx, len=0x%lx ?\n",
313 hi
->devname
, hi
->addr
[j
], hi
->len
[j
]);
317 hi
->addr_mapped
[j
] = (unsigned long) ioremap (hi
->addr
[j
], hi
->len
[j
]);
318 if (!hi
->addr_mapped
[j
])
320 pr_warning("%s: ioremap fails, addr=0x%lx, len=0x%lx ?\n",
321 hi
->devname
, hi
->addr
[j
], hi
->len
[j
]);
326 pr_warning("%s: io remapped from phys %x to virt %x\n",
327 hi
->devname
, (u_int32_t
) hi
->addr
[j
], (u_int32_t
) hi
->addr_mapped
[j
]);
332 drvr_state
= SBE_DRVR_AVAILABLE
;
334 /* Have now memory mapped all boards. Now allow board's access to system */
335 for (i
= 0, hi
= hdw_info
; i
< MAX_BOARDS
; i
++, hi
++)
337 if (hi
->pci_slot
== 0xff)
339 if (pci_enable_device (hi
->pdev
[0]) ||
340 pci_enable_device (hi
->pdev
[1]))
342 drvr_state
= SBE_DRVR_DOWN
;
343 pr_warning("%s: failed to enable card %d slot %d\n",
344 hi
->devname
, i
, hi
->pci_slot
);
349 pci_set_master (hi
->pdev
[0]);
350 pci_set_master (hi
->pdev
[1]);
351 if (!(hi
->ndev
= c4_add_dev (hi
, i
, (long) hi
->addr_mapped
[0],
352 (long) hi
->addr_mapped
[1],
356 drvr_state
= SBE_DRVR_DOWN
;
358 /* NOTE: c4_add_dev() does its own device cleanup */
359 return error_flag
; /* error_flag set w/in add_dev() */
361 show_two (hi
, i
); /* displays found information */
366 /*** End-of-File ***/