📄 if_sc_lpe.c
字号:
//==========================================================================//// dev/if_sc_lpe.c//// Ethernet device driver for Socket Communications Compact Flash card////==========================================================================//####COPYRIGHTBEGIN####// // ------------------------------------------- // The contents of this file are subject to the Red Hat eCos Public License // Version 1.1 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://www.redhat.com/ // // Software distributed under the License is distributed on an "AS IS" // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the // License for the specific language governing rights and limitations under // the License. // // The Original Code is eCos - Embedded Configurable Operating System, // released September 30, 1998. // // The Initial Developer of the Original Code is Red Hat. // Portions created by Red Hat are // Copyright (C) 1998, 1999, 2000 Red Hat, Inc. // All Rights Reserved. // ------------------------------------------- // //####COPYRIGHTEND####//####BSDCOPYRIGHTBEGIN####//// -------------------------------------------//// Portions of this software may have been derived from OpenBSD or other sources,// and are covered by the appropriate copyright disclaimers included herein.//// -------------------------------------------////####BSDCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): gthomas// Contributors: gthomas// Date: 2000-07-07// Purpose: // Description: hardware driver for LPCF+ ethernet// ////####DESCRIPTIONEND####////==========================================================================#include <pkgconf/system.h>#include <cyg/infra/cyg_type.h>#include <cyg/hal/hal_arch.h>#include <cyg/infra/diag.h>#include <cyg/hal/drv_api.h>#include <cyg/io/pcmcia.h>#include <eth_drv.h>#include <netdev.h>#ifdef CYGPKG_NET#include <pkgconf/net.h>#else#include <cyg/hal/hal_if.h>#define diag_printf printf#endif#include "dp8390.h"struct sc_lpe_priv_data { struct cf_slot *slot; dp8390_regs *regs; int tx_next; // First free Tx page int tx_int; // Expecting interrupt from this buffer int rx_next; // First free Rx page int tx1, tx2; // Page numbers for Tx buffers unsigned long tx1_key, tx2_key; // Used to ack when packet sent int tx1_len, tx2_len; bool tx_started, running; struct cyg_netdevtab_entry *tab;} _sc_lpe_priv_data;ETH_DRV_SC(sc_lpe_sc, &_sc_lpe_priv_data, // Driver specific data "eth0", // Name for this interface sc_lpe_start, sc_lpe_stop, sc_lpe_control, sc_lpe_can_send, sc_lpe_send, sc_lpe_recv, sc_lpe_int, // deliver function, called from fast net thread sc_lpe_int, sc_lpe_int_vector );NETDEVTAB_ENTRY(sc_lpe_netdev, "sc_lpe", sc_lpe_init, &sc_lpe_sc);// Updated to actual address when card is insertedstatic unsigned char enaddr[] = { 0x08, 0x88, 0x12, 0x34, 0x56, 0x78};static void sc_lpe_int(struct eth_drv_sc *sc);#ifdef CYGPKG_NET#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICALstatic char sc_lpe_card_handler_stack[STACK_SIZE];static cyg_thread sc_lpe_card_handler_thread_data;static cyg_handle_t sc_lpe_card_handler_thread_handle;#endif // CYGPKG_NETstatic voiddo_delay(int ticks){#ifdef CYGPKG_KERNEL cyg_thread_delay(ticks);#else CYGACC_CALL_IF_DELAY_US(10000*ticks);#endif}//// This runs as a separate thread to handle the card. In particular, insertions// and deletions need to be handled and they take time/coordination, thus the// separate thread.//#ifdef CYGPKG_NETstatic void#elsestatic int#endifsc_lpe_card_handler(cyg_addrword_t param){ struct eth_drv_sc *sc = (struct eth_drv_sc *)param; struct sc_lpe_priv_data *dp = (struct sc_lpe_priv_data *)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; dp8390_regs *regs; unsigned char *vers_product, *vers_manuf, *vers_revision, *vers_date;#ifndef CYGPKG_NET int tries = 0;#endif bool first = true; slot = dp->slot; 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_NET 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_NET if (tries != 0) 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; } // Fetch hardware address from card - terrible, but not well defined for (i = 0; i < ETHER_ADDR_LEN; i++) { enaddr[i] = slot->attr[0x1C0+(i*2)]; } ptr = 0; if (cf_get_CIS(slot, CF_CISTPL_CFTABLE_ENTRY, buf, &len, &ptr)) { if (cf_parse_cftable(buf, len, &cftable)) { dp->regs = regs = (dp8390_regs *)&dp->slot->io[cftable.io_space.base[0]]; cf_set_COR(slot, cor, cftable.cor); // Reset card (read issues RESET, write clears it) regs->w.page0.reset = regs->r.page0.reset; while ((regs->r.page0.isr & DP8390_ISR_RESET) == 0) ; // Wait for card // Initialize upper level driver (sc->funs->eth_drv->init)(sc, enaddr); // Tell system card is ready to talk dp->tab->status = CYG_NETDEVTAB_STATUS_AVAIL;#ifndef CYGPKG_NET 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_NET if (tries == 0) printf("... Waiting for network card: "); 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(); } }}static bool sc_lpe_init(struct cyg_netdevtab_entry *tab){ struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance; struct sc_lpe_priv_data *dp = (struct sc_lpe_priv_data *)sc->driver_private; cf_init(); // Make sure Compact Flash subsystem is initialized dp->slot = cf_get_slot(0); dp->tab = tab;#ifdef CYGPKG_NET // Create card handling [background] thread cyg_thread_create(CYGPKG_NET_THREAD_PRIORITY-1, // Priority sc_lpe_card_handler, // entry (cyg_addrword_t)sc, // entry parameter "SC LP-E card support", // Name &sc_lpe_card_handler_stack[0], // Stack STACK_SIZE, // Size &sc_lpe_card_handler_thread_handle, // Handle &sc_lpe_card_handler_thread_data // Thread data structure ); cyg_thread_resume(sc_lpe_card_handler_thread_handle); // Start it // Initialize environment, setup interrupt handler // eth_drv_dsr is used to tell the fast net thread to run the deliver funcion. cf_register_handler(dp->slot, eth_drv_dsr, sc); return false; // Device is not ready until inserted, powered up, etc.#else // Initialize card return sc_lpe_card_handler(sc);#endif}static voidsc_lpe_stop(struct eth_drv_sc *sc){ struct sc_lpe_priv_data *dp = (struct sc_lpe_priv_data *)sc->driver_private; dp8390_regs *regs = dp->regs; regs->w.page0.cr = DP8390_CR_PAGE0 | DP8390_CR_NODMA | DP8390_CR_STOP; // Brutal regs->w.page0.isr = 0xFF; // Clear any pending interrupts regs->w.page0.imr = 0x00; // Disable all interrupts dp->running = false;}//// This function is called to "start up" the interface. It may be called// multiple times, even when the hardware is already running. It will be// called whenever something "hardware oriented" changes and should leave// the hardware ready to send/receive packets.//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -