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 40extern int log_level; 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 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 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 116 if ((hi->promfmt = pmc_verify_cksum (&hi->mfg_info.data)) == PROM_FORMAT_Unk) 117 { 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; 122 } else 123 hi->mfg_info_sts = EEPROM_OK; 124} 125 126 127void __init 128prep_hdw_info (void) 129{ 130 hdw_info_t *hi; 131 int i; 132 133 for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) 134 { 135 hi->pci_busno = 0xff; 136 hi->pci_slot = 0xff; 137 hi->pci_pin[0] = 0; 138 hi->pci_pin[1] = 0; 139 hi->ndev = 0; 140 hi->addr[0] = 0L; 141 hi->addr[1] = 0L; 142 hi->addr_mapped[0] = 0L; 143 hi->addr_mapped[1] = 0L; 144 } 145} 146 147void 148cleanup_ioremap (void) 149{ 150 hdw_info_t *hi; 151 int i; 152 153 for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) 154 { 155 if (hi->pci_slot == 0xff) 156 break; 157 if (hi->addr_mapped[0]) 158 { 159 iounmap ((void *) (hi->addr_mapped[0])); 160 release_mem_region ((long) hi->addr[0], hi->len[0]); 161 hi->addr_mapped[0] = 0; 162 } 163 if (hi->addr_mapped[1]) 164 { 165 iounmap ((void *) (hi->addr_mapped[1])); 166 release_mem_region ((long) hi->addr[1], hi->len[1]); 167 hi->addr_mapped[1] = 0; 168 } 169 } 170} 171 172 173void 174cleanup_devs (void) 175{ 176 hdw_info_t *hi; 177 int i; 178 179 for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) 180 { 181 if (hi->pci_slot == 0xff || !hi->ndev) 182 break; 183 c4_stopwd(netdev_priv(hi->ndev)); 184#ifdef CONFIG_PROC_FS 185 sbecom_proc_brd_cleanup(netdev_priv(hi->ndev)); 186#endif 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); 191#endif 192 OS_kfree (hi->ndev); 193 } 194} 195 196 197STATIC int __init 198c4_hdw_init (struct pci_dev * pdev, int found) 199{ 200 hdw_info_t *hi; 201 int i; 202 int fun, slot; 203 unsigned char busno = 0xff; 204 205 /* our MUSYCC chip supports two functions, 0 & 1 */ 206 if ((fun = PCI_FUNC (pdev->devfn)) > 1) 207 { 208 pr_warning("unexpected devfun: 0x%x\n", pdev->devfn); 209 return 0; 210 } 211 if (pdev->bus) /* obtain bus number */ 212 busno = pdev->bus->number; 213 else 214 busno = 0; /* default for system PCI inconsistency */ 215 slot = pdev->devfn & ~0x07; 216 217 /* 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. 223 */ 224 for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) 225 { 226 /* 227 * match with board's first found interface, otherwise this is first 228 * found 229 */ 230 if ((hi->pci_slot == 0xff) || /* new board */ 231 ((hi->pci_slot == slot) && (hi->bus == pdev->bus))) 232 break; /* found for-loop exit */ 233 } 234 if (i == MAX_BOARDS) /* no match in above loop means MAX 235 * exceeded */ 236 { 237 pr_warning("exceeded number of allowed devices (>%d)?\n", MAX_BOARDS); 238 return 0; 239 } 240 if (pdev->bus) 241 hi->pci_busno = pdev->bus->number; 242 else 243 hi->pci_busno = 0; /* default for system PCI inconsistency */ 244 hi->pci_slot = slot; 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]); 247 hi->bus = pdev->bus; 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; 251 252 { 253 /* 254 * create device name from module name, plus add the appropriate 255 * board number 256 */ 257 char *cp = hi->devname; 258 259 strcpy (cp, KBUILD_MODNAME); 260 cp += strlen (cp); /* reposition */ 261 *cp++ = '-'; 262 *cp++ = '0' + (found / 2); /* there are two found interfaces per 263 * board */ 264 *cp = 0; /* termination */ 265 } 266 267 return 1; 268} 269 270 271status_t __init 272c4hw_attach_all (void) 273{ 274 hdw_info_t *hi; 275 struct pci_dev *pdev = NULL; 276 int found = 0, i, j; 277 278 error_flag = 0; 279 prep_hdw_info (); 280 /*** scan PCI bus for all possible boards */ 281 while ((pdev = pci_get_device (PCI_VENDOR_ID_CONEXANT, 282 PCI_DEVICE_ID_CN8474, 283 pdev))) 284 { 285 if (c4_hdw_init (pdev, found)) 286 found++; 287 } 288 if (!found) 289 { 290 pr_warning("No boards found\n"); 291 return ENODEV; 292 } 293 /* sanity check for consistant hardware found */ 294 for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) 295 { 296 if (hi->pci_slot != 0xff && (!hi->addr[0] || !hi->addr[1])) 297 { 298 pr_warning("%s: something very wrong with pci_get_device\n", 299 hi->devname); 300 return EIO; 301 } 302 } 303 /* bring board's memory regions on/line */ 304 for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) 305 { 306 if (hi->pci_slot == 0xff) 307 break; 308 for (j = 0; j < 2; j++) 309 { 310 if (request_mem_region (hi->addr[j], hi->len[j], hi->devname) == 0) 311 { 312 pr_warning("%s: memory in use, addr=0x%lx, len=0x%lx ?\n", 313 hi->devname, hi->addr[j], hi->len[j]); 314 cleanup_ioremap (); 315 return ENOMEM; 316 } 317 hi->addr_mapped[j] = (unsigned long) ioremap (hi->addr[j], hi->len[j]); 318 if (!hi->addr_mapped[j]) 319 { 320 pr_warning("%s: ioremap fails, addr=0x%lx, len=0x%lx ?\n", 321 hi->devname, hi->addr[j], hi->len[j]); 322 cleanup_ioremap (); 323 return ENOMEM; 324 } 325#ifdef SBE_MAP_DEBUG 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]); 328#endif 329 } 330 } 331 332 drvr_state = SBE_DRVR_AVAILABLE; 333 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++) 336 { 337 if (hi->pci_slot == 0xff) 338 break; 339 if (pci_enable_device (hi->pdev[0]) || 340 pci_enable_device (hi->pdev[1])) 341 { 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); 345 cleanup_devs (); 346 cleanup_ioremap (); 347 return EIO; 348 } 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], 353 hi->pdev[0]->irq, 354 hi->pdev[1]->irq))) 355 { 356 drvr_state = SBE_DRVR_DOWN; 357 cleanup_ioremap (); 358 /* NOTE: c4_add_dev() does its own device cleanup */ 359 return error_flag; /* error_flag set w/in add_dev() */ 360 } 361 show_two (hi, i); /* displays found information */ 362 } 363 return 0; 364} 365 366/*** End-of-File ***/ 367