hwprobe.c 12 KB

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