Exemple #1
0
/*
  This function is called when a packet has been received.  It's job is
  to prepare to unload the packet from the hardware.  Once the length of
  the packet is known, the upper layer of the driver can be told.  When
  the upper layer is ready to unload the packet, the internal function
  'dp83902a_recv' will be called to actually fetch it from the hardware.
*/
static void
dp83902a_RxEvent(void)
{
	struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;
	cyg_uint8 *base = dp->base;
	unsigned char rsr;
	unsigned char rcv_hdr[4];
	int i, len, pkt, cur;

	DEBUG_FUNCTION();

	DP_IN(base, DP_RSR, rsr);
	while (true) {
		/* Read incoming packet header */
		DP_OUT(base, DP_CR, DP_CR_PAGE1 | DP_CR_NODMA | DP_CR_START);
		DP_IN(base, DP_P1_CURP, cur);
		DP_OUT(base, DP_P1_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
		DP_IN(base, DP_BNDRY, pkt);

		pkt += 1;
		if (pkt == dp->rx_buf_end)
			pkt = dp->rx_buf_start;

		if (pkt == cur) {
			break;
		}
		DP_OUT(base, DP_RBCL, sizeof(rcv_hdr));
		DP_OUT(base, DP_RBCH, 0);
		DP_OUT(base, DP_RSAL, 0);
		DP_OUT(base, DP_RSAH, pkt);
		if (dp->rx_next == pkt) {
			if (cur == dp->rx_buf_start)
				DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1);
			else
				DP_OUT(base, DP_BNDRY, cur-1); /* Update pointer */
			return;
		}
		dp->rx_next = pkt;
		DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */
		DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START);
#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA
		CYGACC_CALL_IF_DELAY_US(10);
#endif

		for (i = 0;  i < sizeof(rcv_hdr);) {
			DP_IN_DATA(dp->data, rcv_hdr[i++]);
		}

#if DEBUG & 5
		printf("rx hdr %02x %02x %02x %02x\n",
		       rcv_hdr[0], rcv_hdr[1], rcv_hdr[2], rcv_hdr[3]);
#endif
		len = ((rcv_hdr[3] << 8) | rcv_hdr[2]) - sizeof(rcv_hdr);
		uboot_push_packet_len(len);
		if (rcv_hdr[1] == dp->rx_buf_start)
			DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1);
		else
			DP_OUT(base, DP_BNDRY, rcv_hdr[1]-1); /* Update pointer */
	}
}
Exemple #2
0
/*
 * Read the tally counters to clear them. Called in response to a CNT
 * interrupt.
 */
static void
dp83902a_ClearCounters(struct nic_priv_data *dp)
{
	u8 *base = dp->base;
	u8 cnt1, cnt2, cnt3;

	DP_IN(base, DP_FER, cnt1);
	DP_IN(base, DP_CER, cnt2);
	DP_IN(base, DP_MISSED, cnt3);
	DP_OUT(base, DP_ISR, DP_ISR_CNT);
}
Exemple #3
0
/* interrupt. */
static void
dp83902a_ClearCounters(void)
{
	struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;
	cyg_uint8 *base = dp->base;
	cyg_uint8 cnt1, cnt2, cnt3;

	DP_IN(base, DP_FER, cnt1);
	DP_IN(base, DP_CER, cnt2);
	DP_IN(base, DP_MISSED, cnt3);
	DP_OUT(base, DP_ISR, DP_ISR_CNT);
}
// ---------------------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------------------
CAudioGainControl::CAudioGainControl()
	{
	TRACE_CREATE();
	DP_CONTEXT(CAudioGainControl::CAudioGainControl *CD1*, CtxDevSound, DPLOCAL);
	DP_IN();
	DP_OUT();
	}
Exemple #5
0
static void
dp83902a_TxEvent(void)
{
	struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;
	cyg_uint8 *base = dp->base;
	unsigned char tsr;
	unsigned long key;

	DEBUG_FUNCTION();

	DP_IN(base, DP_TSR, tsr);
	if (dp->tx_int == 1) {
		key = dp->tx1_key;
		dp->tx1 = 0;
	} else {
		key = dp->tx2_key;
		dp->tx2 = 0;
	}
	/* Start next packet if one is ready */
	dp->tx_started = false;
	if (dp->tx1) {
		dp83902a_start_xmit(dp->tx1, dp->tx1_len);
		dp->tx_int = 1;
	} else if (dp->tx2) {
		dp83902a_start_xmit(dp->tx2, dp->tx2_len);
		dp->tx_int = 2;
	} else {
		dp->tx_int = 0;
	}
	/* Tell higher level we sent this packet */
	uboot_push_tx_done(key, 0);
}
Exemple #6
0
static bool
dp83902a_init(void)
{
	dp83902a_priv_data_t *dp = &nic;
	cyg_uint8* base;
	int i;

	DEBUG_FUNCTION();

	base = dp->base;
	if (!base) return false;  /* No device found */

	DEBUG_LINE();

	/* Prepare ESA */
	DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE1);  /* Select page 1 */
	/* Use the address from the serial EEPROM */
	for (i = 0; i < 6; i++)
		DP_IN(base, DP_P1_PAR0+i, dp->esa[i]);
	DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE0);  /* Select page 0 */

	printf("NE2000 - %s ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",
	       "eeprom",
	       dp->esa[0],
	       dp->esa[1],
	       dp->esa[2],
	       dp->esa[3],
	       dp->esa[4],
	       dp->esa[5] );

	return true;
}
Exemple #7
0
static void
dp83902a_TxEvent(struct nic_priv_data *dp)
{
	u8 *base = dp->base;
	u8 tsr;
	u32 key;

	DP_IN(base, DP_TSR, tsr);
	if (dp->tx_int == 1) {
		key = dp->tx1_key;
		dp->tx1 = 0;
	} else {
		key = dp->tx2_key;
		dp->tx2 = 0;
	}
	/* Start next packet if one is ready */
	dp->tx_started = false;
	if (dp->tx1) {
		dp83902a_start_xmit(dp, dp->tx1, dp->tx1_len);
		dp->tx_int = 1;
	} else if (dp->tx2) {
		dp83902a_start_xmit(dp, dp->tx2, dp->tx2_len);
		dp->tx_int = 2;
	} else {
		dp->tx_int = 0;
	}
	
	/* FIXME: Tell higher level we sent this packet */
	push_tx_done(key, 0);
}
Exemple #8
0
static void
dp83902a_poll(void)
{
    struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;
    u8 *base = dp->base;
    u8 isr;

    DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE0 | DP_CR_START);
    DP_IN(base, DP_ISR, isr);
    while (0 != isr) {
        /*
         * The CNT interrupt triggers when the MSB of one of the error
         * counters is set. We don't much care about these counters, but
         * we should read their values to reset them.
         */
        if (isr & DP_ISR_CNT) {
            dp83902a_ClearCounters();
        }
        /*
         * Check for overflow. It's a special case, since there's a
         * particular procedure that must be followed to get back into
         * a running state.a
         */
        if (isr & DP_ISR_OFLW) {
            dp83902a_Overflow();
        } else {
            /*
             * Other kinds of interrupts can be acknowledged simply by
             * clearing the relevant bits of the ISR. Do that now, then
             * handle the interrupts we care about.
             */
            DP_OUT(base, DP_ISR, isr);	/* Clear set bits */
            if (!dp->running) break;	/* Is this necessary? */
            /*
             * Check for tx_started on TX event since these may happen
             * spuriously it seems.
             */
            if (isr & (DP_ISR_TxP|DP_ISR_TxE) && dp->tx_started) {
                dp83902a_TxEvent();
            }
            if (isr & (DP_ISR_RxP|DP_ISR_RxE)) {
                dp83902a_RxEvent();
            }
        }
        DP_IN(base, DP_ISR, isr);
    }
}
// ---------------------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------------------
//
CBufferSource::CBufferSource()
	: CActive(EPriorityStandard)
	{
	TRACE_CREATE();
	DP_CONTEXT(CBufferSource::CBufferSource *CD1*, CtxDevSound, DPLOCAL);
	DP_IN();
	DP_OUT();
	}
// -----------------------------------------------------------------------------
// CMMFDevSoundAdaptation::CMMFDevSoundAdaptation
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CMMFDevSoundAdaptation::CMMFDevSoundAdaptation()
	{
	TRACE_CREATE();
	DP_CONTEXT(CMMFDevSoundAdaptation::CMMFDevSoundAdaptation *CD1*, CtxDevSound, DPLOCAL);
	DP_IN();
	PRF_HEAP_STATUS(PRF_MEM, HEAP_DS_Session);
	DP_OUT();
	}
Exemple #11
0
/*
 * Deal with an overflow condition. This code follows the procedure set
 * out in section 7.0 of the datasheet.
 */
static void
dp83902a_Overflow(void)
{
    struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *)&nic;
    u8 *base = dp->base;
    u8 isr;

    /* Issue a stop command and wait 1.6ms for it to complete. */
    DP_OUT(base, DP_CR, DP_CR_STOP | DP_CR_NODMA);
    CYGACC_CALL_IF_DELAY_US(1600);

    /* Clear the remote byte counter registers. */
    DP_OUT(base, DP_RBCL, 0);
    DP_OUT(base, DP_RBCH, 0);

    /* Enter loopback mode while we clear the buffer. */
    DP_OUT(base, DP_TCR, DP_TCR_LOCAL);
    DP_OUT(base, DP_CR, DP_CR_START | DP_CR_NODMA);

    /*
     * Read in as many packets as we can and acknowledge any and receive
     * interrupts. Since the buffer has overflowed, a receive event of
     * some kind will have occured.
     */
    dp83902a_RxEvent();
    DP_OUT(base, DP_ISR, DP_ISR_RxP|DP_ISR_RxE);

    /* Clear the overflow condition and leave loopback mode. */
    DP_OUT(base, DP_ISR, DP_ISR_OFLW);
    DP_OUT(base, DP_TCR, DP_TCR_NORMAL);

    /*
     * If a transmit command was issued, but no transmit event has occured,
     * restart it here.
     */
    DP_IN(base, DP_ISR, isr);
    if (dp->tx_started && !(isr & (DP_ISR_TxP|DP_ISR_TxE))) {
        DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_TXPKT | DP_CR_START);
    }
}
Exemple #12
0
/**
 * This function reads the MAC address from the serial EEPROM,
 * used if PROM read fails. Does nothing for ax88796 chips (sh boards)
 */
static bool
dp83902a_init(unsigned char *enetaddr)
{
    dp83902a_priv_data_t *dp = &nic;
    u8* base;
#if defined(NE2000_BASIC_INIT)
    int i;
#endif

    DEBUG_FUNCTION();

    base = dp->base;
    if (!base)
        return false;	/* No device found */

    DEBUG_LINE();

#if defined(NE2000_BASIC_INIT)
    /* AX88796L doesn't need */
    /* Prepare ESA */
    DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE1);	/* Select page 1 */
    /* Use the address from the serial EEPROM */
    for (i = 0; i < 6; i++)
        DP_IN(base, DP_P1_PAR0+i, dp->esa[i]);
    DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE0);	/* Select page 0 */

    printf("NE2000 - %s ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",
           "eeprom",
           dp->esa[0],
           dp->esa[1],
           dp->esa[2],
           dp->esa[3],
           dp->esa[4],
           dp->esa[5] );

    memcpy(enetaddr, dp->esa, 6); /* Use MAC from serial EEPROM */
#endif	/* NE2000_BASIC_INIT */
    return true;
}
Exemple #13
0
/*
  This routine is called to send data to the hardware.  It is known a-priori
  that there is free buffer space (dp->tx_next).
*/
static void
dp83902a_send(unsigned char *data, int total_len, unsigned long key)
{
	struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;
	cyg_uint8 *base = dp->base;
	int len, start_page, pkt_len, i, isr;
#if DEBUG & 4
	int dx;
#endif

	DEBUG_FUNCTION();

	len = pkt_len = total_len;
	if (pkt_len < IEEE_8023_MIN_FRAME) pkt_len = IEEE_8023_MIN_FRAME;

	start_page = dp->tx_next;
	if (dp->tx_next == dp->tx_buf1) {
		dp->tx1 = start_page;
		dp->tx1_len = pkt_len;
		dp->tx1_key = key;
		dp->tx_next = dp->tx_buf2;
	} else {
		dp->tx2 = start_page;
		dp->tx2_len = pkt_len;
		dp->tx2_key = key;
		dp->tx_next = dp->tx_buf1;
	}

#if DEBUG & 5
	printf("TX prep page %d len %d\n", start_page, pkt_len);
#endif

	DP_OUT(base, DP_ISR, DP_ISR_RDC);  /* Clear end of DMA */
	{
		/* Dummy read. The manual sez something slightly different, */
		/* but the code is extended a bit to do what Hitachi's monitor */
		/* does (i.e., also read data). */

		cyg_uint16 tmp;
		int len = 1;

		DP_OUT(base, DP_RSAL, 0x100-len);
		DP_OUT(base, DP_RSAH, (start_page-1) & 0xff);
		DP_OUT(base, DP_RBCL, len);
		DP_OUT(base, DP_RBCH, 0);
		DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_RDMA | DP_CR_START);
		DP_IN_DATA(dp->data, tmp);
	}

#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA
	/* Stall for a bit before continuing to work around random data */
	/* corruption problems on some platforms. */
	CYGACC_CALL_IF_DELAY_US(1);
#endif

	/* Send data to device buffer(s) */
	DP_OUT(base, DP_RSAL, 0);
	DP_OUT(base, DP_RSAH, start_page);
	DP_OUT(base, DP_RBCL, pkt_len & 0xFF);
	DP_OUT(base, DP_RBCH, pkt_len >> 8);
	DP_OUT(base, DP_CR, DP_CR_WDMA | DP_CR_START);

	/* Put data into buffer */
#if DEBUG & 4
	printf(" sg buf %08lx len %08x\n ", (unsigned long) data, len);
	dx = 0;
#endif
	while (len > 0) {
#if DEBUG & 4
		printf(" %02x", *data);
		if (0 == (++dx % 16)) printf("\n ");
#endif
		DP_OUT_DATA(dp->data, *data++);
		len--;
	}
#if DEBUG & 4
	printf("\n");
#endif
	if (total_len < pkt_len) {
#if DEBUG & 4
		printf("  + %d bytes of padding\n", pkt_len - total_len);
#endif
		/* Padding to 802.3 length was required */
		for (i = total_len;  i < pkt_len;) {
			i++;
			DP_OUT_DATA(dp->data, 0);
		}
	}

#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA
	/* After last data write, delay for a bit before accessing the */
	/* device again, or we may get random data corruption in the last */
	/* datum (on some platforms). */
	CYGACC_CALL_IF_DELAY_US(1);
#endif

	/* Wait for DMA to complete */
	do {
		DP_IN(base, DP_ISR, isr);
	} while ((isr & DP_ISR_RDC) == 0);
	/* Then disable DMA */
	DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);

	/* Start transmit if not already going */
	if (!dp->tx_started) {
		if (start_page == dp->tx1) {
			dp->tx_int = 1;  /* Expecting interrupt from BUF1 */
		} else {
			dp->tx_int = 2;  /* Expecting interrupt from BUF2 */
		}
		dp83902a_start_xmit(start_page, pkt_len);
	}
}
Exemple #14
0
static void
#else
static int
#endif
sc_lpe_card_handler(cyg_addrword_t param)
{
    struct eth_drv_sc *sc = (struct eth_drv_sc *)param;
    dp83902a_priv_data_t *dp = (dp83902a_priv_data_t*)sc->driver_private;
    struct cf_slot *slot;
    struct cf_cftable cftable;
    struct cf_config config;
    int i, len, ptr, cor = 0;
    unsigned char buf[256], *cp;
    cyg_uint8* base;
    unsigned char *vers_product, *vers_manuf, *vers_revision, *vers_date;
#ifndef CYGPKG_KERNEL
    int tries = 0;
#endif
    bool first = true;

    slot = (struct cf_slot*)dp->plf_priv;
    cyg_drv_dsr_lock();
    while (true) {
        cyg_drv_dsr_unlock();   // Give DSRs a chance to run (card insertion)
        cyg_drv_dsr_lock();
        if ((slot->state == CF_SLOT_STATE_Inserted) ||
            ((slot->state == CF_SLOT_STATE_Ready) && first)) {
            first = false;
            if (slot->state != CF_SLOT_STATE_Ready) {
                cf_change_state(slot, CF_SLOT_STATE_Ready);
            }
            if (slot->state != CF_SLOT_STATE_Ready) {
                diag_printf("CF card won't go ready!\n");
#ifndef CYGPKG_KERNEL
                return false;
#else
                continue;
#endif
            }
            len = sizeof(buf);
            ptr = 0;
            if (cf_get_CIS(slot, CF_CISTPL_MANFID, buf, &len, &ptr)) {
                if (*(short *)&buf[2] != SC_LPE_MANUF) {
                    diag_printf("Not a SC LPE, sorry\n");
                    continue;
                }
            } 
            ptr = 0;
            if (cf_get_CIS(slot, CF_CISTPL_VERS_1, buf, &len, &ptr)) {
                // Find individual strings
                cp = &buf[4];
                vers_product = cp;
                while (*cp++) ;  // Skip to nul
                vers_manuf = cp;
                while (*cp++) ;  // Skip to nul
                vers_revision = cp;
                while (*cp++) ;  // Skip to nul
                vers_date = cp;
#ifndef CYGPKG_KERNEL
                if (tries != 0) diag_printf("\n");
                diag_printf("%s: %s %s %s\n", vers_manuf, vers_product, vers_revision, vers_date);
#endif
            }
            ptr = 0;
            if (cf_get_CIS(slot, CF_CISTPL_CONFIG, buf, &len, &ptr)) {
                if (cf_parse_config(buf, len, &config)) {
                    cor = config.base;
                }
            }
            if (!cor) {
//                diag_printf("Couldn't find COR pointer!\n");
                continue;
            }

            ptr = 0;
            if (cf_get_CIS(slot, CF_CISTPL_CFTABLE_ENTRY, buf, &len, &ptr)) {
                if (cf_parse_cftable(buf, len, &cftable)) {
                    cyg_uint8 tmp;
                    // Initialize dp83902a IO details
                    dp->base = base = (cyg_uint8*)&slot->io[cftable.io_space.base[0]];
                    dp->data = base + DP_DATA;
                    dp->interrupt = slot->int_num;
                    cf_set_COR(slot, cor, cftable.cor);
                    // Reset card  (read issues RESET, write clears it)
                    HAL_READ_UINT8(base+DP_CARD_RESET, tmp);
                    HAL_WRITE_UINT8(base+DP_CARD_RESET, tmp);
                    // Wait for card
                    do {
                        DP_IN(base, DP_ISR, tmp);
                    } while (0 == (tmp & DP_ISR_RESET));

                    // Fetch hardware address from card - terrible, but not well defined
                    // Patterned after what Linux drivers do
                    if (!dp->hardwired_esa) {
                        static unsigned char sc_lpe_addr[] = { 0x00, 0xC0, 0x1B, 0x00, 0x99, 0x9E};
                        if ((slot->attr[0x1C0] == sc_lpe_addr[0]) &&
                            (slot->attr[0x1C2] == sc_lpe_addr[1]) &&
                            (slot->attr[0x1C4] == sc_lpe_addr[2])) {
                            sc_lpe_addr[3] = slot->attr[0x1C6];
                            sc_lpe_addr[4] = slot->attr[0x1C8];
                            sc_lpe_addr[5] = slot->attr[0x1CA];
                        } else {
                            // Coudn't find it in the CIS (attribute) data
                            unsigned char prom[32];

                            // Tell device to give up ESA
                            DP_OUT(base, DP_DCR, 0x48);  // Bytewide access
                            DP_OUT(base, DP_RBCH, 0);    // Remote byte count
                            DP_OUT(base, DP_RBCL, 0);
                            DP_OUT(base, DP_ISR, 0xFF);  // Clear any pending interrupts
                            DP_OUT(base, DP_IMR, 0x00);  // Mask all interrupts 
                            DP_OUT(base, DP_RCR, 0x20);  // Monitor
                            DP_OUT(base, DP_TCR, 0x02);  // loopback
                            DP_OUT(base, DP_RBCH, 32);   // Remote byte count
                            DP_OUT(base, DP_RBCL, 0);
                            DP_OUT(base, DP_RSAL, 0);    // Remote address
                            DP_OUT(base, DP_RSAH, 0);
                            DP_OUT(base, DP_CR, DP_CR_START|DP_CR_RDMA);  // Read data
                            for (i = 0;  i < 32;  i++) {
                                HAL_READ_UINT8(base+DP_DATAPORT, prom[i]);
                            }
                            if ((prom[0] == sc_lpe_addr[0]) &&
                                (prom[2] == sc_lpe_addr[1]) &&
                                (prom[4] == sc_lpe_addr[2])) {
                                diag_printf("Getting address from port\n");
                                sc_lpe_addr[3] = prom[6];
                                sc_lpe_addr[4] = prom[8];
                                sc_lpe_addr[5] = prom[10];
                            } else {
                                diag_printf("No valid ESA found in CIS! Hardwiring to 00:C0:1B:00:99:9E\n");
                            }
                        }
                        for (i = 0;  i < 6;  i++) {
                            dp->esa[i] = sc_lpe_addr[i];
                        }
                    }

                    // Initialize upper level driver
                    (sc->funs->eth_drv->init)(sc, dp->esa);
                    // Tell system card is ready to talk
                    dp->tab->status = CYG_NETDEVTAB_STATUS_AVAIL;
#ifndef CYGPKG_KERNEL
                    cyg_drv_dsr_unlock();
                    return true;
#endif
                } else {
                    diag_printf("Can't parse CIS\n");
                    continue;
                }
            } else {
                diag_printf("Can't fetch config info\n");
                continue;
            }
        } else if (slot->state == CF_SLOT_STATE_Removed) {
            diag_printf("Compact Flash card removed!\n");
        } else {
            cyg_drv_dsr_unlock();
            do_delay(50);  // FIXME!
#ifndef CYGPKG_KERNEL
            if (tries == 0) diag_printf("... Waiting for network card: ");
            diag_printf(".");
            if (++tries == 10) {
                // 5 seconds have elapsed - give up
                return false;
            }
            cf_hwr_poll(slot);  // Check to see if card has been inserted
#endif
            cyg_drv_dsr_lock();
        }
    }
}