/* * Initialize the soft TST to contain only ABR scheduling and * write it to SRAM */ static void patm_tst_init(struct patm_softc *sc) { u_int i; u_int base, idle; base = sc->mmap->tst1base; idle = sc->mmap->tst1base + sc->mmap->tst_size; /* soft */ for (i = 0; i < sc->mmap->tst_size - 1; i++) sc->tst_soft[i] = IDT_TST_VBR; sc->tst_state = 0; sc->tst_jump[0] = base + sc->mmap->tst_size - 1; sc->tst_jump[1] = idle + sc->mmap->tst_size - 1; sc->tst_base[0] = base; sc->tst_base[1] = idle; /* TST1 */ for (i = 0; i < sc->mmap->tst_size - 1; i++) patm_sram_write(sc, base + i, IDT_TST_VBR); patm_sram_write(sc, sc->tst_jump[0], IDT_TST_BR | (base << 2)); /* TST2 */ for (i = 0; i < sc->mmap->tst_size - 1; i++) patm_sram_write(sc, idle + i, IDT_TST_VBR); patm_sram_write(sc, sc->tst_jump[1], IDT_TST_BR | (idle << 2)); sc->tst_free = sc->mmap->tst_size - 1; sc->tst_reserve = sc->tst_free * PATM_TST_RESERVE / 100; sc->bwrem = IFP2IFATM(sc->ifp)->mib.pcr; }
/* * Initialize the SCDs. This is done by building a list of all free * SCDs in SRAM. The first word of each potential SCD is used as a * link to the next free SCD. The list is rooted in softc. */ static void patm_scd_init(struct patm_softc *sc) { u_int s; /* SRAM address of current SCD */ sc->scd_free = 0; for (s = sc->mmap->scd_base; s + 12 <= sc->mmap->tst1base; s += 12) { patm_sram_write(sc, s, sc->scd_free); sc->scd_free = s; } }
static __inline void rct_write(struct patm_softc *sc, u_int cid, u_int w, u_int val) { patm_sram_write(sc, sc->mmap->rct + cid * IDT_RCT_ENTRY_SIZE + w, val); }
/* * Start the card. This assumes the mutex to be held */ void patm_initialize(struct patm_softc *sc) { uint32_t cfg; u_int i; patm_debug(sc, ATTACH, "configuring..."); /* clear SRAM */ for (i = 0; i < sc->mmap->sram * 1024; i += 4) patm_sram_write4(sc, i, 0, 0, 0, 0); patm_scd_init(sc); /* configuration register. Setting NOIDLE makes the timing wrong! */ cfg = IDT_CFG_TXFIFO9 | IDT_CFG_RXQ512 | PATM_CFG_VPI | /* IDT_CFG_NOIDLE | */ sc->mmap->rxtab; if (!(sc->flags & PATM_UNASS)) cfg |= IDT_CFG_IDLECLP; patm_nor_write(sc, IDT_NOR_CFG, cfg); /* clean all the status queues and the Raw handle */ memset(sc->tsq, 0, sc->sq_size); /* initialize RSQ */ patm_debug(sc, ATTACH, "RSQ %llx", (unsigned long long)sc->rsq_phy); patm_nor_write(sc, IDT_NOR_RSQB, sc->rsq_phy); patm_nor_write(sc, IDT_NOR_RSQT, sc->rsq_phy); patm_nor_write(sc, IDT_NOR_RSQH, 0); sc->rsq_last = PATM_RSQ_SIZE - 1; /* initialize TSTB */ patm_nor_write(sc, IDT_NOR_TSTB, sc->mmap->tst1base << 2); patm_tst_init(sc); /* initialize TSQ */ for (i = 0; i < IDT_TSQ_SIZE; i++) sc->tsq[i].stamp = htole32(IDT_TSQE_EMPTY); patm_nor_write(sc, IDT_NOR_TSQB, sc->tsq_phy); patm_nor_write(sc, IDT_NOR_TSQH, 0); patm_nor_write(sc, IDT_NOR_TSQT, 0); sc->tsq_next = sc->tsq; /* GP */ #if BYTE_ORDER == BIG_ENDIAN && 0 patm_nor_write(sc, IDT_NOR_GP, IDT_GP_BIGE); #else patm_nor_write(sc, IDT_NOR_GP, 0); #endif /* VPM */ patm_nor_write(sc, IDT_NOR_VPM, 0); /* RxFIFO */ patm_nor_write(sc, IDT_NOR_RXFD, IDT_RXFD(sc->mmap->rxfifo_addr, sc->mmap->rxfifo_code)); patm_nor_write(sc, IDT_NOR_RXFT, 0); patm_nor_write(sc, IDT_NOR_RXFH, 0); /* RAWHND */ patm_debug(sc, ATTACH, "RWH %llx", (unsigned long long)sc->rawhnd_phy); patm_nor_write(sc, IDT_NOR_RAWHND, sc->rawhnd_phy); /* ABRSTD */ patm_nor_write(sc, IDT_NOR_ABRSTD, IDT_ABRSTD(sc->mmap->abrstd_addr, sc->mmap->abrstd_code)); for (i = 0; i < sc->mmap->abrstd_size; i++) patm_sram_write(sc, sc->mmap->abrstd_addr + i, 0); patm_nor_write(sc, IDT_NOR_ABRRQ, 0); patm_nor_write(sc, IDT_NOR_VBRRQ, 0); /* rate tables */ if (sc->flags & PATM_25M) { for (i = 0; i < patm_rtables_size; i++) patm_sram_write(sc, sc->mmap->rtables + i, patm_rtables25[i]); } else { for (i = 0; i < patm_rtables_size; i++) patm_sram_write(sc, sc->mmap->rtables + i, patm_rtables155[i]); } patm_nor_write(sc, IDT_NOR_RTBL, sc->mmap->rtables << 2); /* Maximum deficit */ patm_nor_write(sc, IDT_NOR_MXDFCT, 32 | IDT_MDFCT_LCI | IDT_MDFCT_LNI); /* Free buffer queues */ patm_nor_write(sc, IDT_NOR_FBQP0, 0); patm_nor_write(sc, IDT_NOR_FBQP1, 0); patm_nor_write(sc, IDT_NOR_FBQP2, 0); patm_nor_write(sc, IDT_NOR_FBQP3, 0); patm_nor_write(sc, IDT_NOR_FBQWP0, 0); patm_nor_write(sc, IDT_NOR_FBQWP1, 0); patm_nor_write(sc, IDT_NOR_FBQWP2, 0); patm_nor_write(sc, IDT_NOR_FBQWP3, 0); patm_nor_write(sc, IDT_NOR_FBQS0, (SMBUF_THRESHOLD << 28) | (SMBUF_NI_THRESH << 24) | (SMBUF_CI_THRESH << 20) | SMBUF_CELLS); patm_nor_write(sc, IDT_NOR_FBQS1, (LMBUF_THRESHOLD << 28) | (LMBUF_NI_THRESH << 24) | (LMBUF_CI_THRESH << 20) | LMBUF_CELLS); patm_nor_write(sc, IDT_NOR_FBQS2, (VMBUF_THRESHOLD << 28) | VMBUF_CELLS); patm_nor_write(sc, IDT_NOR_FBQS3, 0); /* make SCD0 for UBR0 */ if ((sc->scd0 = patm_scd_alloc(sc)) == NULL) { patm_printf(sc, "cannot create UBR0 SCD\n"); patm_reset(sc); return; } sc->scd0->q.ifq_maxlen = PATM_DLFT_MAXQ; patm_scd_setup(sc, sc->scd0); patm_tct_setup(sc, sc->scd0, NULL); patm_debug(sc, ATTACH, "go..."); sc->utopia.flags &= ~UTP_FL_POLL_CARRIER; sc->ifp->if_drv_flags |= IFF_DRV_RUNNING; /* enable interrupts, Tx and Rx paths */ cfg |= IDT_CFG_RXPTH | IDT_CFG_RXIIMM | IDT_CFG_RAWIE | IDT_CFG_RQFIE | IDT_CFG_TIMOIE | IDT_CFG_FBIE | IDT_CFG_TXENB | IDT_CFG_TXINT | IDT_CFG_TXUIE | IDT_CFG_TXSFI | IDT_CFG_PHYIE; patm_nor_write(sc, IDT_NOR_CFG, cfg); for (i = 0; i < sc->mmap->max_conn; i++) if (sc->vccs[i] != NULL) patm_load_vc(sc, sc->vccs[i], 1); ATMEV_SEND_IFSTATE_CHANGED(IFP2IFATM(sc->ifp), sc->utopia.carrier == UTP_CARR_OK); }