/pcn/src/pcn.c

https://bitbucket.org/0xffea/driver-gate · C · 1748 lines · 1288 code · 337 blank · 123 comment · 204 complexity · 16530b3e839acff0e00f58e39f0a076f MD5 · raw file

  1. /*
  2. * Copyright (c) 2000 Berkeley Software Design, Inc.
  3. * Copyright (c) 1997, 1998, 1999, 2000
  4. * Bill Paul <wpaul@osd.bsdi.com>. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. All advertising materials mentioning features or use of this software
  15. * must display the following acknowledgement:
  16. * This product includes software developed by Bill Paul.
  17. * 4. Neither the name of the author nor the names of any co-contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
  25. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  26. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  27. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  28. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  29. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  30. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  31. * THE POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. #include <sys/varargs.h>
  34. #include <sys/types.h>
  35. #include <sys/modctl.h>
  36. #include <sys/devops.h>
  37. #include <sys/stream.h>
  38. #include <sys/strsun.h>
  39. #include <sys/cmn_err.h>
  40. #include <sys/ethernet.h>
  41. #include <sys/kmem.h>
  42. #include <sys/crc32.h>
  43. #include <sys/mii.h>
  44. #include <sys/miiregs.h>
  45. #include <sys/mac.h>
  46. #include <sys/mac_ether.h>
  47. #include <sys/ddi.h>
  48. #include <sys/sunddi.h>
  49. #include <sys/vlan.h>
  50. #include <sys/pci.h>
  51. #include <sys/conf.h>
  52. #include "pcn.h"
  53. #include "pcnimpl.h"
  54. #define ETHERVLANMTU (ETHERMAX + 4)
  55. #define CSR_WRITE_4(pcnp, reg, val) \
  56. ddi_put32(pcnp->pcn_regshandle, (uint32_t *)(pcnp->pcn_regs + reg), val)
  57. #define CSR_WRITE_2(pcnp, reg, val) \
  58. ddi_put16(pcnp->pcn_regshandle, (uint16_t *)(pcnp->pcn_regs + reg), val)
  59. #define CSR_READ_4(pcnp, reg) \
  60. ddi_get32(pcnp->pcn_regshandle, (uint32_t *)(pcnp->pcn_regs + reg))
  61. #define CSR_READ_2(pcnp, reg) \
  62. ddi_get16(pcnp->pcn_regshandle, (uint16_t *)(pcnp->pcn_regs + reg))
  63. #define PCN_CSR_SETBIT(pcnp, reg, x) \
  64. pcn_csr_write(pcnp, reg, pcn_csr_read(pcnp, reg) | (x))
  65. #define PCN_CSR_CLRBIT(pcnp, reg, x) \
  66. pcn_csr_write(pcnp, reg, pcn_csr_read(pcnp, reg) & ~(x))
  67. #define PCN_BCR_SETBIT(pncp, reg, x) \
  68. pcn_bcr_write(pcnp, reg, pcn_bcr_read(pcnp, reg) | (x))
  69. #define PCN_BCR_CLRBIT(pcnp, reg, x) \
  70. pcn_bcr_write(pcnp, reg, pcn_bcr_read(pcnp, reg) & ~(x))
  71. static int pcn_attach(dev_info_t *, ddi_attach_cmd_t);
  72. static int pcn_detach(dev_info_t *, ddi_detach_cmd_t);
  73. static int pcn_resume(dev_info_t *);
  74. static int pcn_quiesce(dev_info_t *);
  75. static int pcn_setup_intr(pcn_t *);
  76. static int pcn_teardown_intr(pcn_t *);
  77. static int pcn_m_unicast(void *, const uint8_t *);
  78. static int pcn_m_multicast(void *, boolean_t, const uint8_t *);
  79. static int pcn_m_promisc(void *, boolean_t);
  80. static mblk_t *pcn_m_tx(void *, mblk_t *);
  81. static void pcn_m_ioctl(void *, queue_t *, mblk_t *);
  82. static int pcn_m_stat(void *, uint_t, uint64_t *);
  83. static int pcn_m_start(void *);
  84. static void pcn_m_stop(void *);
  85. static int pcn_m_getprop(void *, const char *, mac_prop_id_t, uint_t,
  86. uint_t, void *, uint_t *);
  87. static int pcn_m_setprop(void *, const char *, mac_prop_id_t, uint_t,
  88. const void *);
  89. static unsigned pcn_intr(caddr_t, caddr_t);
  90. static uint16_t pcn_mii_read(void *, uint8_t, uint8_t);
  91. static void pcn_mii_write(void *, uint8_t, uint8_t, uint16_t);
  92. static void pcn_mii_notify(void *, link_state_t);
  93. static uint32_t pcn_csr_read(pcn_t *, uint32_t);
  94. static uint16_t pcn_csr_read16(pcn_t *, uint32_t);
  95. static void pcn_csr_write(pcn_t *, uint32_t, uint32_t);
  96. static uint32_t pcn_bcr_read(pcn_t *, uint32_t);
  97. static uint16_t pcn_bcr_read16(pcn_t *, uint32_t);
  98. static void pcn_bcr_write(pcn_t *, uint32_t, uint32_t);
  99. static boolean_t pcn_send(pcn_t *, mblk_t *);
  100. static int pcn_allocrxring(pcn_t *);
  101. static int pcn_alloctxring(pcn_t *);
  102. static void pcn_freetxring(pcn_t *);
  103. static void pcn_freerxring(pcn_t *);
  104. static void pcn_resetrings(pcn_t *);
  105. static int pcn_initialize(pcn_t *);
  106. static void pcn_enableinterrupts(pcn_t *);
  107. static void pcn_disableinterrupts(pcn_t *);
  108. static mblk_t *pcn_receive(pcn_t *);
  109. static void pcn_resetall(pcn_t *);
  110. static void pcn_startall(pcn_t *);
  111. static void pcn_stopall(pcn_t *);
  112. static void pcn_reclaim(pcn_t *);
  113. static void pcn_setrxfilt(pcn_t *);
  114. static void pcn_getfactaddr(pcn_t *);
  115. static int pcn_set_chipid(pcn_t *, uint32_t);
  116. static const pcn_type_t *pcn_match(uint16_t, uint16_t);
  117. static char *pcn_chipid_name(uint32_t);
  118. static void pcn_error(dev_info_t *, char *, ...);
  119. void *pcn_ssp = NULL;
  120. static uchar_t pcn_broadcast[ETHERADDRL] = {
  121. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
  122. };
  123. static const pcn_type_t pcn_devs[] = {
  124. { PCN_VENDORID, PCN_DEVICEID_PCNET, "AMD PCnet/PCI 10/100BaseTX" },
  125. { PCN_VENDORID, PCN_DEVICEID_HOME, "AMD PCnet/Home HomePNA" },
  126. { 0, 0, NULL }
  127. };
  128. static const struct pcn_chipid {
  129. uint32_t id;
  130. char *name;
  131. } pcn_chipid[] = {
  132. { Am79C971, "Am79C971" },
  133. { Am79C972, "Am79C972" },
  134. { Am79C973, "Am79C973" },
  135. { Am79C978, "Am79C978" },
  136. { Am79C975, "Am79C975" },
  137. { Am79C976, "Am79C976" },
  138. { 0, NULL },
  139. };
  140. static mii_ops_t pcn_mii_ops = {
  141. MII_OPS_VERSION,
  142. pcn_mii_read,
  143. pcn_mii_write,
  144. pcn_mii_notify,
  145. NULL
  146. };
  147. static mac_callbacks_t pcn_m_callbacks = {
  148. MC_IOCTL | MC_SETPROP | MC_GETPROP,
  149. pcn_m_stat,
  150. pcn_m_start,
  151. pcn_m_stop,
  152. pcn_m_promisc,
  153. pcn_m_multicast,
  154. pcn_m_unicast,
  155. pcn_m_tx,
  156. pcn_m_ioctl,
  157. NULL, /* mc_getcapab */
  158. NULL, /* mc_open */
  159. NULL, /* mc_close */
  160. pcn_m_setprop,
  161. pcn_m_getprop
  162. };
  163. DDI_DEFINE_STREAM_OPS(pcn_devops, nulldev, nulldev, pcn_attach, pcn_detach,
  164. nodev, NULL, D_MP, NULL, pcn_quiesce);
  165. static struct modldrv pcn_modldrv = {
  166. &mod_driverops,
  167. "AMD PCnet",
  168. &pcn_devops
  169. };
  170. static struct modlinkage pcn_modlinkage = {
  171. MODREV_1,
  172. { &pcn_modldrv, NULL }
  173. };
  174. static ddi_device_acc_attr_t pcn_devattr = {
  175. DDI_DEVICE_ATTR_V0,
  176. DDI_STRUCTURE_LE_ACC,
  177. DDI_STRICTORDER_ACC
  178. };
  179. static ddi_device_acc_attr_t pcn_bufattr = {
  180. DDI_DEVICE_ATTR_V0,
  181. DDI_NEVERSWAP_ACC,
  182. DDI_STRICTORDER_ACC
  183. };
  184. static ddi_dma_attr_t pcn_dma_attr = {
  185. DMA_ATTR_V0, /* dm_attr_version */
  186. 0, /* dma_attr_addr_lo */
  187. 0xFFFFFFFFU, /* dma_attr_addr_hi */
  188. 0x7FFFFFFFU, /* dma_attr_count_max */
  189. 4, /* dma_attr_align */
  190. 0x3F, /* dma_attr_burstsizes */
  191. 1, /* dma_attr_minxfer */
  192. 0xFFFFFFFFU, /* dma_attr_maxxfer */
  193. 0xFFFFFFFFU, /* dma_attr_seg */
  194. 1, /* dma_attr_sgllen */
  195. 1, /* dma_attr_granular */
  196. 0 /* dma_attr_flags */
  197. };
  198. static ddi_dma_attr_t pcn_dmadesc_attr = {
  199. DMA_ATTR_V0, /* dm_attr_version */
  200. 0, /* dma_attr_addr_lo */
  201. 0xFFFFFFFFU, /* dma_attr_addr_hi */
  202. 0x7FFFFFFFU, /* dma_attr_count_max */
  203. 16, /* dma_attr_align */
  204. 0x3F, /* dma_attr_burstsizes */
  205. 1, /* dma_attr_minxfer */
  206. 0xFFFFFFFFU, /* dma_attr_maxxfer */
  207. 0xFFFFFFFFU, /* dma_attr_seg */
  208. 1, /* dma_attr_sgllen */
  209. 1, /* dma_attr_granular */
  210. 0 /* dma_attr_flags */
  211. };
  212. /*
  213. * DDI entry points
  214. */
  215. int
  216. _init(void)
  217. {
  218. int rc;
  219. if ((rc = ddi_soft_state_init(&pcn_ssp, sizeof (pcn_t), 1)) != 0)
  220. return (rc);
  221. mac_init_ops(&pcn_devops, "pcn");
  222. if ((rc = mod_install(&pcn_modlinkage)) != DDI_SUCCESS) {
  223. mac_fini_ops(&pcn_devops);
  224. ddi_soft_state_fini(&pcn_ssp);
  225. }
  226. return (rc);
  227. }
  228. int
  229. _fini(void)
  230. {
  231. int rc;
  232. if ((rc = mod_remove(&pcn_modlinkage)) == DDI_SUCCESS) {
  233. mac_fini_ops(&pcn_devops);
  234. ddi_soft_state_fini(&pcn_ssp);
  235. }
  236. return (rc);
  237. }
  238. int
  239. _info(struct modinfo *modinfop)
  240. {
  241. return (mod_info(&pcn_modlinkage, modinfop));
  242. }
  243. int
  244. pcn_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
  245. {
  246. pcn_t *pcnp;
  247. mac_register_t *macp;
  248. const pcn_type_t *pcn_type;
  249. int instance = ddi_get_instance(dip);
  250. int rc;
  251. ddi_acc_handle_t pci;
  252. uint32_t chipid;
  253. uint16_t venid;
  254. uint16_t devid;
  255. uint16_t svid;
  256. uint16_t ssid;
  257. uint16_t cachesize;
  258. switch (cmd) {
  259. case DDI_RESUME:
  260. return (pcn_resume(dip));
  261. case DDI_ATTACH:
  262. break;
  263. default:
  264. return (DDI_FAILURE);
  265. }
  266. if (ddi_slaveonly(dip) == DDI_SUCCESS) {
  267. pcn_error(dip, "slot does not support PCI bus-master");
  268. return (DDI_FAILURE);
  269. }
  270. if (ddi_intr_hilevel(dip, 0) != 0) {
  271. pcn_error(dip, "hilevel interrupts not supported");
  272. return (DDI_FAILURE);
  273. }
  274. if (pci_config_setup(dip, &pci) != DDI_SUCCESS) {
  275. pcn_error(dip, "unable to setup PCI config handle");
  276. return (DDI_FAILURE);
  277. }
  278. venid = pci_config_get16(pci, PCI_CONF_VENID);
  279. devid = pci_config_get16(pci, PCI_CONF_DEVID);
  280. svid = pci_config_get16(pci, PCI_CONF_SUBVENID);
  281. ssid = pci_config_get16(pci, PCI_CONF_SUBSYSID);
  282. if ((pcn_type = pcn_match(venid, devid)) == NULL) {
  283. pci_config_teardown(&pci);
  284. pcn_error(dip, "Unable to identify PCI card");
  285. return (DDI_FAILURE);
  286. }
  287. if (ddi_prop_update_string(DDI_DEV_T_NONE, dip, "model",
  288. pcn_type->pcn_name) != DDI_PROP_SUCCESS) {
  289. pci_config_teardown(&pci);
  290. pcn_error(dip, "Unable to create model property");
  291. return (DDI_FAILURE);
  292. }
  293. cachesize = pci_config_get8(pci, PCI_CONF_CACHE_LINESZ);
  294. if (ddi_soft_state_zalloc(pcn_ssp, instance) != DDI_SUCCESS) {
  295. pcn_error(dip, "Unable to allocate soft state");
  296. pci_config_teardown(&pci);
  297. return (DDI_FAILURE);
  298. }
  299. pcnp = ddi_get_soft_state(pcn_ssp, instance);
  300. pcnp->pcn_dip = dip;
  301. pcnp->pcn_instance = instance;
  302. if (pcn_setup_intr(pcnp) != DDI_SUCCESS) {
  303. ddi_soft_state_free(pcn_ssp, instance);
  304. pci_config_teardown(&pci);
  305. return (DDI_FAILURE);
  306. }
  307. mutex_init(&pcnp->pcn_xmtlock, NULL, MUTEX_DRIVER,
  308. DDI_INTR_PRI(pcnp->pcn_int_pri));
  309. mutex_init(&pcnp->pcn_intrlock, NULL, MUTEX_DRIVER,
  310. DDI_INTR_PRI(pcnp->pcn_int_pri));
  311. /*
  312. * Enable bus master, IO space, and memory space accesses
  313. */
  314. pci_config_put16(pci, PCI_CONF_COMM,
  315. pci_config_get16(pci, PCI_CONF_COMM) | PCI_COMM_ME | PCI_COMM_MAE);
  316. pci_config_teardown(&pci);
  317. if ((pcnp->pcn_mii = mii_alloc(pcnp, dip, &pcn_mii_ops)) == NULL)
  318. goto fail;
  319. mii_set_pauseable(pcnp->pcn_mii, B_TRUE, B_TRUE);
  320. if (ddi_regs_map_setup(dip, 1, (caddr_t *)&pcnp->pcn_regs, 0, 0,
  321. &pcn_devattr, &pcnp->pcn_regshandle)) {
  322. pcn_error(dip, "ddi_regs_map_setup failed");
  323. goto fail;
  324. }
  325. if (pcn_set_chipid(pcnp, (uint32_t)ssid << 16 | (uint32_t)svid) !=
  326. DDI_SUCCESS) {
  327. goto fail;
  328. }
  329. if ((pcn_allocrxring(pcnp) != DDI_SUCCESS) ||
  330. (pcn_alloctxring(pcnp) != DDI_SUCCESS)) {
  331. pcn_error(dip, "unable to allocate DMA resources");
  332. goto fail;
  333. }
  334. mutex_enter(&pcnp->pcn_intrlock);
  335. mutex_enter(&pcnp->pcn_xmtlock);
  336. rc = pcn_initialize(pcnp);
  337. mutex_exit(&pcnp->pcn_xmtlock);
  338. mutex_exit(&pcnp->pcn_intrlock);
  339. if (rc != DDI_SUCCESS)
  340. goto fail;
  341. pcn_getfactaddr(pcnp);
  342. pcnp->pcn_promisc = B_FALSE;
  343. (void) pcn_m_unicast(pcnp, pcnp->pcn_addr);
  344. /* XXX: do we need to add the broadcast addr to the addr filter? */
  345. if ((rc = ddi_intr_add_handler(pcnp->pcn_htable, pcn_intr,
  346. (caddr_t)pcnp, NULL)) != DDI_SUCCESS) {
  347. pcn_error(pcnp->pcn_dip, "failed to add interrupt handler");
  348. return (DDI_FAILURE);
  349. }
  350. if (ddi_intr_enable(pcnp->pcn_htable) != DDI_SUCCESS) {
  351. pcn_error(pcnp->pcn_dip, "failed to enable interrupt");
  352. goto fail;
  353. }
  354. if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
  355. pcn_error(pcnp->pcn_dip, "mac_alloc failed");
  356. goto fail;
  357. }
  358. macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
  359. macp->m_driver = pcnp;
  360. macp->m_dip = dip;
  361. macp->m_src_addr = pcnp->pcn_addr;
  362. macp->m_callbacks = &pcn_m_callbacks;
  363. macp->m_min_sdu = 0;
  364. macp->m_max_sdu = ETHERMTU;
  365. macp->m_margin = VLAN_TAGSZ;
  366. if (mac_register(macp, &pcnp->pcn_mh) == DDI_SUCCESS) {
  367. mac_free(macp);
  368. ddi_report_dev(dip);
  369. return (DDI_SUCCESS);
  370. }
  371. mac_free(macp);
  372. fail:
  373. ddi_intr_free(pcnp->pcn_htable);
  374. ddi_soft_state_free(pcn_ssp, instance);
  375. return (DDI_FAILURE);
  376. }
  377. static int
  378. pcn_set_chipid(pcn_t *pcnp, uint32_t conf_id)
  379. {
  380. uint32_t chipid;
  381. /*
  382. * Note: we can *NOT* put the chip into
  383. * 32-bit mode yet. The le(4) driver will only
  384. * work in 16-bit mode, and once the chip
  385. * goes into 32-bit mode, the only way to
  386. * get it out again is with a hardware reset.
  387. * So if pcn_probe() is called before the
  388. * le(4) driver's probe routine, the chip will
  389. * be locked into 32-bit operation and the
  390. * le(4) driver will be unable to attach to it.
  391. * Note II: if the chip happens to already
  392. * be in 32-bit mode, we still need to check
  393. * the chip ID, but first we have to detect
  394. * 32-bit mode using only 16-bit operations.
  395. * The safest way to do this is to read the
  396. * PCI subsystem ID from BCR23/24 and compare
  397. * that with the value read from PCI config
  398. * space.
  399. */
  400. chipid = pcn_bcr_read16(pcnp, PCN_BCR_PCISUBSYSID);
  401. chipid <<= 16;
  402. chipid |= pcn_bcr_read16(pcnp, PCN_BCR_PCISUBVENID);
  403. /*
  404. * Note III: the test for 0x10001000 is a hack to
  405. * pacify VMware, who's pseudo-PCnet interface is
  406. * broken. Reading the subsystem register from PCI
  407. * config space yields 0x00000000 while reading the
  408. * same value from I/O space yields 0x10001000. It's
  409. * not supposed to be that way.
  410. */
  411. if (chipid == conf_id || chipid == 0x10001000) {
  412. /* We're in 16-bit mode. */
  413. chipid = pcn_csr_read16(pcnp, PCN_CSR_CHIPID1);
  414. chipid <<= 16;
  415. chipid |= pcn_csr_read16(pcnp, PCN_CSR_CHIPID0);
  416. } else {
  417. chipid = pcn_csr_read(pcnp, PCN_CSR_CHIPID1);
  418. chipid <<= 16;
  419. chipid |= pcn_csr_read(pcnp, PCN_CSR_CHIPID0);
  420. }
  421. switch ((chipid >> 12) & PART_MASK) {
  422. case Am79C971:
  423. case Am79C972:
  424. case Am79C973:
  425. case Am79C975:
  426. case Am79C976:
  427. case Am79C978:
  428. break;
  429. default:
  430. pcn_error(pcnp->pcn_dip, "Unknown chip id 0x%u",
  431. (chipid >> 12) & PART_MASK);
  432. return (DDI_FAILURE);
  433. }
  434. if (ddi_prop_update_string(DDI_DEV_T_NONE, pcnp->pcn_dip, "chipid",
  435. pcn_chipid_name(chipid)) != DDI_SUCCESS) {
  436. pcn_error(pcnp->pcn_dip, "Unable to set chipid property");
  437. return (DDI_FAILURE);
  438. }
  439. return (DDI_SUCCESS);
  440. }
  441. static int
  442. pcn_setup_intr(pcn_t *pcnp)
  443. {
  444. int int_types, int_count, int_actual, int_avail;
  445. int i, rc;
  446. if ((rc = ddi_intr_get_supported_types(pcnp->pcn_dip, &int_types)) !=
  447. DDI_SUCCESS) {
  448. pcn_error(pcnp->pcn_dip, "unable to get supported interrupt "
  449. "types");
  450. return (DDI_FAILURE);
  451. }
  452. if ((int_types & DDI_INTR_TYPE_FIXED) == 0) {
  453. pcn_error(pcnp->pcn_dip, "fixed interrupts are not supported");
  454. return (DDI_FAILURE);
  455. }
  456. if ((rc = ddi_intr_get_nintrs(pcnp->pcn_dip, DDI_INTR_TYPE_FIXED,
  457. &int_count)) != DDI_SUCCESS) {
  458. pcn_error(pcnp->pcn_dip, "unable to obtain the number of "
  459. "interrupts");
  460. return (DDI_FAILURE);
  461. }
  462. if (int_count != 1) {
  463. pcn_error(pcnp->pcn_dip, "interrupt count is %d, expected 1",
  464. int_count);
  465. return (DDI_FAILURE);
  466. }
  467. rc = ddi_intr_get_navail(pcnp->pcn_dip, DDI_INTR_TYPE_FIXED, &int_avail);
  468. if ((rc != DDI_SUCCESS) || (int_avail == 0)) {
  469. pcn_error(pcnp->pcn_dip, "ddi_intr_get_avail failed");
  470. return (DDI_FAILURE);
  471. }
  472. rc = ddi_intr_alloc(pcnp->pcn_dip, &pcnp->pcn_htable, DDI_INTR_TYPE_FIXED, 0,
  473. int_count, &int_actual, DDI_INTR_ALLOC_STRICT);
  474. if ((rc != DDI_SUCCESS) || (int_actual != int_count)) {
  475. pcn_error(pcnp->pcn_dip, "unable to allocate fixed interrupt!");
  476. return (DDI_FAILURE);
  477. }
  478. if ((rc = ddi_intr_get_pri(pcnp->pcn_htable, &pcnp->pcn_int_pri)) !=
  479. DDI_SUCCESS) {
  480. pcn_error(pcnp->pcn_dip, "unable to obtain interrupt priority");
  481. ddi_intr_free(pcnp->pcn_htable);
  482. return (DDI_FAILURE);
  483. }
  484. return (DDI_SUCCESS);
  485. }
  486. int
  487. pcn_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
  488. {
  489. pcn_t *pcnp;
  490. pcnp = ddi_get_soft_state(pcn_ssp, ddi_get_instance(dip));
  491. if (pcnp == NULL) {
  492. pcn_error(dip, "no soft state in detach!");
  493. return (DDI_FAILURE);
  494. }
  495. switch (cmd) {
  496. case DDI_DETACH:
  497. if (mac_unregister(pcnp->pcn_mh) != 0)
  498. return (DDI_FAILURE);
  499. mutex_enter(&pcnp->pcn_intrlock);
  500. mutex_enter(&pcnp->pcn_xmtlock);
  501. pcnp->pcn_flags &= ~PCN_RUNNING;
  502. pcn_stopall(pcnp);
  503. mutex_exit(&pcnp->pcn_xmtlock);
  504. mutex_exit(&pcnp->pcn_intrlock);
  505. ddi_intr_remove_handler(pcnp->pcn_htable);
  506. ddi_intr_free(pcnp->pcn_htable);
  507. mii_free(pcnp->pcn_mii);
  508. ddi_prop_remove_all(dip);
  509. pcn_freerxring(pcnp);
  510. pcn_freetxring(pcnp);
  511. ddi_regs_map_free(&pcnp->pcn_regshandle);
  512. mutex_destroy(&pcnp->pcn_intrlock);
  513. mutex_destroy(&pcnp->pcn_xmtlock);
  514. ddi_soft_state_free(pcn_ssp, ddi_get_instance(dip));
  515. return (DDI_SUCCESS);
  516. case DDI_SUSPEND:
  517. mii_suspend(pcnp->pcn_mii);
  518. mutex_enter(&pcnp->pcn_intrlock);
  519. mutex_enter(&pcnp->pcn_xmtlock);
  520. pcnp->pcn_flags |= PCN_SUSPENDED;
  521. pcn_stopall(pcnp);
  522. mutex_exit(&pcnp->pcn_xmtlock);
  523. mutex_exit(&pcnp->pcn_intrlock);
  524. return (DDI_SUCCESS);
  525. default:
  526. return (DDI_FAILURE);
  527. }
  528. }
  529. int
  530. pcn_resume(dev_info_t *dip)
  531. {
  532. pcn_t *pcnp;
  533. pcnp = ddi_get_soft_state(pcn_ssp, ddi_get_instance(dip));
  534. if (pcnp == NULL)
  535. return (DDI_FAILURE);
  536. mutex_enter(&pcnp->pcn_intrlock);
  537. mutex_enter(&pcnp->pcn_xmtlock);
  538. pcnp->pcn_flags &= ~PCN_SUSPENDED;
  539. if (!pcn_initialize(pcnp)) {
  540. pcn_error(pcnp->pcn_dip, "unable to resume chip");
  541. pcnp->pcn_flags |= PCN_SUSPENDED;
  542. mutex_exit(&pcnp->pcn_intrlock);
  543. mutex_exit(&pcnp->pcn_xmtlock);
  544. return (DDI_SUCCESS);
  545. }
  546. if (pcnp->pcn_flags & PCN_RUNNING)
  547. pcn_startall(pcnp);
  548. mutex_exit(&pcnp->pcn_xmtlock);
  549. mutex_exit(&pcnp->pcn_intrlock);
  550. mii_resume(pcnp->pcn_mii);
  551. return (DDI_SUCCESS);
  552. }
  553. int
  554. pcn_quiesce(dev_info_t *dip)
  555. {
  556. pcn_t *pcnp;
  557. pcnp = ddi_get_soft_state(pcn_ssp, ddi_get_instance(dip));
  558. if (pcnp == NULL)
  559. return (DDI_FAILURE);
  560. /*
  561. * First suspend the chip, this should drain anything in
  562. * in progress.
  563. */
  564. PCN_CSR_SETBIT(pcnp, PCN_CSR_EXTCTL1, PCN_EXTCTL1_SPND);
  565. /* wait a reasonable amount of time for suspend to finish */
  566. drv_usecwait(RESET_DELAY);
  567. /* abrupt stop */
  568. PCN_CSR_SETBIT(pcnp, PCN_CSR_CSR, PCN_CSR_STOP);
  569. return (DDI_SUCCESS);
  570. }
  571. static void
  572. pcn_setrxfilt(pcn_t *pcnp)
  573. {
  574. int i;
  575. if (pcnp->pcn_flags & PCN_SUSPENDED)
  576. return;
  577. /* temporairly suspend card */
  578. PCN_CSR_SETBIT(pcnp, PCN_CSR_EXTCTL1, PCN_EXTCTL1_SPND);
  579. /* set promiscuous mode */
  580. if (pcnp->pcn_promisc)
  581. PCN_CSR_SETBIT(pcnp, PCN_CSR_MODE, PCN_MODE_PROMISC);
  582. else
  583. PCN_CSR_CLRBIT(pcnp, PCN_CSR_MODE, PCN_MODE_PROMISC);
  584. /* program mac address */
  585. pcn_csr_write(pcnp, PCN_CSR_PAR0,
  586. pcnp->pcn_addr[0] << 8 | pcnp->pcn_addr[1]);
  587. pcn_csr_write(pcnp, PCN_CSR_PAR1,
  588. pcnp->pcn_addr[2] << 8 | pcnp->pcn_addr[2]);
  589. pcn_csr_write(pcnp, PCN_CSR_PAR2,
  590. pcnp->pcn_addr[4] << 8 | pcnp->pcn_addr[5]);
  591. /*
  592. * program multicast filter
  593. * I'm not sure if this is absolutely necessary, but it appears that
  594. * the freebsd driver sets the filter to all 1's when in promiscuous
  595. * mode, so we follow suit.
  596. */
  597. for (i = 0; i < 4; i++)
  598. pcn_csr_write(pcnp, PCN_CSR_MAR0 + i,
  599. pcnp->pcn_promisc ? 0xffff : pcnp->pcn_mctab[i]);
  600. /* reenable card */
  601. PCN_CSR_CLRBIT(pcnp, PCN_CSR_EXTCTL1, PCN_EXTCTL1_SPND);
  602. }
  603. static int
  604. pcn_m_multicast(void *arg, boolean_t add, const uint8_t *macaddr)
  605. {
  606. pcn_t *pcnp = (pcn_t *)arg;
  607. int index;
  608. uint32_t crc;
  609. uint32_t bit;
  610. uint32_t newval, oldval;
  611. /*
  612. * PCNet uses the upper 6 bits of the CRC of the macaddr
  613. * to index into a 64bit mask
  614. */
  615. CRC32(crc, macaddr, ETHERADDRL, -1U, crc32_table);
  616. crc = crc >> 26;
  617. index = crc / 16;
  618. bit = (1 << (crc % 16));
  619. mutex_enter(&pcnp->pcn_intrlock);
  620. mutex_enter(&pcnp->pcn_xmtlock);
  621. newval = oldval = pcnp->pcn_mctab[index];
  622. if (add) {
  623. pcnp->pcn_mccount[crc]++;
  624. if (pcnp->pcn_mccount[crc] == 1)
  625. newval |= bit;
  626. } else {
  627. pcnp->pcn_mccount[crc]--;
  628. if (pcnp->pcn_mccount[crc] == 0)
  629. newval &= ~bit;
  630. }
  631. if (newval != oldval) {
  632. pcnp->pcn_mctab[index] = newval;
  633. pcn_setrxfilt(pcnp);
  634. }
  635. mutex_exit(&pcnp->pcn_xmtlock);
  636. mutex_exit(&pcnp->pcn_intrlock);
  637. return (0);
  638. }
  639. static int
  640. pcn_m_promisc(void *arg, boolean_t on)
  641. {
  642. pcn_t *pcnp = (pcn_t *)arg;
  643. mutex_enter(&pcnp->pcn_intrlock);
  644. mutex_enter(&pcnp->pcn_xmtlock);
  645. pcnp->pcn_promisc = on;
  646. pcn_setrxfilt(pcnp);
  647. mutex_exit(&pcnp->pcn_xmtlock);
  648. mutex_exit(&pcnp->pcn_intrlock);
  649. return (0);
  650. }
  651. static int
  652. pcn_m_unicast(void *arg, const uint8_t *macaddr)
  653. {
  654. pcn_t *pcnp = (pcn_t *)arg;
  655. mutex_enter(&pcnp->pcn_intrlock);
  656. mutex_enter(&pcnp->pcn_xmtlock);
  657. bcopy(macaddr, pcnp->pcn_addr, ETHERADDRL);
  658. pcn_setrxfilt(pcnp);
  659. mutex_exit(&pcnp->pcn_xmtlock);
  660. mutex_exit(&pcnp->pcn_intrlock);
  661. return (0);
  662. }
  663. static mblk_t *
  664. pcn_m_tx(void *arg, mblk_t *mp)
  665. {
  666. pcn_t *pcnp = (pcn_t *)arg;
  667. mblk_t *nmp;
  668. mutex_enter(&pcnp->pcn_xmtlock);
  669. if (pcnp->pcn_flags & PCN_SUSPENDED) {
  670. while ((nmp = mp) != NULL) {
  671. pcnp->pcn_carrier_errors++;
  672. mp = mp->b_next;
  673. freemsg(nmp);
  674. }
  675. mutex_exit(&pcnp->pcn_xmtlock);
  676. return (NULL);
  677. }
  678. while (mp != NULL) {
  679. nmp = mp->b_next;
  680. mp->b_next = NULL;
  681. if (!pcn_send(pcnp, mp)) {
  682. mp->b_next = nmp;
  683. break;
  684. }
  685. mp = nmp;
  686. }
  687. mutex_exit(&pcnp->pcn_xmtlock);
  688. return (mp);
  689. }
  690. static boolean_t
  691. pcn_send(pcn_t *pcnp, mblk_t *mp)
  692. {
  693. size_t len;
  694. pcn_buf_t *txb;
  695. pcn_tx_desc_t *tmd;
  696. int txsend;
  697. ASSERT(mutex_owned(&pcnp->pcn_xmtlock));
  698. ASSERT(mp != NULL);
  699. len = msgsize(mp);
  700. if (len > ETHERVLANMTU) {
  701. pcnp->pcn_macxmt_errors++;
  702. freemsg(mp);
  703. return (B_TRUE);
  704. }
  705. if (pcnp->pcn_txavail < PCN_TXRECLAIM)
  706. pcn_reclaim(pcnp);
  707. if (pcnp->pcn_txavail == 0) {
  708. pcnp->pcn_wantw = B_TRUE;
  709. pcn_enableinterrupts(pcnp);
  710. return (B_FALSE);
  711. }
  712. txsend = pcnp->pcn_txsend;
  713. txb = pcnp->pcn_txbufs[txsend];
  714. mcopymsg(mp, txb->pb_buf); /* frees mp! */
  715. pcnp->pcn_opackets++;
  716. pcnp->pcn_obytes += len;
  717. if (txb->pb_buf[0] & 0x1) {
  718. if (bcmp(txb->pb_buf, pcn_broadcast, ETHERADDRL) != 0)
  719. pcnp->pcn_multixmt++;
  720. else
  721. pcnp->pcn_brdcstxmt++;
  722. }
  723. SYNCBUF(txb, len, DDI_DMA_SYNC_FORDEV);
  724. tmd = &pcnp->pcn_txdescp[txsend];
  725. tmd->pcn_tbaddr = txb->pb_paddr;
  726. tmd->pcn_txctl = PCN_TXCTL_STP|PCN_TXCTL_ENP|PCN_TXCTL_ADD_FCS|
  727. PCN_TXCTL_MORE_LTINT|0xf000;
  728. /* PCNet wants the 2's complement of the length of the buffer */
  729. tmd->pcn_txctl |= (~(len) + 1) & PCN_TXCTL_BUFSZ;
  730. /* Spec suggests this should be set last */
  731. tmd->pcn_txctl |= PCN_TXCTL_OWN;
  732. SYNCTXDESC(pcnp, txsend, DDI_DMA_SYNC_FORDEV);
  733. pcnp->pcn_txavail--;
  734. pcnp->pcn_txsend = (txsend + 1) % PCN_TXRING;
  735. pcnp->pcn_txstall_time = gethrtime() + (5 * 1000000000ULL);
  736. pcn_csr_write(pcnp, PCN_CSR_CSR, PCN_CSR_TX|PCN_CSR_INTEN);
  737. return (B_TRUE);
  738. }
  739. static void
  740. pcn_reclaim(pcn_t *pcnp)
  741. {
  742. pcn_tx_desc_t *tmdp;
  743. while (pcnp->pcn_txavail != PCN_TXRING) {
  744. int index = pcnp->pcn_txreclaim;
  745. tmdp = &pcnp->pcn_txdescp[index];
  746. /* sync before reading */
  747. SYNCTXDESC(pcnp, index, DDI_DMA_SYNC_FORKERNEL);
  748. /* check if chip is still working on it */
  749. if (tmdp->pcn_txctl & PCN_TXCTL_OWN)
  750. break;
  751. pcnp->pcn_txavail++;
  752. pcnp->pcn_txreclaim = (index + 1) % PCN_TXRING;
  753. }
  754. if (pcnp->pcn_txavail >= PCN_TXRESCHED)
  755. if (pcnp->pcn_wantw) {
  756. pcnp->pcn_wantw = B_FALSE;
  757. pcn_enableinterrupts(pcnp);
  758. mac_tx_update(pcnp->pcn_mh);
  759. }
  760. }
  761. static unsigned
  762. pcn_intr(caddr_t arg1, caddr_t arg2)
  763. {
  764. pcn_t *pcnp = (pcn_t *)arg1;
  765. mblk_t *mp = NULL;
  766. uint32_t status;
  767. boolean_t do_reset = B_FALSE;
  768. mutex_enter(&pcnp->pcn_intrlock);
  769. if (pcnp->pcn_flags & PCN_SUSPENDED) {
  770. mutex_exit(&pcnp->pcn_intrlock);
  771. return (DDI_INTR_UNCLAIMED);
  772. }
  773. CSR_WRITE_4(pcnp, PCN_IO32_RAP, PCN_CSR_CSR);
  774. while ((status = CSR_READ_4(pcnp, PCN_IO32_RDP)) & PCN_CSR_INTR) {
  775. CSR_WRITE_4(pcnp, PCN_IO32_RDP, status);
  776. if (status & PCN_CSR_TINT) {
  777. mutex_enter(&pcnp->pcn_xmtlock);
  778. pcn_reclaim(pcnp);
  779. mutex_exit(&pcnp->pcn_xmtlock);
  780. }
  781. if (status & PCN_CSR_RINT)
  782. mp = pcn_receive(pcnp);
  783. if (status & PCN_CSR_ERR) {
  784. do_reset = B_TRUE;
  785. break;
  786. }
  787. }
  788. if (do_reset) {
  789. mutex_enter(&pcnp->pcn_xmtlock);
  790. pcn_resetall(pcnp);
  791. mutex_exit(&pcnp->pcn_xmtlock);
  792. mutex_exit(&pcnp->pcn_intrlock);
  793. mii_reset(pcnp->pcn_mii);
  794. } else {
  795. mutex_exit(&pcnp->pcn_intrlock);
  796. }
  797. if (mp)
  798. mac_rx(pcnp->pcn_mh, NULL, mp);
  799. return (DDI_INTR_CLAIMED);
  800. }
  801. static mblk_t *
  802. pcn_receive(pcn_t *pcnp)
  803. {
  804. uint32_t len;
  805. pcn_buf_t *rxb;
  806. pcn_rx_desc_t *rmd;
  807. mblk_t *mpchain, **mpp, *mp;
  808. int head, cnt;
  809. mpchain = NULL;
  810. mpp = &mpchain;
  811. head = pcnp->pcn_rxhead;
  812. for (cnt = 0; cnt < PCN_RXRING; cnt++) {
  813. rmd = &pcnp->pcn_rxdescp[head];
  814. rxb = pcnp->pcn_rxbufs[head];
  815. SYNCRXDESC(pcnp, head, DDI_DMA_SYNC_FORKERNEL);
  816. if (rmd->pcn_rxstat & PCN_RXSTAT_OWN)
  817. break;
  818. len = rmd->pcn_rxlen - ETHERFCSL;
  819. if (rmd->pcn_rxstat & PCN_RXSTAT_ERR) {
  820. pcnp->pcn_errrcv++;
  821. if (rmd->pcn_rxstat & PCN_RXSTAT_FRAM)
  822. pcnp->pcn_align_errors++;
  823. if (rmd->pcn_rxstat & PCN_RXSTAT_OFLOW)
  824. pcnp->pcn_overflow++;
  825. if (rmd->pcn_rxstat & PCN_RXSTAT_CRC)
  826. pcnp->pcn_fcs_errors++;
  827. } else if (len > ETHERVLANMTU) {
  828. pcnp->pcn_errrcv++;
  829. pcnp->pcn_toolong_errors++;
  830. } else {
  831. mp = allocb(len + PCN_HEADROOM, 0);
  832. if (mp == NULL) {
  833. pcnp->pcn_errrcv++;
  834. pcnp->pcn_norcvbuf++;
  835. goto skip;
  836. }
  837. SYNCBUF(rxb, len, DDI_DMA_SYNC_FORKERNEL);
  838. mp->b_rptr += PCN_HEADROOM;
  839. mp->b_wptr = mp->b_rptr + len;
  840. bcopy((char *)rxb->pb_buf, mp->b_rptr, len);
  841. pcnp->pcn_ipackets++;
  842. pcnp->pcn_rbytes++;
  843. if (rmd->pcn_rxstat & PCN_RXSTAT_LAFM|PCN_RXSTAT_BAM) {
  844. if (rmd->pcn_rxstat & PCN_RXSTAT_BAM)
  845. pcnp->pcn_brdcstrcv++;
  846. else
  847. pcnp->pcn_multircv++;
  848. }
  849. *mpp = mp;
  850. mpp = &mp->b_next;
  851. }
  852. skip:
  853. rmd->pcn_rxstat &= ~(PCN_RXSTAT_OWN);
  854. SYNCRXDESC(pcnp, head, DDI_DMA_SYNC_FORDEV);
  855. head = (head + 1) % PCN_RXRING;
  856. }
  857. pcnp->pcn_rxhead = head;
  858. return (mpchain);
  859. }
  860. static void
  861. pcn_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
  862. {
  863. pcn_t *pcnp = (pcn_t *)arg;
  864. if (mii_m_loop_ioctl(pcnp->pcn_mii, wq, mp))
  865. return;
  866. miocnak(wq, mp, 0, EINVAL);
  867. }
  868. static int
  869. pcn_m_start(void *arg)
  870. {
  871. pcn_t *pcnp = (pcn_t *)arg;
  872. mutex_enter(&pcnp->pcn_intrlock);
  873. mutex_enter(&pcnp->pcn_xmtlock);
  874. pcn_startall(pcnp);
  875. pcnp->pcn_flags |= PCN_RUNNING;
  876. mutex_exit(&pcnp->pcn_xmtlock);
  877. mutex_exit(&pcnp->pcn_intrlock);
  878. mii_start(pcnp->pcn_mii);
  879. return (0);
  880. }
  881. static void
  882. pcn_m_stop(void *arg)
  883. {
  884. pcn_t *pcnp = (pcn_t *)arg;
  885. mii_stop(pcnp->pcn_mii);
  886. mutex_enter(&pcnp->pcn_intrlock);
  887. mutex_enter(&pcnp->pcn_xmtlock);
  888. pcn_stopall(pcnp);
  889. pcnp->pcn_flags &= ~PCN_RUNNING;
  890. mutex_exit(&pcnp->pcn_xmtlock);
  891. mutex_exit(&pcnp->pcn_intrlock);
  892. }
  893. static int
  894. pcn_initialize(pcn_t *pcnp)
  895. {
  896. uint32_t par;
  897. /*
  898. * Issue a reset by reading from the RESET register.
  899. * Note that we don't know if the chip is operating in
  900. * 16-bit or 32-bit mode at this point, so we attempt
  901. * to reset the chip both ways. If one fails, the other
  902. * will succeed.
  903. */
  904. CSR_READ_2(pcnp, PCN_IO16_RESET);
  905. CSR_READ_4(pcnp, PCN_IO32_RESET);
  906. drv_usecwait(1000);
  907. /* Select 32-bit (DWIO) mode */
  908. CSR_WRITE_4(pcnp, PCN_IO32_RDP, 0);
  909. /* Select software style 3. */
  910. pcn_bcr_write(pcnp, PCN_BCR_SSTYLE, PCN_SWSTYLE_PCNETPCI_BURST);
  911. par = 0;
  912. pcn_resetrings(pcnp);
  913. pcn_setrxfilt(pcnp);
  914. /* Enable fast suspend mode. */
  915. PCN_CSR_SETBIT(pcnp, PCN_CSR_EXTCTL2, PCN_EXTCTL2_FASTSPNDE);
  916. return (DDI_SUCCESS);
  917. }
  918. static void
  919. pcn_resetall(pcn_t *pcnp)
  920. {
  921. pcn_stopall(pcnp);
  922. pcn_startall(pcnp);
  923. }
  924. static void
  925. pcn_startmac(pcn_t *pcnp)
  926. {
  927. ASSERT(mutex_owned(&pcnp->pcn_intrlock));
  928. ASSERT(mutex_owned(&pcnp->pcn_xmtlock));
  929. PCN_CSR_SETBIT(pcnp, PCN_CSR_CSR, PCN_CSR_START);
  930. if (pcnp->pcn_flags & PCN_RUNNING)
  931. mac_tx_update(pcnp->pcn_mh);
  932. }
  933. static void
  934. pcn_stopmac(pcn_t *pcnp)
  935. {
  936. ASSERT(mutex_owned(&pcnp->pcn_intrlock));
  937. ASSERT(mutex_owned(&pcnp->pcn_xmtlock));
  938. PCN_CSR_SETBIT(pcnp, PCN_CSR_CSR, PCN_CSR_STOP);
  939. }
  940. static void
  941. pcn_startall(pcn_t *pcnp)
  942. {
  943. ASSERT(mutex_owned(&pcnp->pcn_intrlock));
  944. ASSERT(mutex_owned(&pcnp->pcn_xmtlock));
  945. pcn_disableinterrupts(pcnp);
  946. (void) pcn_initialize(pcnp);
  947. pcn_enableinterrupts(pcnp);
  948. pcn_startmac(pcnp);
  949. }
  950. static void
  951. pcn_stopall(pcn_t *pcnp)
  952. {
  953. pcn_disableinterrupts(pcnp);
  954. pcn_stopmac(pcnp);
  955. }
  956. static int
  957. pcn_m_stat(void *arg, uint_t stat, uint64_t *val)
  958. {
  959. pcn_t *pcnp = (pcn_t *)arg;
  960. if (mii_m_getstat(pcnp->pcn_mii, stat, val) == 0)
  961. return (0);
  962. switch (stat) {
  963. case MAC_STAT_MULTIRCV:
  964. *val = pcnp->pcn_multircv;
  965. break;
  966. case MAC_STAT_BRDCSTRCV:
  967. *val = pcnp->pcn_brdcstrcv;
  968. break;
  969. case MAC_STAT_MULTIXMT:
  970. *val = pcnp->pcn_multixmt;
  971. break;
  972. case MAC_STAT_BRDCSTXMT:
  973. *val = pcnp->pcn_brdcstxmt;
  974. break;
  975. case MAC_STAT_IPACKETS:
  976. *val = pcnp->pcn_ipackets;
  977. break;
  978. case MAC_STAT_RBYTES:
  979. *val = pcnp->pcn_rbytes;
  980. break;
  981. case MAC_STAT_OPACKETS:
  982. *val = pcnp->pcn_opackets;
  983. break;
  984. case MAC_STAT_OBYTES:
  985. *val = pcnp->pcn_obytes;
  986. break;
  987. case MAC_STAT_NORCVBUF:
  988. *val = pcnp->pcn_norcvbuf;
  989. break;
  990. case MAC_STAT_NOXMTBUF:
  991. *val = 0;
  992. break;
  993. case MAC_STAT_COLLISIONS:
  994. *val = pcnp->pcn_collisions;
  995. break;
  996. case MAC_STAT_IERRORS:
  997. *val = pcnp->pcn_errrcv;
  998. break;
  999. case MAC_STAT_OERRORS:
  1000. *val = pcnp->pcn_errxmt;
  1001. break;
  1002. case ETHER_STAT_ALIGN_ERRORS:
  1003. *val = pcnp->pcn_align_errors;
  1004. break;
  1005. case ETHER_STAT_FCS_ERRORS:
  1006. *val = pcnp->pcn_fcs_errors;
  1007. break;
  1008. case ETHER_STAT_SQE_ERRORS:
  1009. *val = pcnp->pcn_sqe_errors;
  1010. break;
  1011. case ETHER_STAT_DEFER_XMTS:
  1012. *val = pcnp->pcn_defer_xmts;
  1013. break;
  1014. case ETHER_STAT_FIRST_COLLISIONS:
  1015. *val = pcnp->pcn_first_collisions;
  1016. break;
  1017. case ETHER_STAT_MULTI_COLLISIONS:
  1018. *val = pcnp->pcn_multi_collisions;
  1019. break;
  1020. case ETHER_STAT_TX_LATE_COLLISIONS:
  1021. *val = pcnp->pcn_tx_late_collisions;
  1022. break;
  1023. case ETHER_STAT_EX_COLLISIONS:
  1024. *val = pcnp->pcn_ex_collisions;
  1025. break;
  1026. case ETHER_STAT_MACXMT_ERRORS:
  1027. *val = pcnp->pcn_macxmt_errors;
  1028. break;
  1029. case ETHER_STAT_CARRIER_ERRORS:
  1030. *val = pcnp->pcn_carrier_errors;
  1031. break;
  1032. case ETHER_STAT_TOOLONG_ERRORS:
  1033. *val = pcnp->pcn_toolong_errors;
  1034. break;
  1035. case ETHER_STAT_MACRCV_ERRORS:
  1036. *val = pcnp->pcn_macrcv_errors;
  1037. break;
  1038. case MAC_STAT_OVERFLOWS:
  1039. *val = pcnp->pcn_overflow;
  1040. break;
  1041. case MAC_STAT_UNDERFLOWS:
  1042. *val = pcnp->pcn_underflow;
  1043. break;
  1044. case ETHER_STAT_TOOSHORT_ERRORS:
  1045. *val = pcnp->pcn_runt;
  1046. break;
  1047. case ETHER_STAT_JABBER_ERRORS:
  1048. *val = pcnp->pcn_jabber;
  1049. break;
  1050. default:
  1051. return (ENOTSUP);
  1052. }
  1053. return (0);
  1054. }
  1055. static int
  1056. pcn_m_getprop(void *arg, const char *name, mac_prop_id_t num, uint_t flags,
  1057. uint_t sz, void *val, uint_t *perm)
  1058. {
  1059. pcn_t *pcnp = (pcn_t *)arg;
  1060. return (mii_m_getprop(pcnp->pcn_mii, name, num, flags, sz, val, perm));
  1061. }
  1062. static int
  1063. pcn_m_setprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz,
  1064. const void *val)
  1065. {
  1066. pcn_t *pcnp = (pcn_t *)arg;
  1067. return (mii_m_setprop(pcnp->pcn_mii, name, num, sz, val));
  1068. }
  1069. static uint16_t
  1070. pcn_mii_read(void *arg, uint8_t phy, uint8_t reg)
  1071. {
  1072. pcn_t *pcnp = (pcn_t *)arg;
  1073. uint16_t val;
  1074. /*
  1075. * At least Am79C971 with DP83840A wedge when isolating the
  1076. * external PHY so we can't allow multiple external PHYs.
  1077. * There are cards that use Am79C971 with both the internal
  1078. * and an external PHY though.
  1079. * For internal PHYs it doesn't really matter whether we can
  1080. * isolate the remaining internal and the external ones in
  1081. * the PHY drivers as the internal PHYs have to be enabled
  1082. * individually in PCN_BCR_PHYSEL, PCN_CSR_MODE, etc.
  1083. * With Am79C97{3,5,8} we don't support switching beetween
  1084. * the internal and external PHYs, yet, so we can't allow
  1085. * multiple PHYs with these either.
  1086. * Am79C97{2,6} actually only support external PHYs (not
  1087. * connectable internal ones respond at the usual addresses,
  1088. * which don't hurt if we let them show up on the bus) and
  1089. * isolating them works.
  1090. */
  1091. if (((pcnp->pcn_type == Am79C971 && phy != PCN_PHYAD_10BT) ||
  1092. pcnp->pcn_type == Am79C973 || pcnp->pcn_type == Am79C975 ||
  1093. pcnp->pcn_type == Am79C978) && pcnp->pcn_extphyaddr != 0xff &&
  1094. phy != pcnp->pcn_extphyaddr)
  1095. return (0xffff);
  1096. pcn_bcr_write(pcnp, PCN_BCR_MIIADDR, reg | (phy << 5));
  1097. val = pcn_bcr_read(pcnp, PCN_BCR_MIIDATA) & 0xFFFF;
  1098. if (val == 0xFFFF)
  1099. return (val);
  1100. if (((pcnp->pcn_type == Am79C971 && phy != PCN_PHYAD_10BT) ||
  1101. pcnp->pcn_type == Am79C973 || pcnp->pcn_type == Am79C975 ||
  1102. pcnp->pcn_type == Am79C978) && pcnp->pcn_extphyaddr == 0xff)
  1103. pcnp->pcn_extphyaddr = phy;
  1104. return (val);
  1105. }
  1106. static void
  1107. pcn_mii_write(void *arg, uint8_t phy, uint8_t reg, uint16_t val)
  1108. {
  1109. pcn_t *pcnp = (pcn_t *)arg;
  1110. pcn_bcr_write(pcnp, PCN_BCR_MIIADDR, reg | (phy << 5));
  1111. pcn_bcr_write(pcnp, PCN_BCR_MIIDATA, val);
  1112. }
  1113. static void
  1114. pcn_mii_notify(void *arg, link_state_t link)
  1115. {
  1116. pcn_t *pcnp = (pcn_t *)arg;
  1117. mac_link_update(pcnp->pcn_mh, link);
  1118. }
  1119. static const pcn_type_t *
  1120. pcn_match(uint16_t vid, uint16_t did)
  1121. {
  1122. const pcn_type_t *t;
  1123. t = pcn_devs;
  1124. while (t->pcn_name != NULL) {
  1125. if ((vid == t->pcn_vid) && (did == t->pcn_did))
  1126. return (t);
  1127. t++;
  1128. }
  1129. return (NULL);
  1130. }
  1131. static char *
  1132. pcn_chipid_name(uint32_t id)
  1133. {
  1134. const struct pcn_chipid *p;
  1135. p = pcn_chipid;
  1136. while (p->name) {
  1137. if (id == p->id)
  1138. return (p->name);
  1139. p++;
  1140. }
  1141. return ("Unknown");
  1142. }
  1143. static void
  1144. pcn_getfactaddr(pcn_t *pcnp)
  1145. {
  1146. uint32_t addr[2];
  1147. addr[0] = CSR_READ_4(pcnp, PCN_IO32_APROM00);
  1148. addr[1] = CSR_READ_4(pcnp, PCN_IO32_APROM01);
  1149. pcnp->pcn_addr[5] = addr[1] >> 8 & 0x000000ffL;
  1150. pcnp->pcn_addr[4] = addr[1] & 0x000000ffL;
  1151. pcnp->pcn_addr[3] = addr[0] >> 24;
  1152. pcnp->pcn_addr[2] = addr[0] >> 16 & 0x000000ffL;
  1153. pcnp->pcn_addr[1] = addr[0] >> 8 & 0x000000ffL;
  1154. pcnp->pcn_addr[0] = addr[0] & 0x000000ffL;
  1155. }
  1156. static void
  1157. pcn_enableinterrupts(pcn_t *pcnp)
  1158. {
  1159. pcn_csr_write(pcnp, PCN_CSR_CSR, PCN_CSR_INTEN);
  1160. }
  1161. static void
  1162. pcn_disableinterrupts(pcn_t *pcnp)
  1163. {
  1164. PCN_CSR_CLRBIT(pcnp, PCN_CSR_CSR, PCN_CSR_INTEN);
  1165. }
  1166. static uint32_t
  1167. pcn_csr_read(pcn_t *pcnp, uint32_t reg)
  1168. {
  1169. CSR_WRITE_4(pcnp, PCN_IO32_RAP, reg);
  1170. return (CSR_READ_4(pcnp, PCN_IO32_RDP));
  1171. }
  1172. static uint16_t
  1173. pcn_csr_read16(pcn_t *pcnp, uint32_t reg)
  1174. {
  1175. CSR_WRITE_2(pcnp, PCN_IO16_RAP, reg);
  1176. return (CSR_READ_2(pcnp, PCN_IO16_RDP));
  1177. }
  1178. static void
  1179. pcn_csr_write(pcn_t *pcnp, uint32_t reg, uint32_t val)
  1180. {
  1181. CSR_WRITE_4(pcnp, PCN_IO32_RAP, reg);
  1182. CSR_WRITE_4(pcnp, PCN_IO32_RDP, val);
  1183. }
  1184. static uint32_t
  1185. pcn_bcr_read(pcn_t *pcnp, uint32_t reg)
  1186. {
  1187. CSR_WRITE_4(pcnp, PCN_IO32_RAP, reg);
  1188. return (CSR_READ_4(pcnp, PCN_IO32_BDP));
  1189. }
  1190. static uint16_t
  1191. pcn_bcr_read16(pcn_t *pcnp, uint32_t reg)
  1192. {
  1193. CSR_WRITE_2(pcnp, PCN_IO16_RAP, reg);
  1194. return (CSR_READ_2(pcnp, PCN_IO16_BDP));
  1195. }
  1196. static void
  1197. pcn_bcr_write(pcn_t *pcnp, uint32_t reg, uint32_t val)
  1198. {
  1199. CSR_WRITE_4(pcnp, PCN_IO32_RAP, reg);
  1200. CSR_WRITE_4(pcnp, PCN_IO32_BDP, val);
  1201. }
  1202. static void
  1203. pcn_resetrings(pcn_t *pcnp)
  1204. {
  1205. int i;
  1206. pcnp->pcn_rxhead = 0;
  1207. pcnp->pcn_txreclaim = 0;
  1208. pcnp->pcn_txsend = 0;
  1209. pcnp->pcn_txavail = PCN_TXRING;
  1210. /* set addresses of decriptors */
  1211. pcn_csr_write(pcnp, PCN_CSR_RXADDR0, pcnp->pcn_rxdesc_paddr & 0xFFFF);
  1212. pcn_csr_write(pcnp, PCN_CSR_RXADDR1,
  1213. (pcnp->pcn_rxdesc_paddr >> 16) & 0xFFFF);
  1214. pcn_csr_write(pcnp, PCN_CSR_TXADDR0, pcnp->pcn_txdesc_paddr & 0xFFFF);
  1215. pcn_csr_write(pcnp, PCN_CSR_TXADDR1,
  1216. (pcnp->pcn_txdesc_paddr >> 16) & 0xFFFF);
  1217. /* set the ring sizes */
  1218. pcn_csr_write(pcnp, PCN_CSR_RXRINGLEN, (~PCN_RXRING) + 1);
  1219. pcn_csr_write(pcnp, PCN_CSR_TXRINGLEN, (~PCN_TXRING) + 1);
  1220. /* don't use the initializtation block */
  1221. pcn_csr_write(pcnp, PCN_CSR_IAB1, 0);
  1222. /* reset rx descriptor values */
  1223. for (i = 0; i < PCN_RXRING; i++) {
  1224. pcn_rx_desc_t *rmd = &pcnp->pcn_rxdescp[i];
  1225. pcn_buf_t *rxb = pcnp->pcn_rxbufs[i];
  1226. rmd->pcn_rbaddr = rxb->pb_paddr;
  1227. rmd->pcn_bufsz = (~(PCN_BUFSZ) + 1) & PCN_RXLEN_BUFSZ;
  1228. rmd->pcn_bufsz |= PCN_RXLEN_MBO;
  1229. rmd->pcn_rxstat = PCN_RXSTAT_STP|PCN_RXSTAT_ENP|PCN_RXSTAT_OWN;
  1230. }
  1231. /* tx descriptors get set on each tx, so no need to do it again */
  1232. }
  1233. static void
  1234. pcn_destroybuf(pcn_buf_t *buf)
  1235. {
  1236. if (buf == NULL)
  1237. return;
  1238. if (buf->pb_paddr)
  1239. (void) ddi_dma_unbind_handle(buf->pb_dmah);
  1240. if (buf->pb_acch)
  1241. ddi_dma_mem_free(&buf->pb_acch);
  1242. if (buf->pb_dmah)
  1243. ddi_dma_free_handle(&buf->pb_dmah);
  1244. kmem_free(buf, sizeof (*buf));
  1245. }
  1246. static pcn_buf_t *
  1247. pcn_allocbuf(pcn_t *pcnp)
  1248. {
  1249. pcn_buf_t *buf;
  1250. size_t len;
  1251. unsigned ccnt;
  1252. ddi_dma_cookie_t dmac;
  1253. buf = kmem_zalloc(sizeof (*buf), KM_SLEEP);
  1254. if (ddi_dma_alloc_handle(pcnp->pcn_dip, &pcn_dma_attr, DDI_DMA_SLEEP,
  1255. NULL, &buf->pb_dmah) != DDI_SUCCESS) {
  1256. kmem_free(buf, sizeof (*buf));
  1257. return (NULL);
  1258. }
  1259. if (ddi_dma_mem_alloc(buf->pb_dmah, PCN_BUFSZ, &pcn_bufattr,
  1260. DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, &buf->pb_buf, &len,
  1261. &buf->pb_acch) != DDI_SUCCESS) {
  1262. pcn_destroybuf(buf);
  1263. return (NULL);
  1264. }
  1265. if (ddi_dma_addr_bind_handle(buf->pb_dmah, NULL, buf->pb_buf, len,
  1266. DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, &dmac,
  1267. &ccnt) != DDI_DMA_MAPPED) {
  1268. pcn_destroybuf(buf);
  1269. return (NULL);
  1270. }
  1271. buf->pb_paddr = dmac.dmac_address;
  1272. return (buf);
  1273. }
  1274. static int
  1275. pcn_alloctxring(pcn_t *pcnp)
  1276. {
  1277. int rval;
  1278. int i;
  1279. size_t size;
  1280. size_t len;
  1281. ddi_dma_cookie_t dmac;
  1282. unsigned ncookies;
  1283. caddr_t kaddr;
  1284. size = PCN_TXRING * sizeof (pcn_tx_desc_t);
  1285. rval = ddi_dma_alloc_handle(pcnp->pcn_dip, &pcn_dma_attr, DDI_DMA_SLEEP,
  1286. NULL, &pcnp->pcn_txdesc_dmah);
  1287. if (rval != DDI_SUCCESS) {
  1288. pcn_error(pcnp->pcn_dip, "unable to allocate DMA handle for tx "
  1289. "descriptors");
  1290. return (DDI_FAILURE);
  1291. }
  1292. rval = ddi_dma_mem_alloc(pcnp->pcn_txdesc_dmah, size, &pcn_devattr,
  1293. DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &kaddr, &len,
  1294. &pcnp->pcn_txdesc_acch);
  1295. if (rval != DDI_SUCCESS) {
  1296. pcn_error(pcnp->pcn_dip, "unable to allocate DMA memory for tx "
  1297. "descriptors");
  1298. return (DDI_FAILURE);
  1299. }
  1300. rval = ddi_dma_addr_bind_handle(pcnp->pcn_txdesc_dmah, NULL, kaddr,
  1301. size, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &dmac,
  1302. &ncookies);
  1303. if (rval != DDI_DMA_MAPPED) {
  1304. pcn_error(pcnp->pcn_dip, "unable to bind DMA for tx "
  1305. "descriptors");
  1306. return (DDI_FAILURE);
  1307. }
  1308. ASSERT(ncookies == 1);
  1309. pcnp->pcn_txdesc_paddr = dmac.dmac_address;
  1310. pcnp->pcn_txdescp = (void *)kaddr;
  1311. pcnp->pcn_txbufs = kmem_zalloc(PCN_TXRING * sizeof (pcn_buf_t *),
  1312. KM_SLEEP);
  1313. for (i = 0; i < PCN_TXRING; i++) {
  1314. pcn_buf_t *txb = pcn_allocbuf(pcnp);
  1315. if (txb == NULL)
  1316. return (DDI_FAILURE);
  1317. pcnp->pcn_txbufs[i] = txb;
  1318. }
  1319. return (DDI_SUCCESS);
  1320. }
  1321. static int
  1322. pcn_allocrxring(pcn_t *pcnp)
  1323. {
  1324. int rval;
  1325. int i;
  1326. size_t len;
  1327. size_t size;
  1328. ddi_dma_cookie_t dmac;
  1329. unsigned ncookies;
  1330. caddr_t kaddr;
  1331. size = PCN_RXRING * sizeof (pcn_rx_desc_t);
  1332. rval = ddi_dma_alloc_handle(pcnp->pcn_dip, &pcn_dmadesc_attr,
  1333. DDI_DMA_SLEEP, NULL, &pcnp->pcn_rxdesc_dmah);
  1334. if (rval != DDI_SUCCESS) {
  1335. pcn_error(pcnp->pcn_dip, "unable to allocate DMA handle for rx "
  1336. "descriptors");
  1337. return (DDI_FAILURE);
  1338. }
  1339. rval = ddi_dma_mem_alloc(pcnp->pcn_rxdesc_dmah, size, &pcn_devattr,
  1340. DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &kaddr, &len,
  1341. &pcnp->pcn_rxdesc_acch);
  1342. if (rval != DDI_SUCCESS) {
  1343. pcn_error(pcnp->pcn_dip, "unable to allocate DMA memory for rx "
  1344. "descriptors");
  1345. return (DDI_FAILURE);
  1346. }
  1347. rval = ddi_dma_addr_bind_handle(pcnp->pcn_rxdesc_dmah, NULL, kaddr,
  1348. size, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &dmac,
  1349. &ncookies);
  1350. if (rval != DDI_DMA_MAPPED) {
  1351. pcn_error(pcnp->pcn_dip, "unable to bind DMA for rx "
  1352. "descriptors");
  1353. return (DDI_FAILURE);
  1354. }
  1355. ASSERT(ncookies == 1);
  1356. pcnp->pcn_rxdesc_paddr = dmac.dmac_address;
  1357. pcnp->pcn_rxdescp = (void *)kaddr;
  1358. pcnp->pcn_rxbufs = kmem_zalloc(PCN_RXRING * sizeof (pcn_buf_t *),
  1359. KM_SLEEP);
  1360. for (i = 0; i < PCN_RXRING; i++) {
  1361. pcn_buf_t *rxb = pcn_allocbuf(pcnp);
  1362. if (rxb == NULL)
  1363. return (DDI_FAILURE);
  1364. pcnp->pcn_rxbufs[i] = rxb;
  1365. }
  1366. return (DDI_SUCCESS);
  1367. }
  1368. static void
  1369. pcn_freetxring(pcn_t *pcnp)
  1370. {
  1371. int i;
  1372. for (i = 0; i < PCN_TXRING; i++)
  1373. pcn_destroybuf(pcnp->pcn_txbufs[i]);
  1374. if (pcnp->pcn_txbufs)
  1375. kmem_free(pcnp->pcn_txbufs, PCN_TXRING * sizeof (pcn_buf_t *));
  1376. if (pcnp->pcn_txdesc_paddr)
  1377. (void) ddi_dma_unbind_handle(pcnp->pcn_txdesc_dmah);
  1378. if (pcnp->pcn_txdesc_acch)
  1379. ddi_dma_mem_free(&pcnp->pcn_txdesc_acch);
  1380. if (pcnp->pcn_txdesc_dmah)
  1381. ddi_dma_free_handle(&pcnp->pcn_txdesc_dmah);
  1382. }
  1383. static void
  1384. pcn_freerxring(pcn_t *pcnp)
  1385. {
  1386. int i;
  1387. for (i = 0; i < PCN_RXRING; i++)
  1388. pcn_destroybuf(pcnp->pcn_rxbufs[i]);
  1389. if (pcnp->pcn_rxbufs)
  1390. kmem_free(pcnp->pcn_rxbufs, PCN_RXRING * sizeof (pcn_buf_t *));
  1391. if (pcnp->pcn_rxdesc_paddr)
  1392. (void) ddi_dma_unbind_handle(pcnp->pcn_rxdesc_dmah);
  1393. if (pcnp->pcn_rxdesc_acch)
  1394. ddi_dma_mem_free(&pcnp->pcn_rxdesc_acch);
  1395. if (pcnp->pcn_rxdesc_dmah)
  1396. ddi_dma_free_handle(&pcnp->pcn_rxdesc_dmah);
  1397. }
  1398. static void
  1399. pcn_error(dev_info_t *dip, char *fmt, ...)
  1400. {
  1401. va_list ap;
  1402. char buf[256];
  1403. va_start(ap, fmt);
  1404. (void) vsnprintf(buf, sizeof (buf), fmt, ap);
  1405. va_end(ap);
  1406. if (dip)
  1407. cmn_err(CE_WARN, "%s%d: %s", ddi_driver_name(dip),
  1408. ddi_get_instance(dip), buf);
  1409. else
  1410. cmn_err(CE_WARN, "pcn: %s", buf);
  1411. }