From 27de4e1fb8bcdbdd8cb882fc0d7a2c152b4e027a Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 3 Apr 2018 07:20:11 +0200 Subject: bsps: Move libchip to bsps This patch is a part of the BSP source reorganization. Update #3285. --- c/src/libchip/Makefile.am | 71 +- c/src/libchip/display/disp_fonts.h | 55 - c/src/libchip/display/disp_hcms29xx.c | 932 -------- c/src/libchip/display/font_hcms29xx.c | 1820 --------------- c/src/libchip/display/font_hcms29xx.h | 36 - c/src/libchip/flash/am29lv160.c | 473 ---- c/src/libchip/i2c/i2c-2b-eeprom.c | 177 -- c/src/libchip/i2c/i2c-ds1621.c | 128 - c/src/libchip/i2c/i2c-sc620.c | 95 - c/src/libchip/i2c/spi-flash-m25p40.c | 60 - c/src/libchip/i2c/spi-fram-fm25l256.c | 60 - c/src/libchip/i2c/spi-memdrv.c | 442 ---- c/src/libchip/i2c/spi-sd-card.c | 1322 ----------- c/src/libchip/ide/ata.c | 1360 ----------- c/src/libchip/ide/ata_util.c | 215 -- c/src/libchip/ide/ide_controller.c | 200 -- c/src/libchip/network/README | 12 - c/src/libchip/network/README.3com | 3 - c/src/libchip/network/README.cs8900 | 26 - c/src/libchip/network/README.dec21140 | 116 - c/src/libchip/network/README.i82586 | 1 - c/src/libchip/network/README.open_eth | 72 - c/src/libchip/network/README.sonic | 135 -- c/src/libchip/network/README.tulipclone | 101 - c/src/libchip/network/cs8900.c | 1216 ---------- c/src/libchip/network/cs8900.c.bsp | 510 ---- c/src/libchip/network/cs8900.h.bsp | 38 - c/src/libchip/network/dec21140.c | 1112 --------- c/src/libchip/network/elnk.c | 3553 ---------------------------- c/src/libchip/network/greth.c | 1196 ---------- c/src/libchip/network/i82586.c | 2198 ------------------ c/src/libchip/network/i82586reg.h | 448 ---- c/src/libchip/network/if_dc.c | 3849 ------------------------------- c/src/libchip/network/if_fxp.c | 2339 ------------------- c/src/libchip/network/if_fxpreg.h | 370 --- c/src/libchip/network/open_eth.c | 767 ------ c/src/libchip/network/smc91111.c | 1653 ------------- c/src/libchip/network/smc91111config.h | 118 - c/src/libchip/network/sonic.c | 1685 -------------- c/src/libchip/rtc/README.ds1643 | 3 - c/src/libchip/rtc/README.icm7170 | 48 - c/src/libchip/rtc/README.m48t08 | 44 - c/src/libchip/rtc/README.m48t18 | 1 - c/src/libchip/rtc/README.mc146818a | 1 - c/src/libchip/rtc/STATUS | 33 - c/src/libchip/rtc/ds1375.c | 461 ---- c/src/libchip/rtc/icm7170.c | 168 -- c/src/libchip/rtc/icm7170_reg.c | 60 - c/src/libchip/rtc/icm7170_reg2.c | 20 - c/src/libchip/rtc/icm7170_reg4.c | 20 - c/src/libchip/rtc/icm7170_reg8.c | 20 - c/src/libchip/rtc/m48t08.c | 161 -- c/src/libchip/rtc/m48t08_reg.c | 60 - c/src/libchip/rtc/m48t08_reg2.c | 20 - c/src/libchip/rtc/m48t08_reg4.c | 20 - c/src/libchip/rtc/m48t08_reg8.c | 20 - c/src/libchip/rtc/mc146818a.c | 180 -- c/src/libchip/rtc/mc146818a_ioreg.c | 56 - c/src/libchip/rtc/rtcprobe.c | 21 - c/src/libchip/serial/README | 13 - c/src/libchip/serial/README.mc68681 | 83 - c/src/libchip/serial/README.ns16550 | 82 - c/src/libchip/serial/README.xr88681 | 2 - c/src/libchip/serial/README.z85c30 | 74 - c/src/libchip/serial/STATUS | 48 - c/src/libchip/serial/mc68681.c | 776 ------- c/src/libchip/serial/mc68681_baud.c | 124 - c/src/libchip/serial/mc68681_p.h | 323 --- c/src/libchip/serial/mc68681_reg.c | 61 - c/src/libchip/serial/mc68681_reg2.c | 20 - c/src/libchip/serial/mc68681_reg4.c | 20 - c/src/libchip/serial/mc68681_reg8.c | 20 - c/src/libchip/serial/ns16550-context.c | 814 ------- c/src/libchip/serial/ns16550.c | 875 ------- c/src/libchip/serial/serprobe.c | 13 - c/src/libchip/serial/z85c30.c | 893 ------- c/src/libchip/serial/z85c30_p.h | 420 ---- c/src/libchip/serial/z85c30_reg.c | 72 - 78 files changed, 1 insertion(+), 35113 deletions(-) delete mode 100644 c/src/libchip/display/disp_fonts.h delete mode 100644 c/src/libchip/display/disp_hcms29xx.c delete mode 100644 c/src/libchip/display/font_hcms29xx.c delete mode 100644 c/src/libchip/display/font_hcms29xx.h delete mode 100644 c/src/libchip/flash/am29lv160.c delete mode 100644 c/src/libchip/i2c/i2c-2b-eeprom.c delete mode 100644 c/src/libchip/i2c/i2c-ds1621.c delete mode 100644 c/src/libchip/i2c/i2c-sc620.c delete mode 100644 c/src/libchip/i2c/spi-flash-m25p40.c delete mode 100644 c/src/libchip/i2c/spi-fram-fm25l256.c delete mode 100644 c/src/libchip/i2c/spi-memdrv.c delete mode 100644 c/src/libchip/i2c/spi-sd-card.c delete mode 100644 c/src/libchip/ide/ata.c delete mode 100644 c/src/libchip/ide/ata_util.c delete mode 100644 c/src/libchip/ide/ide_controller.c delete mode 100644 c/src/libchip/network/README delete mode 100644 c/src/libchip/network/README.3com delete mode 100644 c/src/libchip/network/README.cs8900 delete mode 100644 c/src/libchip/network/README.dec21140 delete mode 100644 c/src/libchip/network/README.i82586 delete mode 100644 c/src/libchip/network/README.open_eth delete mode 100644 c/src/libchip/network/README.sonic delete mode 100644 c/src/libchip/network/README.tulipclone delete mode 100644 c/src/libchip/network/cs8900.c delete mode 100644 c/src/libchip/network/cs8900.c.bsp delete mode 100644 c/src/libchip/network/cs8900.h.bsp delete mode 100644 c/src/libchip/network/dec21140.c delete mode 100644 c/src/libchip/network/elnk.c delete mode 100644 c/src/libchip/network/greth.c delete mode 100644 c/src/libchip/network/i82586.c delete mode 100644 c/src/libchip/network/i82586reg.h delete mode 100644 c/src/libchip/network/if_dc.c delete mode 100644 c/src/libchip/network/if_fxp.c delete mode 100644 c/src/libchip/network/if_fxpreg.h delete mode 100644 c/src/libchip/network/open_eth.c delete mode 100644 c/src/libchip/network/smc91111.c delete mode 100644 c/src/libchip/network/smc91111config.h delete mode 100644 c/src/libchip/network/sonic.c delete mode 100644 c/src/libchip/rtc/README.ds1643 delete mode 100644 c/src/libchip/rtc/README.icm7170 delete mode 100644 c/src/libchip/rtc/README.m48t08 delete mode 100644 c/src/libchip/rtc/README.m48t18 delete mode 100644 c/src/libchip/rtc/README.mc146818a delete mode 100644 c/src/libchip/rtc/STATUS delete mode 100644 c/src/libchip/rtc/ds1375.c delete mode 100644 c/src/libchip/rtc/icm7170.c delete mode 100644 c/src/libchip/rtc/icm7170_reg.c delete mode 100644 c/src/libchip/rtc/icm7170_reg2.c delete mode 100644 c/src/libchip/rtc/icm7170_reg4.c delete mode 100644 c/src/libchip/rtc/icm7170_reg8.c delete mode 100644 c/src/libchip/rtc/m48t08.c delete mode 100644 c/src/libchip/rtc/m48t08_reg.c delete mode 100644 c/src/libchip/rtc/m48t08_reg2.c delete mode 100644 c/src/libchip/rtc/m48t08_reg4.c delete mode 100644 c/src/libchip/rtc/m48t08_reg8.c delete mode 100644 c/src/libchip/rtc/mc146818a.c delete mode 100644 c/src/libchip/rtc/mc146818a_ioreg.c delete mode 100644 c/src/libchip/rtc/rtcprobe.c delete mode 100644 c/src/libchip/serial/README delete mode 100644 c/src/libchip/serial/README.mc68681 delete mode 100644 c/src/libchip/serial/README.ns16550 delete mode 100644 c/src/libchip/serial/README.xr88681 delete mode 100644 c/src/libchip/serial/README.z85c30 delete mode 100644 c/src/libchip/serial/STATUS delete mode 100644 c/src/libchip/serial/mc68681.c delete mode 100644 c/src/libchip/serial/mc68681_baud.c delete mode 100644 c/src/libchip/serial/mc68681_p.h delete mode 100644 c/src/libchip/serial/mc68681_reg.c delete mode 100644 c/src/libchip/serial/mc68681_reg2.c delete mode 100644 c/src/libchip/serial/mc68681_reg4.c delete mode 100644 c/src/libchip/serial/mc68681_reg8.c delete mode 100644 c/src/libchip/serial/ns16550-context.c delete mode 100644 c/src/libchip/serial/ns16550.c delete mode 100644 c/src/libchip/serial/serprobe.c delete mode 100644 c/src/libchip/serial/z85c30.c delete mode 100644 c/src/libchip/serial/z85c30_p.h delete mode 100644 c/src/libchip/serial/z85c30_reg.c (limited to 'c/src/libchip') diff --git a/c/src/libchip/Makefile.am b/c/src/libchip/Makefile.am index 89c9688a8c..74c83f14c8 100644 --- a/c/src/libchip/Makefile.am +++ b/c/src/libchip/Makefile.am @@ -1,77 +1,8 @@ include $(top_srcdir)/automake/compile.am -noinst_LIBRARIES = -noinst_PROGRAMS = - -# display -noinst_LIBRARIES += libdisplay.a -libdisplay_a_SOURCES = display/disp_hcms29xx.c display/font_hcms29xx.c -libdisplay_a_CPPFLAGS = $(AM_CPPFLAGS) - -# flash -noinst_LIBRARIES += libflash.a -libflash_a_SOURCES = flash/am29lv160.c -libflash_a_CPPFLAGS = $(AM_CPPFLAGS) - -# ide -noinst_LIBRARIES += libide.a -libide_a_SOURCES = ide/ata.c ide/ata_util.c ide/ide_controller.c -libide_a_CPPFLAGS = $(AM_CPPFLAGS) - -# network -if HAS_NETWORKING -noinst_LIBRARIES += libnetchip.a -libnetchip_a_CPPFLAGS = $(AM_CPPFLAGS) -libnetchip_a_SOURCES = network/cs8900.c network/dec21140.c network/i82586.c \ - network/sonic.c network/if_fxp.c network/elnk.c network/open_eth.c \ - network/if_dc.c -if !HAS_SMP -libnetchip_a_SOURCES += network/greth.c -endif -libnetchip_a_SOURCES += network/smc91111.c network/smc91111config.h -endif - - -# rtc -noinst_LIBRARIES += librtcio.a -librtcio_a_CPPFLAGS = $(AM_CPPFLAGS) -librtcio_a_SOURCES = rtc/rtcprobe.c rtc/icm7170.c rtc/icm7170_reg.c \ - rtc/icm7170_reg2.c rtc/icm7170_reg4.c rtc/icm7170_reg8.c rtc/m48t08.c \ - rtc/m48t08_reg.c rtc/m48t08_reg2.c rtc/m48t08_reg4.c rtc/m48t08_reg8.c \ - rtc/mc146818a.c rtc/mc146818a_ioreg.c rtc/ds1375.c - - -# i2c -noinst_LIBRARIES += libi2cio.a - -libi2cio_a_CPPFLAGS = $(AM_CPPFLAGS) -libi2cio_a_SOURCES = i2c/i2c-ds1621.h \ - i2c/i2c-2b-eeprom.h \ - i2c/spi-memdrv.h \ - i2c/spi-flash-m25p40.h \ - i2c/spi-fram-fm25l256.h \ - i2c/i2c-ds1621.c \ - i2c/i2c-2b-eeprom.c \ - i2c/i2c-sc620.c \ - i2c/spi-memdrv.c \ - i2c/spi-flash-m25p40.c \ - i2c/spi-fram-fm25l256.c \ - i2c/spi-sd-card.c - -# serial -noinst_LIBRARIES += libserialio.a -libserialio_a_CPPFLAGS = $(AM_CPPFLAGS) -libserialio_a_SOURCES = serial/mc68681.c serial/mc68681_baud.c \ - serial/mc68681_reg.c serial/mc68681_reg2.c serial/mc68681_reg4.c \ - serial/mc68681_reg8.c serial/ns16550.c serial/z85c30.c \ - serial/z85c30_reg.c serial/serprobe.c serial/mc68681_p.h \ - serial/z85c30_p.h -libserialio_a_SOURCES += serial/ns16550-context.c - - ## shmdr if HAS_MP -noinst_LIBRARIES += libshmdr.a +noinst_LIBRARIES = libshmdr.a libshmdr_a_CPPFLAGS = $(AM_CPPFLAGS) libshmdr_a_SOURCES = shmdr/addlq.c shmdr/cnvpkt.c shmdr/getlq.c shmdr/dump.c \ shmdr/fatal.c shmdr/getpkt.c shmdr/init.c shmdr/initlq.c shmdr/intr.c \ diff --git a/c/src/libchip/display/disp_fonts.h b/c/src/libchip/display/disp_fonts.h deleted file mode 100644 index 39e909390a..0000000000 --- a/c/src/libchip/display/disp_fonts.h +++ /dev/null @@ -1,55 +0,0 @@ -/*===============================================================*\ -| Project: display driver for HCMS29xx | -+-----------------------------------------------------------------+ -| File: disp_fonts.h | -+-----------------------------------------------------------------+ -| Copyright (c) 2008 | -| Embedded Brains GmbH | -| Obere Lagerstr. 30 | -| D-82178 Puchheim | -| Germany | -| rtems@embedded-brains.de | -+-----------------------------------------------------------------+ -| The license and distribution terms for this file may be | -| found in the file LICENSE in this distribution or at | -| http://www.rtems.org/license/LICENSE. | -| | -+-----------------------------------------------------------------+ -| This file declares general data structures for font management | -\*===============================================================*/ - -#ifndef DISP_FONTS_H -#define DISP_FONTS_H - -#include - -typedef int8_t disp_font_dimen; - -struct disp_font_bounding_box -{ - disp_font_dimen w, h, x, y; -}; - -struct disp_font_glyph -{ - struct disp_font_bounding_box bb; - disp_font_dimen wx, wy; - const unsigned char *bitmap; -}; - -struct disp_font_base -{ - int8_t trans; - struct disp_font_bounding_box fbb; - disp_font_dimen ascent, descent; - uint8_t default_char; - struct disp_font_glyph *latin1[256]; -}; - -typedef struct disp_font_base *disp_font_t; - -/* Prototypes ------------------------------------------------- */ - -/* End -------------------------------------------------------- */ - -#endif /* not defined DISP_FONTS_H */ diff --git a/c/src/libchip/display/disp_hcms29xx.c b/c/src/libchip/display/disp_hcms29xx.c deleted file mode 100644 index 5730b36ea9..0000000000 --- a/c/src/libchip/display/disp_hcms29xx.c +++ /dev/null @@ -1,932 +0,0 @@ -/*===============================================================*\ -| Project: display driver for HCMS29xx | -+-----------------------------------------------------------------+ -| File: disp_hcms29xx.c | -+-----------------------------------------------------------------+ -| Copyright (c) 2008 | -| Embedded Brains GmbH | -| Obere Lagerstr. 30 | -| D-82178 Puchheim | -| Germany | -| rtems@embedded-brains.de | -+-----------------------------------------------------------------+ -| The license and distribution terms for this file may be | -| found in the file LICENSE in this distribution or at | -| http://www.rtems.org/license/LICENSE. | -+-----------------------------------------------------------------+ -| this file contains the SPI based driver for a HCMS29xx 4 digit | -| alphanumeric LED display | -\*===============================================================*/ - -#include -#include - -#include -#include -#include -#include -#include -#include "font_hcms29xx.h" -#define FONT_BASE font_hcms29xx_base - - -#define DISP_HCMS29XX_DIGIT_CNT (4) -#define DISP_HCMS29XX_SEMA_NAME rtems_build_name('D','4','I','Q') -#define DISP_HCMS29XX_TRNS_SEMA_NAME rtems_build_name('D','4','T','R') -#define DISP_HCMS29XX_TIMER_NAME rtems_build_name('D','4','T','M') -#define DISP_HCMS29XX_TASK_NAME rtems_build_name('D','4','T','A') - -#define DISP_HCMS29XX_EVENT_TIMER RTEMS_EVENT_1 -#define DISP_HCMS29XX_EVENT_NEWSTR RTEMS_EVENT_2 - - -static disp_font_t disp_hcms29xx_font_normal; -static disp_font_t disp_hcms29xx_font_rotate; -const rtems_libi2c_tfr_mode_t spi_disphcms29xx_tfr_mode = { - .baudrate = 1000000, - .bits_per_char = 8, - .lsb_first = true, - .clock_inv = true, - .clock_phs = true, - .idle_char = 0 -}; - -static disp_hcms29xx_drv_t disp_hcms29xx_drv_tbl; - -/*========================================= - * font management functions - */ - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static rtems_status_code disp_hcms29xx_font_struct_size - ( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| compute size of font data structure tree | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - disp_font_t src, /* source font */ - size_t *dst_size /* destination: size of font struct*/ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| rtems_status_code | -\*=========================================================================*/ -{ - - rtems_status_code rc = RTEMS_SUCCESSFUL; - size_t font_size = 0; - size_t glyph_idx; - /* - * check parameters - */ - if ((rc == RTEMS_SUCCESSFUL) && - (src == NULL)) { - rc = RTEMS_INVALID_ADDRESS; - } - if (rc == RTEMS_SUCCESSFUL) { - font_size = - sizeof(*src); /* font_base structure */ - } - glyph_idx = 0; - while ((rc == RTEMS_SUCCESSFUL) && - (glyph_idx < (sizeof(src->latin1)/sizeof(src->latin1[0])))) { - if (src->latin1[glyph_idx] != NULL) { - font_size += sizeof(*(src->latin1[glyph_idx])) - + (size_t) src->latin1[glyph_idx]->bb.w; - } - glyph_idx++; - } - *dst_size = font_size; - - return rc; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static inline unsigned char disp_hcms29xx_bitswap - ( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| swap data bits in byte (7<->0 , 6<->1 etc) | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - unsigned char byte -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| rtems_status_code | -\*=========================================================================*/ -{ - unsigned char result = 0; - int smsk,dmsk; - for (smsk = 0x01,dmsk=0x80; - smsk < 0x100; - smsk<<=1 ,dmsk>>=1) { - if ((byte & smsk) != 0) { - result |= (unsigned char) dmsk; - } - } - return result; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static rtems_status_code disp_hcms29xx_copy_font - ( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| copy font data from source to dest font structure | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - disp_font_t src, /* source font */ - struct disp_font_base *dst, /* ptr to destination font */ - int shift_cnt, /* shift count for font */ - bool do_rotate /* rotate font, if true */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| rtems_status_code | -\*=========================================================================*/ -{ - - rtems_status_code rc = RTEMS_SUCCESSFUL; - char *alloc_next = (char *)dst; - size_t glyph_idx = 0; - int glyph_size; - unsigned char byte; - int bcnt; - - /* - * check parameters - */ - if ((rc == RTEMS_SUCCESSFUL) && - ((src == NULL) || - (dst == NULL))) { - rc = RTEMS_INVALID_ADDRESS; - } - /* - * copy font_base structure - */ - if (rc == RTEMS_SUCCESSFUL) { - *dst = *src; - alloc_next += sizeof(*dst); - } - /* - * for all glyphs: assign own glyph memory - */ - glyph_idx = 0; - while ((rc == RTEMS_SUCCESSFUL) && - glyph_idx < (sizeof(src->latin1)/sizeof(src->latin1[0]))) { - if (src->latin1[glyph_idx] != NULL) { - /* - * allocate space for glyph - */ - dst->latin1[glyph_idx] = (struct disp_font_glyph *)alloc_next; - alloc_next += sizeof(*(dst->latin1[glyph_idx])); - /* - * copy source values. - * Note: bitmap will be reassigned later - */ - *(struct disp_font_glyph *)(dst->latin1[glyph_idx]) = - *(src->latin1[glyph_idx]); - } - else { - dst->latin1[glyph_idx] = NULL; - } - glyph_idx++; - } - - /* - * for all glyphs: reassign bitmap - */ - glyph_idx = 0; - while ((rc == RTEMS_SUCCESSFUL) && - glyph_idx < (sizeof(src->latin1)/sizeof(src->latin1[0]))) { - if (src->latin1[glyph_idx] != NULL) { - glyph_size = src->latin1[glyph_idx]->bb.w; - /* - * allocate space for glyph_bitmap - */ - dst->latin1[glyph_idx]->bitmap = (const unsigned char *) alloc_next; - alloc_next += glyph_size; - /* - * copy/transform bitmap - */ - for (bcnt = 0;bcnt < glyph_size;bcnt++) { - if (do_rotate) { - byte = src->latin1[glyph_idx]->bitmap[glyph_size - 1 - bcnt]; - byte = disp_hcms29xx_bitswap(byte); - } - else { - byte = src->latin1[glyph_idx]->bitmap[bcnt]; - } - if (shift_cnt < 0) { - byte = byte >> shift_cnt; - } - else if (shift_cnt > 0) { - byte = byte >> shift_cnt; - } - ((unsigned char *)(dst->latin1[glyph_idx]->bitmap))[bcnt] = byte; - } - } - glyph_idx++; - } - return rc; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static rtems_status_code disp_hcms29xx_alloc_copy_font - ( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| copy font data from source to dest font structure, alloc all data | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - const disp_font_t src, /* source font */ - disp_font_t *dst, /* ptr to destination font */ - int shift_cnt, /* shift count for font */ - bool do_rotate /* rotate font, if true */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| rtems_status_code | -\*=========================================================================*/ -{ - - rtems_status_code rc = RTEMS_SUCCESSFUL; - size_t src_size = 0; - /* - * check parameters - */ - if ((rc == RTEMS_SUCCESSFUL) && - ((src == NULL) - || (dst == NULL))) { - rc = RTEMS_INVALID_ADDRESS; - } - /* - * determine size of source data - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = disp_hcms29xx_font_struct_size(src,&src_size); - } - /* - * allocate proper data area - */ - if (rc == RTEMS_SUCCESSFUL) { - *dst = malloc(src_size); - if (*dst == NULL) { - rc = RTEMS_UNSATISFIED; - } - } - /* - * scan through source data, copy to dest - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = disp_hcms29xx_copy_font(src,*dst,shift_cnt,do_rotate); - } - return rc; -} - -/*========================================= - * SPI communication functions - */ - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static rtems_status_code disp_hcms29xx_send_to_display - ( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| request access semaphore to SPI, prepare buffer descriptors, start | -| transfer via SPI to display | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - disp_hcms29xx_drv_t *softc_ptr, - const volatile char *disp_buffer /* start of chars to display (4 chars or 'til \0)*/ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| rtems_status_code | -\*=========================================================================*/ -{ - rtems_status_code rc = RTEMS_SUCCESSFUL; - bool char_avail; - const struct disp_font_glyph *glyph_ptr; - disp_font_t curr_font; - int i, ret_cnt; - unsigned char c; - - /* - * select device, set transfer mode, address device - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_start(softc_ptr->disp_param.minor); - } - /* - * set transfer mode - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = -rtems_libi2c_ioctl(softc_ptr->disp_param.minor, - RTEMS_LIBI2C_IOCTL_SET_TFRMODE, - &spi_disphcms29xx_tfr_mode); - } - - /* - * address device - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_addr(softc_ptr->disp_param.minor,true); - } - - /* - * send data - */ - if (rc == RTEMS_SUCCESSFUL) { - curr_font = - softc_ptr->disp_param.rotate - ? disp_hcms29xx_font_rotate - : disp_hcms29xx_font_normal; - - char_avail = true; - /* - * FIXME: for rotated display, write last character first... - * maybe we should copy everything to a common buffer and use - * ONE SPI transfer? - */ - for (i = 0; - ((rc == RTEMS_SUCCESSFUL) && - (i < DISP_HCMS29XX_DIGIT_CNT)); - i++) { - /* test for end of string... */ - c = disp_buffer[i]; /* perform consistent read of disp_buffer */ - if (char_avail && (c == '\0')) { - char_avail = false; - } - glyph_ptr = (char_avail - ? curr_font->latin1[c] - : NULL); - if (glyph_ptr == NULL) { - glyph_ptr = curr_font->latin1[' ']; - } - - /* - * send 5 bytes from (char *)glyph_ptr->bitmap to SPI - */ - if (rc == RTEMS_SUCCESSFUL) { - ret_cnt = rtems_libi2c_write_bytes(softc_ptr->disp_param.minor, - glyph_ptr->bitmap,5); - if (ret_cnt < 0) { - rc = -ret_cnt; - } - } - } - } - /* - * finish transfer - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_stop(softc_ptr->disp_param.minor); - } - - return rc; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static rtems_status_code disp_hcms29xx_send_to_control - ( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| request access semaphore to SPI, prepare buffer descriptors, start | -| transfer via SPI to display | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - disp_hcms29xx_drv_t *softc_ptr, - int pwm, /* value for pwm of LEDs, 0..15 */ - int peak, /* value for peak current for LEDs, 0..3 */ - int sleep, /* value to make display "sleep" (0..1 */ - int div, /* divider for external osc input, unused here */ - int chain /* mode to drive other displays, unused here */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| rtems_status_code | -\*=========================================================================*/ -{ - rtems_status_code rc = RTEMS_SUCCESSFUL; - int run, ret_cnt; - uint8_t ctrl_buffer; - - /* two accesses, control word 0 and 1 */ - for (run = 0; - ((rc == RTEMS_SUCCESSFUL) && (run <= 1)); - run++) { - if (rc == RTEMS_SUCCESSFUL) { - if (run == 0) { - ctrl_buffer = - (0 << 7) | - ((sleep & 0x01) << 6) | - ((peak & 0x03) << 4) | - ((pwm & 0x0f) << 0); - } - else { - ctrl_buffer = - (1 << 7) | - ((div & 0x01) << 1) | - ((chain & 0x01) << 0); - } - /* - * select device, set transfer mode, address device - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_start(softc_ptr->disp_param.minor); - } - /* - * set transfer mode - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = -rtems_libi2c_ioctl(softc_ptr->disp_param.minor, - RTEMS_LIBI2C_IOCTL_SET_TFRMODE, - &spi_disphcms29xx_tfr_mode); - } - - /* - * address device - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_addr(softc_ptr->disp_param.minor,true); - } - - /* - * send 1 byte from ctrl_buffer - */ - if (rc == RTEMS_SUCCESSFUL) { - ret_cnt = rtems_libi2c_write_bytes(softc_ptr->disp_param.minor, - &ctrl_buffer,1); - if (ret_cnt < 0) { - rc = -ret_cnt; - } - } - } - } /* next run ... */ - - /* - * finish transfer - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_stop(softc_ptr->disp_param.minor); - } - - return rc; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static rtems_timer_service_routine disp_hcms29xx_timer_sr -/*-------------------------------------------------------------------------*\ -| Purpose: | -| this task updates the string in the display | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ -( - rtems_id id, /* ID of timer, not used */ - void * arg /* calling arg: softc_ptr */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - disp_hcms29xx_drv_t *softc_ptr = arg; - - rtems_event_send(softc_ptr->disp_param.task_id, DISP_HCMS29XX_EVENT_TIMER); -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static rtems_task disp_hcms29xx_update_task - ( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| this task updates the string in the display | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_task_argument argument -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - rtems_event_set my_events; - rtems_status_code rc = RTEMS_SUCCESSFUL; - int disp_offset = 0; - rtems_id disp_hcms29xx_timer_id; - disp_hcms29xx_drv_t *softc_ptr = &disp_hcms29xx_drv_tbl; - - /* - * initialize display: - */ - /* - * set control attributes for display - * maximum brightness... - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = disp_hcms29xx_send_to_control(softc_ptr, - 14,3,1,0,0);/* pwm/peak/nosleep/div/chain */ - } - - /* - * set display to blank - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = disp_hcms29xx_send_to_display(softc_ptr, - ""); - } - - /* - * create timer for scrolling - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_timer_create(DISP_HCMS29XX_TIMER_NAME, - &disp_hcms29xx_timer_id); - } - - while (rc == RTEMS_SUCCESSFUL) { - /* - * wait for any event - */ - rc = rtems_event_receive(DISP_HCMS29XX_EVENT_NEWSTR | - DISP_HCMS29XX_EVENT_TIMER , - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &my_events); - if (my_events & DISP_HCMS29XX_EVENT_NEWSTR) { - /* - * fetch new string consistently into local buffer - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_semaphore_obtain(softc_ptr->disp_param.trns_sema_id, - RTEMS_WAIT,RTEMS_NO_TIMEOUT); - } - if (rc == RTEMS_SUCCESSFUL) { - strncpy(softc_ptr->disp_param.disp_buffer, - softc_ptr->disp_param.trns_buffer, - sizeof(softc_ptr->disp_param.disp_buffer)); - softc_ptr->disp_param.disp_buffer[sizeof(softc_ptr->disp_param.disp_buffer)-1] = '\0'; - softc_ptr->disp_param.disp_buf_cnt = - (int) strlen(softc_ptr->disp_param.disp_buffer); - } - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_semaphore_release(softc_ptr->disp_param.trns_sema_id); - } - /* - * set initial offset to negative value - * to make string static for some ticks - */ - disp_offset = -4; - } - if (my_events & DISP_HCMS29XX_EVENT_TIMER) { - /* - * increase disp_offset, if possible, otherwise reset it - */ - if ((disp_offset < 0) || - (disp_offset < softc_ptr->disp_param.disp_buf_cnt- - DISP_HCMS29XX_DIGIT_CNT/2)) { - disp_offset++; - } - else { - disp_offset = -4; - } - } - /* - * display string, starting from disp_offset - */ - if (disp_offset < 0) { - rc = disp_hcms29xx_send_to_display(softc_ptr, - softc_ptr->disp_param.disp_buffer); - } - else if (disp_offset - < (softc_ptr->disp_param.disp_buf_cnt - DISP_HCMS29XX_DIGIT_CNT)) { - rc = disp_hcms29xx_send_to_display(softc_ptr, - softc_ptr->disp_param.disp_buffer+disp_offset); - } - else { - rc = disp_hcms29xx_send_to_display(softc_ptr, - softc_ptr->disp_param.disp_buffer - + softc_ptr->disp_param.disp_buf_cnt - - DISP_HCMS29XX_DIGIT_CNT); - } - /* - * activate timer, if needed - */ - if (rc == RTEMS_SUCCESSFUL) { - if (softc_ptr->disp_param.disp_buf_cnt > DISP_HCMS29XX_DIGIT_CNT) { - rc = rtems_timer_fire_after(disp_hcms29xx_timer_id, - 50, - disp_hcms29xx_timer_sr, - NULL); - } - else { - rc = rtems_timer_cancel(disp_hcms29xx_timer_id); - } - } - } - /* - * FIXME: display task is dead... - */ -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static rtems_status_code disp_hcms29xx_update - ( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| move given string to display task | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - disp_hcms29xx_drv_t *softc_ptr, - const char *src -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| rtems_status_code | -\*=========================================================================*/ -{ - rtems_status_code rc = RTEMS_SUCCESSFUL; - - /* - * obtain trns semaphore - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_semaphore_obtain(softc_ptr->disp_param.trns_sema_id, - RTEMS_WAIT,RTEMS_NO_TIMEOUT); - } - /* - * copy string... - */ - strncpy(softc_ptr->disp_param.trns_buffer,src, - sizeof(softc_ptr->disp_param.trns_buffer)); - softc_ptr->disp_param.trns_buffer[sizeof(softc_ptr->disp_param.trns_buffer)-1] = '\0'; - - /* - * release trns semaphore - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_semaphore_release(softc_ptr->disp_param.trns_sema_id); - } - - /* - * send event to task - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_event_send(softc_ptr->disp_param.task_id, - DISP_HCMS29XX_EVENT_NEWSTR); - } - - return rc; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -rtems_device_driver disp_hcms29xx_dev_initialize - ( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| prepare the display device driver to accept write calls | -| register device with its name | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_device_major_number major, - rtems_device_minor_number minor, - void *arg -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| rtems_status_code | -\*=========================================================================*/ -/* - * Initialize and register the device - */ -{ - rtems_status_code rc = RTEMS_SUCCESSFUL; - disp_hcms29xx_drv_t *softc_ptr = &disp_hcms29xx_drv_tbl; - - /* - * initialize font management - * FIXME: check, that default glyph exists - * FIXME: check font size to be 5x7 - */ - /* - * translate font according to direction/baseline - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = disp_hcms29xx_alloc_copy_font( - &FONT_BASE, - &disp_hcms29xx_font_normal, - FONT_BASE.descent, /* shift to visibility... */ - FALSE); /* do not rotate */ - } - /* FIXME: translate font for rotation */ - if (rc == RTEMS_SUCCESSFUL) { - rc = disp_hcms29xx_alloc_copy_font(&FONT_BASE, - &disp_hcms29xx_font_rotate, - 0, /* do not shift */ - true); /* rotate font */ - } - /* - * create the trns_buffer semaphore - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_semaphore_create (DISP_HCMS29XX_TRNS_SEMA_NAME,1, - RTEMS_PRIORITY - |RTEMS_BINARY_SEMAPHORE - |RTEMS_INHERIT_PRIORITY - |RTEMS_NO_PRIORITY_CEILING - |RTEMS_LOCAL, - 0, - &softc_ptr->disp_param.trns_sema_id); - } - - /* - * create and start display task - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_task_create(DISP_HCMS29XX_TASK_NAME, - 20, - RTEMS_MINIMUM_STACK_SIZE, - RTEMS_INTERRUPT_LEVEL(0) | RTEMS_TIMESLICE, - RTEMS_DEFAULT_ATTRIBUTES, - &softc_ptr->disp_param.task_id); - } - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_task_start(softc_ptr->disp_param.task_id, - disp_hcms29xx_update_task,0); - } - return rc; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -rtems_device_driver disp_hcms29xx_dev_open -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| open the display device | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_device_major_number major, - rtems_device_minor_number minor, - void *arg -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| rtems_status_code | -\*=========================================================================*/ -{ - disp_hcms29xx_drv_t *softc_ptr = &disp_hcms29xx_drv_tbl; - /* - * ensure, that disp_hcms29xx device is assumed to be empty - */ - softc_ptr->disp_param.dev_buf_cnt = 0; - - return RTEMS_SUCCESSFUL; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -rtems_device_driver disp_hcms29xx_dev_write -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| write to display device | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_device_major_number major, - rtems_device_minor_number minor, - void *arg -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| rtems_status_code | -\*=========================================================================*/ -{ - rtems_libio_rw_args_t *args = arg; - uint32_t cnt; - disp_hcms29xx_drv_t *softc_ptr = &disp_hcms29xx_drv_tbl; - - for (cnt = 0;cnt < args->count;cnt++) { - /* - * accumulate characters written into display dev buffer - */ - if (((softc_ptr->disp_param.dev_buf_cnt > 0) - &&((args->buffer[cnt] == '\n') - || (args->buffer[cnt] == '\0')) - ) - ||( softc_ptr->disp_param.dev_buf_cnt >= - (int) sizeof(softc_ptr->disp_param.dev_buffer) - 1)) { - softc_ptr->disp_param.dev_buffer[softc_ptr->disp_param.dev_buf_cnt] = '\0'; - /* - * transfer string to display string, redisplay it... - */ - disp_hcms29xx_update(softc_ptr,softc_ptr->disp_param.dev_buffer); - softc_ptr->disp_param.dev_buf_cnt = 0; - } - /* - * write to dev_buf, if '\n' occured or display device buffer is full - */ - if ((args->buffer[cnt] != '\n') && - (args->buffer[cnt] != '\0')) { - softc_ptr->disp_param.dev_buffer[softc_ptr->disp_param.dev_buf_cnt++] = - args->buffer[cnt]; - } - } - args->bytes_moved = args->count; - - return RTEMS_SUCCESSFUL; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -rtems_device_driver disp_hcms29xx_dev_close -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| close the display device | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_device_major_number major, - rtems_device_minor_number minor, - void *arg -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| rtems_status_code | -\*=========================================================================*/ -{ - - return RTEMS_SUCCESSFUL; -} - -/* - * driver operation tables - */ -static rtems_driver_address_table disp_hcms29xx_ops = { - .initialization_entry = disp_hcms29xx_dev_initialize, - .open_entry = disp_hcms29xx_dev_open, - .write_entry = disp_hcms29xx_dev_write, - .close_entry = disp_hcms29xx_dev_close -}; - - -static disp_hcms29xx_drv_t disp_hcms29xx_drv_tbl = { - {/* public fields */ - .ops = &disp_hcms29xx_ops, - .size = sizeof (disp_hcms29xx_drv_t), - }, - { /* our private fields */ - 0, - { 0 }, - 0, - { 0 }, - { 0 }, - 0, - 0, - 0, - false - } -}; - -rtems_libi2c_drv_t *disp_hcms29xx_driver_descriptor = - &disp_hcms29xx_drv_tbl.libi2c_drv_entry; - diff --git a/c/src/libchip/display/font_hcms29xx.c b/c/src/libchip/display/font_hcms29xx.c deleted file mode 100644 index e25cca2eca..0000000000 --- a/c/src/libchip/display/font_hcms29xx.c +++ /dev/null @@ -1,1820 +0,0 @@ -/*===============================================================*\ -| Project: display driver for HCMS29xx | -+-----------------------------------------------------------------+ -| File: font_hcms29xx.c | -+-----------------------------------------------------------------+ -| Copyright (c) 2008 | -| Embedded Brains GmbH | -| Obere Lagerstr. 30 | -| D-82178 Puchheim | -| Germany | -| rtems@embedded-brains.de | -+-----------------------------------------------------------------+ -| The license and distribution terms for this file may be | -| found in the file LICENSE in this distribution or at | -| http://www.rtems.org/license/LICENSE. | -+-----------------------------------------------------------------+ -| This file defines the 5x7 bit font used in disp_hcms29xx | -\*===============================================================*/ - -#include -#include "disp_fonts.h" - -const unsigned char bitmap_hp_fixed_5_7_0 [5] = { - 0x08, - 0x1c, - 0x3e, - 0x7f, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_0 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_0, -}; - -const unsigned char bitmap_hp_fixed_5_7_1 [5] = { - 0x30, - 0x45, - 0x48, - 0x40, - 0x30 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_1 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_1, -}; - -const unsigned char bitmap_hp_fixed_5_7_2 [5] = { - 0x45, - 0x29, - 0x11, - 0x29, - 0x45 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_2 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_2, -}; - -const unsigned char bitmap_hp_fixed_5_7_3 [5] = { - 0x7d, - 0x09, - 0x11, - 0x21, - 0x7d -}; -struct disp_font_glyph glyph_hp_fixed_5_7_3 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_3, -}; - -const unsigned char bitmap_hp_fixed_5_7_4 [5] = { - 0x7d, - 0x09, - 0x05, - 0x05, - 0x79 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_4 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_4, -}; - -const unsigned char bitmap_hp_fixed_5_7_5 [5] = { - 0x38, - 0x44, - 0x44, - 0x38, - 0x44 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_5 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_5, -}; - -const unsigned char bitmap_hp_fixed_5_7_6 [5] = { - 0x7e, - 0x01, - 0x29, - 0x2e, - 0x10 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_6 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_6, -}; - -const unsigned char bitmap_hp_fixed_5_7_7 [5] = { - 0x30, - 0x4a, - 0x4d, - 0x49, - 0x30 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_7 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_7, -}; - -const unsigned char bitmap_hp_fixed_5_7_8 [5] = { - 0x60, - 0x50, - 0x48, - 0x50, - 0x60 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_8 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_8, -}; - -const unsigned char bitmap_hp_fixed_5_7_9 [5] = { - 0x1e, - 0x04, - 0x04, - 0x38, - 0x40 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_9 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_9, -}; - -const unsigned char bitmap_hp_fixed_5_7_10 [5] = { - 0x3e, - 0x49, - 0x49, - 0x49, - 0x3e -}; -struct disp_font_glyph glyph_hp_fixed_5_7_10 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_10, -}; - -const unsigned char bitmap_hp_fixed_5_7_11 [5] = { - 0x62, - 0x14, - 0x08, - 0x10, - 0x60 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_11 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_11, -}; - -const unsigned char bitmap_hp_fixed_5_7_12 [5] = { - 0x40, - 0x3c, - 0x20, - 0x20, - 0x1c -}; -struct disp_font_glyph glyph_hp_fixed_5_7_12 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_12, -}; - -const unsigned char bitmap_hp_fixed_5_7_13 [5] = { - 0x08, - 0x7c, - 0x04, - 0x7c, - 0x02 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_13 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_13, -}; - -const unsigned char bitmap_hp_fixed_5_7_14 [5] = { - 0x38, - 0x44, - 0x44, - 0x3c, - 0x04 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_14 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_14, -}; - -const unsigned char bitmap_hp_fixed_5_7_15 [5] = { - 0x41, - 0x63, - 0x55, - 0x49, - 0x41 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_15 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_15, -}; - -const unsigned char bitmap_hp_fixed_5_7_16 [5] = { - 0x10, - 0x08, - 0x78, - 0x08, - 0x04 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_16 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_16, -}; - -const unsigned char bitmap_hp_fixed_5_7_17 [5] = { - 0x18, - 0x24, - 0x7e, - 0x24, - 0x18 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_17 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_17, -}; - -const unsigned char bitmap_hp_fixed_5_7_18 [5] = { - 0x5e, - 0x61, - 0x01, - 0x61, - 0x5e -}; -struct disp_font_glyph glyph_hp_fixed_5_7_18 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_18, -}; - -const unsigned char bitmap_hp_fixed_5_7_19 [5] = { - 0x78, - 0x14, - 0x15, - 0x14, - 0x78 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_19 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_19, -}; - -const unsigned char bitmap_hp_fixed_5_7_20 [5] = { - 0x38, - 0x44, - 0x45, - 0x3c, - 0x40 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_20 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_20, -}; - -const unsigned char bitmap_hp_fixed_5_7_21 [5] = { - 0x78, - 0x15, - 0x14, - 0x15, - 0x78 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_21 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_21, -}; - -const unsigned char bitmap_hp_fixed_5_7_22 [5] = { - 0x38, - 0x45, - 0x44, - 0x3d, - 0x40 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_22 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_22, -}; - -const unsigned char bitmap_hp_fixed_5_7_23 [5] = { - 0x3c, - 0x43, - 0x42, - 0x43, - 0x3c -}; -struct disp_font_glyph glyph_hp_fixed_5_7_23 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_23, -}; - -const unsigned char bitmap_hp_fixed_5_7_24 [5] = { - 0x38, - 0x45, - 0x44, - 0x45, - 0x38 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_24 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_24, -}; - -const unsigned char bitmap_hp_fixed_5_7_25 [5] = { - 0x3c, - 0x41, - 0x40, - 0x41, - 0x3c -}; -struct disp_font_glyph glyph_hp_fixed_5_7_25 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_25, -}; - -const unsigned char bitmap_hp_fixed_5_7_26 [5] = { - 0x38, - 0x42, - 0x40, - 0x42, - 0x38 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_26 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_26, -}; - -const unsigned char bitmap_hp_fixed_5_7_27 [5] = { - 0x08, - 0x08, - 0x2a, - 0x1c, - 0x08 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_27 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_27, -}; - -const unsigned char bitmap_hp_fixed_5_7_28 [5] = { - 0x20, - 0x7e, - 0x02, - 0x02, - 0x02 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_28 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_28, -}; - -const unsigned char bitmap_hp_fixed_5_7_29 [5] = { - 0x12, - 0x19, - 0x15, - 0x12, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_29 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_29, -}; - -const unsigned char bitmap_hp_fixed_5_7_30 [5] = { - 0x48, - 0x7e, - 0x49, - 0x41, - 0x42 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_30 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_30, -}; - -const unsigned char bitmap_hp_fixed_5_7_31 [5] = { - 0x01, - 0x12, - 0x7c, - 0x12, - 0x01 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_31 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_31, -}; - -const unsigned char bitmap_hp_fixed_5_7_32 [5] = { - 0x00, - 0x00, - 0x00, - 0x00, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_32 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_32, -}; - -const unsigned char bitmap_hp_fixed_5_7_33 [5] = { - 0x00, - 0x5f, - 0x00, - 0x00, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_33 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_33, -}; - -const unsigned char bitmap_hp_fixed_5_7_34 [5] = { - 0x00, - 0x03, - 0x00, - 0x03, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_34 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_34, -}; - -const unsigned char bitmap_hp_fixed_5_7_35 [5] = { - 0x14, - 0x7f, - 0x14, - 0x7f, - 0x14 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_35 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_35, -}; - -const unsigned char bitmap_hp_fixed_5_7_36 [5] = { - 0x24, - 0x2a, - 0x7f, - 0x2a, - 0x12 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_36 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_36, -}; - -const unsigned char bitmap_hp_fixed_5_7_37 [5] = { - 0x23, - 0x13, - 0x08, - 0x64, - 0x62 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_37 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_37, -}; - -const unsigned char bitmap_hp_fixed_5_7_38 [5] = { - 0x36, - 0x49, - 0x56, - 0x20, - 0x50 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_38 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_38, -}; - -const unsigned char bitmap_hp_fixed_5_7_39 [5] = { - 0x00, - 0x0b, - 0x07, - 0x00, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_39 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_39, -}; - -const unsigned char bitmap_hp_fixed_5_7_40 [5] = { - 0x00, - 0x00, - 0x3e, - 0x41, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_40 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_40, -}; - -const unsigned char bitmap_hp_fixed_5_7_41 [5] = { - 0x00, - 0x41, - 0x3e, - 0x00, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_41 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_41, -}; - -const unsigned char bitmap_hp_fixed_5_7_42 [5] = { - 0x08, - 0x2a, - 0x1c, - 0x2a, - 0x08 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_42 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_42, -}; - -const unsigned char bitmap_hp_fixed_5_7_43 [5] = { - 0x08, - 0x08, - 0x3e, - 0x08, - 0x08 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_43 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_43, -}; - -const unsigned char bitmap_hp_fixed_5_7_44 [5] = { - 0x00, - 0x58, - 0x38, - 0x00, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_44 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_44, -}; - -const unsigned char bitmap_hp_fixed_5_7_45 [5] = { - 0x08, - 0x08, - 0x08, - 0x08, - 0x08 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_45 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_45, -}; - -const unsigned char bitmap_hp_fixed_5_7_46 [5] = { - 0x00, - 0x30, - 0x30, - 0x00, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_46 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_46, -}; - -const unsigned char bitmap_hp_fixed_5_7_47 [5] = { - 0x20, - 0x10, - 0x08, - 0x04, - 0x02 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_47 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_47, -}; - -const unsigned char bitmap_hp_fixed_5_7_48 [5] = { - 0x3e, - 0x51, - 0x49, - 0x45, - 0x3e -}; -struct disp_font_glyph glyph_hp_fixed_5_7_48 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_48, -}; - -const unsigned char bitmap_hp_fixed_5_7_49 [5] = { - 0x00, - 0x42, - 0x7f, - 0x40, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_49 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_49, -}; - -const unsigned char bitmap_hp_fixed_5_7_50 [5] = { - 0x62, - 0x51, - 0x49, - 0x49, - 0x46 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_50 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_50, -}; - -const unsigned char bitmap_hp_fixed_5_7_51 [5] = { - 0x22, - 0x41, - 0x49, - 0x49, - 0x36 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_51 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_51, -}; - -const unsigned char bitmap_hp_fixed_5_7_52 [5] = { - 0x18, - 0x14, - 0x12, - 0x7f, - 0x10 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_52 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_52, -}; - -const unsigned char bitmap_hp_fixed_5_7_53 [5] = { - 0x27, - 0x45, - 0x45, - 0x45, - 0x39 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_53 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_53, -}; - -const unsigned char bitmap_hp_fixed_5_7_54 [5] = { - 0x3c, - 0x4a, - 0x49, - 0x49, - 0x30 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_54 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_54, -}; - -const unsigned char bitmap_hp_fixed_5_7_55 [5] = { - 0x01, - 0x71, - 0x09, - 0x05, - 0x03 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_55 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_55, -}; - -const unsigned char bitmap_hp_fixed_5_7_56 [5] = { - 0x36, - 0x49, - 0x49, - 0x49, - 0x36 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_56 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_56, -}; - -const unsigned char bitmap_hp_fixed_5_7_57 [5] = { - 0x06, - 0x49, - 0x49, - 0x29, - 0x1e -}; -struct disp_font_glyph glyph_hp_fixed_5_7_57 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_57, -}; - -const unsigned char bitmap_hp_fixed_5_7_58 [5] = { - 0x00, - 0x36, - 0x36, - 0x00, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_58 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_58, -}; - -const unsigned char bitmap_hp_fixed_5_7_59 [5] = { - 0x00, - 0x5b, - 0x3b, - 0x00, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_59 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_59, -}; - -const unsigned char bitmap_hp_fixed_5_7_60 [5] = { - 0x00, - 0x08, - 0x14, - 0x22, - 0x41 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_60 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_60, -}; - -const unsigned char bitmap_hp_fixed_5_7_61 [5] = { - 0x14, - 0x14, - 0x14, - 0x14, - 0x14 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_61 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_61, -}; - -const unsigned char bitmap_hp_fixed_5_7_62 [5] = { - 0x41, - 0x22, - 0x14, - 0x08, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_62 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_62, -}; - -const unsigned char bitmap_hp_fixed_5_7_63 [5] = { - 0x02, - 0x01, - 0x51, - 0x09, - 0x06 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_63 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_63, -}; - -const unsigned char bitmap_hp_fixed_5_7_64 [5] = { - 0x3e, - 0x41, - 0x5d, - 0x55, - 0x1e -}; -struct disp_font_glyph glyph_hp_fixed_5_7_64 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_64, -}; - -const unsigned char bitmap_hp_fixed_5_7_65 [5] = { - 0x7e, - 0x09, - 0x09, - 0x09, - 0x7e -}; -struct disp_font_glyph glyph_hp_fixed_5_7_65 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_65, -}; - -const unsigned char bitmap_hp_fixed_5_7_66 [5] = { - 0x7e, - 0x49, - 0x49, - 0x49, - 0x36 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_66 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_66, -}; - -const unsigned char bitmap_hp_fixed_5_7_67 [5] = { - 0x3e, - 0x41, - 0x41, - 0x41, - 0x22 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_67 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_67, -}; - -const unsigned char bitmap_hp_fixed_5_7_68 [5] = { - 0x7f, - 0x41, - 0x41, - 0x41, - 0x3e -}; -struct disp_font_glyph glyph_hp_fixed_5_7_68 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_68, -}; - -const unsigned char bitmap_hp_fixed_5_7_69 [5] = { - 0x7f, - 0x49, - 0x49, - 0x49, - 0x41 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_69 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_69, -}; - -const unsigned char bitmap_hp_fixed_5_7_70 [5] = { - 0x7f, - 0x09, - 0x09, - 0x09, - 0x01 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_70 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_70, -}; - -const unsigned char bitmap_hp_fixed_5_7_71 [5] = { - 0x3e, - 0x41, - 0x41, - 0x51, - 0x32 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_71 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_71, -}; - -const unsigned char bitmap_hp_fixed_5_7_72 [5] = { - 0x7f, - 0x08, - 0x08, - 0x08, - 0x7f -}; -struct disp_font_glyph glyph_hp_fixed_5_7_72 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_72, -}; - -const unsigned char bitmap_hp_fixed_5_7_73 [5] = { - 0x00, - 0x41, - 0x7f, - 0x41, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_73 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_73, -}; - -const unsigned char bitmap_hp_fixed_5_7_74 [5] = { - 0x20, - 0x40, - 0x40, - 0x40, - 0x3f -}; -struct disp_font_glyph glyph_hp_fixed_5_7_74 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_74, -}; - -const unsigned char bitmap_hp_fixed_5_7_75 [5] = { - 0x7f, - 0x08, - 0x14, - 0x22, - 0x41 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_75 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_75, -}; - -const unsigned char bitmap_hp_fixed_5_7_76 [5] = { - 0x7f, - 0x40, - 0x40, - 0x40, - 0x40 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_76 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_76, -}; - -const unsigned char bitmap_hp_fixed_5_7_77 [5] = { - 0x7f, - 0x02, - 0x0c, - 0x02, - 0x7f -}; -struct disp_font_glyph glyph_hp_fixed_5_7_77 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_77, -}; - -const unsigned char bitmap_hp_fixed_5_7_78 [5] = { - 0x7f, - 0x04, - 0x08, - 0x10, - 0x7f -}; -struct disp_font_glyph glyph_hp_fixed_5_7_78 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_78, -}; - -const unsigned char bitmap_hp_fixed_5_7_79 [5] = { - 0x3e, - 0x41, - 0x41, - 0x41, - 0x3e -}; -struct disp_font_glyph glyph_hp_fixed_5_7_79 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_79, -}; - -const unsigned char bitmap_hp_fixed_5_7_80 [5] = { - 0x7f, - 0x09, - 0x09, - 0x09, - 0x06 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_80 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_80, -}; - -const unsigned char bitmap_hp_fixed_5_7_81 [5] = { - 0x3e, - 0x41, - 0x51, - 0x21, - 0x5e -}; -struct disp_font_glyph glyph_hp_fixed_5_7_81 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_81, -}; - -const unsigned char bitmap_hp_fixed_5_7_82 [5] = { - 0x7f, - 0x09, - 0x19, - 0x29, - 0x46 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_82 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_82, -}; - -const unsigned char bitmap_hp_fixed_5_7_83 [5] = { - 0x26, - 0x49, - 0x49, - 0x49, - 0x32 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_83 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_83, -}; - -const unsigned char bitmap_hp_fixed_5_7_84 [5] = { - 0x01, - 0x01, - 0x7f, - 0x01, - 0x01 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_84 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_84, -}; - -const unsigned char bitmap_hp_fixed_5_7_85 [5] = { - 0x3f, - 0x40, - 0x40, - 0x40, - 0x3f -}; -struct disp_font_glyph glyph_hp_fixed_5_7_85 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_85, -}; - -const unsigned char bitmap_hp_fixed_5_7_86 [5] = { - 0x07, - 0x18, - 0x60, - 0x18, - 0x07 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_86 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_86, -}; - -const unsigned char bitmap_hp_fixed_5_7_87 [5] = { - 0x7f, - 0x20, - 0x18, - 0x20, - 0x7f -}; -struct disp_font_glyph glyph_hp_fixed_5_7_87 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_87, -}; - -const unsigned char bitmap_hp_fixed_5_7_88 [5] = { - 0x63, - 0x14, - 0x08, - 0x14, - 0x63 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_88 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_88, -}; - -const unsigned char bitmap_hp_fixed_5_7_89 [5] = { - 0x03, - 0x04, - 0x78, - 0x04, - 0x03 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_89 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_89, -}; - -const unsigned char bitmap_hp_fixed_5_7_90 [5] = { - 0x61, - 0x51, - 0x49, - 0x45, - 0x43 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_90 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_90, -}; - -const unsigned char bitmap_hp_fixed_5_7_91 [5] = { - 0x00, - 0x00, - 0x7f, - 0x41, - 0x41 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_91 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_91, -}; - -const unsigned char bitmap_hp_fixed_5_7_92 [5] = { - 0x02, - 0x04, - 0x08, - 0x10, - 0x20 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_92 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_92, -}; - -const unsigned char bitmap_hp_fixed_5_7_93 [5] = { - 0x41, - 0x41, - 0x7f, - 0x00, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_93 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_93, -}; - -const unsigned char bitmap_hp_fixed_5_7_94 [5] = { - 0x04, - 0x02, - 0x7f, - 0x02, - 0x04 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_94 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_94, -}; - -const unsigned char bitmap_hp_fixed_5_7_95 [5] = { - 0x40, - 0x40, - 0x40, - 0x40, - 0x40 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_95 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_95, -}; - -const unsigned char bitmap_hp_fixed_5_7_96 [5] = { - 0x00, - 0x07, - 0x0b, - 0x00, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_96 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_96, -}; - -const unsigned char bitmap_hp_fixed_5_7_97 [5] = { - 0x38, - 0x44, - 0x44, - 0x3c, - 0x40 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_97 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_97, -}; - -const unsigned char bitmap_hp_fixed_5_7_98 [5] = { - 0x7f, - 0x48, - 0x44, - 0x44, - 0x38 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_98 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_98, -}; - -const unsigned char bitmap_hp_fixed_5_7_99 [5] = { - 0x38, - 0x44, - 0x44, - 0x44, - 0x44 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_99 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_99, -}; - -const unsigned char bitmap_hp_fixed_5_7_100 [5] = { - 0x38, - 0x44, - 0x44, - 0x48, - 0x7f -}; -struct disp_font_glyph glyph_hp_fixed_5_7_100 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_100, -}; - -const unsigned char bitmap_hp_fixed_5_7_101 [5] = { - 0x38, - 0x54, - 0x54, - 0x54, - 0x08 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_101 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_101, -}; - -const unsigned char bitmap_hp_fixed_5_7_102 [5] = { - 0x08, - 0x7e, - 0x09, - 0x02, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_102 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_102, -}; - -const unsigned char bitmap_hp_fixed_5_7_103 [5] = { - 0x08, - 0x14, - 0x54, - 0x54, - 0x3c -}; -struct disp_font_glyph glyph_hp_fixed_5_7_103 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_103, -}; - -const unsigned char bitmap_hp_fixed_5_7_104 [5] = { - 0x7f, - 0x08, - 0x04, - 0x04, - 0x78 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_104 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_104, -}; - -const unsigned char bitmap_hp_fixed_5_7_105 [5] = { - 0x00, - 0x44, - 0x7d, - 0x40, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_105 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_105, -}; - -const unsigned char bitmap_hp_fixed_5_7_106 [5] = { - 0x20, - 0x40, - 0x44, - 0x3d, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_106 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_106, -}; - -const unsigned char bitmap_hp_fixed_5_7_107 [5] = { - 0x00, - 0x7f, - 0x10, - 0x28, - 0x44 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_107 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_107, -}; - -const unsigned char bitmap_hp_fixed_5_7_108 [5] = { - 0x00, - 0x41, - 0x7f, - 0x40, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_108 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_108, -}; - -const unsigned char bitmap_hp_fixed_5_7_109 [5] = { - 0x78, - 0x04, - 0x18, - 0x04, - 0x78 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_109 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_109, -}; - -const unsigned char bitmap_hp_fixed_5_7_110 [5] = { - 0x7c, - 0x08, - 0x04, - 0x04, - 0x78 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_110 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_110, -}; - -const unsigned char bitmap_hp_fixed_5_7_111 [5] = { - 0x38, - 0x44, - 0x44, - 0x44, - 0x38 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_111 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_111, -}; - -const unsigned char bitmap_hp_fixed_5_7_112 [5] = { - 0x7c, - 0x14, - 0x24, - 0x24, - 0x18 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_112 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_112, -}; - -const unsigned char bitmap_hp_fixed_5_7_113 [5] = { - 0x18, - 0x24, - 0x14, - 0x7c, - 0x40 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_113 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_113, -}; - -const unsigned char bitmap_hp_fixed_5_7_114 [5] = { - 0x00, - 0x7c, - 0x08, - 0x04, - 0x04 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_114 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_114, -}; - -const unsigned char bitmap_hp_fixed_5_7_115 [5] = { - 0x48, - 0x54, - 0x54, - 0x54, - 0x20 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_115 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_115, -}; - -const unsigned char bitmap_hp_fixed_5_7_116 [5] = { - 0x04, - 0x3e, - 0x44, - 0x20, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_116 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_116, -}; - -const unsigned char bitmap_hp_fixed_5_7_117 [5] = { - 0x3c, - 0x40, - 0x40, - 0x20, - 0x7c -}; -struct disp_font_glyph glyph_hp_fixed_5_7_117 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_117, -}; - -const unsigned char bitmap_hp_fixed_5_7_118 [5] = { - 0x1c, - 0x20, - 0x40, - 0x20, - 0x1c -}; -struct disp_font_glyph glyph_hp_fixed_5_7_118 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_118, -}; - -const unsigned char bitmap_hp_fixed_5_7_119 [5] = { - 0x3c, - 0x40, - 0x30, - 0x40, - 0x3c -}; -struct disp_font_glyph glyph_hp_fixed_5_7_119 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_119, -}; - -const unsigned char bitmap_hp_fixed_5_7_120 [5] = { - 0x44, - 0x28, - 0x10, - 0x28, - 0x44 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_120 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_120, -}; - -const unsigned char bitmap_hp_fixed_5_7_121 [5] = { - 0x04, - 0x48, - 0x30, - 0x08, - 0x04 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_121 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_121, -}; - -const unsigned char bitmap_hp_fixed_5_7_122 [5] = { - 0x44, - 0x64, - 0x54, - 0x4c, - 0x44 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_122 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_122, -}; - -const unsigned char bitmap_hp_fixed_5_7_123 [5] = { - 0x00, - 0x08, - 0x36, - 0x41, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_123 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_123, -}; - -const unsigned char bitmap_hp_fixed_5_7_124 [5] = { - 0x00, - 0x00, - 0x77, - 0x00, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_124 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_124, -}; - -const unsigned char bitmap_hp_fixed_5_7_125 [5] = { - 0x00, - 0x41, - 0x36, - 0x08, - 0x00 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_125 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_125, -}; - -const unsigned char bitmap_hp_fixed_5_7_126 [5] = { - 0x08, - 0x04, - 0x08, - 0x10, - 0x08 -}; -struct disp_font_glyph glyph_hp_fixed_5_7_126 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_126, -}; - -const unsigned char bitmap_hp_fixed_5_7_127 [5] = { - 0x2a, - 0x55, - 0x2a, - 0x55, - 0x2a -}; -struct disp_font_glyph glyph_hp_fixed_5_7_127 = { - {5,7,0,0}, - 5, 0, bitmap_hp_fixed_5_7_127, -}; - -const struct disp_font_base font_hcms29xx_base = { - 1, /* trans */ - {5, 7, 0, -1}, /* fbb w, h, x, y */ - 7, 0, /* ascent, descent */ - 0, /* default_char */ - {&glyph_hp_fixed_5_7_0, - &glyph_hp_fixed_5_7_1, - &glyph_hp_fixed_5_7_2, - &glyph_hp_fixed_5_7_3, - &glyph_hp_fixed_5_7_4, - &glyph_hp_fixed_5_7_5, - &glyph_hp_fixed_5_7_6, - &glyph_hp_fixed_5_7_7, - &glyph_hp_fixed_5_7_8, - &glyph_hp_fixed_5_7_9, - &glyph_hp_fixed_5_7_10, - &glyph_hp_fixed_5_7_11, - &glyph_hp_fixed_5_7_12, - &glyph_hp_fixed_5_7_13, - &glyph_hp_fixed_5_7_14, - &glyph_hp_fixed_5_7_15, - &glyph_hp_fixed_5_7_16, - &glyph_hp_fixed_5_7_17, - &glyph_hp_fixed_5_7_18, - &glyph_hp_fixed_5_7_19, - &glyph_hp_fixed_5_7_20, - &glyph_hp_fixed_5_7_21, - &glyph_hp_fixed_5_7_22, - &glyph_hp_fixed_5_7_23, - &glyph_hp_fixed_5_7_24, - &glyph_hp_fixed_5_7_25, - &glyph_hp_fixed_5_7_26, - &glyph_hp_fixed_5_7_27, - &glyph_hp_fixed_5_7_28, - &glyph_hp_fixed_5_7_29, - &glyph_hp_fixed_5_7_30, - &glyph_hp_fixed_5_7_31, - &glyph_hp_fixed_5_7_32, - &glyph_hp_fixed_5_7_33, - &glyph_hp_fixed_5_7_34, - &glyph_hp_fixed_5_7_35, - &glyph_hp_fixed_5_7_36, - &glyph_hp_fixed_5_7_37, - &glyph_hp_fixed_5_7_38, - &glyph_hp_fixed_5_7_39, - &glyph_hp_fixed_5_7_40, - &glyph_hp_fixed_5_7_41, - &glyph_hp_fixed_5_7_42, - &glyph_hp_fixed_5_7_43, - &glyph_hp_fixed_5_7_44, - &glyph_hp_fixed_5_7_45, - &glyph_hp_fixed_5_7_46, - &glyph_hp_fixed_5_7_47, - &glyph_hp_fixed_5_7_48, - &glyph_hp_fixed_5_7_49, - &glyph_hp_fixed_5_7_50, - &glyph_hp_fixed_5_7_51, - &glyph_hp_fixed_5_7_52, - &glyph_hp_fixed_5_7_53, - &glyph_hp_fixed_5_7_54, - &glyph_hp_fixed_5_7_55, - &glyph_hp_fixed_5_7_56, - &glyph_hp_fixed_5_7_57, - &glyph_hp_fixed_5_7_58, - &glyph_hp_fixed_5_7_59, - &glyph_hp_fixed_5_7_60, - &glyph_hp_fixed_5_7_61, - &glyph_hp_fixed_5_7_62, - &glyph_hp_fixed_5_7_63, - &glyph_hp_fixed_5_7_64, - &glyph_hp_fixed_5_7_65, - &glyph_hp_fixed_5_7_66, - &glyph_hp_fixed_5_7_67, - &glyph_hp_fixed_5_7_68, - &glyph_hp_fixed_5_7_69, - &glyph_hp_fixed_5_7_70, - &glyph_hp_fixed_5_7_71, - &glyph_hp_fixed_5_7_72, - &glyph_hp_fixed_5_7_73, - &glyph_hp_fixed_5_7_74, - &glyph_hp_fixed_5_7_75, - &glyph_hp_fixed_5_7_76, - &glyph_hp_fixed_5_7_77, - &glyph_hp_fixed_5_7_78, - &glyph_hp_fixed_5_7_79, - &glyph_hp_fixed_5_7_80, - &glyph_hp_fixed_5_7_81, - &glyph_hp_fixed_5_7_82, - &glyph_hp_fixed_5_7_83, - &glyph_hp_fixed_5_7_84, - &glyph_hp_fixed_5_7_85, - &glyph_hp_fixed_5_7_86, - &glyph_hp_fixed_5_7_87, - &glyph_hp_fixed_5_7_88, - &glyph_hp_fixed_5_7_89, - &glyph_hp_fixed_5_7_90, - &glyph_hp_fixed_5_7_91, - &glyph_hp_fixed_5_7_92, - &glyph_hp_fixed_5_7_93, - &glyph_hp_fixed_5_7_94, - &glyph_hp_fixed_5_7_95, - &glyph_hp_fixed_5_7_96, - &glyph_hp_fixed_5_7_97, - &glyph_hp_fixed_5_7_98, - &glyph_hp_fixed_5_7_99, - &glyph_hp_fixed_5_7_100, - &glyph_hp_fixed_5_7_101, - &glyph_hp_fixed_5_7_102, - &glyph_hp_fixed_5_7_103, - &glyph_hp_fixed_5_7_104, - &glyph_hp_fixed_5_7_105, - &glyph_hp_fixed_5_7_106, - &glyph_hp_fixed_5_7_107, - &glyph_hp_fixed_5_7_108, - &glyph_hp_fixed_5_7_109, - &glyph_hp_fixed_5_7_110, - &glyph_hp_fixed_5_7_111, - &glyph_hp_fixed_5_7_112, - &glyph_hp_fixed_5_7_113, - &glyph_hp_fixed_5_7_114, - &glyph_hp_fixed_5_7_115, - &glyph_hp_fixed_5_7_116, - &glyph_hp_fixed_5_7_117, - &glyph_hp_fixed_5_7_118, - &glyph_hp_fixed_5_7_119, - &glyph_hp_fixed_5_7_120, - &glyph_hp_fixed_5_7_121, - &glyph_hp_fixed_5_7_122, - &glyph_hp_fixed_5_7_123, - &glyph_hp_fixed_5_7_124, - &glyph_hp_fixed_5_7_125, - &glyph_hp_fixed_5_7_126, - &glyph_hp_fixed_5_7_127, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL} -}; diff --git a/c/src/libchip/display/font_hcms29xx.h b/c/src/libchip/display/font_hcms29xx.h deleted file mode 100644 index 8638fcf600..0000000000 --- a/c/src/libchip/display/font_hcms29xx.h +++ /dev/null @@ -1,36 +0,0 @@ -/*===============================================================*\ -| Project: display driver for HCMS29xx | -+-----------------------------------------------------------------+ -| File: font_hcms29xx.h | -+-----------------------------------------------------------------+ -| Copyright (c) 2008 | -| Embedded Brains GmbH | -| Obere Lagerstr. 30 | -| D-82178 Puchheim | -| Germany | -| rtems@embedded-brains.de | -+-----------------------------------------------------------------+ -| The license and distribution terms for this file may be | -| found in the file LICENSE in this distribution or at | -| http://www.rtems.org/license/LICENSE. | -+-----------------------------------------------------------------+ -| This file declares the 5x7 bit font used in disp_hcms29xx | -\*===============================================================*/ - -#ifndef FONT_HCMS29XX_H -#define FONT_HCMS29XX_H - -#include "disp_fonts.h" - - -#ifdef __cplusplus -extern "C" { -#endif - -extern struct disp_font_base font_hcms29xx_base; - -#ifdef __cplusplus -} -#endif - -#endif /* not defined FONT_HCMS29XX_H */ diff --git a/c/src/libchip/flash/am29lv160.c b/c/src/libchip/flash/am29lv160.c deleted file mode 100644 index 5cfaae4f24..0000000000 --- a/c/src/libchip/flash/am29lv160.c +++ /dev/null @@ -1,473 +0,0 @@ -/* - * RTEMS Project (http://www.rtems.org/) - * - * Copyright 2007 Chris Johns (chrisj@rtems.org) - */ -/** - * Provide flash support for the AM26LV160 device. - * - * The M29W160D is the same device. - */ - -#include -#include -#include - -#include - -#include - -#ifndef AM26LV160_ERROR_TRACE -#define AM26LV160_ERROR_TRACE (0) -#endif - -/** - * Boot blocks at the top - */ -const rtems_fdisk_segment_desc rtems_am29lv160t_segments[4] = -{ - { - .count = 31, - .segment = 0, - .offset = 0x00000000, - .size = RTEMS_FDISK_KBYTES (64) - }, - { - .count = 1, - .segment = 31, - .offset = 0x001f0000, - .size = RTEMS_FDISK_KBYTES (32) - }, - { - .count = 2, - .segment = 32, - .offset = 0x001f8000, - .size = RTEMS_FDISK_KBYTES (8) - }, - { - .count = 1, - .segment = 34, - .offset = 0x001fc000, - .size = RTEMS_FDISK_KBYTES (16) - } -}; - -/** - * Boot blocks at the bottom. - */ -const rtems_fdisk_segment_desc rtems_am29lv160b_segments[] = -{ - { - .count = 1, - .segment = 0, - .offset = 0x00000000, - .size = RTEMS_FDISK_KBYTES (16) - }, - { - . count = 2, - .segment = 1, - .offset = 0x00004000, - .size = RTEMS_FDISK_KBYTES (8) - }, - { - .count = 1, - .segment = 3, - .offset = 0x00008000, - .size = RTEMS_FDISK_KBYTES (32) - }, - { - .count = 31, - .segment = 4, - .offset = 0x00010000, - .size = RTEMS_FDISK_KBYTES (64) - } -}; - -static int -rtems_am29lv160_blank (const rtems_fdisk_segment_desc* sd, - uint32_t device, - uint32_t segment, - uint32_t offset, - uint32_t size) -{ - const rtems_am29lv160_config* ac = &rtems_am29lv160_configuration[device]; - volatile uint8_t* seg_8 = ac->base; - volatile uint32_t* seg_32; - uint32_t count; - - offset += sd->offset + (segment - sd->segment) * sd->size; - - seg_8 += offset; - - count = offset & (sizeof (uint32_t) - 1); - size -= count; - - while (count--) - if (*seg_8++ != 0xff) - { -#if AM26LV160_ERROR_TRACE - printf ("AM26LV160: blank check error: %p = 0x%02x\n", - seg_8 - 1, *(seg_8 - 1)); -#endif - return EIO; - } - - seg_32 = (volatile uint32_t*) seg_8; - - count = size / sizeof (uint32_t); - size -= count * sizeof (uint32_t); - - while (count--) - if (*seg_32++ != 0xffffffff) - { -#if AM26LV160_ERROR_TRACE - printf ("AM26LV160: blank check error: %p = 0x%08lx\n", - seg_32 - 1, *(seg_32 - 1)); -#endif - return EIO; - } - - seg_8 = (volatile uint8_t*) seg_32; - - while (size--) - if (*seg_8++ != 0xff) - { -#if AM26LV160_ERROR_TRACE - printf ("AM26LV160: blank check error: %p = 0x%02x\n", - seg_8 - 1, *(seg_8 - 1)); -#endif - return EIO; - } - - return 0; -} - -static int -rtems_am29lv160_verify (const rtems_fdisk_segment_desc* sd, - uint32_t device, - uint32_t segment, - uint32_t offset, - const void* buffer, - uint32_t size) -{ - const rtems_am29lv160_config* ac = &rtems_am29lv160_configuration[device]; - const uint8_t* addr = ac->base; - - addr += (sd->offset + (segment - sd->segment) * sd->size) + offset; - - if (memcmp (addr, buffer, size) != 0) - return EIO; - - return 0; -} - -static int -rtems_am29lv160_toggle_wait_8 (volatile uint8_t* status) -{ - while (1) - { - volatile uint8_t status1 = *status; - volatile uint8_t status2 = *status; - - if (((status1 ^ status2) & (1 << 6)) == 0) - return 0; - - if ((status1 & (1 << 5)) != 0) - { - status1 = *status; - status2 = *status; - - if (((status1 ^ status2) & (1 << 6)) == 0) - return 0; - -#if AM26LV160_ERROR_TRACE - printf ("AM26LV160: error bit detected: %p = 0x%04x\n", - status, status1); -#endif - - *status = 0xf0; - return EIO; - } - } -} - -static int -rtems_am29lv160_toggle_wait_16 (volatile uint16_t* status) -{ - while (1) - { - volatile uint16_t status1 = *status; - volatile uint16_t status2 = *status; - - if (((status1 ^ status2) & (1 << 6)) == 0) - return 0; - - if ((status1 & (1 << 5)) != 0) - { - status1 = *status; - status2 = *status; - - if (((status1 ^ status2) & (1 << 6)) == 0) - return 0; - -#if AM26LV160_ERROR_TRACE - printf ("AM26LV160: error bit detected: %p = 0x%04x/0x%04x\n", - status, status1, status2); -#endif - - *status = 0xf0; - return EIO; - } - } -} - -static int -rtems_am29lv160_write_data_8 (volatile uint8_t* base, - uint32_t offset, - const uint8_t* data, - uint32_t size) -{ - volatile uint8_t* seg = base + offset; - rtems_interrupt_level level; - - /* - * Issue a reset. - */ - *base = 0xf0; - - while (size) - { - rtems_interrupt_disable (level); - *(base + 0xaaa) = 0xaa; - *(base + 0x555) = 0x55; - *(base + 0xaaa) = 0xa0; - *seg = *data++; - rtems_interrupt_enable (level); - if (rtems_am29lv160_toggle_wait_8 (seg++) != 0) - return EIO; - size--; - } - - /* - * Issue a reset. - */ - *base = 0xf0; - - return 0; -} - -static int -rtems_am29lv160_write_data_16 (volatile uint16_t* base, - uint32_t offset, - const uint16_t* data, - uint32_t size) -{ - volatile uint16_t* seg = base + (offset / 2); - rtems_interrupt_level level; - - size /= 2; - - /* - * Issue a reset. - */ - *base = 0xf0; - - while (size) - { - rtems_interrupt_disable (level); - *(base + 0x555) = 0xaa; - *(base + 0x2aa) = 0x55; - *(base + 0x555) = 0xa0; - *seg = *data++; - rtems_interrupt_enable (level); - if (rtems_am29lv160_toggle_wait_16 (seg++) != 0) - return EIO; - size--; - } - - /* - * Issue a reset. - */ - *base = 0xf0; - - return 0; -} - -static int -rtems_am29lv160_read (const rtems_fdisk_segment_desc* sd, - uint32_t device, - uint32_t segment, - uint32_t offset, - void* buffer, - uint32_t size) -{ - unsigned char* addr = - rtems_am29lv160_configuration[device].base + - sd->offset + ((segment - sd->segment) * sd->size) + offset; - memcpy (buffer, addr, size); - return 0; -} - -/* - * @todo Fix the odd alignment and odd sizes. - */ -static int -rtems_am29lv160_write (const rtems_fdisk_segment_desc* sd, - uint32_t device, - uint32_t segment, - uint32_t offset, - const void* buffer, - uint32_t size) -{ - int ret = rtems_am29lv160_verify (sd, device, segment, offset, buffer, size); - - if (ret != 0) - { - const rtems_am29lv160_config* ac = &rtems_am29lv160_configuration[device]; - uint32_t soffset; - - soffset = offset + sd->offset + ((segment - sd->segment) * sd->size); - - if (offset & 1) - printf ("rtems_am29lv160_write: offset is odd\n"); - - if (size & 1) - printf ("rtems_am29lv160_write: size is odd\n"); - - if (ac->bus_8bit) - ret = rtems_am29lv160_write_data_8 (ac->base, soffset, buffer, size); - else - ret = rtems_am29lv160_write_data_16 (ac->base, soffset, buffer, size); - - /* - * Verify the write worked. - */ - if (ret == 0) - { - ret = rtems_am29lv160_verify (sd, device, segment, offset, buffer, size); -#if AM26LV160_ERROR_TRACE - if (ret) - printf ("AM26LV160: verify failed: %ld-%ld-%08lx: s=%ld\n", - device, segment, offset, size); -#endif - } - } - - return ret; -} - -static int -rtems_am29lv160_erase (const rtems_fdisk_segment_desc* sd, - uint32_t device, - uint32_t segment) -{ - int ret = rtems_am29lv160_blank (sd, device, segment, 0, sd->size); - if (ret != 0) - { - const rtems_am29lv160_config* ac = &rtems_am29lv160_configuration[device]; - uint32_t offset; - rtems_interrupt_level level; - - offset = sd->offset + ((segment - sd->segment) * sd->size); - - if (ac->bus_8bit) - { - volatile uint8_t* base = ac->base; - volatile uint8_t* seg = base + offset; - - /* - * Issue a reset. - */ - rtems_interrupt_disable (level); - *base = 0xf0; - *(base + 0xaaa) = 0xaa; - *(base + 0x555) = 0x55; - *(base + 0xaaa) = 0x80; - *(base + 0xaaa) = 0xaa; - *(base + 0x555) = 0x55; - *seg = 0x30; - rtems_interrupt_enable (level); - - ret = rtems_am29lv160_toggle_wait_8 (seg); - - /* - * Issue a reset. - */ - *base = 0xf0; - } - else - { - volatile uint16_t* base = ac->base; - volatile uint16_t* seg = base + (offset / 2); - - /* - * Issue a reset. - */ - rtems_interrupt_disable (level); - *base = 0xf0; - *(base + 0x555) = 0xaa; - *(base + 0x2aa) = 0x55; - *(base + 0x555) = 0x80; - *(base + 0x555) = 0xaa; - *(base + 0x2aa) = 0x55; - *seg = 0x30; - rtems_interrupt_enable (level); - - ret = rtems_am29lv160_toggle_wait_16 (seg); - - /* - * Issue a reset. - */ - *base = 0xf0; - } - - /* - * Check the erase worked. - */ - if (ret == 0) - { - ret = rtems_am29lv160_blank (sd, device, segment, 0, sd->size); -#if AM26LV160_ERROR_TRACE - if (ret) - printf ("AM26LV160: erase failed: %ld-%ld\n", device, segment); -#endif - } - } - - return ret; -} - -static int -rtems_am29lv160_erase_device (const rtems_fdisk_device_desc* dd, - uint32_t device) -{ - uint32_t segment; - - for (segment = 0; segment < dd->segment_count; segment++) - { - uint32_t seg_segment; - - for (seg_segment = 0; - seg_segment < dd->segments[segment].count; - seg_segment++) - { - int ret = rtems_am29lv160_erase (&dd->segments[segment], - device, - segment + seg_segment); - if (ret) - return ret; - } - } - - return 0; -} - -const rtems_fdisk_driver_handlers rtems_am29lv160_handlers = -{ - .read = rtems_am29lv160_read, - .write = rtems_am29lv160_write, - .blank = rtems_am29lv160_blank, - .verify = rtems_am29lv160_verify, - .erase = rtems_am29lv160_erase, - .erase_device = rtems_am29lv160_erase_device -}; diff --git a/c/src/libchip/i2c/i2c-2b-eeprom.c b/c/src/libchip/i2c/i2c-2b-eeprom.c deleted file mode 100644 index 4a8b5fdb9c..0000000000 --- a/c/src/libchip/i2c/i2c-2b-eeprom.c +++ /dev/null @@ -1,177 +0,0 @@ -/* Trivial i2c driver for reading "2-byte eeproms". - * On 'open' the read-pointer is reset to 0, subsequent - * read operations slurp data from there... - */ - -/* - * Authorship - * ---------- - * This software was created by - * Till Straumann , 2005, - * Stanford Linear Accelerator Center, Stanford University. - * - * Acknowledgement of sponsorship - * ------------------------------ - * This software was produced by - * the Stanford Linear Accelerator Center, Stanford University, - * under Contract DE-AC03-76SFO0515 with the Department of Energy. - * - * Government disclaimer of liability - * ---------------------------------- - * Neither the United States nor the United States Department of Energy, - * nor any of their employees, makes any warranty, express or implied, or - * assumes any legal liability or responsibility for the accuracy, - * completeness, or usefulness of any data, apparatus, product, or process - * disclosed, or represents that its use would not infringe privately owned - * rights. - * - * Stanford disclaimer of liability - * -------------------------------- - * Stanford University makes no representations or warranties, express or - * implied, nor assumes any liability for the use of this software. - * - * Stanford disclaimer of copyright - * -------------------------------- - * Stanford University, owner of the copyright, hereby disclaims its - * copyright and all other rights in this software. Hence, anyone may - * freely use it for any purpose without restriction. - * - * Maintenance of notices - * ---------------------- - * In the interest of clarity regarding the origin and status of this - * SLAC software, this and all the preceding Stanford University notices - * are to remain affixed to any copy or derivative of this software made - * or distributed by the recipient and are to be affixed to any copy of - * software made or distributed by the recipient that contains a copy or - * derivative of this software. - * - * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 - */ - - -#include -#include - -#include -#include - -#define EEPROM_PG_SZ 32 -#define ALGN(x) (((uint32_t)(x) + EEPROM_PG_SZ) & ~(EEPROM_PG_SZ-1)) - -static rtems_status_code -send_file_ptr (rtems_device_minor_number minor, unsigned pos, int tout) -{ - int sc; - unsigned char bytes[2]; - - bytes[0] = (pos >> 8) & 0xff; - bytes[1] = (pos) & 0xff; - - /* poll addressing the next page; if 'tout' is <=0 we only try once - * and return the status. If 'tout' is positive, we try 'tout' times - * and return RTEMS_TIMEOUT if it didnt work - */ - while ((sc = rtems_libi2c_start_write_bytes (minor, bytes, 2)) < 0) { - if (--tout <= 0) - return tout ? -sc : RTEMS_TIMEOUT; - rtems_task_wake_after (1); - } - return RTEMS_SUCCESSFUL; -} - -static rtems_status_code -i2c_2b_eeprom_write (rtems_device_major_number major, - rtems_device_minor_number minor, void *arg) -{ - rtems_libio_rw_args_t *rwargs = arg; - unsigned off = rwargs->offset; - int cnt = rwargs->count; - unsigned char *buf = (unsigned char *)rwargs->buffer; - int sc; - unsigned end; - int l; - - if (cnt <= 0) - return RTEMS_SUCCESSFUL; - - if ((sc = send_file_ptr (minor, off, 0))) - return sc; - - do { - /* write up to next page boundary */ - end = ALGN (off); - l = end - off; - if (l > cnt) - l = cnt; - - sc = rtems_libi2c_write_bytes (minor, buf, l); - if (sc < 0) - return -sc; - - sc = rtems_libi2c_send_stop (minor); - if (sc) - return sc; - - rwargs->bytes_moved += l; - - buf += l; - cnt -= l; - off += l; - - /* poll addressing the next page */ - if ((sc = send_file_ptr (minor, off, 100))) - return sc; - - } while (cnt > 0); - - return rtems_libi2c_send_stop (minor); -} - -static rtems_status_code -i2c_2b_eeprom_read (rtems_device_major_number major, - rtems_device_minor_number minor, void *arg) -{ - int sc; - rtems_libio_rw_args_t *rwargs = arg; - - if (RTEMS_SUCCESSFUL != (sc = send_file_ptr (minor, rwargs->offset, 0))) - return -sc; - - sc = rtems_libi2c_start_read_bytes( - minor, - (unsigned char *)rwargs->buffer, - rwargs->count - ); - - if (sc < 0) { - rwargs->bytes_moved = 0; - return -sc; - } - rwargs->bytes_moved = sc; - - return rtems_libi2c_send_stop (minor); -} - -static rtems_driver_address_table myops = { - .read_entry = i2c_2b_eeprom_read, - .write_entry = i2c_2b_eeprom_write, -}; - -static rtems_libi2c_drv_t my_drv_tbl = { - .ops = &myops, - .size = sizeof (my_drv_tbl), -}; - -/* provide a second table for R/O access */ -static rtems_driver_address_table my_ro_ops = { - .read_entry = i2c_2b_eeprom_read, -}; - -static rtems_libi2c_drv_t my_ro_drv_tbl = { - .ops = &my_ro_ops, - .size = sizeof (my_ro_drv_tbl), -}; - - -rtems_libi2c_drv_t *i2c_2b_eeprom_driver_descriptor = &my_drv_tbl; -rtems_libi2c_drv_t *i2c_2b_eeprom_ro_driver_descriptor = &my_ro_drv_tbl; diff --git a/c/src/libchip/i2c/i2c-ds1621.c b/c/src/libchip/i2c/i2c-ds1621.c deleted file mode 100644 index 51f64de679..0000000000 --- a/c/src/libchip/i2c/i2c-ds1621.c +++ /dev/null @@ -1,128 +0,0 @@ -/* Trivial i2c driver for the maxim DS1621 temperature sensor; - * just implements reading constant conversions with 8-bit - * resolution. - * Demonstrates the implementation of a i2c high-level driver. - */ - -/* - * Authorship - * ---------- - * This software was created by - * Till Straumann , 2005, - * Stanford Linear Accelerator Center, Stanford University. - * - * Acknowledgement of sponsorship - * ------------------------------ - * This software was produced by - * the Stanford Linear Accelerator Center, Stanford University, - * under Contract DE-AC03-76SFO0515 with the Department of Energy. - * - * Government disclaimer of liability - * ---------------------------------- - * Neither the United States nor the United States Department of Energy, - * nor any of their employees, makes any warranty, express or implied, or - * assumes any legal liability or responsibility for the accuracy, - * completeness, or usefulness of any data, apparatus, product, or process - * disclosed, or represents that its use would not infringe privately owned - * rights. - * - * Stanford disclaimer of liability - * -------------------------------- - * Stanford University makes no representations or warranties, express or - * implied, nor assumes any liability for the use of this software. - * - * Stanford disclaimer of copyright - * -------------------------------- - * Stanford University, owner of the copyright, hereby disclaims its - * copyright and all other rights in this software. Hence, anyone may - * freely use it for any purpose without restriction. - * - * Maintenance of notices - * ---------------------- - * In the interest of clarity regarding the origin and status of this - * SLAC software, this and all the preceding Stanford University notices - * are to remain affixed to any copy or derivative of this software made - * or distributed by the recipient and are to be affixed to any copy of - * software made or distributed by the recipient that contains a copy or - * derivative of this software. - * - * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 - */ -#include -#include - -#include - -#include - - -static rtems_status_code -ds1621_init (rtems_device_major_number major, rtems_device_minor_number minor, - void *arg) -{ - int sc; - unsigned char csr[2] = { DS1621_CMD_CSR_ACCESS, 0 }, cmd; - - /* First start command acquires a lock for the bus */ - - /* Initialize; switch continuous conversion on */ - sc = rtems_libi2c_start_write_bytes (minor, csr, 1); - if (sc < 0) - return -sc; - - sc = rtems_libi2c_start_read_bytes (minor, csr + 1, 1); - if (sc < 0) - return -sc; - - csr[1] &= ~DS1621_CSR_1SHOT; - - sc = rtems_libi2c_start_write_bytes (minor, csr, 2); - if (sc < 0) - return -sc; - - /* Start conversion */ - cmd = DS1621_CMD_START_CONV; - - sc = rtems_libi2c_start_write_bytes (minor, &cmd, 1); - if (sc < 0) - return -sc; - - /* sending 'stop' relinquishes the bus mutex -- don't hold it - * across system calls! - */ - return rtems_libi2c_send_stop (minor); -} - -static rtems_status_code -ds1621_read (rtems_device_major_number major, rtems_device_minor_number minor, - void *arg) -{ - int sc; - rtems_libio_rw_args_t *rwargs = arg; - unsigned char cmd = DS1621_CMD_READ_TEMP; - - sc = rtems_libi2c_start_write_bytes (minor, &cmd, 1); - if (sc < 0) - return -sc; - if (sc < 1) - return RTEMS_IO_ERROR; - sc = rtems_libi2c_start_read_bytes(minor, (unsigned char *)rwargs->buffer, 1); - if (sc < 0) { - rwargs->bytes_moved = 0; - return -sc; - } - rwargs->bytes_moved = 1; - return rtems_libi2c_send_stop (minor); -} - -static rtems_driver_address_table myops = { - .initialization_entry = ds1621_init, - .read_entry = ds1621_read, -}; - -static rtems_libi2c_drv_t my_drv_tbl = { - .ops = &myops, - .size = sizeof (my_drv_tbl), -}; - -rtems_libi2c_drv_t *i2c_ds1621_driver_descriptor = &my_drv_tbl; diff --git a/c/src/libchip/i2c/i2c-sc620.c b/c/src/libchip/i2c/i2c-sc620.c deleted file mode 100644 index e4dd2d0871..0000000000 --- a/c/src/libchip/i2c/i2c-sc620.c +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @file - * - * @brief I2C Driver for SEMTECH SC620 Octal LED Driver - */ - -/* - * Copyright (c) 2013 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Obere Lagerstr. 30 - * 82178 Puchheim - * Germany - * - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif - -#include - -#include - -#define SC620_REG_COUNT 10 - -static rtems_status_code i2c_sc620_write( - rtems_device_major_number major, - rtems_device_minor_number minor, - void *arg -) -{ - rtems_status_code sc = RTEMS_IO_ERROR; - rtems_libio_rw_args_t *rw = arg; - unsigned char *buf = (unsigned char *) &rw->buffer[0]; - - if (rw->count == 2 && buf[0] < SC620_REG_COUNT) { - int rv; - - rv = rtems_libi2c_start_write_bytes( - minor, buf, 2 - ); - if (rv == 2) { - sc = rtems_libi2c_send_stop(minor); - } - } - - rw->bytes_moved = sc == RTEMS_SUCCESSFUL ? 2 : 0; - - return sc; -} - -static rtems_status_code i2c_sc620_read( - rtems_device_major_number major, - rtems_device_minor_number minor, - void *arg -) -{ - rtems_status_code sc = RTEMS_IO_ERROR; - rtems_libio_rw_args_t *rw = arg; - unsigned char *buf = (unsigned char *) &rw->buffer[0]; - - if (rw->count == 1 && buf[0] < SC620_REG_COUNT) { - int rv; - - rv = rtems_libi2c_start_write_bytes(minor, buf, 1); - if (rv == 1) { - sc = rtems_libi2c_send_addr(minor, 0); - if (sc == RTEMS_SUCCESSFUL) { - rv = rtems_libi2c_read_bytes(minor, buf, 1); - if (rv == 1) { - sc = rtems_libi2c_send_stop(minor); - } - } - } - } - - rw->bytes_moved = sc == RTEMS_SUCCESSFUL ? 1 : 0; - - return sc; -} - -static rtems_driver_address_table i2c_sc620_ops = { - .read_entry = i2c_sc620_read, - .write_entry = i2c_sc620_write -}; - -rtems_libi2c_drv_t i2c_sc620_driver = { - .ops = &i2c_sc620_ops, - .size = sizeof(i2c_sc620_driver) -}; diff --git a/c/src/libchip/i2c/spi-flash-m25p40.c b/c/src/libchip/i2c/spi-flash-m25p40.c deleted file mode 100644 index 075a4510b9..0000000000 --- a/c/src/libchip/i2c/spi-flash-m25p40.c +++ /dev/null @@ -1,60 +0,0 @@ -/*===============================================================*\ -| Project: SPI driver for M25P40 like spi flash device | -+-----------------------------------------------------------------+ -| Copyright (c) 2007 | -| Embedded Brains GmbH | -| Obere Lagerstr. 30 | -| D-82178 Puchheim | -| Germany | -| rtems@embedded-brains.de | -+-----------------------------------------------------------------+ -| The license and distribution terms for this file may be | -| found in the file LICENSE in this distribution or at | -| | -| http://www.rtems.org/license/LICENSE. | -| | -+-----------------------------------------------------------------+ -\*===============================================================*/ - -#include -#include - -#include -#include - - -static spi_memdrv_t spi_flash_m25p40_rw_drv_t = { - {/* public fields */ - .ops = &spi_memdrv_rw_ops, /* operations of general memdrv */ - .size = sizeof (spi_flash_m25p40_rw_drv_t), - }, - { /* our private fields */ - .baudrate = 2000000, - .erase_before_program = true, - .empty_state = 0xff, - .page_size = 256, /* programming page size in bytes */ - .sector_size = 0x10000, /* 64K - erase sector size in bytes */ - .mem_size = 0x80000, /* 512K - total capacity in bytes */ - } -}; - -rtems_libi2c_drv_t *spi_flash_m25p40_rw_driver_descriptor = -&spi_flash_m25p40_rw_drv_t.libi2c_drv_entry; - -static spi_memdrv_t spi_flash_m25p40_ro_drv_t = { - {/* public fields */ - .ops = &spi_memdrv_ro_ops, /* operations of general memdrv */ - .size = sizeof (spi_flash_m25p40_ro_drv_t), - }, - { /* our private fields */ - .baudrate = 2000000, - .erase_before_program = true, - .empty_state = 0xff, - .page_size = 256, /* programming page size in bytes */ - .sector_size = 0x10000, /* 64K erase sector size in bytes */ - .mem_size = 0x80000, /* 512K total capacity in bytes */ - } -}; - -rtems_libi2c_drv_t *spi_flash_m25p40_ro_driver_descriptor = -&spi_flash_m25p40_ro_drv_t.libi2c_drv_entry; diff --git a/c/src/libchip/i2c/spi-fram-fm25l256.c b/c/src/libchip/i2c/spi-fram-fm25l256.c deleted file mode 100644 index 086feb82bb..0000000000 --- a/c/src/libchip/i2c/spi-fram-fm25l256.c +++ /dev/null @@ -1,60 +0,0 @@ -/*===============================================================*\ -| Project: SPI driver for FM25L256 like spi fram device | -+-----------------------------------------------------------------+ -| Copyright (c) 2008 | -| Embedded Brains GmbH | -| Obere Lagerstr. 30 | -| D-82178 Puchheim | -| Germany | -| rtems@embedded-brains.de | -+-----------------------------------------------------------------+ -| The license and distribution terms for this file may be | -| found in the file LICENSE in this distribution or at | -| | -| http://www.rtems.org/license/LICENSE. | -| | -+-----------------------------------------------------------------+ -\*===============================================================*/ - -#include -#include - -#include -#include - - -static spi_memdrv_t spi_fram_fm25l256_rw_drv_t = { - {/* public fields */ - .ops = &spi_memdrv_rw_ops, /* operations of general memdrv */ - .size = sizeof (spi_fram_fm25l256_rw_drv_t), - }, - { /* our private fields */ - .baudrate = 2000000, - .erase_before_program = false, - .empty_state = 0xff, - .page_size = 0x8000, /* 32K programming page size in bytes */ - .sector_size = 1, /* erase sector size in bytes */ - .mem_size = 0x8000, /* 32K total capacity in bytes */ - } -}; - -rtems_libi2c_drv_t *spi_fram_fm25l256_rw_driver_descriptor = -&spi_fram_fm25l256_rw_drv_t.libi2c_drv_entry; - -static spi_memdrv_t spi_fram_fm25l256_ro_drv_t = { - {/* public fields */ - .ops = &spi_memdrv_ro_ops, /* operations of general memdrv */ - .size = sizeof (spi_fram_fm25l256_ro_drv_t), - }, - { /* our private fields */ - .baudrate = 2000000, - .erase_before_program = false, - .empty_state = 0xff, - .page_size = 0x8000, /* 32k programming page size in bytes */ - .sector_size = 1, /* erase sector size in bytes */ - .mem_size = 0x8000, /* 32k total capacity in bytes */ - } -}; - -rtems_libi2c_drv_t *spi_fram_fm25l256_ro_driver_descriptor = -&spi_fram_fm25l256_ro_drv_t.libi2c_drv_entry; diff --git a/c/src/libchip/i2c/spi-memdrv.c b/c/src/libchip/i2c/spi-memdrv.c deleted file mode 100644 index 593029732e..0000000000 --- a/c/src/libchip/i2c/spi-memdrv.c +++ /dev/null @@ -1,442 +0,0 @@ -/*===============================================================*\ -| Project: SPI driver for spi memory devices | -+-----------------------------------------------------------------+ -| Copyright (c) 2008 | -| Embedded Brains GmbH | -| Obere Lagerstr. 30 | -| D-82178 Puchheim | -| Germany | -| rtems@embedded-brains.de | -+-----------------------------------------------------------------+ -| The license and distribution terms for this file may be | -| found in the file LICENSE in this distribution or at | -| | -| http://www.rtems.org/license/LICENSE. | -| | -+-----------------------------------------------------------------+ -\*===============================================================*/ -/* - * FIXME: currently, this driver only supports read/write accesses - * erase accesses are to be completed - */ - - -#include -#include - -#include -#include - -#define SPI_MEM_CMD_WREN 0x06 -#define SPI_MEM_CMD_WRDIS 0x04 -#define SPI_MEM_CMD_RDID 0x9F -#define SPI_MEM_CMD_RDSR 0x05 -#define SPI_MEM_CMD_WRSR 0x01 -#define SPI_MEM_CMD_READ 0x03 -#define SPI_MEM_CMD_PP 0x02 /* page program */ -#define SPI_MEM_CMD_SE 0xD8 /* sector erase */ -#define SPI_MEM_CMD_BE 0xC7 /* bulk erase */ -#define SPI_MEM_CMD_DP 0xB9 /* deep power down */ -#define SPI_MEM_CMD_RES 0xAB /* release from deep power down */ - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static rtems_status_code spi_memdrv_minor2param_ptr -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| translate given minor device number to param pointer | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_device_minor_number minor, /* minor number of device */ - spi_memdrv_param_t **param_ptr /* ptr to param ptr */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| o = ok or error code | -\*=========================================================================*/ -{ - rtems_status_code rc = RTEMS_SUCCESSFUL; - spi_memdrv_t *drv_ptr; - - if (rc == RTEMS_SUCCESSFUL) { - rc = -rtems_libi2c_ioctl(minor, - RTEMS_LIBI2C_IOCTL_GET_DRV_T, - &drv_ptr); - } - if ((rc == RTEMS_SUCCESSFUL) && - (drv_ptr->libi2c_drv_entry.size != sizeof(spi_memdrv_t))) { - rc = RTEMS_INVALID_SIZE; - } - if (rc == RTEMS_SUCCESSFUL) { - *param_ptr = &(drv_ptr->spi_memdrv_param); - } - return rc; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static rtems_status_code spi_memdrv_wait_ms -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| wait a certain interval given in ms | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - int ms /* time to wait in milliseconds */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| o = ok or error code | -\*=========================================================================*/ -{ - rtems_interval ticks_per_second; - - ticks_per_second = rtems_clock_get_ticks_per_second(); - (void) rtems_task_wake_after(ticks_per_second * ms / 1000); - return 0; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -rtems_status_code spi_memdrv_write -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| write a block of data to flash | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_device_major_number major, /* major device number */ - rtems_device_minor_number minor, /* minor device number */ - void *arg /* ptr to write argument struct */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| o = ok or error code | -\*=========================================================================*/ -{ - rtems_status_code rc = RTEMS_SUCCESSFUL; - rtems_libio_rw_args_t *rwargs = arg; - off_t off = rwargs->offset; - int cnt = rwargs->count; - unsigned char *buf = (unsigned char *)rwargs->buffer; - int bytes_sent = 0; - int curr_cnt; - unsigned char cmdbuf[4]; - int ret_cnt = 0; - int cmd_size; - spi_memdrv_param_t *mem_param_ptr; - rtems_libi2c_tfr_mode_t tfr_mode = { - .baudrate = 20000000, /* maximum bits per second */ - .bits_per_char = 8, /* how many bits per byte/word/longword? */ - .lsb_first = FALSE, /* FALSE: send MSB first */ - .clock_inv = FALSE, /* FALSE: non-inverted clock (high active) */ - .clock_phs = FALSE /* FALSE: clock starts in middle of data tfr */ - } ; - - /* - * get mem parameters - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = spi_memdrv_minor2param_ptr(minor,&mem_param_ptr); - } - /* - * check arguments - */ - if (rc == RTEMS_SUCCESSFUL) { - if ((cnt <= 0) || - (cnt > mem_param_ptr->mem_size) || - (off > (mem_param_ptr->mem_size-cnt))) { - rc = RTEMS_INVALID_SIZE; - } - else if (buf == NULL) { - rc = RTEMS_INVALID_ADDRESS; - } - } - while ((rc == RTEMS_SUCCESSFUL) && - (cnt > bytes_sent)) { - curr_cnt = cnt - bytes_sent; - if ((mem_param_ptr->page_size > 0) && - (off / mem_param_ptr->page_size) != - ((off+curr_cnt+1) / mem_param_ptr->page_size)) { - curr_cnt = mem_param_ptr->page_size - (off % mem_param_ptr->page_size); - } - /* - * select device, set transfer mode, address device - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_start(minor); - } - /* - * set transfer mode - */ - if (rc == RTEMS_SUCCESSFUL) { - tfr_mode.baudrate = mem_param_ptr->baudrate; - rc = -rtems_libi2c_ioctl(minor, - RTEMS_LIBI2C_IOCTL_SET_TFRMODE, - &tfr_mode); - } - - /* - * address device - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_addr(minor,TRUE); - } - - /* - * send write_enable command - */ - if (rc == RTEMS_SUCCESSFUL) { - cmdbuf[0] = SPI_MEM_CMD_WREN; - ret_cnt = rtems_libi2c_write_bytes(minor,cmdbuf,1); - if (ret_cnt < 0) { - rc = -ret_cnt; - } - } - /* - * terminate transfer - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_stop(minor); - } - /* - * select device, set transfer mode - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_start(minor); - } - - /* - * address device - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_addr(minor,TRUE); - } - - /* - * set transfer mode - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = -rtems_libi2c_ioctl(minor, - RTEMS_LIBI2C_IOCTL_SET_TFRMODE, - &tfr_mode); - } - /* - * send "page program" command and address - */ - if (rc == RTEMS_SUCCESSFUL) { - cmdbuf[0] = SPI_MEM_CMD_PP; - if (mem_param_ptr->mem_size > 0x10000 /* 256*256 */) { - cmdbuf[1] = (off >> 16) & 0xff; - cmdbuf[2] = (off >> 8) & 0xff; - cmdbuf[3] = (off >> 0) & 0xff; - cmd_size = 4; - } - else if (mem_param_ptr->mem_size > 256) { - cmdbuf[1] = (off >> 8) & 0xff; - cmdbuf[2] = (off >> 0) & 0xff; - cmd_size = 3; - } - else { - cmdbuf[1] = (off >> 0) & 0xff; - cmd_size = 1; - } - - ret_cnt = rtems_libi2c_write_bytes(minor,cmdbuf,cmd_size); - if (ret_cnt < 0) { - rc = -ret_cnt; - } - } - /* - * send write data - */ - if (rc == RTEMS_SUCCESSFUL) { - ret_cnt = rtems_libi2c_write_bytes(minor,buf,curr_cnt); - if (ret_cnt < 0) { - rc = -ret_cnt; - } - } - /* - * terminate transfer - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_stop(minor); - } - /* - * wait proper time for data to store: 5ms - * FIXME: select proper interval or poll, until device is finished - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = spi_memdrv_wait_ms(5); - } - /* - * adjust bytecount to be sent and pointers - */ - bytes_sent += curr_cnt; - off += curr_cnt; - buf += curr_cnt; - } - rwargs->bytes_moved = bytes_sent; - return rc; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -rtems_status_code spi_memdrv_read -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| read a block of data from flash | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_device_major_number major, /* major device number */ - rtems_device_minor_number minor, /* minor device number */ - void *arg /* ptr to read argument struct */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| o = ok or error code | -\*=========================================================================*/ -{ - rtems_status_code rc = RTEMS_SUCCESSFUL; - rtems_libio_rw_args_t *rwargs = arg; - off_t off = rwargs->offset; - int cnt = rwargs->count; - unsigned char *buf = (unsigned char *)rwargs->buffer; - unsigned char cmdbuf[4]; - int ret_cnt = 0; - int cmd_size; - spi_memdrv_param_t *mem_param_ptr; - rtems_libi2c_tfr_mode_t tfr_mode = { - .baudrate = 20000000, /* maximum bits per second */ - .bits_per_char = 8, /* how many bits per byte/word/longword? */ - .lsb_first = FALSE, /* FALSE: send MSB first */ - .clock_inv = FALSE, /* FALSE: non-inverted clock (high active) */ - .clock_phs = FALSE /* FALSE: clock starts in middle of data tfr */ - }; - - /* - * get mem parameters - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = spi_memdrv_minor2param_ptr(minor,&mem_param_ptr); - } - /* - * check arguments - */ - if (rc == RTEMS_SUCCESSFUL) { - if ((cnt <= 0) || - (cnt > mem_param_ptr->mem_size) || - (off > (mem_param_ptr->mem_size-cnt))) { - rc = RTEMS_INVALID_SIZE; - } - else if (buf == NULL) { - rc = RTEMS_INVALID_ADDRESS; - } - } - /* - * select device, set transfer mode, address device - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_start(minor); - } - /* - * set transfer mode - */ - if (rc == RTEMS_SUCCESSFUL) { - tfr_mode.baudrate = mem_param_ptr->baudrate; - rc = -rtems_libi2c_ioctl(minor, - RTEMS_LIBI2C_IOCTL_SET_TFRMODE, - &tfr_mode); - } - /* - * address device - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_addr(minor,TRUE); - } - - if (off >= mem_param_ptr->mem_size) { - /* - * HACK: beyond size of memory array? then read status register instead - */ - /* - * send read status register command - */ - if (rc == RTEMS_SUCCESSFUL) { - cmdbuf[0] = SPI_MEM_CMD_RDSR; - ret_cnt = rtems_libi2c_write_bytes(minor,cmdbuf,1); - if (ret_cnt < 0) { - rc = -ret_cnt; - } - } - } - else { - /* - * send read command and address - */ - if (rc == RTEMS_SUCCESSFUL) { - cmdbuf[0] = SPI_MEM_CMD_READ; - if (mem_param_ptr->mem_size > 0x10000 /* 256*256 */) { - cmdbuf[1] = (off >> 16) & 0xff; - cmdbuf[2] = (off >> 8) & 0xff; - cmdbuf[3] = (off >> 0) & 0xff; - cmd_size = 4; - } - else if (mem_param_ptr->mem_size > 256) { - cmdbuf[1] = (off >> 8) & 0xff; - cmdbuf[2] = (off >> 0) & 0xff; - cmd_size = 3; - } - else { - cmdbuf[1] = (off >> 0) & 0xff; - cmd_size = 1; - } - ret_cnt = rtems_libi2c_write_bytes(minor,cmdbuf,cmd_size); - if (ret_cnt < 0) { - rc = -ret_cnt; - } - } - } - /* - * fetch read data - */ - if (rc == RTEMS_SUCCESSFUL) { - ret_cnt = rtems_libi2c_read_bytes (minor,buf,cnt); - if (ret_cnt < 0) { - rc = -ret_cnt; - } - } - - /* - * terminate transfer - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_stop(minor); - } - rwargs->bytes_moved = (rc == RTEMS_SUCCESSFUL) ? ret_cnt : 0; - - return rc; -} - -/* - * driver operation tables - */ -rtems_driver_address_table spi_memdrv_rw_ops = { - .read_entry = spi_memdrv_read, - .write_entry = spi_memdrv_write -}; - -rtems_driver_address_table spi_memdrv_ro_ops = { - .read_entry = spi_memdrv_read, -}; - diff --git a/c/src/libchip/i2c/spi-sd-card.c b/c/src/libchip/i2c/spi-sd-card.c deleted file mode 100644 index a343f7faa8..0000000000 --- a/c/src/libchip/i2c/spi-sd-card.c +++ /dev/null @@ -1,1322 +0,0 @@ -/** - * @file - * - * @brief SD Card LibI2C driver. - */ - -/* - * Copyright (c) 2008 - * Embedded Brains GmbH - * Obere Lagerstr. 30 - * D-82178 Puchheim - * Germany - * rtems@embedded-brains.de - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include - -/** - * @name Integer to and from Byte-Stream Converter - * @{ - */ - -static inline uint16_t sd_card_get_uint16( const uint8_t *s) -{ - return (uint16_t) ((s [0] << 8) | s [1]); -} - -static inline uint32_t sd_card_get_uint32( const uint8_t *s) -{ - return ((uint32_t) s [0] << 24) | ((uint32_t) s [1] << 16) | ((uint32_t) s [2] << 8) | (uint32_t) s [3]; -} - -static inline void sd_card_put_uint16( uint16_t v, uint8_t *s) -{ - *s++ = (uint8_t) (v >> 8); - *s = (uint8_t) (v); -} - -static inline void sd_card_put_uint32( uint32_t v, uint8_t *s) -{ - *s++ = (uint8_t) (v >> 24); - *s++ = (uint8_t) (v >> 16); - *s++ = (uint8_t) (v >> 8); - *s = (uint8_t) (v); -} - -/** @} */ - -#define SD_CARD_BUSY_TOKEN 0 - -#define SD_CARD_BLOCK_SIZE_DEFAULT 512 - -#define SD_CARD_COMMAND_RESPONSE_START 7 - -/** - * @name Commands - * @{ - */ - -#define SD_CARD_CMD_GO_IDLE_STATE 0 -#define SD_CARD_CMD_SEND_OP_COND 1 -#define SD_CARD_CMD_SEND_IF_COND 8 -#define SD_CARD_CMD_SEND_CSD 9 -#define SD_CARD_CMD_SEND_CID 10 -#define SD_CARD_CMD_STOP_TRANSMISSION 12 -#define SD_CARD_CMD_SEND_STATUS 13 -#define SD_CARD_CMD_SET_BLOCKLEN 16 -#define SD_CARD_CMD_READ_SINGLE_BLOCK 17 -#define SD_CARD_CMD_READ_MULTIPLE_BLOCK 18 -#define SD_CARD_CMD_SET_BLOCK_COUNT 23 -#define SD_CARD_CMD_WRITE_BLOCK 24 -#define SD_CARD_CMD_WRITE_MULTIPLE_BLOCK 25 -#define SD_CARD_CMD_PROGRAM_CSD 27 -#define SD_CARD_CMD_SET_WRITE_PROT 28 -#define SD_CARD_CMD_CLR_WRITE_PROT 29 -#define SD_CARD_CMD_SEND_WRITE_PROT 30 -#define SD_CARD_CMD_TAG_SECTOR_START 32 -#define SD_CARD_CMD_TAG_SECTOR_END 33 -#define SD_CARD_CMD_UNTAG_SECTOR 34 -#define SD_CARD_CMD_TAG_ERASE_GROUP_START 35 -#define SD_CARD_CMD_TAG_ERASE_GROUP_END 36 -#define SD_CARD_CMD_UNTAG_ERASE_GROUP 37 -#define SD_CARD_CMD_ERASE 38 -#define SD_CARD_CMD_LOCK_UNLOCK 42 -#define SD_CARD_CMD_APP_CMD 55 -#define SD_CARD_CMD_GEN_CND 56 -#define SD_CARD_CMD_READ_OCR 58 -#define SD_CARD_CMD_CRC_ON_OFF 59 - -/** @} */ - -/** - * @name Application Commands - * @{ - */ - -#define SD_CARD_ACMD_SD_SEND_OP_COND 41 - -/** @} */ - -/** - * @name Command Flags - * @{ - */ - -#define SD_CARD_FLAG_HCS 0x40000000U - -#define SD_CARD_FLAG_VHS_2_7_TO_3_3 0x00000100U - -#define SD_CARD_FLAG_CHECK_PATTERN 0x000000aaU - -/** @} */ - -/** - * @name Command Fields - * @{ - */ - -#define SD_CARD_COMMAND_SET_COMMAND( c, cmd) (c) [1] = (uint8_t) (0x40 + ((cmd) & 0x3f)) - -#define SD_CARD_COMMAND_SET_ARGUMENT( c, arg) sd_card_put_uint32( (arg), &((c) [2])) - -#define SD_CARD_COMMAND_SET_CRC7( c, crc7) ((c) [6] = ((crc7) << 1) | 1U) - -#define SD_CARD_COMMAND_GET_CRC7( c) ((c) [6] >> 1) - -/** @} */ - -/** - * @name Response Fields - * @{ - */ - -#define SD_CARD_IS_RESPONSE( r) (((r) & 0x80) == 0) - -#define SD_CARD_IS_ERRORLESS_RESPONSE( r) (((r) & 0x7e) == 0) - -#define SD_CARD_IS_NOT_IDLE_RESPONSE( r) (((r) & 0x81) == 0) - -#define SD_CARD_IS_DATA_ERROR( r) (((r) & 0xe0) == 0) - -#define SD_CARD_IS_DATA_REJECTED( r) (((r) & 0x1f) != 0x05) - -/** @} */ - -/** - * @name Card Identification - * @{ - */ - -#define SD_CARD_CID_SIZE 16 - -#define SD_CARD_CID_GET_MID( cid) ((cid) [0]) -#define SD_CARD_CID_GET_OID( cid) sd_card_get_uint16( cid + 1) -#define SD_CARD_CID_GET_PNM( cid, i) ((char) (cid) [3 + (i)]) -#define SD_CARD_CID_GET_PRV( cid) ((cid) [9]) -#define SD_CARD_CID_GET_PSN( cid) sd_card_get_uint32( cid + 10) -#define SD_CARD_CID_GET_MDT( cid) ((cid) [14]) -#define SD_CARD_CID_GET_CRC7( cid) ((cid) [15] >> 1) - -/** @} */ - -/** - * @name Card Specific Data - * @{ - */ - -#define SD_CARD_CSD_SIZE 16 - -#define SD_CARD_CSD_GET_CSD_STRUCTURE( csd) ((csd) [0] >> 6) -#define SD_CARD_CSD_GET_SPEC_VERS( csd) (((csd) [0] >> 2) & 0xf) -#define SD_CARD_CSD_GET_TAAC( csd) ((csd) [1]) -#define SD_CARD_CSD_GET_NSAC( csd) ((uint32_t) (csd) [2]) -#define SD_CARD_CSD_GET_TRAN_SPEED( csd) ((csd) [3]) -#define SD_CARD_CSD_GET_C_SIZE( csd) ((((uint32_t) (csd) [6] & 0x3) << 10) + (((uint32_t) (csd) [7]) << 2) + ((((uint32_t) (csd) [8]) >> 6) & 0x3)) -#define SD_CARD_CSD_GET_C_SIZE_MULT( csd) ((((csd) [9] & 0x3) << 1) + (((csd) [10] >> 7) & 0x1)) -#define SD_CARD_CSD_GET_READ_BLK_LEN( csd) ((uint32_t) (csd) [5] & 0xf) -#define SD_CARD_CSD_GET_WRITE_BLK_LEN( csd) ((((uint32_t) (csd) [12] & 0x3) << 2) + ((((uint32_t) (csd) [13]) >> 6) & 0x3)) -#define SD_CARD_CSD_1_GET_C_SIZE( csd) ((((uint32_t) (csd) [7] & 0x3f) << 16) + (((uint32_t) (csd) [8]) << 8) + (uint32_t) (csd) [9]) - -/** @} */ - -#define SD_CARD_INVALIDATE_RESPONSE_INDEX( e) e->response_index = SD_CARD_COMMAND_SIZE - -/** - * @name Data Start and Stop Tokens - * @{ - */ - -#define SD_CARD_START_BLOCK_SINGLE_BLOCK_READ 0xfe -#define SD_CARD_START_BLOCK_MULTIPLE_BLOCK_READ 0xfe -#define SD_CARD_START_BLOCK_SINGLE_BLOCK_WRITE 0xfe -#define SD_CARD_START_BLOCK_MULTIPLE_BLOCK_WRITE 0xfc -#define SD_CARD_STOP_TRANSFER_MULTIPLE_BLOCK_WRITE 0xfd - -/** @} */ - -/** - * @name Card Specific Data Functions - * @{ - */ - -static inline uint32_t sd_card_block_number( const uint8_t *csd) -{ - uint32_t size = SD_CARD_CSD_GET_C_SIZE( csd); - uint32_t mult = 1U << (SD_CARD_CSD_GET_C_SIZE_MULT( csd) + 2); - return (size + 1) * mult; -} - -static inline uint32_t sd_card_capacity( const uint8_t *csd) -{ - uint32_t block_size = 1U << SD_CARD_CSD_GET_READ_BLK_LEN( csd); - return sd_card_block_number( csd) * block_size; -} - -static inline uint32_t sd_card_transfer_speed( const uint8_t *csd) -{ - uint32_t s = SD_CARD_CSD_GET_TRAN_SPEED( csd); - uint32_t e = s & 0x7; - uint32_t m = s >> 3; - switch (e) { - case 0: s = 10000; break; - case 1: s = 100000; break; - case 2: s = 1000000; break; - case 3: s = 10000000; break; - default: s = 0; break; - } - switch (m) { - case 1: s *= 10; break; - case 2: s *= 12; break; - case 3: s *= 13; break; - case 4: s *= 15; break; - case 5: s *= 20; break; - case 6: s *= 25; break; - case 7: s *= 30; break; - case 8: s *= 35; break; - case 9: s *= 40; break; - case 10: s *= 45; break; - case 11: s *= 50; break; - case 12: s *= 55; break; - case 13: s *= 60; break; - case 14: s *= 70; break; - case 15: s *= 80; break; - default: s *= 0; break; - } - return s; -} - -static inline uint32_t sd_card_access_time( const uint8_t *csd) -{ - uint32_t ac = SD_CARD_CSD_GET_TAAC( csd); - uint32_t e = ac & 0x7; - uint32_t m = ac >> 3; - switch (e) { - case 0: ac = 1; break; - case 1: ac = 10; break; - case 2: ac = 100; break; - case 3: ac = 1000; break; - case 4: ac = 10000; break; - case 5: ac = 100000; break; - case 6: ac = 1000000; break; - case 7: ac = 10000000; break; - default: ac = 0; break; - } - switch (m) { - case 1: ac *= 10; break; - case 2: ac *= 12; break; - case 3: ac *= 13; break; - case 4: ac *= 15; break; - case 5: ac *= 20; break; - case 6: ac *= 25; break; - case 7: ac *= 30; break; - case 8: ac *= 35; break; - case 9: ac *= 40; break; - case 10: ac *= 45; break; - case 11: ac *= 50; break; - case 12: ac *= 55; break; - case 13: ac *= 60; break; - case 14: ac *= 70; break; - case 15: ac *= 80; break; - default: ac *= 0; break; - } - return ac / 10; -} - -static inline uint32_t sd_card_max_access_time( const uint8_t *csd, uint32_t transfer_speed) -{ - uint64_t ac = sd_card_access_time( csd); - uint32_t ac_100ms = transfer_speed / 80; - uint32_t n = SD_CARD_CSD_GET_NSAC( csd) * 100; - /* ac is in ns, transfer_speed in bps, max_access_time in bytes. - max_access_time is 100 times typical access time (taac+nsac) */ - ac = ac * transfer_speed / 80000000; - ac = ac + 100*n; - if ((uint32_t)ac > ac_100ms) - return ac_100ms; - else - return (uint32_t)ac; -} - -/** @} */ - -/** - * @name CRC functions - * - * Based on http://en.wikipedia.org/wiki/Computation_of_CRC - * - * @{ - */ - -static uint8_t sd_card_compute_crc7 (uint8_t *data, size_t len) -{ - uint8_t e, f, crc; - size_t i; - - crc = 0; - for (i = 0; i < len; i++) { - e = crc ^ data[i]; - f = e ^ (e >> 4) ^ (e >> 7); - crc = (f << 1) ^ (f << 4); - } - return crc >> 1; -} - -static uint16_t sd_card_compute_crc16 (uint8_t *data, size_t len) -{ - uint8_t s, t; - uint16_t crc; - size_t i; - - crc = 0; - for (i = 0; i < len; i++) { - s = data[i] ^ (crc >> 8); - t = s ^ (s >> 4); - crc = (crc << 8) ^ t ^ (t << 5) ^ (t << 12); - } - return crc; -} - -/** @} */ - -/** - * @name Communication Functions - * @{ - */ - -static inline int sd_card_query( sd_card_driver_entry *e, uint8_t *in, int n) -{ - return rtems_libi2c_read_bytes( e->bus, in, n); -} - -static int sd_card_wait( sd_card_driver_entry *e) -{ - int rv = 0; - int r = 0; - int n = 2; - /* For writes, the timeout is 2.5 times that of reads; since we - don't know if it is a write or read, assume write. - FIXME should actually look at R2W_FACTOR for non-HC cards. */ - int retries = e->n_ac_max * 25 / 10; - /* n_ac_max/100 is supposed to be the average waiting time. To - approximate this, we start with waiting n_ac_max/150 and - gradually increase the waiting time. */ - int wait_time_bytes = (retries + 149) / 150; - while (e->busy) { - /* Query busy tokens */ - rv = sd_card_query( e, e->response, n); - RTEMS_CHECK_RV( rv, "Busy"); - - /* Search for non busy tokens */ - for (r = 0; r < n; ++r) { - if (e->response [r] != SD_CARD_BUSY_TOKEN) { - e->busy = false; - return 0; - } - } - retries -= n; - if (retries <= 0) { - return -RTEMS_TIMEOUT; - } - - if (e->schedule_if_busy) { - uint64_t wait_time_us = wait_time_bytes; - wait_time_us *= 8000000; - wait_time_us /= e->transfer_mode.baudrate; - rtems_task_wake_after( RTEMS_MICROSECONDS_TO_TICKS(wait_time_us)); - retries -= wait_time_bytes; - wait_time_bytes = wait_time_bytes * 15 / 10; - } else { - n = SD_CARD_COMMAND_SIZE; - } - } - return 0; -} - -static int sd_card_send_command( sd_card_driver_entry *e, uint32_t command, uint32_t argument) -{ - int rv = 0; - rtems_libi2c_read_write_t rw = { - .rd_buf = e->response, - .wr_buf = e->command, - .byte_cnt = SD_CARD_COMMAND_SIZE - }; - int r = 0; - uint8_t crc7; - - SD_CARD_INVALIDATE_RESPONSE_INDEX( e); - - /* Wait until card is not busy */ - rv = sd_card_wait( e); - RTEMS_CHECK_RV( rv, "Wait"); - - /* Write command and read response */ - SD_CARD_COMMAND_SET_COMMAND( e->command, command); - SD_CARD_COMMAND_SET_ARGUMENT( e->command, argument); - crc7 = sd_card_compute_crc7( e->command + 1, 5); - SD_CARD_COMMAND_SET_CRC7( e->command, crc7); - rv = rtems_libi2c_ioctl( e->bus, RTEMS_LIBI2C_IOCTL_READ_WRITE, &rw); - RTEMS_CHECK_RV( rv, "Write command and read response"); - - /* Check respose */ - for (r = SD_CARD_COMMAND_RESPONSE_START; r < SD_CARD_COMMAND_SIZE; ++r) { - RTEMS_DEBUG_PRINT( "Token [%02u]: 0x%02x\n", r, e->response [r]); - e->response_index = r; - if (SD_CARD_IS_RESPONSE( e->response [r])) { - if (SD_CARD_IS_ERRORLESS_RESPONSE( e->response [r])) { - return 0; - } else { - RTEMS_SYSLOG_ERROR( "Command error [%02i]: 0x%02" PRIx8 "\n", r, e->response [r]); - goto sd_card_send_command_error; - } - } else if (e->response [r] != SD_CARD_IDLE_TOKEN) { - RTEMS_SYSLOG_ERROR( "Unexpected token [%02i]: 0x%02" PRIx8 "\n", r, e->response [r]); - goto sd_card_send_command_error; - } - } - - RTEMS_SYSLOG_ERROR( "Timeout\n"); - -sd_card_send_command_error: - - RTEMS_SYSLOG_ERROR( "Response:"); - for (r = 0; r < SD_CARD_COMMAND_SIZE; ++r) { - if (e->response_index == r) { - RTEMS_SYSLOG_PRINT( " %02" PRIx8 ":[%02" PRIx8 "]", e->command [r], e->response [r]); - } else { - RTEMS_SYSLOG_PRINT( " %02" PRIx8 ":%02" PRIx8 "", e->command [r], e->response [r]); - } - } - RTEMS_SYSLOG_PRINT( "\n"); - - return -RTEMS_IO_ERROR; -} - -static int sd_card_send_register_command( sd_card_driver_entry *e, uint32_t command, uint32_t argument, uint32_t *reg) -{ - int rv = 0; - uint8_t crc7; - - rv = sd_card_send_command( e, command, argument); - RTEMS_CHECK_RV( rv, "Send command"); - - if (e->response_index + 5 > SD_CARD_COMMAND_SIZE) { - /* - * TODO: If this happens in the wild we need to implement a - * more sophisticated response query. - */ - RTEMS_SYSLOG_ERROR( "Unexpected response position\n"); - return -RTEMS_IO_ERROR; - } - - crc7 = sd_card_compute_crc7( e->response + e->response_index, 5); - if (crc7 != SD_CARD_COMMAND_GET_CRC7( e->response + e->response_index) && - SD_CARD_COMMAND_GET_CRC7( e->response + e->response_index) != 0x7f) { - RTEMS_SYSLOG_ERROR( "CRC check failed on register command\n"); - return -RTEMS_IO_ERROR; - } - - *reg = sd_card_get_uint32( e->response + e->response_index + 1); - - return 0; -} - -static int sd_card_stop_multiple_block_read( sd_card_driver_entry *e) -{ - int rv = 0; - uint8_t crc7; - - SD_CARD_COMMAND_SET_COMMAND( e->command, SD_CARD_CMD_STOP_TRANSMISSION); - SD_CARD_COMMAND_SET_ARGUMENT( e->command, 0); - /*crc7 = sd_card_compute_crc7( e->command + 1, 5);*/ - crc7 = 0x30; /* Help compiler - command and argument are constants */ - SD_CARD_COMMAND_SET_CRC7( e->command, crc7); - rv = rtems_libi2c_write_bytes( e->bus, e->command, SD_CARD_COMMAND_SIZE); - RTEMS_CHECK_RV( rv, "Write stop transfer token"); - - return 0; -} - -static int sd_card_stop_multiple_block_write( sd_card_driver_entry *e) -{ - int rv = 0; - uint8_t stop_transfer [3] = { SD_CARD_IDLE_TOKEN, SD_CARD_STOP_TRANSFER_MULTIPLE_BLOCK_WRITE, SD_CARD_IDLE_TOKEN }; - - /* Wait until card is not busy */ - rv = sd_card_wait( e); - RTEMS_CHECK_RV( rv, "Wait"); - - /* Send stop token */ - rv = rtems_libi2c_write_bytes( e->bus, stop_transfer, 3); - RTEMS_CHECK_RV( rv, "Write stop transfer token"); - - /* Card is now busy */ - e->busy = true; - - return 0; -} - -static int sd_card_read( sd_card_driver_entry *e, uint8_t start_token, uint8_t *in, int n) -{ - int rv = 0; - - /* Discard command response */ - int r = e->response_index + 1; - - /* Standard response size */ - int response_size = SD_CARD_COMMAND_SIZE; - - /* Where the response is stored */ - uint8_t *response = e->response; - - /* Data input index */ - int i = 0; - - /* CRC check of data */ - uint16_t crc16; - - /* Maximum number of tokens to read. */ - int retries = e->n_ac_max; - - SD_CARD_INVALIDATE_RESPONSE_INDEX( e); - - while (true) { - RTEMS_DEBUG_PRINT( "Search from %u to %u\n", r, response_size - 1); - - /* Search the data start token in in current response buffer */ - retries -= (response_size - r); - while (r < response_size) { - RTEMS_DEBUG_PRINT( "Token [%02u]: 0x%02x\n", r, response [r]); - if (response [r] == start_token) { - /* Discard data start token */ - ++r; - goto sd_card_read_start; - } else if (SD_CARD_IS_DATA_ERROR( response [r])) { - RTEMS_SYSLOG_ERROR( "Data error token [%02i]: 0x%02" PRIx8 "\n", r, response [r]); - return -RTEMS_IO_ERROR; - } else if (response [r] != SD_CARD_IDLE_TOKEN) { - RTEMS_SYSLOG_ERROR( "Unexpected token [%02i]: 0x%02" PRIx8 "\n", r, response [r]); - return -RTEMS_IO_ERROR; - } - ++r; - } - - if (retries <= 0) { - RTEMS_SYSLOG_ERROR( "Timeout\n"); - return -RTEMS_IO_ERROR; - } - - if (e->schedule_if_busy) - rtems_task_wake_after( RTEMS_YIELD_PROCESSOR); - - /* Query more. We typically have to wait between 10 and 100 - bytes. To reduce overhead, read the response in chunks of - 50 bytes - this doesn't introduce too much copy overhead - but does allow SPI DMA transfers to work efficiently. */ - response = in; - response_size = 50; - if (response_size > n) - response_size = n; - rv = sd_card_query( e, response, response_size); - RTEMS_CHECK_RV( rv, "Query data start token"); - - /* Reset start position */ - r = 0; - } - -sd_card_read_start: - - /* Read data */ - while (r < response_size && i < n) { - in [i++] = response [r++]; - } - - /* Read more data? */ - if (i < n) { - rv = sd_card_query( e, &in [i], n - i); - RTEMS_CHECK_RV( rv, "Read data"); - i += rv; - } - - /* Read CRC 16 and N_RC */ - rv = sd_card_query( e, e->response, 3); - RTEMS_CHECK_RV( rv, "Read CRC 16"); - - crc16 = sd_card_compute_crc16 (in, n); - if ((e->response[0] != ((crc16 >> 8) & 0xff)) || - (e->response[1] != (crc16 & 0xff))) { - RTEMS_SYSLOG_ERROR( "CRC check failed on read\n"); - return -RTEMS_IO_ERROR; - } - - return i; -} - -static int sd_card_write( sd_card_driver_entry *e, uint8_t start_token, uint8_t *out, int n) -{ - int rv = 0; - uint8_t crc16_bytes [2] = { 0, 0 }; - uint16_t crc16; - - /* Data output index */ - int o = 0; - - /* Wait until card is not busy */ - rv = sd_card_wait( e); - RTEMS_CHECK_RV( rv, "Wait"); - - /* Write data start token */ - rv = rtems_libi2c_write_bytes( e->bus, &start_token, 1); - RTEMS_CHECK_RV( rv, "Write data start token"); - - /* Write data */ - o = rtems_libi2c_write_bytes( e->bus, out, n); - RTEMS_CHECK_RV( o, "Write data"); - - /* Write CRC 16 */ - crc16 = sd_card_compute_crc16(out, n); - crc16_bytes[0] = (crc16>>8) & 0xff; - crc16_bytes[1] = (crc16) & 0xff; - rv = rtems_libi2c_write_bytes( e->bus, crc16_bytes, 2); - RTEMS_CHECK_RV( rv, "Write CRC 16"); - - /* Read data response */ - rv = sd_card_query( e, e->response, 2); - RTEMS_CHECK_RV( rv, "Read data response"); - if (SD_CARD_IS_DATA_REJECTED( e->response [0])) { - RTEMS_SYSLOG_ERROR( "Data rejected: 0x%02" PRIx8 "\n", e->response [0]); - return -RTEMS_IO_ERROR; - } - - /* Card is now busy */ - e->busy = true; - - return o; -} - -static inline rtems_status_code sd_card_start( sd_card_driver_entry *e) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - int rv = 0; - - sc = rtems_libi2c_send_start( e->bus); - RTEMS_CHECK_SC( sc, "Send start"); - - rv = rtems_libi2c_ioctl( e->bus, RTEMS_LIBI2C_IOCTL_SET_TFRMODE, &e->transfer_mode); - RTEMS_CHECK_RV_SC( rv, "Set transfer mode"); - - sc = rtems_libi2c_send_addr( e->bus, 1); - RTEMS_CHECK_SC( sc, "Send address"); - - return RTEMS_SUCCESSFUL; -} - -static inline rtems_status_code sd_card_stop( sd_card_driver_entry *e) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - - sc = rtems_libi2c_send_stop( e->bus); - RTEMS_CHECK_SC( sc, "Send stop"); - - return RTEMS_SUCCESSFUL; -} - -static rtems_status_code sd_card_init( sd_card_driver_entry *e) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - int rv = 0; - uint8_t block [SD_CARD_BLOCK_SIZE_DEFAULT]; - uint32_t transfer_speed = 0; - uint32_t read_block_size = 0; - uint32_t write_block_size = 0; - uint8_t csd_structure = 0; - uint64_t capacity = 0; - uint8_t crc7; - - /* Assume first that we have a SD card and not a MMC card */ - bool assume_sd = true; - - /* - * Assume high capacity until proven wrong (applies to SD and not yet - * existing MMC). - */ - bool high_capacity = true; - - bool do_cmd58 = true; - uint32_t cmd_arg = 0; - uint32_t if_cond_test = SD_CARD_FLAG_VHS_2_7_TO_3_3 | SD_CARD_FLAG_CHECK_PATTERN; - uint32_t if_cond_reg = if_cond_test; - - /* Start */ - sc = sd_card_start( e); - RTEMS_CLEANUP_SC( sc, sd_card_driver_init_cleanup, "Start"); - - /* Wait until card is not busy */ - rv = sd_card_wait( e); - RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Wait"); - - /* Send idle tokens for at least 74 clock cycles with active chip select */ - memset( block, SD_CARD_IDLE_TOKEN, SD_CARD_BLOCK_SIZE_DEFAULT); - rv = rtems_libi2c_write_bytes( e->bus, block, SD_CARD_BLOCK_SIZE_DEFAULT); - RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Active chip select delay"); - - /* Stop */ - sc = sd_card_stop( e); - RTEMS_CHECK_SC( sc, "Stop"); - - /* Start with inactive chip select */ - sc = rtems_libi2c_send_start( e->bus); - RTEMS_CHECK_SC( sc, "Send start"); - - /* Set transfer mode */ - rv = rtems_libi2c_ioctl( e->bus, RTEMS_LIBI2C_IOCTL_SET_TFRMODE, &e->transfer_mode); - RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Set transfer mode"); - - /* Send idle tokens with inactive chip select */ - rv = sd_card_query( e, e->response, SD_CARD_COMMAND_SIZE); - RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Inactive chip select delay"); - - /* Activate chip select */ - sc = rtems_libi2c_send_addr( e->bus, 1); - RTEMS_CLEANUP_SC( sc, sd_card_driver_init_cleanup, "Send address"); - - /* Stop multiple block write */ - sd_card_stop_multiple_block_write( e); - - /* Get card status */ - sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0); - - /* Stop multiple block read */ - sd_card_stop_multiple_block_read( e); - - /* Switch to SPI mode */ - rv = sd_card_send_command( e, SD_CARD_CMD_GO_IDLE_STATE, 0); - RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_GO_IDLE_STATE"); - - /* - * Get interface condition, CMD8. This is new for SD 2.x and enables - * getting the High Capacity Support flag HCS and checks that the - * voltage is right. Some MMCs accept this command but will still fail - * on ACMD41. SD 1.x cards will fails this command and do not support - * HCS (> 2G capacity). - */ - rv = sd_card_send_register_command( e, SD_CARD_CMD_SEND_IF_COND, if_cond_reg, &if_cond_reg); - - /* - * Regardless of whether CMD8 above passes or fails, send ACMD41. If - * card is MMC it will fail. But older SD < 2.0 (which fail CMD8) will - * always stay "idle" if cmd_arg is non-zero, so set to 0 above on - * fail. - */ - if (rv < 0) { - /* Failed CMD8, so SD 1.x or MMC */ - cmd_arg = 0; - } else { - cmd_arg = SD_CARD_FLAG_HCS; - } - - /* Enable CRC */ - sd_card_send_command( e, SD_CARD_CMD_CRC_ON_OFF, 1); - - /* Initialize card */ - while (true) { - if (assume_sd) { - /* This command (CMD55) supported by SD and (most?) MMCs */ - rv = sd_card_send_command( e, SD_CARD_CMD_APP_CMD, 0); - if (rv < 0) { - RTEMS_SYSLOG( "CMD55 failed. Assume MMC and try CMD1\n"); - assume_sd = false; - continue; - } - - /* - * This command (ACMD41) only supported by SD. Always - * fails if MMC. - */ - rv = sd_card_send_command( e, SD_CARD_ACMD_SD_SEND_OP_COND, cmd_arg); - if (rv < 0) { - /* - * This *will* fail for MMC. If fails, bad/no - * card or card is MMC, do CMD58 then CMD1. - */ - RTEMS_SYSLOG( "ACMD41 failed. Assume MMC and do CMD58 (once) then CMD1\n"); - assume_sd = false; - cmd_arg = SD_CARD_FLAG_HCS; - do_cmd58 = true; - continue; - } else { - /* - * Passed ACMD41 so SD. It is now save to - * check if_cond_reg from CMD8. Reject the - * card in case of a indicated bad voltage. - */ - if (if_cond_reg != if_cond_test) { - RTEMS_CLEANUP_RV_SC( -1, sc, sd_card_driver_init_cleanup, "Bad voltage for SD"); - } - } - } else { - /* - * Does not seem to be SD card. Do init for MMC. - * First send CMD58 once to enable check for HCS - * (similar to CMD8 of SD) with bits 30:29 set to 10b. - * This will work for MMC >= 4.2. Older cards (<= 4.1) - * may may not respond to CMD1 unless CMD58 is sent - * again with zero argument. - */ - if (do_cmd58) { - rv = sd_card_send_command( e, SD_CARD_CMD_READ_OCR, cmd_arg); - RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Failed CMD58 for MMC"); - - /* A one-shot call */ - do_cmd58 = false; - } - - /* Do CMD1 */ - rv = sd_card_send_command( e, SD_CARD_CMD_SEND_OP_COND, 0); - if (rv < 0) { - if (cmd_arg != 0) { - /* - * Send CMD58 again with zero argument - * value. Proves card is not - * high_capacity. - */ - cmd_arg = 0; - do_cmd58 = true; - high_capacity = false; - continue; - } - - RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Failed to initialize MMC"); - } - } - - /* - * Not idle? - * - * This hangs forever if the card remains not idle and sends - * always a valid response. - */ - if (SD_CARD_IS_NOT_IDLE_RESPONSE( e->response [e->response_index])) { - break; - } - - /* Invoke the scheduler */ - rtems_task_wake_after( RTEMS_YIELD_PROCESSOR); - } - - /* Now we know if we are SD or MMC */ - if (assume_sd) { - if (cmd_arg == 0) { - /* SD is < 2.0 so never high capacity (<= 2G) */ - high_capacity = 0; - } else { - uint32_t reg = 0; - - /* - * SD is definitely 2.x. Now need to send CMD58 to get - * the OCR to see if the HCS bit is set (capacity > 2G) - * or if bit is off (capacity <= 2G, standard - * capacity). - */ - rv = sd_card_send_register_command( e, SD_CARD_CMD_READ_OCR, 0, ®); - RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Failed CMD58 for SD 2.x"); - - /* Check HCS bit of OCR */ - high_capacity = (reg & SD_CARD_FLAG_HCS) != 0; - } - } else { - /* - * Card is MMC. Unless already proven to be not HCS (< 4.2) - * must do CMD58 again to check the OCR bits 30:29. - */ - if (high_capacity) { - uint32_t reg = 0; - - /* - * The argument should still be correct since was never - * set to 0 - */ - rv = sd_card_send_register_command( e, SD_CARD_CMD_READ_OCR, cmd_arg, ®); - RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Failed CMD58 for MMC 4.2"); - - /* Check HCS bit of the OCR */ - high_capacity = (reg & SD_CARD_FLAG_HCS) != 0; - } - } - - /* Card Identification */ - if (e->verbose) { - rv = sd_card_send_command( e, SD_CARD_CMD_SEND_CID, 0); - RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_SEND_CID"); - rv = sd_card_read( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_READ, block, SD_CARD_CID_SIZE); - RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Read: SD_CARD_CMD_SEND_CID"); - RTEMS_SYSLOG( "*** Card Identification ***\n"); - RTEMS_SYSLOG( "Manufacturer ID : %" PRIu8 "\n", SD_CARD_CID_GET_MID( block)); - RTEMS_SYSLOG( "OEM/Application ID : %" PRIu16 "\n", SD_CARD_CID_GET_OID( block)); - RTEMS_SYSLOG( - "Product name : %c%c%c%c%c%c\n", - SD_CARD_CID_GET_PNM( block, 0), - SD_CARD_CID_GET_PNM( block, 1), - SD_CARD_CID_GET_PNM( block, 2), - SD_CARD_CID_GET_PNM( block, 3), - SD_CARD_CID_GET_PNM( block, 4), - SD_CARD_CID_GET_PNM( block, 5) - ); - RTEMS_SYSLOG( "Product revision : %" PRIu8 "\n", SD_CARD_CID_GET_PRV( block)); - RTEMS_SYSLOG( "Product serial number : %" PRIu32 "\n", SD_CARD_CID_GET_PSN( block)); - RTEMS_SYSLOG( "Manufacturing date : %" PRIu8 "\n", SD_CARD_CID_GET_MDT( block)); - RTEMS_SYSLOG( "7-bit CRC checksum : %" PRIu8 "\n", SD_CARD_CID_GET_CRC7( block)); - crc7 = sd_card_compute_crc7( block, 15); - if (crc7 != SD_CARD_CID_GET_CRC7( block)) - RTEMS_SYSLOG( " Failed! (computed %02" PRIx8 ")\n", crc7); - } - - /* Card Specific Data */ - - /* Read CSD */ - rv = sd_card_send_command( e, SD_CARD_CMD_SEND_CSD, 0); - RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_SEND_CSD"); - rv = sd_card_read( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_READ, block, SD_CARD_CSD_SIZE); - RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Read: SD_CARD_CMD_SEND_CSD"); - - crc7 = sd_card_compute_crc7( block, 15); - if (crc7 != SD_CARD_CID_GET_CRC7( block)) { - RTEMS_SYSLOG( "SD_CARD_CMD_SEND_CSD CRC failed\n"); - sc = RTEMS_IO_ERROR; - goto sd_card_driver_init_cleanup; - } - - /* CSD Structure */ - csd_structure = SD_CARD_CSD_GET_CSD_STRUCTURE( block); - - /* Transfer speed and access time */ - transfer_speed = sd_card_transfer_speed( block); - e->transfer_mode.baudrate = transfer_speed; - e->n_ac_max = sd_card_max_access_time( block, transfer_speed); - - /* Block sizes and capacity */ - if (csd_structure == 0 || !assume_sd) { - /* Treat MMC same as CSD Version 1.0 */ - - read_block_size = 1U << SD_CARD_CSD_GET_READ_BLK_LEN( block); - e->block_size_shift = SD_CARD_CSD_GET_WRITE_BLK_LEN( block); - write_block_size = 1U << e->block_size_shift; - if (read_block_size < write_block_size) { - RTEMS_SYSLOG_ERROR( "Read block size smaller than write block size\n"); - return -RTEMS_IO_ERROR; - } - e->block_size = write_block_size; - e->block_number = sd_card_block_number( block); - capacity = sd_card_capacity( block); - } else if (csd_structure == 1) { - uint32_t c_size = SD_CARD_CSD_1_GET_C_SIZE( block); - - /* Block size is fixed in CSD Version 2.0 */ - e->block_size_shift = 9; - e->block_size = 512; - - e->block_number = (c_size + 1) * 1024; - capacity = (c_size + 1) * 512 * 1024; - read_block_size = 512; - write_block_size = 512; - - /* Timeout is fixed at 100ms in CSD Version 2.0 */ - e->n_ac_max = transfer_speed / 80; - } else { - RTEMS_DO_CLEANUP_SC( RTEMS_IO_ERROR, sc, sd_card_driver_init_cleanup, "Unexpected CSD Structure number"); - } - - /* Print CSD information */ - if (e->verbose) { - RTEMS_SYSLOG( "*** Card Specific Data ***\n"); - RTEMS_SYSLOG( "CSD structure : %" PRIu8 "\n", SD_CARD_CSD_GET_CSD_STRUCTURE( block)); - RTEMS_SYSLOG( "Spec version : %" PRIu8 "\n", SD_CARD_CSD_GET_SPEC_VERS( block)); - RTEMS_SYSLOG( "Access time [ns] : %" PRIu32 "\n", sd_card_access_time( block)); - RTEMS_SYSLOG( "Access time [N] : %" PRIu32 "\n", SD_CARD_CSD_GET_NSAC( block)*100); - RTEMS_SYSLOG( "Max access time [N] : %" PRIu32 "\n", e->n_ac_max); - RTEMS_SYSLOG( "Max read block size [B] : %" PRIu32 "\n", read_block_size); - RTEMS_SYSLOG( "Max write block size [B] : %" PRIu32 "\n", write_block_size); - RTEMS_SYSLOG( "Block size [B] : %" PRIu32 "\n", e->block_size); - RTEMS_SYSLOG( "Block number : %" PRIu32 "\n", e->block_number); - RTEMS_SYSLOG( "Capacity [B] : %" PRIu64 "\n", capacity); - RTEMS_SYSLOG( "Max transfer speed [b/s] : %" PRIu32 "\n", transfer_speed); - } - - if (high_capacity) { - /* For high capacity cards the address is in blocks */ - e->block_size_shift = 0; - } else if (e->block_size_shift == 10) { - /* - * Low capacity 2GByte cards with reported block size of 1024 - * need to be set back to block size of 512 per 'Simplified - * Physical Layer Specification Version 2.0' section 4.3.2. - * Otherwise, CMD16 fails if set to 1024. - */ - e->block_size_shift = 9; - e->block_size = 512; - e->block_number *= 2; - } - - /* Set read block size */ - rv = sd_card_send_command( e, SD_CARD_CMD_SET_BLOCKLEN, e->block_size); - RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_SET_BLOCKLEN"); - - /* Stop */ - sc = sd_card_stop( e); - RTEMS_CHECK_SC( sc, "Stop"); - - return RTEMS_SUCCESSFUL; - -sd_card_driver_init_cleanup: - - /* Stop */ - sd_card_stop( e); - - return sc; -} -/** @} */ - -/** - * @name Disk Driver Functions - * @{ - */ - -static int sd_card_disk_block_read( sd_card_driver_entry *e, rtems_blkdev_request *r) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - int rv = 0; - uint32_t start_address = RTEMS_BLKDEV_START_BLOCK (r) << e->block_size_shift; - uint32_t i = 0; - -#ifdef DEBUG - /* Check request */ - if (r->bufs[0].block >= e->block_number) { - RTEMS_SYSLOG_ERROR( "Start block number out of range"); - return -RTEMS_INTERNAL_ERROR; - } else if (r->bufnum > e->block_number - RTEMS_BLKDEV_START_BLOCK (r)) { - RTEMS_SYSLOG_ERROR( "Block count out of range"); - return -RTEMS_INTERNAL_ERROR; - } -#endif /* DEBUG */ - - /* Start */ - sc = sd_card_start( e); - RTEMS_CLEANUP_SC_RV( sc, rv, sd_card_disk_block_read_cleanup, "Start"); - - if (r->bufnum == 1) { -#ifdef DEBUG - /* Check buffer */ - if (r->bufs [0].length != e->block_size) { - RTEMS_DO_CLEANUP_RV( -RTEMS_INTERNAL_ERROR, rv, sd_card_disk_block_read_cleanup, "Buffer and disk block size are not equal"); - } - RTEMS_DEBUG_PRINT( "[01:01]: buffer = 0x%08x, size = %u\n", r->bufs [0].buffer, r->bufs [0].length); -#endif /* DEBUG */ - - /* Single block read */ - rv = sd_card_send_command( e, SD_CARD_CMD_READ_SINGLE_BLOCK, start_address); - RTEMS_CLEANUP_RV( rv, sd_card_disk_block_read_cleanup, "Send: SD_CARD_CMD_READ_SINGLE_BLOCK"); - rv = sd_card_read( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_READ, (uint8_t *) r->bufs [0].buffer, (int) e->block_size); - RTEMS_CLEANUP_RV( rv, sd_card_disk_block_read_cleanup, "Read: SD_CARD_CMD_READ_SINGLE_BLOCK"); - } else { - /* Start multiple block read */ - rv = sd_card_send_command( e, SD_CARD_CMD_READ_MULTIPLE_BLOCK, start_address); - RTEMS_CLEANUP_RV( rv, sd_card_disk_block_read_stop_cleanup, "Send: SD_CARD_CMD_READ_MULTIPLE_BLOCK"); - - /* Multiple block read */ - for (i = 0; i < r->bufnum; ++i) { -#ifdef DEBUG - /* Check buffer */ - if (r->bufs [i].length != e->block_size) { - RTEMS_DO_CLEANUP_RV( -RTEMS_INTERNAL_ERROR, rv, sd_card_disk_block_read_stop_cleanup, "Buffer and disk block size are not equal"); - } - RTEMS_DEBUG_PRINT( "[%02u:%02u]: buffer = 0x%08x, size = %u\n", i + 1, r->bufnum, r->bufs [i].buffer, r->bufs [i].length); -#endif /* DEBUG */ - - rv = sd_card_read( e, SD_CARD_START_BLOCK_MULTIPLE_BLOCK_READ, (uint8_t *) r->bufs [i].buffer, (int) e->block_size); - RTEMS_CLEANUP_RV( rv, sd_card_disk_block_read_stop_cleanup, "Read block"); - } - - /* Stop multiple block read */ - rv = sd_card_stop_multiple_block_read( e); - RTEMS_CLEANUP_RV( rv, sd_card_disk_block_read_cleanup, "Stop multiple block read"); - } - - /* Stop */ - sc = sd_card_stop( e); - RTEMS_CHECK_SC_RV( sc, "Stop"); - - /* Done */ - rtems_blkdev_request_done( r, RTEMS_SUCCESSFUL); - - return 0; - -sd_card_disk_block_read_stop_cleanup: - - /* Stop multiple block read */ - sd_card_stop_multiple_block_read( e); - -sd_card_disk_block_read_cleanup: - - /* Stop */ - sd_card_stop( e); - - /* Done */ - rtems_blkdev_request_done( r, RTEMS_IO_ERROR); - - return 0; -} - -static int sd_card_disk_block_write( sd_card_driver_entry *e, rtems_blkdev_request *r) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - int rv = 0; - uint32_t start_address = RTEMS_BLKDEV_START_BLOCK (r) << e->block_size_shift; - uint32_t i = 0; - -#ifdef DEBUG - /* Check request */ - if (r->bufs[0].block >= e->block_number) { - RTEMS_SYSLOG_ERROR( "Start block number out of range"); - return -RTEMS_INTERNAL_ERROR; - } else if (r->bufnum > e->block_number - RTEMS_BLKDEV_START_BLOCK (r)) { - RTEMS_SYSLOG_ERROR( "Block count out of range"); - return -RTEMS_INTERNAL_ERROR; - } -#endif /* DEBUG */ - - /* Start */ - sc = sd_card_start( e); - RTEMS_CLEANUP_SC_RV( sc, rv, sd_card_disk_block_write_cleanup, "Start"); - - if (r->bufnum == 1) { -#ifdef DEBUG - /* Check buffer */ - if (r->bufs [0].length != e->block_size) { - RTEMS_DO_CLEANUP_RV( -RTEMS_INTERNAL_ERROR, rv, sd_card_disk_block_write_cleanup, "Buffer and disk block size are not equal"); - } - RTEMS_DEBUG_PRINT( "[01:01]: buffer = 0x%08x, size = %u\n", r->bufs [0].buffer, r->bufs [0].length); -#endif /* DEBUG */ - - /* Single block write */ - rv = sd_card_send_command( e, SD_CARD_CMD_WRITE_BLOCK, start_address); - RTEMS_CLEANUP_RV( rv, sd_card_disk_block_write_cleanup, "Send: SD_CARD_CMD_WRITE_BLOCK"); - rv = sd_card_write( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_WRITE, (uint8_t *) r->bufs [0].buffer, (int) e->block_size); - RTEMS_CLEANUP_RV( rv, sd_card_disk_block_write_cleanup, "Write: SD_CARD_CMD_WRITE_BLOCK"); - } else { - /* Start multiple block write */ - rv = sd_card_send_command( e, SD_CARD_CMD_WRITE_MULTIPLE_BLOCK, start_address); - RTEMS_CLEANUP_RV( rv, sd_card_disk_block_write_stop_cleanup, "Send: SD_CARD_CMD_WRITE_MULTIPLE_BLOCK"); - - /* Multiple block write */ - for (i = 0; i < r->bufnum; ++i) { -#ifdef DEBUG - /* Check buffer */ - if (r->bufs [i].length != e->block_size) { - RTEMS_DO_CLEANUP_RV( -RTEMS_INTERNAL_ERROR, rv, sd_card_disk_block_write_stop_cleanup, "Buffer and disk block size are not equal"); - } - RTEMS_DEBUG_PRINT( "[%02u:%02u]: buffer = 0x%08x, size = %u\n", i + 1, r->bufnum, r->bufs [i].buffer, r->bufs [i].length); -#endif /* DEBUG */ - - rv = sd_card_write( e, SD_CARD_START_BLOCK_MULTIPLE_BLOCK_WRITE, (uint8_t *) r->bufs [i].buffer, (int) e->block_size); - RTEMS_CLEANUP_RV( rv, sd_card_disk_block_write_stop_cleanup, "Write block"); - } - - /* Stop multiple block write */ - rv = sd_card_stop_multiple_block_write( e); - RTEMS_CLEANUP_RV( rv, sd_card_disk_block_write_cleanup, "Stop multiple block write"); - } - - /* Get card status */ - rv = sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0); - RTEMS_CHECK_RV( rv, "Send: SD_CARD_CMD_SEND_STATUS"); - - /* Stop */ - sc = sd_card_stop( e); - RTEMS_CHECK_SC_RV( sc, "Stop"); - - /* Done */ - rtems_blkdev_request_done( r, RTEMS_SUCCESSFUL); - - return 0; - -sd_card_disk_block_write_stop_cleanup: - - /* Stop multiple block write */ - sd_card_stop_multiple_block_write( e); - -sd_card_disk_block_write_cleanup: - - /* Get card status */ - rv = sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0); - RTEMS_CHECK_RV( rv, "Send: SD_CARD_CMD_SEND_STATUS"); - - /* Stop */ - sd_card_stop( e); - - /* Done */ - rtems_blkdev_request_done( r, RTEMS_IO_ERROR); - - return 0; -} - -static int sd_card_disk_ioctl( rtems_disk_device *dd, uint32_t req, void *arg) -{ - RTEMS_DEBUG_PRINT( "sd_card_disk_ioctl minor = %u, req = 0x%08x, arg = %p\n", - (unsigned)rtems_filesystem_dev_minor_t(dd->dev), (unsigned)req, arg); - if (req == RTEMS_BLKIO_REQUEST) { - rtems_device_minor_number minor = rtems_disk_get_minor_number( dd); - sd_card_driver_entry *e = &sd_card_driver_table [minor]; - rtems_blkdev_request *r = (rtems_blkdev_request *) arg; - int (*f)( sd_card_driver_entry *, rtems_blkdev_request *); - uint32_t retries = e->retries; - int result; - - switch (r->req) { - case RTEMS_BLKDEV_REQ_READ: - f = sd_card_disk_block_read; - break; - case RTEMS_BLKDEV_REQ_WRITE: - f = sd_card_disk_block_write; - break; - default: - errno = EINVAL; - return -1; - } - do { - result = f( e, r); - } while (retries-- > 0 && result != 0); - return result; - - } else if (req == RTEMS_BLKIO_CAPABILITIES) { - *(uint32_t *) arg = RTEMS_BLKDEV_CAP_MULTISECTOR_CONT; - return 0; - } else { - return rtems_blkdev_ioctl( dd, req, arg ); - } -} - -static rtems_status_code sd_card_disk_init( rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - - /* Initialize disk IO */ - sc = rtems_disk_io_initialize(); - RTEMS_CHECK_SC( sc, "Initialize RTEMS disk IO"); - - for (minor = 0; minor < sd_card_driver_table_size; ++minor) { - sd_card_driver_entry *e = &sd_card_driver_table [minor]; - dev_t dev = rtems_filesystem_make_dev_t( major, minor); - uint32_t retries = e->retries; - - /* Initialize SD Card */ - do { - sc = sd_card_init( e); - } while (retries-- > 0 && sc != RTEMS_SUCCESSFUL); - RTEMS_CHECK_SC( sc, "Initialize SD Card"); - - /* Create disk device */ - sc = rtems_disk_create_phys( dev, e->block_size, e->block_number, sd_card_disk_ioctl, NULL, e->device_name); - RTEMS_CHECK_SC( sc, "Create disk device"); - } - - return RTEMS_SUCCESSFUL; -} - -/** @} */ - -static const rtems_driver_address_table sd_card_disk_ops = { - .initialization_entry = sd_card_disk_init, - .open_entry = rtems_blkdev_generic_open, - .close_entry = rtems_blkdev_generic_close, - .read_entry = rtems_blkdev_generic_read, - .write_entry = rtems_blkdev_generic_write, - .control_entry = rtems_blkdev_generic_ioctl -}; - -rtems_status_code sd_card_register( void) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - rtems_device_major_number major = 0; - - sc = rtems_io_register_driver( 0, &sd_card_disk_ops, &major); - RTEMS_CHECK_SC( sc, "Register disk SD Card driver"); - - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/libchip/ide/ata.c b/c/src/libchip/ide/ata.c deleted file mode 100644 index 7bb3f6ec73..0000000000 --- a/c/src/libchip/ide/ata.c +++ /dev/null @@ -1,1360 +0,0 @@ -/* - * ata.c - * - * ATA RTEMS driver. ATA driver is hardware independant implementation of - * ATA-2 standard, working draft X3T10/0948D, revision 4c. ATA driver bases - * on RTEMS IDE controller driver. - * - * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia - * Authors: Eugeny S. Mints - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - * - */ -#include -#include -#include -#include /* for "memset" declaration */ - -#include -#include -#include -#include -#include -#include - -#define ATA_DEBUG 0 - -#if ATA_DEBUG -#include -bool ata_trace; -#define ata_printf if (ata_trace) printf -#endif - -#if CPU_SIMPLE_VECTORED_INTERRUPTS != TRUE -#include -#define ATA_IRQ_CHAIN_MAX_CNT 4 /* support up to 4 ATA devices */ -typedef struct { - rtems_irq_number name; - rtems_chain_control irq_chain; -} ata_irq_chain_t; - -ata_irq_chain_t ata_irq_chain[ATA_IRQ_CHAIN_MAX_CNT]; -int ata_irq_chain_cnt = 0; -#endif - -static rtems_id ata_lock; -static void -rtems_ata_lock (void) -{ - rtems_status_code sc = rtems_semaphore_obtain (ata_lock, - RTEMS_WAIT, - RTEMS_NO_TIMEOUT); - if (sc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred (RTEMS_INTERNAL_ERROR); -} - -static void -rtems_ata_unlock (void) -{ - rtems_status_code sc = rtems_semaphore_release (ata_lock); - if (sc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred (RTEMS_INTERNAL_ERROR); -} - -#define RTEMS_ATA_LOCK_ATTRIBS \ - (RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE | \ - RTEMS_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL) - -/* FIXME: case if ATA device is FLASH device need more attention */ -#undef ATA_DEV_IS_FLASH_DISK - -/* Array indexed by controllers minor number */ -static ata_ide_ctrl_t ata_ide_ctrls[IDE_CTRL_MAX_MINOR_NUMBER]; - -/* - * Mapping from ATA-minor numbers to - * controller-minor and device on this controller. - */ -static ata_ide_dev_t ata_devs[2 * IDE_CTRL_MAX_MINOR_NUMBER]; -static int ata_devs_number; - -/* Flag meaning that ATA driver has already been initialized */ -static bool ata_initialized = false; - - -/* task and queue used for asynchronous I/O operations */ -static rtems_id ata_task_id; -static rtems_id ata_queue_id; - -#if CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE -/* Mapping of interrupt vectors to devices */ -static rtems_chain_control ata_int_vec[ATA_MAX_RTEMS_INT_VEC_NUMBER + 1]; -#endif - -static void -ata_process_request(rtems_device_minor_number ctrl_minor); - -static void -ata_add_to_controller_queue(rtems_device_minor_number ctrl_minor, - ata_req_t *areq); - -/* - * read/write, open/close and ioctl are provided by general block device - * driver. Only initialization and ata-specific ioctl are here. - */ - -/* ata_io_data_request -- - * Form read/write request for an ATA device and enqueue it to - * IDE controller. - * - * PARAMETERS: - * device - device identifier - * req - read/write request from block device driver - * - * RETURNS: - * RTEMS_SUCCESSFUL on success, or error code if - * error occured - */ -static rtems_status_code -ata_io_data_request(dev_t device, rtems_blkdev_request *req) -{ - ata_req_t *areq; /* ATA request */ - rtems_device_minor_number rel_minor; /* relative minor which indexes - * ata_devs array - */ - rtems_device_minor_number ctrl_minor; - uint8_t dev; - - rel_minor = (rtems_filesystem_dev_minor_t(device)) / - ATA_MINOR_NUM_RESERVED_PER_ATA_DEVICE; - - /* get controller which serves the ATA device */ - ctrl_minor = ata_devs[rel_minor].ctrl_minor; - - /* get ATA device identifier (0 or 1) */ - dev = ata_devs[rel_minor].device; - - areq = malloc(sizeof(ata_req_t)); - if (areq == NULL) - { - rtems_blkdev_request_done(req, RTEMS_NO_MEMORY); - return RTEMS_SUCCESSFUL; - } - - areq->breq = req; - areq->cnt = req->bufnum; - areq->cbuf = 0; - areq->pos = 0; - - /* set up registers masks */ - areq->regs.to_write = ATA_REGISTERS_POSITION; - areq->regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_STATUS); - - /* choose device on the controller for which the command will be issued */ - areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] = - (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS); - - /* Find ATA command and its type */ - if (ATA_DEV_INFO(ctrl_minor, dev).mode_active & ATA_MODES_DMA) - { - /* XXX: never has been tested */ - areq->type = ATA_COMMAND_TYPE_DMA; - if (req->req == RTEMS_BLKDEV_REQ_READ) - areq->regs.regs[IDE_REGISTER_COMMAND] = ATA_COMMAND_READ_DMA; - else - areq->regs.regs[IDE_REGISTER_COMMAND] = ATA_COMMAND_WRITE_DMA; - } - else - { - if (req->req == RTEMS_BLKDEV_REQ_READ) - { - areq->type = ATA_COMMAND_TYPE_PIO_IN; - areq->regs.regs[IDE_REGISTER_COMMAND] = ATA_COMMAND_READ_SECTORS; -#if ATA_DEBUG - ata_printf("ata_io_data_request: type: READ: %lu, %lu cmd:%02x\n", - req->bufs[0].block, req->bufnum, - areq->regs.regs[IDE_REGISTER_COMMAND]); -#endif - } - else - { - areq->type = ATA_COMMAND_TYPE_PIO_OUT; - areq->regs.regs[IDE_REGISTER_COMMAND] = ATA_COMMAND_WRITE_SECTORS; -#if ATA_DEBUG - ata_printf("ata_io_data_request: type: WRITE: %lu, %lu cmd:%02x\n", - req->bufs[0].block, req->bufnum, - areq->regs.regs[IDE_REGISTER_COMMAND]); -#endif - } - } - - /* - * Fill position registers - */ - if (ATA_DEV_INFO(ctrl_minor, dev).lba_avaible) - { - uint32_t start = req->bufs[0].block; - areq->regs.regs[IDE_REGISTER_LBA0] = (uint8_t)start; - areq->regs.regs[IDE_REGISTER_LBA1] = (uint8_t)(start >> 8); - areq->regs.regs[IDE_REGISTER_LBA2] = (uint8_t)(start >> 16); - /* Set as the head register write above */ - areq->regs.regs[IDE_REGISTER_LBA3] |= (uint8_t) (start >> 24); - areq->regs.regs[IDE_REGISTER_LBA3] |= IDE_REGISTER_LBA3_L; - } - else - { - uint32_t count = req->bufs[0].block; - - areq->regs.regs[IDE_REGISTER_SECTOR_NUMBER] = - (count % ATA_DEV_INFO(ctrl_minor, dev).sectors) + 1; - - /* now count = number of tracks: */ - count /= ATA_DEV_INFO(ctrl_minor, dev).sectors; - areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] |= - (count / ATA_DEV_INFO(ctrl_minor, dev).cylinders); - - /* now count = number of cylinders */ - count %= ATA_DEV_INFO(ctrl_minor, dev).cylinders; - areq->regs.regs[IDE_REGISTER_CYLINDER_LOW] = (uint8_t)count; - areq->regs.regs[IDE_REGISTER_CYLINDER_HIGH] = (uint8_t)(count >> 8); - areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] &= - ~IDE_REGISTER_DEVICE_HEAD_L; - } - - /* - * Fill sector count register. We have a number of buffers (bufnum) which - * can be of a specific length (bufs[0].length / ATA_SECTOR_SIZE). - */ - areq->regs.regs[IDE_REGISTER_SECTOR_COUNT] = - areq->breq->bufnum * (areq->breq->bufs[0].length / ATA_SECTOR_SIZE); - - /* add request to the queue of awaiting requests to the controller */ - ata_add_to_controller_queue(ctrl_minor, areq); - - return RTEMS_SUCCESSFUL; -} - -/* ata_non_data_request -- - * Form and serve request of NON DATA type for an ATA device. - * Processing of NON DATA request is SYNChronous operation. - * - * PARAMETERS: - * device - device identifier - * cmd - command - * argp - arguments for command - * - * RETURNS: - * RTEMS_SUCCESSFUL on success, or error code if - * error occured - */ -static rtems_status_code -ata_non_data_request(dev_t device, uint32_t cmd, void *argp) -{ - rtems_status_code rc; - ata_req_t *areq; /* ATA request */ - rtems_device_minor_number rel_minor; /* relative minor which indexes - * ata_devs array - */ - rtems_device_minor_number ctrl_minor; - uint8_t dev; - ata_queue_msg_t msg; - - rel_minor = (rtems_filesystem_dev_minor_t(device)) / - ATA_MINOR_NUM_RESERVED_PER_ATA_DEVICE; - - /* get controller which serves the ATA device */ - ctrl_minor = ata_devs[rel_minor].ctrl_minor; - - /* get ATA device identifier (0 or 1) */ - dev = ata_devs[rel_minor].device; - - /* form the request */ - areq = malloc(sizeof(ata_req_t)); - if (areq == NULL) - { - return RTEMS_NO_MEMORY; - } - memset(areq, 0, sizeof(ata_req_t)); - - areq->type = ATA_COMMAND_TYPE_NON_DATA; - areq->regs.to_write = ATA_REGISTERS_VALUE(IDE_REGISTER_COMMAND); - areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] |= - (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS); - areq->breq = NULL; - areq->regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_ERROR); - - /* - * depending on command fill command register and additional registers - * which are needed for command execution - */ - switch(cmd) - { - case ATAIO_SET_MULTIPLE_MODE: - areq->regs.regs[IDE_REGISTER_COMMAND] = - ATA_COMMAND_SET_MULTIPLE_MODE; - areq->regs.to_write |= - ATA_REGISTERS_VALUE(IDE_REGISTER_SECTOR_COUNT); - areq->regs.regs[IDE_REGISTER_SECTOR_COUNT] = *(uint8_t*)argp; - break; - - default: - free(areq); - return RTEMS_INVALID_NUMBER; - break; - } - - rc = rtems_semaphore_create(rtems_build_name('I', 'D', 'E', 'S'), - 0, - RTEMS_FIFO | RTEMS_COUNTING_SEMAPHORE | - RTEMS_NO_INHERIT_PRIORITY | - RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL, - 0, - &(areq->sema)); - if (rc != RTEMS_SUCCESSFUL) - { - free(areq); - return rc; - } - - ata_add_to_controller_queue(ctrl_minor, areq); - - /* wait for request processing... */ - rc = rtems_semaphore_obtain(areq->sema, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - if (rc != RTEMS_SUCCESSFUL) - { - free(areq); - return rc; - } - - rtems_semaphore_delete(areq->sema); - - /* - * if no error occurred and if necessary, update internal ata driver data - * structures to reflect changes (in device configuration, for example) - */ - if (areq->status == RTEMS_SUCCESSFUL) - { - switch(cmd) - { - case ATAIO_SET_MULTIPLE_MODE: - /* invalid operation now */ - default: - rc = RTEMS_INVALID_NUMBER; - break; - } - } - else - { - /* XXX: should be correct error processing: for ex, may be - * ABRT and then we should return RTEMS_NOT_IMPLEMENTED - */ - rc = RTEMS_IO_ERROR; - } - - /* tell ata driver that controller ready to serve next request */ - ATA_SEND_EVT(msg, ATA_MSG_SUCCESS_EVT, ctrl_minor, 0); - - return rc; -} - -/* ata_process_request -- - * Get first request from controller's queue and process it. - * - * PARAMETERS: - * ctrl_minor - controller identifier - * - * RETURNS: - * NONE - */ -static void -ata_process_request(rtems_device_minor_number ctrl_minor) -{ - ata_req_t *areq; - uint16_t byte; /* emphasize that only 8 low bits is meaningful */ - ata_queue_msg_t msg; - uint8_t i; -#if 0 - uint8_t dev; -#endif - uint16_t val; - ISR_Level level; - - /* if no requests to controller then do nothing */ - if (rtems_chain_is_empty(&ata_ide_ctrls[ctrl_minor].reqs)) - return; - - /* get first request in the controller's queue */ - _ISR_Local_disable(level); - areq = (ata_req_t *)rtems_chain_first(&ata_ide_ctrls[ctrl_minor].reqs); - _ISR_Local_enable(level); - -#if 0 - /* get ATA device identifier (0 or 1) */ - dev = areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] & - IDE_REGISTER_DEVICE_HEAD_DEV; -#endif - - /* execute device select protocol */ - ide_controller_write_register(ctrl_minor, IDE_REGISTER_DEVICE_HEAD, - areq->regs.regs[IDE_REGISTER_DEVICE_HEAD]); - - do { - ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &byte); - } while ((byte & IDE_REGISTER_STATUS_BSY) || - (!(byte & IDE_REGISTER_STATUS_DRDY))); - - /* fill in all necessary registers on the controller */ - for (i=0; i< ATA_MAX_CMD_REG_OFFSET; i++) - { - uint32_t reg = (1 << i); - if (areq->regs.to_write & reg) - ide_controller_write_register(ctrl_minor, i, areq->regs.regs[i]); - } - -#if ATA_DEBUG - ata_printf("ata_process_request: type: %d\n", areq->type); -#endif - - /* continue to execute ATA protocols depending on type of request */ - if (areq->type == ATA_COMMAND_TYPE_PIO_OUT) - { - do { - ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, - &byte); - } while (byte & IDE_REGISTER_STATUS_BSY); - - if (byte & IDE_REGISTER_STATUS_DRQ) - { - if (areq->cnt) - { - int ccbuf = areq->cbuf; - ide_controller_write_data_block(ctrl_minor, - areq->breq->bufs[0].length * areq->cnt, - areq->breq->bufs, &areq->cbuf, - &areq->pos); - ccbuf = areq->cbuf - ccbuf; - areq->cnt -= ccbuf; - } - } - else - { - if (IDE_Controller_Table[ctrl_minor].int_driven == false) - { - ide_controller_read_register( - ctrl_minor, - IDE_REGISTER_ALTERNATE_STATUS_OFFSET, - &val); - ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, - &val); - - ATA_SEND_EVT(msg, ATA_MSG_ERROR_EVT, ctrl_minor, - RTEMS_IO_ERROR); - } - } - } - - if (IDE_Controller_Table[ctrl_minor].int_driven == false) - { - do { - ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, - &byte); - } while (byte & IDE_REGISTER_STATUS_BSY); - - ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, ctrl_minor, 0); - } -} - -/* ata_request_done -- - * Extract request from controller queue, execute callback if necessary - * and process next request for the controller. - * - * PARAMETERS: - * areq - ATA request - * ctrl_minor - controller identifier - * status - status with which request has been done - * error - error, if status != RTEMS_SUCCESSFUL - * - * RETURNS: - * NONE - */ -static inline void -ata_request_done(ata_req_t *areq, rtems_device_minor_number ctrl_minor, - rtems_status_code status) -{ - assert(areq); - -#if ATA_DEBUG - ata_printf("ata_request_done: entry\n"); -#endif - - ATA_EXEC_CALLBACK(areq, status); - rtems_chain_extract(&areq->link); - - if (!rtems_chain_is_empty(&ata_ide_ctrls[ctrl_minor].reqs)) - { - free(areq); - ata_process_request(ctrl_minor); - return; - } - - free(areq); - -#if ATA_DEBUG - ata_printf("ata_request_done: exit\n"); -#endif -} - -/* ata_non_data_request_done -- - * Set up request status and release request's semaphore. - * - * PARAMETERS: - * areq - ATA request - * ctrl_minor - controller identifier - * status - status with which request has been done - * error - error, if status != RTEMS_SUCCESSFUL - * - * RETURNS: - * NONE - */ -static inline void -ata_non_data_request_done(ata_req_t *areq, - rtems_device_minor_number ctrl_minor, - rtems_status_code status, int info) -{ -#if ATA_DEBUG - ata_printf("ata_non_data_request_done: entry\n"); -#endif - - areq->status = status; - areq->info = info; - rtems_semaphore_release(areq->sema); -} - - -/* ata_add_to_controller_queue -- - * Add request to the controller's queue. - * - * PARAMETERS: - * ctrl_minor - controller identifier - * areq - ATA request - * - * RETURNS: - * NONE - */ -static void -ata_add_to_controller_queue(rtems_device_minor_number ctrl_minor, - ata_req_t *areq) -{ - rtems_ata_lock(); - - rtems_chain_append(&ata_ide_ctrls[ctrl_minor].reqs, &areq->link); - if (rtems_chain_has_only_one_node(&ata_ide_ctrls[ctrl_minor].reqs)) - { - - ata_queue_msg_t msg; - -#if ATA_DEBUG_DOES_NOT_WORK_WITH_QEMU - uint16_t val; - /* - * read IDE_REGISTER_ALTERNATE_STATUS instead IDE_REGISTER_STATUS - * to prevent clearing of pending interrupt - */ - ide_controller_read_register(ctrl_minor, - IDE_REGISTER_ALTERNATE_STATUS, - &val); - if (val & IDE_REGISTER_STATUS_BSY) - return; -#endif - ATA_SEND_EVT(msg, ATA_MSG_PROCESS_NEXT_EVT, ctrl_minor, 0); - } - - rtems_ata_unlock(); -} - - -/* ata_interrupt_handler -- - * ATA driver interrrupt handler. If interrrupt happend it mapped it to - * controller (controllerS, if a number of controllers share one int line) - * and generates ATA event(s). - * - * PARAMETERS: - * vec - interrupt vector - * - * RETURNS: - * NONE - */ -#if CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE -static rtems_isr ata_interrupt_handler(rtems_vector_number vec) -{ - rtems_chain_node *the_node = rtems_chain_first(&ata_int_vec[vec]); - ata_queue_msg_t msg; - uint16_t byte; /* emphasize that only 8 low bits is meaningful */ - - for ( ; !rtems_chain_is_tail(&ata_int_vec[vec], the_node) ; ) - { - /* if (1) - is temporary hack - currently I don't know how to identify - * controller which asserted interrupt if few controllers share one - * interrupt line - */ - if (1) - { - msg.ctrl_minor = ((ata_int_st_t *)the_node)->ctrl_minor; - ide_controller_read_register(msg.ctrl_minor, IDE_REGISTER_STATUS, - &byte); - ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, msg.ctrl_minor, 0); - } - the_node = the_node->next; - } -} -#else -static void ata_interrupt_handler(rtems_irq_hdl_param handle) -{ - uintptr_t ata_irq_chain_index = (uintptr_t) handle; - rtems_chain_node *the_node = - rtems_chain_last(&ata_irq_chain[ata_irq_chain_index].irq_chain); - ata_queue_msg_t msg; - uint16_t byte; /* emphasize that only 8 low bits is meaningful */ - - - for ( ; !rtems_chain_is_tail(&ata_irq_chain[ata_irq_chain_index].irq_chain, - the_node) ; ) - { - /* if (1) - is temporary hack - currently I don't know how to identify - * controller which asserted interrupt if few controllers share one - * interrupt line - */ - if (1) - { - msg.ctrl_minor = ((ata_int_st_t *)the_node)->ctrl_minor; - ide_controller_read_register(msg.ctrl_minor, IDE_REGISTER_STATUS, - &byte); - ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, msg.ctrl_minor, 0); - } - the_node = the_node->next; - } -} - -static void ata_interrupt_on(const rtems_irq_connect_data *ptr) - { - - /* enable ATA device interrupt */ - ide_controller_write_register(0, - IDE_REGISTER_DEVICE_CONTROL_OFFSET, - 0x00 - ); - } - - -static void ata_interrupt_off(const rtems_irq_connect_data *ptr) - { - - /* disable ATA device interrupt */ - ide_controller_write_register(0, - IDE_REGISTER_DEVICE_CONTROL_OFFSET, - IDE_REGISTER_DEVICE_CONTROL_nIEN - ); - } - - -static int ata_interrupt_isOn(const rtems_irq_connect_data *ptr) - { - uint16_t byte; /* emphasize that only 8 low bits is meaningful */ - - /* return int. status od ATA device */ - ide_controller_read_register(0, - IDE_REGISTER_DEVICE_CONTROL_OFFSET, - &byte - ); - - return !(byte & IDE_REGISTER_DEVICE_CONTROL_nIEN); - } - - -static rtems_irq_connect_data ata_irq_data = - { - - 0, /* filled out before use... */ - ata_interrupt_handler,/* filled out before use... */ - NULL, - ata_interrupt_on, - ata_interrupt_off, - ata_interrupt_isOn - }; -#endif - -/* ata_pio_in_protocol -- - * ATA PIO_IN protocol implementation, see specification - * - * PARAMETERS: - * ctrl_minor - controller identifier - * areq - ATA request - * - * RETURNS: - * NONE - */ -static inline void -ata_pio_in_protocol(rtems_device_minor_number ctrl_minor, ata_req_t *areq) -{ - uint16_t val; -#if 0 - uint8_t dev; -#endif - ata_queue_msg_t msg; - -#if 0 - dev = areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] & - IDE_REGISTER_DEVICE_HEAD_DEV; -#endif - - if (areq->cnt) - { - int ccbuf = areq->cbuf; - ide_controller_read_data_block(ctrl_minor, - areq->breq->bufs[0].length * areq->cnt, - areq->breq->bufs, &areq->cbuf, &areq->pos); - ccbuf = areq->cbuf - ccbuf; - areq->cnt -= ccbuf; - } - - if (areq->cnt == 0) - { - ata_request_done(areq, ctrl_minor, RTEMS_SUCCESSFUL); - } - else if (IDE_Controller_Table[ctrl_minor].int_driven == false) - { - do { - ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &val); - } while (val & IDE_REGISTER_STATUS_BSY); - - ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, ctrl_minor, 0); - } -} - -/* ata_pio_out_protocol -- - * ATA PIO_OUT protocol implementation, see specification - * - * PARAMETERS: - * ctrl_minor - controller identifier - * areq - ATA request - * - * RETURNS: - * NONE - */ -static inline void -ata_pio_out_protocol(rtems_device_minor_number ctrl_minor, ata_req_t *areq) -{ - uint16_t val; -#if 0 - uint8_t dev; -#endif - ata_queue_msg_t msg; - -#if ATA_DEBUG - ata_printf("ata_pio_out_protocol:\n"); -#endif - -#if 0 - dev = areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] & - IDE_REGISTER_DEVICE_HEAD_DEV; -#endif - - if (areq->cnt == 0) - { - ata_request_done(areq, ctrl_minor, RTEMS_SUCCESSFUL); - } - else - { - if (areq->cnt) - { - int ccbuf = areq->cbuf; - ide_controller_write_data_block(ctrl_minor, - areq->breq->bufs[0].length * areq->cnt, - areq->breq->bufs, &areq->cbuf, - &areq->pos); - ccbuf = areq->cbuf - ccbuf; - areq->cnt -= ccbuf; - } - if (IDE_Controller_Table[ctrl_minor].int_driven == false) - { - do { - ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, - &val); - } while (val & IDE_REGISTER_STATUS_BSY); - - ATA_SEND_EVT(msg, ATA_MSG_GEN_EVT, ctrl_minor, 0); - } - } -} - -/* ata_queue_task -- - * Task which manages ATA driver events queue. - * - * PARAMETERS: - * arg - ignored - * - * RETURNS: - * NONE - * - * NOTES: - * should be non-preemptive - */ -static rtems_task -ata_queue_task(rtems_task_argument arg) -{ - ata_queue_msg_t msg; - size_t size; - ata_req_t *areq; - rtems_device_minor_number ctrl_minor; - uint16_t val; - uint16_t val1; - rtems_status_code rc; - ISR_Level level; - - rtems_ata_lock(); - - while (1) - { - rtems_ata_unlock(); - - /* get event which has happend */ - rc = rtems_message_queue_receive(ata_queue_id, &msg, &size, RTEMS_WAIT, - RTEMS_NO_TIMEOUT); - if (rc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR); - - /* get controller on which event has happend */ - ctrl_minor = msg.ctrl_minor; - - rtems_ata_lock(); - - /* get current request to the controller */ - _ISR_Local_disable(level); - areq = (ata_req_t *)rtems_chain_first(&ata_ide_ctrls[ctrl_minor].reqs); - _ISR_Local_enable(level); - - switch(msg.type) - { - case ATA_MSG_PROCESS_NEXT_EVT: - /* process next request in the controller queue */ - ata_process_request(ctrl_minor); - break; - - case ATA_MSG_SUCCESS_EVT: - /* - * finish processing of current request with successful - * status and start processing of the next request in the - * controller queue - */ - ata_request_done(areq, ctrl_minor, RTEMS_SUCCESSFUL); - break; - - case ATA_MSG_ERROR_EVT: - /* - * finish processing of current request with error - * status and start processing of the next request in the - * controller queue - */ - ata_request_done(areq, ctrl_minor, RTEMS_IO_ERROR); - break; - - case ATA_MSG_GEN_EVT: - /* - * continue processing of the current request to the - * controller according to current request state and - * ATA protocol - */ - ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, - &val); - /* process error case */ - if (val & IDE_REGISTER_STATUS_ERR) - { - ide_controller_read_register(ctrl_minor, - IDE_REGISTER_ERROR, - &val); - if (val & (IDE_REGISTER_ERROR_UNC | - IDE_REGISTER_ERROR_ICRC | - IDE_REGISTER_ERROR_IDNF | - IDE_REGISTER_ERROR_NM | - IDE_REGISTER_ERROR_MED)) - { - if (areq->type == ATA_COMMAND_TYPE_NON_DATA) - ata_non_data_request_done(areq, ctrl_minor, - RTEMS_UNSATISFIED, - RTEMS_IO_ERROR); - else - ata_request_done(areq, ctrl_minor, RTEMS_IO_ERROR); - break; - } - } - - switch(areq->type) - { - case ATA_COMMAND_TYPE_PIO_IN: - ata_pio_in_protocol(ctrl_minor, areq); - break; - - case ATA_COMMAND_TYPE_PIO_OUT: - ata_pio_out_protocol(ctrl_minor, areq); - break; - - case ATA_COMMAND_TYPE_NON_DATA: - ide_controller_read_register(ctrl_minor, - IDE_REGISTER_ERROR, - &val1); - ata_non_data_request_done(areq, ctrl_minor, - RTEMS_SUCCESSFUL, - val1); - break; - - default: -#if ATA_DEBUG - ata_printf("ata_queue_task: non-supported command type\n"); -#endif - ata_request_done(areq, ctrl_minor, RTEMS_IO_ERROR); - break; - } - break; - - default: -#if ATA_DEBUG - ata_printf("ata_queue_task: internal error\n"); - rtems_task_delete (RTEMS_SELF); -#endif - rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR); - break; - } - } -} - -/* ata_ioctl -- - * ATA driver ioctl interface. - * - * PARAMETERS: - * device - device identifier - * cmd - command - * argp - arguments - * - * RETURNS: - * depend on 'cmd' - */ -static int -ata_ioctl(rtems_disk_device *dd, uint32_t cmd, void *argp) -{ - dev_t device = rtems_disk_get_device_identifier(dd); - rtems_status_code status; - rtems_device_minor_number rel_minor; - - rel_minor = (rtems_filesystem_dev_minor_t(device)) / - ATA_MINOR_NUM_RESERVED_PER_ATA_DEVICE; - - /* - * in most cases this means that device 'device' is not an registred ATA - * device - */ - if (ata_devs[rel_minor].device == ATA_UNDEFINED_VALUE) - { - errno = ENODEV; - return -1; - } - - switch (cmd) - { - case RTEMS_BLKIO_REQUEST: - status = ata_io_data_request(device, (rtems_blkdev_request *)argp); - break; - - case ATAIO_SET_MULTIPLE_MODE: - status = ata_non_data_request(device, cmd, argp); - break; - - case RTEMS_BLKIO_CAPABILITIES: - *((uint32_t*) argp) = RTEMS_BLKDEV_CAP_MULTISECTOR_CONT; - status = RTEMS_SUCCESSFUL; - break; - - default: - return rtems_blkdev_ioctl (dd, cmd, argp); - break; - } - - if (status != RTEMS_SUCCESSFUL) - { - errno = EIO; - return -1; - } - return 0; -} - -static void ata_execute_device_diagnostic( - rtems_device_minor_number ctrl_minor, - uint16_t *sector_buffer -) -{ -#if ATA_EXEC_DEVICE_DIAGNOSTIC - ata_req_t areq; - blkdev_request1 breq; - - ata_breq_init(&breq, sector_buffer); - - /* - * Issue EXECUTE DEVICE DIAGNOSTIC ATA command for explore is - * there any ATA device on the controller. - * - * This command may fail and it assumes we have a master device and may - * be a slave device. I think the identify command will handle - * detection better than this method. - */ - memset(&areq, 0, sizeof(ata_req_t)); - areq.type = ATA_COMMAND_TYPE_NON_DATA; - areq.regs.to_write = ATA_REGISTERS_VALUE(IDE_REGISTER_COMMAND); - areq.regs.regs[IDE_REGISTER_COMMAND] = - ATA_COMMAND_EXECUTE_DEVICE_DIAGNOSTIC; - areq.regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_ERROR); - - areq.breq = (rtems_blkdev_request *)&breq; - - /* - * Process the request. Special processing of requests on - * initialization phase is needed because at this moment there - * is no multitasking enviroment - */ - ata_process_request_on_init_phase(ctrl_minor, &areq); - - /* - * check status of I/O operation - */ - if (breq.req.status == RTEMS_SUCCESSFUL) - { - /* disassemble returned diagnostic codes */ - if (areq.info == ATA_DEV0_PASSED_DEV1_PASSED_OR_NOT_PRSNT) - { - printk("ATA: ctrl:%d: primary, secondary\n", ctrl_minor); - ATA_DEV_INFO(ctrl_minor,0).present = true; - ATA_DEV_INFO(ctrl_minor,1).present = true; - } - else if (areq.info == ATA_DEV0_PASSED_DEV1_FAILED) - { - printk("ATA: ctrl:%d: primary\n", ctrl_minor); - ATA_DEV_INFO(ctrl_minor,0).present = true; - ATA_DEV_INFO(ctrl_minor,1).present = false; - } - else if (areq.info < ATA_DEV1_PASSED_DEV0_FAILED) - { - printk("ATA: ctrl:%d: secondary\n", ctrl_minor); - ATA_DEV_INFO(ctrl_minor,0).present = false; - ATA_DEV_INFO(ctrl_minor,1).present = true; - } - else - { - printk("ATA: ctrl:%d: none\n", ctrl_minor); - ATA_DEV_INFO(ctrl_minor, 0).present = false; - ATA_DEV_INFO(ctrl_minor, 1).present = false; - } - - /* refine the returned codes */ - if (ATA_DEV_INFO(ctrl_minor, 1).present) - { - uint16_t ec = 0; - ide_controller_read_register(ctrl_minor, IDE_REGISTER_ERROR, &ec); - if (ec & ATA_DEV1_PASSED_DEV0_FAILED) - { - printk("ATA: ctrl:%d: secondary inforced\n", ctrl_minor); - ATA_DEV_INFO(ctrl_minor, 1).present = true; - } - else - { - printk("ATA: ctrl:%d: secondary removed\n", ctrl_minor); - ATA_DEV_INFO(ctrl_minor, 1).present = false; - } - } - } - else -#endif - { - ATA_DEV_INFO(ctrl_minor, 0).present = true; - ATA_DEV_INFO(ctrl_minor,1).present = true; - } -} - -/* - * ata_initialize -- - * Initializes all ATA devices found on initialized IDE controllers. - * - * PARAMETERS: - * major - device major number - * minor - device minor number - * args - arguments - * - * RETURNS: - * RTEMS_SUCCESSFUL on success, or error code if - * error occured - */ -rtems_device_driver -rtems_ata_initialize(rtems_device_major_number major, - rtems_device_minor_number minor_arg, - void *args) -{ - uint32_t ctrl_minor; - rtems_status_code status; - uint16_t *buffer; - int i, dev = 0; - char name[ATA_MAX_NAME_LENGTH]; - dev_t device; - ata_int_st_t *int_st; - -#if CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE - rtems_isr_entry old_isr; -#else - int ata_irq_chain_use; -#endif - - if (ata_initialized) - return RTEMS_SUCCESSFUL; - - /* initialization of disk devices library */ - status = rtems_disk_io_initialize(); - if (status != RTEMS_SUCCESSFUL) - return status; - - status = rtems_semaphore_create (rtems_build_name ('A', 'T', 'A', 'L'), - 1, RTEMS_ATA_LOCK_ATTRIBS, 0, - &ata_lock); - if (status != RTEMS_SUCCESSFUL) - return status; - - /* create queue for asynchronous requests handling */ - status = rtems_message_queue_create( - rtems_build_name('A', 'T', 'A', 'Q'), - ATA_DRIVER_MESSAGE_QUEUE_SIZE, - sizeof(ata_queue_msg_t), - RTEMS_FIFO | RTEMS_LOCAL, - &ata_queue_id); - if (status != RTEMS_SUCCESSFUL) - { - rtems_disk_io_done(); - return status; - } - - /* - * create ATA driver task, see comments for task implementation for - * details - */ - status = rtems_task_create( - rtems_build_name ('A', 'T', 'A', 'T'), - ((rtems_ata_driver_task_priority > 0) - ? rtems_ata_driver_task_priority - : ATA_DRIVER_TASK_DEFAULT_PRIORITY), - ATA_DRIVER_TASK_STACK_SIZE, - RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR | - RTEMS_INTERRUPT_LEVEL(0), - RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL, - &ata_task_id); - if (status != RTEMS_SUCCESSFUL) - { - rtems_message_queue_delete(ata_queue_id); - rtems_disk_io_done(); - return status; - } - - /* - * start ATA driver task. Actually the task will not start immediately - - * it will start only after multitasking support will be started - */ - status = rtems_task_start(ata_task_id, ata_queue_task, 0); - if (status != RTEMS_SUCCESSFUL) - { - rtems_task_delete(ata_task_id); - rtems_message_queue_delete(ata_queue_id); - rtems_disk_io_done(); - return status; - } - - buffer = (uint16_t*)malloc(ATA_SECTOR_SIZE); - if (buffer == NULL) - { - rtems_task_delete(ata_task_id); - rtems_message_queue_delete(ata_queue_id); - rtems_disk_io_done(); - return RTEMS_NO_MEMORY; - } - - ata_devs_number = 0; - - for (i = 0; i < (2 * IDE_CTRL_MAX_MINOR_NUMBER); i++) - ata_devs[i].device = ATA_UNDEFINED_VALUE; - -#if CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE - /* prepare ATA driver for handling interrupt driven devices */ - for (i = 0; i < ATA_MAX_RTEMS_INT_VEC_NUMBER; i++) - rtems_chain_initialize_empty(&ata_int_vec[i]); -#else - for (i = 0; i < ATA_IRQ_CHAIN_MAX_CNT; i++) { - rtems_chain_initialize_empty(&(ata_irq_chain[i].irq_chain)); - } -#endif - - /* - * during ATA driver initialization EXECUTE DEVICE DIAGNOSTIC and - * IDENTIFY DEVICE ATA command should be issued; for these purposes ATA - * requests should be formed; ATA requests contain block device request, - * so form block device request first - */ - - /* - * for each presented IDE controller execute EXECUTE DEVICE DIAGNOSTIC - * ATA command; for each found device execute IDENTIFY DEVICE ATA - * command - */ - for (ctrl_minor = 0; ctrl_minor < IDE_Controller_Count; ctrl_minor++) - if (IDE_Controller_Table[ctrl_minor].status == IDE_CTRL_INITIALIZED) - { - rtems_chain_initialize_empty(&ata_ide_ctrls[ctrl_minor].reqs); - - if (IDE_Controller_Table[ctrl_minor].int_driven == true) - { - int_st = malloc(sizeof(ata_int_st_t)); - if (int_st == NULL) - { - free(buffer); - rtems_task_delete(ata_task_id); - rtems_message_queue_delete(ata_queue_id); - rtems_disk_io_done(); - return RTEMS_NO_MEMORY; - } - - int_st->ctrl_minor = ctrl_minor; -#if CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE - status = rtems_interrupt_catch( - ata_interrupt_handler, - IDE_Controller_Table[ctrl_minor].int_vec, - &old_isr); -#else - /* - * FIXME: check existing entries. if they use the same - * IRQ name, then append int_st to respective chain - * otherwise, use new ata_irq_chain entry - */ - ata_irq_chain_use = -1; - for (i = 0; - ((i < ata_irq_chain_cnt) && - (ata_irq_chain_use < 0));i++) { - if (ata_irq_chain[i].name == - IDE_Controller_Table[ctrl_minor].int_vec) { - ata_irq_chain_use = i; - } - } - if (ata_irq_chain_use < 0) { - /* - * no match found, try to use new channel entry - */ - if (ata_irq_chain_cnt < ATA_IRQ_CHAIN_MAX_CNT) { - ata_irq_chain_use = ata_irq_chain_cnt++; - - ata_irq_chain[ata_irq_chain_use].name = - IDE_Controller_Table[ctrl_minor].int_vec; - ata_irq_data.name = - IDE_Controller_Table[ctrl_minor].int_vec; - ata_irq_data.hdl = ata_interrupt_handler; - ata_irq_data.handle = (rtems_irq_hdl_param) (uintptr_t) ctrl_minor; - - status = ((0 == BSP_install_rtems_irq_handler(&ata_irq_data)) - ? RTEMS_INVALID_NUMBER - : RTEMS_SUCCESSFUL); - } - else { - status = RTEMS_TOO_MANY; - } - } -#endif - if (status != RTEMS_SUCCESSFUL) - { - free(int_st); - free(buffer); - rtems_task_delete(ata_task_id); - rtems_message_queue_delete(ata_queue_id); - rtems_disk_io_done(); - return status; - } -#if CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE - rtems_chain_append( - &ata_int_vec[IDE_Controller_Table[ctrl_minor].int_vec], - &int_st->link); -#else - rtems_chain_append( - &(ata_irq_chain[ata_irq_chain_use].irq_chain), - &int_st->link); -#endif - - /* disable interrupts */ - ide_controller_write_register(ctrl_minor, - IDE_REGISTER_DEVICE_CONTROL_OFFSET, - IDE_REGISTER_DEVICE_CONTROL_nIEN); - } - - ata_execute_device_diagnostic(ctrl_minor, buffer); - - /* for each found ATA device obtain it configuration */ - for (dev = 0; dev < 2; dev++) - if (ATA_DEV_INFO(ctrl_minor, dev).present) - { - status = ata_identify_device( - ctrl_minor, - dev, - buffer, - &ATA_DEV_INFO(ctrl_minor, dev)); - if (status != RTEMS_SUCCESSFUL) - continue; - - /* - * choose most appropriate ATA device data I/O speed supported - * by the controller - */ - status = ide_controller_config_io_speed( - ctrl_minor, - ATA_DEV_INFO(ctrl_minor, dev).modes_available); - if (status != RTEMS_SUCCESSFUL) - continue; - - /* - * Ok, let register new ATA device in the system - */ - ata_devs[ata_devs_number].ctrl_minor = ctrl_minor; - ata_devs[ata_devs_number].device = dev; - - /* The space leaves a hole for the character. */ - strcpy(name, "/dev/hd "); - name[7] = 'a' + 2 * ctrl_minor + dev; - - device = rtems_filesystem_make_dev_t( - major, - (ata_devs_number * - ATA_MINOR_NUM_RESERVED_PER_ATA_DEVICE)); - status = rtems_disk_create_phys(device, ATA_SECTOR_SIZE, - ATA_DEV_INFO(ctrl_minor, dev).lba_avaible ? - ATA_DEV_INFO(ctrl_minor, dev).lba_sectors : - (ATA_DEV_INFO(ctrl_minor, dev).heads * - ATA_DEV_INFO(ctrl_minor, dev).cylinders * - ATA_DEV_INFO(ctrl_minor, dev).sectors), - ata_ioctl, NULL, name); - if (status != RTEMS_SUCCESSFUL) - { - ata_devs[ata_devs_number].device = ATA_UNDEFINED_VALUE; - continue; - } - ata_devs_number++; - } - if (IDE_Controller_Table[ctrl_minor].int_driven == true) - { - ide_controller_write_register(ctrl_minor, - IDE_REGISTER_DEVICE_CONTROL_OFFSET, - 0x00); - } - } - - free(buffer); - ata_initialized = true; - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/libchip/ide/ata_util.c b/c/src/libchip/ide/ata_util.c deleted file mode 100644 index 68e0f0bbe5..0000000000 --- a/c/src/libchip/ide/ata_util.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (c) 2010 embedded brains GmbH. - * - * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia - * Authors: Eugeny S. Mints - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include - -#include -#include -#include - -/* ata_process_request_on_init_phase -- - * Process the ATA request during system initialization. Request - * processing is syncronous and doesn't use multiprocessing enviroment. - * - * PARAMETERS: - * ctrl_minor - controller identifier - * areq - ATA request - * - * RETURNS: - * NONE - */ -void -ata_process_request_on_init_phase(rtems_device_minor_number ctrl_minor, - ata_req_t *areq) -{ - uint16_t byte;/* emphasize that only 8 low bits is meaningful */ - uint8_t i; -#if 0 - uint8_t dev; -#endif - uint16_t val, val1; - volatile unsigned retries; - - assert(areq); - -#if 0 - dev = areq->regs.regs[IDE_REGISTER_DEVICE_HEAD] & - IDE_REGISTER_DEVICE_HEAD_DEV; -#endif - - ide_controller_write_register(ctrl_minor, IDE_REGISTER_DEVICE_HEAD, - areq->regs.regs[IDE_REGISTER_DEVICE_HEAD]); - - retries = 0; - do { - ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &byte); - /* If device (on INIT, i.e. it should be idle) is neither - * busy nor ready something's fishy, i.e., there is probably - * no device present. - * I'd like to do a proper timeout but don't know of a portable - * timeout routine (w/o using multitasking / rtems_task_wake_after()) - */ - if ( ! (byte & (IDE_REGISTER_STATUS_BSY | IDE_REGISTER_STATUS_DRDY))) { - retries++; - if ( 10000 == retries ) { - /* probably no drive connected */ - areq->breq->status = RTEMS_UNSATISFIED; - return; - } - } - } while ((byte & IDE_REGISTER_STATUS_BSY) || - (!(byte & IDE_REGISTER_STATUS_DRDY))); - - for (i=0; i< ATA_MAX_CMD_REG_OFFSET; i++) - { - uint32_t reg = (1 << i); - if (areq->regs.to_write & reg) - ide_controller_write_register(ctrl_minor, i, - areq->regs.regs[i]); - } - - do { - ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &byte); - } while (byte & IDE_REGISTER_STATUS_BSY); - - ide_controller_read_register(ctrl_minor, IDE_REGISTER_STATUS, &val); - ide_controller_read_register(ctrl_minor, IDE_REGISTER_ERROR, &val1); - - if (val & IDE_REGISTER_STATUS_ERR) - { - areq->breq->status = RTEMS_IO_ERROR; - return; - } - - switch(areq->type) - { - case ATA_COMMAND_TYPE_PIO_IN: - if (areq->cnt) - { - int ccbuf = areq->cbuf; - ide_controller_read_data_block(ctrl_minor, - areq->breq->bufs[0].length * areq->cnt, - areq->breq->bufs, &areq->cbuf, - &areq->pos); - ccbuf = areq->cbuf - ccbuf; - areq->cnt -= ccbuf; - } - if (areq->cnt == 0) - { - areq->breq->status = RTEMS_SUCCESSFUL; - } - else - { - /* - * this shouldn't happend on the initialization - * phase! - */ - rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR); - } - break; - - case ATA_COMMAND_TYPE_NON_DATA: - areq->breq->status = RTEMS_SUCCESSFUL; - areq->info = val1; - break; - - default: - areq->breq->status = RTEMS_IO_ERROR; - break; - } -} - -void ata_breq_init(blkdev_request1 *breq, uint16_t *sector_buffer) -{ - memset(breq, 0, sizeof(*breq)); - - breq->req.done_arg = breq; - breq->req.bufnum = 1; - breq->req.bufs [0].length = ATA_SECTOR_SIZE; - breq->req.bufs [0].buffer = sector_buffer; -} - -rtems_status_code ata_identify_device( - rtems_device_minor_number ctrl_minor, - int dev, - uint16_t *sector_buffer, - ata_dev_t *device_entry -) -{ - ata_req_t areq; - blkdev_request1 breq; - - ata_breq_init(&breq, sector_buffer); - - /* - * Issue DEVICE IDENTIFY ATA command and get device - * configuration - */ - memset(&areq, 0, sizeof(ata_req_t)); - areq.type = ATA_COMMAND_TYPE_PIO_IN; - areq.regs.to_write = ATA_REGISTERS_VALUE(IDE_REGISTER_COMMAND); - areq.regs.regs [IDE_REGISTER_COMMAND] = ATA_COMMAND_IDENTIFY_DEVICE; - areq.regs.to_read = ATA_REGISTERS_VALUE(IDE_REGISTER_STATUS); - areq.breq = (rtems_blkdev_request *)&breq; - areq.cnt = breq.req.bufnum; - areq.regs.regs [IDE_REGISTER_DEVICE_HEAD] |= - dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS; - - /* - * Process the request. Special processing of requests on - * initialization phase is needed because at this moment there - * is no multitasking enviroment - */ - ata_process_request_on_init_phase(ctrl_minor, &areq); - - /* check status of I/O operation */ - if (breq.req.status != RTEMS_SUCCESSFUL) { - return RTEMS_IO_ERROR; - } - - /* - * Parse returned device configuration and fill in ATA internal - * device info structure - */ - device_entry->cylinders = - CF_LE_W(sector_buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_CLNDS]); - device_entry->heads = - CF_LE_W(sector_buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_HEADS]); - device_entry->sectors = - CF_LE_W(sector_buffer[ATA_IDENT_WORD_NUM_OF_CURR_LOG_SECS]); - device_entry->lba_sectors = - CF_LE_W(sector_buffer[ATA_IDENT_WORD_NUM_OF_USR_SECS1]); - device_entry->lba_sectors <<= 16; - device_entry->lba_sectors += CF_LE_W(sector_buffer[ATA_IDENT_WORD_NUM_OF_USR_SECS0]); - device_entry->lba_avaible = - (CF_LE_W(sector_buffer[ATA_IDENT_WORD_CAPABILITIES]) >> 9) & 0x1; - - if ((CF_LE_W(sector_buffer[ATA_IDENT_WORD_FIELD_VALIDITY]) & - ATA_IDENT_BIT_VALID) == 0) { - /* no "supported modes" info -> use default */ - device_entry->mode_active = ATA_MODES_PIO3; - } else { - device_entry->modes_available = - ((CF_LE_W(sector_buffer[64]) & 0x1) ? ATA_MODES_PIO3 : 0) | - ((CF_LE_W(sector_buffer[64]) & 0x2) ? ATA_MODES_PIO4 : 0) | - ((CF_LE_W(sector_buffer[63]) & 0x1) ? ATA_MODES_DMA0 : 0) | - ((CF_LE_W(sector_buffer[63]) & 0x2) ? - ATA_MODES_DMA0 | ATA_MODES_DMA1 : 0) | - ((CF_LE_W(sector_buffer[63]) & 0x4) ? - ATA_MODES_DMA0 | ATA_MODES_DMA1 | ATA_MODES_DMA2 : 0); - if (device_entry->modes_available == 0) { - return RTEMS_IO_ERROR; - } - } - - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/libchip/ide/ide_controller.c b/c/src/libchip/ide/ide_controller.c deleted file mode 100644 index 912f9e3157..0000000000 --- a/c/src/libchip/ide/ide_controller.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * ide_controller.c - * - * This is generic rtems driver for IDE controllers. - * - * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia - * Authors: Alexandra Kossovsky - * Eugeny S. Mints - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - * - */ - -#define IDE_CONTROLLER_TRACE 0 - -#include -#include -#include - -#include -#include -#include - -#if IDE_CONTROLLER_TRACE -int ide_controller_trace = 1; -#endif - -/* - * ide_controller_initialize -- - * Initializes all configured IDE controllers. Controllers configuration - * table is provided by BSP - * - * PARAMETERS: - * major - device major number - * minor_arg - device minor number - * args - arguments - * - * RETURNS: - * RTEMS_SUCCESSFUL on success, or error code if - * error occured - */ -rtems_device_driver -ide_controller_initialize(rtems_device_major_number major, - rtems_device_minor_number minor_arg, - void *args) -{ - unsigned long minor; - - /* FIXME: may be it should be done on compilation phase */ - if (IDE_Controller_Count > IDE_CTRL_MAX_MINOR_NUMBER) - rtems_fatal_error_occurred(RTEMS_TOO_MANY); - - for (minor=0; minor < IDE_Controller_Count; minor++) - { - IDE_Controller_Table[minor].status = IDE_CTRL_NON_INITIALIZED; - - if ((IDE_Controller_Table[minor].probe == NULL || - IDE_Controller_Table[minor].probe(minor)) && - (IDE_Controller_Table[minor].fns->ctrl_probe == NULL || - IDE_Controller_Table[minor].fns->ctrl_probe(minor))) - { - dev_t dev; - dev = rtems_filesystem_make_dev_t( major, minor ); - if (mknod(IDE_Controller_Table[minor].name, - 0777 | S_IFBLK, dev ) < 0) - rtems_fatal_error_occurred(errno); - IDE_Controller_Table[minor].fns->ctrl_initialize(minor); - IDE_Controller_Table[minor].status = IDE_CTRL_INITIALIZED; - } - } - return RTEMS_SUCCESSFUL; -} - -/* - * ide_controller_read_data_block -- - * Read data block via controller's data register - * - * PARAMETERS: - * minor - minor number of controller - * block_size - number of bytes to read - * bufs - set of buffers to store data - * cbuf - number of current buffer from the set - * pos - position inside current buffer 'cbuf' - * - * RETURNS: - * NONE - */ -void -ide_controller_read_data_block(rtems_device_minor_number minor, - uint32_t block_size, - rtems_blkdev_sg_buffer *bufs, - uint32_t *cbuf, - uint32_t *pos) -{ -#if IDE_CONTROLLER_TRACE - if (ide_controller_trace) - printk ("IDE data block read: %d:%d\n", *cbuf, bufs[*cbuf].block); -#endif - IDE_Controller_Table[minor].fns->ctrl_read_block(minor, block_size, bufs, - cbuf, pos); -} - -/* - * ide_controller_write_data_block -- - * Write data block via controller's data register - * - * PARAMETERS: - * minor - minor number of controller - * block_size - number of bytes to write - * bufs - set of buffers which store data - * cbuf - number of current buffer from the set - * pos - position inside current buffer 'cbuf' - * - * RETURNS: - * NONE - */ -void -ide_controller_write_data_block(rtems_device_minor_number minor, - uint32_t block_size, - rtems_blkdev_sg_buffer *bufs, - uint32_t *cbuf, - uint32_t *pos) - -{ -#if IDE_CONTROLLER_TRACE - if (ide_controller_trace) - printk ("IDE data block write: %d:%d\n", *cbuf, bufs[*cbuf].block); -#endif - IDE_Controller_Table[minor].fns->ctrl_write_block(minor, block_size, bufs, - cbuf, pos); -} - -/* - * ide_controller_read_register -- - * Read controller's register - * - * PARAMETERS: - * minor - minor number of controller - * reg - register to read - * value - placeholder for result - * - * RETURNS - * NONE - */ -void -ide_controller_read_register(rtems_device_minor_number minor, - int reg, - uint16_t *value) -{ - IDE_Controller_Table[minor].fns->ctrl_reg_read(minor, reg, value); -#if IDE_CONTROLLER_TRACE - if (ide_controller_trace) - printk ("IDE read reg: %d => %04x\n", reg, *value); -#endif -} - -/* - * ide_controller_write_register -- - * Write controller's register - * - * PARAMETERS: - * minor - minor number of controller - * reg - register to write - * value - value to write - * - * RETURNS: - * NONE - */ -void -ide_controller_write_register(rtems_device_minor_number minor, int reg, - uint16_t value) -{ -#if IDE_CONTROLLER_TRACE - if (ide_controller_trace) - printk ("IDE write reg: %d => %04x\n", reg, value); -#endif - IDE_Controller_Table[minor].fns->ctrl_reg_write(minor, reg, value); -} - -/* - * ide_controller_config_io_speed -- - * Set controller's speed of IO operations - * - * PARAMETERS: - * minor - minor number of controller - * modes_available - speeds available - * - * RETURNS: - * RTEMS_SUCCESSFUL on success, or error code if - * error occured - */ -rtems_status_code -ide_controller_config_io_speed(int minor, uint16_t modes_available) -{ - return IDE_Controller_Table[minor].fns->ctrl_config_io_speed( - minor, - modes_available); -} diff --git a/c/src/libchip/network/README b/c/src/libchip/network/README deleted file mode 100644 index ecb996e65f..0000000000 --- a/c/src/libchip/network/README +++ /dev/null @@ -1,12 +0,0 @@ -This is the network interface controller portion of the libchip library. -This directory contains the source code for reusable TCP/IP network driver -support code. Each driver has its own configuration table and its -chip specific attach routine must be called by a board specific -attach routine. The board specific chip routine passes the chip -configuration and network configuration to the resuable device driver. - -The reusable chip drivers do not directly access the controller. -They access the registers on the controller via a set of -functions which are provided by the BSP. These functions set and get -general registers and data buffers. - diff --git a/c/src/libchip/network/README.3com b/c/src/libchip/network/README.3com deleted file mode 100644 index b67061dec2..0000000000 --- a/c/src/libchip/network/README.3com +++ /dev/null @@ -1,3 +0,0 @@ -# -# README.3com -# diff --git a/c/src/libchip/network/README.cs8900 b/c/src/libchip/network/README.cs8900 deleted file mode 100644 index ecd575230f..0000000000 --- a/c/src/libchip/network/README.cs8900 +++ /dev/null @@ -1,26 +0,0 @@ -Target Support -============== - -The target is required to provide the low level support routines as -listed in the Configuration section of this file. - -The file cs8900.[ch].bsp are an example BSP files for DIMMPC target. - -Conditionals -============ -CS8900_DATA_BUS_SWAPPED - XXX - -CS8900_TRACE - XXX - -CS8900_VERBOSE - XXX - -Todo -==== -+ Build two versions -- one with swapped, one without. - -+ Document conditionals. - -Configuration -============= -See the cs8900.h header file for the documentation. - diff --git a/c/src/libchip/network/README.dec21140 b/c/src/libchip/network/README.dec21140 deleted file mode 100644 index f07bec7a36..0000000000 --- a/c/src/libchip/network/README.dec21140 +++ /dev/null @@ -1,116 +0,0 @@ -This TULIP driver can be used on BSPs that support PCI bus. - -It can handle any DEC21140 and DEC21143 based Ethernet controller -although the DEC21143 support has only been tested on Intel. - -It works on big or little endian target. - -The DEC21140 has been tested with powerpc/mcp750 BSP (OnBoard Ethernet -controller) and i386/pc386 BSP (D-Link DFE-500TX Ethernet board). - -The DEC21143 has been tested only on the i386/pc386 using -the Kingston KNE100TX with 21143PD chip. - -***************************************************************** -******** *************** -******** tests with ttcp benchmark for DEC driver *************** -******** optimization *************** -******** *************** -***************************************************************** - - -LINUX -> LINUX-ix86 - -Transmitter : - -ttcp-t: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -> genesis -ttcp-t: 16777216 bytes in 1.87 real seconds = 8775.25 KB/sec +++ -ttcp-t: 2048 I/O calls, msec/call = 0.93, calls/sec = 1096.91 -ttcp-t: 0.0user 0.9sys 0:01real 51% 0i+0d 0maxrss 0+2pf 0+0csw - -Receiver : - -ttcp-r: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -ttcp-r: 16777216 bytes in 1.88 real seconds = 8706.53 KB/sec +++ -ttcp-r: 10802 I/O calls, msec/call = 0.18, calls/sec = 5740.23 -ttcp-r: 0.0user 0.2sys 0:01real 13% 0i+0d 0maxrss 0+2pf 0+0csw - -============================================================== -============================================================== -============================================================== - -LINUX -> RTEMS-ix86 with tulip driver from pc386 bsp - -Transmitter : - -ttcp-t: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -> neil-young-100 -ttcp-t: 16777216 bytes in 1.98 real seconds = 8294.76 KB/sec +++ -ttcp-t: 2048 I/O calls, msec/call = 0.99, calls/sec = 1036.85 -ttcp-t: 0.0user 0.1sys 0:01real 9% 0i+0d 0maxrss 0+2pf 0+0csw - -Receiver : - -ttcp-r: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -ttcp-r: 16777216 bytes in 2.03 real seconds = 8065.14 KB/sec +++ -ttcp-r: 3088 I/O calls, msec/call = 0.67, calls/sec = 1520.09 -ttcp-r: 0.0user 2.0sys 0:02real 100% 0i+0d 0maxrss 0+0pf 0+0csw - -============================================================== -============================================================== -============================================================== - -RTEMS-ix86 with tulip driver from pc386 bsp -> LINUX - -Transmitter : - -ttcp-t: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -> 194.2.81.126 -ttcp-t: 16777216 bytes in 2.76 real seconds = 5938.77 KB/sec +++ -ttcp-t: 2048 I/O calls, msec/call = 1.38, calls/sec = 742.35 -ttcp-t: 0.0user 2.5sys 0:02real 100% 0i+0d 0maxrss 0+0pf 0+0csw - -Receiver : - -ttcp-r: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -ttcp-r: 16777216 bytes in 2.75 real seconds = 5948.53 KB/sec +++ -ttcp-r: 11349 I/O calls, msec/call = 0.25, calls/sec = 4120.48 -ttcp-r: 0.0user 0.1sys 0:02real 6% 0i+0d 0maxrss 0+2pf 0+0csw - -============================================================== -============================================================== -============================================================== - -LINUX -> RTEMS-ix86 with optimized tulip driver - -Transmitter : - -ttcp-t: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -> neil-young-100 -ttcp-t: 16777216 bytes in 1.73 real seconds = 9470.13 KB/sec +++ -ttcp-t: 2048 I/O calls, msec/call = 0.87, calls/sec = 1183.77 -ttcp-t: 0.0user 0.1sys 0:01real 6% 0i+0d 0maxrss 0+2pf 0+0csw - -Receiver : - -ttcp-r: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -ttcp-r: 16777216 bytes in 1.76 real seconds = 9315.33 KB/sec +++ -ttcp-r: 4558 I/O calls, msec/call = 0.40, calls/sec = 2591.51 -ttcp-r: 0.0user 1.7sys 0:01real 100% 0i+0d 0maxrss 0+0pf 0+0csw - -============================================================== -============================================================== -============================================================== - -RTEMS-ix86 with optimized tulip driver -> LINUX - -Transmitter : - -ttcp-t: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -> 194.2.81.126 -ttcp-t: 16777216 bytes in 2.09 real seconds = 7847.80 KB/sec +++ -ttcp-t: 2048 I/O calls, msec/call = 1.04, calls/sec = 980.98 -ttcp-t: 0.0user 2.0sys 0:02real 100% 0i+0d 0maxrss 0+0pf 0+0csw - -Receiver : - -ttcp-r: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -ttcp-r: 16777216 bytes in 2.08 real seconds = 7874.23 KB/sec +++ -ttcp-r: 11404 I/O calls, msec/call = 0.19, calls/sec = 5480.82 -ttcp-r: 0.0user 0.1sys 0:02real 8% 0i+0d 0maxrss 0+2pf 0+0csw diff --git a/c/src/libchip/network/README.i82586 b/c/src/libchip/network/README.i82586 deleted file mode 100644 index a0990367ef..0000000000 --- a/c/src/libchip/network/README.i82586 +++ /dev/null @@ -1 +0,0 @@ -TBD diff --git a/c/src/libchip/network/README.open_eth b/c/src/libchip/network/README.open_eth deleted file mode 100644 index af9d8882cf..0000000000 --- a/c/src/libchip/network/README.open_eth +++ /dev/null @@ -1,72 +0,0 @@ -Driver for opencores ethernet MAC - README ------------------------------------------- - -The device name for the driver is 'open_eth1', the attach -function for the leon bsp is rtems_leon_open_eth_driver_attach(). - -No cache flushing is made when a frame is received. On leon, -this means that cache snooping must be configured in the -vhdl model and enabled by software. - -TX interrupts are not used and masked in the interrupt mask -register. - -For now, only 10 Mbit/s half-duplex is supported. -100 Mbit/s operations does not work reliably, the transmitter -locks up or skips frames. Seems to depend on the TX fifo -implementation in the opencores MAC. Send a mail to -jiri@gaisler.com if you know how to fix this. - -Tested only on leon, using the GR-PCI-XC2V board @ 40 MHz. -Output from ttcp receiving 1 Mbyte file: - ->>> ttcp -r -s -ttcp-r: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -ttcp-r: socket -ttcp-r: accept from 192.168.0.2 -ttcp-r: 1145339 bytes in 1.18 real seconds = 947.88 KB/sec +++ -ttcp-r: 792 I/O calls, msec/call = 1.53, calls/sec = 671.19 -ttcp-r: 0.0user 1.1sys 0:01real 100% 0i+0d 0maxrss 0+0pf 0+0csw -************ MBUF STATISTICS ************ -mbufs:1024 clusters: 128 free: 112 -drops: 0 waits: 0 drains: 0 - free:1007 data:17 header:0 socket:0 - pcb:0 rtable:0 htable:0 atable:0 - soname:0 soopts:0 ftable:0 rights:0 - ifaddr:0 control:0 oobdata:0 - -************ INTERFACE STATISTICS ************ -***** open_eth1 ***** -Address:192.168.0.66 Broadcast Address:192.168.0.255 -Flags: Up Broadcast Running Simplex -Send queue limit:50 length:0 Dropped:0 - Rx Packets:796 Rx Interrupts:796 Length:0 - Bad CRC:0 Overrun:0 Miss:0 - Tx Interrupts:0 Deferred:0 Missed Hearbeat:0 - No Carrier:0 Retransmit Limit:0 Late Collision:0 - Underrun:0 Raw output wait:0 - -************ IP Statistics ************ - total packets received 795 - datagrams delivered to upper level 795 - total ip packets generated here 401 - -************ TCP Statistics ************ - connections accepted 1 - connections established 1 - conn. closed (includes drops) 1 - segs where we tried to get rtt 2 - times we succeeded 2 - delayed acks sent 4 - total packets sent 401 - ack-only packets sent 6 - window update-only packets sent 394 - control (SYN|FIN|RST) packets sent 1 - total packets received 795 - packets received in sequence 792 - bytes received in sequence 1145339 - rcvd ack packets 2 - bytes acked by rcvd acks 2 - times hdr predict ok for data pkts 791 - - diff --git a/c/src/libchip/network/README.sonic b/c/src/libchip/network/README.sonic deleted file mode 100644 index b2478b5571..0000000000 --- a/c/src/libchip/network/README.sonic +++ /dev/null @@ -1,135 +0,0 @@ -This SONIC driver does not make any attempt to support the SONIC chip -in any of the following modes: - - + 16-bit - + little endian - -It does not attempt to handle SONIC's older than Revision C. There is -a bug in chips before that revision that must be handled in the driver. - -The configuration table should be discussed here but if you look in the -include file for the sonic, it is reasonably obvious. :) - -The performance impact of transforming this driver into libchip format -was minimal. - -The powerpc/dmv177 BSP used this driver and the following should -serve as an example configuration table. This BSP was obsoleted after -the 4.6 release series so the code is included here. - -====================================================================== - -/* - * DMV177 SONIC Configuration Information - * - * References: - * - * 1) SVME/DMV-171 Single Board Computer Documentation Package, #805905, - * DY 4 Systems Inc., Kanata, Ontario, September, 1996. - */ - -#include -#include -#include - -void dmv177_sonic_write_register( - void *base, - unsigned32 regno, - unsigned32 value -) -{ - volatile unsigned32 *p = base; - -#if (SONIC_DEBUG & SONIC_DEBUG_PRINT_REGISTERS) - printf( "%p Write 0x%04x to %s (0x%02x)\n", - &p[regno], value, SONIC_Reg_name[regno], regno ); - fflush( stdout ); -#endif - p[regno] = value; -} - -unsigned32 dmv177_sonic_read_register( - void *base, - unsigned32 regno -) -{ - volatile unsigned32 *p = base; - unsigned32 value; - - value = p[regno]; -#if (SONIC_DEBUG & SONIC_DEBUG_PRINT_REGISTERS) - printf( "%p Read 0x%04x from %s (0x%02x)\n", - &p[regno], value, SONIC_Reg_name[regno], regno ); - fflush( stdout ); -#endif - return value; -} - -/* - * Default sizes of transmit and receive descriptor areas - */ -#define RDA_COUNT 20 /* 20 */ -#define TDA_COUNT 20 /* 10 */ - -/* - * Default device configuration register values - * Conservative, generic values. - * DCR: - * No extended bus mode - * Unlatched bus retry - * Programmable outputs unused - * Asynchronous bus mode - * User definable pins unused - * No wait states (access time controlled by DTACK*) - * 32-bit DMA - * Empty/Fill DMA mode - * Maximum Transmit/Receive FIFO - * DC2: - * Extended programmable outputs unused - * Normal HOLD request - * Packet compress output unused - * No reject on CAM match - */ -#define SONIC_DCR \ - (DCR_DW32 | DCR_WAIT0 | DCR_PO0 | DCR_PO1 | DCR_RFT24 | DCR_TFT28) -#ifndef SONIC_DCR -# define SONIC_DCR (DCR_DW32 | DCR_TFT28) -#endif -#ifndef SONIC_DC2 -# define SONIC_DC2 (0) -#endif - -/* - * Default location of device registers - */ -#ifndef SONIC_BASE_ADDRESS -# define SONIC_BASE_ADDRESS 0xF3000000 -# warning "Using default SONIC_BASE_ADDRESS." -#endif - -/* - * Default interrupt vector - */ -#ifndef SONIC_VECTOR -# define SONIC_VECTOR 1 -# warning "Using default SONIC_VECTOR." -#endif - -sonic_configuration_t dmv177_sonic_configuration = { - SONIC_BASE_ADDRESS, /* base address */ - SONIC_VECTOR, /* vector number */ - SONIC_DCR, /* DCR register value */ - SONIC_DC2, /* DC2 register value */ - TDA_COUNT, /* number of transmit descriptors */ - RDA_COUNT, /* number of receive descriptors */ - dmv177_sonic_write_register, - dmv177_sonic_read_register -}; - -int rtems_dmv177_sonic_driver_attach(struct rtems_bsdnet_ifconfig *config) -{ - return rtems_sonic_driver_attach( config, &dmv177_sonic_configuration ); - -} - -====================================================================== diff --git a/c/src/libchip/network/README.tulipclone b/c/src/libchip/network/README.tulipclone deleted file mode 100644 index 90332bfd61..0000000000 --- a/c/src/libchip/network/README.tulipclone +++ /dev/null @@ -1,101 +0,0 @@ -***************************************************************** -******** *************** -******** ttcp benchmark tests of dec2114x driver *************** -******** adapted from FreeBSD's if_dc.c for RTEMS *************** -******** by: Daron Chabot (12/15/03), *************** -******** *************** -***************************************************************** - -Test Equipment: ------------------------ -- Intel 450 MHz P3's -- RH Linux v7.3, 2.4.7-10 kernel, D-Link DFE-530TX (via-rhine) -- RTEMS rtems-ss-20030703, pc386 BSP, Linksys LNE100TX ( actually, -a cleverly disguised ADMtek Centaur, aka "Comet"). -- the PCs were directly connected ( RJ-45 X-over cable ) on a class C -subnet (private) - -NOTE: ------------------------ -- the following lines must be added to the BSP's "bsp.h" file, or -inserted into an application header (e.g. a "network_config.h" file, or -similar): - -extern int rtems_dc_driver_attach(struct rtems_bsdnet_ifconfig *, int); -#define BSP_DEC_NETWORK_DRIVER_NAME "tl1" /* "tl" as in "tulip-clone" */ -#define BSP_DEC_NETWORK_DRIVER_ATTACH rtems_dc_driver_attach - - -************************** -Linux Tx ----> RTEMS Rx: * -************************** -TRANSMITTER: -ttcp-t: buflen=8192, nbuf=65536, align=16384/0, port=5001 tcp -> rtems -ttcp-t: 536870912 bytes in 45.72 real seconds = 11468.54 KB/sec +++ -ttcp-t: 536870912 bytes in 6.87 CPU seconds = 76315.57 KB/cpu sec -ttcp-t: 65536 I/O calls, msec/call = 0.71, calls/sec = 1433.57 -ttcp-t: 0.1user 6.7sys 0:45real 15% 0i+0d 0maxrss 0+2pf 0+0csw - - -RECEIVER: -ttcp-r: buflen=8192, nbuf=65536, align=16384/0, port=5001 tcp -ttcp-r: 536870912 bytes in 45.72 real seconds = 11467.37 KB/sec +++ -ttcp-r: 536870912 bytes in 45.87 CPU seconds = 11467.37 KB/cpu sec -ttcp-r: 370837 I/O calls, msec/call = 0.13, calls/sec = 8111.05 -ttcp-r: 0.0user 45.7sys 0:45real 100% 0i+0d 0maxrss 0+0pf 0+0csw - - - -************************** -RTEMS Tx ----> Linux Rx: * -************************** -TRANSMITTER: -ttcp-t: buflen=8192, nbuf=65536, align=16384/0, port=5001 tcp ->192.168.1.1 -ttcp-t: 536870912 bytes in 46.22 real seconds = 11343.31 KB/sec +++ -ttcp-t: 536870912 bytes in 46.22 CPU seconds = 11343.31 KB/cpu sec -ttcp-t: 65536 I/O calls, msec/call = 0.72, calls/sec = 1417.91 -ttcp-t: 0.0user 46.2sys 0:46real 100% 0i+0d 0maxrss 0+0pf 0+0csw - - - - -RECEIVER: -ttcp-r: buflen=8192, nbuf=65536, align=16384/0, port=5001 tcp -ttcp-r: 536870912 bytes in 46.22 real seconds = 11343.05 KB/sec +++ -ttcp-r: 536870912 bytes in 11.60 CPU seconds = 45197.24 KB/cpu sec -ttcp-r: 356183 I/O calls, msec/call = 0.13, calls/sec = 7706.07 -ttcp-r: 0.6user 10.9sys 0:46real 25% 0i+0d 0maxrss 0+2pf 0+0csw - - - -**************************************************************************** -**************************************************************************** -**************************************************************************** -******************* Test with 40kB buffer size ***************************** -**************************************************************************** -**************************************************************************** -**************************************************************************** - - -************************** -RTEMS Tx ----> Linux Rx: * -************************** -TRANSMITTER: -ttcp-t: buflen=40960, nbuf=13107, align=16384/0, port=5001 tcp -> 192.168.1.1 -ttcp-t: 536862720 bytes in 46.23 real seconds = 11340.69 KB/sec +++ -ttcp-t: 536862720 bytes in 46.23 CPU seconds = 11340.69 KB/cpu sec -ttcp-t: 13107 I/O calls, msec/call = 3.61, calls/sec = 283.52 -ttcp-t: 0.0user 46.2sys 0:46real 100% 0i+0d 0maxrss 0+0pf 0+0csw - - -RECEIVER: -ttcp-r: buflen=40960, nbuf=13107, align=16384/0, port=5001 tcp -ttcp-r: 536862720 bytes in 46.23 real seconds = 11339.54 KB/sec +++ -ttcp-r: 536862720 bytes in 10.70 CPU seconds = 48998.13 KB/cpu sec -ttcp-r: 355970 I/O calls, msec/call = 0.13, calls/sec = 7699.20 -ttcp-r: 0.5user 10.1sys 0:46real 23% 0i+0d 0maxrss 0+5pf 0+0csw - - - -**************************************************************************** -**************************************************************************** diff --git a/c/src/libchip/network/cs8900.c b/c/src/libchip/network/cs8900.c deleted file mode 100644 index 650a0e1fef..0000000000 --- a/c/src/libchip/network/cs8900.c +++ /dev/null @@ -1,1216 +0,0 @@ -/* - ------------------------------------------------------------------------ - - Copyright Cybertec Pty Ltd, 2000 - All rights reserved Cybertec Pty Ltd, 2000 - - Port to the DIMM PC copyright (c) 2004 Angelo Fraietta - This project has been assisted by the Commonwealth Government - through the Australia Council, its arts funding and advisory body. - - COPYRIGHT (c) 1989-1998. - On-Line Applications Research Corporation (OAR). - - The license and distribution terms for this file may be - found in the file LICENSE in this distribution or at - http://www.rtems.org/license/LICENSE. - - ------------------------------------------------------------------------ - - CS8900 RTEMS driver. - - See the header file for details. - -*/ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include -#include -#include - -#include - -/* - * We expect to be able to read a complete packet into an mbuf. - */ - -#if (MCLBYTES < 1520) -#error "CS8900 Driver must have MCLBYTES >= 1520" -#endif - -/* - * Task event usage. - */ - -#define CS8900_RX_OK_EVENT RTEMS_EVENT_1 -#define CS8900_TX_START_EVENT RTEMS_EVENT_1 -#define CS8900_TX_OK_EVENT RTEMS_EVENT_2 -#define CS8900_TX_WAIT_EVENT RTEMS_EVENT_3 - -/* - * IO Packet Page inteface. - */ - -static inline unsigned short -io_pp_get_reg_16 (cs8900_device *cs, unsigned short reg) -{ - rtems_interrupt_level level; - unsigned short data; - rtems_interrupt_disable (level); - cs8900_io_set_reg (cs, CS8900_IO_PACKET_PAGE_PTR, - 0x3000 | CS8900_PPP_AUTO_INCREMENT | reg); - data = cs8900_io_get_reg (cs, CS8900_IO_PP_DATA_PORT0); - rtems_interrupt_enable (level); - return data; -} - -static inline uint32_t -io_pp_get_reg_32 (cs8900_device *cs, uint16_t reg) -{ - rtems_interrupt_level level; - uint32_t data; - rtems_interrupt_disable (level); - cs8900_io_set_reg (cs, CS8900_IO_PACKET_PAGE_PTR, - 0x3000 | CS8900_PPP_AUTO_INCREMENT | reg); - data = cs8900_io_get_reg (cs, CS8900_IO_PP_DATA_PORT0); - data <<= 16; - data |= cs8900_io_get_reg (cs, CS8900_IO_PP_DATA_PORT1); - rtems_interrupt_enable (level); - return data; -} - -static inline void -io_pp_set_reg_16 (cs8900_device *cs, unsigned short reg, unsigned short data) -{ - rtems_interrupt_level level; - rtems_interrupt_disable (level); - cs8900_io_set_reg (cs, CS8900_IO_PACKET_PAGE_PTR, - 0x3000 | CS8900_PPP_AUTO_INCREMENT | reg); - cs8900_io_set_reg (cs, CS8900_IO_PP_DATA_PORT0, data); - rtems_interrupt_enable (level); -} - -static inline void -io_pp_set_reg_32 (cs8900_device *cs, unsigned short reg, unsigned long data) -{ - cs8900_io_set_reg (cs, CS8900_IO_PACKET_PAGE_PTR, - 0x3000 | CS8900_PPP_AUTO_INCREMENT | reg); - cs8900_io_set_reg (cs, CS8900_IO_PP_DATA_PORT0, data >> 16); - cs8900_io_set_reg (cs, CS8900_IO_PP_DATA_PORT1, data); -} - -static inline void -io_pp_bit_set_reg_16 (cs8900_device *cs, unsigned short reg, unsigned short mask) -{ - rtems_interrupt_level level; - rtems_interrupt_disable (level); - io_pp_set_reg_16 (cs, reg, io_pp_get_reg_16 (cs, reg) | mask); - rtems_interrupt_enable (level); -} - -static inline void -io_pp_bit_clear_reg_16 (cs8900_device *cs, unsigned short reg, unsigned short mask) -{ - rtems_interrupt_level level; - rtems_interrupt_disable (level); - io_pp_set_reg_16 (cs, reg, io_pp_get_reg_16 (cs, reg) & ~mask); - rtems_interrupt_enable (level); -} - -/* - * Memory Mapped Packet Page interface. - * - * If the BSP does not configure mem_base use the I/O register accesses. - */ - -static inline unsigned short -mem_pp_get_reg (cs8900_device *cs, unsigned short reg) -{ - if (!cs->mem_base) - return io_pp_get_reg_16 (cs, reg); - return cs8900_mem_get_reg (cs, reg); -} - -static inline void -mem_pp_set_reg (cs8900_device *cs, unsigned short reg, unsigned short data) -{ - if (!cs->mem_base) - io_pp_set_reg_16 (cs, reg, data); - else - cs8900_mem_set_reg (cs, reg, data); -} - -static inline void -mem_pp_bit_set_reg (cs8900_device *cs, unsigned short reg, unsigned short mask) -{ - if (!cs->mem_base) - io_pp_bit_set_reg_16 (cs, reg, mask); - else - { - rtems_interrupt_level level; - rtems_interrupt_disable (level); - mem_pp_set_reg (cs, reg, mem_pp_get_reg (cs, reg) | mask); - rtems_interrupt_enable (level); - } -} - -static inline void -mem_pp_bit_clear_reg (cs8900_device *cs, unsigned short reg, unsigned short mask) -{ - if (!cs->mem_base) - io_pp_bit_clear_reg_16 (cs, reg, mask); - else - { - rtems_interrupt_level level; - rtems_interrupt_disable (level); - mem_pp_set_reg (cs, reg, mem_pp_get_reg (cs, reg) & ~mask); - rtems_interrupt_enable (level); - } -} - -/* - * Trace defines and control structures. - */ - -#define CS8900_T_INT (0) -#define CS8900_T_RX_OK (1) -#define CS8900_T_RX_DROPPED (2) -#define CS8900_T_NO_MBUF (3) -#define CS8900_T_NO_CLUSTERS (4) -#define CS8900_T_RX_BEGIN (5) -#define CS8900_T_RX_END (6) - -#if CS8900_TRACE - -static const char *cs8900_trace_labels[] = -{ - "int", - "rx ok", - "rx dropped", - "no mbuf", - "no clusters", - "rx begin", - "rx end" -}; - -/* - * Assumes a micro-second timer such as the Coldfire. - */ - -uint32_t rtems_read_timer (); - -static inline void -cs8900_trace (cs8900_device *cs, unsigned short key, unsigned long var) -{ - rtems_interrupt_level level; - - rtems_interrupt_disable (level); - - if (cs->trace_in < CS8900_TRACE_SIZE) - { - cs->trace_key[cs->trace_in] = key; - cs->trace_var[cs->trace_in] = var; - cs->trace_time[cs->trace_in] = rtems_read_timer (); - cs->trace_in++; - } - - rtems_interrupt_enable (level); -} -#else -#define cs8900_trace(c, k, v) -#endif - -void cs8900_get_mac_addr (cs8900_device *cs, unsigned char *mac_address) -{ - unsigned short ma; - - /* - * Only ever use IO calls for this function as it can be - * called before memory mode has been enabled. - */ - - ma = io_pp_get_reg_16 (cs, CS8900_PP_IA); - mac_address[0] = ma >> 8; - mac_address[1] = ma; - - ma = io_pp_get_reg_16 (cs, CS8900_PP_IA + 2); - mac_address[2] = ma >> 8; - mac_address[3] = ma; - - ma = io_pp_get_reg_16 (cs, CS8900_PP_IA + 4); - mac_address[4] = ma >> 8; - mac_address[5] = ma; -} - -/* - * Bring the chip online. - */ - -static void -cs8900_hardware_init (cs8900_device *cs) -{ - unsigned long prod_id; - unsigned short status; - - /* - * Do nothing while the device is calibrating and checking the EEPROM. - * We must wait 20msecs. - */ - - io_pp_bit_set_reg_16 (cs, CS8900_PP_SelfCTL, CS8900_SELF_CTRL_RESET); - - rtems_task_wake_after (RTEMS_MILLISECONDS_TO_TICKS (20)); - - status = io_pp_get_reg_16 (cs, CS8900_PP_SelfST); - if (status == 0) { - printf("Reading status register again\n"); - status = io_pp_get_reg_16 (cs, CS8900_PP_SelfST); - } - - if (((status & CS8900_SELF_STATUS_INITD) == 0) || - ((status & CS8900_SELF_STATUS_INITD) && - (status & CS8900_SELF_STATUS_EEPROM_PRESENT) && - (status & CS8900_SELF_STATUS_SIBUST))) - { - printf ("CS8900: %s. Initialisation aborted.\n", - (status & CS8900_SELF_STATUS_INITD) ? - "EEPROM read/write failed to complete" : - "Failed to complete to reset"); - return; - } - - /* Set the RX queue size if not set by the BSP. */ - - if (cs->rx_queue_size == 0) - cs->rx_queue_size = 10; - - /* Probe the device for its ID */ - - prod_id = io_pp_get_reg_32 (cs, CS8900_PP_PROD_ID); - - if ((prod_id >> 16) != CS8900_ESIA_ID) - { - printf ("CS8900: Invalid EISA ID, read product code 0x%08lx\n", prod_id); - return; - } - - if ((prod_id & 0x000000ff) != 0) - { - printf ("CS8900: Unsupported product id, read product code 0x%08lx\n", - prod_id); - return; - } - - printf ("CS8900 Rev %ld, %s, %s.\n", - (prod_id >> 8) & 0x1f, - status & CS8900_SELF_STATUS_3_3_V ? "3.3V" : "5.0V", - status & CS8900_SELF_STATUS_EEPROM_PRESENT ? - "EEPROM present" : "no EEPROM"); - - /* - * Switch to memory base accesses as they are faster. No indirect access. - */ - - if (cs->mem_base) - { - io_pp_set_reg_16 (cs, CS8900_PP_MEM_BASE, cs->mem_base); - io_pp_set_reg_16 (cs, CS8900_PP_MEM_BASE + 2, (cs->mem_base >> 16) & 0xf); - - io_pp_set_reg_16 (cs, - CS8900_PP_BusCTL, - CS8900_BUS_CTRL_RESET_RX_DMA | - CS8900_BUS_CTRL_USE_SA | - CS8900_BUS_CTRL_MEMORY_ENABLE); - io_pp_set_reg_16 (cs, - CS8900_PP_BusCTL, - CS8900_BUS_CTRL_USE_SA | - CS8900_BUS_CTRL_MEMORY_ENABLE); - } - - /* - * We are now in memory mapped mode. - */ - - /* - * Program the Line Control register with the mode we want. - * - * No auto detect support at the moment. Only 10BaseT. - */ - - mem_pp_set_reg (cs, CS8900_PP_LineCFG, CS8900_LINE_CTRL_10BASET); - - /* - * Ask the user for the MAC address, the program into the device. - */ - -#define MACO(o) cs->arpcom.ac_enaddr[o] - - mem_pp_set_reg (cs, CS8900_PP_IA, - (((unsigned int) MACO (1)) << 8) | - ((unsigned int) MACO (0))); - mem_pp_set_reg (cs, CS8900_PP_IA + 2, - (((unsigned int) MACO (3)) << 8) | - ((unsigned int) MACO (2))); - mem_pp_set_reg (cs, CS8900_PP_IA + 4, - (((unsigned int) MACO (5)) << 8) | - ((unsigned int) MACO (4))); - - /* - * Set the Buffer configuration. - */ - - mem_pp_set_reg (cs, CS8900_PP_BufCFG, - CS8900_BUFFER_CONFIG_RDY_FOR_TX | - CS8900_BUFFER_CONFIG_TX_UNDERRUN | - CS8900_BUFFER_CONFIG_TX_COL_OVF | - CS8900_BUFFER_CONFIG_RX_MISSED_OVF); - - /* - * Set the Receiver configuration. - */ - - mem_pp_set_reg (cs, CS8900_PP_RxCFG, - CS8900_RX_CONFIG_RX_OK | - CS8900_RX_CONFIG_CRC_ERROR | - CS8900_RX_CONFIG_RUNT| - CS8900_RX_CONFIG_EXTRA_DATA); - - /* - * Set the Receiver control. - */ - - mem_pp_set_reg (cs, CS8900_PP_RxCTL, - CS8900_RX_CTRL_RX_OK | - CS8900_RX_CTRL_MULTICAST | - CS8900_RX_CTRL_INDIVIDUAL | - CS8900_RX_CTRL_BROADCAST); - - /* - * Set the Transmitter configuration. - */ - - mem_pp_set_reg (cs, CS8900_PP_TxCFG, - CS8900_TX_CONFIG_TX_OK | - CS8900_TX_CONFIG_OUT_OF_WINDOW | - CS8900_TX_CONFIG_JABBER | - CS8900_TX_CONFIG_16_COLLISION); - - /* - * Attach the interrupt handler. - */ - - cs8900_attach_interrupt (cs); - - /* - * Program the interrupt level we require then enable interrupts. - * - * Note, this will need to change to support other levels. - */ - - mem_pp_set_reg (cs, CS8900_PP_INT, cs->irq_level & 3); - - mem_pp_bit_set_reg (cs, CS8900_PP_BusCTL, - CS8900_BUS_CTRL_ENABLE_INT); -} - -rtems_isr -cs8900_interrupt (rtems_vector_number v, void *csp) -{ - cs8900_device *cs = csp; - unsigned short isq = 0; - struct mbuf *m; - unsigned char *p; - - ++cs->eth_stats.interrupts; - - while (1) - { - isq = mem_pp_get_reg (cs, CS8900_PP_ISQ); - - cs8900_trace (cs, CS8900_T_INT, isq); - - /* - * No more interrupts to service. - */ - - if (isq == 0) - return; - - switch (isq & 0x1f) - { - case 0x04: - - /* - * RxEvent. - */ - - ++cs->eth_stats.rx_interrupts; - - if (isq & CS8900_RX_EVENT_RX_OK) - { - m = cs->rx_ready_head; - if (m) - { - cs->rx_ready_head = m->m_nextpkt; - if (cs->rx_ready_head == 0) - cs->rx_ready_tail = 0; - m->m_nextpkt = 0; - cs->rx_ready_len--; - - p = mtod (m, unsigned char *); - - m->m_pkthdr.len = cs8900_get_data_block (cs, p); - - if (cs->rx_loaded_tail == 0) - cs->rx_loaded_head = m; - else - cs->rx_loaded_tail->m_nextpkt = m; - cs->rx_loaded_tail = m; - cs->rx_loaded_len++; - - if (cs->rx_loaded_len == 1) - { - cs8900_trace (cs, CS8900_T_RX_OK, cs->rx_loaded_len); - rtems_bsdnet_event_send (cs->rx_task, CS8900_RX_OK_EVENT); - } - } - else - { - ++cs->eth_stats.rx_dropped; - - cs8900_trace (cs, CS8900_T_RX_DROPPED, cs->rx_loaded_len); - - if (cs->rx_loaded_len == 0) - rtems_bsdnet_event_send (cs->rx_task, CS8900_RX_OK_EVENT); - } - } - else - { - if (isq & CS8900_RX_EVENT_CRC_ERROR) - ++cs->eth_stats.rx_crc_errors; - - if (isq & CS8900_RX_EVENT_RUNT) - ++cs->eth_stats.rx_runt_errors; - - if (isq & CS8900_RX_EVENT_EXTRA_DATA) - ++cs->eth_stats.rx_oversize_errors; - } - break; - - case 0x08: - - /* - * TxEvent. - */ - - ++cs->eth_stats.tx_interrupts; - - if (cs->tx_active) - { - if (isq & CS8900_TX_EVENT_TX_OK) - ++cs->eth_stats.tx_ok; - - cs->tx_active = 0; - - rtems_bsdnet_event_send (cs->tx_task, CS8900_TX_OK_EVENT); - } - break; - - case 0x0c: - - /* - * BufEvent. - */ - - if (isq & CS8900_BUFFER_EVENT_RDY_FOR_TX) - { - if (cs->tx_active) - { - ++cs->eth_stats.tx_rdy4tx; - rtems_bsdnet_event_send (cs->tx_task, CS8900_TX_WAIT_EVENT); - } - } - else if (isq & CS8900_BUFFER_EVENT_TX_UNDERRUN) - { - ++cs->eth_stats.tx_underrun_errors; - if (cs->tx_active) - rtems_bsdnet_event_send (cs->tx_task, CS8900_TX_OK_EVENT); - } - else if (isq & CS8900_BUFFER_EVENT_SW_INT) - { - ++cs->eth_stats.int_swint_res; - } - break; - - case 0x10: - - /* - * RxMiss. - */ - - cs->eth_stats.rx_missed_errors += - mem_pp_get_reg (cs, CS8900_PP_RxMISS) >> 6; - break; - - case 0x12: - - /* - * TxCol. - */ - - cs->eth_stats.tx_collisions += - mem_pp_get_reg (cs, CS8900_PP_TxCol) >> 6; - break; - - default: - break; - } - } - -} - -int -cs8900_link_active (cs8900_device *cs) -{ - return ((mem_pp_get_reg (cs, CS8900_PP_LineST) & CS8900_LINE_STATUS_LINK_OK) ? - 1 : 0); -} - -static inline void -cs8900_rx_refill_queue (cs8900_device *cs) -{ - struct ifnet *ifp = &cs->arpcom.ac_if; - struct mbuf *m; - rtems_interrupt_level level; - - /* - * Hold a single queue of mbuf's at the interface. This - * will lower the latency of the driver. - */ - - while (cs->rx_ready_len < cs->rx_queue_size) - { - MGETHDR (m, M_DONTWAIT, MT_DATA); - - if (!m) - { - ++cs->eth_stats.rx_no_mbufs; - cs8900_trace (cs, CS8900_T_NO_MBUF, cs->eth_stats.rx_no_mbufs); - return; - } - - MCLGET (m, M_DONTWAIT); - - if (!m->m_ext.ext_buf) - { - ++cs->eth_stats.rx_no_clusters; - cs8900_trace (cs, CS8900_T_NO_CLUSTERS, cs->eth_stats.rx_no_clusters); - m_free (m); - return; - } - m->m_pkthdr.rcvif = ifp; - m->m_nextpkt = 0; - - rtems_interrupt_disable (level); - - if (cs->rx_ready_tail == 0) - cs->rx_ready_head = m; - else - cs->rx_ready_tail->m_nextpkt = m; - cs->rx_ready_tail = m; - cs->rx_ready_len++; - - rtems_interrupt_enable (level); - } -} - -static void -cs8900_rx_task (void *arg) -{ - cs8900_device *cs = arg; - struct ifnet *ifp = &cs->arpcom.ac_if; - rtems_event_set events; - struct mbuf *m; - struct ether_header *eh; - rtems_status_code sc; - rtems_interrupt_level level; - - /* - * Turn the receiver and transmitter on. - */ - - mem_pp_bit_set_reg (cs, CS8900_PP_LineCFG, - CS8900_LINE_CTRL_RX_ON | - CS8900_LINE_CTRL_TX_ON); - - /* - * Start the software interrupt watchdog. - */ - - mem_pp_bit_set_reg (cs, CS8900_PP_BufCFG, - CS8900_BUFFER_CONFIG_SW_INT); - ++cs->eth_stats.int_swint_req; - - /* - * Loop reading packets. - */ - - while (1) - { - cs8900_rx_refill_queue (cs); - - sc = rtems_bsdnet_event_receive (CS8900_RX_OK_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_MILLISECONDS_TO_TICKS (250), - &events); - - cs8900_rx_refill_queue (cs); - - if (sc == RTEMS_TIMEOUT) - { - /* - * We need to check the interrupt hardware in the cs8900a - * has not locked up. It seems this occurs if the ISQ - * queue fills up. - * To test we generate a software interrupt and watch - * a counter go up. If the counter does not go for 2 - * software interrupts requests we flush the ISQ queue. - */ - - if ((cs->eth_stats.int_swint_req - cs->eth_stats.int_swint_res) > 1) - { - printf ("cs8900: int lockup, isq flush\n"); - - mem_pp_bit_clear_reg (cs, CS8900_PP_BusCTL, - CS8900_BUS_CTRL_ENABLE_INT); - - while (mem_pp_get_reg (cs, CS8900_PP_ISQ) != 0); - - cs->eth_stats.int_swint_req = cs->eth_stats.int_swint_res = 0; - ++cs->eth_stats.int_lockup; - - mem_pp_bit_set_reg (cs, CS8900_PP_BusCTL, - CS8900_BUS_CTRL_ENABLE_INT); - } - - mem_pp_bit_set_reg (cs, CS8900_PP_BufCFG, - CS8900_BUFFER_CONFIG_SW_INT); - ++cs->eth_stats.int_swint_req; - } - - cs8900_trace (cs, CS8900_T_RX_BEGIN, cs->rx_loaded_len); - - while (cs->rx_loaded_len) - { - rtems_interrupt_disable (level); - - m = cs->rx_loaded_head; - if (m) - { - cs->rx_loaded_head = m->m_nextpkt; - if (cs->rx_loaded_head == 0) - cs->rx_loaded_tail = 0; - m->m_nextpkt = 0; - cs->rx_loaded_len--; - - rtems_interrupt_enable (level); - - m->m_pkthdr.rcvif = ifp; - - cs->eth_stats.rx_bytes += m->m_pkthdr.len; - - m->m_len = m->m_pkthdr.len = m->m_pkthdr.len - sizeof (struct ether_header); - - eh = mtod (m, struct ether_header *); - m->m_data += sizeof (struct ether_header); - - ++cs->eth_stats.rx_packets; - - ether_input (ifp, eh, m); - } - else - { - rtems_interrupt_enable (level); - } - } - cs8900_trace (cs, CS8900_T_RX_END, cs->rx_loaded_len); - } -} - -static void -cs8900_tx_task (void *arg) -{ - cs8900_device *cs = arg; - struct ifnet *ifp = &cs->arpcom.ac_if; - rtems_event_set events; - struct mbuf *m; - rtems_status_code sc; - - /* - * Wait for the link to come up. - */ - - rtems_task_wake_after (RTEMS_MILLISECONDS_TO_TICKS (750)); - - /* - * Loop processing the tx queue. - */ - - while (1) - { - /* - * Fetch the mbuf list from the interface's queue. - */ - - IF_DEQUEUE (&ifp->if_snd, m); - - /* - * If something actually is present send it. - */ - - if (!m) - { - ifp->if_flags &= ~IFF_OACTIVE; - - rtems_bsdnet_event_receive (CS8900_TX_START_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - } - else - { - if (cs8900_link_active (cs)) - { - int resending; - - do - { - unsigned short buf_status; - - resending = 0; - - cs->tx_active = 1; - - mem_pp_set_reg (cs, CS8900_PP_TxCMD, - CS8900_TX_CMD_STATUS_TX_START_ENTIRE | - CS8900_TX_CMD_STATUS_FORCE); - mem_pp_set_reg (cs, CS8900_PP_TxLength, m->m_pkthdr.len); - - buf_status = mem_pp_get_reg (cs, CS8900_PP_BusST); - - /* - * If the bid for memory in the device fails trash the - * transmit and try again next time. - */ - - if (buf_status & CS8900_BUS_STATUS_TX_BID_ERROR) - ++cs->eth_stats.tx_bid_errors; - else - { - /* - * If the buffer is not read enable the interrupt and then wait. - */ - - if ((buf_status & CS8900_BUS_STATUS_RDY_FOR_TX_NOW) == 0) - { - cs->eth_stats.tx_wait_for_rdy4tx++; - sc = rtems_bsdnet_event_receive (CS8900_TX_WAIT_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_MILLISECONDS_TO_TICKS (750), - &events); - if (sc == RTEMS_TIMEOUT) - { - /* - * For some reason the wait request has been dropped, - * so lets resend from the start. - */ - - printf ("tx resend\n"); - ++cs->eth_stats.tx_resends; - resending = 1; - } - } - - if (!resending) - { - cs8900_tx_load (cs, m); - cs->eth_stats.tx_packets++; - cs->eth_stats.tx_bytes += m->m_pkthdr.len; - } - } - } - while (resending); - - m_freem (m); - - do - { - rtems_bsdnet_event_receive (CS8900_TX_OK_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - } - while (cs->tx_active); - } - else - { - ++cs->eth_stats.tx_dropped; - m_freem (m); - } - } - } -} - -static void -cs8900_start (struct ifnet *ifp) -{ - cs8900_device *cs = ifp->if_softc; - - /* - * Tell the transmit daemon to wake up and send a packet. - */ - - ifp->if_flags |= IFF_OACTIVE; - - rtems_bsdnet_event_send (cs->tx_task, CS8900_TX_START_EVENT); -} - -static void -cs8900_stop (cs8900_device *cs) -{ - mem_pp_bit_clear_reg (cs, CS8900_PP_LineCFG, - CS8900_LINE_CTRL_RX_ON | - CS8900_LINE_CTRL_TX_ON); - - mem_pp_bit_clear_reg (cs, CS8900_PP_BusCTL, - CS8900_BUS_CTRL_ENABLE_INT); -} - -static const char *eth_statistics_labels[] = -{ - "rx packets", - "tx packets", - "rx bytes", - "tx bytes", - "rx interrupts", - "tx interrupts", - "rx dropped", - "rx no mbuf", - "rx no custers", - "rx oversize errors", - "rx crc errors", - "rx runt errors", - "rx missed errors", - "tx ok", - "tx collisions", - "tx bid errors", - "tx wait for rdy4tx", - "tx rdy4tx", - "tx underrun errors", - "tx dropped", - "tx resends", - "int swint req", - "int swint res", - "int lockup", - "interrupts" -}; - -static void -cs8900_stats (cs8900_device *cs) -{ - int i; - int max_label = 0; - int len; - unsigned long *value = (unsigned long*) &cs->eth_stats.rx_packets; - - cs->eth_stats.rx_missed_errors += - mem_pp_get_reg (cs, CS8900_PP_RxMISS) >> 6; - - cs->eth_stats.tx_collisions += - mem_pp_get_reg (cs, CS8900_PP_TxCol) >> 6; - - printf ("Network Driver Stats for CS8900 :\n"); - - for (i = 0; i < (sizeof (eth_statistics_labels) / sizeof (const char *)); i++) - { - len = strlen (eth_statistics_labels[i]); - if (len > max_label) - max_label = len; - } - - max_label += 2; - - printf ("%*s - %10u %*s - %10u\n", - max_label, "rx ready len", cs->rx_ready_len, - max_label, "rx loaded len", cs->rx_loaded_len); - - for (i = 0; - i < (sizeof (eth_statistics_labels) / sizeof (const char *)); - i++) - { - printf ("%*s - %10lu", - max_label, eth_statistics_labels[i], value[i]); - - i++; - - if (i < (sizeof (eth_statistics_labels) / sizeof (const char *))) - printf (" %*s - %10lu", - max_label, eth_statistics_labels[i], value[i]); - printf ("\n"); - } - -#if CS8900_TRACE - - for (i = 0; i < cs->trace_in; i++) - { - printf ("%8ld.%03ld ", cs->trace_time[i] / 1000, cs->trace_time[i] % 1000); - - if (cs->trace_key[i] < sizeof (cs8900_trace_labels) / sizeof (char*)) - printf ("%s : ", cs8900_trace_labels[cs->trace_key[i]]); - else - printf ("unknown trace key, %d : ", cs->trace_key[i]); - - if (cs->trace_key[i] == CS8900_T_INT) - { - printf ("0x%04lx ", cs->trace_var[i]); - if (cs->trace_var[i] == 0) - printf ("end"); - else - { - switch (cs->trace_var[i] & 0x1f) - { - case 0x04: - printf ("rx event"); - break; - - case 0x08: - printf ("tx event"); - break; - - case 0x0c: - printf ("buffer event"); - break; - - case 0x10: - printf ("rx missed"); - break; - - case 0x12: - printf ("tx collisions"); - break; - - case 0x1f: - printf ("tx request"); - break; - - case 0x1e: - printf ("tx wait 4 tx"); - break; - - case 0x1d: - printf ("tx already active"); - break; - - default: - printf ("unknown event"); - break; - } - } - } - else - printf ("0x%08lx", cs->trace_var[i]); - - printf ("\n"); - } - - cs->trace_in = 0; - -#endif -} - -static void -cs8900_init (void *arg) -{ - cs8900_device *cs = arg; - struct ifnet *ifp = &cs->arpcom.ac_if; - - if (cs->rx_task == 0) - { - - /* - * Set up the hardware. - */ - - cs8900_hardware_init (cs); - - /* - * Start driver task. We have only one task. - */ - - cs->rx_task = rtems_bsdnet_newproc ("CSr0", 4096, cs8900_rx_task, cs); - cs->tx_task = rtems_bsdnet_newproc ("CSt0", 4096, cs8900_tx_task, cs); - } - -#ifdef todo - /* - * Set flags appropriately - */ - if (ifp->if_flags & IFF_PROMISC) - else -#endif - - /* - * Tell the world that we're running. - */ - - ifp->if_flags |= IFF_RUNNING; - - /* - * Set the Line Control to bring the receive and transmitter online. - */ - - mem_pp_bit_set_reg (cs, CS8900_PP_LineCFG, - CS8900_LINE_CTRL_RX_ON | - CS8900_LINE_CTRL_TX_ON); - - mem_pp_bit_set_reg (cs, CS8900_PP_BusCTL, - CS8900_BUS_CTRL_ENABLE_INT); -} - -static int -cs8900_ioctl (struct ifnet *ifp, ioctl_command_t cmd, caddr_t data) -{ - cs8900_device *cs = ifp->if_softc; - int error = 0; - - switch (cmd) - { - case SIOCGIFADDR: - case SIOCSIFADDR: - - error = ether_ioctl (ifp, cmd, data); - break; - - case SIOCSIFFLAGS: - - switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) - { - case IFF_RUNNING: - - cs8900_stop (cs); - break; - - case IFF_UP: - - cs8900_init (cs); - break; - - case IFF_UP | IFF_RUNNING: - - cs8900_stop (cs); - cs8900_init (cs); - break; - - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - - cs8900_stats (cs); - break; - - /* FIXME: Multicast commands must be added here. */ - - default: - error = EINVAL; - break; - } - - return error; -} - -int -cs8900_driver_attach (struct rtems_bsdnet_ifconfig *config, int attaching) -{ - cs8900_device *cs; - struct ifnet *ifp; - int mtu; - int unit; - char *name; - - /* - * Parse driver name - */ - - if ((unit = rtems_bsdnet_parse_driver_name (config, &name)) < 0) - return 0; - - cs = config->drv_ctrl; - cs->dev = unit; - ifp = &cs->arpcom.ac_if; - - if (attaching) - { - if (ifp->if_softc) - { - printf ("Driver `%s' already in use.\n", config->name); - return 0; - } - - /* - * Process options - */ - - if (config->hardware_address) - memcpy (cs->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); - else - cs8900_get_mac_addr (cs, cs->arpcom.ac_enaddr); - - if (config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - - cs->accept_bcast = !config->ignore_broadcast; - - /* - * Set up network interface values. - */ - - ifp->if_softc = cs; - ifp->if_unit = unit; - ifp->if_name = name; - ifp->if_mtu = mtu; - ifp->if_init = cs8900_init; - ifp->if_ioctl = cs8900_ioctl; - ifp->if_start = cs8900_start; - ifp->if_output = ether_output; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; - - if (ifp->if_snd.ifq_maxlen == 0) - ifp->if_snd.ifq_maxlen = ifqmaxlen; - - /* - * Attach the interface to the stack. - */ - - if_attach (ifp); - ether_ifattach (ifp); - } - else - { - if (!ifp->if_softc) - { - printf ("Driver `%s' not found.\n", config->name); - return 0; - } - - cs8900_stop (cs); - cs8900_detach_interrupt (cs); - } - - return 1; -} diff --git a/c/src/libchip/network/cs8900.c.bsp b/c/src/libchip/network/cs8900.c.bsp deleted file mode 100644 index 7b7374a0f2..0000000000 --- a/c/src/libchip/network/cs8900.c.bsp +++ /dev/null @@ -1,510 +0,0 @@ -/* - * RTEMS CS8900 Driver Setup for the DIMM-PC/i386 made by Kontron. - * - * Port to the DIMM PC copyright (c) 2004 Angelo Fraietta - * This project has been assisted by the Commonwealth Government - * through the Australia Council, its arts funding and advisory body. - * - * Port performed by Chris Johns, Cybertec Pty Ltd, Jan 2004. - * Based on the Cybertec CS8900 driver setup for the SFP-101. - * - */ - -#define CS8900_VERBOSE 0 -#define HAVE_MRB_CS8900_DATA_BUS_SWAPPED 1 - -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include "cs8900.h" - -#include - -/* - * Loopback interface. - */ - -extern int rtems_bsdnet_loopattach (struct rtems_bsdnet_ifconfig *, int); - -static struct rtems_bsdnet_ifconfig loopback_config = -{ - "lo0", /* name */ - rtems_bsdnet_loopattach, /* attach function */ - NULL, /* link to next interface */ - "127.0.0.1", /* IP address */ - "255.0.0.0", /* IP net mask */ -}; - -/* - * Network configuration - */ - -struct rtems_bsdnet_config rtems_bsdnet_config = -{ - &loopback_config, - NULL, - 20, /* Network task priority */ - 32 * 1024, /* Mbuf capacity */ - 96 * 1024, /* Mbuf cluster capacity */ -}; - - -static void cs8900_isr (); -static void cs8900_int_off (const rtems_irq_connect_data* unused); -static void cs8900_int_on (const rtems_irq_connect_data* unused); -static int cs8900_int_is_on (const rtems_irq_connect_data *irq); - -/** - * The device's data. - */ -static cs8900_device cs8900; -static rtems_irq_connect_data cs8900_irq = -{ - 0, - cs8900_isr, - cs8900_int_on, - cs8900_int_off, - cs8900_int_is_on -}; - -#if CS8900_VERBOSE -static int cs8900_io_verbose = 1; -#endif - -/** - * Device structure for attaching to the BSD stack. - */ -static struct rtems_bsdnet_ifconfig cs8900_ifconfig = -{ - "cs0", /* name */ - cs8900_driver_attach, /* attach funtion */ - NULL, /* next interface */ - NULL, /* ip address */ - NULL, /* ip netmask */ - NULL, /* hardware address */ - 0, /* ignore broadcast */ - 0, /* mtu */ - 0, /* rbuf count */ - 0, /* xbuf count */ - 0, /* port */ - 0, /* irno */ - 0, /* bpar */ - 0 /* drv ctrl */ -}; - - -/* - * Commands to register. - */ - -rtems_monitor_command_entry_t rtems_bsdnet_commands[] = -{ - { - "ifstats", - "Show the interface stats.\n", - 0, - (void*) rtems_bsdnet_show_if_stats, - 0, - 0, - }, - { - "ipstats", - "Show the IP stats.\n", - 0, - (void*) rtems_bsdnet_show_ip_stats, - 0, - 0, - }, - { - "routes", - "Show the inet routes.\n", - 0, - (void*) rtems_bsdnet_show_inet_routes, - 0, - 0, - }, - { - "mbufs", - "Show the mbuf stats.\n", - 0, - (void*) rtems_bsdnet_show_mbuf_stats, - 0, - 0, - }, - { - "icmp", - "Show the ICMP stats.\n", - 0, - (void*) rtems_bsdnet_show_icmp_stats, - 0, - 0, - }, - { - "udp", - "Show the UDP stats.\n", - 0, - (void*) rtems_bsdnet_show_udp_stats, - 0, - 0, - }, - { - "tcp", - "Show the TCP stats.\n", - 0, - (void*) rtems_bsdnet_show_tcp_stats, - 0, - 0, - } -}; - -static void -cs8900_isr () -{ - /* - * Note: we could have a high priority task here to call the - * drivers handler. The would lower the interrupt latancy - * we aother wise have. - */ - cs8900_interrupt (cs8900_irq.name, &cs8900); -} - -static void -cs8900_int_on (const rtems_irq_connect_data *unused) -{ -} - -static void -cs8900_int_off (const rtems_irq_connect_data *unused) -{ -} - -static int -cs8900_int_is_on (const rtems_irq_connect_data *irq) -{ - return BSP_irq_enabled_at_i8259s (irq->name); -} - -void cs8900_io_set_reg (cs8900_device *cs, unsigned short reg, unsigned short data) -{ -#if CS8900_VERBOSE - if (cs8900_io_verbose) - printk ("CS8900: io set reg=0x%04x, data=0x%04x\n", reg, data); -#endif - outport_word (cs->io_base + reg, data); -} - -unsigned short cs8900_io_get_reg (cs8900_device *cs, unsigned short reg) -{ - unsigned short data; - inport_word (cs->io_base + reg, data); -#if CS8900_VERBOSE - if (cs8900_io_verbose) - printk ("CS8900: io get reg=0x%04x, data=0x%04x\n", reg, data); -#endif - return data; -} - -void cs8900_mem_set_reg (cs8900_device *cs, unsigned long reg, unsigned short data) -{ - printk ("CS8900: mem_set_reg register access called. Only IO supported.\n"); - while (1); -} - -unsigned short cs8900_mem_get_reg (cs8900_device *cs, unsigned long reg) -{ - printk ("CS8900: mem_get_reg register access called. Only IO supported.\n"); - while (1); - return 0; -} - -void cs8900_put_data_block (cs8900_device *cs, int len, unsigned char *data) -{ - unsigned short *src = (unsigned short *) ((unsigned long) data); - - for (; len > 1; len -= 2) - outport_word (cs->io_base, *src++); - - if (len) - outport_word (cs->io_base, *src++); -} - -unsigned short cs8900_get_data_block (cs8900_device *cs, unsigned char *data) -{ - unsigned short *dst; - int cnt; - int len; - - /* - * Drop the Rx status first. - */ - inport_word (cs->io_base, len); - - /* - * Now the length. - */ - inport_word (cs->io_base, len); - - dst = (unsigned short *) ((unsigned long) data); - cnt = len >> 1; - - while (cnt--) - inport_word (cs->io_base, *dst++); - - if (len & 1) - inport_word (cs->io_base, *dst++); - - return len; -} - -void -cs8900_tx_load (cs8900_device *cs, struct mbuf *m) -{ - unsigned int len; - unsigned char *src = 0; - unsigned short *wsrc = 0; - unsigned char remainder = 0; - unsigned char word[2]; - - while (m) - { - /* - * We can get empty mbufs from the stack. - */ - - len = m->m_len; - src = mtod (m, unsigned char*); - - if (len) - { - if (remainder) - { -#if HAVE_MRB_CS8900_DATA_BUS_SWAPPED - word[1] = *src++; -#else - word[0] = *src++; -#endif - outport_word (cs->io_base, *((unsigned short*) (unsigned long) &word)); - len--; - remainder = 0; - } - - if (len & 1) - { - remainder = 1; - len--; - } - - wsrc = (unsigned short*) src; - - for (; len; len -= 2, src += 2) - outport_word (cs->io_base, *wsrc++); - - if (remainder) -#if HAVE_MRB_CS8900_DATA_BUS_SWAPPED - word[0] = *src++; -#else - word[1] = *src++; -#endif - } - - m = m->m_next; - } - - if (remainder) - { -#if HAVE_MRB_CS8900_DATA_BUS_SWAPPED - word[1] = *src++; -#else - word[0] = *src++; -#endif - outport_word (cs->io_base, *((unsigned short*) (unsigned long) &word)); - } -} - -void cs8900_attach_interrupt (cs8900_device *cs) -{ - BSP_install_rtems_irq_handler (&cs8900_irq); -} - -void cs8900_detach_interrupt (cs8900_device *cs) -{ - BSP_remove_rtems_irq_handler (&cs8900_irq); -} - -void -BSP_cs8900_attach (unsigned long io_base, unsigned long mem_base, int intrp, - const char* ip, const char* nm, const char* gw) -{ - cs8900_device *cs = &cs8900; - int flags; - struct sockaddr_in address; - struct sockaddr_in netmask; - struct sockaddr_in broadcast; - struct sockaddr_in gateway; - int cmd; - - printf ("cso: io=0x%0lx mem=0 irq=%d\n", io_base, intrp); - - memset (cs, 0, sizeof (cs8900)); - - cs->dev = 0; - cs->rx_queue_size = 30; - cs->io_base = io_base; - - if (mem_base) - printf ("cs8900: memory mode is currently not supported.\n"); - - cs->mem_base = 0; - - switch (intrp) - { - case 5: - cs->irq_level = 3; - break; - case 10: - cs->irq_level = 0; - break; - case 11: - cs->irq_level = 1; - break; - case 12: - cs->irq_level = 2; - break; - default: - printf ("cs8900: unsupported IRQ level\n"); - return; - } - - cs8900_irq.name = intrp; - - /* - * Get the MAC adress from the CS8900. - */ - - cs8900_get_mac_addr (cs, cs->mac_address); - - /* - * Setup the BSD interface configure structure. - */ - - cs8900_ifconfig.drv_ctrl = cs; - cs8900_ifconfig.hardware_address = cs->mac_address; - - printf ("CS8900 initialisation\n"); - - rtems_bsdnet_attach (&cs8900_ifconfig); - - /* - * Configure the interface using the boot configuration. - */ - - flags = IFF_UP; - if (rtems_bsdnet_ifconfig (cs8900_ifconfig.name, - SIOCSIFFLAGS, - &flags) < 0) - { - printf ("error: can't bring up %s: %s\n", - cs8900_ifconfig.name, strerror (errno)); - return; - } - - if (ip && strlen (ip) && nm && strlen (nm)) - { - printf ("%s: addr: %s netmask: %s gateway: %s\n", - cs8900_ifconfig.name, ip, nm, gw ? gw : "none"); - - memset (&netmask, '\0', sizeof netmask); - netmask.sin_len = sizeof netmask; - netmask.sin_family = AF_INET; - - if (!inet_aton (nm, &netmask.sin_addr)) - { - printf ("error: cannot parse the network mask: %s\n", nm); - return; - } - - memset (&address, '\0', sizeof address); - address.sin_len = sizeof address; - address.sin_family = AF_INET; - - if (!inet_aton (ip, &address.sin_addr)) - { - printf ("error: cannot parse the ip address: %s\n", ip); - return; - } - - if (rtems_bsdnet_ifconfig (cs8900_ifconfig.name, - SIOCSIFNETMASK, - &netmask) < 0) - { - printf ("error: can't set %s netmask: %s\n", - cs8900_ifconfig.name, strerror (errno)); - return; - } - - if (rtems_bsdnet_ifconfig (cs8900_ifconfig.name, - SIOCSIFADDR, - &address) < 0) - { - printf ("error: can't set %s address: %s\n", - cs8900_ifconfig.name, strerror (errno)); - return; - } - - memset (&broadcast, '\0', sizeof broadcast); - broadcast.sin_len = sizeof broadcast; - broadcast.sin_family = AF_INET; - broadcast.sin_addr.s_addr = - (address.sin_addr.s_addr & netmask.sin_addr.s_addr) | ~netmask.sin_addr.s_addr; - - if (rtems_bsdnet_ifconfig (cs8900_ifconfig.name, - SIOCSIFBRDADDR, - &broadcast) < 0) - { - printf ("error: can't set %s broadcast address: %s\n", - cs8900_ifconfig.name, strerror (errno)); - return; - } - - if (gw && strlen (gw)) - { - address.sin_addr.s_addr = INADDR_ANY; - netmask.sin_addr.s_addr = INADDR_ANY; - memset (&gateway, '\0', sizeof gateway); - gateway.sin_len = sizeof gateway; - gateway.sin_family = AF_INET; - - if (!inet_aton (gw, &gateway.sin_addr)) - printf ("warning: cannot parse the gateway address: %s\n", ip); - else - { - if (rtems_bsdnet_rtrequest (RTM_ADD, - (struct sockaddr *) &address, - (struct sockaddr *) &gateway, - (struct sockaddr *) &netmask, - (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL) < 0) - printf ("error: can't set default route: %s\n", strerror (errno)); - } - } - } - else - { - rtems_bsdnet_do_bootp_and_rootfs (); - } - - for (cmd = 0; - cmd < sizeof (rtems_bsdnet_commands) / sizeof (rtems_monitor_command_entry_t); - cmd++) - rtems_monitor_insert_cmd (&rtems_bsdnet_commands[cmd]); -} diff --git a/c/src/libchip/network/cs8900.h.bsp b/c/src/libchip/network/cs8900.h.bsp deleted file mode 100644 index 65ce0d2e93..0000000000 --- a/c/src/libchip/network/cs8900.h.bsp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * RTEMS CS8900 Driver Setup for the DIMM-PC/i386 made by Kontron. - * - * Port to the DIMM PC copyright (c) 2004 Angelo Fraietta - * This project has been assisted by the Commonwealth Government - * through the Australia Council, its arts funding and advisory body. - * - * Port performed by Chris Johns, Cybertec Pty Ltd, Jan 2004. - * Based on the Cybertec CS8900 driver setup for the SFP-101. - */ - -#if !defined (__BSP_CS8900_H__) -#define __BSP_CS8900_H__ - -/** - * BSP CS8900 Device initialisation and interface attach. - * - * @param io_base The I/O base address of the device. - * - * @param mem_base The memory base address. Currently not used. - * - * @param intrp The ISA bus IRQ. These are currently limited to - * 5, 10, 11, and 12 as documented in the CS8900 - * manual. - * - * @param ip IP address in ASCII. For example 10.10.10.10. If the - * pointer is a NULL (0) the interface will BOOTP. - * - * @param nm Network Mask in ASCII. For example 10.10.10.255. - * - * @param gw Address of the gateway machine. For example - * 10.10.10.1. - */ - -void BSP_cs8900_attach (unsigned long io_base, unsigned long mem_base, int intrp, - const char* ip, const char* nm, const char* gw); - -#endif diff --git a/c/src/libchip/network/dec21140.c b/c/src/libchip/network/dec21140.c deleted file mode 100644 index 6fd3d5b33f..0000000000 --- a/c/src/libchip/network/dec21140.c +++ /dev/null @@ -1,1112 +0,0 @@ -/* - * RTEMS driver for TULIP based Ethernet Controller - * - * Copyright (C) 1999 Emmanuel Raguet. raguet@crf.canon.fr - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - * - * ------------------------------------------------------------------------ - * [22.05.2000,StWi/CWA] added support for the DEC/Intel 21143 chip - * - * Thanks go to Andrew Klossner who provided the vital information about the - * Intel 21143 chip. FWIW: The 21143 additions to this driver were initially - * tested with a PC386 BSP using a Kingston KNE100TX with 21143PD chip. - * - * The driver will automatically detect whether there is a 21140 or 21143 - * network card in the system and activate support accordingly. It will - * look for the 21140 first. If the 21140 is not found the driver will - * look for the 21143. - * - * 2004-11-10, Joel/Richard - 21143 support works on MVME2100. - * ------------------------------------------------------------------------ - * - * 2003-03-13, Greg Menke, gregory.menke@gsfc.nasa.gov - * - * Added support for up to 8 units (which is an arbitrary limit now), - * consolidating their support into a single pair of rx/tx daemons and a - * single ISR for all vectors servicing the DEC units. The driver now - * simply uses whatever INTERRUPT_LINE the card supplies, requiring it - * be configured either by the boot monitor or bspstart() hackery. - * Tested on a MCP750 PPC based system with 2 DEC21140 boards. - * - * Also fixed a few bugs related to board configuration, start and stop. - * - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include -#include - -/* - * This driver only supports architectures with the new style - * exception processing. The following checks try to keep this - * from being compiled on systems which can't support this driver. - */ - -#if defined(__i386__) - #define DEC21140_SUPPORTED - #define PCI_DRAM_OFFSET 0 -#endif -#if defined(__PPC__) - #define DEC21140_SUPPORTED -#endif - -#include - -#if !defined(PCI_DRAM_OFFSET) - #undef DEC21140_SUPPORTED -#endif - -#if defined(DEC21140_SUPPORTED) -#include - -#if defined(__PPC__) -#include -#include -#endif - -#if defined(__i386__) -#include -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include - -#ifdef malloc -#undef malloc -#endif -#ifdef free -#undef free -#endif - -#define DEC_DEBUG - -/* note: the 21143 isn't really a DEC, it's an Intel chip */ -#define PCI_VENDOR_ID_DEC 0x1011 -#define PCI_DEVICE_ID_DEC_21140 0x0009 -#define PCI_DEVICE_ID_DEC_21143 0x0019 - -#define DRIVER_PREFIX "dc" - -#define IO_MASK 0x3 -#define MEM_MASK 0xF - -/* command and status registers, 32-bit access, only if IO-ACCESS */ -#define ioCSR0 0x00 /* bus mode register */ -#define ioCSR1 0x08 /* transmit poll demand */ -#define ioCSR2 0x10 /* receive poll demand */ -#define ioCSR3 0x18 /* receive list base address */ -#define ioCSR4 0x20 /* transmit list base address */ -#define ioCSR5 0x28 /* status register */ -#define ioCSR6 0x30 /* operation mode register */ -#define ioCSR7 0x38 /* interrupt mask register */ -#define ioCSR8 0x40 /* missed frame counter */ -#define ioCSR9 0x48 /* Ethernet ROM register */ -#define ioCSR10 0x50 /* reserved */ -#define ioCSR11 0x58 /* full-duplex register */ -#define ioCSR12 0x60 /* SIA status register */ -#define ioCSR13 0x68 -#define ioCSR14 0x70 -#define ioCSR15 0x78 /* SIA general register */ - -/* command and status registers, 32-bit access, only if MEMORY-ACCESS */ -#define memCSR0 0x00 /* bus mode register */ -#define memCSR1 0x02 /* transmit poll demand */ -#define memCSR2 0x04 /* receive poll demand */ -#define memCSR3 0x06 /* receive list base address */ -#define memCSR4 0x08 /* transmit list base address */ -#define memCSR5 0x0A /* status register */ -#define memCSR6 0x0C /* operation mode register */ -#define memCSR7 0x0E /* interrupt mask register */ -#define memCSR8 0x10 /* missed frame counter */ -#define memCSR9 0x12 /* Ethernet ROM register */ -#define memCSR10 0x14 /* reserved */ -#define memCSR11 0x16 /* full-duplex register */ -#define memCSR12 0x18 /* SIA status register */ -#define memCSR13 0x1A -#define memCSR14 0x1C -#define memCSR15 0x1E /* SIA general register */ - -#define DEC_REGISTER_SIZE 0x100 /* to reserve virtual memory */ - - - - -#define RESET_CHIP 0x00000001 -#if defined(__PPC__) -#define CSR0_MODE 0x0030e002 /* 01b08000 */ -#else -#define CSR0_MODE 0x0020e002 /* 01b08000 */ -#endif -#define ROM_ADDRESS 0x00004800 -#define CSR6_INIT 0x022cc000 /* 022c0000 020c0000 */ -#define CSR6_TX 0x00002000 -#define CSR6_TXRX 0x00002002 -#define IT_SETUP 0x000100c0 /* 000100e0 */ -#define CLEAR_IT 0xFFFFFFFF -#define NO_IT 0x00000000 - -/* message descriptor entry */ -struct MD { - /* used by hardware */ - volatile uint32_t status; - volatile uint32_t counts; - volatile uint32_t buf1, buf2; - /* used by software */ - volatile struct mbuf *m; - volatile struct MD *next; -} __attribute__ ((packed)); - -/* -** These buffers allocated for each unit, so ensure -** -** rtems_bsdnet_config.mbuf_bytecount -** rtems_bsdnet_config.mbuf_cluster_bytecount -** -** are adequately sized to provide enough clusters and mbufs for all the -** units. The default bsdnet configuration is sufficient for one dec -** unit, but will be nearing exhaustion with 2 or more. Although a -** little expensive in memory, the following configuration should -** eliminate all mbuf/cluster issues; -** -** rtems_bsdnet_config.mbuf_bytecount = 128*1024; -** rtems_bsdnet_config.mbuf_cluster_bytecount = 256*1024; -*/ - -#define NRXBUFS 16 /* number of receive buffers */ -#define NTXBUFS 16 /* number of transmit buffers */ - -/* - * Number of DEC boards supported by this driver - */ -#define NDECDRIVER 8 - -/* - * Receive buffer size -- Allow for a full ethernet packet including CRC - */ -#define RBUF_SIZE 1536 - -#define ET_MINLEN 60 /* minimum message length */ - -/* -** Events, one per unit. The event is sent to the rx task from the isr -** or from the stack to the tx task whenever a unit needs service. The -** rx/tx tasks identify the requesting unit(s) by their particular -** events so only requesting units are serviced. -*/ - -static rtems_event_set unit_signals[NDECDRIVER]= { RTEMS_EVENT_1, - RTEMS_EVENT_2, - RTEMS_EVENT_3, - RTEMS_EVENT_4, - RTEMS_EVENT_5, - RTEMS_EVENT_6, - RTEMS_EVENT_7, - RTEMS_EVENT_8 }; - -#if defined(__PPC__) -#define phys_to_bus(address) ((unsigned int)((address)) + PCI_DRAM_OFFSET) -#define bus_to_phys(address) ((unsigned int)((address)) - PCI_DRAM_OFFSET) -#define CPU_CACHE_ALIGNMENT_FOR_BUFFER PPC_CACHE_ALIGNMENT -#else -extern void Wait_X_ms( unsigned int timeToWait ); -#define phys_to_bus(address) ((unsigned int) ((address))) -#define bus_to_phys(address) ((unsigned int) ((address))) -#define rtems_bsp_delay_in_bus_cycles(cycle) Wait_X_ms( cycle/100 ) -#define CPU_CACHE_ALIGNMENT_FOR_BUFFER PG_SIZE -#endif - -#if (MCLBYTES < RBUF_SIZE) -# error "Driver must have MCLBYTES > RBUF_SIZE" -#endif - -/* - * Per-device data - */ -struct dec21140_softc { - - struct arpcom arpcom; - - rtems_irq_connect_data irqInfo; - rtems_event_set ioevent; - - int numRxbuffers, numTxbuffers; - - volatile struct MD *MDbase; - volatile struct MD *nextRxMD; - volatile unsigned char *bufferBase; - int acceptBroadcast; - - volatile struct MD *TxMD; - volatile struct MD *SentTxMD; - int PendingTxCount; - int TxSuspended; - - unsigned int port; - volatile uint32_t *base; - - /* - * Statistics - */ - unsigned long rxInterrupts; - unsigned long rxNotFirst; - unsigned long rxNotLast; - unsigned long rxGiant; - unsigned long rxNonOctet; - unsigned long rxRunt; - unsigned long rxBadCRC; - unsigned long rxOverrun; - unsigned long rxCollision; - - unsigned long txInterrupts; - unsigned long txDeferred; - unsigned long txHeartbeat; - unsigned long txLateCollision; - unsigned long txRetryLimit; - unsigned long txUnderrun; - unsigned long txLostCarrier; - unsigned long txRawWait; -}; - -static struct dec21140_softc dec21140_softc[NDECDRIVER]; -static rtems_id rxDaemonTid; -static rtems_id txDaemonTid; - -void dec21140_txDaemon (void *arg); - -/* - * This routine reads a word (16 bits) from the serial EEPROM. - */ -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */ -#define EE_CS 0x01 /* EEPROM chip select. */ -#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x01 -#define EE_WRITE_1 0x05 -#define EE_DATA_READ 0x08 /* EEPROM chip data out. */ -#define EE_ENB (0x4800 | EE_CS) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5 << 6) -#define EE_READ_CMD (6 << 6) -#define EE_ERASE_CMD (7 << 6) - -static int eeget16(volatile uint32_t *ioaddr, int location) -{ - int i; - unsigned short retval = 0; - int read_cmd = location | EE_READ_CMD; - - st_le32(ioaddr, EE_ENB & ~EE_CS); - st_le32(ioaddr, EE_ENB); - - /* Shift the read command bits out. */ - for (i = 10; i >= 0; i--) { - short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - st_le32(ioaddr, EE_ENB | dataval); - rtems_bsp_delay_in_bus_cycles(200); - st_le32(ioaddr, EE_ENB | dataval | EE_SHIFT_CLK); - rtems_bsp_delay_in_bus_cycles(200); - st_le32(ioaddr, EE_ENB | dataval); /* Finish EEPROM a clock tick. */ - rtems_bsp_delay_in_bus_cycles(200); - } - st_le32(ioaddr, EE_ENB); - - for (i = 16; i > 0; i--) { - st_le32(ioaddr, EE_ENB | EE_SHIFT_CLK); - rtems_bsp_delay_in_bus_cycles(200); - retval = (retval << 1) | ((ld_le32(ioaddr) & EE_DATA_READ) ? 1 : 0); - st_le32(ioaddr, EE_ENB); - rtems_bsp_delay_in_bus_cycles(200); - } - - /* Terminate the EEPROM access. */ - st_le32(ioaddr, EE_ENB & ~EE_CS); - return ( ((retval<<8)&0xff00) | ((retval>>8)&0xff) ); -} - -static void no_op(const rtems_irq_connect_data* irq) -{ - return; -} - -/* - * DEC21140 interrupt handler - */ -static rtems_isr -dec21140Enet_interrupt_handler ( struct dec21140_softc *sc ) -{ - volatile uint32_t *tbase; - uint32_t status; - - tbase = (uint32_t*)(sc->base); - - /* - * Read status - */ - status = ld_le32(tbase+memCSR5); - st_le32((tbase+memCSR5), status); - - /* - * Frame received? - */ - if( status & 0x000000c0 ) - { - sc->rxInterrupts++; - rtems_bsdnet_event_send(rxDaemonTid, sc->ioevent); - } -} - -static rtems_isr -dec21140Enet_interrupt_handler_entry(void) -{ - int i; - - /* - ** Check all the initialized dec units for interrupt service - */ - - for(i=0; i< NDECDRIVER; i++ ) - { - if( dec21140_softc[i].base ) - dec21140Enet_interrupt_handler( &dec21140_softc[i] ); - } -} - -/* - * Initialize the ethernet hardware - */ -static void -dec21140Enet_initialize_hardware (struct dec21140_softc *sc) -{ - int i,st; - volatile uint32_t *tbase; - volatile unsigned char *cp, *setup_frm, *eaddrs; - volatile unsigned char *buffer; - volatile struct MD *rmd; - - -#ifdef DEC_DEBUG - printk("dec2114x : %02x:%02x:%02x:%02x:%02x:%02x name '%s%d', io %x, mem %x, int %d\n", - sc->arpcom.ac_enaddr[0], sc->arpcom.ac_enaddr[1], - sc->arpcom.ac_enaddr[2], sc->arpcom.ac_enaddr[3], - sc->arpcom.ac_enaddr[4], sc->arpcom.ac_enaddr[5], - sc->arpcom.ac_if.if_name, sc->arpcom.ac_if.if_unit, - sc->port, (unsigned) sc->base, sc->irqInfo.name ); -#endif - - tbase = sc->base; - - /* - * WARNING : First write in CSR6 - * Then Reset the chip ( 1 in CSR0) - */ - st_le32( (tbase+memCSR6), CSR6_INIT); - st_le32( (tbase+memCSR0), RESET_CHIP); - rtems_bsp_delay_in_bus_cycles(200); - - st_le32( (tbase+memCSR7), NO_IT); - - /* - * Init CSR0 - */ - st_le32( (tbase+memCSR0), CSR0_MODE); - - /* - * Init RX ring - */ - cp = (volatile unsigned char *)malloc(((sc->numRxbuffers+sc->numTxbuffers)*sizeof(struct MD)) - + (sc->numTxbuffers*RBUF_SIZE) - + CPU_CACHE_ALIGNMENT_FOR_BUFFER); - sc->bufferBase = cp; - cp += (CPU_CACHE_ALIGNMENT_FOR_BUFFER - (int)cp) & (CPU_CACHE_ALIGNMENT_FOR_BUFFER - 1); -#if defined(__i386__) -#ifdef PCI_BRIDGE_DOES_NOT_ENSURE_CACHE_COHERENCY_FOR_DMA - if (_CPU_is_paging_enabled()) - _CPU_change_memory_mapping_attribute - (NULL, cp, - ((sc->numRxbuffers+sc->numTxbuffers)*sizeof(struct MD)) - + (sc->numTxbuffers*RBUF_SIZE), - PTE_CACHE_DISABLE | PTE_WRITABLE); -#endif -#endif - rmd = (volatile struct MD*)cp; - sc->MDbase = rmd; - sc->nextRxMD = sc->MDbase; - - buffer = cp + ((sc->numRxbuffers+sc->numTxbuffers)*sizeof(struct MD)); - st_le32( (tbase+memCSR3), (long)(phys_to_bus((long)(sc->MDbase)))); - - for (i=0 ; inumRxbuffers; i++) - { - struct mbuf *m; - - /* allocate an mbuf for each receive descriptor */ - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - m->m_pkthdr.rcvif = &sc->arpcom.ac_if; - rmd->m = m; - - rmd->buf2 = phys_to_bus(rmd+1); - rmd->buf1 = phys_to_bus(mtod(m, void *)); - rmd->status = 0x80000000; - rmd->counts = 0xfdc00000 | (RBUF_SIZE); - rmd->next = rmd+1; - rmd++; - } - /* - * mark last RX buffer. - */ - sc->MDbase [sc->numRxbuffers-1].buf2 = 0; - sc->MDbase [sc->numRxbuffers-1].counts = 0xfec00000 | (RBUF_SIZE); - sc->MDbase [sc->numRxbuffers-1].next = sc->MDbase; - - - - /* - * Init TX ring - */ - st_le32( (tbase+memCSR4), (long)(phys_to_bus((long)(rmd))) ); - for (i=0 ; inumTxbuffers; i++){ - (rmd+i)->buf2 = phys_to_bus(rmd+i+1); - (rmd+i)->buf1 = phys_to_bus(buffer + (i*RBUF_SIZE)); - (rmd+i)->counts = 0x01000000; - (rmd+i)->status = 0x0; - (rmd+i)->next = rmd+i+1; - (rmd+i)->m = 0; - } - - /* - * mark last TX buffer. - */ - (rmd+sc->numTxbuffers-1)->buf2 = phys_to_bus(rmd); - (rmd+sc->numTxbuffers-1)->next = rmd; - - - /* - * Build setup frame - */ - setup_frm = (volatile unsigned char *)(bus_to_phys(rmd->buf1)); - eaddrs = (unsigned char *)(sc->arpcom.ac_enaddr); - /* Fill the buffer with our physical address. */ - for (i = 1; i < 16; i++) { - *setup_frm++ = eaddrs[0]; - *setup_frm++ = eaddrs[1]; - *setup_frm++ = eaddrs[0]; - *setup_frm++ = eaddrs[1]; - *setup_frm++ = eaddrs[2]; - *setup_frm++ = eaddrs[3]; - *setup_frm++ = eaddrs[2]; - *setup_frm++ = eaddrs[3]; - *setup_frm++ = eaddrs[4]; - *setup_frm++ = eaddrs[5]; - *setup_frm++ = eaddrs[4]; - *setup_frm++ = eaddrs[5]; - } - - /* Add the broadcast address when doing perfect filtering */ - memset((void*) setup_frm, 0xff, 12); - rmd->counts = 0x09000000 | 192 ; - rmd->status = 0x80000000; - st_le32( (tbase+memCSR6), CSR6_INIT | CSR6_TX); - st_le32( (tbase+memCSR1), 1); - - while (rmd->status != 0x7fffffff); - rmd->counts = 0x01000000; - - sc->TxMD = rmd+1; - - sc->irqInfo.hdl = (rtems_irq_hdl)dec21140Enet_interrupt_handler_entry; - sc->irqInfo.on = no_op; - sc->irqInfo.off = no_op; - sc->irqInfo.isOn = NULL; - -#ifdef DEC_DEBUG - printk( "dec2114x: Installing IRQ %d\n", sc->irqInfo.name ); -#endif -#ifdef BSP_SHARED_HANDLER_SUPPORT - st = BSP_install_rtems_shared_irq_handler( &sc->irqInfo ); -#else - st = BSP_install_rtems_irq_handler( &sc->irqInfo ); -#endif - - if (!st) - rtems_panic ("dec2114x : Interrupt name %d already in use\n", sc->irqInfo.name ); -} - -static void -dec21140_rxDaemon (void *arg) -{ - volatile struct MD *rmd; - struct dec21140_softc *sc; - struct ifnet *ifp; - struct ether_header *eh; - struct mbuf *m; - unsigned int i,len; - rtems_event_set events; - - for (;;) - { - - rtems_bsdnet_event_receive( RTEMS_ALL_EVENTS, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - - for(i=0; i< NDECDRIVER; i++ ) - { - sc = &dec21140_softc[i]; - if( sc->base ) - { - if( events & sc->ioevent ) - { - ifp = &sc->arpcom.ac_if; - rmd = sc->nextRxMD; - - /* - ** Read off all the packets we've received on this unit - */ - while((rmd->status & 0x80000000) == 0) - { - /* printk("unit %i rx\n", ifp->if_unit ); */ - - /* pass on the packet in the mbuf */ - len = (rmd->status >> 16) & 0x7ff; - m = (struct mbuf *)(rmd->m); - m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header); - eh = mtod (m, struct ether_header *); - m->m_data += sizeof(struct ether_header); - ether_input (ifp, eh, m); - - /* get a new mbuf for the 21140 */ - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - rmd->m = m; - rmd->buf1 = phys_to_bus(mtod(m, void *)); - - /* mark the descriptor as ready to receive */ - rmd->status = 0x80000000; - - rmd=rmd->next; - } - - sc->nextRxMD = rmd; - } - } - } - - } -} - -static void -sendpacket (struct ifnet *ifp, struct mbuf *m) -{ - struct dec21140_softc *dp = ifp->if_softc; - volatile struct MD *tmd; - volatile unsigned char *temp; - struct mbuf *n; - unsigned int len; - volatile uint32_t *tbase; - - tbase = dp->base; - /* - * Waiting for Transmitter ready - */ - - tmd = dp->TxMD; - n = m; - - while ((tmd->status & 0x80000000) != 0) - { - tmd=tmd->next; - } - - len = 0; - temp = (volatile unsigned char *)(bus_to_phys(tmd->buf1)); - - for (;;) - { - len += m->m_len; - memcpy((void*) temp, (char *)m->m_data, m->m_len); - temp += m->m_len ; - if ((m = m->m_next) == NULL) - break; - } - - if (len < ET_MINLEN) len = ET_MINLEN; - tmd->counts = 0xe1000000 | (len & 0x7ff); - tmd->status = 0x80000000; - - st_le32( (tbase+memCSR1), 0x1); - - m_freem(n); - - dp->TxMD = tmd->next; -} - -/* - * Driver transmit daemon - */ -void -dec21140_txDaemon (void *arg) -{ - struct dec21140_softc *sc; - struct ifnet *ifp; - struct mbuf *m; - int i; - rtems_event_set events; - - for (;;) - { - /* - * Wait for packets bound for any of the dec units - */ - rtems_bsdnet_event_receive( RTEMS_ALL_EVENTS, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, &events); - - for(i=0; i< NDECDRIVER; i++ ) - { - sc = &dec21140_softc[i]; - if( sc->base ) - { - if( events & sc->ioevent ) - { - ifp = &sc->arpcom.ac_if; - - /* - * Send packets till queue is empty - */ - for(;;) - { - IF_DEQUEUE(&ifp->if_snd, m); - if( !m ) break; - /* printk("unit %i tx\n", ifp->if_unit ); */ - sendpacket (ifp, m); - } - - ifp->if_flags &= ~IFF_OACTIVE; - } - } - } - - } -} - -static void -dec21140_start (struct ifnet *ifp) -{ - struct dec21140_softc *sc = ifp->if_softc; - rtems_bsdnet_event_send( txDaemonTid, sc->ioevent ); - ifp->if_flags |= IFF_OACTIVE; -} - -/* - * Initialize and start the device - */ -static void -dec21140_init (void *arg) -{ - struct dec21140_softc *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - volatile uint32_t *tbase; - - /* - * Set up DEC21140 hardware if its not already been done - */ - if( !sc->irqInfo.hdl ) - { - dec21140Enet_initialize_hardware (sc); - } - - /* - * Enable RX and TX - */ - tbase = sc->base; - st_le32( (tbase+memCSR5), IT_SETUP); - st_le32( (tbase+memCSR7), IT_SETUP); - st_le32( (tbase+memCSR6), CSR6_INIT | CSR6_TXRX); - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; -} - -/* - * Stop the device - */ -static void -dec21140_stop (struct dec21140_softc *sc) -{ - volatile uint32_t *tbase; - struct ifnet *ifp = &sc->arpcom.ac_if; - - ifp->if_flags &= ~IFF_RUNNING; - - /* - * Stop the transmitter - */ - tbase = sc->base; - st_le32( (tbase+memCSR7), NO_IT); - st_le32( (tbase+memCSR6), CSR6_INIT); - - /* free((void*)sc->bufferBase); */ -} - -/* - * Show interface statistics - */ -static void -dec21140_stats (struct dec21140_softc *sc) -{ - printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); - printf (" Not First:%-8lu", sc->rxNotFirst); - printf (" Not Last:%-8lu\n", sc->rxNotLast); - printf (" Giant:%-8lu", sc->rxGiant); - printf (" Runt:%-8lu", sc->rxRunt); - printf (" Non-octet:%-8lu\n", sc->rxNonOctet); - printf (" Bad CRC:%-8lu", sc->rxBadCRC); - printf (" Overrun:%-8lu", sc->rxOverrun); - printf (" Collision:%-8lu\n", sc->rxCollision); - - printf (" Tx Interrupts:%-8lu", sc->txInterrupts); - printf (" Deferred:%-8lu", sc->txDeferred); - printf (" Missed Hearbeat:%-8lu\n", sc->txHeartbeat); - printf (" No Carrier:%-8lu", sc->txLostCarrier); - printf ("Retransmit Limit:%-8lu", sc->txRetryLimit); - printf (" Late Collision:%-8lu\n", sc->txLateCollision); - printf (" Underrun:%-8lu", sc->txUnderrun); - printf (" Raw output wait:%-8lu\n", sc->txRawWait); -} - -/* - * Driver ioctl handler - */ -static int -dec21140_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - struct dec21140_softc *sc = ifp->if_softc; - int error = 0; - - switch (command) { - case SIOCGIFADDR: - case SIOCSIFADDR: - ether_ioctl (ifp, command, data); - break; - - case SIOCSIFFLAGS: - switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { - case IFF_RUNNING: - dec21140_stop (sc); - break; - - case IFF_UP: - dec21140_init (sc); - break; - - case IFF_UP | IFF_RUNNING: - dec21140_stop (sc); - dec21140_init (sc); - break; - - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - dec21140_stats (sc); - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } - - return error; -} - - -/* -int iftap(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m ) -{ - int i; - - if( ifp->if_unit == 1 ) return 0; - - printf("unit %i, src ", ifp->if_unit ); - for(i=0; i< ETHER_ADDR_LEN; i++) printf("%02x", (char) eh->ether_shost[i] ); - printf(" dest "); - for(i=0; i< ETHER_ADDR_LEN; i++) printf("%02x", (char) eh->ether_dhost[i] ); - printf("\n"); - - return -1; -} -*/ - -/* - * Attach an DEC21140 driver to the system - */ -int -rtems_dec21140_driver_attach (struct rtems_bsdnet_ifconfig *config, int attach) -{ - struct dec21140_softc *sc; - struct ifnet *ifp; - char *unitName; - int unitNumber; - int mtu; - unsigned char cvalue; -#if defined(__i386__) - uint32_t value; - uint8_t interrupt; -#endif - int pbus, pdev, pfun; -#if defined(__PPC__) - int tmp; - uint32_t lvalue; -#endif - - /* - * Get the instance number for the board we're going to configure - * from the user. - */ - if( (unitNumber = rtems_bsdnet_parse_driver_name(config, &unitName)) == -1 ) - { - return 0; - } - if( strcmp(unitName, DRIVER_PREFIX) ) - { - printk("dec2114x : unit name '%s' not %s\n", unitName, DRIVER_PREFIX ); - return 0; - } - - /* - * Find the board - */ - if ( pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21140, - unitNumber-1, &pbus, &pdev, &pfun) == -1 ) { - if ( pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21143, - unitNumber-1, &pbus, &pdev, &pfun) != -1 ) { - - /* the 21143 chip must be enabled before it can be accessed */ -#if defined(__i386__) - pci_write_config_dword(pbus, pdev, pfun, 0x40, 0 ); -#else - pci_write_config_dword(pbus, pdev, pfun, 0x40, PCI_DEVICE_ID_DEC_21143); -#endif - - } else { - printk("dec2114x : device '%s' not found on PCI bus\n", config->name ); - return 0; - } - } - -#ifdef DEC_DEBUG - else { - printk("dec21140 : found device '%s', bus 0x%02x, dev 0x%02x, func 0x%02x\n", - config->name, pbus, pdev, pfun); - } -#endif - - if ((unitNumber < 1) || (unitNumber > NDECDRIVER)) - { - printk("dec2114x : unit %i is invalid, must be (1 <= n <= %d)\n", - unitNumber, NDECDRIVER); - return 0; - } - - sc = &dec21140_softc[unitNumber - 1]; - ifp = &sc->arpcom.ac_if; - if (ifp->if_softc != NULL) - { - printk("dec2114x : unit %i already in use.\n", unitNumber ); - return 0; - } - - - /* - ** Get this unit's rx/tx event - */ - sc->ioevent = unit_signals[unitNumber-1]; - - /* - ** Save the buffer counts - */ - sc->numRxbuffers = (config->rbuf_count) ? config->rbuf_count : NRXBUFS; - sc->numTxbuffers = (config->xbuf_count) ? config->xbuf_count : NTXBUFS; - - - /* - * Get card address spaces & retrieve its isr vector - */ -#if defined(__i386__) - - pci_read_config_dword(pbus, pdev, pfun, 16, &value); - sc->port = value & ~IO_MASK; - - pci_read_config_dword(pbus, pdev, pfun, 20, &value); - if (_CPU_is_paging_enabled()) - _CPU_map_phys_address((void **) &(sc->base), - (void *)(value & ~MEM_MASK), - DEC_REGISTER_SIZE , - PTE_CACHE_DISABLE | PTE_WRITABLE); - else - sc->base = (uint32_t *)(value & ~MEM_MASK); - - pci_read_config_byte(pbus, pdev, pfun, 60, &interrupt); - cvalue = interrupt; -#endif -#if defined(__PPC__) - (void)pci_read_config_dword(pbus, - pdev, - pfun, - PCI_BASE_ADDRESS_0, - &lvalue); - - sc->port = lvalue & (unsigned int)(~IO_MASK); - - (void)pci_read_config_dword(pbus, - pdev, - pfun, - PCI_BASE_ADDRESS_1, - &lvalue); - - tmp = (unsigned int)(lvalue & (unsigned int)(~MEM_MASK)) - + (unsigned int)PCI_MEM_BASE; - - sc->base = (uint32_t*)(tmp); - - pci_read_config_byte(pbus, - pdev, - pfun, - PCI_INTERRUPT_LINE, - &cvalue); - -#endif - - /* - ** Prep the board - */ - - pci_write_config_word(pbus, pdev, pfun, - PCI_COMMAND, - (uint16_t) ( PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER ) ); - - /* - ** Store the interrupt name, we'll use it later when we initialize - ** the board. - */ - memset(&sc->irqInfo,0,sizeof(rtems_irq_connect_data)); - sc->irqInfo.name = cvalue; - - -#ifdef DEC_DEBUG - printk("dec2114x : unit %d base address %p.\n", unitNumber, sc->base); -#endif - - - /* - ** Setup ethernet address - */ - if (config->hardware_address) { - memcpy (sc->arpcom.ac_enaddr, config->hardware_address, - ETHER_ADDR_LEN); - } - else { - union {char c[64]; unsigned short s[32];} rombuf; - int i; - - for (i=0; i<32; i++){ - rombuf.s[i] = eeget16( sc->base + memCSR9, i); - } -#if defined(__i386__) - for (i=0 ; i<(ETHER_ADDR_LEN/2); i++){ - sc->arpcom.ac_enaddr[2*i] = rombuf.c[20+2*i+1]; - sc->arpcom.ac_enaddr[2*i+1] = rombuf.c[20+2*i]; - } -#endif -#if defined(__PPC__) - memcpy (sc->arpcom.ac_enaddr, rombuf.c+20, ETHER_ADDR_LEN); -#endif - } - - if (config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - - sc->acceptBroadcast = !config->ignore_broadcast; - - /* - * Set up network interface values - */ - -/* ifp->if_tap = iftap; */ - - ifp->if_softc = sc; - ifp->if_unit = unitNumber; - ifp->if_name = unitName; - ifp->if_mtu = mtu; - ifp->if_init = dec21140_init; - ifp->if_ioctl = dec21140_ioctl; - ifp->if_start = dec21140_start; - ifp->if_output = ether_output; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; - if (ifp->if_snd.ifq_maxlen == 0) - ifp->if_snd.ifq_maxlen = ifqmaxlen; - - /* - * Attach the interface - */ - if_attach (ifp); - ether_ifattach (ifp); - -#ifdef DEC_DEBUG - printk( "dec2114x : driver attached\n" ); -#endif - - /* - * Start driver tasks if this is the first dec unit initialized - */ - if (txDaemonTid == 0) - { - rxDaemonTid = rtems_bsdnet_newproc( "DCrx", 4096, - dec21140_rxDaemon, NULL); - - txDaemonTid = rtems_bsdnet_newproc( "DCtx", 4096, - dec21140_txDaemon, NULL); -#ifdef DEC_DEBUG - printk( "dec2114x : driver tasks created\n" ); -#endif - } - - return 1; -}; - -#endif /* DEC21140_SUPPORTED */ diff --git a/c/src/libchip/network/elnk.c b/c/src/libchip/network/elnk.c deleted file mode 100644 index 29adbe9c21..0000000000 --- a/c/src/libchip/network/elnk.c +++ /dev/null @@ -1,3553 +0,0 @@ -/* - * RTEMS driver for Etherlink based Ethernet Controllers - * - * Copyright (C) 2003, Gregory Menke, NASA/GSFC - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - * - * elnk.c - * - * - */ - - -/* - * Portions of this driver are taken from the Freebsd if_xl.c driver, - * version "1.133 2003/03/19 01:48:14" and are covered by the license - * text included below that was taken verbatim from the original file. - * More particularly, all structures, variables, and #defines prefixed - * with XL_ or xl_, along with their associated comments were taken - * directly from the Freebsd driver and modified as required to suit the - * purposes of this one. Additionally, much of the device setup & - * manipulation logic was also copied and modified to suit. All types - * and functions beginning with elnk are either my own creations or were - * adapted from other RTEMS components, and regardless, are subject to - * the standard OAR licensing terms given in the comments at the top of - * this file. - * - * Greg Menke, 6/11/2003 - */ - - /* - * Copyright (c) 1997, 1998, 1999 - * Bill Paul . All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include - -/* - * This driver only supports architectures with the new style - * exception processing. The following checks try to keep this - * from being compiled on systems which can't support this driver. - */ - -#if defined(__i386__) -#define ELNK_SUPPORTED - #define PCI_DRAM_OFFSET 0 -#endif - -#if defined(__PPC__) -#define ELNK_SUPPORTED -#endif - -#include - -#if !defined(PCI_DRAM_OFFSET) - #undef ELNK_SUPPORTED -#endif - -/* #undef ELNK_SUPPORTED */ - - -#if defined(ELNK_SUPPORTED) -#include - -#if defined(__PPC__) -#include -#include -#endif - -#if defined(__i386__) -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#if defined(__i386__) -#define IO_MASK 0x3 -#define MEM_MASK 0xF -#endif - -#ifdef malloc -#undef malloc -#endif -#ifdef free -#undef free -#endif - -#define ELNK_DEBUG - - -#define DRIVER_PREFIX "elnk" - - - - - -/* -* These buffers allocated for each unit, so ensure -* -* rtems_bsdnet_config.mbuf_bytecount -* rtems_bsdnet_config.mbuf_cluster_bytecount -* -* are adequately sized to provide enough clusters and mbufs for all the -* units. The default bsdnet configuration is sufficient for one unit, -* but will be nearing exhaustion with 2 or more. Although a little -* expensive in memory, the following configuration should eliminate all -* mbuf/cluster issues; -* -* rtems_bsdnet_config.mbuf_bytecount = 128*1024; -* rtems_bsdnet_config.mbuf_cluster_bytecount = 256*1024; -* -* The default size in buffers of the rx & tx rings are given below. -* This driver honors the rtems_bsdnet_ifconfig fields 'rbuf_count' and -* 'xbuf_count', allowing the user to specify something else. -*/ - -#define RX_RING_SIZE 16 /* default number of receive buffers */ -#define TX_RING_SIZE 16 /* default number of transmit buffers */ - - -/* - * Number of boards supported by this driver - */ -#define NUM_UNITS 8 - -/* - * Receive buffer size -- Allow for a full ethernet packet including CRC - */ -#define XL_PACKET_SIZE 1540 - - -/* -** Events, one per unit. The event is sent to the rx task from the isr -** or from the stack to the tx task whenever a unit needs service. The -** rx/tx tasks identify the requesting unit(s) by their particular -** events so only requesting units are serviced. -*/ - -static rtems_event_set unit_signals[NUM_UNITS]= { RTEMS_EVENT_1, - RTEMS_EVENT_2, - RTEMS_EVENT_3, - RTEMS_EVENT_4, - RTEMS_EVENT_5, - RTEMS_EVENT_6, - RTEMS_EVENT_7, - RTEMS_EVENT_8 }; - - - - -#if defined(__PPC__) -#define phys_to_bus(address) ((unsigned int)((address)) + PCI_DRAM_OFFSET) -#define bus_to_phys(address) ((unsigned int)((address)) - PCI_DRAM_OFFSET) -#define CPU_CACHE_ALIGNMENT_FOR_BUFFER PPC_CACHE_ALIGNMENT -#else -extern void Wait_X_ms( unsigned int timeToWait ); -#define phys_to_bus(address) ((unsigned int) ((address))) -#define bus_to_phys(address) ((unsigned int) ((address))) -#define rtems_bsp_delay_in_bus_cycles(cycle) Wait_X_ms( cycle/100 ) -#define CPU_CACHE_ALIGNMENT_FOR_BUFFER PG_SIZE -#endif - -/* the actual duration waited in DELAY is not especially predictable, - * though it will be consistent on a given host. It should not be - * relied upon for specific timing given the vague per-bsp, - * per-architecture implementation of the actual delay function. It - * would probably be helpful to make this more accurate at some point... - */ -#define DELAY(n) rtems_bsp_delay_in_bus_cycles( n*20 ) - - - - -/* - * Register layouts. - */ -#define XL_COMMAND 0x0E -#define XL_STATUS 0x0E - -#define XL_TX_STATUS 0x1B -#define XL_TX_FREE 0x1C -#define XL_DMACTL 0x20 -#define XL_DOWNLIST_PTR 0x24 -#define XL_DOWN_POLL 0x2D /* 3c90xB only */ -#define XL_TX_FREETHRESH 0x2F -#define XL_UPLIST_PTR 0x38 -#define XL_UPLIST_STATUS 0x30 -#define XL_UP_POLL 0x3D /* 3c90xB only */ - -#define XL_PKTSTAT_UP_STALLED 0x00002000 -#define XL_PKTSTAT_UP_ERROR 0x00004000 -#define XL_PKTSTAT_UP_CMPLT 0x00008000 - -#define XL_DMACTL_DN_CMPLT_REQ 0x00000002 -#define XL_DMACTL_DOWN_STALLED 0x00000004 -#define XL_DMACTL_UP_CMPLT 0x00000008 -#define XL_DMACTL_DOWN_CMPLT 0x00000010 -#define XL_DMACTL_UP_RX_EARLY 0x00000020 -#define XL_DMACTL_ARM_COUNTDOWN 0x00000040 -#define XL_DMACTL_DOWN_INPROG 0x00000080 -#define XL_DMACTL_COUNTER_SPEED 0x00000100 -#define XL_DMACTL_DOWNDOWN_MODE 0x00000200 -#define XL_DMACTL_TARGET_ABORT 0x40000000 -#define XL_DMACTL_MASTER_ABORT 0x80000000 - -/* - * Command codes. Some command codes require that we wait for - * the CMD_BUSY flag to clear. Those codes are marked as 'mustwait.' - */ -#define XL_CMD_RESET 0x0000 /* mustwait */ -#define XL_CMD_WINSEL 0x0800 -#define XL_CMD_COAX_START 0x1000 -#define XL_CMD_RX_DISABLE 0x1800 -#define XL_CMD_RX_ENABLE 0x2000 -#define XL_CMD_RX_RESET 0x2800 /* mustwait */ -#define XL_CMD_UP_STALL 0x3000 /* mustwait */ -#define XL_CMD_UP_UNSTALL 0x3001 -#define XL_CMD_DOWN_STALL 0x3002 /* mustwait */ -#define XL_CMD_DOWN_UNSTALL 0x3003 -#define XL_CMD_RX_DISCARD 0x4000 -#define XL_CMD_TX_ENABLE 0x4800 -#define XL_CMD_TX_DISABLE 0x5000 -#define XL_CMD_TX_RESET 0x5800 /* mustwait */ -#define XL_CMD_INTR_FAKE 0x6000 -#define XL_CMD_INTR_ACK 0x6800 -#define XL_CMD_INTR_ENB 0x7000 -#define XL_CMD_STAT_ENB 0x7800 -#define XL_CMD_RX_SET_FILT 0x8000 -#define XL_CMD_RX_SET_THRESH 0x8800 -#define XL_CMD_TX_SET_THRESH 0x9000 -#define XL_CMD_TX_SET_START 0x9800 -#define XL_CMD_DMA_UP 0xA000 -#define XL_CMD_DMA_STOP 0xA001 -#define XL_CMD_STATS_ENABLE 0xA800 -#define XL_CMD_STATS_DISABLE 0xB000 -#define XL_CMD_COAX_STOP 0xB800 - -#define XL_CMD_SET_TX_RECLAIM 0xC000 /* 3c905B only */ -#define XL_CMD_RX_SET_HASH 0xC800 /* 3c905B only */ - -#define XL_HASH_SET 0x0400 -#define XL_HASHFILT_SIZE 256 - -/* - * status codes - * Note that bits 15 to 13 indicate the currently visible register window - * which may be anything from 0 to 7. - */ -#define XL_STAT_INTLATCH 0x0001 /* 0 */ -#define XL_STAT_ADFAIL 0x0002 /* 1 */ -#define XL_STAT_TX_COMPLETE 0x0004 /* 2 */ -#define XL_STAT_TX_AVAIL 0x0008 /* 3 first generation */ -#define XL_STAT_RX_COMPLETE 0x0010 /* 4 */ -#define XL_STAT_RX_EARLY 0x0020 /* 5 */ -#define XL_STAT_INTREQ 0x0040 /* 6 */ -#define XL_STAT_STATSOFLOW 0x0080 /* 7 */ -#define XL_STAT_DMADONE 0x0100 /* 8 first generation */ -#define XL_STAT_LINKSTAT 0x0100 /* 8 3c509B */ -#define XL_STAT_DOWN_COMPLETE 0x0200 /* 9 */ -#define XL_STAT_UP_COMPLETE 0x0400 /* 10 */ -#define XL_STAT_DMABUSY 0x0800 /* 11 first generation */ -#define XL_STAT_CMDBUSY 0x1000 /* 12 */ - -/* - * Interrupts we normally want enabled. - */ -#define XL_INTRS \ - (XL_STAT_UP_COMPLETE | XL_STAT_STATSOFLOW | XL_STAT_ADFAIL| \ - XL_STAT_DOWN_COMPLETE | XL_STAT_TX_COMPLETE | XL_STAT_INTLATCH) - - - -/* - * General constants that are fun to know. - * - * 3Com PCI vendor ID - */ -#define TC_VENDORID 0x10B7 - -/* - * 3Com chip device IDs. - */ -#define TC_DEVICEID_BOOMERANG_10BT 0x9000 -#define TC_DEVICEID_BOOMERANG_10BT_COMBO 0x9001 -#define TC_DEVICEID_BOOMERANG_10_100BT 0x9050 -#define TC_DEVICEID_BOOMERANG_100BT4 0x9051 -#define TC_DEVICEID_KRAKATOA_10BT 0x9004 -#define TC_DEVICEID_KRAKATOA_10BT_COMBO 0x9005 -#define TC_DEVICEID_KRAKATOA_10BT_TPC 0x9006 -#define TC_DEVICEID_CYCLONE_10FL 0x900A -#define TC_DEVICEID_HURRICANE_10_100BT 0x9055 -#define TC_DEVICEID_CYCLONE_10_100BT4 0x9056 -#define TC_DEVICEID_CYCLONE_10_100_COMBO 0x9058 -#define TC_DEVICEID_CYCLONE_10_100FX 0x905A -#define TC_DEVICEID_TORNADO_10_100BT 0x9200 -#define TC_DEVICEID_TORNADO_10_100BT_920B 0x9201 -#define TC_DEVICEID_HURRICANE_10_100BT_SERV 0x9800 -#define TC_DEVICEID_TORNADO_10_100BT_SERV 0x9805 -#define TC_DEVICEID_HURRICANE_SOHO100TX 0x7646 -#define TC_DEVICEID_TORNADO_HOMECONNECT 0x4500 -#define TC_DEVICEID_HURRICANE_555 0x5055 -#define TC_DEVICEID_HURRICANE_556 0x6055 -#define TC_DEVICEID_HURRICANE_556B 0x6056 -#define TC_DEVICEID_HURRICANE_575A 0x5057 -#define TC_DEVICEID_HURRICANE_575B 0x5157 -#define TC_DEVICEID_HURRICANE_575C 0x5257 -#define TC_DEVICEID_HURRICANE_656 0x6560 -#define TC_DEVICEID_HURRICANE_656B 0x6562 -#define TC_DEVICEID_TORNADO_656C 0x6564 - - - -#define XL_RXSTAT_LENMASK 0x00001FFF -#define XL_RXSTAT_UP_ERROR 0x00004000 -#define XL_RXSTAT_UP_CMPLT 0x00008000 -#define XL_RXSTAT_UP_OVERRUN 0x00010000 -#define XL_RXSTAT_RUNT 0x00020000 -#define XL_RXSTAT_ALIGN 0x00040000 -#define XL_RXSTAT_CRC 0x00080000 -#define XL_RXSTAT_OVERSIZE 0x00100000 -#define XL_RXSTAT_DRIBBLE 0x00800000 -#define XL_RXSTAT_UP_OFLOW 0x01000000 -#define XL_RXSTAT_IPCKERR 0x02000000 /* 3c905B only */ -#define XL_RXSTAT_TCPCKERR 0x04000000 /* 3c905B only */ -#define XL_RXSTAT_UDPCKERR 0x08000000 /* 3c905B only */ -#define XL_RXSTAT_BUFEN 0x10000000 /* 3c905B only */ -#define XL_RXSTAT_IPCKOK 0x20000000 /* 3c905B only */ -#define XL_RXSTAT_TCPCOK 0x40000000 /* 3c905B only */ -#define XL_RXSTAT_UDPCKOK 0x80000000 /* 3c905B only */ - -#define XL_TXSTAT_LENMASK 0x00001FFF -#define XL_TXSTAT_CRCDIS 0x00002000 -#define XL_TXSTAT_TX_INTR 0x00008000 -#define XL_TXSTAT_DL_COMPLETE 0x00010000 -#define XL_TXSTAT_IPCKSUM 0x02000000 /* 3c905B only */ -#define XL_TXSTAT_TCPCKSUM 0x04000000 /* 3c905B only */ -#define XL_TXSTAT_UDPCKSUM 0x08000000 /* 3c905B only */ -#define XL_TXSTAT_RND_DEFEAT 0x10000000 /* 3c905B only */ -#define XL_TXSTAT_EMPTY 0x20000000 /* 3c905B only */ -#define XL_TXSTAT_DL_INTR 0x80000000 - - -#define XL_FLAG_FUNCREG 0x0001 -#define XL_FLAG_PHYOK 0x0002 -#define XL_FLAG_EEPROM_OFFSET_30 0x0004 -#define XL_FLAG_WEIRDRESET 0x0008 -#define XL_FLAG_8BITROM 0x0010 -#define XL_FLAG_INVERT_LED_PWR 0x0020 -#define XL_FLAG_INVERT_MII_PWR 0x0040 -#define XL_FLAG_NO_XCVR_PWR 0x0080 -#define XL_FLAG_USE_MMIO 0x0100 - - - -#define XL_EE_READ 0x0080 /* read, 5 bit address */ -#define XL_EE_WRITE 0x0040 /* write, 5 bit address */ -#define XL_EE_ERASE 0x00c0 /* erase, 5 bit address */ -#define XL_EE_EWEN 0x0030 /* erase, no data needed */ -#define XL_EE_8BIT_READ 0x0200 /* read, 8 bit address */ -#define XL_EE_BUSY 0x8000 - -#define XL_EE_EADDR0 0x00 /* station address, first word */ -#define XL_EE_EADDR1 0x01 /* station address, next word, */ -#define XL_EE_EADDR2 0x02 /* station address, last word */ -#define XL_EE_PRODID 0x03 /* product ID code */ -#define XL_EE_MDATA_DATE 0x04 /* manufacturing data, date */ -#define XL_EE_MDATA_DIV 0x05 /* manufacturing data, division */ -#define XL_EE_MDATA_PCODE 0x06 /* manufacturing data, product code */ -#define XL_EE_MFG_ID 0x07 -#define XL_EE_PCI_PARM 0x08 -#define XL_EE_ROM_ONFO 0x09 -#define XL_EE_OEM_ADR0 0x0A -#define XL_EE_OEM_ADR1 0x0B -#define XL_EE_OEM_ADR2 0x0C -#define XL_EE_SOFTINFO1 0x0D -#define XL_EE_COMPAT 0x0E -#define XL_EE_SOFTINFO2 0x0F -#define XL_EE_CAPS 0x10 /* capabilities word */ -#define XL_EE_RSVD0 0x11 -#define XL_EE_ICFG_0 0x12 -#define XL_EE_ICFG_1 0x13 -#define XL_EE_RSVD1 0x14 -#define XL_EE_SOFTINFO3 0x15 -#define XL_EE_RSVD_2 0x16 - -/* - * Bits in the capabilities word - */ -#define XL_CAPS_PNP 0x0001 -#define XL_CAPS_FULL_DUPLEX 0x0002 -#define XL_CAPS_LARGE_PKTS 0x0004 -#define XL_CAPS_SLAVE_DMA 0x0008 -#define XL_CAPS_SECOND_DMA 0x0010 -#define XL_CAPS_FULL_BM 0x0020 -#define XL_CAPS_FRAG_BM 0x0040 -#define XL_CAPS_CRC_PASSTHRU 0x0080 -#define XL_CAPS_TXDONE 0x0100 -#define XL_CAPS_NO_TXLENGTH 0x0200 -#define XL_CAPS_RX_REPEAT 0x0400 -#define XL_CAPS_SNOOPING 0x0800 -#define XL_CAPS_100MBPS 0x1000 -#define XL_CAPS_PWRMGMT 0x2000 - - - -/* - * Window 0 registers - */ -#define XL_W0_EE_DATA 0x0C -#define XL_W0_EE_CMD 0x0A -#define XL_W0_RSRC_CFG 0x08 -#define XL_W0_ADDR_CFG 0x06 -#define XL_W0_CFG_CTRL 0x04 - -#define XL_W0_PROD_ID 0x02 -#define XL_W0_MFG_ID 0x00 - -/* - * Window 1 - */ - -#define XL_W1_TX_FIFO 0x10 - -#define XL_W1_FREE_TX 0x0C -#define XL_W1_TX_STATUS 0x0B -#define XL_W1_TX_TIMER 0x0A -#define XL_W1_RX_STATUS 0x08 -#define XL_W1_RX_FIFO 0x00 - -/* - * RX status codes - */ -#define XL_RXSTATUS_OVERRUN 0x01 -#define XL_RXSTATUS_RUNT 0x02 -#define XL_RXSTATUS_ALIGN 0x04 -#define XL_RXSTATUS_CRC 0x08 -#define XL_RXSTATUS_OVERSIZE 0x10 -#define XL_RXSTATUS_DRIBBLE 0x20 - -/* - * TX status codes - */ -#define XL_TXSTATUS_RECLAIM 0x02 /* 3c905B only */ -#define XL_TXSTATUS_OVERFLOW 0x04 -#define XL_TXSTATUS_MAXCOLS 0x08 -#define XL_TXSTATUS_UNDERRUN 0x10 -#define XL_TXSTATUS_JABBER 0x20 -#define XL_TXSTATUS_INTREQ 0x40 -#define XL_TXSTATUS_COMPLETE 0x80 - -/* - * Window 2 - */ -#define XL_W2_RESET_OPTIONS 0x0C /* 3c905B only */ -#define XL_W2_STATION_MASK_HI 0x0A -#define XL_W2_STATION_MASK_MID 0x08 -#define XL_W2_STATION_MASK_LO 0x06 -#define XL_W2_STATION_ADDR_HI 0x04 -#define XL_W2_STATION_ADDR_MID 0x02 -#define XL_W2_STATION_ADDR_LO 0x00 - -#define XL_RESETOPT_FEATUREMASK 0x0001|0x0002|0x004 -#define XL_RESETOPT_D3RESETDIS 0x0008 -#define XL_RESETOPT_DISADVFD 0x0010 -#define XL_RESETOPT_DISADV100 0x0020 -#define XL_RESETOPT_DISAUTONEG 0x0040 -#define XL_RESETOPT_DEBUGMODE 0x0080 -#define XL_RESETOPT_FASTAUTO 0x0100 -#define XL_RESETOPT_FASTEE 0x0200 -#define XL_RESETOPT_FORCEDCONF 0x0400 -#define XL_RESETOPT_TESTPDTPDR 0x0800 -#define XL_RESETOPT_TEST100TX 0x1000 -#define XL_RESETOPT_TEST100RX 0x2000 - -#define XL_RESETOPT_INVERT_LED 0x0010 -#define XL_RESETOPT_INVERT_MII 0x4000 - -/* - * Window 3 (fifo management) - */ -#define XL_W3_INTERNAL_CFG 0x00 -#define XL_W3_MAXPKTSIZE 0x04 /* 3c905B only */ -#define XL_W3_RESET_OPT 0x08 -#define XL_W3_FREE_TX 0x0C -#define XL_W3_FREE_RX 0x0A -#define XL_W3_MAC_CTRL 0x06 - -#define XL_ICFG_CONNECTOR_MASK 0x00F00000 -#define XL_ICFG_CONNECTOR_BITS 20 - -#define XL_ICFG_RAMSIZE_MASK 0x00000007 -#define XL_ICFG_RAMWIDTH 0x00000008 -#define XL_ICFG_ROMSIZE_MASK (0x00000040|0x00000080) -#define XL_ICFG_DISABLE_BASSD 0x00000100 -#define XL_ICFG_RAMLOC 0x00000200 -#define XL_ICFG_RAMPART (0x00010000|0x00020000) -#define XL_ICFG_XCVRSEL (0x00100000|0x00200000|0x00400000) -#define XL_ICFG_AUTOSEL 0x01000000 - -#define XL_XCVR_10BT 0x00 -#define XL_XCVR_AUI 0x01 -#define XL_XCVR_RSVD_0 0x02 -#define XL_XCVR_COAX 0x03 -#define XL_XCVR_100BTX 0x04 -#define XL_XCVR_100BFX 0x05 -#define XL_XCVR_MII 0x06 -#define XL_XCVR_RSVD_1 0x07 -#define XL_XCVR_AUTO 0x08 /* 3c905B only */ - -#define XL_MACCTRL_DEFER_EXT_END 0x0001 -#define XL_MACCTRL_DEFER_0 0x0002 -#define XL_MACCTRL_DEFER_1 0x0004 -#define XL_MACCTRL_DEFER_2 0x0008 -#define XL_MACCTRL_DEFER_3 0x0010 -#define XL_MACCTRL_DUPLEX 0x0020 -#define XL_MACCTRL_ALLOW_LARGE_PACK 0x0040 -#define XL_MACCTRL_EXTEND_AFTER_COL 0x0080 (3c905B only) -#define XL_MACCTRL_FLOW_CONTROL_ENB 0x0100 (3c905B only) -#define XL_MACCTRL_VLT_END 0x0200 (3c905B only) - -/* - * The 'reset options' register contains power-on reset values - * loaded from the EEPROM. This includes the supported media - * types on the card. It is also known as the media options register. - */ -#define XL_W3_MEDIA_OPT 0x08 - -#define XL_MEDIAOPT_BT4 0x0001 /* MII */ -#define XL_MEDIAOPT_BTX 0x0002 /* on-chip */ -#define XL_MEDIAOPT_BFX 0x0004 /* on-chip */ -#define XL_MEDIAOPT_BT 0x0008 /* on-chip */ -#define XL_MEDIAOPT_BNC 0x0010 /* on-chip */ -#define XL_MEDIAOPT_AUI 0x0020 /* on-chip */ -#define XL_MEDIAOPT_MII 0x0040 /* MII */ -#define XL_MEDIAOPT_VCO 0x0100 /* 1st gen chip only */ - -#define XL_MEDIAOPT_10FL 0x0100 /* 3x905B only, on-chip */ -#define XL_MEDIAOPT_MASK 0x01FF - -/* - * Window 4 (diagnostics) - */ -#define XL_W4_UPPERBYTESOK 0x0D -#define XL_W4_BADSSD 0x0C -#define XL_W4_MEDIA_STATUS 0x0A -#define XL_W4_PHY_MGMT 0x08 -#define XL_W4_NET_DIAG 0x06 -#define XL_W4_FIFO_DIAG 0x04 -#define XL_W4_VCO_DIAG 0x02 - -#define XL_W4_CTRLR_STAT 0x08 -#define XL_W4_TX_DIAG 0x00 - -#define XL_MII_CLK 0x01 -#define XL_MII_DATA 0x02 -#define XL_MII_DIR 0x04 - -#define XL_MEDIA_SQE 0x0008 -#define XL_MEDIA_10TP 0x00C0 -#define XL_MEDIA_LNK 0x0080 -#define XL_MEDIA_LNKBEAT 0x0800 - -#define XL_MEDIASTAT_CRCSTRIP 0x0004 -#define XL_MEDIASTAT_SQEENB 0x0008 -#define XL_MEDIASTAT_COLDET 0x0010 -#define XL_MEDIASTAT_CARRIER 0x0020 -#define XL_MEDIASTAT_JABGUARD 0x0040 -#define XL_MEDIASTAT_LINKBEAT 0x0080 -#define XL_MEDIASTAT_JABDETECT 0x0200 -#define XL_MEDIASTAT_POLREVERS 0x0400 -#define XL_MEDIASTAT_LINKDETECT 0x0800 -#define XL_MEDIASTAT_TXINPROG 0x1000 -#define XL_MEDIASTAT_DCENB 0x4000 -#define XL_MEDIASTAT_AUIDIS 0x8000 - -#define XL_NETDIAG_TEST_LOWVOLT 0x0001 -#define XL_NETDIAG_ASIC_REVMASK (0x0002|0x0004|0x0008|0x0010|0x0020) -#define XL_NETDIAG_UPPER_BYTES_ENABLE 0x0040 -#define XL_NETDIAG_STATS_ENABLED 0x0080 -#define XL_NETDIAG_TX_FATALERR 0x0100 -#define XL_NETDIAG_TRANSMITTING 0x0200 -#define XL_NETDIAG_RX_ENABLED 0x0400 -#define XL_NETDIAG_TX_ENABLED 0x0800 -#define XL_NETDIAG_FIFO_LOOPBACK 0x1000 -#define XL_NETDIAG_MAC_LOOPBACK 0x2000 -#define XL_NETDIAG_ENDEC_LOOPBACK 0x4000 -#define XL_NETDIAG_EXTERNAL_LOOP 0x8000 - -/* - * Window 5 - */ -#define XL_W5_STAT_ENB 0x0C -#define XL_W5_INTR_ENB 0x0A -#define XL_W5_RECLAIM_THRESH 0x09 /* 3c905B only */ -#define XL_W5_RX_FILTER 0x08 -#define XL_W5_RX_EARLYTHRESH 0x06 -#define XL_W5_TX_AVAILTHRESH 0x02 -#define XL_W5_TX_STARTTHRESH 0x00 - -/* - * RX filter bits - */ -#define XL_RXFILTER_INDIVIDUAL 0x01 -#define XL_RXFILTER_ALLMULTI 0x02 -#define XL_RXFILTER_BROADCAST 0x04 -#define XL_RXFILTER_ALLFRAMES 0x08 -#define XL_RXFILTER_MULTIHASH 0x10 /* 3c905B only */ - -/* - * Window 6 (stats) - */ -#define XL_W6_TX_BYTES_OK 0x0C -#define XL_W6_RX_BYTES_OK 0x0A -#define XL_W6_UPPER_FRAMES_OK 0x09 -#define XL_W6_DEFERRED 0x08 -#define XL_W6_RX_OK 0x07 -#define XL_W6_TX_OK 0x06 -#define XL_W6_RX_OVERRUN 0x05 -#define XL_W6_COL_LATE 0x04 -#define XL_W6_COL_SINGLE 0x03 -#define XL_W6_COL_MULTIPLE 0x02 -#define XL_W6_SQE_ERRORS 0x01 -#define XL_W6_CARRIER_LOST 0x00 - -/* - * Window 7 (bus master control) - */ -#define XL_W7_BM_ADDR 0x00 -#define XL_W7_BM_LEN 0x06 -#define XL_W7_BM_STATUS 0x0B -#define XL_W7_BM_TIMEr 0x0A - -/* - * bus master control registers - */ -#define XL_BM_PKTSTAT 0x20 -#define XL_BM_DOWNLISTPTR 0x24 -#define XL_BM_FRAGADDR 0x28 -#define XL_BM_FRAGLEN 0x2C -#define XL_BM_TXFREETHRESH 0x2F -#define XL_BM_UPPKTSTAT 0x30 -#define XL_BM_UPLISTPTR 0x38 - - - - - - - - -struct xl_mii_frame { - u_int8_t mii_stdelim; - u_int8_t mii_opcode; - u_int8_t mii_phyaddr; - u_int8_t mii_regaddr; - u_int8_t mii_turnaround; - u_int16_t mii_data; -}; - -/* - * MII constants - */ -#define XL_MII_STARTDELIM 0x01 -#define XL_MII_READOP 0x02 -#define XL_MII_WRITEOP 0x01 -#define XL_MII_TURNAROUND 0x02 - - - -/* - * The 3C905B adapters implement a few features that we want to - * take advantage of, namely the multicast hash filter. With older - * chips, you only have the option of turning on reception of all - * multicast frames, which is kind of lame. - * - * We also use this to decide on a transmit strategy. For the 3c90xB - * cards, we can use polled descriptor mode, which reduces CPU overhead. - */ -#define XL_TYPE_905B 1 -#define XL_TYPE_90X 2 - -#define XL_FLAG_FUNCREG 0x0001 -#define XL_FLAG_PHYOK 0x0002 -#define XL_FLAG_EEPROM_OFFSET_30 0x0004 -#define XL_FLAG_WEIRDRESET 0x0008 -#define XL_FLAG_8BITROM 0x0010 -#define XL_FLAG_INVERT_LED_PWR 0x0020 -#define XL_FLAG_INVERT_MII_PWR 0x0040 -#define XL_FLAG_NO_XCVR_PWR 0x0080 -#define XL_FLAG_USE_MMIO 0x0100 - -#define XL_NO_XCVR_PWR_MAGICBITS 0x0900 - - -#define XL_MIN_FRAMELEN 60 - -#define XL_LAST_FRAG 0x80000000 - - - - - - - -struct xl_stats -{ - /* accumulated stats */ - u_int16_t xl_carrier_lost; - u_int16_t xl_sqe_errs; - u_int16_t xl_tx_multi_collision; - u_int16_t xl_tx_single_collision; - u_int16_t xl_tx_late_collision; - u_int16_t xl_rx_overrun; - u_int16_t xl_tx_deferred; - - u_int32_t xl_rx_bytes_ok; - u_int32_t xl_tx_bytes_ok; - - u_int32_t xl_tx_frames_ok; - u_int32_t xl_rx_frames_ok; - - u_int16_t xl_badssd; - - /* non-accumulated stats */ - u_int16_t intstatus; - u_int16_t rxstatus; - u_int8_t txstatus; - u_int16_t mediastatus; - - u_int32_t txcomplete_ints; - - u_int16_t miianr, miipar, miistatus, miicmd; - - u_int32_t device_interrupts; - u_int32_t internalconfig; - u_int16_t mac_control; - - u_int16_t smbstatus; - u_int32_t dmactl; - u_int16_t txfree; -}; - - - -struct xl_type -{ - u_int16_t xl_vid; - u_int16_t xl_did; - char *xl_name; -}; - - - -/* - * Various supported device vendors/types and their names. - */ -static struct xl_type xl_devs[] = { - { TC_VENDORID, TC_DEVICEID_BOOMERANG_10BT, - "3Com 3c900-TPO Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_BOOMERANG_10BT_COMBO, - "3Com 3c900-COMBO Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_BOOMERANG_10_100BT, - "3Com 3c905-TX Fast Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_BOOMERANG_100BT4, - "3Com 3c905-T4 Fast Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_KRAKATOA_10BT, - "3Com 3c900B-TPO Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_KRAKATOA_10BT_COMBO, - "3Com 3c900B-COMBO Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_KRAKATOA_10BT_TPC, - "3Com 3c900B-TPC Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_CYCLONE_10FL, - "3Com 3c900B-FL Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_HURRICANE_10_100BT, - "3Com 3c905B-TX Fast Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_CYCLONE_10_100BT4, - "3Com 3c905B-T4 Fast Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_CYCLONE_10_100FX, - "3Com 3c905B-FX/SC Fast Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_CYCLONE_10_100_COMBO, - "3Com 3c905B-COMBO Fast Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_TORNADO_10_100BT, - "3Com 3c905C-TX Fast Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_TORNADO_10_100BT_920B, - "3Com 3c920B-EMB Integrated Fast Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_HURRICANE_10_100BT_SERV, - "3Com 3c980 Fast Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_TORNADO_10_100BT_SERV, - "3Com 3c980C Fast Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_HURRICANE_SOHO100TX, - "3Com 3cSOHO100-TX OfficeConnect" }, - { TC_VENDORID, TC_DEVICEID_TORNADO_HOMECONNECT, - "3Com 3c450-TX HomeConnect" }, - { TC_VENDORID, TC_DEVICEID_HURRICANE_555, - "3Com 3c555 Fast Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_HURRICANE_556, - "3Com 3c556 Fast Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_HURRICANE_556B, - "3Com 3c556B Fast Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_HURRICANE_575A, - "3Com 3c575TX Fast Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_HURRICANE_575B, - "3Com 3c575B Fast Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_HURRICANE_575C, - "3Com 3c575C Fast Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_HURRICANE_656, - "3Com 3c656 Fast Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_HURRICANE_656B, - "3Com 3c656B Fast Etherlink XL" }, - { TC_VENDORID, TC_DEVICEID_TORNADO_656C, - "3Com 3c656C Fast Etherlink XL" }, - { 0, 0, NULL } -}; - - -#define XL_TIMEOUT 1000 - - - - - - -/* rx message descriptor entry, ensure the struct is aligned to 8 bytes */ -struct RXMD -{ - /* used by hardware */ - volatile uint32_t next; - volatile uint32_t status; - volatile uint32_t addr; - volatile uint32_t length; - /* used by software */ - struct mbuf *mbuf; /* scratch variable used in the tx ring */ - struct RXMD *next_md; -} __attribute__ ((aligned (8), packed)); - - - - - -#define NUM_FRAGS 6 - -/* - * tx message descriptor entry, ensure the struct is aligned to 8 bytes - */ - -struct tfrag -{ - volatile uint32_t addr; - volatile uint32_t length; -} __attribute__ ((packed)); - -struct TXMD -{ - /* used by hardware */ - volatile uint32_t next; - volatile uint32_t status; - struct tfrag txfrags[NUM_FRAGS]; - /* used by software */ - struct mbuf *mbuf; /* scratch variable used in the tx ring */ - struct TXMD *next_md, *chainptr; -} __attribute__ ((aligned (8), packed)); - - - - - -#define NUM_CHAIN_LENGTHS 50 - - - -/* - * Per-device data - */ -struct elnk_softc -{ - struct arpcom arpcom; - - rtems_irq_connect_data irqInfo; - rtems_event_set ioevent; - unsigned int ioaddr; - - unsigned char *bufferBase, *ringBase; - - struct RXMD *rx_ring, *curr_rx_md; - struct TXMD *tx_ring, *last_tx_md, *last_txchain_head; - - rtems_id stat_timer_id; - uint32_t stats_update_ticks; - - struct xl_stats xl_stats; - - u_int8_t xl_unit; /* interface number */ - u_int8_t xl_type; - int xl_flags; - u_int16_t xl_media; - u_int16_t xl_caps; - u_int32_t xl_xcvr; - u_int8_t xl_stats_no_timeout; - u_int16_t xl_tx_thresh; - - int tx_idle; - - short chain_lengths[NUM_CHAIN_LENGTHS]; - int chlenIndex; - - unsigned short vendorID, deviceID; - int acceptBroadcast; - int numTxbuffers, numRxbuffers; -}; - -static struct elnk_softc elnk_softc[NUM_UNITS]; -static rtems_id rxDaemonTid; -static rtems_id txDaemonTid; -static rtems_id chainRecoveryQueue; - - - - - - - -#if defined(__i386__) - -#define CSR_WRITE_4(sc, reg, val) i386_outport_long( sc->ioaddr + reg, val ) -#define CSR_WRITE_2(sc, reg, val) i386_outport_word( sc->ioaddr + reg, val ) -#define CSR_WRITE_1(sc, reg, val) i386_outport_byte( sc->ioaddr + reg, val ) - - -inline unsigned int CSR_READ_4( struct elnk_softc *sc, int reg) -{ - unsigned int myval; - i386_inport_long( sc->ioaddr + reg, myval ); - return myval; -} - -inline unsigned short CSR_READ_2( struct elnk_softc *sc, int reg) -{ - unsigned short myval; - i386_inport_word( sc->ioaddr + reg, myval ); - return myval; -} - -inline unsigned char CSR_READ_1( struct elnk_softc *sc, int reg) -{ - unsigned char myval; - i386_inport_byte( sc->ioaddr + reg, myval ); - return myval; -} - -#endif - -#if defined(__PPC__) - -#define CSR_WRITE_4(sc, reg, val) outl( val, sc->ioaddr + reg) -#define CSR_WRITE_2(sc, reg, val) outw( val, sc->ioaddr + reg) -#define CSR_WRITE_1(sc, reg, val) outb( val, sc->ioaddr + reg) - -#define CSR_READ_4(sc, reg) inl(sc->ioaddr + reg) -#define CSR_READ_2(sc, reg) inw(sc->ioaddr + reg) -#define CSR_READ_1(sc, reg) inb(sc->ioaddr + reg) - -#endif - - -#define XL_SEL_WIN(x) CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_WINSEL | x) - - - - - - - - - - - -/* - * Murphy's law says that it's possible the chip can wedge and - * the 'command in progress' bit may never clear. Hence, we wait - * only a finite amount of time to avoid getting caught in an - * infinite loop. Normally this delay routine would be a macro, - * but it isn't called during normal operation so we can afford - * to make it a function. - */ -static void -xl_wait(struct elnk_softc *sc) -{ - register int i; - - for(i = 0; i < XL_TIMEOUT; i++) - { - if (!(CSR_READ_2(sc, XL_STATUS) & XL_STAT_CMDBUSY)) - break; - } - - if (i == XL_TIMEOUT) - printk("etherlink : unit elnk%d command never completed\n", sc->xl_unit ); - return; -} - - - - - - -/* - * MII access routines are provided for adapters with external - * PHYs (3c905-TX, 3c905-T4, 3c905B-T4) and those with built-in - * autoneg logic that's faked up to look like a PHY (3c905B-TX). - * Note: if you don't perform the MDIO operations just right, - * it's possible to end up with code that works correctly with - * some chips/CPUs/processor speeds/bus speeds/etc but not - * with others. - */ -#define MII_SET(x) \ - CSR_WRITE_2(sc, XL_W4_PHY_MGMT, \ - CSR_READ_2(sc, XL_W4_PHY_MGMT) | (x)) - -#define MII_CLR(x) \ - CSR_WRITE_2(sc, XL_W4_PHY_MGMT, \ - CSR_READ_2(sc, XL_W4_PHY_MGMT) & ~(x)) - -/* - * Sync the PHYs by setting data bit and strobing the clock 32 times. - */ -static void -xl_mii_sync( - struct elnk_softc *sc) -{ - register int i; - - XL_SEL_WIN(4); - MII_SET(XL_MII_DIR|XL_MII_DATA); - - for (i = 0; i < 32; i++) { - MII_SET(XL_MII_CLK); - MII_SET(XL_MII_DATA); - MII_CLR(XL_MII_CLK); - MII_SET(XL_MII_DATA); - } - - return; -} - -/* - * Clock a series of bits through the MII. - */ -static void -xl_mii_send( - struct elnk_softc *sc, - u_int32_t bits, - int cnt ) -{ - int i; - - XL_SEL_WIN(4); - MII_CLR(XL_MII_CLK); - - for (i = (0x1 << (cnt - 1)); i; i >>= 1) { - if (bits & i) { - MII_SET(XL_MII_DATA); - } else { - MII_CLR(XL_MII_DATA); - } - MII_CLR(XL_MII_CLK); - MII_SET(XL_MII_CLK); - } -} - -/* - * Read an PHY register through the MII. - */ -static int -xl_mii_readreg( - struct elnk_softc *sc, - struct xl_mii_frame *frame ) -{ - int i, ack; - - /* - * Set up frame for RX. - */ - frame->mii_stdelim = XL_MII_STARTDELIM; - frame->mii_opcode = XL_MII_READOP; - frame->mii_turnaround = 0; - frame->mii_data = 0; - - /* - * Select register window 4. - */ - - XL_SEL_WIN(4); - - CSR_WRITE_2(sc, XL_W4_PHY_MGMT, 0); - /* - * Turn on data xmit. - */ - MII_SET(XL_MII_DIR); - - xl_mii_sync(sc); - - /* - * Send command/address info. - */ - xl_mii_send(sc, frame->mii_stdelim, 2); - xl_mii_send(sc, frame->mii_opcode, 2); - xl_mii_send(sc, frame->mii_phyaddr, 5); - xl_mii_send(sc, frame->mii_regaddr, 5); - - /* Idle bit */ - MII_CLR((XL_MII_CLK|XL_MII_DATA)); - MII_SET(XL_MII_CLK); - - /* Turn off xmit. */ - MII_CLR(XL_MII_DIR); - - /* Check for ack */ - MII_CLR(XL_MII_CLK); - ack = CSR_READ_2(sc, XL_W4_PHY_MGMT) & XL_MII_DATA; - MII_SET(XL_MII_CLK); - - /* - * Now try reading data bits. If the ack failed, we still - * need to clock through 16 cycles to keep the PHY(s) in sync. - */ - if (ack) { - for(i = 0; i < 16; i++) { - MII_CLR(XL_MII_CLK); - MII_SET(XL_MII_CLK); - } - goto fail; - } - - for (i = 0x8000; i; i >>= 1) { - MII_CLR(XL_MII_CLK); - if (!ack) { - if (CSR_READ_2(sc, XL_W4_PHY_MGMT) & XL_MII_DATA) - frame->mii_data |= i; - } - MII_SET(XL_MII_CLK); - } - - fail: - - MII_CLR(XL_MII_CLK); - MII_SET(XL_MII_CLK); - - if (ack) - return(1); - return(0); -} - -/* - * Write to a PHY register through the MII. - */ -static int -xl_mii_writereg( - struct elnk_softc *sc, - struct xl_mii_frame *frame ) -{ - /* - * Set up frame for TX. - */ - - frame->mii_stdelim = XL_MII_STARTDELIM; - frame->mii_opcode = XL_MII_WRITEOP; - frame->mii_turnaround = XL_MII_TURNAROUND; - - /* - * Select the window 4. - */ - XL_SEL_WIN(4); - - /* - * Turn on data output. - */ - MII_SET(XL_MII_DIR); - - xl_mii_sync(sc); - - xl_mii_send(sc, frame->mii_stdelim, 2); - xl_mii_send(sc, frame->mii_opcode, 2); - xl_mii_send(sc, frame->mii_phyaddr, 5); - xl_mii_send(sc, frame->mii_regaddr, 5); - xl_mii_send(sc, frame->mii_turnaround, 2); - xl_mii_send(sc, frame->mii_data, 16); - - /* Idle bit. */ - MII_SET(XL_MII_CLK); - MII_CLR(XL_MII_CLK); - - /* - * Turn off xmit. - */ - MII_CLR(XL_MII_DIR); - - return(0); -} - -static int -xl_miibus_readreg( - struct elnk_softc *sc, - int phy, - int reg ) -{ - struct xl_mii_frame frame; - - /* - * Pretend that PHYs are only available at MII address 24. - * This is to guard against problems with certain 3Com ASIC - * revisions that incorrectly map the internal transceiver - * control registers at all MII addresses. This can cause - * the miibus code to attach the same PHY several times over. - */ - if ((!(sc->xl_flags & XL_FLAG_PHYOK)) && phy != 24) - { - printk("etherlink : unit elnk%d xl_miibus_readreg returned\n", sc->xl_unit); - return(0); - } - - memset((char *)&frame, 0, sizeof(frame)); - - frame.mii_phyaddr = phy; - frame.mii_regaddr = reg; - xl_mii_readreg(sc, &frame); - - return(frame.mii_data); -} - -static int -xl_miibus_writereg( - struct elnk_softc *sc, - int phy, - int reg, - int data ) -{ - struct xl_mii_frame frame; - - if ((!(sc->xl_flags & XL_FLAG_PHYOK)) && phy != 24) - { - printk("etherlink : unit elnk%d xl_miibus_writereg returned\n", sc->xl_unit); - return(0); - } - - memset((char *)&frame, 0, sizeof(frame)); - - frame.mii_phyaddr = phy; - frame.mii_regaddr = reg; - frame.mii_data = data; - - xl_mii_writereg(sc, &frame); - - return(0); -} - - - - - - - - - -/* - * The EEPROM is slow: give it time to come ready after issuing - * it a command. - */ -static int -xl_eeprom_wait(struct elnk_softc *sc) -{ - int i; - - for (i = 0; i < 100; i++) { - if (CSR_READ_2(sc, XL_W0_EE_CMD) & XL_EE_BUSY) - DELAY(162); - else - break; - } - - if (i == 100) { - printk("etherlink : unit elnk%d eeprom failed to come ready\n", sc->xl_unit); - return(1); - } - - return(0); -} - -/* - * Read a sequence of words from the EEPROM. Note that ethernet address - * data is stored in the EEPROM in network byte order. - */ -static int -xl_read_eeprom( - struct elnk_softc *sc, - caddr_t dest, - int off, - int cnt, - int swap) -{ - int err = 0, i; - u_int16_t word = 0, *ptr; -#define EEPROM_5BIT_OFFSET(A) ((((A) << 2) & 0x7F00) | ((A) & 0x003F)) -#define EEPROM_8BIT_OFFSET(A) ((A) & 0x003F) - /* WARNING! DANGER! - * It's easy to accidentally overwrite the rom content! - * Note: the 3c575 uses 8bit EEPROM offsets. - */ - XL_SEL_WIN(0); - - if (xl_eeprom_wait(sc)) - return(1); - - if (sc->xl_flags & XL_FLAG_EEPROM_OFFSET_30) - off += 0x30; - - for (i = 0; i < cnt; i++) { - if (sc->xl_flags & XL_FLAG_8BITROM) - CSR_WRITE_2(sc, XL_W0_EE_CMD, - XL_EE_8BIT_READ | EEPROM_8BIT_OFFSET(off + i)); - else - CSR_WRITE_2(sc, XL_W0_EE_CMD, - XL_EE_READ | EEPROM_5BIT_OFFSET(off + i)); - err = xl_eeprom_wait(sc); - if (err) - break; - word = CSR_READ_2(sc, XL_W0_EE_DATA); - ptr = (u_int16_t*)(dest + (i * 2)); - if (swap) - *ptr = ntohs(word); - else - *ptr = word; - } - - return(err ? 1 : 0); -} - - - - -static void -xl_stats_update( - rtems_id timerid, - void *xsc) -{ - struct elnk_softc *sc = (struct elnk_softc *)xsc; - struct ifnet *ifp = &sc->arpcom.ac_if; - u_int32_t t1; - - sc->xl_stats.intstatus = CSR_READ_2(sc, XL_STATUS); - - sc->xl_stats.miianr = xl_miibus_readreg(sc, 0x18, MII_ANAR ); - sc->xl_stats.miipar = xl_miibus_readreg(sc, 0x18, MII_ANLPAR ); - sc->xl_stats.miistatus = xl_miibus_readreg(sc, 0x18, MII_BMSR ); - sc->xl_stats.miicmd = xl_miibus_readreg(sc, 0x18, MII_BMCR ); - - XL_SEL_WIN(1); - sc->xl_stats.rxstatus = CSR_READ_2(sc, XL_W1_RX_STATUS ); - sc->xl_stats.txstatus = CSR_READ_1(sc, XL_W1_TX_STATUS ); - sc->xl_stats.smbstatus = CSR_READ_2(sc, 2 ); - - XL_SEL_WIN(3); - sc->xl_stats.internalconfig = CSR_READ_4(sc, XL_W3_INTERNAL_CFG); - sc->xl_stats.mac_control = CSR_READ_2(sc, XL_W3_MAC_CTRL); - sc->xl_stats.txfree = CSR_READ_2(sc, XL_W3_FREE_TX ); - - - /* Read all the stats registers. */ - XL_SEL_WIN(6); - - sc->xl_stats.xl_carrier_lost += CSR_READ_1(sc, XL_W6_CARRIER_LOST); - sc->xl_stats.xl_sqe_errs += CSR_READ_1(sc, XL_W6_SQE_ERRORS); - sc->xl_stats.xl_tx_multi_collision += CSR_READ_1(sc, XL_W6_COL_MULTIPLE); - sc->xl_stats.xl_tx_single_collision += CSR_READ_1(sc, XL_W6_COL_SINGLE); - sc->xl_stats.xl_tx_late_collision += CSR_READ_1(sc, XL_W6_COL_LATE); - sc->xl_stats.xl_rx_overrun += CSR_READ_1(sc, XL_W6_RX_OVERRUN); - sc->xl_stats.xl_tx_deferred += CSR_READ_1(sc, XL_W6_DEFERRED); - - sc->xl_stats.xl_tx_frames_ok += CSR_READ_1(sc, XL_W6_TX_OK); - sc->xl_stats.xl_rx_frames_ok += CSR_READ_1(sc, XL_W6_RX_OK); - - sc->xl_stats.xl_rx_bytes_ok += CSR_READ_2(sc, XL_W6_TX_BYTES_OK ); - sc->xl_stats.xl_tx_bytes_ok += CSR_READ_2(sc, XL_W6_RX_BYTES_OK ); - - t1 = CSR_READ_1(sc, XL_W6_UPPER_FRAMES_OK); - sc->xl_stats.xl_rx_frames_ok += ((t1 & 0x3) << 8); - sc->xl_stats.xl_tx_frames_ok += (((t1 >> 4) & 0x3) << 8); - - - ifp->if_ierrors += sc->xl_stats.xl_rx_overrun; - - ifp->if_collisions += sc->xl_stats.xl_tx_multi_collision + - sc->xl_stats.xl_tx_single_collision + - sc->xl_stats.xl_tx_late_collision; - - /* - * Boomerang and cyclone chips have an extra stats counter - * in window 4 (BadSSD). We have to read this too in order - * to clear out all the stats registers and avoid a statsoflow - * interrupt. - */ - XL_SEL_WIN(4); - - t1 = CSR_READ_1(sc, XL_W4_UPPERBYTESOK); - sc->xl_stats.xl_rx_bytes_ok += ((t1 & 0xf) << 16); - sc->xl_stats.xl_tx_bytes_ok += (((t1 >> 4) & 0xf) << 16); - - sc->xl_stats.xl_badssd += CSR_READ_1(sc, XL_W4_BADSSD); - - sc->xl_stats.mediastatus = CSR_READ_2(sc, XL_W4_MEDIA_STATUS ); - sc->xl_stats.dmactl = CSR_READ_4(sc, XL_DMACTL ); - - - XL_SEL_WIN(7); - - if (!sc->xl_stats_no_timeout) - rtems_timer_fire_after( sc->stat_timer_id, sc->stats_update_ticks, xl_stats_update, (void *)sc ); - return; -} - - - - - - - -static void -xl_reset(struct elnk_softc *sc) -{ - register int i; - - XL_SEL_WIN(0); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RESET | - ((sc->xl_flags & XL_FLAG_WEIRDRESET) ? - XL_RESETOPT_DISADVFD:0)); - - for (i = 0; i < XL_TIMEOUT; i++) { - DELAY(10); - if (!(CSR_READ_2(sc, XL_STATUS) & XL_STAT_CMDBUSY)) - break; - } - - if (i == XL_TIMEOUT) - printk("etherlink : unit elnk%d reset didn't complete\n", sc->xl_unit); - - /* Reset TX and RX. */ - /* Note: the RX reset takes an absurd amount of time - * on newer versions of the Tornado chips such as those - * on the 3c905CX and newer 3c908C cards. We wait an - * extra amount of time so that xl_wait() doesn't complain - * and annoy the users. - */ - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_RESET); - DELAY(100000); - xl_wait(sc); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_RESET); - xl_wait(sc); - - if (sc->xl_flags & XL_FLAG_INVERT_LED_PWR || - sc->xl_flags & XL_FLAG_INVERT_MII_PWR) - { - XL_SEL_WIN(2); - CSR_WRITE_2(sc, XL_W2_RESET_OPTIONS, CSR_READ_2(sc, - XL_W2_RESET_OPTIONS) - | ((sc->xl_flags & XL_FLAG_INVERT_LED_PWR)?XL_RESETOPT_INVERT_LED:0) - | ((sc->xl_flags & XL_FLAG_INVERT_MII_PWR)?XL_RESETOPT_INVERT_MII:0) - ); - } - - /* Wait a little while for the chip to get its brains in order. */ - DELAY(100000); - return; -} - - - - -static void -xl_stop(struct elnk_softc *sc) -{ - struct ifnet *ifp; - - ifp = &sc->arpcom.ac_if; - ifp->if_timer = 0; - - rtems_timer_cancel( sc->stat_timer_id ); - - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_DISABLE); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STATS_DISABLE); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_DISCARD); - xl_wait(sc); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_DISABLE); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_STOP); - DELAY(800); - - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ACK|XL_STAT_INTLATCH); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STAT_ENB|0); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|0); - - return; -} - - - - - - - - - - - - - - - -static void -xl_setcfg(struct elnk_softc *sc) -{ - u_int32_t icfg; - - XL_SEL_WIN(3); - icfg = CSR_READ_4(sc, XL_W3_INTERNAL_CFG); - - icfg &= ~XL_ICFG_CONNECTOR_MASK; - - if (sc->xl_media & XL_MEDIAOPT_MII || sc->xl_media & XL_MEDIAOPT_BT4) - icfg |= (XL_XCVR_MII << XL_ICFG_CONNECTOR_BITS); - - if (sc->xl_media & XL_MEDIAOPT_BTX) - icfg |= (XL_XCVR_AUTO << XL_ICFG_CONNECTOR_BITS); - - CSR_WRITE_4(sc, XL_W3_INTERNAL_CFG, icfg); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_STOP); - - XL_SEL_WIN(7); - return; -} - - - -static void -xl_setmode( - struct elnk_softc *sc, - int media) -{ - u_int32_t icfg; - u_int16_t mediastat; - - printk("etherlink : unit elnk%d selecting ", sc->xl_unit); - - XL_SEL_WIN(4); - mediastat = CSR_READ_2(sc, XL_W4_MEDIA_STATUS); - XL_SEL_WIN(3); - icfg = CSR_READ_4(sc, XL_W3_INTERNAL_CFG); - - if (sc->xl_media & XL_MEDIAOPT_BT) { - if (IFM_SUBTYPE(media) == IFM_10_T) { - printk("10baseT transceiver, "); - sc->xl_xcvr = XL_XCVR_10BT; - icfg &= ~XL_ICFG_CONNECTOR_MASK; - icfg |= (XL_XCVR_10BT << XL_ICFG_CONNECTOR_BITS); - mediastat |= XL_MEDIASTAT_LINKBEAT| - XL_MEDIASTAT_JABGUARD; - mediastat &= ~XL_MEDIASTAT_SQEENB; - } - } - - if (sc->xl_media & XL_MEDIAOPT_BFX) { - if (IFM_SUBTYPE(media) == IFM_100_FX) { - printk("100baseFX port, "); - sc->xl_xcvr = XL_XCVR_100BFX; - icfg &= ~XL_ICFG_CONNECTOR_MASK; - icfg |= (XL_XCVR_100BFX << XL_ICFG_CONNECTOR_BITS); - mediastat |= XL_MEDIASTAT_LINKBEAT; - mediastat &= ~XL_MEDIASTAT_SQEENB; - } - } - - if (sc->xl_media & (XL_MEDIAOPT_AUI|XL_MEDIAOPT_10FL)) { - if (IFM_SUBTYPE(media) == IFM_10_5) { - printk("AUI port, "); - sc->xl_xcvr = XL_XCVR_AUI; - icfg &= ~XL_ICFG_CONNECTOR_MASK; - icfg |= (XL_XCVR_AUI << XL_ICFG_CONNECTOR_BITS); - mediastat &= ~(XL_MEDIASTAT_LINKBEAT| - XL_MEDIASTAT_JABGUARD); - mediastat |= ~XL_MEDIASTAT_SQEENB; - } - if (IFM_SUBTYPE(media) == IFM_10_FL) { - printk("10baseFL transceiver, "); - sc->xl_xcvr = XL_XCVR_AUI; - icfg &= ~XL_ICFG_CONNECTOR_MASK; - icfg |= (XL_XCVR_AUI << XL_ICFG_CONNECTOR_BITS); - mediastat &= ~(XL_MEDIASTAT_LINKBEAT| - XL_MEDIASTAT_JABGUARD); - mediastat |= ~XL_MEDIASTAT_SQEENB; - } - } - - if (sc->xl_media & XL_MEDIAOPT_BNC) { - if (IFM_SUBTYPE(media) == IFM_10_2) { - printk("BNC port, "); - sc->xl_xcvr = XL_XCVR_COAX; - icfg &= ~XL_ICFG_CONNECTOR_MASK; - icfg |= (XL_XCVR_COAX << XL_ICFG_CONNECTOR_BITS); - mediastat &= ~(XL_MEDIASTAT_LINKBEAT| - XL_MEDIASTAT_JABGUARD| - XL_MEDIASTAT_SQEENB); - } - } - - if ((media & IFM_GMASK) == IFM_FDX || - IFM_SUBTYPE(media) == IFM_100_FX) { - printk("full duplex\n"); - XL_SEL_WIN(3); - CSR_WRITE_1(sc, XL_W3_MAC_CTRL, XL_MACCTRL_DUPLEX); - } else { - printk("half duplex\n"); - XL_SEL_WIN(3); - CSR_WRITE_1(sc, XL_W3_MAC_CTRL, - (CSR_READ_1(sc, XL_W3_MAC_CTRL) & ~XL_MACCTRL_DUPLEX)); - } - - if (IFM_SUBTYPE(media) == IFM_10_2) - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_START); - else - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_STOP); - - CSR_WRITE_4(sc, XL_W3_INTERNAL_CFG, icfg); - XL_SEL_WIN(4); - CSR_WRITE_2(sc, XL_W4_MEDIA_STATUS, mediastat); - DELAY(800); - XL_SEL_WIN(7); - - return; -} - - - - - - - -static void -xl_choose_xcvr( - struct elnk_softc *sc, - int verbose) -{ - u_int16_t devid; - - /* - * Read the device ID from the EEPROM. - * This is what's loaded into the PCI device ID register, so it has - * to be correct otherwise we wouldn't have gotten this far. - */ - xl_read_eeprom(sc, (caddr_t)&devid, XL_EE_PRODID, 1, 0); - - switch(devid) { - case TC_DEVICEID_BOOMERANG_10BT: /* 3c900-TPO */ - case TC_DEVICEID_KRAKATOA_10BT: /* 3c900B-TPO */ - sc->xl_media = XL_MEDIAOPT_BT; - sc->xl_xcvr = XL_XCVR_10BT; - if (verbose) - printk("etherlink : unit elnk%d guessing 10BaseT " - "transceiver\n", sc->xl_unit); - break; - case TC_DEVICEID_BOOMERANG_10BT_COMBO: /* 3c900-COMBO */ - case TC_DEVICEID_KRAKATOA_10BT_COMBO: /* 3c900B-COMBO */ - sc->xl_media = XL_MEDIAOPT_BT|XL_MEDIAOPT_BNC|XL_MEDIAOPT_AUI; - sc->xl_xcvr = XL_XCVR_10BT; - if (verbose) - printk("etherlink : unit elnk%d guessing COMBO " - "(AUI/BNC/TP)\n", sc->xl_unit); - break; - case TC_DEVICEID_KRAKATOA_10BT_TPC: /* 3c900B-TPC */ - sc->xl_media = XL_MEDIAOPT_BT|XL_MEDIAOPT_BNC; - sc->xl_xcvr = XL_XCVR_10BT; - if (verbose) - printk("etherlink : unit elnk%d guessing TPC (BNC/TP)\n", sc->xl_unit); - break; - case TC_DEVICEID_CYCLONE_10FL: /* 3c900B-FL */ - sc->xl_media = XL_MEDIAOPT_10FL; - sc->xl_xcvr = XL_XCVR_AUI; - if (verbose) - printk("etherlink : unit elnk%d guessing 10baseFL\n", sc->xl_unit); - break; - case TC_DEVICEID_BOOMERANG_10_100BT: /* 3c905-TX */ - case TC_DEVICEID_HURRICANE_555: /* 3c555 */ - case TC_DEVICEID_HURRICANE_556: /* 3c556 */ - case TC_DEVICEID_HURRICANE_556B: /* 3c556B */ - case TC_DEVICEID_HURRICANE_575A: /* 3c575TX */ - case TC_DEVICEID_HURRICANE_575B: /* 3c575B */ - case TC_DEVICEID_HURRICANE_575C: /* 3c575C */ - case TC_DEVICEID_HURRICANE_656: /* 3c656 */ - case TC_DEVICEID_HURRICANE_656B: /* 3c656B */ - case TC_DEVICEID_TORNADO_656C: /* 3c656C */ - case TC_DEVICEID_TORNADO_10_100BT_920B: /* 3c920B-EMB */ - sc->xl_media = XL_MEDIAOPT_MII; - sc->xl_xcvr = XL_XCVR_MII; - if (verbose) - printk("etherlink : unit elnk%d guessing MII\n", sc->xl_unit); - break; - case TC_DEVICEID_BOOMERANG_100BT4: /* 3c905-T4 */ - case TC_DEVICEID_CYCLONE_10_100BT4: /* 3c905B-T4 */ - sc->xl_media = XL_MEDIAOPT_BT4; - sc->xl_xcvr = XL_XCVR_MII; - if (verbose) - printk("etherlink : unit elnk%d guessing 100BaseT4/MII\n", sc->xl_unit); - break; - case TC_DEVICEID_HURRICANE_10_100BT: /* 3c905B-TX */ - case TC_DEVICEID_HURRICANE_10_100BT_SERV:/*3c980-TX */ - case TC_DEVICEID_TORNADO_10_100BT_SERV: /* 3c980C-TX */ - case TC_DEVICEID_HURRICANE_SOHO100TX: /* 3cSOHO100-TX */ - case TC_DEVICEID_TORNADO_10_100BT: /* 3c905C-TX */ - case TC_DEVICEID_TORNADO_HOMECONNECT: /* 3c450-TX */ - sc->xl_media = XL_MEDIAOPT_BTX; - sc->xl_xcvr = XL_XCVR_AUTO; - if (verbose) - printk("etherlink : unit elnk%d guessing 10/100 internal\n", sc->xl_unit); - break; - case TC_DEVICEID_CYCLONE_10_100_COMBO: /* 3c905B-COMBO */ - sc->xl_media = XL_MEDIAOPT_BTX|XL_MEDIAOPT_BNC|XL_MEDIAOPT_AUI; - sc->xl_xcvr = XL_XCVR_AUTO; - if (verbose) - printk("etherlink : unit elnk%d guessing 10/100 " - "plus BNC/AUI\n", sc->xl_unit); - break; - default: - printk("etherlink : unit elnk%d unknown device ID: %x -- " - "defaulting to 10baseT\n", sc->xl_unit, devid); - sc->xl_media = XL_MEDIAOPT_BT; - break; - } - - return; -} - - - - - - - -/* - * This routine is a kludge to work around possible hardware faults - * or manufacturing defects that can cause the media options register - * (or reset options register, as it's called for the first generation - * 3c90x adapters) to return an incorrect result. I have encountered - * one Dell Latitude laptop docking station with an integrated 3c905-TX - * which doesn't have any of the 'mediaopt' bits set. This screws up - * the attach routine pretty badly because it doesn't know what media - * to look for. If we find ourselves in this predicament, this routine - * will try to guess the media options values and warn the user of a - * possible manufacturing defect with his adapter/system/whatever. - */ -static void -xl_mediacheck(struct elnk_softc *sc) -{ - - xl_choose_xcvr(sc, 1); - - /* - * If some of the media options bits are set, assume they are - * correct. If not, try to figure it out down below. - * XXX I should check for 10baseFL, but I don't have an adapter - * to test with. - */ - if (sc->xl_media & (XL_MEDIAOPT_MASK & ~XL_MEDIAOPT_VCO)) { - /* - * Check the XCVR value. If it's not in the normal range - * of values, we need to fake it up here. - */ - if (sc->xl_xcvr <= XL_XCVR_AUTO) - return; - else { - printk("etherlink : unit elnk%d bogus xcvr value " - "in EEPROM (%" PRIx32 ")\n", sc->xl_unit, sc->xl_xcvr); - printk("etherlink : unit elnk%d choosing new default based " - "on card type\n", sc->xl_unit); - } - } else { - if (sc->xl_type == XL_TYPE_905B && - sc->xl_media & XL_MEDIAOPT_10FL) - return; - printk("etherlink : unit elnk%d WARNING: no media options bits set in " - "the media options register!!\n", sc->xl_unit); - printk("etherlink : unit elnk%d this could be a manufacturing defect in " - "your adapter or system\n", sc->xl_unit); - printk("etherlink : unit elnk%d attempting to guess media type; you " - "should probably consult your vendor\n", sc->xl_unit); - } - - return; -} - - - - - - - - - - - - - - - - - - - - - - - - - -static void no_op(const rtems_irq_connect_data* irq) -{ - return; -} - - - - -static void -elnk_start_txchain( struct elnk_softc *sc, struct TXMD *chainhead ) -{ - xl_wait(sc); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_STALL); - - /* save the address of the TX list */ - sc->last_txchain_head = chainhead; - sc->tx_idle = 0; - - xl_wait(sc); - - CSR_WRITE_4(sc, XL_DOWNLIST_PTR, phys_to_bus( sc->last_txchain_head )); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_UNSTALL); -} - - - - - -/* - * ELNK interrupt handler - */ -static rtems_isr -elnk_interrupt_handler ( struct elnk_softc *sc ) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - u_int16_t status; - - while( ((status = CSR_READ_2(sc, XL_STATUS)) & XL_INTRS) && status != 0xFFFF) - { - sc->xl_stats.device_interrupts++; - - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ACK | (status & XL_INTRS)); - -#if 0 - printk("etherlink : unit elnk%d intstatus %04x\n", sc->xl_unit, status ); -#endif - - if (status & XL_STAT_UP_COMPLETE) - { -#if 0 - printk("etherlink : unit elnk%d rx\n", sc->xl_unit ); -#endif - /* received packets */ - rtems_bsdnet_event_send(rxDaemonTid, sc->ioevent); - } - - if( (status & XL_STAT_DOWN_COMPLETE) || (status & XL_STAT_TX_COMPLETE) ) - { - /* all packets uploaded to the device */ - struct TXMD *chaintailmd = NULL; - - - if( status & XL_STAT_TX_COMPLETE ) - { - /* if we got a tx complete error, count it, then reset the - transmitter. Consider the entire chain lost.. */ - - ifp->if_oerrors++; - sc->xl_stats.txcomplete_ints++; - - printk("etherlink : unit elnk%d transmit error\n", sc->xl_unit ); - - /* reset, re-enable fifo */ - - xl_wait(sc); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_DISABLE); - - xl_wait(sc); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_RESET | 1 ); - - xl_wait(sc); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_ENABLE); - - xl_wait(sc); - } - - - /* send the chain head to the tx task which will recover the - whole chain */ - rtems_message_queue_send( chainRecoveryQueue, &sc->last_txchain_head, sizeof(struct TXMD *)); - - - /* set up the next chain */ - if( sc->last_txchain_head->chainptr ) - { - /* check the head of the chain of packets we just finished, - * if != 0, either this is a chain of 2 or more packets or - * its a single packet chain and another chain is ready to - * send. - */ - if( (int)sc->last_txchain_head->chainptr == -1 ) - { - /* - ** single packet was sent so no indirection to the last - ** entry in the chain. since chainptr is != 0, then - ** another chain is ready starting from the packet AFTER - ** the chain we just finished. - in this case the last - ** chain's head == its tail - */ - chaintailmd = sc->last_txchain_head; - } - else - { - /* - ** otherwise, this is a pointer to the last packet in the - ** chain of 2 or more packets. If the chain's last - ** packet's chainptr is != 0, then another chain is ready - ** to send. - */ - chaintailmd = sc->last_txchain_head->chainptr; - if( !chaintailmd->chainptr ) chaintailmd = NULL; - } - } - - if( chaintailmd ) - { - /* the next MD is the start of another chain */ - elnk_start_txchain(sc, chaintailmd->next_md ); - } - else - { - /* otherwise nothing to send, so go idle */ - sc->tx_idle = -1; - - /* wake up the tx daemon once so we're sure this last chain - will be freed */ - rtems_bsdnet_event_send( txDaemonTid, sc->ioevent ); -#if 0 - printk("unit elnk%d tx done\n", sc->xl_unit ); -#endif - } - } - - - if (status & XL_STAT_ADFAIL) - { - printk("etherlink : unit elnk%d Catastrophic bus failure\n", sc->xl_unit ); - } - if (status & XL_STAT_STATSOFLOW) - { - sc->xl_stats_no_timeout = 1; - xl_stats_update(sc->stat_timer_id,sc); - sc->xl_stats_no_timeout = 0; - } - } - - -#if 0 - { - uint16_t intstatus, intenable, indenable; - - intstatus = CSR_READ_2(sc, XL_STATUS ); - - XL_SEL_WIN(5); - intenable = CSR_READ_2(sc, XL_W5_INTR_ENB ); - indenable = CSR_READ_2(sc, XL_W5_STAT_ENB ); - XL_SEL_WIN(7); - printk("etherlink : unit elnk%d istat %04x, ien %04x, ind %04x\n", sc->xl_unit, intstatus, intenable, indenable ); - } -#endif -} - - - - - -static rtems_isr -elnk_interrupt_handler_entry(void) -{ - int i; - - /* - ** Check all the initialized units for interrupt service - */ - - for(i=0; i< NUM_UNITS; i++ ) - { - if( elnk_softc[i].ioaddr ) - elnk_interrupt_handler( &elnk_softc[i] ); - } -} - - - - - - - - - - - -/* - * Initialize the ethernet hardware - */ -static void -elnk_initialize_hardware (struct elnk_softc *sc) -{ - unsigned char *cp; - int i, j, rxsize, txsize, ringsize; - - /* - * Init RX ring - */ - cp = (unsigned char *)malloc( (ringsize = ((rxsize = (sc->numRxbuffers * sizeof(struct RXMD))) + - (txsize = (sc->numTxbuffers * sizeof(struct TXMD)))) ) + - + CPU_CACHE_ALIGNMENT_FOR_BUFFER); - sc->bufferBase = cp; - cp += (CPU_CACHE_ALIGNMENT_FOR_BUFFER - (int)cp) & (CPU_CACHE_ALIGNMENT_FOR_BUFFER - 1); -#if defined(__i386__) -#ifdef PCI_BRIDGE_DOES_NOT_ENSURE_CACHE_COHERENCY_FOR_DMA - if (_CPU_is_paging_enabled()) - _CPU_change_memory_mapping_attribute - (NULL, cp, ringsize, PTE_CACHE_DISABLE | PTE_WRITABLE); -#endif -#endif - sc->ringBase = cp; - - /* build tx and rx rings */ - - sc->rx_ring = (struct RXMD *)sc->ringBase; - sc->tx_ring = (struct TXMD *)&sc->ringBase[ rxsize ]; - - { - struct mbuf *m; - struct RXMD *nxtmd; - /* - * The rx ring is easy as its just an array of RXMD structs. New - * mbuf entries are allocated from the stack whenever the rx - * daemon forwards an incoming packet into it. Here, we - * pre-allocate the rx mbufs for the rx ring entries. - */ - for(i=0 ; inumRxbuffers; i++) - { - if( ((uint32_t)&sc->rx_ring[i] & 0x7) ) - { - rtems_panic ("etherlink : unit elnk%d rx ring entry %d not aligned to 8 bytes\n", sc->xl_unit, i ); - } - - /* allocate an mbuf for each receive descriptor */ - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - m->m_pkthdr.rcvif = &sc->arpcom.ac_if; - - if( i == sc->numRxbuffers-1 ) - nxtmd = &sc->rx_ring[0]; - else - nxtmd = &sc->rx_ring[i+1]; - - sc->rx_ring[i].next_md = nxtmd; - sc->rx_ring[i].mbuf = m; - - st_le32( &sc->rx_ring[i].status, 0); - st_le32( &sc->rx_ring[i].next, (uint32_t)phys_to_bus( nxtmd )); - st_le32( &sc->rx_ring[i].addr, (uint32_t)phys_to_bus( mtod(m, void *) )); - st_le32( &sc->rx_ring[i].length, XL_LAST_FRAG | XL_PACKET_SIZE ); - } - sc->curr_rx_md = &sc->rx_ring[0]; - } - - - { - struct TXMD *thismd, *nxtmd; - /* - * The tx ring is more complex. Each MD has an array of fragment - * descriptors that are loaded from each packet as they arrive - * from the stack. Each packet gets one ring entry, this allows - * the lanboard to efficiently assemble the piecemeal packets into - * a contiguous unit at transmit time, rather than spending - * cputime concatenating them first. Although the next_md fields - * form a ring, the DPD next is filled only when packets are added - * to the tx chain, thus last entry of a series of packets has the - * requisite dpd->next value == 0 to terminate the dma. mbuf - * holds the packet info so it can be freed once the packet has - * been sent. chainptr is used to link the head & tail of a chain - * of 2 or more packets. A chain is formed when the tx daemon - * gets 2 or more packets from the stack's queue in a service - * period, so higher outgoing loads are handled as efficiently as - * possible. - */ - - for(i=0 ; inumTxbuffers; i++) - { - if( ((uint32_t)&sc->tx_ring[i] & 0x7) ) - { - rtems_panic ("etherlink : unit elnk%d tx ring entry %d not aligned to 8 bytes\n", sc->xl_unit, i ); - } - - if( i == sc->numTxbuffers-1 ) - nxtmd = &sc->tx_ring[0]; - else - nxtmd = &sc->tx_ring[i+1]; - - thismd = &sc->tx_ring[i]; - - thismd->next_md = nxtmd; - thismd->chainptr = NULL; - thismd->mbuf = NULL; - - st_le32( &thismd->status, XL_TXSTAT_DL_COMPLETE ); - st_le32( &thismd->next, 0); - - for(j=0; j< NUM_FRAGS; j++) - { - st_le32( &thismd->txfrags[j].addr, 0 ); - st_le32( &thismd->txfrags[j].length, 0 ); - } - } - sc->last_tx_md = &sc->tx_ring[0]; - } - - - - -#ifdef ELNK_DEBUG - printk("etherlink : %02x:%02x:%02x:%02x:%02x:%02x name 'elnk%d', io %x, int %d\n", - sc->arpcom.ac_enaddr[0], sc->arpcom.ac_enaddr[1], - sc->arpcom.ac_enaddr[2], sc->arpcom.ac_enaddr[3], - sc->arpcom.ac_enaddr[4], sc->arpcom.ac_enaddr[5], - sc->xl_unit, - (unsigned)sc->ioaddr, sc->irqInfo.name ); -#endif - - - sc->irqInfo.hdl = (rtems_irq_hdl)elnk_interrupt_handler_entry; - sc->irqInfo.on = no_op; - sc->irqInfo.off = no_op; - sc->irqInfo.isOn = NULL; - - if( sc->irqInfo.name != 255 ) - { - int st; - -#ifdef BSP_SHARED_HANDLER_SUPPORT - st = BSP_install_rtems_shared_irq_handler( &sc->irqInfo ); -#else - st = BSP_install_rtems_irq_handler( &sc->irqInfo ); -#endif - if (!st) - rtems_panic ("etherlink : unit elnk%d Interrupt name %d already in use\n", sc->xl_unit, sc->irqInfo.name ); - } - else - { - printk("etherlink : unit elnk%d Interrupt not specified by device\n", sc->xl_unit ); - } -} - - - - - - - - - - - -static void -elnk_rxDaemon (void *arg) -{ - struct elnk_softc *sc; - struct ether_header *eh; - struct mbuf *m; - struct RXMD *rmd; - unsigned int i,len, rxstat; - rtems_event_set events; - - for (;;) - { - - rtems_bsdnet_event_receive( RTEMS_ALL_EVENTS, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - - for(;;) - { - for(i=0; i< NUM_UNITS; i++ ) - { - sc = &elnk_softc[i]; - if( sc->ioaddr ) - { - if( events & sc->ioevent ) - { - struct ifnet *ifp = &sc->arpcom.ac_if; - - rmd = sc->curr_rx_md; - - /* - ** Read off all the packets we've received on this unit - */ - while( (rxstat = ld_le32(&rmd->status)) ) - { - if (rxstat & XL_RXSTAT_UP_ERROR) - { - printk("unit %i up error\n", sc->xl_unit ); - ifp->if_ierrors++; - } - - if( (rxstat & XL_RXSTAT_UP_CMPLT) ) - { - -#if 0 - { - char *pkt, *delim; - int i; - pkt = mtod(rmd->mbuf, char *); - printk("unit %i rx pkt (%08x) ", sc->xl_unit, pkt ); - for(delim="", i=0; i < sizeof(struct ether_header)+8; i++, delim=":") - printk("%s%02x", delim, (char) pkt[i] ); - printk("\n"); - } -#endif - - /* pass on the packet in the mbuf */ - len = ( ld_le32(&rmd->status) & XL_RXSTAT_LENMASK); - m = rmd->mbuf; - m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header); - eh = mtod(m, struct ether_header *); - m->m_data += sizeof(struct ether_header); - - ether_input(ifp, eh, m); - - /* get a new mbuf */ - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - rmd->mbuf = m; - st_le32( &rmd->status, 0 ); - st_le32( &rmd->addr, (uint32_t)phys_to_bus(mtod(m, void *)) ); - } - else - { - /* some kind of packet failure */ - printk("etherlink : unit elnk%d bad receive status -- packet dropped\n", sc->xl_unit); - ifp->if_ierrors++; - } - /* clear descriptor status */ - rmd->status = 0; - - rmd = rmd->next_md; - } - - sc->curr_rx_md = rmd; - } - } - } - - /* - ** If more events are pending, service them before we go back to sleep - */ - if( rtems_event_system_receive( RTEMS_ALL_EVENTS, - RTEMS_NO_WAIT | RTEMS_EVENT_ANY, - 0, - &events ) == RTEMS_UNSATISFIED ) break; - } - } -} - - - - - - - - -/* - * Driver transmit daemon - */ -static void -elnk_txDaemon (void *arg) -{ - struct elnk_softc *sc; - struct ifnet *ifp; - struct mbuf *m; - struct TXMD *lastmd, *nextmd, *firstmd; - int chainCount,i; - rtems_event_set events; - - for (;;) - { - /* - * Wait for any unit's signal to wake us up - */ - rtems_bsdnet_event_receive( RTEMS_ALL_EVENTS, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, &events); - - for(i=0; i< NUM_UNITS; i++ ) - { - sc = &elnk_softc[i]; - if( sc->ioaddr ) - { - if( events & sc->ioevent ) - { - ifp = &sc->arpcom.ac_if; - - /* - * Send packets till queue is empty or tx ring is full - */ - - chainCount = 0; - firstmd = NULL; - - lastmd = sc->last_tx_md; - - for(;;) - { - /* - ** Check the chain recovery queue whenever the tx - ** daemon services the stack. Note this routine does - ** not assume the context of one of the lanboard units - ** because used tx mbufs are no longer associated with - ** any unit. - */ - { - struct TXMD *chainhead, *chaintail; - size_t esize; - - if( rtems_message_queue_receive( chainRecoveryQueue, &chainhead, &esize, - RTEMS_NO_WAIT, 0) == RTEMS_SUCCESSFUL ) - { - /* get a pointer to the tail */ - chaintail = chainhead->chainptr; - - /* if the tail points somewhere, free the entire - chain */ - if( chaintail && (int)chaintail != -1 ) - { - for(;;) - { - m_freem( chainhead->mbuf ); - st_le32( &chainhead->status, XL_TXSTAT_DL_COMPLETE ); - chainhead->mbuf = NULL; - - if( chainhead == chaintail ) break; - chainhead = chainhead->next_md; - } - } - else - { - /* a single packet chain */ - m_freem( chainhead->mbuf ); - st_le32( &chainhead->status, XL_TXSTAT_DL_COMPLETE ); - chainhead->mbuf = NULL; - } - } - } - - nextmd = lastmd->next_md; - - /* stop when ring is full */ - if( ! (ld_le32(&nextmd->status) & XL_TXSTAT_DL_COMPLETE) ) - { - printk("etherlink : unit elnk%d tx ring full!\n", sc->xl_unit); - break; - } - /* sanity check the next packet descriptor */ - if( nextmd->mbuf ) - { - printk("etherlink : unit elnk%d tx ring corrupt!\n", sc->xl_unit); - break; - } - - - - IF_DEQUEUE(&ifp->if_snd, m); - if( !m ) break; - - { - int i; - - nextmd->mbuf = m; - - for(i=0; i< NUM_FRAGS; i++) - { - st_le32( &nextmd->txfrags[i].length, ((m->m_next)?0:XL_LAST_FRAG) | ( m->m_len & XL_TXSTAT_LENMASK) ); - st_le32( &nextmd->txfrags[i].addr, (uint32_t)phys_to_bus( m->m_data ) ); - if ((m = m->m_next) == NULL) - break; - } - if( m ) - { - printk("etherlink : unit elnk%d tx fragments exhausted, truncating packet!\n", sc->xl_unit); - st_le32( &nextmd->txfrags[NUM_FRAGS-1].length, XL_LAST_FRAG | - ld_le32( &nextmd->txfrags[NUM_FRAGS-1].length) ); - } - } - -#if 0 - { - char *pkt = bus_to_phys( ld_le32( &nextmd->txfrags[i].addr )), *delim; - int i; - printk("unit %d queued pkt (%08x) ", sc->xl_unit, (uint32_t)pkt ); - for(delim="", i=0; i < sizeof(struct ether_header); i++, delim=":") - printk("%s%02x", delim, (char) pkt[i] ); - printk("\n"); - } -#endif - - - /* this packet will be the new end of the list */ - st_le32( &nextmd->next, 0); - st_le32( &nextmd->status, 0); - - if( !firstmd ) - { - /* keep track of the first packet we add to the chain */ - firstmd = nextmd; - - /* - ** use the chainbuf pointer of the last packet of - ** the previous chain as a flag so when a - ** dnComplete interrupt indicates the card is - ** finished downloading the chain, the isr can - ** immediately start the next which always begins - ** with the next packet in the ring. Note several - ** chains of packets may be assembled this way. - */ - lastmd->chainptr = (struct TXMD *)-1; - } - else - { - /* hook this packet to the previous one */ - st_le32( &lastmd->next, (uint32_t)phys_to_bus( nextmd )); - } - - ++chainCount; - lastmd = nextmd; - } - - - - - - if( firstmd ) - { - /* only enter if we've queued one or more packets */ - - /* save the last descriptor we set up in the chain */ - sc->last_tx_md = lastmd; - - /* - * We've added one or more packets to a chain, flag - * the last packet so we get an dnComplete interrupt - * when the card finishes accepting the chain - */ - st_le32( &lastmd->status, XL_TXSTAT_DL_INTR ); - - /* - * point the chain head's chainptr to the tail so we - * can jump to the next chain to send inside the isr. - * If we're only sending one packet, then don't bother - * with the link, as the chainptr value will either be - * 0 if theres no next chain or -1 if there is. - */ - if( chainCount > 1 ) - { - firstmd->chainptr = lastmd; - - sc->chain_lengths[sc->chlenIndex]= (short)chainCount; - if( ++sc->chlenIndex == NUM_CHAIN_LENGTHS ) sc->chlenIndex = 0; - } - - /* - ** clear the last packet's chainptr flag. If another - ** chain is added later but before this chain is - ** finished being sent, this flag on this packet will - ** be re-set to -1 - */ - lastmd->chainptr = NULL; - -#if 0 - printk("unit %d queued %d pkts, lastpkt status %08X\n", - sc->xl_unit, - chainCount, - (uint32_t)ld_le32( &lastmd->status) ); -#endif - - if( sc->tx_idle == 0 && CSR_READ_4(sc, XL_DOWNLIST_PTR) == 0 ) - { - printk("etherlink : unit elnk%d tx forced!\n", sc->xl_unit); - sc->tx_idle = -1; - } - - /* - ** start sending this chain of packets if tx isn't - ** busy, else the dnComplete interrupt will see there - ** is another chain waiting and begin it immediately. - */ - if( sc->tx_idle ) - { -#if 0 - printk("etherlink : unit elnk%d tx started %d packets\n", sc->xl_unit, chainCount ); -#endif - elnk_start_txchain(sc, firstmd); - } - } - - - ifp->if_flags &= ~IFF_OACTIVE; - } - } - } - } -} - - - - - - - - - - - -static void -elnk_start (struct ifnet *ifp) -{ - struct elnk_softc *sc = ifp->if_softc; -#if 0 - printk("unit %i tx signaled\n", sc->xl_unit ); -#endif - ifp->if_flags |= IFF_OACTIVE; - rtems_bsdnet_event_send( txDaemonTid, sc->ioevent ); -} - - - - - - - - - - - - - - - -/* - * Initialize and start the device - */ -static void -elnk_init (void *arg) -{ - int i; - struct elnk_softc *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - - if( !(ifp->if_flags & IFF_RUNNING) ) - { - xl_stop(sc); - xl_reset(sc); - sc->tx_idle = -1; - - { - uint32_t cr,sr; - - xl_miibus_writereg(sc, 0x18, MII_BMCR, BMCR_RESET ); - - while( (cr = xl_miibus_readreg(sc, 0x18, MII_BMCR )) & BMCR_RESET ) - { - DELAY(100000); - } - - xl_miibus_writereg(sc, 0x18, MII_ANAR, ANAR_10 | ANAR_TX | ANAR_10_FD | ANAR_TX_FD ); /* ANAR_T4 */ - xl_miibus_writereg(sc, 0x18, MII_BMCR, BMCR_STARTNEG | BMCR_AUTOEN ); - - for (i=0; ((sr = xl_miibus_readreg(sc, 0x18, MII_BMSR)) & BMSR_ACOMP) == 0 && i < 20; i++) - DELAY(10000); - } - - - /* - * Set up hardware if its not already been done - */ - if( !sc->irqInfo.hdl ) - { - elnk_initialize_hardware(sc); - } - - /* - * Enable the card - */ - { - u_int8_t rxfilt; - - /* Init our MAC address */ - XL_SEL_WIN(2); - for (i = 0; i < ETHER_ADDR_LEN; i++) - { - CSR_WRITE_1(sc, XL_W2_STATION_ADDR_LO + i, sc->arpcom.ac_enaddr[i]); - } - - { - int media = IFM_ETHER|IFM_100_TX|IFM_FDX; - - xl_mediacheck(sc); - - /* Choose a default media. */ - switch(sc->xl_xcvr) { - case XL_XCVR_10BT: - media = IFM_ETHER|IFM_10_T; - xl_setmode(sc, media); - break; - case XL_XCVR_AUI: - if (sc->xl_type == XL_TYPE_905B && - sc->xl_media == XL_MEDIAOPT_10FL) { - media = IFM_ETHER|IFM_10_FL; - xl_setmode(sc, media); - } else { - media = IFM_ETHER|IFM_10_5; - xl_setmode(sc, media); - } - break; - case XL_XCVR_COAX: - media = IFM_ETHER|IFM_10_2; - xl_setmode(sc, media); - break; - case XL_XCVR_AUTO: - case XL_XCVR_100BTX: - xl_setcfg(sc); - break; - case XL_XCVR_MII: - printk( - "etherlink : unit elnk%d MII media not supported!\n", - sc->xl_unit); - break; - case XL_XCVR_100BFX: - media = IFM_ETHER|IFM_100_FX; - break; - default: - printk( - "etherlink : unit elnk%d unknown XCVR type: %" PRId32 "\n", - sc->xl_unit, - sc->xl_xcvr); - /* - * This will probably be wrong, but it prevents - * the ifmedia code from panicking. - */ - media = IFM_ETHER|IFM_10_T; - break; - } - - - if (sc->xl_flags & XL_FLAG_NO_XCVR_PWR) { - XL_SEL_WIN(0); - CSR_WRITE_2(sc, XL_W0_MFG_ID, XL_NO_XCVR_PWR_MAGICBITS); - } - } - - - - XL_SEL_WIN(2); - /* Clear the station mask. */ - for (i = 0; i < 3; i++) - CSR_WRITE_2(sc, XL_W2_STATION_MASK_LO + (i * 2), 0); - - /* - * Set the TX freethresh value. - * Note that this has no effect on 3c905B "cyclone" - * cards but is required for 3c900/3c905 "boomerang" - * cards in order to enable the download engine. - */ - CSR_WRITE_1(sc, XL_TX_FREETHRESH, XL_PACKET_SIZE >> 8); - - /* Set the TX start threshold for best performance. */ - sc->xl_tx_thresh = XL_MIN_FRAMELEN; - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_SET_START|sc->xl_tx_thresh); - - /* - * If this is a 3c905B, also set the tx reclaim threshold. - * This helps cut down on the number of tx reclaim errors - * that could happen on a busy network. The chip multiplies - * the register value by 16 to obtain the actual threshold - * in bytes, so we divide by 16 when setting the value here. - * The existing threshold value can be examined by reading - * the register at offset 9 in window 5. - */ - if (sc->xl_type == XL_TYPE_905B) { - CSR_WRITE_2(sc, XL_COMMAND, - XL_CMD_SET_TX_RECLAIM|(XL_PACKET_SIZE >> 4)); - } - - /* Set RX filter bits. */ - XL_SEL_WIN(5); - rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER); - - /* Set the individual bit to receive frames for this host only. */ - rxfilt |= XL_RXFILTER_INDIVIDUAL; - - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) { - rxfilt |= XL_RXFILTER_ALLFRAMES; - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt); - } else { - rxfilt &= ~XL_RXFILTER_ALLFRAMES; - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt); - } - - /* - * Set capture broadcast bit to capture broadcast frames. - */ - if (ifp->if_flags & IFF_BROADCAST) { - rxfilt |= XL_RXFILTER_BROADCAST; - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt); - } else { - rxfilt &= ~XL_RXFILTER_BROADCAST; - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt); - } - -#if 0 - /* - * Program the multicast filter, if necessary. - */ - if (sc->xl_type == XL_TYPE_905B) - xl_setmulti_hash(sc); - else - xl_setmulti(sc); -#endif - /* - * Load the address of the RX list. We have to - * stall the upload engine before we can manipulate - * the uplist pointer register, then unstall it when - * we're finished. We also have to wait for the - * stall command to complete before proceeding. - * Note that we have to do this after any RX resets - * have completed since the uplist register is cleared - * by a reset. - */ - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_STALL); - xl_wait(sc); - CSR_WRITE_4(sc, XL_UPLIST_PTR, phys_to_bus( sc->curr_rx_md )); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_UNSTALL); - xl_wait(sc); - - -#if 0 - if (sc->xl_type == XL_TYPE_905B) { - /* Set polling interval */ - CSR_WRITE_1(sc, XL_DOWN_POLL, 64); - xl_wait(sc); - printk("etherlink : unit elnk%d tx polling enabled\n", sc->xl_unit ); - } -#endif - - /* - * If the coax transceiver is on, make sure to enable - * the DC-DC converter. - */ - XL_SEL_WIN(3); - if (sc->xl_xcvr == XL_XCVR_COAX) - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_START); - else - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_STOP); - - /* increase packet size to allow reception of 802.1q or ISL packets */ - if (sc->xl_type == XL_TYPE_905B) - CSR_WRITE_2(sc, XL_W3_MAXPKTSIZE, XL_PACKET_SIZE); - /* Clear out the stats counters. */ - - memset( &sc->xl_stats, 0, sizeof(struct xl_stats)); - - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STATS_DISABLE); - sc->xl_stats_no_timeout = 1; - xl_stats_update(sc->stat_timer_id,sc); - sc->xl_stats_no_timeout = 0; - XL_SEL_WIN(4); - CSR_WRITE_2(sc, XL_W4_NET_DIAG, XL_NETDIAG_UPPER_BYTES_ENABLE); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STATS_ENABLE); - - - /* - * Enable interrupts. - */ - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ACK|0xFF); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STAT_ENB|XL_INTRS); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|XL_INTRS); - - /* Set the RX early threshold */ - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_THRESH|(XL_PACKET_SIZE >>2)); - CSR_WRITE_4(sc, XL_DMACTL, XL_DMACTL_UP_RX_EARLY ); - - /* Enable receiver and transmitter. */ - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_ENABLE); - xl_wait(sc); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_ENABLE); - xl_wait(sc); - - /* Select window 7 for normal operations. */ - XL_SEL_WIN(7); - - /* schedule the stats update timer */ - rtems_timer_fire_after( sc->stat_timer_id, sc->stats_update_ticks, xl_stats_update, (void *)sc ); - } - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; - } -} - - - - - - - -/* - * Stop the device - */ -static void -elnk_stop (struct elnk_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - int i; - - /* - * Stop the transmitter - */ - xl_stop(sc); - xl_reset(sc); - sc->tx_idle = -1; - - ifp->if_flags &= ~IFF_RUNNING; - - /* - ** Clear out the rx & tx rings - */ - { - struct TXMD *chainhead; - size_t esize; - - while( rtems_message_queue_receive( chainRecoveryQueue, &chainhead, &esize, - RTEMS_NO_WAIT, 0) == RTEMS_SUCCESSFUL ); - } - - for(i=0 ; inumRxbuffers; i++) - { - st_le32( &sc->rx_ring[i].status, 0); - st_le32( &sc->rx_ring[i].length, XL_LAST_FRAG | XL_PACKET_SIZE ); - } - - for(i=0 ; inumTxbuffers; i++) - { - st_le32( &sc->tx_ring[i].status, XL_TXSTAT_DL_COMPLETE ); - st_le32( &sc->tx_ring[i].next, 0); - if( sc->tx_ring[i].mbuf ) - { - m_free( sc->tx_ring[i].mbuf ); - sc->tx_ring[i].mbuf = NULL; - } - } -} - - - - -/* - * Show interface statistics - */ -static void -elnk_stats (struct elnk_softc *sc) -{ - printf(" MII PHY data { anr:%04x lpar:%04x stat:%04x ctl:%04x }\n", - sc->xl_stats.miianr, - sc->xl_stats.miipar, - sc->xl_stats.miistatus, - sc->xl_stats.miicmd); - - printf(" internalcfg:%08" PRIx32 " macctl:%04x dmactl:%08" PRIx32 "\n", - sc->xl_stats.internalconfig, - sc->xl_stats.mac_control, - sc->xl_stats.dmactl); - - printf(" rxstatus:%04x txstatus:%02x smbstat:%04x\n", - sc->xl_stats.rxstatus, - sc->xl_stats.txstatus, - sc->xl_stats.smbstatus); - - printf(" txfree:%04X intstatus:%04x mediastat:%04x\n", - sc->xl_stats.txfree, - sc->xl_stats.intstatus, - sc->xl_stats.mediastatus); - - - { - int i, totalLengths= 0, numLengths= 0; - - for(i=0; i< NUM_CHAIN_LENGTHS; i++) - { - if( sc->chain_lengths[i] > -1 ) - { - totalLengths += sc->chain_lengths[i]; - ++numLengths; - } - } - - printf(" interrupts:%-9" PRIu32 " txcmp_ints:%-5" PRIu32 " avg_chain_len:%-4d\n", - sc->xl_stats.device_interrupts, - sc->xl_stats.txcomplete_ints, - numLengths ? (totalLengths / numLengths) : -1 ); - } - - printf(" carrier_lost:%-5d sqe_errs:%-5d\n", - sc->xl_stats.xl_carrier_lost, - sc->xl_stats.xl_sqe_errs); - - printf(" tx_multi_collision:%-5d tx_single_collision:%-5d\n", - sc->xl_stats.xl_tx_multi_collision, - sc->xl_stats.xl_tx_single_collision); - - printf(" tx_late_collision:%-5d rx_overrun:%-5d\n", - sc->xl_stats.xl_tx_late_collision, - sc->xl_stats.xl_rx_overrun); - - printf(" tx_deferred:%-5d badssd:%-5d\n", - sc->xl_stats.xl_tx_deferred, - sc->xl_stats.xl_badssd); - - printf(" rx_frames_ok:%-9" PRIu32 " tx_frames_ok:%-9" PRIu32 "\n", - sc->xl_stats.xl_rx_frames_ok, - sc->xl_stats.xl_tx_frames_ok); - - printf(" rx_bytes_ok:%-9" PRIu32 " tx_bytes_ok:%-9" PRIu32 "\n", - sc->xl_stats.xl_rx_bytes_ok, - sc->xl_stats.xl_tx_bytes_ok ); -} - - - - - - - -/* - * Driver ioctl handler - */ -static int -elnk_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - struct elnk_softc *sc = ifp->if_softc; - int error = 0; - - switch (command) { - case SIOCGIFADDR: - case SIOCSIFADDR: - ether_ioctl (ifp, command, data); - break; - - case SIOCSIFFLAGS: - switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { - case IFF_RUNNING: - elnk_stop (sc); - break; - - case IFF_UP: - elnk_init (sc); - break; - - case IFF_UP | IFF_RUNNING: - elnk_stop (sc); - elnk_init (sc); - break; - - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - elnk_stats (sc); - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } - - return error; -} - - - - - - - - -#if 0 -static int iftap(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m ) -{ - int i; - char *delim, *pkt; - - printk("unit %i, src ", ifp->if_unit ); - for(delim= "", i=0; i< ETHER_ADDR_LEN; i++, delim=":") - printk("%s%02x", delim, (char) eh->ether_shost[i] ); - - printk(" dest "); - - for(delim= "", i=0; i< ETHER_ADDR_LEN; i++, delim=":") - printk("%s%02x", delim, (char) eh->ether_dhost[i] ); - printk(" pkt "); - - pkt = (char *)eh; - for(delim="", i=0; i < sizeof(struct ether_header); i++, delim=":") - printk("%s%02x", delim, (char) pkt[i] ); - - printk("\n"); - return 0; -} -#endif - - - -struct el_boards -{ - int pbus,pdev,pfun, vid, did, tindex; -}; - -/* Prototype to avoid warning. This must be a global symbol. */ -int rtems_elnk_driver_attach(struct rtems_bsdnet_ifconfig *config, int attach); - -/* - * Attach an ELNK driver to the system - */ -int -rtems_elnk_driver_attach (struct rtems_bsdnet_ifconfig *config, int attach) -{ - struct elnk_softc *sc; - struct ifnet *ifp; - char *unitName; - int unitNumber; - int mtu, i; - unsigned char cvalue; - struct el_boards sysboards[NUM_UNITS]; - int numFound = 0; - int pbus, pdev, pfun; -#if defined(__i386__) - uint32_t value; - uint8_t interrupt; -#endif -#if defined(__PPC__) - uint32_t lvalue; -#endif - - - /* - * Get the instance number for the board we're going to configure - * from the user. - */ - if( (unitNumber = rtems_bsdnet_parse_driver_name( config, &unitName)) == -1 ) - { - return 0; - } - - if( strcmp(unitName, DRIVER_PREFIX) ) - { - printk("etherlink : invalid unit name '%s'\n", unitName ); - return 0; - } - - if ((unitNumber < 1) || (unitNumber > NUM_UNITS)) - { - printk("etherlink : unit %i is invalid, must be (1 <= n <= %d)\n", unitNumber, NUM_UNITS); - return 0; - } - - - { - int done= 0, unum; - - /* - * Run thru the list of boards, finding all that are present in - * the system. Sort by slot,dev - and then use the unitNumber-1 - * to index the list and select the device. Yucky. - */ - for( i=0; !done && xl_devs[i].xl_vid; i++) - { - for(unum= 1; !done && - pci_find_device( xl_devs[i].xl_vid, xl_devs[i].xl_did, unum-1, - &sysboards[numFound].pbus, - &sysboards[numFound].pdev, - &sysboards[numFound].pfun)==0; unum++) - { - if( numFound == NUM_UNITS ) - { - printk("etherlink : Maximum of %d units found, extra devices ignored.\n", NUM_UNITS ); - done=-1; - } - else - { - sysboards[numFound].vid = xl_devs[i].xl_vid; - sysboards[numFound].did = xl_devs[i].xl_did; - sysboards[numFound].tindex = i; - ++numFound; - } - } - } - - if( ! numFound ) - { - printk("etherlink : No Etherlink devices found\n"); - return 0; - } - - if( unitNumber-1 >= numFound ) - { - printk("etherlink : device '%s' not found\n", config->name ); - return 0; - } - - /* - * Got the list of etherlink boards in the system, now sort by - * slot,device. bubble sorts aren't all that wonderful, but this - * is a short & infrequently sorted list. - */ - if( numFound > 1 ) - { - struct el_boards tboard; - int didsort; - - do - { - didsort = 0; - - for(i=1; i sysboards[i].pbus || - (sysboards[i-1].pbus == sysboards[i].pbus && sysboards[i-1].pdev > sysboards[i].pdev) ) - { - memcpy(&tboard, &sysboards[i-1], sizeof(struct el_boards)); - memcpy(&sysboards[i-1], &sysboards[i], sizeof(struct el_boards)); - memcpy(&sysboards[i], &tboard, sizeof(struct el_boards)); - didsort++; - } - } - } - while( didsort ); - } - - /* - ** board list is sorted, now select the unit - */ - - pbus = sysboards[unitNumber-1].pbus; - pdev = sysboards[unitNumber-1].pdev; - pfun = sysboards[unitNumber-1].pfun; - } - - sc = &elnk_softc[unitNumber - 1]; - ifp = &sc->arpcom.ac_if; - if (ifp->if_softc != NULL) - { - printk("etherlink : unit %i already in use.\n", unitNumber ); - return 0; - } - - /* - ** Save various things - */ - sc->xl_unit = unitNumber; - sc->xl_type = sysboards[ unitNumber-1 ].tindex; - - sc->vendorID = sysboards[numFound].vid; - sc->deviceID = sysboards[numFound].did; - - sc->numRxbuffers = (config->rbuf_count) ? config->rbuf_count : RX_RING_SIZE; - sc->numTxbuffers = (config->xbuf_count) ? config->xbuf_count : TX_RING_SIZE; - - - for(i=0; i< NUM_CHAIN_LENGTHS; i++) sc->chain_lengths[i]= -1; - sc->chlenIndex = 0; - - - if (config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - - sc->acceptBroadcast = !config->ignore_broadcast; - - - -#ifdef ELNK_DEBUG - printk("etherlink : device '%s', name 'elnk%d', pci %02x:%02x.%02x, %d rx/%d tx buffers\n", - xl_devs[sc->xl_type].xl_name, sc->xl_unit, - pbus, pdev, pfun, - sc->numRxbuffers, sc->numTxbuffers); -#endif - - - /* - ** Create this unit's stats timer - */ - if( rtems_timer_create( rtems_build_name( 'X', 'L', 't', (char)(sc->xl_unit & 255)), - &sc->stat_timer_id ) != RTEMS_SUCCESSFUL ) - { - printk("etherlink : unit elnk%d unable to create stats timer\n", sc->xl_unit ); - return 0; - } - - /* update stats 1 times/second if things aren't incrementing fast - * enough to trigger stats interrupts - */ - sc->stats_update_ticks = rtems_clock_get_ticks_per_second(); - - /* - ** Get this unit's rx/tx event - */ - sc->ioevent = unit_signals[unitNumber-1]; - - -#if defined(__i386__) - pci_read_config_dword(pbus, pdev, pfun, 16, &value); - sc->ioaddr = value & ~IO_MASK; - - pci_read_config_byte(pbus, pdev, pfun, 60, &interrupt); - cvalue = interrupt; -#endif -#if defined(__PPC__) - /* - ** Prep the board - */ - pci_write_config_word(pbus, pdev, pfun, - PCI_COMMAND, - (uint16_t)( PCI_COMMAND_IO | - PCI_COMMAND_MASTER | - PCI_COMMAND_INVALIDATE | - PCI_COMMAND_WAIT ) ); - /* - * Get the device's base address - */ - pci_read_config_dword(pbus, pdev, pfun, - PCI_BASE_ADDRESS_0, - &lvalue); - - sc->ioaddr = (uint32_t)lvalue & PCI_BASE_ADDRESS_IO_MASK; - /* - ** Store the interrupt name, we'll use it later when we initialize - ** the board. - */ - pci_read_config_byte(pbus, pdev, pfun, - PCI_INTERRUPT_LINE, - &cvalue); -#endif - - memset(&sc->irqInfo,0,sizeof(rtems_irq_connect_data)); - sc->irqInfo.name = cvalue; - - - /* - ** Establish basic board config, set node address from config or - ** board eeprom, do stuff with additional device properties - */ - - { - uint8_t pci_latency; - uint8_t new_latency = 248; - - /* Check the PCI latency value. On the 3c590 series the latency timer - must be set to the maximum value to avoid data corruption that occurs - when the timer expires during a transfer. This bug exists the Vortex - chip only. */ -#if defined(__i386__) - pci_read_config_byte(pbus, pdev, pfun, 0x0d, &pci_latency); -#endif -#if defined(__PPC__) - pci_read_config_byte(pbus,pdev,pfun, PCI_LATENCY_TIMER, &pci_latency); -#endif - if (pci_latency < new_latency) - { - printk("etherlink : unit elnk%d Overriding PCI latency, timer (CFLT) setting of %d, new value is %d.\n", sc->xl_unit, pci_latency, new_latency ); -#if defined(__i386__) - pci_write_config_byte(pbus, pdev, pfun, 0x0d, new_latency); -#endif -#if defined(__PPC__) - pci_write_config_byte(pbus,pdev,pfun, PCI_LATENCY_TIMER, new_latency); -#endif - } - } - - /* Reset the adapter. */ - xl_reset(sc); - - - { - u_int16_t xcvr[2]; - u_char eaddr[ETHER_ADDR_LEN]; - - sc->xl_flags = 0; - if (sc->deviceID == TC_DEVICEID_HURRICANE_555) - sc->xl_flags |= XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_PHYOK; - if (sc->deviceID == TC_DEVICEID_HURRICANE_556 || - sc->deviceID == TC_DEVICEID_HURRICANE_556B) - sc->xl_flags |= XL_FLAG_FUNCREG | XL_FLAG_PHYOK | - XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_WEIRDRESET | - XL_FLAG_INVERT_LED_PWR | XL_FLAG_INVERT_MII_PWR; - if (sc->deviceID == TC_DEVICEID_HURRICANE_555 || - sc->deviceID == TC_DEVICEID_HURRICANE_556) - sc->xl_flags |= XL_FLAG_8BITROM; - if (sc->deviceID == TC_DEVICEID_HURRICANE_556B) - sc->xl_flags |= XL_FLAG_NO_XCVR_PWR; - - if (sc->deviceID == TC_DEVICEID_HURRICANE_575A || - sc->deviceID == TC_DEVICEID_HURRICANE_575B || - sc->deviceID == TC_DEVICEID_HURRICANE_575C || - sc->deviceID == TC_DEVICEID_HURRICANE_656B || - sc->deviceID == TC_DEVICEID_TORNADO_656C) - sc->xl_flags |= XL_FLAG_FUNCREG | XL_FLAG_PHYOK | - XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM; - if (sc->deviceID == TC_DEVICEID_HURRICANE_656) - sc->xl_flags |= XL_FLAG_FUNCREG | XL_FLAG_PHYOK; - if (sc->deviceID == TC_DEVICEID_HURRICANE_575B) - sc->xl_flags |= XL_FLAG_INVERT_LED_PWR; - if (sc->deviceID == TC_DEVICEID_HURRICANE_575C) - sc->xl_flags |= XL_FLAG_INVERT_MII_PWR; - if (sc->deviceID == TC_DEVICEID_TORNADO_656C) - sc->xl_flags |= XL_FLAG_INVERT_MII_PWR; - if (sc->deviceID == TC_DEVICEID_HURRICANE_656 || - sc->deviceID == TC_DEVICEID_HURRICANE_656B) - sc->xl_flags |= XL_FLAG_INVERT_MII_PWR | - XL_FLAG_INVERT_LED_PWR; - if (sc->deviceID == TC_DEVICEID_TORNADO_10_100BT_920B) - sc->xl_flags |= XL_FLAG_PHYOK; - - - if (config->hardware_address) - { - memcpy(sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); - } - else - { - if (xl_read_eeprom(sc, (caddr_t)&eaddr, XL_EE_OEM_ADR0, 3, 1)) - { - printk("etherlink : unit elnk%d Failed to read station address\n", sc->xl_unit ); - return 0; - } - memcpy((char *)&sc->arpcom.ac_enaddr, eaddr, ETHER_ADDR_LEN); - } - - /* - * Figure out the card type. 3c905B adapters have the - * 'supportsNoTxLength' bit set in the capabilities - * word in the EEPROM. - */ - xl_read_eeprom(sc, (caddr_t)&sc->xl_caps, XL_EE_CAPS, 1, 0); - if (sc->xl_caps & XL_CAPS_NO_TXLENGTH) - sc->xl_type = XL_TYPE_905B; - else - sc->xl_type = XL_TYPE_90X; - - - /* - * Now we have to see what sort of media we have. - * This includes probing for an MII interace and a - * possible PHY. - */ - XL_SEL_WIN(3); - sc->xl_media = CSR_READ_2(sc, XL_W3_MEDIA_OPT); - - xl_read_eeprom(sc, (char *)&xcvr, XL_EE_ICFG_0, 2, 0); - sc->xl_xcvr = xcvr[0] | xcvr[1] << 16; - sc->xl_xcvr &= XL_ICFG_CONNECTOR_MASK; - sc->xl_xcvr >>= XL_ICFG_CONNECTOR_BITS; - -#if 0 - printk("etherlink : unit elnk%d EEPROM set xcvr to 0x%x\n", sc->xl_unit, sc->xl_xcvr); -#endif - - { - char msg[255]; - int i; - - struct _availmedia - { - int bit; - char *name; - } _am[]= {{ XL_MEDIAOPT_BT4, "100BaseT4" }, - { XL_MEDIAOPT_BTX, "100BaseTX" }, - { XL_MEDIAOPT_BFX, "100BaseFX" }, - { XL_MEDIAOPT_BT, "10BaseT" }, - { XL_MEDIAOPT_BNC, "10Base2" }, - { XL_MEDIAOPT_AUI, "10mbps AUI"}, - { XL_MEDIAOPT_MII, "MII"}, - { 0, NULL }}; - - msg[0]= 0; - for( i=0; _am[i].bit; i++) - { - if( sc->xl_media & _am[i].bit ) - sprintf( &msg[strlen(msg)], ",%s", _am[i].name ); - } - if( !strlen(msg) ) strcpy( &msg[1], ""); - - printk("etherlink : unit elnk%d available media : %s\n", sc->xl_unit, &msg[1]); - } - - XL_SEL_WIN(7); - } - - - - /* - * Set up network interface - */ - ifp->if_softc = sc; - ifp->if_name = unitName; - ifp->if_unit = sc->xl_unit; - ifp->if_mtu = mtu; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; - if (ifp->if_snd.ifq_maxlen == 0) - ifp->if_snd.ifq_maxlen = ifqmaxlen; - ifp->if_init = elnk_init; - ifp->if_start = elnk_start; - ifp->if_ioctl = elnk_ioctl; - ifp->if_output = ether_output; - -#if 0 - ifp->if_tap = iftap; -#endif - - /* - * Attach the interface - */ - if_attach (ifp); - ether_ifattach (ifp); - -#ifdef ELNK_DEBUG - printk( "etherlink : unit elnk%d driver attached\n", sc->xl_unit ); -#endif - - /* - * Start driver tasks if this is the first unit initialized - */ - if (txDaemonTid == 0) - { - if( rtems_message_queue_create( rtems_build_name('X','L','c','r'), - sc->numTxbuffers+1, - sizeof(struct TXMD *), - RTEMS_FIFO | RTEMS_LOCAL, - &chainRecoveryQueue ) != RTEMS_SUCCESSFUL ) - { - rtems_panic( "etherlink : Unable to create TX buffer recovery queue\n" ); - } - - - rxDaemonTid = rtems_bsdnet_newproc( "XLrx", 4096, - elnk_rxDaemon, NULL); - - txDaemonTid = rtems_bsdnet_newproc( "XLtx", 4096, - elnk_txDaemon, NULL); -#ifdef ELNK_DEBUG - printk( "etherlink : driver tasks created\n" ); -#endif - } - - return 1; -}; - -#endif /* ELNK_SUPPORTED */ - -/* eof */ diff --git a/c/src/libchip/network/greth.c b/c/src/libchip/network/greth.c deleted file mode 100644 index 20be83ee48..0000000000 --- a/c/src/libchip/network/greth.c +++ /dev/null @@ -1,1196 +0,0 @@ -/* - * Gaisler Research ethernet MAC driver - * adapted from Opencores driver by Marko Isomaki - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - * - * 2007-09-07, Ported GBIT support from 4.6.5 - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include -#include - -#ifdef GRETH_SUPPORTED - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#ifdef malloc -#undef malloc -#endif -#ifdef free -#undef free -#endif - -/* #define GRETH_DEBUG */ - -#ifdef CPU_U32_FIX -extern void ipalign(struct mbuf *m); -#endif - -/* Used when reading from memory written by GRETH DMA unit */ -#ifndef GRETH_MEM_LOAD -#define GRETH_MEM_LOAD(addr) (*(volatile unsigned int *)(addr)) -#endif - -/* - * Number of OCs supported by this driver - */ -#define NOCDRIVER 1 - -/* - * Receive buffer size -- Allow for a full ethernet packet including CRC - */ -#define RBUF_SIZE 1518 - -#define ET_MINLEN 64 /* minimum message length */ - -/* - * RTEMS event used by interrupt handler to signal driver tasks. - * This must not be any of the events used by the network task synchronization. - */ -#define INTERRUPT_EVENT RTEMS_EVENT_1 - -/* - * RTEMS event used to start transmit daemon. - * This must not be the same as INTERRUPT_EVENT. - */ -#define START_TRANSMIT_EVENT RTEMS_EVENT_2 - - /* event to send when tx buffers become available */ -#define GRETH_TX_WAIT_EVENT RTEMS_EVENT_3 - -#if (MCLBYTES < RBUF_SIZE) -# error "Driver must have MCLBYTES > RBUF_SIZE" -#endif - -/* 4s Autonegotiation Timeout */ -#ifndef GRETH_AUTONEGO_TIMEOUT_MS -#define GRETH_AUTONEGO_TIMEOUT_MS 4000 -#endif -const struct timespec greth_tan = { - GRETH_AUTONEGO_TIMEOUT_MS/1000, - (GRETH_AUTONEGO_TIMEOUT_MS % 1000) *1000000 -}; - -/* For optimizing the autonegotiation time */ -#define GRETH_AUTONEGO_PRINT_TIME - -/* Ethernet buffer descriptor */ - -typedef struct _greth_rxtxdesc { - volatile uint32_t ctrl; /* Length and status */ - uint32_t *addr; /* Buffer pointer */ -} greth_rxtxdesc; - - -/* - * Per-device data - */ -struct greth_softc -{ - - struct arpcom arpcom; - - greth_regs *regs; - - int acceptBroadcast; - rtems_id daemonTid; - - unsigned int tx_ptr; - unsigned int tx_dptr; - unsigned int tx_cnt; - unsigned int rx_ptr; - unsigned int txbufs; - unsigned int rxbufs; - greth_rxtxdesc *txdesc; - greth_rxtxdesc *rxdesc; - struct mbuf **rxmbuf; - struct mbuf **txmbuf; - rtems_vector_number vector; - - /* TX descriptor interrupt generation */ - int tx_int_gen; - int tx_int_gen_cur; - struct mbuf *next_tx_mbuf; - int max_fragsize; - - /*Status*/ - struct phy_device_info phydev; - int fd; - int sp; - int gb; - int gbit_mac; - int auto_neg; - struct timespec auto_neg_time; - - /* - * Statistics - */ - unsigned long rxInterrupts; - - unsigned long rxPackets; - unsigned long rxLengthError; - unsigned long rxNonOctet; - unsigned long rxBadCRC; - unsigned long rxOverrun; - - unsigned long txInterrupts; - - unsigned long txDeferred; - unsigned long txHeartbeat; - unsigned long txLateCollision; - unsigned long txRetryLimit; - unsigned long txUnderrun; - -}; - -static struct greth_softc greth; - -int greth_process_tx_gbit(struct greth_softc *sc); -int greth_process_tx(struct greth_softc *sc); - -static char *almalloc(int sz) -{ - char *tmp; - tmp = calloc(1,2*sz); - tmp = (char *) (((uintptr_t)tmp+sz) & ~(sz -1)); - return(tmp); -} - -/* GRETH interrupt handler */ - -static void greth_interrupt_handler (void *arg) -{ - uint32_t status; - uint32_t ctrl; - rtems_event_set events = 0; - struct greth_softc *greth = arg; - - /* read and clear interrupt cause */ - status = greth->regs->status; - greth->regs->status = status; - ctrl = greth->regs->ctrl; - - /* Frame received? */ - if ((ctrl & GRETH_CTRL_RXIRQ) && (status & (GRETH_STATUS_RXERR | GRETH_STATUS_RXIRQ))) - { - greth->rxInterrupts++; - /* Stop RX-Error and RX-Packet interrupts */ - ctrl &= ~GRETH_CTRL_RXIRQ; - events |= INTERRUPT_EVENT; - } - - if ( (ctrl & GRETH_CTRL_TXIRQ) && (status & (GRETH_STATUS_TXERR | GRETH_STATUS_TXIRQ)) ) - { - greth->txInterrupts++; - ctrl &= ~GRETH_CTRL_TXIRQ; - events |= GRETH_TX_WAIT_EVENT; - } - - /* Clear interrupt sources */ - greth->regs->ctrl = ctrl; - - /* Send the event(s) */ - if ( events ) - rtems_bsdnet_event_send (greth->daemonTid, events); -} - -static uint32_t read_mii(uint32_t phy_addr, uint32_t reg_addr) -{ - while (greth.regs->mdio_ctrl & GRETH_MDIO_BUSY) {} - greth.regs->mdio_ctrl = (phy_addr << 11) | (reg_addr << 6) | GRETH_MDIO_READ; - while (greth.regs->mdio_ctrl & GRETH_MDIO_BUSY) {} - if (!(greth.regs->mdio_ctrl & GRETH_MDIO_LINKFAIL)) - return((greth.regs->mdio_ctrl >> 16) & 0xFFFF); - else { - printf("greth: failed to read mii\n"); - return (0); - } -} - -static void write_mii(uint32_t phy_addr, uint32_t reg_addr, uint32_t data) -{ - while (greth.regs->mdio_ctrl & GRETH_MDIO_BUSY) {} - greth.regs->mdio_ctrl = - ((data & 0xFFFF) << 16) | (phy_addr << 11) | (reg_addr << 6) | GRETH_MDIO_WRITE; - while (greth.regs->mdio_ctrl & GRETH_MDIO_BUSY) {} -} - -static void print_init_info(struct greth_softc *sc) -{ - printf("greth: driver attached\n"); - if ( sc->auto_neg == -1 ){ - printf("Auto negotiation timed out. Selecting default config\n"); - } - printf("**** PHY ****\n"); - printf("Vendor: %x Device: %x Revision: %d\n",sc->phydev.vendor, sc->phydev.device, sc->phydev.rev); - printf("Current Operating Mode: "); - if (sc->gb) { - printf("1000 Mbit "); - } else if (sc->sp) { - printf("100 Mbit "); - } else { - printf("10 Mbit "); - } - if (sc->fd) { - printf("Full Duplex\n"); - } else { - printf("Half Duplex\n"); - } -#ifdef GRETH_AUTONEGO_PRINT_TIME - if ( sc->auto_neg ) { - printf("Autonegotiation Time: %ldms\n", sc->auto_neg_time.tv_sec*1000 + - sc->auto_neg_time.tv_nsec/1000000); - } -#endif -} - - -/* - * Initialize the ethernet hardware - */ -static void -greth_initialize_hardware (struct greth_softc *sc) -{ - struct mbuf *m; - int i; - int phyaddr; - int phyctrl; - int phystatus; - int tmp1; - int tmp2; - struct timespec tstart, tnow; - - greth_regs *regs; - - regs = sc->regs; - - /* Reset the controller. */ - greth.rxInterrupts = 0; - greth.rxPackets = 0; - - regs->ctrl = 0; - regs->ctrl = GRETH_CTRL_RST; /* Reset ON */ - regs->ctrl = 0; /* Reset OFF */ - - /* Check if mac is gbit capable*/ - sc->gbit_mac = (regs->ctrl >> 27) & 1; - - /* Get the phy address which assumed to have been set - correctly with the reset value in hardware*/ - phyaddr = (regs->mdio_ctrl >> 11) & 0x1F; - - /* get phy control register default values */ - while ((phyctrl = read_mii(phyaddr, 0)) & 0x8000) {} - - /* reset PHY and wait for completion */ - write_mii(phyaddr, 0, 0x8000 | phyctrl); - - while ((read_mii(phyaddr, 0)) & 0x8000) {} - phystatus = read_mii(phyaddr, 1); - - /* Disable Gbit auto-neg advertisement if MAC does not support it */ - - if ((!sc->gbit_mac) && (phystatus & 0x100)) write_mii(phyaddr, 9, 0); - - /* Restart auto-negotiation if available */ - if (phystatus & 0x08) { - write_mii(phyaddr, 0, phyctrl | 0x1200); - phyctrl = read_mii(phyaddr, 0); - } - - /* Check if PHY is autoneg capable and then determine operating mode, - otherwise force it to 10 Mbit halfduplex */ - sc->gb = 0; - sc->fd = 0; - sc->sp = 0; - sc->auto_neg = 0; - _Timespec_Set_to_zero(&sc->auto_neg_time); - if ((phyctrl >> 12) & 1) { - /*wait for auto negotiation to complete*/ - sc->auto_neg = 1; - if (rtems_clock_get_uptime(&tstart) != RTEMS_SUCCESSFUL) - printk("rtems_clock_get_uptime failed\n"); - while (!(((phystatus = read_mii(phyaddr, 1)) >> 5) & 1)) { - if (rtems_clock_get_uptime(&tnow) != RTEMS_SUCCESSFUL) - printk("rtems_clock_get_uptime failed\n"); - _Timespec_Subtract(&tstart, &tnow, &sc->auto_neg_time); - if (_Timespec_Greater_than(&sc->auto_neg_time, &greth_tan)) { - sc->auto_neg = -1; /* Failed */ - tmp1 = read_mii(phyaddr, 0); - sc->gb = ((phyctrl >> 6) & 1) && !((phyctrl >> 13) & 1); - sc->sp = !((phyctrl >> 6) & 1) && ((phyctrl >> 13) & 1); - sc->fd = (phyctrl >> 8) & 1; - goto auto_neg_done; - } - /* Wait about 30ms, time is PHY dependent */ - rtems_task_wake_after(rtems_clock_get_ticks_per_second()/32); - } - sc->phydev.adv = read_mii(phyaddr, 4); - sc->phydev.part = read_mii(phyaddr, 5); - if ((phystatus >> 8) & 1) { - sc->phydev.extadv = read_mii(phyaddr, 9); - sc->phydev.extpart = read_mii(phyaddr, 10); - if ( (sc->phydev.extadv & GRETH_MII_EXTADV_1000FD) && - (sc->phydev.extpart & GRETH_MII_EXTPRT_1000FD)) { - sc->gb = 1; - sc->fd = 1; - } - else if ( (sc->phydev.extadv & GRETH_MII_EXTADV_1000HD) && - (sc->phydev.extpart & GRETH_MII_EXTPRT_1000HD)) { - sc->gb = 1; - sc->fd = 0; - } - } - if ((sc->gb == 0) || ((sc->gb == 1) && (sc->gbit_mac == 0))) { - if ( (sc->phydev.adv & GRETH_MII_100TXFD) && - (sc->phydev.part & GRETH_MII_100TXFD)) { - sc->sp = 1; - sc->fd = 1; - } - else if ( (sc->phydev.adv & GRETH_MII_100TXHD) && - (sc->phydev.part & GRETH_MII_100TXHD)) { - sc->sp = 1; - sc->fd = 0; - } - else if ( (sc->phydev.adv & GRETH_MII_10FD) && - (sc->phydev.part & GRETH_MII_10FD)) { - sc->fd = 1; - } - } - } -auto_neg_done: - sc->phydev.vendor = 0; - sc->phydev.device = 0; - sc->phydev.rev = 0; - phystatus = read_mii(phyaddr, 1); - - /*Read out PHY info if extended registers are available */ - if (phystatus & 1) { - tmp1 = read_mii(phyaddr, 2); - tmp2 = read_mii(phyaddr, 3); - - sc->phydev.vendor = (tmp1 << 6) | ((tmp2 >> 10) & 0x3F); - sc->phydev.rev = tmp2 & 0xF; - sc->phydev.device = (tmp2 >> 4) & 0x3F; - } - - /* Force to 10 mbit half duplex if the 10/100 MAC is used with a 1000 PHY*/ - /*check if marvell 88EE1111 PHY. Needs special reset handling */ - if ((phystatus & 1) && (sc->phydev.vendor == 0x005043) && (sc->phydev.device == 0x0C)) { - if (((sc->gb) && !(sc->gbit_mac)) || !((phyctrl >> 12) & 1)) { - write_mii(phyaddr, 0, sc->sp << 13); - write_mii(phyaddr, 0, 0x8000); - sc->gb = 0; - sc->sp = 0; - sc->fd = 0; - } - } else { - if (((sc->gb) && !(sc->gbit_mac)) || !((phyctrl >> 12) & 1)) { - write_mii(phyaddr, 0, sc->sp << 13); - sc->gb = 0; - sc->sp = 0; - sc->fd = 0; - } - } - while ((read_mii(phyaddr, 0)) & 0x8000) {} - - regs->ctrl = 0; - regs->ctrl = GRETH_CTRL_RST; /* Reset ON */ - regs->ctrl = 0; - - /* Initialize rx/tx descriptor pointers */ - sc->txdesc = (greth_rxtxdesc *) almalloc(1024); - sc->rxdesc = (greth_rxtxdesc *) almalloc(1024); - sc->tx_ptr = 0; - sc->tx_dptr = 0; - sc->tx_cnt = 0; - sc->rx_ptr = 0; - regs->txdesc = (uintptr_t) sc->txdesc; - regs->rxdesc = (uintptr_t) sc->rxdesc; - - sc->rxmbuf = calloc(sc->rxbufs, sizeof(*sc->rxmbuf)); - sc->txmbuf = calloc(sc->txbufs, sizeof(*sc->txmbuf)); - - for (i = 0; i < sc->txbufs; i++) - { - sc->txdesc[i].ctrl = 0; - if (!(sc->gbit_mac)) { - sc->txdesc[i].addr = malloc(GRETH_MAXBUF_LEN); - } -#ifdef GRETH_DEBUG - /* printf("TXBUF: %08x\n", (int) sc->txdesc[i].addr); */ -#endif - } - for (i = 0; i < sc->rxbufs; i++) - { - - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - if (sc->gbit_mac) - m->m_data += 2; - m->m_pkthdr.rcvif = &sc->arpcom.ac_if; - sc->rxmbuf[i] = m; - sc->rxdesc[i].addr = (uint32_t *) mtod(m, uint32_t *); - sc->rxdesc[i].ctrl = GRETH_RXD_ENABLE | GRETH_RXD_IRQ; -#ifdef GRETH_DEBUG -/* printf("RXBUF: %08x\n", (int) sc->rxdesc[i].addr); */ -#endif - } - sc->rxdesc[sc->rxbufs - 1].ctrl |= GRETH_RXD_WRAP; - - /* set ethernet address. */ - regs->mac_addr_msb = - sc->arpcom.ac_enaddr[0] << 8 | sc->arpcom.ac_enaddr[1]; - - uint32_t mac_addr_lsb; - mac_addr_lsb = sc->arpcom.ac_enaddr[2]; - mac_addr_lsb <<= 8; - mac_addr_lsb |= sc->arpcom.ac_enaddr[3]; - mac_addr_lsb <<= 8; - mac_addr_lsb |= sc->arpcom.ac_enaddr[4]; - mac_addr_lsb <<= 8; - mac_addr_lsb |= sc->arpcom.ac_enaddr[5]; - regs->mac_addr_lsb = mac_addr_lsb; - - if ( sc->rxbufs < 10 ) { - sc->tx_int_gen = sc->tx_int_gen_cur = 1; - }else{ - sc->tx_int_gen = sc->tx_int_gen_cur = sc->txbufs/2; - } - sc->next_tx_mbuf = NULL; - - if ( !sc->gbit_mac ) - sc->max_fragsize = 1; - - /* clear all pending interrupts */ - regs->status = 0xffffffff; - - /* install interrupt handler */ - rtems_interrupt_handler_install(sc->vector, "greth", RTEMS_INTERRUPT_SHARED, - greth_interrupt_handler, sc); - - regs->ctrl |= GRETH_CTRL_RXEN | (sc->fd << 4) | GRETH_CTRL_RXIRQ | (sc->sp << 7) | (sc->gb << 8); - - print_init_info(sc); -} - -#ifdef CPU_U32_FIX - -/* - * Routine to align the received packet so that the ip header - * is on a 32-bit boundary. Necessary for cpu's that do not - * allow unaligned loads and stores and when the 32-bit DMA - * mode is used. - * - * Transfers are done on word basis to avoid possibly slow byte - * and half-word writes. - */ - -void ipalign(struct mbuf *m) -{ - unsigned int *first, *last, data; - unsigned int tmp; - - if ((((int) m->m_data) & 2) && (m->m_len)) { - last = (unsigned int *) ((((int) m->m_data) + m->m_len + 8) & ~3); - first = (unsigned int *) (((int) m->m_data) & ~3); - tmp = GRETH_MEM_LOAD(first); - tmp = tmp << 16; - first++; - do { - /* When snooping is not available the LDA instruction must be used - * to avoid the cache to return an illegal value. - * Load with forced cache miss - */ - data = GRETH_MEM_LOAD(first); - *first = tmp | (data >> 16); - tmp = data << 16; - first++; - } while (first <= last); - - m->m_data = (caddr_t)(((int) m->m_data) + 2); - } -} -#endif - -static void -greth_Daemon (void *arg) -{ - struct ether_header *eh; - struct greth_softc *dp = (struct greth_softc *) &greth; - struct ifnet *ifp = &dp->arpcom.ac_if; - struct mbuf *m; - unsigned int len, len_status, bad; - rtems_event_set events; - rtems_interrupt_level level; - int first; -#ifdef CPU_U32_FIX - unsigned int tmp; -#endif - - for (;;) - { - rtems_bsdnet_event_receive (INTERRUPT_EVENT | GRETH_TX_WAIT_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, &events); - - if ( events & GRETH_TX_WAIT_EVENT ){ - /* TX interrupt. - * We only end up here when all TX descriptors has been used, - * and - */ - if ( dp->gbit_mac ) - greth_process_tx_gbit(dp); - else - greth_process_tx(dp); - - /* If we didn't get a RX interrupt we don't process it */ - if ( (events & INTERRUPT_EVENT) == 0 ) - continue; - } - -#ifdef GRETH_ETH_DEBUG - printf ("r\n"); -#endif - first=1; - /* Scan for Received packets */ -again: - while (!((len_status = - GRETH_MEM_LOAD(&dp->rxdesc[dp->rx_ptr].ctrl)) & GRETH_RXD_ENABLE)) - { - bad = 0; - if (len_status & GRETH_RXD_TOOLONG) - { - dp->rxLengthError++; - bad = 1; - } - if (len_status & GRETH_RXD_DRIBBLE) - { - dp->rxNonOctet++; - bad = 1; - } - if (len_status & GRETH_RXD_CRCERR) - { - dp->rxBadCRC++; - bad = 1; - } - if (len_status & GRETH_RXD_OVERRUN) - { - dp->rxOverrun++; - bad = 1; - } - if (len_status & GRETH_RXD_LENERR) - { - dp->rxLengthError++; - bad = 1; - } - if (!bad) - { - /* pass on the packet in the receive buffer */ - len = len_status & 0x7FF; - m = dp->rxmbuf[dp->rx_ptr]; -#ifdef GRETH_DEBUG - int i; - printf("RX: 0x%08x, Len: %d : ", (int) m->m_data, len); - for (i=0; im_data[i] >> 4) & 0x0ff, m->m_data[i] & 0x0ff); - printf("\n"); -#endif - m->m_len = m->m_pkthdr.len = - len - sizeof (struct ether_header); - - eh = mtod (m, struct ether_header *); - - m->m_data += sizeof (struct ether_header); -#ifdef CPU_U32_FIX - if(!dp->gbit_mac) { - /* OVERRIDE CACHED ETHERNET HEADER FOR NON-SNOOPING SYSTEMS */ - tmp = GRETH_MEM_LOAD((uintptr_t)eh); - tmp = GRETH_MEM_LOAD(4+(uintptr_t)eh); - tmp = GRETH_MEM_LOAD(8+(uintptr_t)eh); - tmp = GRETH_MEM_LOAD(12+(uintptr_t)eh); - (void)tmp; - ipalign(m); /* Align packet on 32-bit boundary */ - } -#endif - - ether_input (ifp, eh, m); - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - if (dp->gbit_mac) - m->m_data += 2; - dp->rxmbuf[dp->rx_ptr] = m; - m->m_pkthdr.rcvif = ifp; - dp->rxdesc[dp->rx_ptr].addr = - (uint32_t *) mtod (m, uint32_t *); - dp->rxPackets++; - } - if (dp->rx_ptr == dp->rxbufs - 1) { - dp->rxdesc[dp->rx_ptr].ctrl = GRETH_RXD_ENABLE | GRETH_RXD_IRQ | GRETH_RXD_WRAP; - } else { - dp->rxdesc[dp->rx_ptr].ctrl = GRETH_RXD_ENABLE | GRETH_RXD_IRQ; - } - rtems_interrupt_disable(level); - dp->regs->ctrl |= GRETH_CTRL_RXEN; - rtems_interrupt_enable(level); - dp->rx_ptr = (dp->rx_ptr + 1) % dp->rxbufs; - } - - /* Always scan twice to avoid deadlock */ - if ( first ){ - first=0; - rtems_interrupt_disable(level); - dp->regs->ctrl |= GRETH_CTRL_RXIRQ; - rtems_interrupt_enable(level); - goto again; - } - - } - -} - -static int inside = 0; -static int -sendpacket (struct ifnet *ifp, struct mbuf *m) -{ - struct greth_softc *dp = ifp->if_softc; - unsigned char *temp; - struct mbuf *n; - unsigned int len; - rtems_interrupt_level level; - - /*printf("Send packet entered\n");*/ - if (inside) printf ("error: sendpacket re-entered!!\n"); - inside = 1; - - /* - * Is there a free descriptor available? - */ - if (GRETH_MEM_LOAD(&dp->txdesc[dp->tx_ptr].ctrl) & GRETH_TXD_ENABLE){ - /* No. */ - inside = 0; - return 1; - } - - /* Remember head of chain */ - n = m; - - len = 0; - temp = (unsigned char *) GRETH_MEM_LOAD(&dp->txdesc[dp->tx_ptr].addr); -#ifdef GRETH_DEBUG - printf("TXD: 0x%08x : BUF: 0x%08x\n", (int) m->m_data, (int) temp); -#endif - for (;;) - { -#ifdef GRETH_DEBUG - int i; - printf("MBUF: 0x%08x : ", (int) m->m_data); - for (i=0;im_len;i++) - printf("%x%x", (m->m_data[i] >> 4) & 0x0ff, m->m_data[i] & 0x0ff); - printf("\n"); -#endif - len += m->m_len; - if (len <= RBUF_SIZE) - memcpy ((void *) temp, (char *) m->m_data, m->m_len); - temp += m->m_len; - if ((m = m->m_next) == NULL) - break; - } - - m_freem (n); - - /* don't send long packets */ - - if (len <= GRETH_MAXBUF_LEN) { - if (dp->tx_ptr < dp->txbufs-1) { - dp->txdesc[dp->tx_ptr].ctrl = GRETH_TXD_ENABLE | len; - } else { - dp->txdesc[dp->tx_ptr].ctrl = - GRETH_TXD_WRAP | GRETH_TXD_ENABLE | len; - } - dp->tx_ptr = (dp->tx_ptr + 1) % dp->txbufs; - rtems_interrupt_disable(level); - dp->regs->ctrl = dp->regs->ctrl | GRETH_CTRL_TXEN; - rtems_interrupt_enable(level); - - } - inside = 0; - - return 0; -} - - -static int -sendpacket_gbit (struct ifnet *ifp, struct mbuf *m) -{ - struct greth_softc *dp = ifp->if_softc; - unsigned int len; - - unsigned int ctrl; - int frags; - struct mbuf *mtmp; - int int_en; - rtems_interrupt_level level; - - if (inside) printf ("error: sendpacket re-entered!!\n"); - inside = 1; - - len = 0; -#ifdef GRETH_DEBUG - printf("TXD: 0x%08x\n", (int) m->m_data); -#endif - /* Get number of fragments too see if we have enough - * resources. - */ - frags=1; - mtmp=m; - while(mtmp->m_next){ - frags++; - mtmp = mtmp->m_next; - } - - if ( frags > dp->max_fragsize ) - dp->max_fragsize = frags; - - if ( frags > dp->txbufs ){ - inside = 0; - printf("GRETH: MBUF-chain cannot be sent. Increase descriptor count.\n"); - return -1; - } - - if ( frags > (dp->txbufs-dp->tx_cnt) ){ - inside = 0; - /* Return number of fragments */ - return frags; - } - - - /* Enable interrupt from descriptor every tx_int_gen - * descriptor. Typically every 16 descriptor. This - * is only to reduce the number of interrupts during - * heavy load. - */ - dp->tx_int_gen_cur-=frags; - if ( dp->tx_int_gen_cur <= 0 ){ - dp->tx_int_gen_cur = dp->tx_int_gen; - int_en = GRETH_TXD_IRQ; - }else{ - int_en = 0; - } - - /* At this stage we know that enough descriptors are available */ - for (;;) - { - -#ifdef GRETH_DEBUG - int i; - printf("MBUF: 0x%08x, Len: %d : ", (int) m->m_data, m->m_len); - for (i=0; im_len; i++) - printf("%x%x", (m->m_data[i] >> 4) & 0x0ff, m->m_data[i] & 0x0ff); - printf("\n"); -#endif - len += m->m_len; - dp->txdesc[dp->tx_ptr].addr = (uint32_t *)m->m_data; - - /* Wrap around? */ - if (dp->tx_ptr < dp->txbufs-1) { - ctrl = GRETH_TXD_ENABLE; - }else{ - ctrl = GRETH_TXD_ENABLE | GRETH_TXD_WRAP; - } - - /* Enable Descriptor */ - if ((m->m_next) == NULL) { - dp->txdesc[dp->tx_ptr].ctrl = ctrl | int_en | m->m_len; - break; - }else{ - dp->txdesc[dp->tx_ptr].ctrl = GRETH_TXD_MORE | ctrl | int_en | m->m_len; - } - - /* Next */ - dp->txmbuf[dp->tx_ptr] = m; - dp->tx_ptr = (dp->tx_ptr + 1) % dp->txbufs; - dp->tx_cnt++; - m = m->m_next; - } - dp->txmbuf[dp->tx_ptr] = m; - dp->tx_ptr = (dp->tx_ptr + 1) % dp->txbufs; - dp->tx_cnt++; - - /* Tell Hardware about newly enabled descriptor */ - rtems_interrupt_disable(level); - dp->regs->ctrl = dp->regs->ctrl | GRETH_CTRL_TXEN; - rtems_interrupt_enable(level); - - inside = 0; - - return 0; -} - -int greth_process_tx_gbit(struct greth_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - rtems_interrupt_level level; - int first=1; - - /* - * Send packets till queue is empty - */ - for (;;){ - /* Reap Sent packets */ - while((sc->tx_cnt > 0) && !(GRETH_MEM_LOAD(&sc->txdesc[sc->tx_dptr].ctrl) & GRETH_TXD_ENABLE)) { - m_free(sc->txmbuf[sc->tx_dptr]); - sc->tx_dptr = (sc->tx_dptr + 1) % sc->txbufs; - sc->tx_cnt--; - } - - if ( sc->next_tx_mbuf ){ - /* Get packet we tried but faild to transmit last time */ - m = sc->next_tx_mbuf; - sc->next_tx_mbuf = NULL; /* Mark packet taken */ - }else{ - /* - * Get the next mbuf chain to transmit from Stack. - */ - IF_DEQUEUE (&ifp->if_snd, m); - if (!m){ - /* Hardware has sent all schedule packets, this - * makes the stack enter at greth_start next time - * a packet is to be sent. - */ - ifp->if_flags &= ~IFF_OACTIVE; - break; - } - } - - /* Are there free descriptors available? */ - /* Try to send packet, if it a negative number is returned. */ - if ( (sc->tx_cnt >= sc->txbufs) || sendpacket_gbit(ifp, m) ){ - /* Not enough resources */ - - /* Since we have taken the mbuf out of the "send chain" - * we must remember to use that next time we come back. - * or else we have dropped a packet. - */ - sc->next_tx_mbuf = m; - - /* Not enough resources, enable interrupt for transmissions - * this way we will be informed when more TX-descriptors are - * available. - */ - if ( first ){ - first = 0; - rtems_interrupt_disable(level); - ifp->if_flags |= IFF_OACTIVE; - sc->regs->ctrl |= GRETH_CTRL_TXIRQ; - rtems_interrupt_enable(level); - - /* We must check again to be sure that we didn't - * miss an interrupt (if a packet was sent just before - * enabling interrupts) - */ - continue; - } - - return -1; - }else{ - /* Sent Ok, proceed to process more packets if available */ - } - } - return 0; -} - -int greth_process_tx(struct greth_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - rtems_interrupt_level level; - int first=1; - - /* - * Send packets till queue is empty - */ - for (;;){ - if ( sc->next_tx_mbuf ){ - /* Get packet we tried but failed to transmit last time */ - m = sc->next_tx_mbuf; - sc->next_tx_mbuf = NULL; /* Mark packet taken */ - }else{ - /* - * Get the next mbuf chain to transmit from Stack. - */ - IF_DEQUEUE (&ifp->if_snd, m); - if (!m){ - /* Hardware has sent all schedule packets, this - * makes the stack enter at greth_start next time - * a packet is to be sent. - */ - ifp->if_flags &= ~IFF_OACTIVE; - break; - } - } - - /* Try to send packet, failed if it a non-zero number is returned. */ - if ( sendpacket(ifp, m) ){ - /* Not enough resources */ - - /* Since we have taken the mbuf out of the "send chain" - * we must remember to use that next time we come back. - * or else we have dropped a packet. - */ - sc->next_tx_mbuf = m; - - /* Not enough resources, enable interrupt for transmissions - * this way we will be informed when more TX-descriptors are - * available. - */ - if ( first ){ - first = 0; - rtems_interrupt_disable(level); - ifp->if_flags |= IFF_OACTIVE; - sc->regs->ctrl |= GRETH_CTRL_TXIRQ; - rtems_interrupt_enable(level); - - /* We must check again to be sure that we didn't - * miss an interrupt (if a packet was sent just before - * enabling interrupts) - */ - continue; - } - - return -1; - }else{ - /* Sent Ok, proceed to process more packets if available */ - } - } - return 0; -} - -static void -greth_start (struct ifnet *ifp) -{ - struct greth_softc *sc = ifp->if_softc; - - if ( ifp->if_flags & IFF_OACTIVE ) - return; - - if ( sc->gbit_mac ){ - /* No use trying to handle this if we are waiting on GRETH - * to send the previously scheduled packets. - */ - - greth_process_tx_gbit(sc); - }else{ - greth_process_tx(sc); - } -} - -/* - * Initialize and start the device - */ -static void -greth_init (void *arg) -{ - struct greth_softc *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - - if (sc->daemonTid == 0) { - - /* - * Start driver tasks - */ - sc->daemonTid = rtems_bsdnet_newproc ("DCrxtx", 4096, - greth_Daemon, sc); - - /* - * Set up GRETH hardware - */ - greth_initialize_hardware (sc); - - } - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; -} - -/* - * Stop the device - */ -static void -greth_stop (struct greth_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - - ifp->if_flags &= ~IFF_RUNNING; - - sc->regs->ctrl = 0; /* RX/TX OFF */ - sc->regs->ctrl = GRETH_CTRL_RST; /* Reset ON */ - sc->regs->ctrl = 0; /* Reset OFF */ - - sc->next_tx_mbuf = NULL; -} - - -/* - * Show interface statistics - */ -static void -greth_stats (struct greth_softc *sc) -{ - printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); - printf (" Rx Packets:%-8lu", sc->rxPackets); - printf (" Length:%-8lu", sc->rxLengthError); - printf (" Non-octet:%-8lu\n", sc->rxNonOctet); - printf (" Bad CRC:%-8lu", sc->rxBadCRC); - printf (" Overrun:%-8lu", sc->rxOverrun); - printf (" Tx Interrupts:%-8lu", sc->txInterrupts); - printf (" Maximal Frags:%-8d", sc->max_fragsize); - printf (" GBIT MAC:%-8d", sc->gbit_mac); -} - -/* - * Driver ioctl handler - */ -static int -greth_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - struct greth_softc *sc = ifp->if_softc; - int error = 0; - - switch (command) - { - case SIOCGIFADDR: - case SIOCSIFADDR: - ether_ioctl (ifp, command, data); - break; - - case SIOCSIFFLAGS: - switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) - { - case IFF_RUNNING: - greth_stop (sc); - break; - - case IFF_UP: - greth_init (sc); - break; - - case IFF_UP | IFF_RUNNING: - greth_stop (sc); - greth_init (sc); - break; - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - greth_stats (sc); - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } - - return error; -} - -/* - * Attach an GRETH driver to the system - */ -int -rtems_greth_driver_attach (struct rtems_bsdnet_ifconfig *config, - greth_configuration_t *chip) -{ - struct greth_softc *sc; - struct ifnet *ifp; - int mtu; - int unitNumber; - char *unitName; - - /* parse driver name */ - if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0) - return 0; - - sc = &greth; - ifp = &sc->arpcom.ac_if; - memset (sc, 0, sizeof (*sc)); - - if (config->hardware_address) - { - memcpy (sc->arpcom.ac_enaddr, config->hardware_address, - ETHER_ADDR_LEN); - } - else - { - memset (sc->arpcom.ac_enaddr, 0x08, ETHER_ADDR_LEN); - } - - if (config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - - sc->acceptBroadcast = !config->ignore_broadcast; - sc->regs = chip->base_address; - sc->vector = chip->vector; - sc->txbufs = chip->txd_count; - sc->rxbufs = chip->rxd_count; - - /* - * Set up network interface values - */ - ifp->if_softc = sc; - ifp->if_unit = unitNumber; - ifp->if_name = unitName; - ifp->if_mtu = mtu; - ifp->if_init = greth_init; - ifp->if_ioctl = greth_ioctl; - ifp->if_start = greth_start; - ifp->if_output = ether_output; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; - if (ifp->if_snd.ifq_maxlen == 0) - ifp->if_snd.ifq_maxlen = ifqmaxlen; - - /* - * Attach the interface - */ - if_attach (ifp); - ether_ifattach (ifp); - -#ifdef GRETH_DEBUG - printf ("GRETH : driver has been attached\n"); -#endif - return 1; -}; - -#endif diff --git a/c/src/libchip/network/i82586.c b/c/src/libchip/network/i82586.c deleted file mode 100644 index c79af66e0d..0000000000 --- a/c/src/libchip/network/i82586.c +++ /dev/null @@ -1,2198 +0,0 @@ -/* $NetBSD: i82586.c,v 1.38 2001/07/07 05:35:39 thorpej Exp $ */ - -/*- - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Paul Kranenburg and Charles M. Hannum. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/*- - * Copyright (c) 1997 Paul Kranenburg. - * Copyright (c) 1992, 1993, University of Vermont and State - * Agricultural College. - * Copyright (c) 1992, 1993, Garrett A. Wollman. - * - * Portions: - * Copyright (c) 1994, 1995, Rafal K. Boni - * Copyright (c) 1990, 1991, William F. Jolitz - * Copyright (c) 1990, The Regents of the University of California - * - * RTEMS: - * Copyright (c) 2001, Chris Johns, Cybertec Pty Ltd, - * http://www.cybertec.com.au/. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of Vermont - * and State Agricultural College and Garrett A. Wollman, by William F. - * Jolitz, and by the University of California, Berkeley, Lawrence - * Berkeley Laboratory, and its contributors. - * 4. Neither the names of the Universities nor the names of the authors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR AUTHORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Intel 82586 Ethernet chip - * Register, bit, and structure definitions. - * - * Original StarLAN driver written by Garrett Wollman with reference to the - * Clarkson Packet Driver code for this chip written by Russ Nelson and others. - * - * BPF support code taken from hpdev/if_le.c, supplied with tcpdump. - * - * 3C507 support is loosely based on code donated to NetBSD by Rafal Boni. - * - * Majorly cleaned up and 3C507 code merged by Charles Hannum. - * - * Converted to SUN ie driver by Charles D. Cranor, - * October 1994, January 1995. - * This sun version based on i386 version 1.30. - */ - -/* - * The i82586 is a very painful chip, found in sun3's, sun-4/100's - * sun-4/200's, and VME based suns. The byte order is all wrong for a - * SUN, making life difficult. Programming this chip is mostly the same, - * but certain details differ from system to system. This driver is - * written so that different "ie" interfaces can be controled by the same - * driver. - */ - -/* -Mode of operation: - - We run the 82586 in a standard Ethernet mode. We keep NFRAMES - received frame descriptors around for the receiver to use, and - NRXBUF associated receive buffer descriptors, both in a circular - list. Whenever a frame is received, we rotate both lists as - necessary. (The 586 treats both lists as a simple queue.) We also - keep a transmit command around so that packets can be sent off - quickly. - - We configure the adapter in AL-LOC = 1 mode, which means that the - Ethernet/802.3 MAC header is placed at the beginning of the receive - buffer rather than being split off into various fields in the RFD. - This also means that we must include this header in the transmit - buffer as well. - - By convention, all transmit commands, and only transmit commands, - shall have the I (IE_CMD_INTR) bit set in the command. This way, - when an interrupt arrives at i82586_intr(), it is immediately possible - to tell what precisely caused it. ANY OTHER command-sending - routines should run at splnet(), and should post an acknowledgement - to every interrupt they generate. - - To save the expense of shipping a command to 82586 every time we - want to send a frame, we use a linked list of commands consisting - of alternate XMIT and NOP commands. The links of these elements - are manipulated (in iexmit()) such that the NOP command loops back - to itself whenever the following XMIT command is not yet ready to - go. Whenever an XMIT is ready, the preceding NOP link is pointed - at it, while its own link field points to the following NOP command. - Thus, a single transmit command sets off an interlocked traversal - of the xmit command chain, with the host processor in control of - the synchronization. -*/ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include "i82586reg.h" -#include - -#if defined(ALIGNBYTES) && defined(ALIGN) -/* FIXME: Redefine because some versions of - * RTEMS newlib and the BSDs ship a broken ALIGN */ -#undef ALIGN -#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) & ~ALIGNBYTES) -#else -#define ALIGN(p) (p) -#endif - -/* - * A global way to change all async cmd requests at once. For RTEMS and running - * as tasks I wanted to see if the tx race condition is effected by this. - */ -#define ASYNC_OPTION (1) - -void i82586_reset (struct ie_softc *, int); -void i82586_watchdog (struct ifnet *); -void i82586_init (void *); -int i82586_ioctl (struct ifnet *, ioctl_command_t cmd, caddr_t data); -void i82586_start (struct ifnet *); - -void i82586_stop (struct ifnet *, int); -int i82586_rint (struct ie_softc *, int); -int i82586_tint (struct ie_softc *, int); - -int i82586_mediachange (struct ifnet *); -void i82586_mediastatus (struct ifnet *, struct ifmediareq *); - -static void i82586_tx_task(void *arg); -static void i82586_start_tx(struct ie_softc *sc); - -static int ie_readframe (struct ie_softc *, int); -static struct mbuf *ieget (struct ie_softc *, int, int); -static int i82586_get_rbd_list (struct ie_softc *, u_int16_t*, - u_int16_t*, int *); -static void i82586_release_rbd_list (struct ie_softc *, - u_int16_t, u_int16_t); -static int i82586_drop_frames (struct ie_softc *); -static int i82586_chk_rx_ring (struct ie_softc *); - -static __inline__ void ie_ack (struct ie_softc *, u_int); -static __inline__ void iexmit (struct ie_softc *); -static void i82586_start_transceiver (struct ie_softc *); - -static void i82586_count_errors (struct ie_softc *); -static void i82586_rx_errors (struct ie_softc *, int, int); -static void i82586_setup_bufs (struct ie_softc *); -static void setup_simple_command (struct ie_softc *, int, int); -static int ie_cfg_setup (struct ie_softc *, int, int, int); -static int ie_ia_setup (struct ie_softc *, int); -static void ie_run_tdr (struct ie_softc *, int); -static int ie_mc_setup (struct ie_softc *, int); -static void ie_mc_reset (struct ie_softc *); -static int i82586_start_cmd (struct ie_softc *, int, int, int, int); -static int i82586_cmd_wait (struct ie_softc *); - -#if I82586_DEBUG -static void print_softie(struct ie_softc *sc); -static void print_rbd (struct ie_softc *, int); -#endif - -#define min(l,r) ((l) < (r) ? (l) : (r)) -#define max(l,r) ((l) > (r) ? (l) : (r)) - -#define delay(p) rtems_task_wake_after (RTEMS_MICROSECONDS_TO_TICKS (p)) - -#define i82586_WAKE_EVENT RTEMS_EVENT_1 -#define i82586_TX_EVENT RTEMS_EVENT_2 - -static char * -bitmask_snprintf(unsigned long value, const char *format, char *buf, int blen) -{ - char *b = buf; - int bit = 31; - - while (bit-- > *format) - value <<= 1; - - format++; - - while (*format) - { - if (value & 0x80000000) - while (isalnum((unsigned char)*format)) - *b++ = *format; - else - *b++ = '0'; - - *b++ = ','; - - while (bit-- > *format) - value <<= 1; - - format++; - } - - *b = '\0'; - return buf; -} - -/* - * Front-ends call this function to attach to the MI driver. - * - * The front-end has responsibility for managing the ICP and ISCP - * structures. Both of these are opaque to us. Also, the front-end - * chooses a location for the SCB which is expected to be addressable - * (through `sc->scb') as an offset against the shared-memory bus handle. - * - * The following MD interface function must be setup by the front-end - * before calling here: - * - * hwreset - board dependent reset - * hwinit - board dependent initialization - * chan_attn - channel attention - * intrhook - board dependent interrupt processing - * memcopyin - shared memory copy: board to KVA - * memcopyout - shared memory copy: KVA to board - * ie_bus_read16 - read a sixteen-bit i82586 pointer - * ie_bus_write16 - write a sixteen-bit i82586 pointer - * ie_bus_write24 - write a twenty-four-bit i82586 pointer - * - */ -int -i82586_attach(struct rtems_bsdnet_ifconfig *config, int attaching) -{ - struct ie_softc *sc; - struct ifnet *ifp; - char *name; - int unit; - int mtu; - - /* - * Parse driver name - */ - - if ((unit = rtems_bsdnet_parse_driver_name (config, &name)) < 0) - return 0; - - sc = config->drv_ctrl; - ifp = &sc->arpcom.ac_if; - -#if I82586_DEBUG - sc->sc_debug = 0; /*IED_TINT | IED_XMIT; */ -#endif - - if (attaching) - { - if (ifp->if_softc) - { - printf ("Driver `%s' already in use.\n", config->name); - return 0; - } - - /* - * Process options - */ - - memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); - - if (config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - - ifp->if_softc = sc; - ifp->if_unit = unit; - ifp->if_name = name; - ifp->if_mtu = mtu; - ifp->if_init = i82586_init; - ifp->if_ioctl = i82586_ioctl; - ifp->if_start = i82586_start; - ifp->if_output = ether_output; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - - if (ifp->if_snd.ifq_maxlen == 0) - ifp->if_snd.ifq_maxlen = ifqmaxlen; - - /* Attach the interface. */ - if_attach(ifp); - ether_ifattach(ifp); - return 1; - } - return 0; -} - - -/* - * Interrupt Acknowledge. Mask in native byte-order. - */ -static __inline__ void -ie_ack(struct ie_softc *sc, u_int mask) -{ - u_int status; - - IE_BUS_BARRIER(sc, 0, 0, BUS_SPACE_BARRIER_READ); - status = sc->ie_bus_read16(sc, IE_SCB_STATUS(sc->scb)); - i82586_start_cmd(sc, status & mask, 0, 0, 0); - if (sc->intrhook) - sc->intrhook(sc, INTR_ACK); -} - - -/* - * Read data off the interface, and turn it into an mbuf chain. - * - * This code is DRAMATICALLY different from the previous version; this - * version tries to allocate the entire mbuf chain up front, given the - * length of the data available. This enables us to allocate mbuf - * clusters in many situations where before we would have had a long - * chain of partially-full mbufs. This should help to speed up the - * operation considerably. (Provided that it works, of course.) - */ -static __inline struct mbuf * -ieget(struct ie_softc *sc, int head, int totlen) -{ - struct mbuf *m, *m0, *newm; - int len, resid; - int thisrboff, thismboff; - struct ether_header eh; - - /* - * Snarf the Ethernet header. - */ - (sc->memcopyin)(sc, &eh, IE_RBUF_ADDR(sc, head), - sizeof(struct ether_header)); - - resid = totlen; - - MGETHDR(m0, M_DONTWAIT, MT_DATA); - if (m0 == 0) - return (0); - m0->m_pkthdr.rcvif = &sc->arpcom.ac_if; - m0->m_pkthdr.len = totlen; - len = MHLEN; - m = m0; - - /* - * This loop goes through and allocates mbufs for all the data we will - * be copying in. It does not actually do the copying yet. - */ - while (totlen > 0) { - if (totlen >= MINCLSIZE) { - MCLGET(m, M_DONTWAIT); - if ((m->m_flags & M_EXT) == 0) - goto bad; - len = MCLBYTES; - } - - if (m == m0) { - caddr_t newdata = (caddr_t) - ALIGN(m->m_data + sizeof(struct ether_header)) - - sizeof(struct ether_header); - len -= newdata - m->m_data; - m->m_data = newdata; - } - - m->m_len = len = min(totlen, len); - - totlen -= len; - if (totlen > 0) { - MGET(newm, M_DONTWAIT, MT_DATA); - if (newm == 0) - goto bad; - len = MLEN; - m = m->m_next = newm; - } - } - - m = m0; - thismboff = 0; - - /* - * Copy the Ethernet header into the mbuf chain. - */ - memcpy(mtod(m, caddr_t), &eh, sizeof(struct ether_header)); - thismboff = sizeof(struct ether_header); - thisrboff = sizeof(struct ether_header); - resid -= sizeof(struct ether_header); - - /* - * Now we take the mbuf chain (hopefully only one mbuf most of the - * time) and stuff the data into it. There are no possible failures - * at or after this point. - */ - while (resid > 0) { - int thisrblen = IE_RBUF_SIZE - thisrboff, - thismblen = m->m_len - thismboff; - len = min(thisrblen, thismblen); - - (sc->memcopyin)(sc, mtod(m, caddr_t) + thismboff, - IE_RBUF_ADDR(sc,head) + thisrboff, - (u_int)len); - resid -= len; - - if (len == thismblen) { - m = m->m_next; - thismboff = 0; - } else - thismboff += len; - - if (len == thisrblen) { - if (++head == sc->nrxbuf) - head = 0; - thisrboff = 0; - } else - thisrboff += len; - } - - /* - * Unless something changed strangely while we were doing the copy, - * we have now copied everything in from the shared memory. - * This means that we are done. - */ - return (m0); - - bad: - m_freem(m0); - return (0); -} - -/* - * Setup all necessary artifacts for an XMIT command, and then pass the XMIT - * command to the chip to be executed. - */ -static __inline__ void -iexmit(struct ie_softc *sc) -{ - int off; - int cur, prev; - - cur = sc->xctail; - -#if I82586_DEBUG - I82586_TRACE(sc, I82586_TX_EMIT, cur); -#endif - -#if I82586_DEBUG - if (sc->sc_debug & IED_XMIT) - printf("%s: xmit buffer %d\n", sc->arpcom.ac_if.if_name, cur); -#endif - - /* - * Setup the transmit command. - */ - sc->ie_bus_write16(sc, IE_CMD_XMIT_DESC(sc->xmit_cmds, cur), - IE_XBD_ADDR(sc->xbds, cur)); - - sc->ie_bus_write16(sc, IE_CMD_XMIT_STATUS(sc->xmit_cmds, cur), 0); - - if (sc->do_xmitnopchain) { - /* - * Gate this XMIT command to the following NOP - */ - sc->ie_bus_write16(sc, IE_CMD_XMIT_LINK(sc->xmit_cmds, cur), - IE_CMD_NOP_ADDR(sc->nop_cmds, cur)); - sc->ie_bus_write16(sc, IE_CMD_XMIT_CMD(sc->xmit_cmds, cur), - IE_CMD_XMIT | IE_CMD_INTR); - - /* - * Loopback at following NOP - */ - sc->ie_bus_write16(sc, IE_CMD_NOP_STATUS(sc->nop_cmds, cur), 0); - sc->ie_bus_write16(sc, IE_CMD_NOP_LINK(sc->nop_cmds, cur), - IE_CMD_NOP_ADDR(sc->nop_cmds, cur)); - - /* - * Gate preceding NOP to this XMIT command - */ - prev = (cur + NTXBUF - 1) % NTXBUF; - sc->ie_bus_write16(sc, IE_CMD_NOP_STATUS(sc->nop_cmds, prev), 0); - sc->ie_bus_write16(sc, IE_CMD_NOP_LINK(sc->nop_cmds, prev), - IE_CMD_XMIT_ADDR(sc->xmit_cmds, cur)); - - off = IE_SCB_STATUS(sc->scb); - IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ); - if ((sc->ie_bus_read16(sc, off) & IE_CUS_ACTIVE) == 0) { - printf("iexmit: CU not active\n"); - i82586_start_transceiver(sc); - } - } else { - sc->ie_bus_write16(sc, IE_CMD_XMIT_LINK(sc->xmit_cmds,cur), - 0xffff); - - sc->ie_bus_write16(sc, IE_CMD_XMIT_CMD(sc->xmit_cmds, cur), - IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST); - - off = IE_SCB_CMDLST(sc->scb); - sc->ie_bus_write16(sc, off, IE_CMD_XMIT_ADDR(sc->xmit_cmds, cur)); - IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ); - - if (i82586_start_cmd(sc, IE_CUC_START, 0, 0, ASYNC_OPTION)) - printf("%s: iexmit: start xmit command timed out\n", - sc->arpcom.ac_if.if_name); - } - - sc->arpcom.ac_if.if_timer = 5; -} - - -/* - * Device timeout/watchdog routine. - * Entered if the device neglects to generate an interrupt after a - * transmit has been started on it. - */ -void -i82586_watchdog(struct ifnet *ifp) -{ - struct ie_softc *sc = ifp->if_softc; - printf("%s: device timeout\n", ifp->if_name); - ++ifp->if_oerrors; - i82586_reset(sc, 1); -} - -static int -i82586_cmd_wait(struct ie_softc *sc) -{ - /* spin on i82586 command acknowledge; wait at most 0.9 (!) seconds */ - int i, off; - u_int16_t cmd; - - for (i = 0; i < 900000; i++) { - /* Read the command word */ - off = IE_SCB_CMD(sc->scb); - - IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ); - if ((cmd = sc->ie_bus_read16(sc, off)) == 0) - return (0); - delay(1); - } - - off = IE_SCB_STATUS(sc->scb); - printf("i82586_cmd_wait: timo(%ssync): scb status: 0x%x, cmd: 0x%x\n", - sc->async_cmd_inprogress?"a":"", - sc->ie_bus_read16(sc, off), cmd); - - return (1); /* Timeout */ -} - -/* - * Send a command to the controller and wait for it to either complete - * or be accepted, depending on the command. If the command pointer - * is null, then pretend that the command is not an action command. - * If the command pointer is not null, and the command is an action - * command, wait for one of the MASK bits to turn on in the command's - * status field. - * If ASYNC is set, we just call the chip's attention and return. - * We may have to wait for the command's acceptance later though. - */ -static int -i82586_start_cmd(struct ie_softc *sc, int cmd, int iecmdbuf, int mask, int async) -{ - int i; - int off; - - if (sc->async_cmd_inprogress != 0) { - /* - * If previous command was issued asynchronously, wait - * for it now. - */ - if (i82586_cmd_wait(sc) != 0) - return (1); - sc->async_cmd_inprogress = 0; - } - - off = IE_SCB_CMD(sc->scb); - sc->ie_bus_write16(sc, off, cmd); - IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_WRITE); - (sc->chan_attn)(sc, CARD_RESET); - - if (async != 0) { - sc->async_cmd_inprogress = 1; - return (0); - } - - if (IE_ACTION_COMMAND(cmd) && iecmdbuf) { - int status; - /* - * Now spin-lock waiting for status. This is not a very nice - * thing to do, and can kill performance pretty well... - * According to the packet driver, the minimum timeout - * should be .369 seconds. - */ - for (i = 0; i < 369000; i++) { - /* Read the command status */ - off = IE_CMD_COMMON_STATUS(iecmdbuf); - IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ); - status = sc->ie_bus_read16(sc, off); - if (status & mask) - return (0); - delay(1); - } - - } else { - /* - * Otherwise, just wait for the command to be accepted. - */ - return (i82586_cmd_wait(sc)); - } - - /* Timeout */ - return (1); -} - - -/* - * Transfer accumulated chip error counters to IF. - */ -static __inline void -i82586_count_errors(struct ie_softc *sc) -{ - int scb = sc->scb; - - sc->arpcom.ac_if.if_ierrors += - sc->ie_bus_read16(sc, IE_SCB_ERRCRC(scb)) + - sc->ie_bus_read16(sc, IE_SCB_ERRALN(scb)) + - sc->ie_bus_read16(sc, IE_SCB_ERRRES(scb)) + - sc->ie_bus_read16(sc, IE_SCB_ERROVR(scb)); - - /* Clear error counters */ - sc->ie_bus_write16(sc, IE_SCB_ERRCRC(scb), 0); - sc->ie_bus_write16(sc, IE_SCB_ERRALN(scb), 0); - sc->ie_bus_write16(sc, IE_SCB_ERRRES(scb), 0); - sc->ie_bus_write16(sc, IE_SCB_ERROVR(scb), 0); -} - - -static void -i82586_rx_errors(struct ie_softc *sc, int fn, int status) -{ - char bits[128]; - - printf("%s: rx error (frame# %d): %s\n", sc->arpcom.ac_if.if_name, fn, - bitmask_snprintf(status, IE_FD_STATUSBITS, bits, sizeof(bits))); -} - -/* - * i82586 interrupt entry point. - */ -rtems_isr -i82586_intr(rtems_vector_number vec, void *arg) -{ - struct ie_softc *sc = arg; - -#if I82586_DEBUG - static unsigned long icnt = 0; - I82586_TRACE(sc, I82586_INTS_REQ, icnt++); -#endif - - /* - * Implementation dependent interrupt handling. It must at least - * disabled interrupts from the i82586. It is hoped this can - * happen somewhere outside the i82586. - */ - if (sc->intrhook) - (sc->intrhook)(sc, INTR_ENTER); - - /* - * Wake the task to handle the interrupt. It will - * enabled the interrupts when it has finished. - */ - rtems_bsdnet_event_send (sc->intr_task, i82586_WAKE_EVENT); -} - -/* - * i82586 interrupt task. The task is actually an extension of the interrupt - * with a context switch in the middle. The RTEMS TCP/IP stack requires a task - * be used to talk to the stack as a network semaphore is claimed. This - * cannot happen during an interrupt. - */ -static void -i82586_intr_task(void *arg) -{ - struct ie_softc *sc = arg; - rtems_event_set events; - u_int status; - int off; - int reset; - - /* - * Not sure this is a good idea but as a out path exists and - * roads lead to it, it seems ok. - */ - for (;;) { - rtems_bsdnet_event_receive (i82586_WAKE_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - 0, &events); - - off = IE_SCB_STATUS(sc->scb); - IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ); - status = sc->ie_bus_read16(sc, off) & IE_ST_WHENCE; - -#if I82586_DEBUG - I82586_TRACE(sc, I82586_INTS_IN, status); -#endif - - reset = 0; - - while ((status & IE_ST_WHENCE) != 0) { -#if I82586_DEBUG - if (sc->sc_debug) - printf ("%s: -------\n%s: scbstatus=0x%x\n", - sc->arpcom.ac_if.if_name, sc->arpcom.ac_if.if_name, status); -#endif - -#if 1 - /* Ack interrupts FIRST in case we receive more during the ISR. */ - ie_ack(sc, status & IE_ST_WHENCE); -#endif - - i82586_start_cmd(sc, status & IE_ST_WHENCE, 0, 0, ASYNC_OPTION); - - if (status & (IE_ST_FR | IE_ST_RNR)) - if (i82586_rint(sc, status) != 0) { - reset = 1; - break; - } - - if (status & IE_ST_CX) - if (i82586_tint(sc, status) != 0) { - reset = 1; - break; - } - -#if I82586_DEBUG - if ((status & IE_ST_CNA) && (sc->sc_debug & IED_CNA)) - printf("%s: cna; status=0x%x\n", sc->arpcom.ac_if.if_name, status); -#endif - -#if 0 - if (sc->intrhook) - (sc->intrhook)(sc, INTR_LOOP); -#endif - -#if 1 - /* - * Interrupt ACK was posted asynchronously; wait for - * completion here before reading SCB status again. - * - * If ACK fails, try to reset the chip, in hopes that - * it helps. - */ - if (i82586_cmd_wait(sc) != 0) { - reset = 1; - break; - } -#endif - - IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ); - status = sc->ie_bus_read16(sc, off); -#if I82586_DEBUG - I82586_TRACE(sc, I82586_INTS_LOOPS, status); -#endif - } - - if (reset) { -#if I82586_DEBUG - printf("%s: intr reset; status=0x%x\n", sc->arpcom.ac_if.if_name, status); -#endif - i82586_cmd_wait(sc); - i82586_reset(sc, 1); - } - -#if I82586_DEBUG - I82586_TRACE(sc, I82586_INTS_OUT, status); -#endif - - if (sc->intrhook) - (sc->intrhook)(sc, INTR_EXIT); - } -} - -/* - * Process a received-frame interrupt. - */ -int -i82586_rint(struct ie_softc *sc, int scbstatus) -{ - static int timesthru = 1024; - int i, status, off; - -#if I82586_DEBUG - I82586_TRACE(sc, I82586_RX_INT, scbstatus); - - if (sc->sc_debug & IED_RINT) - printf("%s: rint: status 0x%x\n", - sc->arpcom.ac_if.if_name, scbstatus); -#endif - - for (;;) { - int drop = 0; - - i = sc->rfhead; - off = IE_RFRAME_STATUS(sc->rframes, i); - IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ); - status = sc->ie_bus_read16(sc, off); - -#if I82586_DEBUG - if (sc->sc_debug & IED_RINT) - printf("%s: rint: frame(%d) status 0x%x\n", - sc->arpcom.ac_if.if_name, i, status); -#endif - if ((status & IE_FD_COMPLETE) == 0) { - if ((status & IE_FD_OK) != 0) { - printf("%s: rint: weird: ", - sc->arpcom.ac_if.if_name); - i82586_rx_errors(sc, i, status); -#if I82586_DEBUG - I82586_TRACE(sc, I82586_RX_ERR, status); -#endif - break; - } - if (--timesthru == 0) { - /* Account the accumulated errors */ - i82586_count_errors(sc); - timesthru = 1024; - } - break; - } else if ((status & IE_FD_OK) == 0) { - /* - * If the chip is configured to automatically - * discard bad frames, the only reason we can - * get here is an "out-of-resource" condition. - */ - i82586_rx_errors(sc, i, status); - drop = 1; - -#if I82586_DEBUG - I82586_TRACE(sc, I82586_RX_DROP, status); -#endif - } - -#if I82586_DEBUG - if ((status & IE_FD_BUSY) != 0) - printf("%s: rint: frame(%d) busy; status=0x%x\n", - sc->arpcom.ac_if.if_name, i, status); -#endif - - /* - * Advance the RFD list, since we're done with - * this descriptor. - */ - - /* Clear frame status */ - sc->ie_bus_write16(sc, off, 0); - - /* Put fence at this frame (the head) */ - off = IE_RFRAME_LAST(sc->rframes, i); - sc->ie_bus_write16(sc, off, IE_FD_EOL|IE_FD_SUSP); - - /* and clear RBD field */ - off = IE_RFRAME_BUFDESC(sc->rframes, i); - sc->ie_bus_write16(sc, off, 0xffff); - - /* Remove fence from current tail */ - off = IE_RFRAME_LAST(sc->rframes, sc->rftail); - sc->ie_bus_write16(sc, off, 0); - - if (++sc->rftail == sc->nframes) - sc->rftail = 0; - if (++sc->rfhead == sc->nframes) - sc->rfhead = 0; - - /* Pull the frame off the board */ - if (drop) { - i82586_drop_frames(sc); - if ((status & IE_FD_RNR) != 0) - sc->rnr_expect = 1; - sc->arpcom.ac_if.if_ierrors++; - } else if (ie_readframe(sc, i) != 0) - return (1); - } - - if ((scbstatus & IE_ST_RNR) != 0) { - - /* - * Receiver went "Not Ready". We try to figure out - * whether this was an expected event based on past - * frame status values. - */ - - if ((scbstatus & IE_RUS_SUSPEND) != 0) { - /* - * We use the "suspend on last frame" flag. - * Send a RU RESUME command in response, since - * we should have dealt with all completed frames - * by now. - */ - printf("RINT: SUSPENDED; scbstatus=0x%x\n", - scbstatus); - if (i82586_start_cmd(sc, IE_RUC_RESUME, 0, 0, 0) == 0) - return (0); - printf("%s: RU RESUME command timed out\n", - sc->arpcom.ac_if.if_name); - return (1); /* Ask for a reset */ - } - - if (sc->rnr_expect != 0) { - /* - * The RNR condition was announced in the previously - * completed frame. Assume the receive ring is Ok, - * so restart the receiver without further delay. - */ - i82586_start_transceiver(sc); - sc->rnr_expect = 0; - return (0); - - } else if ((scbstatus & IE_RUS_NOSPACE) != 0) { - /* - * We saw no previous IF_FD_RNR flag. - * We check our ring invariants and, if ok, - * just restart the receiver at the current - * point in the ring. - */ - if (i82586_chk_rx_ring(sc) != 0) - return (1); - - i82586_start_transceiver(sc); - sc->arpcom.ac_if.if_ierrors++; - return (0); - } else - printf("%s: receiver not ready; scbstatus=0x%x\n", - sc->arpcom.ac_if.if_name, scbstatus); - - sc->arpcom.ac_if.if_ierrors++; - return (1); /* Ask for a reset */ - } - - return (0); -} - -/* - * Process a command-complete interrupt. These are only generated by the - * transmission of frames. This routine is deceptively simple, since most - * of the real work is done by i82586_start(). - */ -int -i82586_tint(struct ie_softc *sc, int scbstatus) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - int status; - -#if I82586_DEBUG - I82586_TRACE(sc, I82586_TX_INT, sc->xmit_busy); -#endif - -#if I82586_DEBUG - if (sc->xmit_busy <= 0) { - printf("i82586_tint: (%d), WEIRD: xmit_busy=%d, xctail=%d, xchead=%d\n", - sc->trace_flow_in / 2, sc->xmit_busy, sc->xctail, sc->xchead); - I82586_TRACE(sc, I82586_TX_BAD, sc->xctail); - return (0); - } -#endif - - ifp->if_timer = 0; - ifp->if_flags &= ~IFF_OACTIVE; - - status = sc->ie_bus_read16(sc, IE_CMD_XMIT_STATUS(sc->xmit_cmds, - sc->xctail)); - -#if I82586_DEBUG - if (sc->sc_debug & IED_TINT) - printf("%s: tint: SCB status 0x%x; xmit status 0x%x\n", - sc->arpcom.ac_if.if_name, scbstatus, status); -#endif - - if ((status & IE_STAT_COMPL) == 0 || (status & IE_STAT_BUSY)) { - printf("i82586_tint: (%d) command still busy; status=0x%x; tail=%d\n", - sc->trace_flow_in / 2, status, sc->xctail); - printf("iestatus = 0x%x\n", scbstatus); -/* sc->sc_debug = IED_ALL; */ - } - - if (status & IE_STAT_OK) { - ifp->if_opackets++; - ifp->if_collisions += (status & IE_XS_MAXCOLL); - } else { - ifp->if_oerrors++; - /* - * Check SQE and DEFERRED? - * What if more than one bit is set? - */ - if (status & IE_STAT_ABORT) - printf("%s: send aborted\n", sc->arpcom.ac_if.if_name); - else if (status & IE_XS_NOCARRIER) - printf("%s: no carrier\n", sc->arpcom.ac_if.if_name); - else if (status & IE_XS_LOSTCTS) - printf("%s: lost CTS\n", sc->arpcom.ac_if.if_name); - else if (status & IE_XS_UNDERRUN) - printf("%s: DMA underrun\n", sc->arpcom.ac_if.if_name); - else if (status & IE_XS_EXCMAX) { - printf("%s: too many collisions\n", - sc->arpcom.ac_if.if_name); - sc->arpcom.ac_if.if_collisions += 16; - } - } - - /* - * If multicast addresses were added or deleted while transmitting, - * ie_mc_reset() set the want_mcsetup flag indicating that we - * should do it. - */ - if (sc->want_mcsetup) { - ie_mc_setup(sc, IE_XBUF_ADDR(sc, sc->xctail)); - sc->want_mcsetup = 0; - } - - /* Done with the buffer. */ - sc->xmit_busy--; - sc->xctail = (sc->xctail + 1) % NTXBUF; - - /* Start the next packet, if any, transmitting. */ - if (sc->xmit_busy > 0) - iexmit(sc); - - i82586_start_tx(sc); - return (0); -} - -/* - * Get a range of receive buffer descriptors that represent one packet. - */ -static int -i82586_get_rbd_list(struct ie_softc *sc, u_int16_t *start, u_int16_t *end, int *pktlen) -{ - int off, rbbase = sc->rbds; - int rbindex, count = 0; - int plen = 0; - int rbdstatus; - - *start = rbindex = sc->rbhead; - - do { - off = IE_RBD_STATUS(rbbase, rbindex); - IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ); - rbdstatus = sc->ie_bus_read16(sc, off); - if ((rbdstatus & IE_RBD_USED) == 0) { - /* - * This means we are somehow out of sync. So, we - * reset the adapter. - */ -#if I82586_DEBUG - print_rbd(sc, rbindex); -#endif - printf("%s: receive descriptors out of sync at %d\n", - sc->arpcom.ac_if.if_name, rbindex); - return (0); - } - plen += (rbdstatus & IE_RBD_CNTMASK); - - if (++rbindex == sc->nrxbuf) - rbindex = 0; - - ++count; - } while ((rbdstatus & IE_RBD_LAST) == 0); - *end = rbindex; - *pktlen = plen; - return (count); -} - - -/* - * Release a range of receive buffer descriptors after we've copied the packet. - */ -static void -i82586_release_rbd_list(struct ie_softc *sc, u_int16_t start, u_int16_t end) -{ - int off, rbbase = sc->rbds; - int rbindex = start; - - do { - /* Clear buffer status */ - off = IE_RBD_STATUS(rbbase, rbindex); - sc->ie_bus_write16(sc, off, 0); - if (++rbindex == sc->nrxbuf) - rbindex = 0; - } while (rbindex != end); - - /* Mark EOL at new tail */ - rbindex = ((rbindex == 0) ? sc->nrxbuf : rbindex) - 1; - off = IE_RBD_BUFLEN(rbbase, rbindex); - sc->ie_bus_write16(sc, off, IE_RBUF_SIZE|IE_RBD_EOL); - - /* Remove EOL from current tail */ - off = IE_RBD_BUFLEN(rbbase, sc->rbtail); - sc->ie_bus_write16(sc, off, IE_RBUF_SIZE); - - /* New head & tail pointer */ -/* hmm, why have both? head is always (tail + 1) % NRXBUF */ - sc->rbhead = end; - sc->rbtail = rbindex; -} - -/* - * Drop the packet at the head of the RX buffer ring. - * Called if the frame descriptor reports an error on this packet. - * Returns 1 if the buffer descriptor ring appears to be corrupt; - * and 0 otherwise. - */ -static int -i82586_drop_frames(struct ie_softc *sc) -{ - u_int16_t bstart, bend; - int pktlen; - - if (i82586_get_rbd_list(sc, &bstart, &bend, &pktlen) == 0) - return (1); - i82586_release_rbd_list(sc, bstart, bend); - return (0); -} - -/* - * Check the RX frame & buffer descriptor lists for our invariants, - * i.e.: EOL bit set iff. it is pointed at by the r*tail pointer. - * - * Called when the receive unit has stopped unexpectedly. - * Returns 1 if an inconsistency is detected; 0 otherwise. - * - * The Receive Unit is expected to be NOT RUNNING. - */ -static int -i82586_chk_rx_ring(struct ie_softc *sc) -{ - int n, off, val; - - for (n = 0; n < sc->nrxbuf; n++) { - off = IE_RBD_BUFLEN(sc->rbds, n); - val = sc->ie_bus_read16(sc, off); - if ((n == sc->rbtail) ^ ((val & IE_RBD_EOL) != 0)) { - /* `rbtail' and EOL flag out of sync */ - printf("%s: rx buffer descriptors out of sync at %d\n", - sc->arpcom.ac_if.if_name, n); - return (1); - } - - /* Take the opportunity to clear the status fields here ? */ - } - - for (n = 0; n < sc->nframes; n++) { - off = IE_RFRAME_LAST(sc->rframes, n); - val = sc->ie_bus_read16(sc, off); - if ((n == sc->rftail) ^ ((val & (IE_FD_EOL|IE_FD_SUSP)) != 0)) { - /* `rftail' and EOL flag out of sync */ - printf("%s: rx frame list out of sync at %d\n", - sc->arpcom.ac_if.if_name, n); - return (1); - } - } - - return (0); -} - - -/* - * Read frame NUM from unit UNIT (pre-cached as IE). - * - * This routine reads the RFD at NUM, and copies in the buffers from the list - * of RBD, then rotates the RBD list so that the receiver doesn't start - * complaining. Trailers are DROPPED---there's no point in wasting time - * on confusing code to deal with them. Hopefully, this machine will - * never ARP for trailers anyway. - */ -static int -ie_readframe(struct ie_softc *sc, int num) /* frame number to read */ -{ - struct ether_header *eh; - struct mbuf *m; - u_int16_t bstart, bend; - int pktlen; - - if (i82586_get_rbd_list(sc, &bstart, &bend, &pktlen) == 0) { - sc->arpcom.ac_if.if_ierrors++; - return (1); - } - - m = ieget(sc, bstart, pktlen); - i82586_release_rbd_list(sc, bstart, bend); - - if (m == 0) { - sc->arpcom.ac_if.if_ierrors++; - return (0); - } - - /* - * Remove the mac header. This is different from the NetBSD - * stack. - */ - eh = mtod(m, struct ether_header *); - m->m_data += sizeof (struct ether_header); - m->m_len -= sizeof (struct ether_header); - m->m_pkthdr.len -= sizeof (struct ether_header); - -#if I82586_DEBUG - if (sc->sc_debug & IED_READFRAME) { - - printf("%s: frame from ether %s type 0x%x len %d\n", - sc->arpcom.ac_if.if_name, - ether_sprintf(eh->ether_shost), - (u_int)ntohs(eh->ether_type), - pktlen); - } -#endif - -#if NBPFILTER > 0 - /* Check for a BPF filter; if so, hand it up. */ - if (sc->arpcom.ac_if.if_bpf != 0) - /* Pass it up. */ - bpf_mtap(sc->arpcom.ac_if.if_bpf, m); -#endif /* NBPFILTER > 0 */ - - /* - * Finally pass this packet up to higher layers. - */ - ether_input (&sc->arpcom.ac_if, eh, m); - sc->arpcom.ac_if.if_ipackets++; - -#if I82586_DEBUG - I82586_TRACE(sc, I82586_RX_OK, sc->arpcom.ac_if.if_ipackets); -#endif - - return (0); -} - -/* - * Start transmission on an interface. - */ -void -i82586_start(struct ifnet *ifp) -{ - struct ie_softc *sc = ifp->if_softc; - - if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) - return; - -#if I82586_DEBUG - I82586_TRACE(sc, I82586_TX_REQ, sc->xmit_busy); -#endif - - rtems_bsdnet_event_send (sc->tx_task, i82586_TX_EVENT); -} - -static void -i82586_tx_task(void *arg) -{ - struct ie_softc *sc = arg; - rtems_event_set events; - - for (;;) { - rtems_bsdnet_event_receive (i82586_TX_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - 0, &events); - -#if I82586_DEBUG - I82586_TRACE(sc, I82586_TX_EVT, sc->xmit_busy); - - if (sc->sc_debug) - printf ("%s: =======\n", sc->arpcom.ac_if.if_name); -#endif - - i82586_start_tx(sc); - } -} - -static void -i82586_start_tx(struct ie_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m0, *m; - int buffer, head, xbase; - u_short len; - int s; - -#if I82586_DEBUG - I82586_TRACE(sc, I82586_START_TX, sc->xmit_busy); -#endif - - if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) - { -#if I82586_DEBUG - I82586_TRACE(sc, I82586_TX_ACTIVE, ifp->if_snd.ifq_len); -#endif - return; - } - - for (;;) { - if (sc->xmit_busy == NTXBUF) { - ifp->if_flags |= IFF_OACTIVE; - break; - } - - head = sc->xchead; - xbase = sc->xbds; - - IF_DEQUEUE(&ifp->if_snd, m0); - if (m0 == 0) - break; - - /* We need to use m->m_pkthdr.len, so require the header */ - if ((m0->m_flags & M_PKTHDR) == 0) - panic("i82586_start: no header mbuf"); - -#if NBPFILTER > 0 - /* Tap off here if there is a BPF listener. */ - if (ifp->if_bpf) - bpf_mtap(ifp->if_bpf, m0); -#endif - -#if I82586_DEBUG - if (sc->sc_debug & IED_ENQ) - printf("%s: fill buffer %d\n", sc->arpcom.ac_if.if_name, - sc->xchead); -#endif - - if (m0->m_pkthdr.len > IE_TBUF_SIZE) - printf("%s: tbuf overflow\n", sc->arpcom.ac_if.if_name); - - buffer = IE_XBUF_ADDR(sc, head); - for (m = m0; m != 0; m = m->m_next) { - (sc->memcopyout)(sc, mtod(m,caddr_t), buffer, m->m_len); - buffer += m->m_len; - } - - len = max(m0->m_pkthdr.len, ETHER_MIN_LEN); - m_freem(m0); - - /* - * Setup the transmit buffer descriptor here, while we - * know the packet's length. - */ - sc->ie_bus_write16(sc, IE_XBD_FLAGS(xbase, head), - len | IE_TBD_EOL); - sc->ie_bus_write16(sc, IE_XBD_NEXT(xbase, head), 0xffff); - sc->ie_bus_write24(sc, IE_XBD_BUF(xbase, head), - IE_XBUF_ADDR(sc, head)); - - if (++head == NTXBUF) - head = 0; - sc->xchead = head; - -#if I82586_DEBUG - I82586_TRACE(sc, I82586_TX_START, sc->xmit_busy); -#endif - - s = splnet(); - /* Start the first packet transmitting. */ - if (sc->xmit_busy == 0) - iexmit(sc); - - sc->xmit_busy++; - - splx(s); - } -} - -/* - * Probe IE's ram setup [ Move all this into MD front-end!? ] - * Use only if SCP and ISCP represent offsets into shared ram space. - */ -int -i82586_proberam(struct ie_softc *sc) -{ - int result, off; - - /* Put in 16-bit mode */ - off = IE_SCP_BUS_USE(sc->scp); - sc->ie_bus_write16(sc, off, 0); - IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_WRITE); - - /* Set the ISCP `busy' bit */ - off = IE_ISCP_BUSY(sc->iscp); - sc->ie_bus_write16(sc, off, 1); - IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_WRITE); - - if (sc->hwreset) - (sc->hwreset)(sc, CHIP_PROBE); - - (sc->chan_attn) (sc, CHIP_PROBE); - - delay(100); /* wait a while... */ - - /* Read back the ISCP `busy' bit; it should be clear by now */ - off = IE_ISCP_BUSY(sc->iscp); - IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ); - result = sc->ie_bus_read16(sc, off) == 0; - - /* Acknowledge any interrupts we may have caused. */ - ie_ack(sc, IE_ST_WHENCE); - - return (result); -} - -void -i82586_reset(struct ie_softc *sc, int hard) -{ - int s = splnet(); - - if (hard) - printf("%s: reset\n", sc->arpcom.ac_if.if_name); - - /* Clear OACTIVE in case we're called from watchdog (frozen xmit). */ - sc->arpcom.ac_if.if_timer = 0; - sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE; - - /* - * Stop i82586 dead in its tracks. - */ - if (i82586_start_cmd(sc, IE_RUC_ABORT | IE_CUC_ABORT, 0, 0, 0)) - printf("%s: abort commands timed out\n", sc->arpcom.ac_if.if_name); - - /* - * This can really slow down the i82586_reset() on some cards, but it's - * necessary to unwedge other ones (eg, the Sun VME ones) from certain - * lockups. - */ - if (hard && sc->hwreset) - (sc->hwreset)(sc, CARD_RESET); - - delay(100); - ie_ack(sc, IE_ST_WHENCE); - - if ((sc->arpcom.ac_if.if_flags & IFF_UP) != 0) { - i82586_init(&sc->arpcom.ac_if); - } - - splx(s); -} - -static void -setup_simple_command(struct ie_softc *sc, int cmd, int cmdbuf) -{ - /* Setup a simple command */ - sc->ie_bus_write16(sc, IE_CMD_COMMON_STATUS(cmdbuf), 0); - sc->ie_bus_write16(sc, IE_CMD_COMMON_CMD(cmdbuf), cmd | IE_CMD_LAST); - sc->ie_bus_write16(sc, IE_CMD_COMMON_LINK(cmdbuf), 0xffff); - - /* Assign the command buffer to the SCB command list */ - sc->ie_bus_write16(sc, IE_SCB_CMDLST(sc->scb), cmdbuf); -} - -/* - * Run the time-domain reflectometer. - */ -static void -ie_run_tdr(struct ie_softc *sc, int cmd) -{ - uint32_t result; - - setup_simple_command(sc, IE_CMD_TDR, cmd); - sc->ie_bus_write16(sc, IE_CMD_TDR_TIME(cmd), 0); - - if (i82586_start_cmd(sc, IE_CUC_START, cmd, IE_STAT_COMPL, 0) || - (sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmd)) & IE_STAT_OK) == 0) - result = 0x10000; /* XXX */ - else - result = sc->ie_bus_read16(sc, IE_CMD_TDR_TIME(cmd)); - - /* Squash any pending interrupts */ - ie_ack(sc, IE_ST_WHENCE); - - if (result & IE_TDR_SUCCESS) - return; - - if (result & 0x10000) - printf("%s: TDR command failed\n", sc->arpcom.ac_if.if_name); - else if (result & IE_TDR_XCVR) - printf("%s: transceiver problem\n", sc->arpcom.ac_if.if_name); - else if (result & IE_TDR_OPEN) - printf("%s: TDR detected incorrect termination %" PRId32 " clocks away\n", - sc->arpcom.ac_if.if_name, result & IE_TDR_TIME); - else if (result & IE_TDR_SHORT) - printf("%s: TDR detected a short circuit %" PRId32 " clocks away\n", - sc->arpcom.ac_if.if_name, result & IE_TDR_TIME); - else - printf("%s: TDR returned unknown status 0x%" PRIx32 "\n", - sc->arpcom.ac_if.if_name, result); -} - - -/* - * i82586_setup_bufs: set up the buffers - * - * We have a block of KVA at sc->buf_area which is of size sc->buf_area_sz. - * this is to be used for the buffers. The chip indexs its control data - * structures with 16 bit offsets, and it indexes actual buffers with - * 24 bit addresses. So we should allocate control buffers first so that - * we don't overflow the 16 bit offset field. The number of transmit - * buffers is fixed at compile time. - * - */ -static void -i82586_setup_bufs(struct ie_softc *sc) -{ - int ptr = sc->buf_area; /* memory pool */ - int n, r; - - /* - * step 0: zero memory and figure out how many recv buffers and - * frames we can have. - */ - ptr = (ptr + 3) & ~3; /* set alignment and stick with it */ - - - /* - * step 1: lay out data structures in the shared-memory area - */ - - /* The no-op commands; used if "nop-chaining" is in effect */ - sc->nop_cmds = ptr; - ptr += NTXBUF * IE_CMD_NOP_SZ; - - /* The transmit commands */ - sc->xmit_cmds = ptr; - ptr += NTXBUF * IE_CMD_XMIT_SZ; - - /* The transmit buffers descriptors */ - sc->xbds = ptr; - ptr += NTXBUF * IE_XBD_SZ; - - /* The transmit buffers */ - sc->xbufs = ptr; - ptr += NTXBUF * IE_TBUF_SIZE; - - ptr = (ptr + 3) & ~3; /* re-align.. just in case */ - - /* Compute free space for RECV stuff */ - n = sc->buf_area_sz - (ptr - sc->buf_area); - - /* Compute size of one RECV frame */ - r = IE_RFRAME_SZ + ((IE_RBD_SZ + IE_RBUF_SIZE) * B_PER_F); - - sc->nframes = n / r; - - if (sc->nframes <= 0) - panic("ie: bogus buffer calc\n"); - - sc->nrxbuf = sc->nframes * B_PER_F; - - /* The receice frame descriptors */ - sc->rframes = ptr; - ptr += sc->nframes * IE_RFRAME_SZ; - - /* The receive buffer descriptors */ - sc->rbds = ptr; - ptr += sc->nrxbuf * IE_RBD_SZ; - - /* The receive buffers */ - sc->rbufs = ptr; - ptr += sc->nrxbuf * IE_RBUF_SIZE; - -#if I82586_DEBUG - printf("%s: %d frames %d bufs\n", sc->arpcom.ac_if.if_name, sc->nframes, - sc->nrxbuf); -#endif - - /* - * step 2: link together the recv frames and set EOL on last one - */ - for (n = 0; n < sc->nframes; n++) { - int m = (n == sc->nframes - 1) ? 0 : n + 1; - - /* Clear status */ - sc->ie_bus_write16(sc, IE_RFRAME_STATUS(sc->rframes,n), 0); - - /* RBD link = NULL */ - sc->ie_bus_write16(sc, IE_RFRAME_BUFDESC(sc->rframes,n), - 0xffff); - - /* Make a circular list */ - sc->ie_bus_write16(sc, IE_RFRAME_NEXT(sc->rframes,n), - IE_RFRAME_ADDR(sc->rframes,m)); - - /* Mark last as EOL */ - sc->ie_bus_write16(sc, IE_RFRAME_LAST(sc->rframes,n), - ((m==0)? (IE_FD_EOL|IE_FD_SUSP) : 0)); - } - - /* - * step 3: link the RBDs and set EOL on last one - */ - for (n = 0; n < sc->nrxbuf; n++) { - int m = (n == sc->nrxbuf - 1) ? 0 : n + 1; - - /* Clear status */ - sc->ie_bus_write16(sc, IE_RBD_STATUS(sc->rbds,n), 0); - - /* Make a circular list */ - sc->ie_bus_write16(sc, IE_RBD_NEXT(sc->rbds,n), - IE_RBD_ADDR(sc->rbds,m)); - - /* Link to data buffers */ - sc->ie_bus_write24(sc, IE_RBD_BUFADDR(sc->rbds, n), - IE_RBUF_ADDR(sc, n)); - sc->ie_bus_write16(sc, IE_RBD_BUFLEN(sc->rbds,n), - IE_RBUF_SIZE | ((m==0)?IE_RBD_EOL:0)); - } - - /* - * step 4: all xmit no-op commands loopback onto themselves - */ - for (n = 0; n < NTXBUF; n++) { - sc->ie_bus_write16(sc, IE_CMD_NOP_STATUS(sc->nop_cmds, n), 0); - - sc->ie_bus_write16(sc, IE_CMD_NOP_CMD(sc->nop_cmds, n), - IE_CMD_NOP); - - sc->ie_bus_write16(sc, IE_CMD_NOP_LINK(sc->nop_cmds, n), - IE_CMD_NOP_ADDR(sc->nop_cmds, n)); - } - - - /* - * step 6: set the head and tail pointers on receive to keep track of - * the order in which RFDs and RBDs are used. - */ - - /* Pointers to last packet sent and next available transmit buffer. */ - sc->xchead = sc->xctail = 0; - - /* Clear transmit-busy flag and set number of free transmit buffers. */ - sc->xmit_busy = 0; - - /* - * Pointers to first and last receive frame. - * The RFD pointed to by rftail is the only one that has EOL set. - */ - sc->rfhead = 0; - sc->rftail = sc->nframes - 1; - - /* - * Pointers to first and last receive descriptor buffer. - * The RBD pointed to by rbtail is the only one that has EOL set. - */ - sc->rbhead = 0; - sc->rbtail = sc->nrxbuf - 1; - -/* link in recv frames * and buffer into the scb. */ -#if I82586_DEBUG - printf("%s: reserved %d bytes\n", - sc->arpcom.ac_if.if_name, ptr - sc->buf_area); -#endif -} - -static int -ie_cfg_setup(struct ie_softc *sc, int cmd, int promiscuous, int manchester) -{ - int cmdresult, status; - u_int8_t buf[IE_CMD_CFG_SZ]; /* XXX malloc? */ - - *IE_CMD_CFG_CNT(buf) = 0x0c; - *IE_CMD_CFG_FIFO(buf) = 8; - *IE_CMD_CFG_SAVEBAD(buf) = 0x40; - *IE_CMD_CFG_ADDRLEN(buf) = 0x2e; - *IE_CMD_CFG_PRIORITY(buf) = 0; - *IE_CMD_CFG_IFS(buf) = 0x60; - *IE_CMD_CFG_SLOT_LOW(buf) = 0; - *IE_CMD_CFG_SLOT_HIGH(buf) = 0xf2; - *IE_CMD_CFG_PROMISC(buf) = (!!promiscuous) | (manchester << 2); - *IE_CMD_CFG_CRSCDT(buf) = 0; - *IE_CMD_CFG_MINLEN(buf) = 64; - *IE_CMD_CFG_JUNK(buf) = 0xff; - sc->memcopyout(sc, buf, cmd, IE_CMD_CFG_SZ); - setup_simple_command(sc, IE_CMD_CONFIG, cmd); - IE_BUS_BARRIER(sc, cmd, IE_CMD_CFG_SZ, BUS_SPACE_BARRIER_WRITE); - - cmdresult = i82586_start_cmd(sc, IE_CUC_START, cmd, IE_STAT_COMPL, 0); - status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmd)); - if (cmdresult != 0) { - printf("%s: configure command timed out; status %x\n", - sc->arpcom.ac_if.if_name, status); - return (0); - } - if ((status & IE_STAT_OK) == 0) { - printf("%s: configure command failed; status %x\n", - sc->arpcom.ac_if.if_name, status); - return (0); - } - - /* Squash any pending interrupts */ - ie_ack(sc, IE_ST_WHENCE); - return (1); -} - -static int -ie_ia_setup(struct ie_softc *sc, int cmdbuf) -{ - int cmdresult, status; - - setup_simple_command(sc, IE_CMD_IASETUP, cmdbuf); - - (sc->memcopyout)(sc, sc->arpcom.ac_enaddr, - IE_CMD_IAS_EADDR(cmdbuf), ETHER_ADDR_LEN); - - cmdresult = i82586_start_cmd(sc, IE_CUC_START, cmdbuf, IE_STAT_COMPL, 0); - status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmdbuf)); - if (cmdresult != 0) { - printf("%s: individual address command timed out; status %x\n", - sc->arpcom.ac_if.if_name, status); - return (0); - } - if ((status & IE_STAT_OK) == 0) { - printf("%s: individual address command failed; status %x\n", - sc->arpcom.ac_if.if_name, status); - return (0); - } - - /* Squash any pending interrupts */ - ie_ack(sc, IE_ST_WHENCE); - return (1); -} - -/* - * Run the multicast setup command. - * Called at splnet(). - */ -static int -ie_mc_setup(struct ie_softc *sc, int cmdbuf) -{ - int cmdresult, status; - - if (sc->mcast_count == 0) - return (1); - - setup_simple_command(sc, IE_CMD_MCAST, cmdbuf); - - (sc->memcopyout)(sc, (caddr_t)sc->mcast_addrs, - IE_CMD_MCAST_MADDR(cmdbuf), - sc->mcast_count * ETHER_ADDR_LEN); - - sc->ie_bus_write16(sc, IE_CMD_MCAST_BYTES(cmdbuf), - sc->mcast_count * ETHER_ADDR_LEN); - - /* Start the command */ - cmdresult = i82586_start_cmd(sc, IE_CUC_START, cmdbuf, IE_STAT_COMPL, 0); - status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmdbuf)); - if (cmdresult != 0) { - printf("%s: multicast setup command timed out; status %x\n", - sc->arpcom.ac_if.if_name, status); - return (0); - } - if ((status & IE_STAT_OK) == 0) { - printf("%s: multicast setup command failed; status %x\n", - sc->arpcom.ac_if.if_name, status); - return (0); - } - - /* Squash any pending interrupts */ - ie_ack(sc, IE_ST_WHENCE); - return (1); -} - -/* - * This routine takes the environment generated by check_ie_present() and adds - * to it all the other structures we need to operate the adapter. This - * includes executing the CONFIGURE, IA-SETUP, and MC-SETUP commands, starting - * the receiver unit, and clearing interrupts. - * - * THIS ROUTINE MUST BE CALLED AT splnet() OR HIGHER. - */ -void -i82586_init(void *arg) -{ - struct ie_softc *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - int cmd; - - sc->async_cmd_inprogress = 0; - sc->xmit_busy = 0; - -#if I82586_DEBUG - memset(sc->trace_flow, 0, sizeof(sc->trace_flow)); - sc->trace_flow_wrap = 0; -#endif - sc->trace_flow_in = 0; - - cmd = sc->buf_area; - -#if I82586_DEBUG - printf ("%s: sc_debug at 0x%08x\n", sc->arpcom.ac_if.if_name, (unsigned int) &sc->sc_debug); -#endif - - /* - * Send the configure command first. - */ - if (ie_cfg_setup(sc, cmd, sc->promisc, 0) == 0) - return; - - /* - * Send the Individual Address Setup command. - */ - if (ie_ia_setup(sc, cmd) == 0) - return; - - /* - * Run the time-domain reflectometer. - */ - ie_run_tdr(sc, cmd); - - /* - * Set the multi-cast filter, if any - */ - if (ie_mc_setup(sc, cmd) == 0) - return; - - /* - * If no tasks exist, create them. Need to add something to allow - * different names for the different devices. - */ - if (sc->intr_task == 0) - sc->intr_task = rtems_bsdnet_newproc ("IEi0", 2048, i82586_intr_task, sc); - if (sc->tx_task == 0) - sc->tx_task = rtems_bsdnet_newproc ("IEt0", 2048, i82586_tx_task, sc); - - - /* - * Acknowledge any interrupts we have generated thus far. - */ - ie_ack(sc, IE_ST_WHENCE); - - /* - * Set up the transmit and recv buffers. - */ - i82586_setup_bufs(sc); - - if (sc->hwinit) - (sc->hwinit)(sc); - - ifp->if_flags |= IFF_RUNNING; - ifp->if_flags &= ~IFF_OACTIVE; - - if (NTXBUF < 2) - sc->do_xmitnopchain = 0; - - i82586_start_transceiver(sc); -} - -/* - * Start the RU and possibly the CU unit - */ -static void -i82586_start_transceiver(struct ie_softc *sc) -{ -#if I82586_DEBUG - I82586_TRACE(sc, I82586_RX_START, 0); -#endif - - /* - * Start RU at current position in frame & RBD lists. - */ - sc->ie_bus_write16(sc, IE_RFRAME_BUFDESC(sc->rframes,sc->rfhead), - IE_RBD_ADDR(sc->rbds, sc->rbhead)); - - sc->ie_bus_write16(sc, IE_SCB_RCVLST(sc->scb), - IE_RFRAME_ADDR(sc->rframes,sc->rfhead)); - - if (sc->do_xmitnopchain) { - /* Stop transmit command chain */ - if (i82586_start_cmd(sc, IE_CUC_SUSPEND|IE_RUC_SUSPEND, 0, 0, 0)) - printf("%s: CU/RU stop command timed out\n", - sc->arpcom.ac_if.if_name); - - /* Start the receiver & transmitter chain */ - /* sc->scb->ie_command_list = - IEADDR(sc->nop_cmds[(sc->xctail+NTXBUF-1) % NTXBUF]);*/ - sc->ie_bus_write16(sc, IE_SCB_CMDLST(sc->scb), - IE_CMD_NOP_ADDR( - sc->nop_cmds, - (sc->xctail + NTXBUF - 1) % NTXBUF)); - - if (i82586_start_cmd(sc, IE_CUC_START|IE_RUC_START, 0, 0, 0)) - printf("%s: CU/RU command timed out\n", - sc->arpcom.ac_if.if_name); - } else { - if (i82586_start_cmd(sc, IE_RUC_START, 0, 0, 0)) - printf("%s: RU command timed out\n", - sc->arpcom.ac_if.if_name); - } -} - -void -i82586_stop(struct ifnet *ifp, int disable) -{ - struct ie_softc *sc = ifp->if_softc; - - if (i82586_start_cmd(sc, IE_RUC_SUSPEND | IE_CUC_SUSPEND, 0, 0, 0)) - printf("%s: iestop: disable commands timed out\n", - sc->arpcom.ac_if.if_name); -} - -int -i82586_ioctl(struct ifnet *ifp, ioctl_command_t cmd, caddr_t data) -{ - struct ie_softc *sc = ifp->if_softc; -/* struct ifreq *ifr = (struct ifreq *)data; */ - int s; - int error = 0; - - s = splnet(); - switch(cmd) { - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - break; - case SIO_RTEMS_SHOW_STATS: -#if I82586_DEBUG - print_softie(sc); -#endif - break; - default: - error = ether_ioctl(ifp, cmd, data); - if (error == ENETRESET) { - /* - * Multicast list has changed; set the hardware filter - * accordingly. - */ - ie_mc_reset(sc); - error = 0; - } - break; - } -#if I82586_DEBUG - if (cmd == SIOCSIFFLAGS) - sc->sc_debug = (ifp->if_flags & IFF_DEBUG) ? IED_ALL : 0; -#endif - splx(s); - return (error); -} - -static void -ie_mc_reset(struct ie_softc *sc) -{ - struct ether_multi *enm; - struct ether_multistep step; - int size; - - /* - * Step through the list of addresses. - */ - again: - size = 0; - sc->mcast_count = 0; - ETHER_FIRST_MULTI(step, &sc->arpcom, enm); - while (enm) { - size += 6; - if (sc->mcast_count >= IE_MAXMCAST || - memcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) { - sc->arpcom.ac_if.if_flags |= IFF_ALLMULTI; - i82586_ioctl(&sc->arpcom.ac_if, - SIOCSIFFLAGS, (void *)0); - return; - } - ETHER_NEXT_MULTI(step, enm); - } - - if (size > sc->mcast_addrs_size) { - /* Need to allocate more space */ - if (sc->mcast_addrs_size) - free(sc->mcast_addrs, M_IPMADDR); - sc->mcast_addrs = (char *) - malloc(size, M_IPMADDR, M_WAITOK); - sc->mcast_addrs_size = size; - } - - /* - * We've got the space; now copy the addresses - */ - ETHER_FIRST_MULTI(step, &sc->arpcom, enm); - while (enm) { - if (sc->mcast_count >= IE_MAXMCAST) - goto again; /* Just in case */ - - memcpy(&sc->mcast_addrs[sc->mcast_count], enm->enm_addrlo, 6); - sc->mcast_count++; - ETHER_NEXT_MULTI(step, enm); - } - sc->want_mcsetup = 1; -} - -/* - * Media change callback. - */ -int -i82586_mediachange(struct ifnet *ifp) -{ - struct ie_softc *sc = ifp->if_softc; - - if (sc->sc_mediachange) - return ((*sc->sc_mediachange)(sc)); - return (0); -} - -/* - * Media status callback. - */ -void -i82586_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) -{ - struct ie_softc *sc = ifp->if_softc; - - if (sc->sc_mediastatus) - (*sc->sc_mediastatus)(sc, ifmr); -} - -#if I82586_DEBUG -static void -print_softie(struct ie_softc *sc) -{ - static char *trace_labels[] = { - "INTS_REQ", - "INTS_IN", - "INTS_LOOPS", - "INTS_OUT", - "RX_INT", - "RX_DROP", - "RX_ERR", - "RX_OK", - "RX_START", - "START_TX", - "TX_START", - "TX_INT", - "TX_REQ", - "TX_EVT", - "TX_EMIT", - "TX_BAD", - "TX_ACTIVE", - "TRACE_CNT" - }; - - int i; - - printf("i82586 %s:\n", sc->arpcom.ac_if.if_name); - - printf(" iobase=%p\n", sc->sc_iobase); - - printf(" scp=0x%08x\t\tiscp=0x%08x\t\tscb=0x%08x\n", - sc->scp, sc->iscp, sc->scb); - printf(" buf_area=0x%08x\tbuf_area_sz=0x%08x\n", - sc->buf_area, sc->buf_area_sz); - printf(" rframes=0x%08x\trbds=0x%08x\t\trbufs=0x%08x\n", - sc->rframes, sc->rbds, sc->rbufs); - printf(" nop_cmds=0x%08x\txmit_cmds=0x%08x\n", - sc->nop_cmds, sc->xmit_cmds); - printf(" xbds=0x%08x\txbufs=0x%08x\n\n", - sc->xbds, sc->xbufs); - printf(" rfhead=%d\trftail=%d\n", - sc->rfhead, sc->rftail); - printf(" rbhead=%d\trbtail=%d\n", - sc->rbhead, sc->rbtail); - printf(" nframes=%d\tnrxbuf=%d\trnr_expect=%d\n", - sc->nframes, sc->nrxbuf, sc->rnr_expect); - printf(" xchead=%d\txctail=%d\n", - sc->xchead, sc->xctail); - printf(" xmit_busy=%d\txmit_req=%d\tdo_xmitnopchain=%d\n", - sc->xmit_busy, sc->xmit_req, sc->do_xmitnopchain); - printf(" promisc=%d\tasync_cmd_inprogress=%d\n\n", - sc->promisc, sc->async_cmd_inprogress); - - { - int cnt; - int in; - int lfdone = 0; - char *tabs; - - if (!sc->trace_flow_wrap) { - cnt = sc->trace_flow_in; - in = 0; - } - else { - cnt = I82586_TRACE_FLOW; - in = sc->trace_flow_in; - } - - sc->trace_flow_in = sc->trace_flow_wrap = 0; - - cnt /= 2; - - for (i = 0; i < cnt; i++) { - if (!lfdone) { - switch (sc->trace_flow[in]) { - case I82586_INTS_REQ: - case I82586_INTS_IN: - printf("\n"); - } - } - - lfdone = 0; - - if (strlen(trace_labels[sc->trace_flow[in]]) < 8) - tabs = "\t\t"; - else - tabs = "\t"; - - printf(" %d\t%s%s0x%08x (%d)\n", - i, trace_labels[sc->trace_flow[in]], tabs, - sc->trace_flow[in + 1], sc->trace_flow[in + 1]); - - switch (sc->trace_flow[in]) { - case I82586_INTS_REQ: - case I82586_INTS_OUT: - lfdone = 1; - printf("\n"); - } - - in += 2; - - if (in >= I82586_TRACE_FLOW) - in = 0; - } - } -} - -static void -print_rbd(struct ie_softc *sc, int n) -{ - printf("RBD at %08x:\n status %04x, next %04x, buffer %lx\n" - "length/EOL %04x\n", IE_RBD_ADDR(sc->rbds,n), - sc->ie_bus_read16(sc, IE_RBD_STATUS(sc->rbds,n)), - sc->ie_bus_read16(sc, IE_RBD_NEXT(sc->rbds,n)), - (u_long)0,/*bus_space_read_4(sc->bt, sc->bh, IE_RBD_BUFADDR(sc->rbds,n)),-* XXX */ - sc->ie_bus_read16(sc, IE_RBD_BUFLEN(sc->rbds,n))); -} - -#endif diff --git a/c/src/libchip/network/i82586reg.h b/c/src/libchip/network/i82586reg.h deleted file mode 100644 index e093aff68f..0000000000 --- a/c/src/libchip/network/i82586reg.h +++ /dev/null @@ -1,448 +0,0 @@ -/* $NetBSD: i82586reg.h,v 1.7 1998/02/28 01:07:45 pk Exp $ */ - -/*- - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Paul Kranenburg. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/*- - * Copyright (c) 1992, University of Vermont and State Agricultural College. - * Copyright (c) 1992, Garrett A. Wollman. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * Vermont and State Agricultural College and Garrett A. Wollman. - * 4. Neither the name of the University nor the name of the author - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR AUTHOR BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Intel 82586 Ethernet chip - * Register, bit, and structure definitions. - * - * Written by GAW with reference to the Clarkson Packet Driver code for this - * chip written by Russ Nelson and others. - */ - -/* - * NOTE, the structure definitions in here are for reference only. - * We use integer offsets exclusively to access the i82586 data structures. - */ - - -#if 0 -/* - * This is the master configuration block. - * It tells the hardware where all the rest of the stuff is. - */ -struct __ie_sys_conf_ptr { - u_int16_t mbz; /* must be zero */ - u_int8_t ie_bus_use; /* true if 8-bit only */ - u_int8_t mbz2[5]; /* must be zero */ - u_int32_t ie_iscp_ptr; /* 24-bit physaddr of ISCP */ -}; -#endif -#define IE_SCP_SZ 12 -#define IE_SCP_BUS_USE(base) ((base) + 2) -#define IE_SCP_ISCP(base) ((base) + 8) - -/* - * Note that this is wired in hardware; the SCP is always located here, no - * matter what. - */ -#define IE_SCP_ADDR 0xfffff4 - -#if 0 -/* - * The tells the hardware where all the rest of the stuff is, too. - * FIXME: some of these should be re-commented after we figure out their - * REAL function. - */ -struct __ie_int_sys_conf_ptr { - u_int8_t ie_busy; // zeroed after init - u_int8_t mbz; - u_int16_t ie_scb_offset; // 16-bit physaddr of next struct - caddr_t ie_base; // 24-bit physaddr for all 16-bit vars -}; -#endif -#define IE_ISCP_SZ 8 -#define IE_ISCP_BUSY(base) ((base) + 0) -#define IE_ISCP_SCB(base) ((base) + 2) -#define IE_ISCP_BASE(base) ((base) + 4) - -#if 0 -/* - * This FINALLY tells the hardware what to do and where to put it. - */ -struct __ie_sys_ctl_block { - u_int16_t ie_status; // status word - u_int16_t ie_command; // command word - u_int16_t ie_command_list; // 16-pointer to command block list - u_int16_t ie_recv_list; // 16-pointer to receive frame list - u_int16_t ie_err_crc; // CRC errors - u_int16_t ie_err_align; // Alignment errors - u_int16_t ie_err_resource; // Resource errors - u_int16_t ie_err_overrun; // Overrun errors -}; -#endif -#define IE_SCB_SZ 16 -#define IE_SCB_STATUS(base) ((base) + 0) -#define IE_SCB_CMD(base) ((base) + 2) -#define IE_SCB_CMDLST(base) ((base) + 4) -#define IE_SCB_RCVLST(base) ((base) + 6) -#define IE_SCB_ERRCRC(base) ((base) + 8) -#define IE_SCB_ERRALN(base) ((base) + 10) -#define IE_SCB_ERRRES(base) ((base) + 12) -#define IE_SCB_ERROVR(base) ((base) + 14) - -/* Command values */ -#define IE_RUC_MASK 0x0070 /* mask for RU command */ -#define IE_RUC_NOP 0 /* for completeness */ -#define IE_RUC_START 0x0010 /* start receive unit command */ -#define IE_RUC_RESUME 0x0020 /* resume a suspended receiver command */ -#define IE_RUC_SUSPEND 0x0030 /* suspend receiver command */ -#define IE_RUC_ABORT 0x0040 /* abort current receive operation */ - -#define IE_CUC_MASK 0x0700 /* mask for CU command */ -#define IE_CUC_NOP 0 /* included for completeness */ -#define IE_CUC_START 0x0100 /* do-command command */ -#define IE_CUC_RESUME 0x0200 /* resume a suspended cmd list */ -#define IE_CUC_SUSPEND 0x0300 /* suspend current command */ -#define IE_CUC_ABORT 0x0400 /* abort current command */ - -#define IE_ACK_COMMAND 0xf000 /* mask for ACK command */ -#define IE_ACK_CX 0x8000 /* ack IE_ST_CX */ -#define IE_ACK_FR 0x4000 /* ack IE_ST_FR */ -#define IE_ACK_CNA 0x2000 /* ack IE_ST_CNA */ -#define IE_ACK_RNR 0x1000 /* ack IE_ST_RNR */ - -#define IE_ACTION_COMMAND(x) (((x) & IE_CUC_MASK) == IE_CUC_START) - /* is this command an action command? */ - -/* Status values */ -#define IE_ST_WHENCE 0xf000 /* mask for cause of interrupt */ -#define IE_ST_CX 0x8000 /* command with I bit completed */ -#define IE_ST_FR 0x4000 /* frame received */ -#define IE_ST_CNA 0x2000 /* all commands completed */ -#define IE_ST_RNR 0x1000 /* receive not ready */ - -#define IE_CUS_MASK 0x0700 /* mask for command unit status */ -#define IE_CUS_ACTIVE 0x0200 /* command unit is active */ -#define IE_CUS_SUSPEND 0x0100 /* command unit is suspended */ - -#define IE_RUS_MASK 0x0070 /* mask for receiver unit status */ -#define IE_RUS_SUSPEND 0x0010 /* receiver is suspended */ -#define IE_RUS_NOSPACE 0x0020 /* receiver has no resources */ -#define IE_RUS_READY 0x0040 /* receiver is ready */ - -#if 0 -/* - * This is filled in partially by the chip, partially by us. - */ -struct __ie_recv_frame_desc { - u_int16_t ie_fd_status; // status for this frame - u_int16_t ie_fd_last; // end of frame list flag - u_int16_t ie_fd_next; // 16-pointer to next RFD - u_int16_t ie_fd_buf_desc; // 16-pointer to list of buffer descs - struct __ie_en_addr dest; // destination ether - struct __ie_en_addr src; // source ether - u_int16_t ie_length; // 802 length/Ether type - u_short mbz; // must be zero -}; -#endif -#define IE_RFRAME_SZ 24 -#define IE_RFRAME_ADDR(base,i) ((base) + (i) * IE_RFRAME_SZ) -#define IE_RFRAME_STATUS(b,i) (IE_RFRAME_ADDR(b,i) + 0) -#define IE_RFRAME_LAST(b,i) (IE_RFRAME_ADDR(b,i) + 2) -#define IE_RFRAME_NEXT(b,i) (IE_RFRAME_ADDR(b,i) + 4) -#define IE_RFRAME_BUFDESC(b,i) (IE_RFRAME_ADDR(b,i) + 6) -#define IE_RFRAME_EDST(b,i) (IE_RFRAME_ADDR(b,i) + 8) -#define IE_RFRAME_ESRC(b,i) (IE_RFRAME_ADDR(b,i) + 14) -#define IE_RFRAME_ELEN(b,i) (IE_RFRAME_ADDR(b,i) + 20) - -/* "last" bits */ -#define IE_FD_EOL 0x8000 /* last rfd in list */ -#define IE_FD_SUSP 0x4000 /* suspend RU after receipt */ - -/* status field bits */ -#define IE_FD_COMPLETE 0x8000 /* frame is complete */ -#define IE_FD_BUSY 0x4000 /* frame is busy */ -#define IE_FD_OK 0x2000 /* frame is ok */ -#define IE_FD_CRC 0x0800 /* CRC error */ -#define IE_FD_ALGN 0x0400 /* Alignment error */ -#define IE_FD_RNR 0x0200 /* receiver out of resources here */ -#define IE_FD_OVR 0x0100 /* DMA overrun */ -#define IE_FD_SHORT 0x0080 /* Short frame */ -#define IE_FD_NOEOF 0x0040 /* no EOF (?) */ -#define IE_FD_ERRMASK /* all error bits */ \ - (IE_FD_CRC|IE_FD_ALGN|IE_FD_RNR|IE_FD_OVR|IE_FD_SHORT|IE_FD_NOEOF) -#define IE_FD_STATUSBITS \ - "\20\20COMPLT\17BUSY\16OK\14CRC\13ALGN\12RNR\11OVR\10SHORT\7NOEOF" - -#if 0 -/* - * linked list of buffers... - */ -struct __ie_recv_buf_desc { - u_int16_t ie_rbd_status; // status for this buffer - u_int16_t ie_rbd_next; // 16-pointer to next RBD - caddr_t ie_rbd_buffer; // 24-pointer to buffer for this RBD - u_int16_t ie_rbd_length; // length of the buffer - u_int16_t mbz; // must be zero -}; -#endif -#define IE_RBD_SZ 12 -#define IE_RBD_ADDR(base,i) ((base) + (i) * IE_RBD_SZ) -#define IE_RBD_STATUS(b,i) (IE_RBD_ADDR(b,i) + 0) -#define IE_RBD_NEXT(b,i) (IE_RBD_ADDR(b,i) + 2) -#define IE_RBD_BUFADDR(b,i) (IE_RBD_ADDR(b,i) + 4) -#define IE_RBD_BUFLEN(b,i) (IE_RBD_ADDR(b,i) + 8) - -/* RBD status fields */ -#define IE_RBD_LAST 0x8000 /* last buffer */ -#define IE_RBD_USED 0x4000 /* this buffer has data */ -#define IE_RBD_CNTMASK 0x3fff /* byte count of buffer data */ - -/* RDB `End Of List' flag; encoded in `buffer length' field */ -#define IE_RBD_EOL 0x8000 /* last buffer */ - - -#if 0 -/* - * All commands share this in common. - */ -struct __ie_cmd_common { - u_int16_t ie_cmd_status; // status of this command - u_int16_t ie_cmd_cmd; // command word - u_int16_t ie_cmd_link; // link to next command -}; -#endif -#define IE_CMD_COMMON_SZ 6 -#define IE_CMD_COMMON_STATUS(base) ((base) + 0) -#define IE_CMD_COMMON_CMD(base) ((base) + 2) -#define IE_CMD_COMMON_LINK(base) ((base) + 4) - -#define IE_STAT_COMPL 0x8000 /* command is completed */ -#define IE_STAT_BUSY 0x4000 /* command is running now */ -#define IE_STAT_OK 0x2000 /* command completed successfully */ -#define IE_STAT_ABORT 0x1000 /* command was aborted */ - -#define IE_CMD_NOP 0x0000 /* NOP */ -#define IE_CMD_IASETUP 0x0001 /* initial address setup */ -#define IE_CMD_CONFIG 0x0002 /* configure command */ -#define IE_CMD_MCAST 0x0003 /* multicast setup command */ -#define IE_CMD_XMIT 0x0004 /* transmit command */ -#define IE_CMD_TDR 0x0005 /* time-domain reflectometer command */ -#define IE_CMD_DUMP 0x0006 /* dump command */ -#define IE_CMD_DIAGNOSE 0x0007 /* diagnostics command */ - -#define IE_CMD_LAST 0x8000 /* this is the last command in the list */ -#define IE_CMD_SUSPEND 0x4000 /* suspend CU after this command */ -#define IE_CMD_INTR 0x2000 /* post an interrupt after completion */ - -/* - * No-op commands; just like COMMON but "indexable" - */ -#define IE_CMD_NOP_SZ IE_CMD_COMMON_SZ -#define IE_CMD_NOP_ADDR(base,i) ((base) + (i) * IE_CMD_NOP_SZ) -#define IE_CMD_NOP_STATUS(b,i) (IE_CMD_NOP_ADDR(b,i) + 0) -#define IE_CMD_NOP_CMD(b,i) (IE_CMD_NOP_ADDR(b,i) + 2) -#define IE_CMD_NOP_LINK(b,i) (IE_CMD_NOP_ADDR(b,i) + 4) - - -#if 0 -/* - * This is the command to transmit a frame. - */ -struct __ie_xmit_cmd { - struct __ie_cmd_common com; // common part -#define __ie_xmit_status com.ie_cmd_status - - u_int16_t ie_xmit_desc; // pointer to buffer descriptor - struct __ie_en_addr ie_xmit_addr; // destination address - u_int16_t ie_xmit_length; // 802.3 length/Ether type field -}; -#endif -#define IE_CMD_XMIT_SZ (IE_CMD_COMMON_SZ + 10) -#define IE_CMD_XMIT_ADDR(base,i) ((base) + (i) * IE_CMD_XMIT_SZ) -#define IE_CMD_XMIT_STATUS(b,i) \ - (IE_CMD_XMIT_ADDR(b,i) + 0) /* == CMD_COMMON_STATUS */ -#define IE_CMD_XMIT_CMD(b,i) \ - (IE_CMD_XMIT_ADDR(b,i) + 2) /* == CMD_COMMON_CMD */ -#define IE_CMD_XMIT_LINK(b,i) \ - (IE_CMD_XMIT_ADDR(b,i) + 4) /* == CMD_COMMON_LINK */ -#define IE_CMD_XMIT_DESC(b,i) \ - (IE_CMD_XMIT_ADDR(b,i) + IE_CMD_COMMON_SZ + 0) -#define IE_CMD_XMIT_EADDR(b,i) \ - (IE_CMD_XMIT_ADDR(b,i) + IE_CMD_COMMON_SZ + 2) -#define IE_CMD_XMIT_LEN(b,i) \ - (IE_CMD_XMIT_ADDR(b,i) + IE_CMD_COMMON_SZ + 8) - -#define IE_XS_MAXCOLL 0x000f /* number of collisions during transmit */ -#define IE_XS_EXCMAX 0x0020 /* exceeded maximum number of collisions */ -#define IE_XS_SQE 0x0040 /* SQE positive */ -#define IE_XS_DEFERRED 0x0080 /* transmission deferred */ -#define IE_XS_UNDERRUN 0x0100 /* DMA underrun */ -#define IE_XS_LOSTCTS 0x0200 /* Lost CTS */ -#define IE_XS_NOCARRIER 0x0400 /* No Carrier */ -#define IE_XS_LATECOLL 0x0800 /* Late collision */ - -#if 0 -/* - * This is a buffer descriptor for a frame to be transmitted. - */ -struct __ie_xmit_buf { - u_int16_t ie_xmit_flags; // see below - u_int16_t ie_xmit_next; // 16-pointer to next desc - caddr_t ie_xmit_buf; // 24-pointer to the actual buffer -}; -#endif -#define IE_XBD_SZ 8 -#define IE_XBD_ADDR(base,i) ((base) + (i) * IE_XBD_SZ) -#define IE_XBD_FLAGS(b,i) (IE_XBD_ADDR(b,i) + 0) -#define IE_XBD_NEXT(b,i) (IE_XBD_ADDR(b,i) + 2) -#define IE_XBD_BUF(b,i) (IE_XBD_ADDR(b,i) + 4) - -#define IE_TBD_EOL 0x8000 /* this TBD is the last one */ -#define IE_TBD_CNTMASK 0x3fff /* The rest of the `flags' word - is actually the length. */ - - -#if 0 -/* - * Multicast setup command. - */ -struct __ie_mcast_cmd { - struct __ie_cmd_common com; // common part -#define ie_mcast_status com.ie_cmd_status - - // size (in bytes) of multicast addresses - u_short ie_mcast_bytes; - struct __ie_en_addr ie_mcast_addrs[IE_MAXMCAST + 1];// space for them -}; -#endif -#define IE_CMD_MCAST_SZ (IE_CMD_COMMON_SZ + 2 /* + XXX */) -#define IE_CMD_MCAST_BYTES(base) ((base) + IE_CMD_COMMON_SZ + 0) -#define IE_CMD_MCAST_MADDR(base) ((base) + IE_CMD_COMMON_SZ + 2) - -#if 0 -/* - * Time Domain Reflectometer command. - */ -struct __ie_tdr_cmd { - struct __ie_cmd_common com; // common part -#define ie_tdr_status com.ie_cmd_status - u_short ie_tdr_time; // error bits and time -}; -#endif -#define IE_CMD_TDR_SZ (IE_CMD_COMMON_SZ + 2) -#define IE_CMD_TDR_TIME(base) ((base) + IE_CMD_COMMON_SZ + 0) - -#define IE_TDR_SUCCESS 0x8000 /* TDR succeeded without error */ -#define IE_TDR_XCVR 0x4000 /* detected a transceiver problem */ -#define IE_TDR_OPEN 0x2000 /* detected an incorrect termination ("open") */ -#define IE_TDR_SHORT 0x1000 /* TDR detected a short circuit */ -#define IE_TDR_TIME 0x07ff /* mask for reflection time */ - -#if 0 -/* - * Initial Address Setup command - */ -struct __ie_iasetup_cmd { - struct __ie_cmd_common com; -#define ie_iasetup_status com.ie_cmd_status - struct __ie_en_addr ie_address; -}; -#endif -#define IE_CMD_IAS_SZ (IE_CMD_COMMON_SZ + 6) -#define IE_CMD_IAS_EADDR(base) ((base) + IE_CMD_COMMON_SZ + 0) - -#if 0 -/* - * Configuration command - */ -struct __ie_config_cmd { - struct __ie_cmd_common com; // common part -#define ie_config_status com.ie_cmd_status - - u_int8_t ie_config_count; // byte count (0x0c) - u_int8_t ie_fifo; // fifo (8) - u_int8_t ie_save_bad; // save bad frames (0x40) - u_int8_t ie_addr_len; // address length (0x2e) (AL-LOC == 1) - u_int8_t ie_priority; // priority and backoff (0x0) - u_int8_t ie_ifs; // inter-frame spacing (0x60) - u_int8_t ie_slot_low; // slot time, LSB (0x0) - u_int8_t ie_slot_high; // slot time, MSN, and retries (0xf2) - u_int8_t ie_promisc; // 1 if promiscuous, else 0 - u_int8_t ie_crs_cdt; // CSMA/CD parameters (0x0) - u_int8_t ie_min_len; // min frame length (0x40) - u_int8_t ie_junk; // stuff for 82596 (0xff) -}; -#endif -#define IE_CMD_CFG_SZ (IE_CMD_COMMON_SZ + 12) -#define IE_CMD_CFG_CNT(base) ((base) + IE_CMD_COMMON_SZ + 0) -#define IE_CMD_CFG_FIFO(base) ((base) + IE_CMD_COMMON_SZ + 1) -#define IE_CMD_CFG_SAVEBAD(base) ((base) + IE_CMD_COMMON_SZ + 2) -#define IE_CMD_CFG_ADDRLEN(base) ((base) + IE_CMD_COMMON_SZ + 3) -#define IE_CMD_CFG_PRIORITY(base) ((base) + IE_CMD_COMMON_SZ + 4) -#define IE_CMD_CFG_IFS(base) ((base) + IE_CMD_COMMON_SZ + 5) -#define IE_CMD_CFG_SLOT_LOW(base) ((base) + IE_CMD_COMMON_SZ + 6) -#define IE_CMD_CFG_SLOT_HIGH(base) ((base) + IE_CMD_COMMON_SZ + 7) -#define IE_CMD_CFG_PROMISC(base) ((base) + IE_CMD_COMMON_SZ + 8) -#define IE_CMD_CFG_CRSCDT(base) ((base) + IE_CMD_COMMON_SZ + 9) -#define IE_CMD_CFG_MINLEN(base) ((base) + IE_CMD_COMMON_SZ + 10) -#define IE_CMD_CFG_JUNK(base) ((base) + IE_CMD_COMMON_SZ + 11) diff --git a/c/src/libchip/network/if_dc.c b/c/src/libchip/network/if_dc.c deleted file mode 100644 index e822a7c533..0000000000 --- a/c/src/libchip/network/if_dc.c +++ /dev/null @@ -1,3849 +0,0 @@ -/* - * Ported from FreeBSD --> RTEMS, december 03. - * Daron Chabot - * -- only tested with i386 bsp. - * -- supports *one* card (until the PCI & IRQ APIs get sorted out ;-)) - * - * - * Copyright (c) 1997, 1998, 1999 - * Bill Paul . All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/pci/if_dc.c,v 1.9.2.41 2003/03/05 18:42:33 njl Exp $ - */ - -/* - * DEC "tulip" clone ethernet driver. Supports the DEC/Intel 21143 - * series chips and several workalikes including the following: - * - * Macronix 98713/98715/98725/98727/98732 PMAC (www.macronix.com) - * Macronix/Lite-On 82c115 PNIC II (www.macronix.com) - * Lite-On 82c168/82c169 PNIC (www.litecom.com) - * ASIX Electronics AX88140A (www.asix.com.tw) - * ASIX Electronics AX88141 (www.asix.com.tw) - * ADMtek AL981 (www.admtek.com.tw) - * ADMtek AN985 (www.admtek.com.tw) - * Davicom DM9100, DM9102, DM9102A (www.davicom8.com) - * Accton EN1217 (www.accton.com) - * Conexant LANfinity (www.conexant.com) - * - * Datasheets for the 21143 are available at developer.intel.com. - * Datasheets for the clone parts can be found at their respective sites. - * (Except for the PNIC; see www.freebsd.org/~wpaul/PNIC/pnic.ps.gz.) - * The PNIC II is essentially a Macronix 98715A chip; the only difference - * worth noting is that its multicast hash table is only 128 bits wide - * instead of 512. - * - * Written by Bill Paul - * Electrical Engineering Department - * Columbia University, New York City - */ - -/* - * The Intel 21143 is the successor to the DEC 21140. It is basically - * the same as the 21140 but with a few new features. The 21143 supports - * three kinds of media attachments: - * - * o MII port, for 10Mbps and 100Mbps support and NWAY - * autonegotiation provided by an external PHY. - * o SYM port, for symbol mode 100Mbps support. - * o 10baseT port. - * o AUI/BNC port. - * - * The 100Mbps SYM port and 10baseT port can be used together in - * combination with the internal NWAY support to create a 10/100 - * autosensing configuration. - * - * Note that not all tulip workalikes are handled in this driver: we only - * deal with those which are relatively well behaved. The Winbond is - * handled separately due to its different register offsets and the - * special handling needed for its various bugs. The PNIC is handled - * here, but I'm not thrilled about it. - * - * All of the workalike chips use some form of MII transceiver support - * with the exception of the Macronix chips, which also have a SYM port. - * The ASIX AX88140A is also documented to have a SYM port, but all - * the cards I've seen use an MII transceiver, probably because the - * AX88140A doesn't support internal NWAY. - */ - -/* - * This driver only supports architectures with the new style - * exception processing. The following checks try to keep this - * from being compiled on systems which can't support this driver. - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#if defined(DRIVER_SUPPORTED) - #undef DRIVER_SUPPORTED -#endif - -#if defined(__i386__) - #define DRIVER_SUPPORTED -#endif - -#if defined(__PPC__) - #define DRIVER_SUPPORTED -#endif - -#include - -#if !defined(PCI_DRAM_OFFSET) - #undef DRIVER_SUPPORTED -#endif - -#if defined(DRIVER_SUPPORTED) /* this covers the file "globally"... */ -#include - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* moved to cpukit/include/rtems in CVS current ! */ -/*#include "if_media.h" */ -/*#include "pci.h" */ -#include -#include -/* -#include -#include -*/ - -#include /* for vtophys */ - - -#define vtophys(p) (uintptr_t)(p) - -/* -#include -#include -#include -*/ - -#if 0 -#include /* for vtophys */ -#include /* for DELAY */ -#include -#include -#include -#include -#include -#include -#endif -#include -#if 0 -#include - -#include -#include -#endif - -/* NOTE: use mem space mapping (for now ...) -#define DC_USEIOSPACE -*/ - -#ifdef __alpha__ -#define SRM_MEDIA -#endif - -#include - - -#include - - -#define DRIVER_PREFIX "tl" -#define NDRIVER 1 -#define IRQ_EVENT RTEMS_EVENT_13 /* Ha ... */ -static struct dc_softc dc_softc_devs[NDRIVER]; - -#define UNUSED - -#if 0 -/* "controller miibus0" required. See GENERIC if you get errors here. */ -#include "miibus_if.h" - - - -#ifndef lint -static const char rcsid[] = - "$FreeBSD: src/sys/pci/if_dc.c,v 1.9.2.41 2003/03/05 18:42:33 njl Exp $"; -#endif - -#endif - - -/* - * Various supported device vendors/types and their names. - * NOTE: - * ----- - * Only the "ADMtek AN985" has been tested under RTEMS !!! - */ -static struct dc_type dc_devs[] = { - { DC_VENDORID_DEC, DC_DEVICEID_21143, - "Intel 21143 10/100BaseTX", 0 }, - { DC_VENDORID_DAVICOM, DC_DEVICEID_DM9009, - "Davicom DM9009 10/100BaseTX", 0 }, - { DC_VENDORID_DAVICOM, DC_DEVICEID_DM9100, - "Davicom DM9100 10/100BaseTX", 0 }, - { DC_VENDORID_DAVICOM, DC_DEVICEID_DM9102, - "Davicom DM9102 10/100BaseTX", 0 }, - { DC_VENDORID_DAVICOM, DC_DEVICEID_DM9102, - "Davicom DM9102A 10/100BaseTX", 0 }, - { DC_VENDORID_ADMTEK, DC_DEVICEID_AL981, - "ADMtek AL981 10/100BaseTX", 0 }, - { DC_VENDORID_ADMTEK, DC_DEVICEID_AN985, - "ADMtek AN985 10/100BaseTX", 0 }, - { DC_VENDORID_ASIX, DC_DEVICEID_AX88140A, - "ASIX AX88140A 10/100BaseTX", 0 }, - { DC_VENDORID_ASIX, DC_DEVICEID_AX88140A, - "ASIX AX88141 10/100BaseTX", 0 }, - { DC_VENDORID_MX, DC_DEVICEID_98713, - "Macronix 98713 10/100BaseTX", 0 }, - { DC_VENDORID_MX, DC_DEVICEID_98713, - "Macronix 98713A 10/100BaseTX", 0 }, - { DC_VENDORID_CP, DC_DEVICEID_98713_CP, - "Compex RL100-TX 10/100BaseTX", 0 }, - { DC_VENDORID_CP, DC_DEVICEID_98713_CP, - "Compex RL100-TX 10/100BaseTX", 0 }, - { DC_VENDORID_MX, DC_DEVICEID_987x5, - "Macronix 98715/98715A 10/100BaseTX", 0 }, - { DC_VENDORID_MX, DC_DEVICEID_987x5, - "Macronix 98715AEC-C 10/100BaseTX", 0 }, - { DC_VENDORID_MX, DC_DEVICEID_987x5, - "Macronix 98725 10/100BaseTX", 0 }, - { DC_VENDORID_MX, DC_DEVICEID_98727, - "Macronix 98727/98732 10/100BaseTX", 0 }, - { DC_VENDORID_LO, DC_DEVICEID_82C115, - "LC82C115 PNIC II 10/100BaseTX", 0 }, - { DC_VENDORID_LO, DC_DEVICEID_82C168, - "82c168 PNIC 10/100BaseTX", 0 }, - { DC_VENDORID_LO, DC_DEVICEID_82C168, - "82c169 PNIC 10/100BaseTX", 0 }, - { DC_VENDORID_ACCTON, DC_DEVICEID_EN1217, - "Accton EN1217 10/100BaseTX", 0 }, - { DC_VENDORID_ACCTON, DC_DEVICEID_EN2242, - "Accton EN2242 MiniPCI 10/100BaseTX", 0 }, - { DC_VENDORID_CONEXANT, DC_DEVICEID_RS7112, - "Conexant LANfinity MiniPCI 10/100BaseTX", 0 }, - { 0, 0, NULL, 0 } -}; - -#if 0 -static int dc_probe __P((device_t)); -static int dc_attach __P((device_t)); -static int dc_detach __P((device_t)); -static int dc_suspend __P((device_t)); -static int dc_resume __P((device_t)); -static void dc_shutdown __P((device_t)); -static void dc_acpi __P((device_t)); -#endif - -static struct dc_type *dc_devtype(int); -static int dc_newbuf(struct dc_softc *, int, struct mbuf *); -static int dc_encap(struct dc_softc *, struct mbuf *, - u_int32_t *); -static int dc_coal(struct dc_softc *, struct mbuf **); -static void dc_pnic_rx_bug_war(struct dc_softc *, int); -static int dc_rx_resync(struct dc_softc *); -static void dc_rxeof(struct dc_softc *); -static void dc_txeof(struct dc_softc *); -/*static void dc_tick((void *));*/ -static void dc_tx_underrun(struct dc_softc *); -static void dc_intr(void *); -static void dc_daemon(void *); -static void dc_start(struct ifnet *); -static int dc_ioctl(struct ifnet *, ioctl_command_t, caddr_t); -static void dc_init(void *); -static void dc_stop(struct dc_softc *); -static void dc_watchdog(struct ifnet *); -#if 0 -static int dc_ifmedia_upd __P((struct ifnet *)); -static void dc_ifmedia_sts __P((struct ifnet *, struct ifmediareq *)); -#endif - -static void dc_delay(struct dc_softc *); -static void dc_eeprom_idle(struct dc_softc *); -static void dc_eeprom_putbyte(struct dc_softc *, int); -static void dc_eeprom_getword(struct dc_softc *, int, u_int16_t *); -static void dc_eeprom_getword_pnic(struct dc_softc *, int, u_int16_t *); -static void dc_eeprom_width(struct dc_softc *); -static void dc_read_eeprom(struct dc_softc *, caddr_t, int,int, int); - -#if 0 -static void dc_mii_writebit __P((struct dc_softc *, int)); -static int dc_mii_readbit __P((struct dc_softc *)); -static void dc_mii_sync __P((struct dc_softc *)); -static void dc_mii_send __P((struct dc_softc *, u_int32_t, int)); -static int dc_mii_readreg __P((struct dc_softc *, struct dc_mii_frame *)); -static int dc_mii_writereg __P((struct dc_softc *, struct dc_mii_frame *)); -static int dc_miibus_readreg __P((device_t, int, int)); -static int dc_miibus_writereg __P((device_t, int, int, int)); -static void dc_miibus_statchg __P((device_t)); -static void dc_miibus_mediainit __P((device_t)); -#endif - -static void dc_setcfg(struct dc_softc *, int); -static u_int32_t dc_crc_le(struct dc_softc *, caddr_t); -#ifndef UNUSED -static u_int32_t dc_crc_be(caddr_t); -#endif -static void dc_setfilt_21143(struct dc_softc *); -static void dc_setfilt_asix(struct dc_softc *); -static void dc_setfilt_admtek(struct dc_softc *); -static void dc_setfilt(struct dc_softc *); -static void dc_reset(struct dc_softc *); -static int dc_list_rx_init(struct dc_softc *); -static int dc_list_tx_init(struct dc_softc *); -static void dc_read_srom(struct dc_softc *, int); -static void dc_parse_21143_srom(struct dc_softc *); -static void dc_apply_fixup(struct dc_softc *, int); - -#if 0 -static void dc_decode_leaf_sia __P((struct dc_softc *, - struct dc_eblock_sia *)); -static void dc_decode_leaf_mii __P((struct dc_softc *, - struct dc_eblock_mii *)); -static void dc_decode_leaf_sym __P((struct dc_softc *, - struct dc_eblock_sym *)); -#endif - - -#ifdef DC_USEIOSPACE -#define DC_RES SYS_RES_IOPORT -#define DC_RID DC_PCI_CFBIO -#else -#define DC_RES SYS_RES_MEMORY -#define DC_RID DC_PCI_CFBMA -#endif - -#if 0 -static device_method_t dc_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, dc_probe), - DEVMETHOD(device_attach, dc_attach), - DEVMETHOD(device_detach, dc_detach), - DEVMETHOD(device_suspend, dc_suspend), - DEVMETHOD(device_resume, dc_resume), - DEVMETHOD(device_shutdown, dc_shutdown), - - /* bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_driver_added, bus_generic_driver_added), - - /* MII interface */ - DEVMETHOD(miibus_readreg, dc_miibus_readreg), - DEVMETHOD(miibus_writereg, dc_miibus_writereg), - DEVMETHOD(miibus_statchg, dc_miibus_statchg), - DEVMETHOD(miibus_mediainit, dc_miibus_mediainit), - - { 0, 0 } -}; - -static driver_t dc_driver = { - "dc", - dc_methods, - sizeof(struct dc_softc) -}; - -static devclass_t dc_devclass; -#endif - - -#ifdef __i386__ -static int dc_quick=1; -#if 0 -SYSCTL_INT(_hw, OID_AUTO, dc_quick, CTLFLAG_RW, - &dc_quick,0,"do not mdevget in dc driver"); -#endif -#endif - -#if 0 -DRIVER_MODULE(if_dc, pci, dc_driver, dc_devclass, 0, 0); -DRIVER_MODULE(miibus, dc, miibus_driver, miibus_devclass, 0, 0); -#endif - - -#define DC_SETBIT(sc, reg, x) \ - CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) | (x)) - -#define DC_CLRBIT(sc, reg, x) \ - CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) & ~(x)) - -#define SIO_SET(x) DC_SETBIT(sc, DC_SIO, (x)) -#define SIO_CLR(x) DC_CLRBIT(sc, DC_SIO, (x)) - - -/* XXX Fixme: rtems_bsp_delay( ) for the pc386 BSP (at least) - * needs work... see pc386/include/bsp.h. - * I have "a" solution, utilizing the 2nd i8254 timer, - * if anyone is interested (first timer is used for clock_tick ISR)... - */ -#ifdef __i386__ -extern void Wait_X_ms( unsigned int ); -#define DELAY(n) Wait_X_ms( (unsigned int)((n)/100) ) -#else -#define DELAY(n) rtems_bsp_delay(n) -#endif - - -static void dc_delay(sc) - struct dc_softc *sc; -{ - int idx; - - for (idx = (300 / 33) + 1; idx > 0; idx--) - CSR_READ_4(sc, DC_BUSCTL); -} - -static void dc_eeprom_width(sc) - struct dc_softc *sc; -{ - int i; - - /* Force EEPROM to idle state. */ - dc_eeprom_idle(sc); - - /* Enter EEPROM access mode. */ - CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL); - dc_delay(sc); - DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ); - dc_delay(sc); - DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK); - dc_delay(sc); - DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS); - dc_delay(sc); - - for (i = 3; i--;) { - if (6 & (1 << i)) - DC_SETBIT(sc, DC_SIO, DC_SIO_EE_DATAIN); - else - DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_DATAIN); - dc_delay(sc); - DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK); - dc_delay(sc); - DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK); - dc_delay(sc); - } - - for (i = 1; i <= 12; i++) { - DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK); - dc_delay(sc); - if (!(CSR_READ_4(sc, DC_SIO) & DC_SIO_EE_DATAOUT)) { - DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK); - dc_delay(sc); - break; - } - DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK); - dc_delay(sc); - } - - /* Turn off EEPROM access mode. */ - dc_eeprom_idle(sc); - - if (i < 4 || i > 12) - sc->dc_romwidth = 6; - else - sc->dc_romwidth = i; - - /* Enter EEPROM access mode. */ - CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL); - dc_delay(sc); - DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ); - dc_delay(sc); - DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK); - dc_delay(sc); - DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS); - dc_delay(sc); - - /* Turn off EEPROM access mode. */ - dc_eeprom_idle(sc); -} - -static void dc_eeprom_idle(sc) - struct dc_softc *sc; -{ - register int i; - - CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL); - dc_delay(sc); - DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ); - dc_delay(sc); - DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK); - dc_delay(sc); - DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS); - dc_delay(sc); - - for (i = 0; i < 25; i++) { - DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK); - dc_delay(sc); - DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK); - dc_delay(sc); - } - - DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK); - dc_delay(sc); - DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CS); - dc_delay(sc); - CSR_WRITE_4(sc, DC_SIO, 0x00000000); - - return; -} - -/* - * Send a read command and address to the EEPROM, check for ACK. - */ -static void dc_eeprom_putbyte(sc, addr) - struct dc_softc *sc; - int addr; -{ - register int d, i; - - d = DC_EECMD_READ >> 6; - for (i = 3; i--; ) { - if (d & (1 << i)) - DC_SETBIT(sc, DC_SIO, DC_SIO_EE_DATAIN); - else - DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_DATAIN); - dc_delay(sc); - DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK); - dc_delay(sc); - DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK); - dc_delay(sc); - } - - /* - * Feed in each bit and strobe the clock. - */ - for (i = sc->dc_romwidth; i--;) { - if (addr & (1 << i)) { - SIO_SET(DC_SIO_EE_DATAIN); - } else { - SIO_CLR(DC_SIO_EE_DATAIN); - } - dc_delay(sc); - SIO_SET(DC_SIO_EE_CLK); - dc_delay(sc); - SIO_CLR(DC_SIO_EE_CLK); - dc_delay(sc); - } - - return; -} - -/* - * Read a word of data stored in the EEPROM at address 'addr.' - * The PNIC 82c168/82c169 has its own non-standard way to read - * the EEPROM. - */ -static void dc_eeprom_getword_pnic(sc, addr, dest) - struct dc_softc *sc; - int addr; - u_int16_t *dest; -{ - register int i; - u_int32_t r; - - CSR_WRITE_4(sc, DC_PN_SIOCTL, DC_PN_EEOPCODE_READ|addr); - - for (i = 0; i < DC_TIMEOUT; i++) { - DELAY(1); - r = CSR_READ_4(sc, DC_SIO); - if (!(r & DC_PN_SIOCTL_BUSY)) { - *dest = (u_int16_t)(r & 0xFFFF); - return; - } - } - - return; -} - -/* - * Read a word of data stored in the EEPROM at address 'addr.' - */ -static void dc_eeprom_getword(sc, addr, dest) - struct dc_softc *sc; - int addr; - u_int16_t *dest; -{ - register int i; - u_int16_t word = 0; - - /* Force EEPROM to idle state. */ - dc_eeprom_idle(sc); - - /* Enter EEPROM access mode. */ - CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL); - dc_delay(sc); - DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ); - dc_delay(sc); - DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK); - dc_delay(sc); - DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS); - dc_delay(sc); - - /* - * Send address of word we want to read. - */ - dc_eeprom_putbyte(sc, addr); - - /* - * Start reading bits from EEPROM. - */ - for (i = 0x8000; i; i >>= 1) { - SIO_SET(DC_SIO_EE_CLK); - dc_delay(sc); - if (CSR_READ_4(sc, DC_SIO) & DC_SIO_EE_DATAOUT) - word |= i; - dc_delay(sc); - SIO_CLR(DC_SIO_EE_CLK); - dc_delay(sc); - } - - /* Turn off EEPROM access mode. */ - dc_eeprom_idle(sc); - - *dest = word; - - return; -} - -/* - * Read a sequence of words from the EEPROM. - */ -static void dc_read_eeprom(sc, dest, off, cnt, swap) - struct dc_softc *sc; - caddr_t dest; - int off; - int cnt; - int swap; -{ - int i; - u_int16_t word = 0, *ptr; - - for (i = 0; i < cnt; i++) { - if (DC_IS_PNIC(sc)) - dc_eeprom_getword_pnic(sc, off + i, &word); - else - dc_eeprom_getword(sc, off + i, &word); - ptr = (u_int16_t *)(dest + (i * 2)); - if (swap) - *ptr = ntohs(word); - else - *ptr = word; - } - - return; -} - - -#if 0 -/* - * The following two routines are taken from the Macronix 98713 - * Application Notes pp.19-21. - */ -/* - * Write a bit to the MII bus. - */ -static void dc_mii_writebit(sc, bit) - struct dc_softc *sc; - int bit; -{ - if (bit) - CSR_WRITE_4(sc, DC_SIO, - DC_SIO_ROMCTL_WRITE|DC_SIO_MII_DATAOUT); - else - CSR_WRITE_4(sc, DC_SIO, DC_SIO_ROMCTL_WRITE); - - DC_SETBIT(sc, DC_SIO, DC_SIO_MII_CLK); - DC_CLRBIT(sc, DC_SIO, DC_SIO_MII_CLK); - - return; -} - -/* - * Read a bit from the MII bus. - */ -static int dc_mii_readbit(sc) - struct dc_softc *sc; -{ - CSR_WRITE_4(sc, DC_SIO, DC_SIO_ROMCTL_READ|DC_SIO_MII_DIR); - CSR_READ_4(sc, DC_SIO); - DC_SETBIT(sc, DC_SIO, DC_SIO_MII_CLK); - DC_CLRBIT(sc, DC_SIO, DC_SIO_MII_CLK); - if (CSR_READ_4(sc, DC_SIO) & DC_SIO_MII_DATAIN) - return(1); - - return(0); -} - -/* - * Sync the PHYs by setting data bit and strobing the clock 32 times. - */ -static void dc_mii_sync(sc) - struct dc_softc *sc; -{ - register int i; - - CSR_WRITE_4(sc, DC_SIO, DC_SIO_ROMCTL_WRITE); - - for (i = 0; i < 32; i++) - dc_mii_writebit(sc, 1); - - return; -} - -/* - * Clock a series of bits through the MII. - */ -static void dc_mii_send(sc, bits, cnt) - struct dc_softc *sc; - u_int32_t bits; - int cnt; -{ - int i; - - for (i = (0x1 << (cnt - 1)); i; i >>= 1) - dc_mii_writebit(sc, bits & i); -} - -/* - * Read an PHY register through the MII. - */ -static int dc_mii_readreg(sc, frame) - struct dc_softc *sc; - struct dc_mii_frame *frame; - -{ - int i, ack, s; - - - /* - * Set up frame for RX. - */ - frame->mii_stdelim = DC_MII_STARTDELIM; - frame->mii_opcode = DC_MII_READOP; - frame->mii_turnaround = 0; - frame->mii_data = 0; - - /* - * Sync the PHYs. - */ - dc_mii_sync(sc); - - /* - * Send command/address info. - */ - dc_mii_send(sc, frame->mii_stdelim, 2); - dc_mii_send(sc, frame->mii_opcode, 2); - dc_mii_send(sc, frame->mii_phyaddr, 5); - dc_mii_send(sc, frame->mii_regaddr, 5); - -#ifdef notdef - /* Idle bit */ - dc_mii_writebit(sc, 1); - dc_mii_writebit(sc, 0); -#endif - - /* Check for ack */ - ack = dc_mii_readbit(sc); - - /* - * Now try reading data bits. If the ack failed, we still - * need to clock through 16 cycles to keep the PHY(s) in sync. - */ - if (ack) { - for(i = 0; i < 16; i++) { - dc_mii_readbit(sc); - } - goto fail; - } - - for (i = 0x8000; i; i >>= 1) { - if (!ack) { - if (dc_mii_readbit(sc)) - frame->mii_data |= i; - } - } - -fail: - - dc_mii_writebit(sc, 0); - dc_mii_writebit(sc, 0); - - - if (ack) - return(1); - return(0); -} - -/* - * Write to a PHY register through the MII. - */ -static int dc_mii_writereg(sc, frame) - struct dc_softc *sc; - struct dc_mii_frame *frame; - -{ - int s; - - /* - * Set up frame for TX. - */ - - frame->mii_stdelim = DC_MII_STARTDELIM; - frame->mii_opcode = DC_MII_WRITEOP; - frame->mii_turnaround = DC_MII_TURNAROUND; - - /* - * Sync the PHYs. - */ - dc_mii_sync(sc); - - dc_mii_send(sc, frame->mii_stdelim, 2); - dc_mii_send(sc, frame->mii_opcode, 2); - dc_mii_send(sc, frame->mii_phyaddr, 5); - dc_mii_send(sc, frame->mii_regaddr, 5); - dc_mii_send(sc, frame->mii_turnaround, 2); - dc_mii_send(sc, frame->mii_data, 16); - - /* Idle bit. */ - dc_mii_writebit(sc, 0); - dc_mii_writebit(sc, 0); - - - return(0); -} - -static int dc_miibus_readreg(dev, phy, reg) - device_t dev; - int phy, reg; -{ - struct dc_mii_frame frame; - struct dc_softc *sc; - int i, rval, phy_reg = 0; - - sc = device_get_softc(dev); - bzero((char *)&frame, sizeof(frame)); - - /* - * Note: both the AL981 and AN985 have internal PHYs, - * however the AL981 provides direct access to the PHY - * registers while the AN985 uses a serial MII interface. - * The AN985's MII interface is also buggy in that you - * can read from any MII address (0 to 31), but only address 1 - * behaves normally. To deal with both cases, we pretend - * that the PHY is at MII address 1. - */ - if (DC_IS_ADMTEK(sc) && phy != DC_ADMTEK_PHYADDR) - return(0); - - /* - * Note: the ukphy probes of the RS7112 report a PHY at - * MII address 0 (possibly HomePNA?) and 1 (ethernet) - * so we only respond to correct one. - */ - if (DC_IS_CONEXANT(sc) && phy != DC_CONEXANT_PHYADDR) - return(0); - - if (sc->dc_pmode != DC_PMODE_MII) { - if (phy == (MII_NPHY - 1)) { - switch(reg) { - case MII_BMSR: - /* - * Fake something to make the probe - * code think there's a PHY here. - */ - return(BMSR_MEDIAMASK); - break; - case MII_PHYIDR1: - if (DC_IS_PNIC(sc)) - return(DC_VENDORID_LO); - return(DC_VENDORID_DEC); - break; - case MII_PHYIDR2: - if (DC_IS_PNIC(sc)) - return(DC_DEVICEID_82C168); - return(DC_DEVICEID_21143); - break; - default: - return(0); - break; - } - } else - return(0); - } - - if (DC_IS_PNIC(sc)) { - CSR_WRITE_4(sc, DC_PN_MII, DC_PN_MIIOPCODE_READ | - (phy << 23) | (reg << 18)); - for (i = 0; i < DC_TIMEOUT; i++) { - DELAY(1); - rval = CSR_READ_4(sc, DC_PN_MII); - if (!(rval & DC_PN_MII_BUSY)) { - rval &= 0xFFFF; - return(rval == 0xFFFF ? 0 : rval); - } - } - return(0); - } - - if (DC_IS_COMET(sc)) { - switch(reg) { - case MII_BMCR: - phy_reg = DC_AL_BMCR; - break; - case MII_BMSR: - phy_reg = DC_AL_BMSR; - break; - case MII_PHYIDR1: - phy_reg = DC_AL_VENID; - break; - case MII_PHYIDR2: - phy_reg = DC_AL_DEVID; - break; - case MII_ANAR: - phy_reg = DC_AL_ANAR; - break; - case MII_ANLPAR: - phy_reg = DC_AL_LPAR; - break; - case MII_ANER: - phy_reg = DC_AL_ANER; - break; - default: - printk("dc%d: phy_read: bad phy register %x\n", - sc->dc_unit, reg); - return(0); - break; - } - - rval = CSR_READ_4(sc, phy_reg) & 0x0000FFFF; - - if (rval == 0xFFFF) - return(0); - return(rval); - } - - frame.mii_phyaddr = phy; - frame.mii_regaddr = reg; - if (sc->dc_type == DC_TYPE_98713) { - phy_reg = CSR_READ_4(sc, DC_NETCFG); - CSR_WRITE_4(sc, DC_NETCFG, phy_reg & ~DC_NETCFG_PORTSEL); - } - dc_mii_readreg(sc, &frame); - if (sc->dc_type == DC_TYPE_98713) - CSR_WRITE_4(sc, DC_NETCFG, phy_reg); - - return(frame.mii_data); -} - -static int dc_miibus_writereg(dev, phy, reg, data) - device_t dev; - int phy, reg, data; -{ - struct dc_softc *sc; - struct dc_mii_frame frame; - int i, phy_reg = 0; - - sc = device_get_softc(dev); - bzero((char *)&frame, sizeof(frame)); - - if (DC_IS_ADMTEK(sc) && phy != DC_ADMTEK_PHYADDR) - return(0); - - if (DC_IS_CONEXANT(sc) && phy != DC_CONEXANT_PHYADDR) - return(0); - - if (DC_IS_PNIC(sc)) { - CSR_WRITE_4(sc, DC_PN_MII, DC_PN_MIIOPCODE_WRITE | - (phy << 23) | (reg << 10) | data); - for (i = 0; i < DC_TIMEOUT; i++) { - if (!(CSR_READ_4(sc, DC_PN_MII) & DC_PN_MII_BUSY)) - break; - } - return(0); - } - - if (DC_IS_COMET(sc)) { - switch(reg) { - case MII_BMCR: - phy_reg = DC_AL_BMCR; - break; - case MII_BMSR: - phy_reg = DC_AL_BMSR; - break; - case MII_PHYIDR1: - phy_reg = DC_AL_VENID; - break; - case MII_PHYIDR2: - phy_reg = DC_AL_DEVID; - break; - case MII_ANAR: - phy_reg = DC_AL_ANAR; - break; - case MII_ANLPAR: - phy_reg = DC_AL_LPAR; - break; - case MII_ANER: - phy_reg = DC_AL_ANER; - break; - default: - printk("dc%d: phy_write: bad phy register %x\n", - sc->dc_unit, reg); - return(0); - break; - } - - CSR_WRITE_4(sc, phy_reg, data); - return(0); - } - - frame.mii_phyaddr = phy; - frame.mii_regaddr = reg; - frame.mii_data = data; - - if (sc->dc_type == DC_TYPE_98713) { - phy_reg = CSR_READ_4(sc, DC_NETCFG); - CSR_WRITE_4(sc, DC_NETCFG, phy_reg & ~DC_NETCFG_PORTSEL); - } - dc_mii_writereg(sc, &frame); - if (sc->dc_type == DC_TYPE_98713) - CSR_WRITE_4(sc, DC_NETCFG, phy_reg); - - return(0); -} - -static void dc_miibus_statchg(dev) - device_t dev; -{ - struct dc_softc *sc; - struct mii_data *mii; - struct ifmedia *ifm; - - sc = device_get_softc(dev); - if (DC_IS_ADMTEK(sc)) - return; - - mii = device_get_softc(sc->dc_miibus); - ifm = &mii->mii_media; - if (DC_IS_DAVICOM(sc) && - IFM_SUBTYPE(ifm->ifm_media) == IFM_homePNA) { - dc_setcfg(sc, ifm->ifm_media); - sc->dc_if_media = ifm->ifm_media; - } else { - dc_setcfg(sc, mii->mii_media_active); - sc->dc_if_media = mii->mii_media_active; - } - - return; -} - -/* - * Special support for DM9102A cards with HomePNA PHYs. Note: - * with the Davicom DM9102A/DM9801 eval board that I have, it seems - * to be impossible to talk to the management interface of the DM9801 - * PHY (its MDIO pin is not connected to anything). Consequently, - * the driver has to just 'know' about the additional mode and deal - * with it itself. *sigh* - */ -static void dc_miibus_mediainit(dev) - device_t dev; -{ - struct dc_softc *sc; - struct mii_data *mii; - struct ifmedia *ifm; - int rev; - - rev = pci_read_config(dev, DC_PCI_CFRV, 4) & 0xFF; - - sc = device_get_softc(dev); - mii = device_get_softc(sc->dc_miibus); - ifm = &mii->mii_media; - - if (DC_IS_DAVICOM(sc) && rev >= DC_REVISION_DM9102A) - ifmedia_add(ifm, IFM_ETHER|IFM_homePNA, 0, NULL); - - return; -} -#endif - -#define DC_POLY 0xEDB88320 -#define DC_BITS_512 9 -#define DC_BITS_128 7 -#define DC_BITS_64 6 - -static u_int32_t dc_crc_le(sc, addr) - struct dc_softc *sc; - caddr_t addr; -{ - u_int32_t idx, bit, data, crc; - - /* Compute CRC for the address value. */ - crc = 0xFFFFFFFF; /* initial value */ - - for (idx = 0; idx < 6; idx++) { - for (data = *addr++, bit = 0; bit < 8; bit++, data >>= 1) - crc = (crc >> 1) ^ (((crc ^ data) & 1) ? DC_POLY : 0); - } - - /* - * The hash table on the PNIC II and the MX98715AEC-C/D/E - * chips is only 128 bits wide. - */ - if (sc->dc_flags & DC_128BIT_HASH) - return (crc & ((1 << DC_BITS_128) - 1)); - - /* The hash table on the MX98715BEC is only 64 bits wide. */ - if (sc->dc_flags & DC_64BIT_HASH) - return (crc & ((1 << DC_BITS_64) - 1)); - - return (crc & ((1 << DC_BITS_512) - 1)); -} - -#ifndef UNUSED -/* - * Calculate CRC of a multicast group address, return the lower 6 bits. - */ -static u_int32_t dc_crc_be(addr) - caddr_t addr; -{ - u_int32_t crc, carry; - int i, j; - u_int8_t c; - - /* Compute CRC for the address value. */ - crc = 0xFFFFFFFF; /* initial value */ - - for (i = 0; i < 6; i++) { - c = *(addr + i); - for (j = 0; j < 8; j++) { - carry = ((crc & 0x80000000) ? 1 : 0) ^ (c & 0x01); - crc <<= 1; - c >>= 1; - if (carry) - crc = (crc ^ 0x04c11db6) | carry; - } - } - - /* return the filter bit position */ - return((crc >> 26) & 0x0000003F); -} -#endif - -/* - * 21143-style RX filter setup routine. Filter programming is done by - * downloading a special setup frame into the TX engine. 21143, Macronix, - * PNIC, PNIC II and Davicom chips are programmed this way. - * - * We always program the chip using 'hash perfect' mode, i.e. one perfect - * address (our node address) and a 512-bit hash filter for multicast - * frames. We also sneak the broadcast address into the hash filter since - * we need that too. - */ -void dc_setfilt_21143(sc) - struct dc_softc *sc; -{ - struct dc_desc *sframe; - u_int32_t h, *sp; - /*struct ifmultiaddr *ifma;*/ - struct ifnet *ifp; - int i; - u_int16_t *ac_enaddr; - - ifp = &sc->arpcom.ac_if; - - i = sc->dc_cdata.dc_tx_prod; - DC_INC(sc->dc_cdata.dc_tx_prod, DC_TX_LIST_CNT); - sc->dc_cdata.dc_tx_cnt++; - sframe = &sc->dc_ldata->dc_tx_list[i]; - sp = (u_int32_t *)&sc->dc_cdata.dc_sbuf; - bzero((char *)sp, DC_SFRAME_LEN); - - sframe->dc_data = vtophys(&sc->dc_cdata.dc_sbuf); - sframe->dc_ctl = DC_SFRAME_LEN | DC_TXCTL_SETUP | DC_TXCTL_TLINK | - DC_FILTER_HASHPERF | DC_TXCTL_FINT; - - sc->dc_cdata.dc_tx_chain[i] = (struct mbuf *)&sc->dc_cdata.dc_sbuf; - - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); - else - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); - - if (ifp->if_flags & IFF_ALLMULTI) - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); - else - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); -#if 0 - for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL; - ifma = ifma->ifma_link.le_next) { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - h = dc_crc_le(sc, - LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); - sp[h >> 4] |= 1 << (h & 0xF); - } -#endif - - if (ifp->if_flags & IFF_BROADCAST) { - h = dc_crc_le(sc, (caddr_t)ðerbroadcastaddr); - sp[h >> 4] |= 1 << (h & 0xF); - } - - /* Set our MAC address */ - ac_enaddr = (u_int16_t *)sc->arpcom.ac_enaddr; - sp[39] = ac_enaddr[0]; - sp[40] = ac_enaddr[1]; - sp[41] = ac_enaddr[2]; - - sframe->dc_status = DC_TXSTAT_OWN; - CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF); - - /* - * The PNIC takes an exceedingly long time to process its - * setup frame; wait 10ms after posting the setup frame - * before proceeding, just so it has time to swallow its - * medicine. - */ - DELAY(10000); - - ifp->if_timer = 5; - - return; -} - -void dc_setfilt_admtek(sc) - struct dc_softc *sc; -{ - struct ifnet *ifp; -#if 0 - int h = 0; - u_int32_t hashes[2] = { 0, 0 }; - struct ifmultiaddr *ifma; -#endif - u_int32_t *ac_enaddr; - - ifp = &sc->arpcom.ac_if; - - /* Init our MAC address */ - ac_enaddr = (u_int32_t *)&sc->arpcom.ac_enaddr[0]; - CSR_WRITE_4(sc, DC_AL_PAR0, *ac_enaddr); - ac_enaddr = (u_int32_t *)&sc->arpcom.ac_enaddr[4]; - CSR_WRITE_4(sc, DC_AL_PAR1, *ac_enaddr); - - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); - else - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); - - if (ifp->if_flags & IFF_ALLMULTI) - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); - else - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); - - /* first, zot all the existing hash bits */ - CSR_WRITE_4(sc, DC_AL_MAR0, 0); - CSR_WRITE_4(sc, DC_AL_MAR1, 0); - -#if 0 - /* - * If we're already in promisc or allmulti mode, we - * don't have to bother programming the multicast filter. - */ - if (ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI)) - return; - - /* now program new ones */ - for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL; - ifma = ifma->ifma_link.le_next) { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - h = dc_crc_be(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); - if (h < 32) - hashes[0] |= (1 << h); - else - hashes[1] |= (1 << (h - 32)); - } - - CSR_WRITE_4(sc, DC_AL_MAR0, hashes[0]); - CSR_WRITE_4(sc, DC_AL_MAR1, hashes[1]); -#endif - return; -} - -void dc_setfilt_asix(sc) - struct dc_softc *sc; -{ - struct ifnet *ifp; -#if 0 - int h = 0; - u_int32_t hashes[2] = { 0, 0 }; - struct ifmultiaddr *ifma; -#endif - u_int32_t *ac_enaddr; - - ifp = &sc->arpcom.ac_if; - - /* Init our MAC address */ - CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_PAR0); - ac_enaddr = (u_int32_t *)&sc->arpcom.ac_enaddr[0]; - CSR_WRITE_4(sc, DC_AX_FILTDATA, *ac_enaddr); - - CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_PAR1); - - ac_enaddr = (u_int32_t *)&sc->arpcom.ac_enaddr[4]; - CSR_WRITE_4(sc, DC_AX_FILTDATA, *ac_enaddr); - - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); - else - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); - - if (ifp->if_flags & IFF_ALLMULTI) - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); - else - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); - - /* - * The ASIX chip has a special bit to enable reception - * of broadcast frames. - */ - if (ifp->if_flags & IFF_BROADCAST) - DC_SETBIT(sc, DC_NETCFG, DC_AX_NETCFG_RX_BROAD); - else - DC_CLRBIT(sc, DC_NETCFG, DC_AX_NETCFG_RX_BROAD); - - /* first, zot all the existing hash bits */ - CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR0); - CSR_WRITE_4(sc, DC_AX_FILTDATA, 0); - CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR1); - CSR_WRITE_4(sc, DC_AX_FILTDATA, 0); - -#if 0 - /* - * If we're already in promisc or allmulti mode, we - * don't have to bother programming the multicast filter. - */ - if (ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI)) - return; - - /* now program new ones */ - for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL; - ifma = ifma->ifma_link.le_next) { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - h = dc_crc_be(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); - if (h < 32) - hashes[0] |= (1 << h); - else - hashes[1] |= (1 << (h - 32)); - } - - CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR0); - CSR_WRITE_4(sc, DC_AX_FILTDATA, hashes[0]); - CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR1); - CSR_WRITE_4(sc, DC_AX_FILTDATA, hashes[1]); -#endif - return; -} - -static void dc_setfilt(sc) - struct dc_softc *sc; -{ - if (DC_IS_INTEL(sc) || DC_IS_MACRONIX(sc) || DC_IS_PNIC(sc) || - DC_IS_PNICII(sc) || DC_IS_DAVICOM(sc) || DC_IS_CONEXANT(sc)) - dc_setfilt_21143(sc); - - if (DC_IS_ASIX(sc)) - dc_setfilt_asix(sc); - - if (DC_IS_ADMTEK(sc)) - dc_setfilt_admtek(sc); - - return; -} - -/* - * In order to fiddle with the - * 'full-duplex' and '100Mbps' bits in the netconfig register, we - * first have to put the transmit and/or receive logic in the idle state. - */ -static void dc_setcfg(sc, media) - struct dc_softc *sc; - int media; -{ - int i, restart = 0; - u_int32_t isr; - - if (IFM_SUBTYPE(media) == IFM_NONE) - return; - - if (CSR_READ_4(sc, DC_NETCFG) & (DC_NETCFG_TX_ON|DC_NETCFG_RX_ON)) { - restart = 1; - DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_TX_ON|DC_NETCFG_RX_ON)); - - for (i = 0; i < DC_TIMEOUT; i++) { - isr = CSR_READ_4(sc, DC_ISR); - if (isr & DC_ISR_TX_IDLE || - (isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED) - break; - DELAY(10); - } - - if (i == DC_TIMEOUT) - printk("dc%d: failed to force tx and " - "rx to idle state\n", sc->dc_unit); - } - - if (IFM_SUBTYPE(media) == IFM_100_TX) { - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_SPEEDSEL); - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_HEARTBEAT); - if (sc->dc_pmode == DC_PMODE_MII) { - int watchdogreg; - - if (DC_IS_INTEL(sc)) { - /* there's a write enable bit here that reads as 1 */ - watchdogreg = CSR_READ_4(sc, DC_WATCHDOG); - watchdogreg &= ~DC_WDOG_CTLWREN; - watchdogreg |= DC_WDOG_JABBERDIS; - CSR_WRITE_4(sc, DC_WATCHDOG, watchdogreg); - } else { - DC_SETBIT(sc, DC_WATCHDOG, DC_WDOG_JABBERDIS); - } - DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_PCS| - DC_NETCFG_PORTSEL|DC_NETCFG_SCRAMBLER)); - if (sc->dc_type == DC_TYPE_98713) - DC_SETBIT(sc, DC_NETCFG, (DC_NETCFG_PCS| - DC_NETCFG_SCRAMBLER)); - if (!DC_IS_DAVICOM(sc)) - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL); - DC_CLRBIT(sc, DC_10BTCTRL, 0xFFFF); - if (DC_IS_INTEL(sc)) - dc_apply_fixup(sc, IFM_AUTO); - } else { - if (DC_IS_PNIC(sc)) { - DC_PN_GPIO_SETBIT(sc, DC_PN_GPIO_SPEEDSEL); - DC_PN_GPIO_SETBIT(sc, DC_PN_GPIO_100TX_LOOP); - DC_SETBIT(sc, DC_PN_NWAY, DC_PN_NWAY_SPEEDSEL); - } - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL); - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PCS); - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_SCRAMBLER); - if (DC_IS_INTEL(sc)) - dc_apply_fixup(sc, - (media & IFM_GMASK) == IFM_FDX ? - IFM_100_TX|IFM_FDX : IFM_100_TX); - } - } - - if (IFM_SUBTYPE(media) == IFM_10_T) { - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_SPEEDSEL); - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_HEARTBEAT); - if (sc->dc_pmode == DC_PMODE_MII) { - int watchdogreg; - - /* there's a write enable bit here that reads as 1 */ - if (DC_IS_INTEL(sc)) { - watchdogreg = CSR_READ_4(sc, DC_WATCHDOG); - watchdogreg &= ~DC_WDOG_CTLWREN; - watchdogreg |= DC_WDOG_JABBERDIS; - CSR_WRITE_4(sc, DC_WATCHDOG, watchdogreg); - } else { - DC_SETBIT(sc, DC_WATCHDOG, DC_WDOG_JABBERDIS); - } - DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_PCS| - DC_NETCFG_PORTSEL|DC_NETCFG_SCRAMBLER)); - if (sc->dc_type == DC_TYPE_98713) - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PCS); - if (!DC_IS_DAVICOM(sc)) - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL); - DC_CLRBIT(sc, DC_10BTCTRL, 0xFFFF); - if (DC_IS_INTEL(sc)) - dc_apply_fixup(sc, IFM_AUTO); - } else { - if (DC_IS_PNIC(sc)) { - DC_PN_GPIO_CLRBIT(sc, DC_PN_GPIO_SPEEDSEL); - DC_PN_GPIO_SETBIT(sc, DC_PN_GPIO_100TX_LOOP); - DC_CLRBIT(sc, DC_PN_NWAY, DC_PN_NWAY_SPEEDSEL); - } - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL); - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PCS); - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_SCRAMBLER); - if (DC_IS_INTEL(sc)) { - DC_CLRBIT(sc, DC_SIARESET, DC_SIA_RESET); - DC_CLRBIT(sc, DC_10BTCTRL, 0xFFFF); - if ((media & IFM_GMASK) == IFM_FDX) - DC_SETBIT(sc, DC_10BTCTRL, 0x7F3D); - else - DC_SETBIT(sc, DC_10BTCTRL, 0x7F3F); - DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET); - DC_CLRBIT(sc, DC_10BTCTRL, - DC_TCTL_AUTONEGENBL); - dc_apply_fixup(sc, - (media & IFM_GMASK) == IFM_FDX ? - IFM_10_T|IFM_FDX : IFM_10_T); - DELAY(20000); - } - } - } - -#if 0 - /* - * If this is a Davicom DM9102A card with a DM9801 HomePNA - * PHY and we want HomePNA mode, set the portsel bit to turn - * on the external MII port. - */ - if (DC_IS_DAVICOM(sc)) { - if (IFM_SUBTYPE(media) == IFM_homePNA) { - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL); - sc->dc_link = 1; - } else { - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL); - } - } -#endif - - if ((media & IFM_GMASK) == IFM_FDX) { - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_FULLDUPLEX); - if (sc->dc_pmode == DC_PMODE_SYM && DC_IS_PNIC(sc)) - DC_SETBIT(sc, DC_PN_NWAY, DC_PN_NWAY_DUPLEX); - } else { - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_FULLDUPLEX); - if (sc->dc_pmode == DC_PMODE_SYM && DC_IS_PNIC(sc)) - DC_CLRBIT(sc, DC_PN_NWAY, DC_PN_NWAY_DUPLEX); - } - - if (restart) - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON|DC_NETCFG_RX_ON); - - return; -} - -static void dc_reset(sc) - struct dc_softc *sc; -{ - register int i; - - DC_SETBIT(sc, DC_BUSCTL, DC_BUSCTL_RESET); - - for (i = 0; i < DC_TIMEOUT; i++) { - DELAY(10); - if (!(CSR_READ_4(sc, DC_BUSCTL) & DC_BUSCTL_RESET)) - break; - } - - if (DC_IS_ASIX(sc) || DC_IS_ADMTEK(sc) || DC_IS_CONEXANT(sc)) { - DELAY(10000); - DC_CLRBIT(sc, DC_BUSCTL, DC_BUSCTL_RESET); - i = 0; - } - - if (i == DC_TIMEOUT) - printk("dc%d: reset never completed!\n", sc->dc_unit); - - /* Wait a little while for the chip to get its brains in order. */ - DELAY(1000); - - CSR_WRITE_4(sc, DC_IMR, 0x00000000); - CSR_WRITE_4(sc, DC_BUSCTL, 0x00000000); - CSR_WRITE_4(sc, DC_NETCFG, 0x00000000); - - /* - * Bring the SIA out of reset. In some cases, it looks - * like failing to unreset the SIA soon enough gets it - * into a state where it will never come out of reset - * until we reset the whole chip again. - */ - if (DC_IS_INTEL(sc)) { - DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET); - CSR_WRITE_4(sc, DC_10BTCTRL, 0); - CSR_WRITE_4(sc, DC_WATCHDOG, 0); - } - - return; -} - -static -struct dc_type *dc_devtype( int unitnum ) -{ - struct dc_type *t; - uint32_t rev; - int rc; - - - t = dc_devs; - - while(t->dc_name != NULL) { - rc = pci_find_device(t->dc_vid, t->dc_did, \ - (unitnum - 1), &t->dc_bus, &t->dc_dev, &t->dc_fun); - if (rc == PCIB_ERR_SUCCESS) { - /* Check the PCI revision */ - /*pcib_conf_read32(t->dc_devsig, DC_PCI_CFRV, &rev); */ - pci_read_config_dword(t->dc_bus,t->dc_dev,t->dc_fun,\ - DC_PCI_CFRV, &rev); - rev &= 0xFF; - - if (t->dc_did == DC_DEVICEID_98713 && - rev >= DC_REVISION_98713A) - t++; - if (t->dc_did == DC_DEVICEID_98713_CP && - rev >= DC_REVISION_98713A) - t++; - if (t->dc_did == DC_DEVICEID_987x5 && - rev >= DC_REVISION_98715AEC_C) - t++; - if (t->dc_did == DC_DEVICEID_987x5 && - rev >= DC_REVISION_98725) - t++; - if (t->dc_did == DC_DEVICEID_AX88140A && - rev >= DC_REVISION_88141) - t++; - if (t->dc_did == DC_DEVICEID_82C168 && - rev >= DC_REVISION_82C169) - t++; - if (t->dc_did == DC_DEVICEID_DM9102 && - rev >= DC_REVISION_DM9102A) - t++; - return(t); - } - t++; - } - - return(NULL); -} - -#if 0 -/* - * Probe for a 21143 or clone chip. Check the PCI vendor and device - * IDs against our list and return a device name if we find a match. - * We do a little bit of extra work to identify the exact type of - * chip. The MX98713 and MX98713A have the same PCI vendor/device ID, - * but different revision IDs. The same is true for 98715/98715A - * chips and the 98725, as well as the ASIX and ADMtek chips. In some - * cases, the exact chip revision affects driver behavior. - */ -static int dc_probe(dev) - device_t dev; -{ - struct dc_type *t; - - t = dc_devtype(dev); - - if (t != NULL) { - device_set_desc(dev, t->dc_name); - return(0); - } - - return(ENXIO); -} - - -static void dc_acpi(dev) - device_t dev; -{ - u_int32_t r, cptr; - int unit; - - unit = device_get_unit(dev); - - /* Find the location of the capabilities block */ - cptr = pci_read_config(dev, DC_PCI_CCAP, 4) & 0xFF; - - r = pci_read_config(dev, cptr, 4) & 0xFF; - if (r == 0x01) { - - r = pci_read_config(dev, cptr + 4, 4); - if (r & DC_PSTATE_D3) { - u_int32_t iobase, membase, irq; - - /* Save important PCI config data. */ - iobase = pci_read_config(dev, DC_PCI_CFBIO, 4); - membase = pci_read_config(dev, DC_PCI_CFBMA, 4); - irq = pci_read_config(dev, DC_PCI_CFIT, 4); - - /* Reset the power state. */ - printk("dc%d: chip is in D%d power mode " - "-- setting to D0\n", unit, r & DC_PSTATE_D3); - r &= 0xFFFFFFFC; - pci_write_config(dev, cptr + 4, r, 4); - - /* Restore PCI config data. */ - pci_write_config(dev, DC_PCI_CFBIO, iobase, 4); - pci_write_config(dev, DC_PCI_CFBMA, membase, 4); - pci_write_config(dev, DC_PCI_CFIT, irq, 4); - } - } - return; -} -#endif - - -static void dc_apply_fixup(sc, media) - struct dc_softc *sc; - int media; -{ - struct dc_mediainfo *m; - u_int8_t *p; - int i; - u_int32_t reg; - - m = sc->dc_mi; - - while (m != NULL) { - if (m->dc_media == media) - break; - m = m->dc_next; - } - - if (m == NULL) - return; - - for (i = 0, p = m->dc_reset_ptr; i < m->dc_reset_len; i++, p += 2) { - reg = (p[0] | (p[1] << 8)) << 16; - CSR_WRITE_4(sc, DC_WATCHDOG, reg); - } - - for (i = 0, p = m->dc_gp_ptr; i < m->dc_gp_len; i++, p += 2) { - reg = (p[0] | (p[1] << 8)) << 16; - CSR_WRITE_4(sc, DC_WATCHDOG, reg); - } - - return; -} - -#if 0 -static void dc_decode_leaf_sia(sc, l) - struct dc_softc *sc; - struct dc_eblock_sia *l; -{ - struct dc_mediainfo *m; - - m = malloc(sizeof(struct dc_mediainfo), M_DEVBUF, M_NOWAIT); - bzero(m, sizeof(struct dc_mediainfo)); - if (l->dc_sia_code == DC_SIA_CODE_10BT) - m->dc_media = IFM_10_T; - - if (l->dc_sia_code == DC_SIA_CODE_10BT_FDX) - m->dc_media = IFM_10_T|IFM_FDX; - - if (l->dc_sia_code == DC_SIA_CODE_10B2) - m->dc_media = IFM_10_2; - - if (l->dc_sia_code == DC_SIA_CODE_10B5) - m->dc_media = IFM_10_5; - - m->dc_gp_len = 2; - m->dc_gp_ptr = (u_int8_t *)&l->dc_sia_gpio_ctl; - - m->dc_next = sc->dc_mi; - sc->dc_mi = m; - - sc->dc_pmode = DC_PMODE_SIA; - - return; -} - -static void dc_decode_leaf_sym(sc, l) - struct dc_softc *sc; - struct dc_eblock_sym *l; -{ - struct dc_mediainfo *m; - - m = malloc(sizeof(struct dc_mediainfo), M_DEVBUF, M_NOWAIT); - bzero(m, sizeof(struct dc_mediainfo)); - if (l->dc_sym_code == DC_SYM_CODE_100BT) - m->dc_media = IFM_100_TX; - - if (l->dc_sym_code == DC_SYM_CODE_100BT_FDX) - m->dc_media = IFM_100_TX|IFM_FDX; - - m->dc_gp_len = 2; - m->dc_gp_ptr = (u_int8_t *)&l->dc_sym_gpio_ctl; - - m->dc_next = sc->dc_mi; - sc->dc_mi = m; - - sc->dc_pmode = DC_PMODE_SYM; - - return; -} - -static void dc_decode_leaf_mii(sc, l) - struct dc_softc *sc; - struct dc_eblock_mii *l; -{ - u_int8_t *p; - struct dc_mediainfo *m; - - m = malloc(sizeof(struct dc_mediainfo), M_DEVBUF, M_NOWAIT); - bzero(m, sizeof(struct dc_mediainfo)); - /* We abuse IFM_AUTO to represent MII. */ - m->dc_media = IFM_AUTO; - m->dc_gp_len = l->dc_gpr_len; - - p = (u_int8_t *)l; - p += sizeof(struct dc_eblock_mii); - m->dc_gp_ptr = p; - p += 2 * l->dc_gpr_len; - m->dc_reset_len = *p; - p++; - m->dc_reset_ptr = p; - - m->dc_next = sc->dc_mi; - sc->dc_mi = m; - - return; -} -#endif - -static void dc_read_srom(sc, bits) - struct dc_softc *sc; - int bits; -{ - int size; - - size = 2 << bits; - sc->dc_srom = malloc(size, M_DEVBUF, M_NOWAIT); - dc_read_eeprom(sc, (caddr_t)sc->dc_srom, 0, (size / 2), 0); -} - -static void dc_parse_21143_srom(sc) - struct dc_softc *sc; -{ - struct dc_leaf_hdr *lhdr; - struct dc_eblock_hdr *hdr; - int i, loff; - char *ptr; - - loff = sc->dc_srom[27]; - lhdr = (struct dc_leaf_hdr *)&(sc->dc_srom[loff]); - - ptr = (char *)lhdr; - ptr += sizeof(struct dc_leaf_hdr) - 1; - for (i = 0; i < lhdr->dc_mcnt; i++) { - hdr = (struct dc_eblock_hdr *)ptr; - switch(hdr->dc_type) { -#if 0 - case DC_EBLOCK_MII: - dc_decode_leaf_mii(sc, (struct dc_eblock_mii *)hdr); - break; - case DC_EBLOCK_SIA: - dc_decode_leaf_sia(sc, (struct dc_eblock_sia *)hdr); - break; - case DC_EBLOCK_SYM: - dc_decode_leaf_sym(sc, (struct dc_eblock_sym *)hdr); - break; -#endif - default: - /* Don't care. Yet. */ - break; - } - ptr += (hdr->dc_len & 0x7F); - ptr++; - } - - return; -} - - -static void -nop(const rtems_irq_connect_data* unused) -{ -} - -/* - * Attach the interface. Allocate softc structures, do ifmedia - * setup and ethernet/BPF attach. - */ -int -rtems_dc_driver_attach(struct rtems_bsdnet_ifconfig *config, int attaching) -{ - int rc; - u_char eaddr[ETHER_ADDR_LEN]; - - char *unitName; - int unitNumber; - - uint32_t command; - struct dc_softc *sc; - struct ifnet *ifp; - struct dc_type *t; - uint32_t revision; - int error = 0, mac_offset; - uint32_t value; - - /* - * Get the instance number for the board we're going to configure - * from the user. - */ - unitNumber = rtems_bsdnet_parse_driver_name(config, &unitName); - if( unitNumber < 0) { - return 0; - } - if( strcmp(unitName, DRIVER_PREFIX) ) { - printk("dec2114x : unit name '%s' not %s\n", \ - unitName, DRIVER_PREFIX ); - return 0; - } - - sc = &dc_softc_devs[unitNumber - 1]; - ifp = &sc->arpcom.ac_if; - - if(ifp->if_softc != NULL) { - printk("dec2114x[%d]: unit number already in use.\n", \ - unitNumber); - return (0); - } - memset(sc, 0, sizeof(struct dc_softc)); - - /*unit = device_get_unit(dev);*/ - sc->dc_unit = unitNumber; - sc->dc_name = unitName; - - /* - * Handle power management nonsense. - * - dc_acpi(dev); - */ - - /* Scan for dec2114x cards in pci config space */ - if( (sc->dc_info = dc_devtype(unitNumber)) == NULL) { - printk("Can't find any dec2114x NICs in PCI space.\n"); - return 0; - } - t = sc->dc_info; - - - /* - * Map control/status registers. - */ - /*sig = sc->dc_info->dc_devsig; */ - pci_read_config_dword(t->dc_bus,t->dc_dev,t->dc_fun,\ - PCI_COMMAND, &command); - /*pcib_conf_read32(sig, PCI_COMMAND, &command); */ - command |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - pci_write_config_dword(t->dc_bus,t->dc_dev,t->dc_fun,\ - PCI_COMMAND, command); - /*pcib_conf_write32(sig, PCI_COMMAND, command); */ - pci_read_config_dword(t->dc_bus,t->dc_dev,t->dc_fun,\ - PCI_COMMAND, &command); - /*pcib_conf_read32(sig, PCI_COMMAND, &command); */ - -#ifdef DC_USEIOSPACE - if (!(command & PCI_COMMAND_IO)) { - printk("dc%d: failed to enable I/O ports!\n", sc->dc_unit); - error = ENXIO; - goto fail; - } -#else - if (!(command & PCI_COMMAND_MEMORY)) { - printk("dc%d: failed to enable memory mapping!\n", sc->dc_unit); - error = ENXIO; - goto fail; - } -#endif - -#if 0 - rid = DC_RID; - sc->dc_res = bus_alloc_resource(dev, DC_RES, &rid, - 0, ~0, 1, RF_ACTIVE); - - if (sc->dc_res == NULL) { - printk("dc%d: couldn't map ports/memory\n", unit); - error = ENXIO; - goto fail; - } - sc->dc_btag = rman_get_bustag(sc->dc_res); - sc->dc_bhandle = rman_get_bushandle(sc->dc_res); -#endif - - /* sc->membase is the address of the card's CSRs !!! */ - /*pcib_conf_read32(sig, DC_PCI_CFBMA, &value); */ - pci_read_config_dword(t->dc_bus,t->dc_dev,t->dc_fun,\ - DC_PCI_CFBMA, &value); - sc->membase = value; - - /* Allocate interrupt */ - memset(&sc->irqInfo, 0, sizeof(rtems_irq_connect_data)); - /*pcib_conf_read32(sig, DC_PCI_CFIT, &value); */ - pci_read_config_dword(t->dc_bus,t->dc_dev,t->dc_fun,\ - DC_PCI_CFIT, &value); - - sc->irqInfo.name = value & 0xFF; - sc->irqInfo.hdl = (rtems_irq_hdl)dc_intr; - sc->irqInfo.handle = (void *)sc; /* new parameter */ - sc->irqInfo.on = nop; - sc->irqInfo.off = nop; - sc->irqInfo.isOn = NULL; - -#ifdef BSP_SHARED_HANDLER_SUPPORT - rc = BSP_install_rtems_shared_irq_handler( &sc->irqInfo ); -#else - rc = BSP_install_rtems_irq_handler( &sc->irqInfo ); -#endif - if(!rc) { - rtems_panic("Can't install dec2114x irq handler.\n"); - } - - -#if 0 - rid = 0; - sc->dc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, - RF_SHAREABLE | RF_ACTIVE); - - if (sc->dc_irq == NULL) { - printk("dc%d: couldn't map interrupt\n", unit); - bus_release_resource(dev, DC_RES, DC_RID, sc->dc_res); - error = ENXIO; - goto fail; - } - - error = bus_setup_intr(dev, sc->dc_irq, INTR_TYPE_NET, - dc_intr, sc, &sc->dc_intrhand); - - if (error) { - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->dc_irq); - bus_release_resource(dev, DC_RES, DC_RID, sc->dc_res); - printk("dc%d: couldn't set up irq\n", unit); - goto fail; - } -#endif - - - /* Need this info to decide on a chip type. - sc->dc_info = dc_devtype(dev); - */ - /*pcib_conf_read32(sig, DC_PCI_CFRV, &revision); */ - pci_read_config_dword(t->dc_bus,t->dc_dev,t->dc_fun,\ - DC_PCI_CFRV, &revision); - revision &= 0x000000FF; - - /* Get the eeprom width, but PNIC has diff eeprom */ - if (sc->dc_info->dc_did != DC_DEVICEID_82C168) - dc_eeprom_width(sc); - - switch(sc->dc_info->dc_did) { - case DC_DEVICEID_21143: - sc->dc_type = DC_TYPE_21143; - sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; - sc->dc_flags |= DC_REDUCED_MII_POLL; - /* Save EEPROM contents so we can parse them later. */ - dc_read_srom(sc, sc->dc_romwidth); - break; - case DC_DEVICEID_DM9009: - case DC_DEVICEID_DM9100: - case DC_DEVICEID_DM9102: - sc->dc_type = DC_TYPE_DM9102; - sc->dc_flags |= DC_TX_COALESCE|DC_TX_INTR_ALWAYS; - sc->dc_flags |= DC_REDUCED_MII_POLL|DC_TX_STORENFWD; - sc->dc_pmode = DC_PMODE_MII; - /* Increase the latency timer value. */ - /*pcib_conf_read32(sig, DC_PCI_CFLT, &command); */ - pci_read_config_dword(t->dc_bus,t->dc_dev,t->dc_fun,\ - DC_PCI_CFLT, &command); - command &= 0xFFFF00FF; - command |= 0x00008000; - /*pcib_conf_write32(sig, DC_PCI_CFLT, command); */ - pci_write_config_dword(t->dc_bus,t->dc_dev,t->dc_fun,\ - DC_PCI_CFLT, command); - break; - case DC_DEVICEID_AL981: - sc->dc_type = DC_TYPE_AL981; - sc->dc_flags |= DC_TX_USE_TX_INTR; - sc->dc_flags |= DC_TX_ADMTEK_WAR; - sc->dc_pmode = DC_PMODE_MII; - dc_read_srom(sc, sc->dc_romwidth); - break; - case DC_DEVICEID_AN985: - case DC_DEVICEID_EN2242: - sc->dc_type = DC_TYPE_AN985; - sc->dc_flags |= DC_TX_USE_TX_INTR; - sc->dc_flags |= DC_TX_ADMTEK_WAR; - sc->dc_pmode = DC_PMODE_MII; - dc_read_srom(sc, sc->dc_romwidth); - break; - case DC_DEVICEID_98713: - case DC_DEVICEID_98713_CP: - if (revision < DC_REVISION_98713A) { - sc->dc_type = DC_TYPE_98713; - } - if (revision >= DC_REVISION_98713A) { - sc->dc_type = DC_TYPE_98713A; - sc->dc_flags |= DC_21143_NWAY; - } - sc->dc_flags |= DC_REDUCED_MII_POLL; - sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; - break; - case DC_DEVICEID_987x5: - case DC_DEVICEID_EN1217: - /* - * Macronix MX98715AEC-C/D/E parts have only a - * 128-bit hash table. We need to deal with these - * in the same manner as the PNIC II so that we - * get the right number of bits out of the - * CRC routine. - */ - if (revision >= DC_REVISION_98715AEC_C && - revision < DC_REVISION_98725) - sc->dc_flags |= DC_128BIT_HASH; - sc->dc_type = DC_TYPE_987x5; - sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; - sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY; - break; - case DC_DEVICEID_98727: - sc->dc_type = DC_TYPE_987x5; - sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; - sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY; - break; - case DC_DEVICEID_82C115: - sc->dc_type = DC_TYPE_PNICII; - sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR|DC_128BIT_HASH; - sc->dc_flags |= DC_REDUCED_MII_POLL|DC_21143_NWAY; - break; - case DC_DEVICEID_82C168: - sc->dc_type = DC_TYPE_PNIC; - sc->dc_flags |= DC_TX_STORENFWD|DC_TX_INTR_ALWAYS; - sc->dc_flags |= DC_PNIC_RX_BUG_WAR; - sc->dc_pnic_rx_buf = malloc(DC_RXLEN * 5, M_DEVBUF, M_NOWAIT); - if (revision < DC_REVISION_82C169) - sc->dc_pmode = DC_PMODE_SYM; - break; - case DC_DEVICEID_AX88140A: - sc->dc_type = DC_TYPE_ASIX; - sc->dc_flags |= DC_TX_USE_TX_INTR|DC_TX_INTR_FIRSTFRAG; - sc->dc_flags |= DC_REDUCED_MII_POLL; - sc->dc_pmode = DC_PMODE_MII; - break; - case DC_DEVICEID_RS7112: - sc->dc_type = DC_TYPE_CONEXANT; - sc->dc_flags |= DC_TX_INTR_ALWAYS; - sc->dc_flags |= DC_REDUCED_MII_POLL; - sc->dc_pmode = DC_PMODE_MII; - dc_read_srom(sc, sc->dc_romwidth); - break; - default: - printk("dc%d: unknown device: %x\n", sc->dc_unit, - sc->dc_info->dc_did); - break; - } - - /* Save the cache line size. */ - if (DC_IS_DAVICOM(sc)) { - sc->dc_cachesize = 0; - } - else { - /*pcib_conf_read32(sig, DC_PCI_CFLT, &value); */ - pci_read_config_dword(t->dc_bus,t->dc_dev,t->dc_fun,\ - DC_PCI_CFLT, &value); - sc->dc_cachesize = (u_int8_t)(value & 0xFF); - } - - /* Reset the adapter. */ - dc_reset(sc); - - /* Take 21143 out of snooze mode */ - if (DC_IS_INTEL(sc)) { - /*pcib_conf_read32(sig, DC_PCI_CFDD, &command); */ - pci_read_config_dword(t->dc_bus,t->dc_dev,t->dc_fun,\ - DC_PCI_CFDD, &command); - command &= ~(DC_CFDD_SNOOZE_MODE|DC_CFDD_SLEEP_MODE); - /*pcib_conf_write32(sig, DC_PCI_CFDD, command); */ - pci_write_config_dword(t->dc_bus,t->dc_dev,t->dc_fun,\ - DC_PCI_CFDD, command); - } - - - /* - * Try to learn something about the supported media. - * We know that ASIX and ADMtek and Davicom devices - * will *always* be using MII media, so that's a no-brainer. - * The tricky ones are the Macronix/PNIC II and the - * Intel 21143. - */ - if (DC_IS_INTEL(sc)) - dc_parse_21143_srom(sc); - else if (DC_IS_MACRONIX(sc) || DC_IS_PNICII(sc)) { - if (sc->dc_type == DC_TYPE_98713) - sc->dc_pmode = DC_PMODE_MII; - else - sc->dc_pmode = DC_PMODE_SYM; - } else if (!sc->dc_pmode) - sc->dc_pmode = DC_PMODE_MII; - - /* - * Get station address from the EEPROM. - */ - switch(sc->dc_type) { - case DC_TYPE_98713: - case DC_TYPE_98713A: - case DC_TYPE_987x5: - case DC_TYPE_PNICII: - dc_read_eeprom(sc, (caddr_t)&mac_offset, - (DC_EE_NODEADDR_OFFSET / 2), 1, 0); - dc_read_eeprom(sc, (caddr_t)&eaddr, (mac_offset / 2), 3, 0); - break; - case DC_TYPE_PNIC: - dc_read_eeprom(sc, (caddr_t)&eaddr, 0, 3, 1); - break; - case DC_TYPE_DM9102: - case DC_TYPE_21143: - case DC_TYPE_ASIX: - dc_read_eeprom(sc, (caddr_t)&eaddr, DC_EE_NODEADDR, 3, 0); - break; - case DC_TYPE_AL981: - case DC_TYPE_AN985: - bcopy(&sc->dc_srom[DC_AL_EE_NODEADDR], (caddr_t)&eaddr, - ETHER_ADDR_LEN); - dc_read_eeprom(sc, (caddr_t)&eaddr, DC_AL_EE_NODEADDR, 3, 0); - break; - case DC_TYPE_CONEXANT: - bcopy(sc->dc_srom + DC_CONEXANT_EE_NODEADDR, &eaddr, 6); - break; - default: - dc_read_eeprom(sc, (caddr_t)&eaddr, DC_EE_NODEADDR, 3, 0); - break; - } - - /* - * A 21143 or clone chip was detected. Inform the world. - */ - bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); - printk("dc%d: MAC address -- %02x:%02x:%02x:%02x:%02x:%02x\n", \ - sc->dc_unit,sc->arpcom.ac_enaddr[0], \ - sc->arpcom.ac_enaddr[1], sc->arpcom.ac_enaddr[2], \ - sc->arpcom.ac_enaddr[3], sc->arpcom.ac_enaddr[4], \ - sc->arpcom.ac_enaddr[5]); - - - sc->dc_ldata = malloc(sizeof(struct dc_list_data), M_DEVBUF, M_NOWAIT); - - if (sc->dc_ldata == NULL) { - printk("dc%d: no memory for list buffers!\n", sc->dc_unit); - if (sc->dc_pnic_rx_buf != NULL) - free(sc->dc_pnic_rx_buf, M_DEVBUF); -#if 0 - bus_teardown_intr(dev, sc->dc_irq, sc->dc_intrhand); - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->dc_irq); - bus_release_resource(dev, DC_RES, DC_RID, sc->dc_res); -#endif - error = ENXIO; - goto fail; - } - - bzero(sc->dc_ldata, sizeof(struct dc_list_data)); - - ifp = &sc->arpcom.ac_if; - ifp->if_softc = sc; - ifp->if_unit = unitNumber; /*sc->dc_unit;*/ - ifp->if_name = unitName; /*sc->dc_name;*/ - ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; /* | IFF_MULTICAST;*/ - ifp->if_ioctl = dc_ioctl; - ifp->if_output = ether_output; - ifp->if_start = dc_start; - ifp->if_watchdog = dc_watchdog; - ifp->if_init = dc_init; - ifp->if_baudrate = 100000000; - ifp->if_snd.ifq_maxlen = DC_TX_LIST_CNT - 1; - -#if 0 - /* - * Do MII setup. If this is a 21143, check for a PHY on the - * MII bus after applying any necessary fixups to twiddle the - * GPIO bits. If we don't end up finding a PHY, restore the - * old selection (SIA only or SIA/SYM) and attach the dcphy - * driver instead. - */ - if (DC_IS_INTEL(sc)) { - dc_apply_fixup(sc, IFM_AUTO); - tmp = sc->dc_pmode; - sc->dc_pmode = DC_PMODE_MII; - } - - error = mii_phy_probe(dev, &sc->dc_miibus, - dc_ifmedia_upd, dc_ifmedia_sts); - - if (error && DC_IS_INTEL(sc)) { - sc->dc_pmode = tmp; - if (sc->dc_pmode != DC_PMODE_SIA) - sc->dc_pmode = DC_PMODE_SYM; - sc->dc_flags |= DC_21143_NWAY; - mii_phy_probe(dev, &sc->dc_miibus, - dc_ifmedia_upd, dc_ifmedia_sts); - /* - * For non-MII cards, we need to have the 21143 - * drive the LEDs. Except there are some systems - * like the NEC VersaPro NoteBook PC which have no - * LEDs, and twiddling these bits has adverse effects - * on them. (I.e. you suddenly can't get a link.) - */ - if (pci_read_config(dev, DC_PCI_CSID, 4) != 0x80281033) - sc->dc_flags |= DC_TULIP_LEDS; - error = 0; - } - - if (error) { - printk("dc%d: MII without any PHY!\n", sc->dc_unit); - contigfree(sc->dc_ldata, sizeof(struct dc_list_data), - M_DEVBUF); - if (sc->dc_pnic_rx_buf != NULL) - free(sc->dc_pnic_rx_buf, M_DEVBUF); - bus_teardown_intr(dev, sc->dc_irq, sc->dc_intrhand); - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->dc_irq); - bus_release_resource(dev, DC_RES, DC_RID, sc->dc_res); - error = ENXIO; - goto fail; - } -#endif - - /* - * Call MI attach routine. - */ - if_attach(ifp); - ether_ifattach(ifp); - /*callout_handle_init(&sc->dc_stat_ch);*/ - - if (DC_IS_ADMTEK(sc)) { - /* - * Set automatic TX underrun recovery for the ADMtek chips - */ - DC_SETBIT(sc, DC_AL_CR, DC_AL_CR_ATUR); - } - - if(sc->daemontid == 0) { - sc->daemontid = rtems_bsdnet_newproc("decD",4096, \ - dc_daemon,(void *)sc); - printk("dec[%d]: daemon process started\n", sc->dc_unit); - } - - /* - * Tell the upper layer(s) we support long frames. - * - ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); - */ - -#ifdef SRM_MEDIA /* only defined if __alpha__ is defined... */ - sc->dc_srm_media = 0; - - /* Remember the SRM console media setting */ - if (DC_IS_INTEL(sc)) { - command = pci_read_config(dev, DC_PCI_CFDD, 4); - command &= ~(DC_CFDD_SNOOZE_MODE|DC_CFDD_SLEEP_MODE); - switch ((command >> 8) & 0xff) { - case 3: - sc->dc_srm_media = IFM_10_T; - break; - case 4: - sc->dc_srm_media = IFM_10_T | IFM_FDX; - break; - case 5: - sc->dc_srm_media = IFM_100_TX; - break; - case 6: - sc->dc_srm_media = IFM_100_TX | IFM_FDX; - break; - } - if (sc->dc_srm_media) - sc->dc_srm_media |= IFM_ACTIVE | IFM_ETHER; - } -#endif - - -fail: - - return (1); /*(error);*/ -} - -#if 0 -static int dc_detach(dev) - device_t dev; -{ - struct dc_softc *sc; - struct ifnet *ifp; - int s; - struct dc_mediainfo *m; - - - sc = device_get_softc(dev); - ifp = &sc->arpcom.ac_if; - - dc_stop(sc); - ether_ifdetach(ifp, ETHER_BPF_SUPPORTED); - - bus_generic_detach(dev); - device_delete_child(dev, sc->dc_miibus); - - bus_teardown_intr(dev, sc->dc_irq, sc->dc_intrhand); - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->dc_irq); - bus_release_resource(dev, DC_RES, DC_RID, sc->dc_res); - - contigfree(sc->dc_ldata, sizeof(struct dc_list_data), M_DEVBUF); - if (sc->dc_pnic_rx_buf != NULL) - free(sc->dc_pnic_rx_buf, M_DEVBUF); - - while(sc->dc_mi != NULL) { - m = sc->dc_mi->dc_next; - free(sc->dc_mi, M_DEVBUF); - sc->dc_mi = m; - } - free(sc->dc_srom, M_DEVBUF); - - - return(0); -} -#endif - - -/* - * Initialize the transmit descriptors. - */ -static int dc_list_tx_init(sc) - struct dc_softc *sc; -{ - struct dc_chain_data *cd; - struct dc_list_data *ld; - int i; - - cd = &sc->dc_cdata; - ld = sc->dc_ldata; - for (i = 0; i < DC_TX_LIST_CNT; i++) { - if (i == (DC_TX_LIST_CNT - 1)) { - ld->dc_tx_list[i].dc_next = - vtophys(&ld->dc_tx_list[0]); - } else { - ld->dc_tx_list[i].dc_next = - vtophys(&ld->dc_tx_list[i + 1]); - } - cd->dc_tx_chain[i] = NULL; - ld->dc_tx_list[i].dc_data = 0; - ld->dc_tx_list[i].dc_ctl = 0; - } - - cd->dc_tx_prod = cd->dc_tx_cons = cd->dc_tx_cnt = 0; - - return(0); -} - - -/* - * Initialize the RX descriptors and allocate mbufs for them. Note that - * we arrange the descriptors in a closed ring, so that the last descriptor - * points back to the first. - */ -static int dc_list_rx_init(sc) - struct dc_softc *sc; -{ - struct dc_chain_data *cd; - struct dc_list_data *ld; - int i; - - cd = &sc->dc_cdata; - ld = sc->dc_ldata; - - for (i = 0; i < DC_RX_LIST_CNT; i++) { - if (dc_newbuf(sc, i, NULL) == ENOBUFS) - return(ENOBUFS); - if (i == (DC_RX_LIST_CNT - 1)) { - ld->dc_rx_list[i].dc_next = - vtophys(&ld->dc_rx_list[0]); - } else { - ld->dc_rx_list[i].dc_next = - vtophys(&ld->dc_rx_list[i + 1]); - } - } - - cd->dc_rx_prod = 0; - - return(0); -} - -/* - * Initialize an RX descriptor and attach an MBUF cluster. - */ -static int dc_newbuf(sc, i, m) - struct dc_softc *sc; - int i; - struct mbuf *m; -{ - struct mbuf *m_new = NULL; - struct dc_desc *c; - - c = &sc->dc_ldata->dc_rx_list[i]; - - if (m == NULL) { - MGETHDR(m_new, M_DONTWAIT, MT_DATA); - if (m_new == NULL) - return(ENOBUFS); - - MCLGET(m_new, M_DONTWAIT); - if (!(m_new->m_flags & M_EXT)) { - m_freem(m_new); - return(ENOBUFS); - } - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; - } else { - m_new = m; - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; - m_new->m_data = m_new->m_ext.ext_buf; - } - - m_adj(m_new, sizeof(u_int64_t)); - - /* - * If this is a PNIC chip, zero the buffer. This is part - * of the workaround for the receive bug in the 82c168 and - * 82c169 chips. - */ - if (sc->dc_flags & DC_PNIC_RX_BUG_WAR) - bzero((char *)mtod(m_new, char *), m_new->m_len); - - sc->dc_cdata.dc_rx_chain[i] = m_new; - c->dc_data = vtophys(mtod(m_new, caddr_t)); - c->dc_ctl = DC_RXCTL_RLINK | DC_RXLEN; - c->dc_status = DC_RXSTAT_OWN; - - return(0); -} - -/* - * Grrrrr. - * The PNIC chip has a terrible bug in it that manifests itself during - * periods of heavy activity. The exact mode of failure if difficult to - * pinpoint: sometimes it only happens in promiscuous mode, sometimes it - * will happen on slow machines. The bug is that sometimes instead of - * uploading one complete frame during reception, it uploads what looks - * like the entire contents of its FIFO memory. The frame we want is at - * the end of the whole mess, but we never know exactly how much data has - * been uploaded, so salvaging the frame is hard. - * - * There is only one way to do it reliably, and it's disgusting. - * Here's what we know: - * - * - We know there will always be somewhere between one and three extra - * descriptors uploaded. - * - * - We know the desired received frame will always be at the end of the - * total data upload. - * - * - We know the size of the desired received frame because it will be - * provided in the length field of the status word in the last descriptor. - * - * Here's what we do: - * - * - When we allocate buffers for the receive ring, we bzero() them. - * This means that we know that the buffer contents should be all - * zeros, except for data uploaded by the chip. - * - * - We also force the PNIC chip to upload frames that include the - * ethernet CRC at the end. - * - * - We gather all of the bogus frame data into a single buffer. - * - * - We then position a pointer at the end of this buffer and scan - * backwards until we encounter the first non-zero byte of data. - * This is the end of the received frame. We know we will encounter - * some data at the end of the frame because the CRC will always be - * there, so even if the sender transmits a packet of all zeros, - * we won't be fooled. - * - * - We know the size of the actual received frame, so we subtract - * that value from the current pointer location. This brings us - * to the start of the actual received packet. - * - * - We copy this into an mbuf and pass it on, along with the actual - * frame length. - * - * The performance hit is tremendous, but it beats dropping frames all - * the time. - */ - -#define DC_WHOLEFRAME (DC_RXSTAT_FIRSTFRAG|DC_RXSTAT_LASTFRAG) -static void dc_pnic_rx_bug_war(sc, idx) - struct dc_softc *sc; - int idx; -{ - struct dc_desc *cur_rx; - struct dc_desc *c = NULL; - struct mbuf *m = NULL; - unsigned char *ptr; - int i, total_len; - u_int32_t rxstat = 0; - - i = sc->dc_pnic_rx_bug_save; - cur_rx = &sc->dc_ldata->dc_rx_list[idx]; - ptr = sc->dc_pnic_rx_buf; - bzero(ptr, sizeof(DC_RXLEN * 5)); - - /* Copy all the bytes from the bogus buffers. */ - while (1) { - c = &sc->dc_ldata->dc_rx_list[i]; - rxstat = c->dc_status; - m = sc->dc_cdata.dc_rx_chain[i]; - bcopy(mtod(m, char *), ptr, DC_RXLEN); - ptr += DC_RXLEN; - /* If this is the last buffer, break out. */ - if (i == idx || rxstat & DC_RXSTAT_LASTFRAG) - break; - dc_newbuf(sc, i, m); - DC_INC(i, DC_RX_LIST_CNT); - } - - /* Find the length of the actual receive frame. */ - total_len = DC_RXBYTES(rxstat); - - /* Scan backwards until we hit a non-zero byte. */ - while(*ptr == 0x00) - ptr--; -#if 0 - /* Round off. */ - if ((uintptr_t)(ptr) & 0x3) - ptr -= 1; -#endif - - /* Now find the start of the frame. */ - ptr -= total_len; - if (ptr < sc->dc_pnic_rx_buf) - ptr = sc->dc_pnic_rx_buf; - - /* - * Now copy the salvaged frame to the last mbuf and fake up - * the status word to make it look like a successful - * frame reception. - */ - dc_newbuf(sc, i, m); - bcopy(ptr, mtod(m, char *), total_len); - cur_rx->dc_status = rxstat | DC_RXSTAT_FIRSTFRAG; - - return; -} - -/* - * This routine searches the RX ring for dirty descriptors in the - * event that the rxeof routine falls out of sync with the chip's - * current descriptor pointer. This may happen sometimes as a result - * of a "no RX buffer available" condition that happens when the chip - * consumes all of the RX buffers before the driver has a chance to - * process the RX ring. This routine may need to be called more than - * once to bring the driver back in sync with the chip, however we - * should still be getting RX DONE interrupts to drive the search - * for new packets in the RX ring, so we should catch up eventually. - */ -static int dc_rx_resync(sc) - struct dc_softc *sc; -{ - int i, pos; - struct dc_desc *cur_rx; - - pos = sc->dc_cdata.dc_rx_prod; - - for (i = 0; i < DC_RX_LIST_CNT; i++) { - cur_rx = &sc->dc_ldata->dc_rx_list[pos]; - if (!(cur_rx->dc_status & DC_RXSTAT_OWN)) - break; - DC_INC(pos, DC_RX_LIST_CNT); - } - - /* If the ring really is empty, then just return. */ - if (i == DC_RX_LIST_CNT) - return(0); - - /* We've fallen behing the chip: catch it. */ - sc->dc_cdata.dc_rx_prod = pos; - - return(EAGAIN); -} - -/* - * A frame has been uploaded: pass the resulting mbuf chain up to - * the higher level protocols. - */ -static void dc_rxeof(sc) - struct dc_softc *sc; -{ - struct ether_header *eh; - struct mbuf *m; - struct ifnet *ifp; - struct dc_desc *cur_rx; - int i, total_len = 0; - u_int32_t rxstat; - - ifp = &sc->arpcom.ac_if; - i = sc->dc_cdata.dc_rx_prod; - - while(!(sc->dc_ldata->dc_rx_list[i].dc_status & DC_RXSTAT_OWN)) { - -#ifdef DEVICE_POLLING - if (ifp->if_ipending & IFF_POLLING) { - if (sc->rxcycles <= 0) - break; - sc->rxcycles--; - } -#endif /* DEVICE_POLLING */ - cur_rx = &sc->dc_ldata->dc_rx_list[i]; - rxstat = cur_rx->dc_status; - m = sc->dc_cdata.dc_rx_chain[i]; - total_len = DC_RXBYTES(rxstat); - - if (sc->dc_flags & DC_PNIC_RX_BUG_WAR) { - if ((rxstat & DC_WHOLEFRAME) != DC_WHOLEFRAME) { - if (rxstat & DC_RXSTAT_FIRSTFRAG) - sc->dc_pnic_rx_bug_save = i; - if ((rxstat & DC_RXSTAT_LASTFRAG) == 0) { - DC_INC(i, DC_RX_LIST_CNT); - continue; - } - dc_pnic_rx_bug_war(sc, i); - rxstat = cur_rx->dc_status; - total_len = DC_RXBYTES(rxstat); - } - } - - sc->dc_cdata.dc_rx_chain[i] = NULL; - - /* - * If an error occurs, update stats, clear the - * status word and leave the mbuf cluster in place: - * it should simply get re-used next time this descriptor - * comes up in the ring. However, don't report long - * frames as errors since they could be vlans - */ - if ((rxstat & DC_RXSTAT_RXERR)){ - if (!(rxstat & DC_RXSTAT_GIANT) || - (rxstat & (DC_RXSTAT_CRCERR | DC_RXSTAT_DRIBBLE | - DC_RXSTAT_MIIERE | DC_RXSTAT_COLLSEEN | - DC_RXSTAT_RUNT | DC_RXSTAT_DE))) { - ifp->if_ierrors++; - if (rxstat & DC_RXSTAT_COLLSEEN) - ifp->if_collisions++; - dc_newbuf(sc, i, m); - if (rxstat & DC_RXSTAT_CRCERR) { - DC_INC(i, DC_RX_LIST_CNT); - continue; - } else { - dc_init(sc); - return; - } - } - } - - /* No errors; receive the packet. */ - total_len -= ETHER_CRC_LEN; - -#ifdef __i386__ - /* - * On the x86 we do not have alignment problems, so try to - * allocate a new buffer for the receive ring, and pass up - * the one where the packet is already, saving the expensive - * copy done in m_devget(). - * If we are on an architecture with alignment problems, or - * if the allocation fails, then use m_devget and leave the - * existing buffer in the receive ring. - */ - if (dc_quick && dc_newbuf(sc, i, NULL) == 0) { - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = total_len; - DC_INC(i, DC_RX_LIST_CNT); - } else -#endif - { - struct mbuf *m0; - - m0 = m_devget(mtod(m, char *) - ETHER_ALIGN, - total_len + ETHER_ALIGN, 0, ifp, NULL); - dc_newbuf(sc, i, m); - DC_INC(i, DC_RX_LIST_CNT); - if (m0 == NULL) { - ifp->if_ierrors++; - continue; - } - m_adj(m0, ETHER_ALIGN); - m = m0; - } - - ifp->if_ipackets++; - eh = mtod(m, struct ether_header *); - - /* Remove header from mbuf and pass it on. */ - m_adj(m, sizeof(struct ether_header)); - ether_input(ifp, eh, m); - } - - sc->dc_cdata.dc_rx_prod = i; -} - -/* - * A frame was downloaded to the chip. It's safe for us to clean up - * the list buffers. - */ - -static void -dc_txeof(sc) - struct dc_softc *sc; -{ - struct dc_desc *cur_tx = NULL; - struct ifnet *ifp; - int idx; - - ifp = &sc->arpcom.ac_if; - - /* - * Go through our tx list and free mbufs for those - * frames that have been transmitted. - */ - idx = sc->dc_cdata.dc_tx_cons; - while(idx != sc->dc_cdata.dc_tx_prod) { - u_int32_t txstat; - - cur_tx = &sc->dc_ldata->dc_tx_list[idx]; - txstat = cur_tx->dc_status; - - if (txstat & DC_TXSTAT_OWN) - break; - - if (!(cur_tx->dc_ctl & DC_TXCTL_LASTFRAG) || - cur_tx->dc_ctl & DC_TXCTL_SETUP) { - if (cur_tx->dc_ctl & DC_TXCTL_SETUP) { - /* - * Yes, the PNIC is so brain damaged - * that it will sometimes generate a TX - * underrun error while DMAing the RX - * filter setup frame. If we detect this, - * we have to send the setup frame again, - * or else the filter won't be programmed - * correctly. - */ - if (DC_IS_PNIC(sc)) { - if (txstat & DC_TXSTAT_ERRSUM) - dc_setfilt(sc); - } - sc->dc_cdata.dc_tx_chain[idx] = NULL; - } - sc->dc_cdata.dc_tx_cnt--; - DC_INC(idx, DC_TX_LIST_CNT); - continue; - } - - if (DC_IS_CONEXANT(sc)) { - /* - * For some reason Conexant chips like - * setting the CARRLOST flag even when - * the carrier is there. In CURRENT we - * have the same problem for Xircom - * cards ! - */ - if (/*sc->dc_type == DC_TYPE_21143 &&*/ - sc->dc_pmode == DC_PMODE_MII && - ((txstat & 0xFFFF) & ~(DC_TXSTAT_ERRSUM| - DC_TXSTAT_NOCARRIER))) - txstat &= ~DC_TXSTAT_ERRSUM; - } else { - if (/*sc->dc_type == DC_TYPE_21143 &&*/ - sc->dc_pmode == DC_PMODE_MII && - ((txstat & 0xFFFF) & ~(DC_TXSTAT_ERRSUM| - DC_TXSTAT_NOCARRIER|DC_TXSTAT_CARRLOST))) - txstat &= ~DC_TXSTAT_ERRSUM; - } - - if (txstat & DC_TXSTAT_ERRSUM) { - ifp->if_oerrors++; - if (txstat & DC_TXSTAT_EXCESSCOLL) - ifp->if_collisions++; - if (txstat & DC_TXSTAT_LATECOLL) - ifp->if_collisions++; - if (!(txstat & DC_TXSTAT_UNDERRUN)) { - dc_init(sc); - return; - } - } - - ifp->if_collisions += (txstat & DC_TXSTAT_COLLCNT) >> 3; - - ifp->if_opackets++; - if (sc->dc_cdata.dc_tx_chain[idx] != NULL) { - m_freem(sc->dc_cdata.dc_tx_chain[idx]); - sc->dc_cdata.dc_tx_chain[idx] = NULL; - } - - sc->dc_cdata.dc_tx_cnt--; - DC_INC(idx, DC_TX_LIST_CNT); - } - - if (idx != sc->dc_cdata.dc_tx_cons) { - /* some buffers have been freed */ - sc->dc_cdata.dc_tx_cons = idx; - ifp->if_flags &= ~IFF_OACTIVE; - } - ifp->if_timer = (sc->dc_cdata.dc_tx_cnt == 0) ? 0 : 5; - - return; -} - - -#if 0 -static void dc_tick(xsc) - void *xsc; -{ - struct dc_softc *sc; - /*struct mii_data *mii;*/ - struct ifnet *ifp; - int s; - u_int32_t r; - - - sc = xsc; - ifp = &sc->arpcom.ac_if; - mii = device_get_softc(sc->dc_miibus); - - if (sc->dc_flags & DC_REDUCED_MII_POLL) { - if (sc->dc_flags & DC_21143_NWAY) { - r = CSR_READ_4(sc, DC_10BTSTAT); - if (IFM_SUBTYPE(mii->mii_media_active) == - IFM_100_TX && (r & DC_TSTAT_LS100)) { - sc->dc_link = 0; - mii_mediachg(mii); - } - if (IFM_SUBTYPE(mii->mii_media_active) == - IFM_10_T && (r & DC_TSTAT_LS10)) { - sc->dc_link = 0; - mii_mediachg(mii); - } - if (sc->dc_link == 0) - mii_tick(mii); - } else { - r = CSR_READ_4(sc, DC_ISR); - if ((r & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT && - sc->dc_cdata.dc_tx_cnt == 0) - mii_tick(mii); - if (!(mii->mii_media_status & IFM_ACTIVE)) - sc->dc_link = 0; - } - } else - mii_tick(mii); - - /* - * When the init routine completes, we expect to be able to send - * packets right away, and in fact the network code will send a - * gratuitous ARP the moment the init routine marks the interface - * as running. However, even though the MAC may have been initialized, - * there may be a delay of a few seconds before the PHY completes - * autonegotiation and the link is brought up. Any transmissions - * made during that delay will be lost. Dealing with this is tricky: - * we can't just pause in the init routine while waiting for the - * PHY to come ready since that would bring the whole system to - * a screeching halt for several seconds. - * - * What we do here is prevent the TX start routine from sending - * any packets until a link has been established. After the - * interface has been initialized, the tick routine will poll - * the state of the PHY until the IFM_ACTIVE flag is set. Until - * that time, packets will stay in the send queue, and once the - * link comes up, they will be flushed out to the wire. - */ - if (!sc->dc_link) { - mii_pollstat(mii); - if (mii->mii_media_status & IFM_ACTIVE && - IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { - sc->dc_link++; - if (ifp->if_snd.ifq_head != NULL) - dc_start(ifp); - } - } - - if (sc->dc_flags & DC_21143_NWAY && !sc->dc_link) - sc->dc_stat_ch = timeout(dc_tick, sc, hz/10); - else - sc->dc_stat_ch = timeout(dc_tick, sc, hz); - - return; -} -#endif - -/* - * A transmit underrun has occurred. Back off the transmit threshold, - * or switch to store and forward mode if we have to. - */ -static void dc_tx_underrun(sc) - struct dc_softc *sc; -{ - u_int32_t isr; - int i; - - if (DC_IS_DAVICOM(sc)) - dc_init(sc); - - if (DC_IS_INTEL(sc)) { - /* - * The real 21143 requires that the transmitter be idle - * in order to change the transmit threshold or store - * and forward state. - */ - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON); - - for (i = 0; i < DC_TIMEOUT; i++) { - isr = CSR_READ_4(sc, DC_ISR); - if (isr & DC_ISR_TX_IDLE) - break; - DELAY(10); - } - if (i == DC_TIMEOUT) { - printk("dc%d: failed to force tx to idle state\n", - sc->dc_unit); - dc_init(sc); - } - } - - printk("dc%d: TX underrun -- ", sc->dc_unit); - sc->dc_txthresh += DC_TXTHRESH_INC; - if (sc->dc_txthresh > DC_TXTHRESH_MAX) { - printk("using store and forward mode\n"); - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD); - } else { - printk("increasing TX threshold\n"); - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_THRESH); - DC_SETBIT(sc, DC_NETCFG, sc->dc_txthresh); - } - - if (DC_IS_INTEL(sc)) - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON); - - return; -} - -#ifdef DEVICE_POLLING -static poll_handler_t dc_poll; - -static void -dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) -{ - struct dc_softc *sc = ifp->if_softc; - - if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */ - /* Re-enable interrupts. */ - CSR_WRITE_4(sc, DC_IMR, DC_INTRS); - return; - } - sc->rxcycles = count; - dc_rxeof(sc); - dc_txeof(sc); - if (ifp->if_snd.ifq_head != NULL && !(ifp->if_flags & IFF_OACTIVE)) - dc_start(ifp); - - if (cmd == POLL_AND_CHECK_STATUS) { /* also check status register */ - u_int32_t status; - - status = CSR_READ_4(sc, DC_ISR); - status &= (DC_ISR_RX_WATDOGTIMEO|DC_ISR_RX_NOBUF| - DC_ISR_TX_NOBUF|DC_ISR_TX_IDLE|DC_ISR_TX_UNDERRUN| - DC_ISR_BUS_ERR); - if (!status) - return ; - /* ack what we have */ - CSR_WRITE_4(sc, DC_ISR, status); - - if (status & (DC_ISR_RX_WATDOGTIMEO|DC_ISR_RX_NOBUF) ) { - u_int32_t r = CSR_READ_4(sc, DC_FRAMESDISCARDED); - ifp->if_ierrors += (r & 0xffff) + ((r >> 17) & 0x7ff); - - if (dc_rx_resync(sc)) - dc_rxeof(sc); - } - /* restart transmit unit if necessary */ - if (status & DC_ISR_TX_IDLE && sc->dc_cdata.dc_tx_cnt) - CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF); - - if (status & DC_ISR_TX_UNDERRUN) - dc_tx_underrun(sc); - - if (status & DC_ISR_BUS_ERR) { - printk("dc_poll: dc%d bus error\n", sc->dc_unit); - dc_reset(sc); - dc_init(sc); - } - } -} -#endif /* DEVICE_POLLING */ - -static void -dc_intr(void* arg) -{ - /* Need to make this work for multiple devices ... eventually */ - struct dc_softc *sc = (struct dc_softc *)arg; - - - /* Disable interrupts. */ - CSR_WRITE_4(sc, DC_IMR, 0x00000000); - - rtems_bsdnet_event_send(sc->daemontid, IRQ_EVENT); -#if 0 - if (sc->suspended) { - return; - } - - ifp = &sc->arpcom.ac_if; - -#ifdef DEVICE_POLLING - if (ifp->if_ipending & IFF_POLLING) - return; - if (ether_poll_register(dc_poll, ifp)) { /* ok, disable interrupts */ - CSR_WRITE_4(sc, DC_IMR, 0x00000000); - return; - } -#endif /* DEVICE_POLLING */ - if ( (CSR_READ_4(sc, DC_ISR) & DC_INTRS) == 0) - return ; - - /* Suppress unwanted interrupts */ - if (!(ifp->if_flags & IFF_UP)) { - if (CSR_READ_4(sc, DC_ISR) & DC_INTRS) - dc_stop(sc); - return; - } -#endif -} - - -static void -dc_daemon(void * arg) -{ - struct dc_softc *sc = (struct dc_softc *)arg; - struct ifnet *ifp; - u_int32_t status; - rtems_event_set events; - - - for(;;) { - rtems_bsdnet_event_receive(RTEMS_ALL_EVENTS, \ - RTEMS_WAIT | RTEMS_EVENT_ANY, \ - RTEMS_NO_TIMEOUT, - &events); - - - ifp = &sc->arpcom.ac_if; - - while((status = CSR_READ_4(sc, DC_ISR)) & DC_INTRS) { - - CSR_WRITE_4(sc, DC_ISR, status); - - if (status & DC_ISR_RX_OK) { - int curpkts; - curpkts = ifp->if_ipackets; - dc_rxeof(sc); - if (curpkts == ifp->if_ipackets) { - while(dc_rx_resync(sc)) - dc_rxeof(sc); - } - } - - if (status & (DC_ISR_TX_OK|DC_ISR_TX_NOBUF)) - dc_txeof(sc); - - if (status & DC_ISR_TX_IDLE) { - dc_txeof(sc); - if (sc->dc_cdata.dc_tx_cnt) { - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON); - CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF); - } - } - - if (status & DC_ISR_TX_UNDERRUN) - dc_tx_underrun(sc); - - if ((status & DC_ISR_RX_WATDOGTIMEO) - || (status & DC_ISR_RX_NOBUF)) { - int curpkts; - curpkts = ifp->if_ipackets; - dc_rxeof(sc); - if (curpkts == ifp->if_ipackets) { - while(dc_rx_resync(sc)) - dc_rxeof(sc); - } - } - - if (status & DC_ISR_BUS_ERR) { - dc_reset(sc); - dc_init(sc); - } - } - - /* Make atomic !!! */ - /* Re-enable interrupts. */ - CSR_WRITE_4(sc, DC_IMR, DC_INTRS); - - if (ifp->if_snd.ifq_head != NULL) - dc_start(ifp); - } - -} - - -/* - * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data - * pointers to the fragment pointers. - */ -static int dc_encap(sc, m_head, txidx) - struct dc_softc *sc; - struct mbuf *m_head; - u_int32_t *txidx; -{ - struct dc_desc *f = NULL; - struct mbuf *m; - int frag, cur, cnt = 0; - - /* - * Start packing the mbufs in this chain into - * the fragment pointers. Stop when we run out - * of fragments or hit the end of the mbuf chain. - */ - m = m_head; - cur = frag = *txidx; - - for (m = m_head; m != NULL; m = m->m_next) { - if (m->m_len != 0) { - if (sc->dc_flags & DC_TX_ADMTEK_WAR) { - if (*txidx != sc->dc_cdata.dc_tx_prod && - frag == (DC_TX_LIST_CNT - 1)) - return(ENOBUFS); - } - if ((DC_TX_LIST_CNT - - (sc->dc_cdata.dc_tx_cnt + cnt)) < 5) - return(ENOBUFS); - - f = &sc->dc_ldata->dc_tx_list[frag]; - f->dc_ctl = DC_TXCTL_TLINK | m->m_len; - if (cnt == 0) { - f->dc_status = 0; - f->dc_ctl |= DC_TXCTL_FIRSTFRAG; - } else - f->dc_status = DC_TXSTAT_OWN; - f->dc_data = vtophys(mtod(m, vm_offset_t)); - cur = frag; - DC_INC(frag, DC_TX_LIST_CNT); - cnt++; - } - } - - if (m != NULL) - return(ENOBUFS); - - sc->dc_cdata.dc_tx_cnt += cnt; - sc->dc_cdata.dc_tx_chain[cur] = m_head; - sc->dc_ldata->dc_tx_list[cur].dc_ctl |= DC_TXCTL_LASTFRAG; - if (sc->dc_flags & DC_TX_INTR_FIRSTFRAG) - sc->dc_ldata->dc_tx_list[*txidx].dc_ctl |= DC_TXCTL_FINT; - if (sc->dc_flags & DC_TX_INTR_ALWAYS) - sc->dc_ldata->dc_tx_list[cur].dc_ctl |= DC_TXCTL_FINT; - if (sc->dc_flags & DC_TX_USE_TX_INTR && sc->dc_cdata.dc_tx_cnt > 64) - sc->dc_ldata->dc_tx_list[cur].dc_ctl |= DC_TXCTL_FINT; - sc->dc_ldata->dc_tx_list[*txidx].dc_status = DC_TXSTAT_OWN; - *txidx = frag; - - return(0); -} - -/* - * Coalesce an mbuf chain into a single mbuf cluster buffer. - * Needed for some really badly behaved chips that just can't - * do scatter/gather correctly. - */ -static int dc_coal(sc, m_head) - struct dc_softc *sc; - struct mbuf **m_head; -{ - struct mbuf *m_new, *m; - - m = *m_head; - MGETHDR(m_new, M_DONTWAIT, MT_DATA); - if (m_new == NULL) - return(ENOBUFS); - if (m->m_pkthdr.len > MHLEN) { - MCLGET(m_new, M_DONTWAIT); - if (!(m_new->m_flags & M_EXT)) { - m_freem(m_new); - return(ENOBUFS); - } - } - m_copydata(m, 0, m->m_pkthdr.len, mtod(m_new, caddr_t)); - m_new->m_pkthdr.len = m_new->m_len = m->m_pkthdr.len; - m_freem(m); - *m_head = m_new; - - return(0); -} - -/* - * Main transmit routine. To avoid having to do mbuf copies, we put pointers - * to the mbuf data regions directly in the transmit lists. We also save a - * copy of the pointers since the transmit list fragment pointers are - * physical addresses. - */ - -static void dc_start(ifp) - struct ifnet *ifp; -{ - struct dc_softc *sc; - struct mbuf *m_head = NULL; - u_int32_t idx; - - sc = ifp->if_softc; -#if 0 - if (!sc->dc_link && ifp->if_snd.ifq_len < 10) - return; -#endif - if (ifp->if_flags & IFF_OACTIVE) - return; - - idx = sc->dc_cdata.dc_tx_prod; - - while(sc->dc_cdata.dc_tx_chain[idx] == NULL) { - IF_DEQUEUE(&ifp->if_snd, m_head); - if (m_head == NULL) - break; - - if (sc->dc_flags & DC_TX_COALESCE && - m_head->m_next != NULL) { - /* only coalesce if have >1 mbufs */ - if (dc_coal(sc, &m_head)) { - IF_PREPEND(&ifp->if_snd, m_head); - ifp->if_flags |= IFF_OACTIVE; - break; - } - } - - if (dc_encap(sc, m_head, &idx)) { - IF_PREPEND(&ifp->if_snd, m_head); - ifp->if_flags |= IFF_OACTIVE; - break; - } -#if 0 - /* - * If there's a BPF listener, bounce a copy of this frame - * to him. - */ - if (ifp->if_bpf) - bpf_mtap(ifp, m_head); -#endif - if (sc->dc_flags & DC_TX_ONE) { - ifp->if_flags |= IFF_OACTIVE; - break; - } - } - - /* Transmit */ - sc->dc_cdata.dc_tx_prod = idx; - if (!(sc->dc_flags & DC_TX_POLL)) - CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF); - - /* - * Set a timeout in case the chip goes out to lunch. - */ - ifp->if_timer = 5; - - return; -} - -static void dc_init(xsc) - void *xsc; -{ - struct dc_softc *sc = xsc; - struct ifnet *ifp = &sc->arpcom.ac_if; - /*struct mii_data *mii;*/ - - - /*mii = device_get_softc(sc->dc_miibus);*/ - - /* - * Cancel pending I/O and free all RX/TX buffers. - */ - dc_stop(sc); - dc_reset(sc); - - /* - * Set cache alignment and burst length. - */ - if (DC_IS_ASIX(sc) || DC_IS_DAVICOM(sc)) - CSR_WRITE_4(sc, DC_BUSCTL, 0); - else - CSR_WRITE_4(sc, DC_BUSCTL, DC_BUSCTL_MRME|DC_BUSCTL_MRLE); - /* - * Evenly share the bus between receive and transmit process. - */ - if (DC_IS_INTEL(sc)) - DC_SETBIT(sc, DC_BUSCTL, DC_BUSCTL_ARBITRATION); - if (DC_IS_DAVICOM(sc) || DC_IS_INTEL(sc)) { - DC_SETBIT(sc, DC_BUSCTL, DC_BURSTLEN_USECA); - } else { - DC_SETBIT(sc, DC_BUSCTL, DC_BURSTLEN_16LONG); - } - if (sc->dc_flags & DC_TX_POLL) - DC_SETBIT(sc, DC_BUSCTL, DC_TXPOLL_1); - switch(sc->dc_cachesize) { - case 32: - DC_SETBIT(sc, DC_BUSCTL, DC_CACHEALIGN_32LONG); - break; - case 16: - DC_SETBIT(sc, DC_BUSCTL, DC_CACHEALIGN_16LONG); - break; - case 8: - DC_SETBIT(sc, DC_BUSCTL, DC_CACHEALIGN_8LONG); - break; - case 0: - default: - DC_SETBIT(sc, DC_BUSCTL, DC_CACHEALIGN_NONE); - break; - } - - if (sc->dc_flags & DC_TX_STORENFWD) - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD); - else { - if (sc->dc_txthresh > DC_TXTHRESH_MAX) { - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD); - } else { - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD); - DC_SETBIT(sc, DC_NETCFG, sc->dc_txthresh); - } - } - - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_NO_RXCRC); - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_BACKOFF); - - if (DC_IS_MACRONIX(sc) || DC_IS_PNICII(sc)) { - /* - * The app notes for the 98713 and 98715A say that - * in order to have the chips operate properly, a magic - * number must be written to CSR16. Macronix does not - * document the meaning of these bits so there's no way - * to know exactly what they do. The 98713 has a magic - * number all its own; the rest all use a different one. - */ - DC_CLRBIT(sc, DC_MX_MAGICPACKET, 0xFFFF0000); - if (sc->dc_type == DC_TYPE_98713) - DC_SETBIT(sc, DC_MX_MAGICPACKET, DC_MX_MAGIC_98713); - else - DC_SETBIT(sc, DC_MX_MAGICPACKET, DC_MX_MAGIC_98715); - } - - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_THRESH); - DC_SETBIT(sc, DC_NETCFG, DC_TXTHRESH_MIN); - - /* Init circular RX list. */ - if (dc_list_rx_init(sc) == ENOBUFS) { - printk("dc%d: initialization failed: no " - "memory for rx buffers\n", sc->dc_unit); - dc_stop(sc); - return; - } - - /* - * Init tx descriptors. - */ - dc_list_tx_init(sc); - - /* - * Load the address of the RX list. - */ - CSR_WRITE_4(sc, DC_RXADDR, vtophys(&sc->dc_ldata->dc_rx_list[0])); - CSR_WRITE_4(sc, DC_TXADDR, vtophys(&sc->dc_ldata->dc_tx_list[0])); - - /* - * Enable interrupts. - */ -#ifdef DEVICE_POLLING - /* - * ... but only if we are not polling, and make sure they are off in - * the case of polling. Some cards (e.g. fxp) turn interrupts on - * after a reset. - */ - if (ifp->if_ipending & IFF_POLLING) - CSR_WRITE_4(sc, DC_IMR, 0x00000000); - else -#endif - /* Enable interrupts */ - CSR_WRITE_4(sc, DC_IMR, DC_INTRS); - CSR_WRITE_4(sc, DC_ISR, 0xFFFFFFFF); - - /* Enable transmitter. */ - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON); - - /* - * If this is an Intel 21143 and we're not using the - * MII port, program the LED control pins so we get - * link and activity indications. - */ - if (sc->dc_flags & DC_TULIP_LEDS) { - CSR_WRITE_4(sc, DC_WATCHDOG, - DC_WDOG_CTLWREN|DC_WDOG_LINK|DC_WDOG_ACTIVITY); - CSR_WRITE_4(sc, DC_WATCHDOG, 0); - } - - /* - * Load the RX/multicast filter. We do this sort of late - * because the filter programming scheme on the 21143 and - * some clones requires DMAing a setup frame via the TX - * engine, and we need the transmitter enabled for that. - */ - dc_setfilt(sc); - - /* Enable receiver. */ - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ON); - CSR_WRITE_4(sc, DC_RXSTART, 0xFFFFFFFF); - - /*mii_mediachg(mii);*/ - dc_setcfg(sc, sc->dc_if_media); - - ifp->if_flags |= IFF_RUNNING; - ifp->if_flags &= ~IFF_OACTIVE; - - -#if 0 - - /* Don't start the ticker if this is a homePNA link. */ - if (IFM_SUBTYPE(mii->mii_media.ifm_media) == IFM_homePNA) - sc->dc_link = 1; - else { - if (sc->dc_flags & DC_21143_NWAY) - sc->dc_stat_ch = timeout(dc_tick, sc, hz/10); - else - sc->dc_stat_ch = timeout(dc_tick, sc, hz); - } - -#ifdef SRM_MEDIA - if(sc->dc_srm_media) { - struct ifreq ifr; - - ifr.ifr_media = sc->dc_srm_media; - ifmedia_ioctl(ifp, &ifr, &mii->mii_media, SIOCSIFMEDIA); - sc->dc_srm_media = 0; - } -#endif -#endif /* end if (0) */ - return; -} - - -#if 0 -/* - * Set media options. - */ -static int dc_ifmedia_upd(ifp) - struct ifnet *ifp; -{ - struct dc_softc *sc; - struct mii_data *mii; - struct ifmedia *ifm; - - sc = ifp->if_softc; - mii = device_get_softc(sc->dc_miibus); - mii_mediachg(mii); - ifm = &mii->mii_media; - - if (DC_IS_DAVICOM(sc) && - IFM_SUBTYPE(ifm->ifm_media) == IFM_homePNA) - dc_setcfg(sc, ifm->ifm_media); - else - sc->dc_link = 0; - - return(0); -} - -/* - * Report current media status. - */ -static void dc_ifmedia_sts(ifp, ifmr) - struct ifnet *ifp; - struct ifmediareq *ifmr; -{ - struct dc_softc *sc; - struct mii_data *mii; - struct ifmedia *ifm; - - sc = ifp->if_softc; - mii = device_get_softc(sc->dc_miibus); - mii_pollstat(mii); - ifm = &mii->mii_media; - if (DC_IS_DAVICOM(sc)) { - if (IFM_SUBTYPE(ifm->ifm_media) == IFM_homePNA) { - ifmr->ifm_active = ifm->ifm_media; - ifmr->ifm_status = 0; - return; - } - } - ifmr->ifm_active = mii->mii_media_active; - ifmr->ifm_status = mii->mii_media_status; - - return; -} -#endif - - -static int dc_ioctl(ifp, command, data) - struct ifnet *ifp; - ioctl_command_t command; - caddr_t data; -{ - struct dc_softc *sc = ifp->if_softc; - /*struct ifreq *ifr = (struct ifreq *) data; - struct mii_data *mii;*/ - int error = 0; - - - switch(command) { - case SIOCSIFADDR: - case SIOCGIFADDR: - case SIOCSIFMTU: - error = ether_ioctl(ifp, command, data); - break; - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - int need_setfilt = (ifp->if_flags ^ sc->dc_if_flags) & - (IFF_PROMISC | IFF_ALLMULTI); - if (ifp->if_flags & IFF_RUNNING) { - if (need_setfilt) - dc_setfilt(sc); - } else { - sc->dc_txthresh = 0; - dc_init(sc); - } - } else { - if (ifp->if_flags & IFF_RUNNING) - dc_stop(sc); - } - sc->dc_if_flags = ifp->if_flags; - error = 0; - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - dc_setfilt(sc); - error = 0; - break; -#if 0 - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - mii = device_get_softc(sc->dc_miibus); - error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); -#ifdef SRM_MEDIA - if (sc->dc_srm_media) - sc->dc_srm_media = 0; -#endif - break; -#endif - default: - error = EINVAL; - break; - } - - - return(error); -} - -static void dc_watchdog(ifp) - struct ifnet *ifp; -{ - struct dc_softc *sc; - - sc = ifp->if_softc; - - ifp->if_oerrors++; - printk("dc%d: watchdog timeout\n", sc->dc_unit); - - dc_stop(sc); - dc_reset(sc); - dc_init(sc); - - if (ifp->if_snd.ifq_head != NULL) - dc_start(ifp); - - return; -} - -/* - * Stop the adapter and free any mbufs allocated to the - * RX and TX lists. - */ -static void dc_stop(sc) - struct dc_softc *sc; -{ - register int i; - struct ifnet *ifp; - - ifp = &sc->arpcom.ac_if; - ifp->if_timer = 0; - - /*untimeout(dc_tick, sc, sc->dc_stat_ch);*/ - - ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); -#ifdef DEVICE_POLLING - ether_poll_deregister(ifp); -#endif - - DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ON|DC_NETCFG_TX_ON)); - CSR_WRITE_4(sc, DC_IMR, 0x00000000); - CSR_WRITE_4(sc, DC_TXADDR, 0x00000000); - CSR_WRITE_4(sc, DC_RXADDR, 0x00000000); - sc->dc_link = 0; - - /* - * Free data in the RX lists. - */ - for (i = 0; i < DC_RX_LIST_CNT; i++) { - if (sc->dc_cdata.dc_rx_chain[i] != NULL) { - m_freem(sc->dc_cdata.dc_rx_chain[i]); - sc->dc_cdata.dc_rx_chain[i] = NULL; - } - } - bzero((char *)&sc->dc_ldata->dc_rx_list, - sizeof(sc->dc_ldata->dc_rx_list)); - - /* - * Free the TX list buffers. - */ - for (i = 0; i < DC_TX_LIST_CNT; i++) { - if (sc->dc_cdata.dc_tx_chain[i] != NULL) { - if (sc->dc_ldata->dc_tx_list[i].dc_ctl & - DC_TXCTL_SETUP) { - sc->dc_cdata.dc_tx_chain[i] = NULL; - continue; - } - m_freem(sc->dc_cdata.dc_tx_chain[i]); - sc->dc_cdata.dc_tx_chain[i] = NULL; - } - } - - bzero((char *)&sc->dc_ldata->dc_tx_list, - sizeof(sc->dc_ldata->dc_tx_list)); - - return; -} - - -#if 0 -/* - * Stop all chip I/O so that the kernel's probe routines don't - * get confused by errant DMAs when rebooting. - */ -static void dc_shutdown(dev) - device_t dev; -{ - struct dc_softc *sc; - - sc = device_get_softc(dev); - - dc_stop(sc); - - return; -} - -/* - * Device suspend routine. Stop the interface and save some PCI - * settings in case the BIOS doesn't restore them properly on - * resume. - */ -static int dc_suspend(dev) - device_t dev; -{ - register int i; - int s; - struct dc_softc *sc; - - - sc = device_get_softc(dev); - - dc_stop(sc); - - for (i = 0; i < 5; i++) - sc->saved_maps[i] = pci_read_config(dev, PCIR_MAPS + i * 4, 4); - sc->saved_biosaddr = pci_read_config(dev, PCIR_BIOS, 4); - sc->saved_intline = pci_read_config(dev, PCIR_INTLINE, 1); - sc->saved_cachelnsz = pci_read_config(dev, PCIR_CACHELNSZ, 1); - sc->saved_lattimer = pci_read_config(dev, PCIR_LATTIMER, 1); - - sc->suspended = 1; - - return (0); -} - -/* - * Device resume routine. Restore some PCI settings in case the BIOS - * doesn't, re-enable busmastering, and restart the interface if - * appropriate. - */ -static int dc_resume(dev) - device_t dev; -{ - register int i; - int s; - struct dc_softc *sc; - struct ifnet *ifp; - - - sc = device_get_softc(dev); - ifp = &sc->arpcom.ac_if; - - dc_acpi(dev); - - /* better way to do this? */ - for (i = 0; i < 5; i++) - pci_write_config(dev, PCIR_MAPS + i * 4, sc->saved_maps[i], 4); - pci_write_config(dev, PCIR_BIOS, sc->saved_biosaddr, 4); - pci_write_config(dev, PCIR_INTLINE, sc->saved_intline, 1); - pci_write_config(dev, PCIR_CACHELNSZ, sc->saved_cachelnsz, 1); - pci_write_config(dev, PCIR_LATTIMER, sc->saved_lattimer, 1); - - /* reenable busmastering */ - pci_enable_busmaster(dev); - pci_enable_io(dev, DC_RES); - - /* reinitialize interface if necessary */ - if (ifp->if_flags & IFF_UP) - dc_init(sc); - - sc->suspended = 0; - - return (0); -} -#endif - -#endif /* end if supported */ diff --git a/c/src/libchip/network/if_fxp.c b/c/src/libchip/network/if_fxp.c deleted file mode 100644 index 2fe9a5c403..0000000000 --- a/c/src/libchip/network/if_fxp.c +++ /dev/null @@ -1,2339 +0,0 @@ -/*- - * Copyright (c) 1995, David Greenman - * Copyright (c) 2001 Jonathan Lemon - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice unmodified, this list of conditions, and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/fxp/if_fxp.c,v 1.118 2001/09/05 23:33:58 brooks Exp $ - */ - -/* - * Intel EtherExpress Pro/100B PCI Fast Ethernet driver - */ - -/* - * RTEMS Revision Preliminary History - * - * July XXX, 2002 W. Eric Norum - * Placed in RTEMS CVS repository. All further modifications will be - * noted in the CVS log and not in this comment. - * - * July 11, 2002 W. Eric Norum - * Minor modifications to get driver working with NIC on VersaLogic - * Bobcat PC-104 single-board computer. The Bobcat has no video - * driver so printf/printk calls are directed to COM2:. This - * arrangement seems to require delays after the printk calls or - * else things lock up. Perhaps the RTEMS pc386 console code - * should be modified to insert these delays itself. - * - * June 27, 2002 W. Eric Norum - * Obtained from Thomas Doerfler . - * A big thank-you to Thomas for making this available. - * - * October 01, 2001 Thomas Doerfler - * Original RTEMS modifications. - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#if defined(__i386__) - -/*#define DEBUG_OUT 0*/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef NS -#include -#include -#endif - -#include - -#include /* for vtophys */ - -#include - -#include "if_fxpreg.h" -#include - -/* - * some adaptation replacements for RTEMS - */ -static rtems_interval fxp_ticksPerSecond; -#define device_printf(device,format,args...) printk(format,## args) -#define DELAY(n) rtems_task_wake_after(((n)*fxp_ticksPerSecond/1000000)+1) -#ifdef DEBUG_OUT -#define DBGLVL_PRINTK(LVL,format, args...) \ -if (DEBUG_OUT >= (LVL)) { \ - printk(format, ## args); \ -} -#else -#define DBGLVL_PRINTK(LVL,format, args...) -#endif - -/* - * RTEMS event used by interrupt handler to signal driver tasks. - * This must not be any of the events used by the network task synchronization. - */ -#define INTERRUPT_EVENT RTEMS_EVENT_1 - -/* - * remapping between PCI device and CPU memmory address view... - */ -#if defined(__i386) -#define vtophys(p) (u_int32_t)(p) -#else -#define vtophys(p) vtophys(p) -#endif - -#define NFXPDRIVER 1 -static struct fxp_softc fxp_softc[NFXPDRIVER]; -static bool fxp_is_verbose = true; -/* - * NOTE! On the Alpha, we have an alignment constraint. The - * card DMAs the packet immediately following the RFA. However, - * the first thing in the packet is a 14-byte Ethernet header. - * This means that the packet is misaligned. To compensate, - * we actually offset the RFA 2 bytes into the cluster. This - * alignes the packet after the Ethernet header at a 32-bit - * boundary. HOWEVER! This means that the RFA is misaligned! - */ -#define RFA_ALIGNMENT_FUDGE 2 - -/* - * Set initial transmit threshold at 64 (512 bytes). This is - * increased by 64 (512 bytes) at a time, to maximum of 192 - * (1536 bytes), if an underrun occurs. - */ -static int tx_threshold = 64; - -/* - * The configuration byte map has several undefined fields which - * must be one or must be zero. Set up a template for these bits - * only, (assuming a 82557 chip) leaving the actual configuration - * to fxp_init. - * - * See struct fxp_cb_config for the bit definitions. - */ -static u_char fxp_cb_config_template[] = { - 0x0, 0x0, /* cb_status */ - 0x0, 0x0, /* cb_command */ - 0x0, 0x0, 0x0, 0x0, /* link_addr */ - 0x0, /* 0 */ - 0x0, /* 1 */ - 0x0, /* 2 */ - 0x0, /* 3 */ - 0x0, /* 4 */ - 0x0, /* 5 */ - 0x32, /* 6 */ - 0x0, /* 7 */ - 0x0, /* 8 */ - 0x0, /* 9 */ - 0x6, /* 10 */ - 0x0, /* 11 */ - 0x0, /* 12 */ - 0x0, /* 13 */ - 0xf2, /* 14 */ - 0x48, /* 15 */ - 0x0, /* 16 */ - 0x40, /* 17 */ - 0xf0, /* 18 */ - 0x0, /* 19 */ - 0x3f, /* 20 */ - 0x5 /* 21 */ -}; - -struct fxp_ident { - u_int16_t devid; - char *name; - int warn; -}; - -#define UNTESTED 1 - -/* - * Claim various Intel PCI device identifiers for this driver. The - * sub-vendor and sub-device field are extensively used to identify - * particular variants, but we don't currently differentiate between - * them. - */ -static struct fxp_ident fxp_ident_table[] = { - { 0x1229, "Intel Pro 10/100B/100+ Ethernet", 0 }, - { 0x2449, "Intel Pro/100 Ethernet", UNTESTED }, - { 0x1209, "Intel Embedded 10/100 Ethernet", 0 }, - { 0x1029, "Intel Pro/100 Ethernet", UNTESTED }, - { 0x1030, "Intel Pro/100 Ethernet", 0 }, - { 0x1031, "Intel Pro/100 Ethernet", UNTESTED }, - { 0x1032, "Intel Pro/100 Ethernet", UNTESTED }, - { 0x1033, "Intel Pro/100 Ethernet", UNTESTED }, - { 0x1034, "Intel Pro/100 Ethernet", UNTESTED }, - { 0x1035, "Intel Pro/100 Ethernet", UNTESTED }, - { 0x1036, "Intel Pro/100 Ethernet", UNTESTED }, - { 0x1037, "Intel Pro/100 Ethernet", UNTESTED }, - { 0x1038, "Intel Pro/100 Ethernet", UNTESTED }, - { 0x103B, "Intel Pro/100 Ethernet (82801BD PRO/100 VM (LOM))", 0 }, - { 0, NULL, 0 } -}; - -#if 0 -static int fxp_probe(device_t dev); -static int fxp_attach(device_t dev); -static int fxp_detach(device_t dev); -static int fxp_shutdown(device_t dev); -#endif -int fxp_output (struct ifnet *, - struct mbuf *, struct sockaddr *, struct rtentry *); - - -static void fxp_intr(void *arg); -static void fxp_init(void *xsc); -static void fxp_tick(void *xsc); -static void fxp_start(struct ifnet *ifp); -static void fxp_stop(struct fxp_softc *sc); -static void fxp_release(struct fxp_softc *sc); -static int fxp_ioctl(struct ifnet *ifp, ioctl_command_t command, - caddr_t data); -static void fxp_watchdog(struct ifnet *ifp); -static int fxp_add_rfabuf(struct fxp_softc *sc, struct mbuf *oldm); -static void fxp_mc_setup(struct fxp_softc *sc); -static u_int16_t fxp_eeprom_getword(struct fxp_softc *sc, int offset, - int autosize); -static void fxp_eeprom_putword(struct fxp_softc *sc, int offset, - u_int16_t data); -static void fxp_autosize_eeprom(struct fxp_softc *sc); -static void fxp_read_eeprom(struct fxp_softc *sc, u_short *data, - int offset, int words); -static void fxp_write_eeprom(struct fxp_softc *sc, u_short *data, - int offset, int words); -#ifdef NOTUSED -static int fxp_ifmedia_upd(struct ifnet *ifp); -static void fxp_ifmedia_sts(struct ifnet *ifp, - struct ifmediareq *ifmr); -static int fxp_serial_ifmedia_upd(struct ifnet *ifp); -static void fxp_serial_ifmedia_sts(struct ifnet *ifp, - struct ifmediareq *ifmr); -static volatile int fxp_miibus_readreg(device_t dev, int phy, int reg); -static void fxp_miibus_writereg(device_t dev, int phy, int reg, - int value); -#endif -static __inline void fxp_lwcopy(volatile u_int32_t *src, - volatile u_int32_t *dst); -static __inline void fxp_scb_wait(struct fxp_softc *sc); -static __inline void fxp_scb_cmd(struct fxp_softc *sc, int cmd); -static __inline void fxp_dma_wait(volatile u_int16_t *status, - struct fxp_softc *sc); - -/* - * Inline function to copy a 16-bit aligned 32-bit quantity. - */ -static __inline void -fxp_lwcopy(volatile u_int32_t *src, volatile u_int32_t *dst) -{ -#ifdef __i386__ - *dst = *src; -#else - volatile u_int16_t *a = (volatile u_int16_t*)src; - volatile u_int16_t *b = (volatile u_int16_t*)dst; - - b[0] = a[0]; - b[1] = a[1]; -#endif -} - -/* - * inline access functions to pci space registers - */ -static __inline u_int8_t fxp_csr_read_1(struct fxp_softc *sc,int reg) { - u_int8_t val; - if (sc->pci_regs_are_io) { - inport_byte(sc->pci_regs_base + reg,val); - } - else { - val = *(volatile u_int8_t*)(sc->pci_regs_base+reg); - } - return val; -} -static __inline u_int32_t fxp_csr_read_2(struct fxp_softc *sc,int reg) { - u_int16_t val; - if (sc->pci_regs_are_io) { - inport_word(sc->pci_regs_base + reg,val); - } - else { - val = *(volatile u_int16_t*)(sc->pci_regs_base+reg); - } - return val; -} -static __inline u_int32_t fxp_csr_read_4(struct fxp_softc *sc,int reg) { - u_int32_t val; - if (sc->pci_regs_are_io) { - inport_long(sc->pci_regs_base + reg,val); - } - else { - val = *(volatile u_int32_t*)(sc->pci_regs_base+reg); - } - return val; -} - -/* - * Wait for the previous command to be accepted (but not necessarily - * completed). - */ -static __inline void -fxp_scb_wait(struct fxp_softc *sc) -{ - int i = 10000; - - while (CSR_READ_1(sc, FXP_CSR_SCB_COMMAND) && --i) - DELAY(2); - if (i == 0) - device_printf(sc->dev, "SCB timeout: 0x%d 0x%d" - "0x%d" PRIx32 "0x%" PRIx32 "\n", - CSR_READ_1(sc, FXP_CSR_SCB_COMMAND), - CSR_READ_1(sc, FXP_CSR_SCB_STATACK), - CSR_READ_1(sc, FXP_CSR_SCB_RUSCUS), - CSR_READ_2(sc, FXP_CSR_FLOWCONTROL)); -} - -static __inline void -fxp_scb_cmd(struct fxp_softc *sc, int cmd) -{ - - if (cmd == FXP_SCB_COMMAND_CU_RESUME && sc->cu_resume_bug) { - CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_CB_COMMAND_NOP); - fxp_scb_wait(sc); - } - CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, cmd); -} - -static __inline void -fxp_dma_wait(volatile u_int16_t *status, struct fxp_softc *sc) -{ - int i = 10000; - - while (!(*status & FXP_CB_STATUS_C) && --i) - DELAY(2); - if (i == 0) - device_printf(sc->dev, "DMA timeout\n"); -} - - -#define FXP_PCI_CONF_ACCESSOR(_confop, _baseop, _type) \ - \ - static inline int _confop ( \ - struct fxp_softc *sc, \ - int offset, \ - _type data ) \ - { \ - _baseop( \ - sc->pci_bus, \ - sc->pci_dev, \ - sc->pci_fun, \ - offset, \ - data \ - ); \ - return PCIB_ERR_SUCCESS; \ - } - -FXP_PCI_CONF_ACCESSOR( fxp_pci_conf_read8, pci_read_config_byte, uint8_t * ); -FXP_PCI_CONF_ACCESSOR( fxp_pci_conf_read16, pci_read_config_word, uint16_t * ); -FXP_PCI_CONF_ACCESSOR( fxp_pci_conf_read32, pci_read_config_dword, uint32_t * ); -FXP_PCI_CONF_ACCESSOR( fxp_pci_conf_write8, pci_write_config_byte, uint8_t ); -FXP_PCI_CONF_ACCESSOR( fxp_pci_conf_write16, pci_write_config_word, uint16_t ); -FXP_PCI_CONF_ACCESSOR( fxp_pci_conf_write32, pci_write_config_dword, uint32_t ); - -static __inline unsigned int fxp_pci_get_vendor(struct fxp_softc *sc) { - u_int16_t vendor; - fxp_pci_conf_read16(sc, PCI_VENDOR_ID, &vendor); - return vendor; -} - -static __inline unsigned int fxp_pci_get_device(struct fxp_softc *sc) { - u_int16_t device; - fxp_pci_conf_read16(sc, PCI_DEVICE_ID, &device); - return device; -} - -static __inline unsigned int fxp_pci_get_subvendor(struct fxp_softc *sc) { - u_int16_t subvendor; - fxp_pci_conf_read16(sc, PCI_SUBSYSTEM_VENDOR_ID, &subvendor); - return subvendor; -} - -static __inline unsigned int fxp_pci_get_subdevice(struct fxp_softc *sc) { - u_int16_t subdevice; - fxp_pci_conf_read16(sc, PCI_SUBSYSTEM_ID, &subdevice); - return subdevice; -} - -static __inline unsigned int fxp_pci_get_revid(struct fxp_softc *sc) { - u_int8_t revid; - fxp_pci_conf_read8(sc, PCI_REVISION_ID, &revid); - return revid; -} - -/* Prototype to avoid warning. This must be a global symbol. */ -int rtems_fxp_attach(struct rtems_bsdnet_ifconfig *config, int attaching); - -int -rtems_fxp_attach(struct rtems_bsdnet_ifconfig *config, int attaching) -{ - int error = 0; - struct fxp_softc *sc; - struct ifnet *ifp; - uint16_t val16; - uint32_t val32; - uint16_t data; - int i; - int s; - int unitNumber; - char *unitName; - u_int16_t dev_id; - u_int8_t interrupt; - int mtu; - - /* - * Set up some timing values - */ - fxp_ticksPerSecond = rtems_clock_get_ticks_per_second(); - DBGLVL_PRINTK(1,"fxp_attach called\n"); - - /* - * Parse driver name - */ - if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0) - return 0; - - /* - * Is driver free? - */ - if ((unitNumber <= 0) || (unitNumber > NFXPDRIVER)) { - device_printf(dev,"Bad FXP unit number.\n"); - return 0; - } - sc = &fxp_softc[unitNumber - 1]; - ifp = &sc->arpcom.ac_if; - if (ifp->if_softc != NULL) { - device_printf(dev,"FXP Driver already in use.\n"); - return 0; - } - - memset(sc, 0, sizeof(*sc)); -#ifdef NOTUSED - sc->dev = dev; - callout_handle_init(&sc->stat_ch); - mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_DEF | MTX_RECURSE); -#endif - s = splimp(); - - /* - * find device on pci bus - */ - { int j; int pbus, pdev, pfun; - - for (j=0; fxp_ident_table[j].devid; j++ ) { - i = pci_find_device( 0x8086, fxp_ident_table[j].devid, - unitNumber-1, &pbus, &pdev, &pfun ); - sc->pci_bus = pbus; - sc->pci_dev = pdev; - sc->pci_fun = pfun; - DBGLVL_PRINTK(2,"fxp_attach: find_devid returned %d ," - "pci bus %d dev %d fun %d \n", - i, sc->pci_bus, sc->pci_dev, sc->pci_fun); - if (PCIB_ERR_SUCCESS == i) { - if ( UNTESTED == fxp_ident_table[j].warn ) { - device_printf(dev, -"WARNING: this chip version has NOT been reported to work under RTEMS yet.\n"); - device_printf(dev, -" If it works OK, report it as tested in 'c/src/libchip/network/if_fxp.c'\n"); - } - break; - } - } - } - - /* - * FIXME: add search for more device types... - */ - if (i != PCIB_ERR_SUCCESS) { - device_printf(dev, "could not find 82559ER device\n"); - return 0; - } - - - /* - * Enable bus mastering. Enable memory space too, in case - * BIOS/Prom forgot about it. - */ - fxp_pci_conf_read16(sc, PCI_COMMAND,&val16); - val16 |= (PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER); - fxp_pci_conf_write16(sc, PCI_COMMAND, val16); - DBGLVL_PRINTK(3,"fxp_attach: PCI_COMMAND_write = 0x%x\n",val16); - fxp_pci_conf_read16(sc, PCI_COMMAND,&val16); - DBGLVL_PRINTK(4,"fxp_attach: PCI_COMMAND_read = 0x%x\n",val16); - - /* - * Figure out which we should try first - memory mapping or i/o mapping? - * We default to memory mapping. Then we accept an override from the - * command line. Then we check to see which one is enabled. - */ -#ifdef NOTUSED - m1 = PCI_COMMAND_MEMORY; - m2 = PCI_COMMAND_IO; - prefer_iomap = 0; - if (resource_int_value(device_get_name(dev), device_get_unit(dev), - "prefer_iomap", &prefer_iomap) == 0 && prefer_iomap != 0) { - m1 = PCI_COMMAND_IO; - m2 = PCI_COMMAND_MEMORY; - } - - if (val & m1) { - sc->rtp = ((m1 == PCI_COMMAND_MEMORY) - ? SYS_RES_MEMORY : SYS_RES_IOPORT); - sc->rgd = ((m1 == PCI_COMMAND_MEMORY) - ? FXP_PCI_MMBA : FXP_PCI_IOBA); - sc->mem = bus_alloc_resource(dev, sc->rtp, &sc->rgd, - 0, ~0, 1, RF_ACTIVE); - } - if (sc->mem == NULL && (val & m2)) { - sc->rtp = ((m2 == PCI_COMMAND_MEMORY) - ? SYS_RES_MEMORY : SYS_RES_IOPORT); - sc->rgd = ((m2 == PCI_COMMAND_MEMORY) - ? FXP_PCI_MMBA : FXP_PCI_IOBA); - sc->mem = bus_alloc_resource(dev, sc->rtp, &sc->rgd, - 0, ~0, 1, RF_ACTIVE); - } - - if (!sc->mem) { - device_printf(dev, "could not map device registers\n"); - error = ENXIO; - goto fail; - } - if (fxp_is_verbose) { - device_printf(dev, "using %s space register mapping\n", - sc->rtp == SYS_RES_MEMORY? "memory" : "I/O"); - } - - sc->sc_st = rman_get_bustag(sc->mem); - sc->sc_sh = rman_get_bushandle(sc->mem); - - /* - * Allocate our interrupt. - */ - rid = 0; - sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, - RF_SHAREABLE | RF_ACTIVE); - if (sc->irq == NULL) { - device_printf(dev, "could not map interrupt\n"); - error = ENXIO; - goto fail; - } - - error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, - fxp_intr, sc, &sc->ih); - if (error) { - device_printf(dev, "could not setup irq\n"); - goto fail; - } -#endif - - /* - * get mapping and base address of registers - */ - fxp_pci_conf_read16(sc, PCI_COMMAND,&val16); - DBGLVL_PRINTK(4,"fxp_attach: PCI_COMMAND_read = 0x%x\n",val16); - if((val16 & PCI_COMMAND_IO) != 0) { - sc->pci_regs_are_io = true; - fxp_pci_conf_read32(sc, PCI_BASE_ADDRESS_1, &val32); - sc->pci_regs_base = val32 & PCI_BASE_ADDRESS_IO_MASK; - } - else { - sc->pci_regs_are_io = false; - fxp_pci_conf_read32(sc, PCI_BASE_ADDRESS_0, &val32); - sc->pci_regs_base = val32 & PCI_BASE_ADDRESS_MEM_MASK; - } - DBGLVL_PRINTK(3,"fxp_attach: CSR registers are mapped in %s space" - " at address 0x%x\n", - sc->pci_regs_are_io ? "I/O" : "MEM", - sc->pci_regs_base); - - /* - * get interrupt level to be used - */ - fxp_pci_conf_read8(sc, PCI_INTERRUPT_LINE, &interrupt); - DBGLVL_PRINTK(3,"fxp_attach: interrupt = 0x%x\n",interrupt); - sc->irq_num = interrupt; - /* - * Reset to a stable state. - CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET); - */ - CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SOFTWARE_RESET); - DELAY(10); - - sc->cbl_base = malloc(sizeof(struct fxp_cb_tx) * FXP_NTXCB, - M_DEVBUF, M_NOWAIT); - DBGLVL_PRINTK(3,"fxp_attach: sc->cbl_base = 0x%x\n",sc->cbl_base); - if (sc->cbl_base == NULL) - goto failmem; - else - memset(sc->cbl_base, 0, sizeof(struct fxp_cb_tx) * FXP_NTXCB); - - sc->fxp_stats = malloc(sizeof(struct fxp_stats), M_DEVBUF, - M_NOWAIT); - DBGLVL_PRINTK(3,"fxp_attach: sc->fxp_stats = 0x%x\n",sc->fxp_stats); - if (sc->fxp_stats == NULL) - goto failmem; - else - memset(sc->fxp_stats, 0, sizeof(struct fxp_stats)); - - sc->mcsp = malloc(sizeof(struct fxp_cb_mcs), M_DEVBUF, M_NOWAIT); - DBGLVL_PRINTK(3,"fxp_attach: sc->mcsp = 0x%x\n",sc->mcsp); - if (sc->mcsp == NULL) - goto failmem; - - /* - * Pre-allocate our receive buffers. - */ - for (i = 0; i < FXP_NRFABUFS; i++) { - if (fxp_add_rfabuf(sc, NULL) != 0) { - goto failmem; - } - } - - /* - * Find out how large of an SEEPROM we have. - */ - DBGLVL_PRINTK(3,"fxp_attach: calling fxp_autosize_eeprom\n"); - fxp_autosize_eeprom(sc); - - /* - * Determine whether we must use the 503 serial interface. - */ - fxp_read_eeprom(sc, &data, 6, 1); - if ((data & FXP_PHY_DEVICE_MASK) != 0 && - (data & FXP_PHY_SERIAL_ONLY)) - sc->flags |= FXP_FLAG_SERIAL_MEDIA; - - /* - * Find out the basic controller type; we currently only - * differentiate between a 82557 and greater. - */ - fxp_read_eeprom(sc, &data, 5, 1); - if ((data >> 8) == 1) - sc->chip = FXP_CHIP_82557; - DBGLVL_PRINTK(3,"fxp_attach: sc->chip = %d\n",sc->chip); - - /* - * Enable workarounds for certain chip revision deficiencies. - * - * Systems based on the ICH2/ICH2-M chip from Intel have a defect - * where the chip can cause a PCI protocol violation if it receives - * a CU_RESUME command when it is entering the IDLE state. The - * workaround is to disable Dynamic Standby Mode, so the chip never - * deasserts CLKRUN#, and always remains in an active state. - * - * See Intel 82801BA/82801BAM Specification Update, Errata #30. - */ -#ifdef NOTUSED - i = fxp_pci_get_device(dev); -#else - fxp_pci_conf_read16(sc, PCI_DEVICE_ID, &dev_id); - DBGLVL_PRINTK(3,"fxp_attach: device id = 0x%x\n",dev_id); -#endif - if (dev_id == 0x2449 || (dev_id > 0x1030 && dev_id < 0x1039)) { - device_printf(dev, "*** See Intel 82801BA/82801BAM Specification Update, Errata #30. ***\n"); - fxp_read_eeprom(sc, &data, 10, 1); - if (data & 0x02) { /* STB enable */ - u_int16_t cksum; - int i; - - device_printf(dev, - "*** DISABLING DYNAMIC STANDBY MODE IN EEPROM ***\n"); - data &= ~0x02; - fxp_write_eeprom(sc, &data, 10, 1); - device_printf(dev, "New EEPROM ID: 0x%x\n", data); - cksum = 0; - for (i = 0; i < (1 << sc->eeprom_size) - 1; i++) { - fxp_read_eeprom(sc, &data, i, 1); - cksum += data; - } - i = (1 << sc->eeprom_size) - 1; - cksum = 0xBABA - cksum; - fxp_read_eeprom(sc, &data, i, 1); - fxp_write_eeprom(sc, &cksum, i, 1); - device_printf(dev, - "EEPROM checksum @ 0x%x: 0x%x -> 0x%x\n", - i, data, cksum); - /* - * We need to do a full PCI reset here. A software - * reset to the port doesn't cut it, but let's try - * anyway. - */ - CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SOFTWARE_RESET); - DELAY(50); - device_printf(dev, - "*** PLEASE REBOOT THE SYSTEM NOW FOR CORRECT OPERATION ***\n"); -#if 1 - /* - * If the user elects to continue, try the software - * workaround, as it is better than nothing. - */ - sc->flags |= FXP_FLAG_CU_RESUME_BUG; -#endif - } - } - - /* - * If we are not a 82557 chip, we can enable extended features. - */ - if (sc->chip != FXP_CHIP_82557) { - u_int8_t tmp_val; - /* - * If MWI is enabled in the PCI configuration, and there - * is a valid cacheline size (8 or 16 dwords), then tell - * the board to turn on MWI. - */ - fxp_pci_conf_read8(sc, PCI_CACHE_LINE_SIZE, &tmp_val); - DBGLVL_PRINTK(3,"fxp_attach: CACHE_LINE_SIZE = %d\n",tmp_val); - if (val16 & PCI_COMMAND_MEMORY && - tmp_val != 0) - sc->flags |= FXP_FLAG_MWI_ENABLE; - - /* turn on the extended TxCB feature */ - sc->flags |= FXP_FLAG_EXT_TXCB; - - /* enable reception of long frames for VLAN */ - sc->flags |= FXP_FLAG_LONG_PKT_EN; - DBGLVL_PRINTK(3,"fxp_attach: sc->flags = 0x%x\n", - sc->flags); - } - - /* - * Read MAC address. - */ - fxp_read_eeprom(sc, (u_int16_t*)sc->arpcom.ac_enaddr, 0, 3); - if (fxp_is_verbose) { - device_printf(dev, "Ethernet address %x:%x:%x:%x:%x:%x %s \n", - ((u_int8_t*)sc->arpcom.ac_enaddr)[0], - ((u_int8_t*)sc->arpcom.ac_enaddr)[1], - ((u_int8_t*)sc->arpcom.ac_enaddr)[2], - ((u_int8_t*)sc->arpcom.ac_enaddr)[3], - ((u_int8_t*)sc->arpcom.ac_enaddr)[4], - ((u_int8_t*)sc->arpcom.ac_enaddr)[5], - sc->flags & FXP_FLAG_SERIAL_MEDIA ? ", 10Mbps" : ""); - device_printf(dev, "PCI IDs: 0x%x 0x%x 0x%x 0x%x 0x%x\n", - fxp_pci_get_vendor(sc), fxp_pci_get_device(sc), - fxp_pci_get_subvendor(sc), fxp_pci_get_subdevice(sc), - fxp_pci_get_revid(sc)); - device_printf(dev, "Chip Type: %d\n", sc->chip); - } - -#ifdef NOTUSED /* do not set up interface at all... */ - /* - * If this is only a 10Mbps device, then there is no MII, and - * the PHY will use a serial interface instead. - * - * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter - * doesn't have a programming interface of any sort. The - * media is sensed automatically based on how the link partner - * is configured. This is, in essence, manual configuration. - */ - if (sc->flags & FXP_FLAG_SERIAL_MEDIA) { - ifmedia_init(&sc->sc_media, 0, fxp_serial_ifmedia_upd, - fxp_serial_ifmedia_sts); - ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL); - ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL); - } else { - if (mii_phy_probe(dev, &sc->miibus, fxp_ifmedia_upd, - fxp_ifmedia_sts)) { - device_printf(dev, "MII without any PHY!\n"); - error = ENXIO; - goto fail; - } - } -#endif - if (config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - - ifp->if_softc = sc; - ifp->if_unit = unitNumber; - ifp->if_name = unitName; - ifp->if_mtu = mtu; - ifp->if_baudrate = 100000000; - ifp->if_init = fxp_init; - ifp->if_ioctl = fxp_ioctl; - ifp->if_start = fxp_start; - ifp->if_output = ether_output; - ifp->if_watchdog = fxp_watchdog; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX /*| IFF_MULTICAST*/; - if (ifp->if_snd.ifq_maxlen == 0) - ifp->if_snd.ifq_maxlen = ifqmaxlen; - - /* - * Attach the interface. - */ - DBGLVL_PRINTK(3,"fxp_attach: calling if_attach\n"); - if_attach (ifp); - DBGLVL_PRINTK(3,"fxp_attach: calling ether_if_attach\n"); - ether_ifattach(ifp); - DBGLVL_PRINTK(3,"fxp_attach: return from ether_if_attach\n"); - -#ifdef NOTUSED - /* - * Tell the upper layer(s) we support long frames. - */ - ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); -#endif - /* - * Let the system queue as many packets as we have available - * TX descriptors. - */ - ifp->if_snd.ifq_maxlen = FXP_NTXCB - 1; - - splx(s); - return (0); - -failmem: - device_printf(dev, "Failed to malloc memory\n"); - error = ENOMEM; -#ifdef NOTUSED -fail: -#endif - splx(s); - fxp_release(sc); - return (error); -} - -/* - * release all resources - */ -static void -fxp_release(struct fxp_softc *sc) -{ - -#ifdef NOTUSED - bus_generic_detach(sc->dev); - if (sc->miibus) - device_delete_child(sc->dev, sc->miibus); -#endif - if (sc->cbl_base) - free(sc->cbl_base, M_DEVBUF); - if (sc->fxp_stats) - free(sc->fxp_stats, M_DEVBUF); - if (sc->mcsp) - free(sc->mcsp, M_DEVBUF); - if (sc->rfa_headm) - m_freem(sc->rfa_headm); - -#ifdef NOTUSED - if (sc->ih) - bus_teardown_intr(sc->dev, sc->irq, sc->ih); - if (sc->irq) - bus_release_resource(sc->dev, SYS_RES_IRQ, 0, sc->irq); - if (sc->mem) - bus_release_resource(sc->dev, sc->rtp, sc->rgd, sc->mem); - mtx_destroy(&sc->sc_mtx); -#endif -} - -#if NOTUSED -/* - * Detach interface. - */ -static int -fxp_detach(device_t dev) -{ - struct fxp_softc *sc = device_get_softc(dev); - int s; - - /* disable interrupts */ - CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL, FXP_SCB_INTR_DISABLE); - - s = splimp(); - - /* - * Stop DMA and drop transmit queue. - */ - fxp_stop(sc); - - /* - * Close down routes etc. - */ - ether_ifdetach(&sc->arpcom.ac_if, ETHER_BPF_SUPPORTED); - - /* - * Free all media structures. - */ - ifmedia_removeall(&sc->sc_media); - - splx(s); - - /* Release our allocated resources. */ - fxp_release(sc); - - return (0); -} - -/* - * Device shutdown routine. Called at system shutdown after sync. The - * main purpose of this routine is to shut off receiver DMA so that - * kernel memory doesn't get clobbered during warmboot. - */ -static int -fxp_shutdown(device_t dev) -{ - /* - * Make sure that DMA is disabled prior to reboot. Not doing - * do could allow DMA to corrupt kernel memory during the - * reboot before the driver initializes. - */ - fxp_stop((struct fxp_softc *) device_get_softc(dev)); - return (0); -} -#endif - -/* - * Show interface statistics - */ -static void -fxp_stats(struct fxp_softc *sc) -{ - struct ifnet *ifp = &sc->sc_if; - - printf (" Output packets:%-8" PRIu64, ifp->if_opackets); - printf (" Collisions:%-8" PRIu64, ifp->if_collisions); - printf (" Output errors:%-8" PRIu64 "\n", ifp->if_oerrors); - printf (" Input packets:%-8" PRIu64, ifp->if_ipackets); - printf (" Input errors:%-8" PRIu64 "\n", ifp->if_ierrors); -} - -static void -fxp_eeprom_shiftin(struct fxp_softc *sc, int data, int length) -{ - u_int16_t reg; - int x; - - /* - * Shift in data. - */ - for (x = 1 << (length - 1); x; x >>= 1) { - if (data & x) - reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI; - else - reg = FXP_EEPROM_EECS; - CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg); - DELAY(1); - CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg | FXP_EEPROM_EESK); - DELAY(1); - CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg); - DELAY(1); - } -} - -/* - * Read from the serial EEPROM. Basically, you manually shift in - * the read opcode (one bit at a time) and then shift in the address, - * and then you shift out the data (all of this one bit at a time). - * The word size is 16 bits, so you have to provide the address for - * every 16 bits of data. - */ -static u_int16_t -fxp_eeprom_getword(struct fxp_softc *sc, int offset, int autosize) -{ - u_int16_t reg, data; - int x; - - CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS); - /* - * Shift in read opcode. - */ - fxp_eeprom_shiftin(sc, FXP_EEPROM_OPC_READ, 3); - /* - * Shift in address. - */ - data = 0; - for (x = 1 << (sc->eeprom_size - 1); x; x >>= 1) { - if (offset & x) - reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI; - else - reg = FXP_EEPROM_EECS; - CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg); - DELAY(1); - CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg | FXP_EEPROM_EESK); - DELAY(1); - CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg); - DELAY(1); - reg = CSR_READ_2(sc, FXP_CSR_EEPROMCONTROL) & FXP_EEPROM_EEDO; - data++; - if (autosize && reg == 0) { - sc->eeprom_size = data; - break; - } - } - /* - * Shift out data. - */ - data = 0; - reg = FXP_EEPROM_EECS; - for (x = 1 << 15; x; x >>= 1) { - CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg | FXP_EEPROM_EESK); - DELAY(1); - if (CSR_READ_2(sc, FXP_CSR_EEPROMCONTROL) & FXP_EEPROM_EEDO) - data |= x; - CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg); - DELAY(1); - } - CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 0); - DELAY(1); - - return (data); -} - -static void -fxp_eeprom_putword(struct fxp_softc *sc, int offset, u_int16_t data) -{ - int i; - - /* - * Erase/write enable. - */ - CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS); - fxp_eeprom_shiftin(sc, 0x4, 3); - fxp_eeprom_shiftin(sc, 0x03 << (sc->eeprom_size - 2), sc->eeprom_size); - CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 0); - DELAY(1); - /* - * Shift in write opcode, address, data. - */ - CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS); - fxp_eeprom_shiftin(sc, FXP_EEPROM_OPC_WRITE, 3); - fxp_eeprom_shiftin(sc, offset, sc->eeprom_size); - fxp_eeprom_shiftin(sc, data, 16); - CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 0); - DELAY(1); - /* - * Wait for EEPROM to finish up. - */ - CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS); - DELAY(1); - for (i = 0; i < 1000; i++) { - if (CSR_READ_2(sc, FXP_CSR_EEPROMCONTROL) & FXP_EEPROM_EEDO) - break; - DELAY(50); - } - CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 0); - DELAY(1); - /* - * Erase/write disable. - */ - CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS); - fxp_eeprom_shiftin(sc, 0x4, 3); - fxp_eeprom_shiftin(sc, 0, sc->eeprom_size); - CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 0); - DELAY(1); -} - -/* - * From NetBSD: - * - * Figure out EEPROM size. - * - * 559's can have either 64-word or 256-word EEPROMs, the 558 - * datasheet only talks about 64-word EEPROMs, and the 557 datasheet - * talks about the existance of 16 to 256 word EEPROMs. - * - * The only known sizes are 64 and 256, where the 256 version is used - * by CardBus cards to store CIS information. - * - * The address is shifted in msb-to-lsb, and after the last - * address-bit the EEPROM is supposed to output a `dummy zero' bit, - * after which follows the actual data. We try to detect this zero, by - * probing the data-out bit in the EEPROM control register just after - * having shifted in a bit. If the bit is zero, we assume we've - * shifted enough address bits. The data-out should be tri-state, - * before this, which should translate to a logical one. - */ -static void -fxp_autosize_eeprom(struct fxp_softc *sc) -{ - - /* guess maximum size of 256 words */ - sc->eeprom_size = 8; - - /* autosize */ - (void) fxp_eeprom_getword(sc, 0, 1); -} - -static void -fxp_read_eeprom(struct fxp_softc *sc, u_short *data, int offset, int words) -{ - int i; - - for (i = 0; i < words; i++) { - data[i] = fxp_eeprom_getword(sc, offset + i, 0); - DBGLVL_PRINTK(4,"fxp_eeprom_read(off=0x%x)=0x%x\n", - offset+i,data[i]); - } -} - -static void -fxp_write_eeprom(struct fxp_softc *sc, u_short *data, int offset, int words) -{ - int i; - - for (i = 0; i < words; i++) - fxp_eeprom_putword(sc, offset + i, data[i]); - DBGLVL_PRINTK(4,"fxp_eeprom_write(off=0x%x,0x%x)\n", - offset+i,data[i]); -} - -/* - * Start packet transmission on the interface. - */ -static void -fxp_start(struct ifnet *ifp) -{ - struct fxp_softc *sc = ifp->if_softc; - struct fxp_cb_tx *txp; - - DBGLVL_PRINTK(3,"fxp_start called\n"); - - /* - * See if we need to suspend xmit until the multicast filter - * has been reprogrammed (which can only be done at the head - * of the command chain). - */ - if (sc->need_mcsetup) { - DBGLVL_PRINTK(3,"fxp_start need_mcsetup\n"); - return; - } - - txp = NULL; - - /* - * We're finished if there is nothing more to add to the list or if - * we're all filled up with buffers to transmit. - * NOTE: One TxCB is reserved to guarantee that fxp_mc_setup() can add - * a NOP command when needed. - */ - while (ifp->if_snd.ifq_head != NULL && sc->tx_queued < FXP_NTXCB - 1) { - struct mbuf *m, *mb_head; - int segment; - - /* - * Grab a packet to transmit. - */ - IF_DEQUEUE(&ifp->if_snd, mb_head); - - /* - * Get pointer to next available tx desc. - */ - txp = sc->cbl_last->next; - - /* - * Go through each of the mbufs in the chain and initialize - * the transmit buffer descriptors with the physical address - * and size of the mbuf. - */ -tbdinit: - for (m = mb_head, segment = 0; m != NULL; m = m->m_next) { - if (m->m_len != 0) { - if (segment == FXP_NTXSEG) - break; - txp->tbd[segment].tb_addr = - vtophys(mtod(m, vm_offset_t)); - txp->tbd[segment].tb_size = m->m_len; - segment++; - } - } - if (m != NULL) { - struct mbuf *mn; - - /* - * We ran out of segments. We have to recopy this - * mbuf chain first. Bail out if we can't get the - * new buffers. - */ - MGETHDR(mn, M_DONTWAIT, MT_DATA); - if (mn == NULL) { - m_freem(mb_head); - break; - } - if (mb_head->m_pkthdr.len > MHLEN) { - MCLGET(mn, M_DONTWAIT); - if ((mn->m_flags & M_EXT) == 0) { - m_freem(mn); - m_freem(mb_head); - break; - } - } - m_copydata(mb_head, 0, mb_head->m_pkthdr.len, - mtod(mn, caddr_t)); - mn->m_pkthdr.len = mn->m_len = mb_head->m_pkthdr.len; - m_freem(mb_head); - mb_head = mn; - goto tbdinit; - } - - txp->tbd_number = segment; - txp->mb_head = mb_head; - txp->cb_status = 0; - if (sc->tx_queued != FXP_CXINT_THRESH - 1) { - txp->cb_command = - FXP_CB_COMMAND_XMIT | FXP_CB_COMMAND_SF | - FXP_CB_COMMAND_S; - } else { - txp->cb_command = - FXP_CB_COMMAND_XMIT | FXP_CB_COMMAND_SF | - FXP_CB_COMMAND_S | FXP_CB_COMMAND_I; - /* - * Set a 5 second timer just in case we don't hear - * from the card again. - */ - ifp->if_timer = 5; - } - txp->tx_threshold = tx_threshold; - - /* - * Advance the end of list forward. - */ - -#ifdef __alpha__ - /* - * On platforms which can't access memory in 16-bit - * granularities, we must prevent the card from DMA'ing - * up the status while we update the command field. - * This could cause us to overwrite the completion status. - */ - atomic_clear_short(&sc->cbl_last->cb_command, - FXP_CB_COMMAND_S); -#else - sc->cbl_last->cb_command &= ~FXP_CB_COMMAND_S; -#endif /*__alpha__*/ - sc->cbl_last = txp; - - /* - * Advance the beginning of the list forward if there are - * no other packets queued (when nothing is queued, cbl_first - * sits on the last TxCB that was sent out). - */ - if (sc->tx_queued == 0) - sc->cbl_first = txp; - - sc->tx_queued++; - -#ifdef NOTUSED - /* - * Pass packet to bpf if there is a listener. - */ - if (ifp->if_bpf) - bpf_mtap(ifp, mb_head); -#endif - } - - /* - * We're finished. If we added to the list, issue a RESUME to get DMA - * going again if suspended. - */ - if (txp != NULL) { - fxp_scb_wait(sc); - fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_RESUME); - } - - /* - * reenable interrupts - */ - RTEMS_COMPILER_MEMORY_BARRIER(); - CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL,0); - bsp_interrupt_vector_enable(sc->irq_num); - RTEMS_COMPILER_MEMORY_BARRIER(); -} - -/* - * Process interface interrupts. - */ -static void fxp_intr(void *arg) -{ - /* - * Obtain device state - */ - struct fxp_softc *sc = (struct fxp_softc *)arg; - - /* - * disable interrupts - */ - CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL, FXP_SCB_INTR_DISABLE); - /* - * send event to deamon - */ - rtems_bsdnet_event_send (sc->daemonTid, INTERRUPT_EVENT); -} - -static void fxp_daemon(void *xsc) -{ - struct fxp_softc *sc = xsc; - struct ifnet *ifp = &sc->sc_if; - u_int8_t statack; - rtems_event_set events; - -#ifdef NOTUSED - if (sc->suspended) { - return; - } -#endif - for (;;) { - - DBGLVL_PRINTK(4,"fxp_daemon waiting for event, INTRCNTL 0x%02x\n", - CSR_READ_1(sc, FXP_CSR_SCB_INTRCNTL)); - /* - * wait for event to receive from interrupt function - */ - rtems_bsdnet_event_receive (INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - while ((statack = CSR_READ_1(sc, FXP_CSR_SCB_STATACK)) != 0) { - DBGLVL_PRINTK(4,"fxp_daemon: processing event, statack = 0x%x\n", - statack); -#ifdef NOTUSED - /* - * It should not be possible to have all bits set; the - * FXP_SCB_INTR_SWI bit always returns 0 on a read. If - * all bits are set, this may indicate that the card has - * been physically ejected, so ignore it. - */ - if (statack == 0xff) - return; -#endif - - /* - * First ACK all the interrupts in this pass. - */ - CSR_WRITE_1(sc, FXP_CSR_SCB_STATACK, statack); - - /* - * Free any finished transmit mbuf chains. - * - * Handle the CNA event likt a CXTNO event. It used to - * be that this event (control unit not ready) was not - * encountered, but it is now with the SMPng modifications. - * The exact sequence of events that occur when the interface - * is brought up are different now, and if this event - * goes unhandled, the configuration/rxfilter setup sequence - * can stall for several seconds. The result is that no - * packets go out onto the wire for about 5 to 10 seconds - * after the interface is ifconfig'ed for the first time. - */ - if (statack & (FXP_SCB_STATACK_CXTNO | FXP_SCB_STATACK_CNA)) { - struct fxp_cb_tx *txp; - - for (txp = sc->cbl_first; sc->tx_queued && - (txp->cb_status & FXP_CB_STATUS_C) != 0; - txp = txp->next) { - if (txp->mb_head != NULL) { - m_freem(txp->mb_head); - txp->mb_head = NULL; - } - sc->tx_queued--; - } - sc->cbl_first = txp; - ifp->if_timer = 0; - if (sc->tx_queued == 0) { - if (sc->need_mcsetup) - fxp_mc_setup(sc); - } - /* - * Try to start more packets transmitting. - */ - if (ifp->if_snd.ifq_head != NULL) - fxp_start(ifp); - } - /* - * Process receiver interrupts. If a no-resource (RNR) - * condition exists, get whatever packets we can and - * re-start the receiver. - */ - if (statack & (FXP_SCB_STATACK_FR | FXP_SCB_STATACK_RNR)) { - struct mbuf *m; - struct fxp_rfa *rfa; -rcvloop: - m = sc->rfa_headm; - rfa = (struct fxp_rfa *)(m->m_ext.ext_buf + - RFA_ALIGNMENT_FUDGE); - - if (rfa->rfa_status & FXP_RFA_STATUS_C) { - /* - * Remove first packet from the chain. - */ - sc->rfa_headm = m->m_next; - m->m_next = NULL; - - /* - * Add a new buffer to the receive chain. - * If this fails, the old buffer is recycled - * instead. - */ - if (fxp_add_rfabuf(sc, m) == 0) { - struct ether_header *eh; - int total_len; - - total_len = rfa->actual_size & - (MCLBYTES - 1); - if (total_len < - sizeof(struct ether_header)) { - m_freem(m); - goto rcvloop; - } - - /* - * Drop the packet if it has CRC - * errors. This test is only needed - * when doing 802.1q VLAN on the 82557 - * chip. - */ - if (rfa->rfa_status & - FXP_RFA_STATUS_CRC) { - m_freem(m); - goto rcvloop; - } - - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = total_len; - eh = mtod(m, struct ether_header *); - m->m_data += - sizeof(struct ether_header); - m->m_len -= - sizeof(struct ether_header); - m->m_pkthdr.len = m->m_len; - ether_input(ifp, eh, m); - } - goto rcvloop; - } - if (statack & FXP_SCB_STATACK_RNR) { - fxp_scb_wait(sc); - CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, - vtophys(sc->rfa_headm->m_ext.ext_buf) + - RFA_ALIGNMENT_FUDGE); - fxp_scb_cmd(sc, FXP_SCB_COMMAND_RU_START); - } - } - } - /* - * reenable interrupts - */ - RTEMS_COMPILER_MEMORY_BARRIER(); - CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL,0); - RTEMS_COMPILER_MEMORY_BARRIER(); - } -} - -/* - * Update packet in/out/collision statistics. The i82557 doesn't - * allow you to access these counters without doing a fairly - * expensive DMA to get _all_ of the statistics it maintains, so - * we do this operation here only once per second. The statistics - * counters in the kernel are updated from the previous dump-stats - * DMA and then a new dump-stats DMA is started. The on-chip - * counters are zeroed when the DMA completes. If we can't start - * the DMA immediately, we don't wait - we just prepare to read - * them again next time. - */ -static void -fxp_tick(void *xsc) -{ - struct fxp_softc *sc = xsc; - struct ifnet *ifp = &sc->sc_if; - struct fxp_stats *sp = sc->fxp_stats; - struct fxp_cb_tx *txp; - int s; - - DBGLVL_PRINTK(4,"fxp_tick called\n"); - - ifp->if_opackets += sp->tx_good; - ifp->if_collisions += sp->tx_total_collisions; - if (sp->rx_good) { - ifp->if_ipackets += sp->rx_good; - sc->rx_idle_secs = 0; - } else { - /* - * Receiver's been idle for another second. - */ - sc->rx_idle_secs++; - } - ifp->if_ierrors += - sp->rx_crc_errors + - sp->rx_alignment_errors + - sp->rx_rnr_errors + - sp->rx_overrun_errors; - /* - * If any transmit underruns occured, bump up the transmit - * threshold by another 512 bytes (64 * 8). - */ - if (sp->tx_underruns) { - ifp->if_oerrors += sp->tx_underruns; - if (tx_threshold < 192) - tx_threshold += 64; - } - s = splimp(); - /* - * Release any xmit buffers that have completed DMA. This isn't - * strictly necessary to do here, but it's advantagous for mbufs - * with external storage to be released in a timely manner rather - * than being defered for a potentially long time. This limits - * the delay to a maximum of one second. - */ - for (txp = sc->cbl_first; sc->tx_queued && - (txp->cb_status & FXP_CB_STATUS_C) != 0; - txp = txp->next) { - if (txp->mb_head != NULL) { - m_freem(txp->mb_head); - txp->mb_head = NULL; - } - sc->tx_queued--; - } - sc->cbl_first = txp; - /* - * If we haven't received any packets in FXP_MAC_RX_IDLE seconds, - * then assume the receiver has locked up and attempt to clear - * the condition by reprogramming the multicast filter. This is - * a work-around for a bug in the 82557 where the receiver locks - * up if it gets certain types of garbage in the syncronization - * bits prior to the packet header. This bug is supposed to only - * occur in 10Mbps mode, but has been seen to occur in 100Mbps - * mode as well (perhaps due to a 10/100 speed transition). - */ - if (sc->rx_idle_secs > FXP_MAX_RX_IDLE) { - sc->rx_idle_secs = 0; - fxp_mc_setup(sc); - } - /* - * If there is no pending command, start another stats - * dump. Otherwise punt for now. - */ - if (CSR_READ_1(sc, FXP_CSR_SCB_COMMAND) == 0) { - /* - * Start another stats dump. - */ - fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_DUMPRESET); - } else { - /* - * A previous command is still waiting to be accepted. - * Just zero our copy of the stats and wait for the - * next timer event to update them. - */ - sp->tx_good = 0; - sp->tx_underruns = 0; - sp->tx_total_collisions = 0; - - sp->rx_good = 0; - sp->rx_crc_errors = 0; - sp->rx_alignment_errors = 0; - sp->rx_rnr_errors = 0; - sp->rx_overrun_errors = 0; - } -#ifdef NOTUSED - if (sc->miibus != NULL) - mii_tick(device_get_softc(sc->miibus)); -#endif - splx(s); - /* - * Schedule another timeout one second from now. - */ - if (sc->stat_ch == fxp_timeout_running) { - timeout(fxp_tick, sc, hz); - } - else if (sc->stat_ch == fxp_timeout_stop_rq) { - sc->stat_ch = fxp_timeout_stopped; - } -} - -/* - * Stop the interface. Cancels the statistics updater and resets - * the interface. - */ -static void -fxp_stop(struct fxp_softc *sc) -{ - struct ifnet *ifp = &sc->sc_if; - struct fxp_cb_tx *txp; - int i; - - DBGLVL_PRINTK(2,"fxp_stop called\n"); - - ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); - ifp->if_timer = 0; - - /* - * stop stats updater. - */ - if (sc->stat_ch == fxp_timeout_running) { - DBGLVL_PRINTK(3,"fxp_stop: trying to stop stat update tick\n"); - sc->stat_ch = fxp_timeout_stop_rq; - while(sc->stat_ch != fxp_timeout_stopped) { - rtems_bsdnet_semaphore_release(); - rtems_task_wake_after(fxp_ticksPerSecond); - rtems_bsdnet_semaphore_obtain(); - } - DBGLVL_PRINTK(3,"fxp_stop: stat update tick stopped\n"); - } - /* - * Issue software reset - */ - DBGLVL_PRINTK(3,"fxp_stop: issue software reset\n"); - CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET); - DELAY(10); - - /* - * Release any xmit buffers. - */ - DBGLVL_PRINTK(3,"fxp_stop: releasing xmit buffers\n"); - txp = sc->cbl_base; - if (txp != NULL) { - for (i = 0; i < FXP_NTXCB; i++) { - if (txp[i].mb_head != NULL) { - m_freem(txp[i].mb_head); - txp[i].mb_head = NULL; - } - } - } - sc->tx_queued = 0; - - /* - * Free all the receive buffers then reallocate/reinitialize - */ - DBGLVL_PRINTK(3,"fxp_stop: free and reinit all receive buffers\n"); - if (sc->rfa_headm != NULL) - m_freem(sc->rfa_headm); - sc->rfa_headm = NULL; - sc->rfa_tailm = NULL; - for (i = 0; i < FXP_NRFABUFS; i++) { - if (fxp_add_rfabuf(sc, NULL) != 0) { - /* - * This "can't happen" - we're at splimp() - * and we just freed all the buffers we need - * above. - */ - panic("fxp_stop: no buffers!"); - } - } - DBGLVL_PRINTK(2,"fxp_stop: finished\n"); -} - -/* - * Watchdog/transmission transmit timeout handler. Called when a - * transmission is started on the interface, but no interrupt is - * received before the timeout. This usually indicates that the - * card has wedged for some reason. - */ -static void -fxp_watchdog(struct ifnet *ifp) -{ - struct fxp_softc *sc = ifp->if_softc; - - device_printf(sc->dev, "device timeout\n"); - ifp->if_oerrors++; - - fxp_init(sc); -} - -static void -fxp_init(void *xsc) -{ - struct fxp_softc *sc = xsc; - struct ifnet *ifp = &sc->sc_if; - struct fxp_cb_config *cbp; - struct fxp_cb_ias *cb_ias; - struct fxp_cb_tx *txp; - int i, prm, s; - rtems_status_code statcode; - -rtems_task_wake_after(100); - DBGLVL_PRINTK(2,"fxp_init called\n"); - - s = splimp(); - /* - * Cancel any pending I/O - */ - /* - * E. Norum 2004-10-11 - * Add line suggested by "Eugene Denisov" . - * Prevents lockup at initialization. - */ - sc->stat_ch = fxp_timeout_stopped; - fxp_stop(sc); - - prm = (ifp->if_flags & IFF_PROMISC) ? 1 : 0; - - DBGLVL_PRINTK(5,"fxp_init: Initializing base of CBL and RFA memory\n"); - /* - * Initialize base of CBL and RFA memory. Loading with zero - * sets it up for regular linear addressing. - */ - CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, 0); - fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_BASE); - - fxp_scb_wait(sc); - fxp_scb_cmd(sc, FXP_SCB_COMMAND_RU_BASE); - - /* - * Initialize base of dump-stats buffer. - */ - DBGLVL_PRINTK(5,"fxp_init: Initializing base of dump-stats buffer\n"); - fxp_scb_wait(sc); - CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, vtophys(sc->fxp_stats)); - fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_DUMP_ADR); - - /* - * We temporarily use memory that contains the TxCB list to - * construct the config CB. The TxCB list memory is rebuilt - * later. - */ - cbp = (struct fxp_cb_config *) sc->cbl_base; - DBGLVL_PRINTK(5,"fxp_init: cbp = 0x%x\n",cbp); - - /* - * This memcpy is kind of disgusting, but there are a bunch of must be - * zero and must be one bits in this structure and this is the easiest - * way to initialize them all to proper values. - */ - memcpy( (void *)(u_int32_t*)(volatile void *)&cbp->cb_status, - fxp_cb_config_template, - sizeof(fxp_cb_config_template)); - - cbp->cb_status = 0; - cbp->cb_command = FXP_CB_COMMAND_CONFIG | FXP_CB_COMMAND_EL; - cbp->link_addr = -1; /* (no) next command */ - cbp->byte_count = 22; /* (22) bytes to config */ - cbp->rx_fifo_limit = 8; /* rx fifo threshold (32 bytes) */ - cbp->tx_fifo_limit = 0; /* tx fifo threshold (0 bytes) */ - cbp->adaptive_ifs = 0; /* (no) adaptive interframe spacing */ - cbp->mwi_enable = sc->flags & FXP_FLAG_MWI_ENABLE ? 1 : 0; - cbp->type_enable = 0; /* actually reserved */ - cbp->read_align_en = sc->flags & FXP_FLAG_READ_ALIGN ? 1 : 0; - cbp->end_wr_on_cl = sc->flags & FXP_FLAG_WRITE_ALIGN ? 1 : 0; - cbp->rx_dma_bytecount = 0; /* (no) rx DMA max */ - cbp->tx_dma_bytecount = 0; /* (no) tx DMA max */ - cbp->dma_mbce = 0; /* (disable) dma max counters */ - cbp->late_scb = 0; /* (don't) defer SCB update */ - cbp->direct_dma_dis = 1; /* disable direct rcv dma mode */ - cbp->tno_int_or_tco_en =0; /* (disable) tx not okay interrupt */ - cbp->ci_int = 1; /* interrupt on CU idle */ - cbp->ext_txcb_dis = sc->flags & FXP_FLAG_EXT_TXCB ? 0 : 1; - cbp->ext_stats_dis = 1; /* disable extended counters */ - cbp->keep_overrun_rx = 0; /* don't pass overrun frames to host */ - cbp->save_bf = sc->chip == FXP_CHIP_82557 ? 1 : prm; - cbp->disc_short_rx = !prm; /* discard short packets */ - cbp->underrun_retry = 1; /* retry mode (once) on DMA underrun */ - cbp->two_frames = 0; /* do not limit FIFO to 2 frames */ - cbp->dyn_tbd = 0; /* (no) dynamic TBD mode */ - cbp->mediatype = sc->flags & FXP_FLAG_SERIAL_MEDIA ? 0 : 1; - cbp->csma_dis = 0; /* (don't) disable link */ - cbp->tcp_udp_cksum = 0; /* (don't) enable checksum */ - cbp->vlan_tco = 0; /* (don't) enable vlan wakeup */ - cbp->link_wake_en = 0; /* (don't) assert PME# on link change */ - cbp->arp_wake_en = 0; /* (don't) assert PME# on arp */ - cbp->mc_wake_en = 0; /* (don't) enable PME# on mcmatch */ - cbp->nsai = 1; /* (don't) disable source addr insert */ - cbp->preamble_length = 2; /* (7 byte) preamble */ - cbp->loopback = 0; /* (don't) loopback */ - cbp->linear_priority = 0; /* (normal CSMA/CD operation) */ - cbp->linear_pri_mode = 0; /* (wait after xmit only) */ - cbp->interfrm_spacing = 6; /* (96 bits of) interframe spacing */ - cbp->promiscuous = prm; /* promiscuous mode */ - cbp->bcast_disable = 0; /* (don't) disable broadcasts */ - cbp->wait_after_win = 0; /* (don't) enable modified backoff alg*/ - cbp->ignore_ul = 0; /* consider U/L bit in IA matching */ - cbp->crc16_en = 0; /* (don't) enable crc-16 algorithm */ - cbp->crscdt = sc->flags & FXP_FLAG_SERIAL_MEDIA ? 1 : 0; - - cbp->stripping = !prm; /* truncate rx packet to byte count */ - cbp->padding = 1; /* (do) pad short tx packets */ - cbp->rcv_crc_xfer = 0; /* (don't) xfer CRC to host */ - cbp->long_rx_en = sc->flags & FXP_FLAG_LONG_PKT_EN ? 1 : 0; - cbp->ia_wake_en = 0; /* (don't) wake up on address match */ - cbp->magic_pkt_dis = 0; /* (don't) disable magic packet */ - /* must set wake_en in PMCSR also */ - cbp->force_fdx = 0; /* (don't) force full duplex */ - cbp->fdx_pin_en = 1; /* (enable) FDX# pin */ - cbp->multi_ia = 0; /* (don't) accept multiple IAs */ - cbp->mc_all = sc->flags & FXP_FLAG_ALL_MCAST ? 1 : 0; - - DBGLVL_PRINTK(5,"fxp_init: cbp initialized\n"); - if (sc->chip == FXP_CHIP_82557) { - /* - * The 82557 has no hardware flow control, the values - * below are the defaults for the chip. - */ - cbp->fc_delay_lsb = 0; - cbp->fc_delay_msb = 0x40; - cbp->pri_fc_thresh = 3; - cbp->tx_fc_dis = 0; - cbp->rx_fc_restop = 0; - cbp->rx_fc_restart = 0; - cbp->fc_filter = 0; - cbp->pri_fc_loc = 1; - } else { - cbp->fc_delay_lsb = 0x1f; - cbp->fc_delay_msb = 0x01; - cbp->pri_fc_thresh = 3; - cbp->tx_fc_dis = 0; /* enable transmit FC */ - cbp->rx_fc_restop = 1; /* enable FC restop frames */ - cbp->rx_fc_restart = 1; /* enable FC restart frames */ - cbp->fc_filter = !prm; /* drop FC frames to host */ - cbp->pri_fc_loc = 1; /* FC pri location (byte31) */ - } - - /* - * Start the config command/DMA. - */ - DBGLVL_PRINTK(5,"fxp_init: starting config command/DMA\n"); - fxp_scb_wait(sc); - CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, vtophys(&cbp->cb_status)); - fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_START); - /* ...and wait for it to complete. */ - fxp_dma_wait(&cbp->cb_status, sc); - - /* - * Now initialize the station address. Temporarily use the TxCB - * memory area like we did above for the config CB. - */ - DBGLVL_PRINTK(5,"fxp_init: initialize station address\n"); - cb_ias = (struct fxp_cb_ias *) sc->cbl_base; - cb_ias->cb_status = 0; - cb_ias->cb_command = FXP_CB_COMMAND_IAS | FXP_CB_COMMAND_EL; - cb_ias->link_addr = -1; - memcpy((void *)(u_int32_t*)(volatile void *)cb_ias->macaddr, - sc->arpcom.ac_enaddr, - sizeof(sc->arpcom.ac_enaddr)); - - /* - * Start the IAS (Individual Address Setup) command/DMA. - */ - DBGLVL_PRINTK(5,"fxp_init: start IAS command/DMA\n"); - fxp_scb_wait(sc); - fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_START); - /* ...and wait for it to complete. */ - fxp_dma_wait(&cb_ias->cb_status, sc); - - /* - * Initialize transmit control block (TxCB) list. - */ - - DBGLVL_PRINTK(5,"fxp_init: initialize TxCB list\n"); - txp = sc->cbl_base; - memset(txp, 0, sizeof(struct fxp_cb_tx) * FXP_NTXCB); - for (i = 0; i < FXP_NTXCB; i++) { - txp[i].cb_status = FXP_CB_STATUS_C | FXP_CB_STATUS_OK; - txp[i].cb_command = FXP_CB_COMMAND_NOP; - txp[i].link_addr = - vtophys(&txp[(i + 1) & FXP_TXCB_MASK].cb_status); - if (sc->flags & FXP_FLAG_EXT_TXCB) - txp[i].tbd_array_addr = vtophys(&txp[i].tbd[2]); - else - txp[i].tbd_array_addr = vtophys(&txp[i].tbd[0]); - txp[i].next = &txp[(i + 1) & FXP_TXCB_MASK]; - } - /* - * Set the suspend flag on the first TxCB and start the control - * unit. It will execute the NOP and then suspend. - */ - DBGLVL_PRINTK(5,"fxp_init: setup suspend flag\n"); - txp->cb_command = FXP_CB_COMMAND_NOP | FXP_CB_COMMAND_S; - sc->cbl_first = sc->cbl_last = txp; - sc->tx_queued = 1; - - fxp_scb_wait(sc); - fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_START); - - /* - * Initialize receiver buffer area - RFA. - */ - DBGLVL_PRINTK(5,"fxp_init: initialize RFA\n"); - fxp_scb_wait(sc); - CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, - vtophys(sc->rfa_headm->m_ext.ext_buf) + RFA_ALIGNMENT_FUDGE); - fxp_scb_cmd(sc, FXP_SCB_COMMAND_RU_START); - -#ifdef NOTUSED - /* - * Set current media. - */ - if (sc->miibus != NULL) - mii_mediachg(device_get_softc(sc->miibus)); -#endif - - ifp->if_flags |= IFF_RUNNING; - ifp->if_flags &= ~IFF_OACTIVE; - - if (sc->daemonTid == 0) { - /* - * Start driver task - */ - sc->daemonTid = rtems_bsdnet_newproc ("FXPd", 4096, fxp_daemon, sc); - - /* - * Set up interrupts - */ - statcode = rtems_interrupt_handler_install( - sc->irq_num, - "fxp_intr", - RTEMS_INTERRUPT_SHARED, - fxp_intr, - sc - ); - - if ( statcode != RTEMS_SUCCESSFUL ) { - rtems_panic ("Can't attach fxp interrupt handler for irq %d\n", - sc->irq_num); - } - } - - /* - * Enable interrupts. - */ - CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL, 0); - splx(s); - - /* - * Start stats updater. - */ - sc->stat_ch = fxp_timeout_running; - DBGLVL_PRINTK(2,"fxp_init: stats updater timeout called with hz=%d\n", hz); - timeout(fxp_tick, sc, hz); - DBGLVL_PRINTK(2,"fxp_init finished\n"); -} - -#ifdef NOTUSED -static int -fxp_serial_ifmedia_upd(struct ifnet *ifp) -{ - - return (0); -} - -static void -fxp_serial_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) -{ - - ifmr->ifm_active = IFM_ETHER|IFM_MANUAL; -} - -/* - * Change media according to request. - */ -static int -fxp_ifmedia_upd(struct ifnet *ifp) -{ - struct fxp_softc *sc = ifp->if_softc; - struct mii_data *mii; - - mii = device_get_softc(sc->miibus); - mii_mediachg(mii); - return (0); -} - -/* - * Notify the world which media we're using. - */ -static void -fxp_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) -{ - struct fxp_softc *sc = ifp->if_softc; - struct mii_data *mii; - - mii = device_get_softc(sc->miibus); - mii_pollstat(mii); - ifmr->ifm_active = mii->mii_media_active; - ifmr->ifm_status = mii->mii_media_status; - - if (ifmr->ifm_status & IFM_10_T && sc->flags & FXP_FLAG_CU_RESUME_BUG) - sc->cu_resume_bug = 1; - else - sc->cu_resume_bug = 0; -} -#endif - -/* - * Add a buffer to the end of the RFA buffer list. - * Return 0 if successful, 1 for failure. A failure results in - * adding the 'oldm' (if non-NULL) on to the end of the list - - * tossing out its old contents and recycling it. - * The RFA struct is stuck at the beginning of mbuf cluster and the - * data pointer is fixed up to point just past it. - */ -static int -fxp_add_rfabuf(struct fxp_softc *sc, struct mbuf *oldm) -{ - u_int32_t v; - struct mbuf *m; - struct fxp_rfa *rfa, *p_rfa; - - DBGLVL_PRINTK(4,"fxp_add_rfabuf called\n"); - - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m != NULL) { - MCLGET(m, M_DONTWAIT); - if ((m->m_flags & M_EXT) == 0) { - m_freem(m); - if (oldm == NULL) - return 1; - m = oldm; - m->m_data = m->m_ext.ext_buf; - } - } else { - if (oldm == NULL) - return 1; - m = oldm; - m->m_data = m->m_ext.ext_buf; - } - - /* - * Move the data pointer up so that the incoming data packet - * will be 32-bit aligned. - */ - m->m_data += RFA_ALIGNMENT_FUDGE; - - /* - * Get a pointer to the base of the mbuf cluster and move - * data start past it. - */ - rfa = mtod(m, struct fxp_rfa *); - m->m_data += sizeof(struct fxp_rfa); - rfa->size = (u_int16_t)(MCLBYTES - sizeof(struct fxp_rfa) - RFA_ALIGNMENT_FUDGE); - - /* - * Initialize the rest of the RFA. Note that since the RFA - * is misaligned, we cannot store values directly. Instead, - * we use an optimized, inline copy. - */ - - rfa->rfa_status = 0; - rfa->rfa_control = FXP_RFA_CONTROL_EL; - rfa->actual_size = 0; - - v = -1; - fxp_lwcopy(&v, (volatile u_int32_t*) rfa->link_addr); - fxp_lwcopy(&v, (volatile u_int32_t*) rfa->rbd_addr); - - /* - * If there are other buffers already on the list, attach this - * one to the end by fixing up the tail to point to this one. - */ - if (sc->rfa_headm != NULL) { - p_rfa = (struct fxp_rfa *) (sc->rfa_tailm->m_ext.ext_buf + - RFA_ALIGNMENT_FUDGE); - sc->rfa_tailm->m_next = m; - v = vtophys(rfa); - fxp_lwcopy(&v, (volatile u_int32_t*) p_rfa->link_addr); - p_rfa->rfa_control = 0; - } else { - sc->rfa_headm = m; - } - sc->rfa_tailm = m; - - return (m == oldm); -} - -#ifdef NOTUSED -static volatile int -fxp_miibus_readreg(device_t dev, int phy, int reg) -{ - struct fxp_softc *sc = device_get_softc(dev); - int count = 10000; - int value; - - CSR_WRITE_4(sc, FXP_CSR_MDICONTROL, - (FXP_MDI_READ << 26) | (reg << 16) | (phy << 21)); - - while (((value = CSR_READ_4(sc, FXP_CSR_MDICONTROL)) & 0x10000000) == 0 - && count--) - DELAY(10); - - if (count <= 0) - device_printf(dev, "fxp_miibus_readreg: timed out\n"); - - return (value & 0xffff); -} - -static void -fxp_miibus_writereg(device_t dev, int phy, int reg, int value) -{ - struct fxp_softc *sc = device_get_softc(dev); - int count = 10000; - - CSR_WRITE_4(sc, FXP_CSR_MDICONTROL, - (FXP_MDI_WRITE << 26) | (reg << 16) | (phy << 21) | - (value & 0xffff)); - - while ((CSR_READ_4(sc, FXP_CSR_MDICONTROL) & 0x10000000) == 0 && - count--) - DELAY(10); - - if (count <= 0) - device_printf(dev, "fxp_miibus_writereg: timed out\n"); -} -#endif - -static int -fxp_ioctl(struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - struct fxp_softc *sc = ifp->if_softc; -#ifdef NOTUSED - struct ifreq *ifr = (struct ifreq *)data; - struct mii_data *mii; -#endif - int s, error = 0; - - DBGLVL_PRINTK(2,"fxp_ioctl called\n"); - - s = splimp(); - - switch (command) { - case SIOCSIFADDR: - case SIOCGIFADDR: - case SIOCSIFMTU: - error = ether_ioctl(ifp, command, data); - break; - - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_ALLMULTI) - sc->flags |= FXP_FLAG_ALL_MCAST; - else - sc->flags &= ~FXP_FLAG_ALL_MCAST; - - /* - * If interface is marked up and not running, then start it. - * If it is marked down and running, stop it. - * XXX If it's up then re-initialize it. This is so flags - * such as IFF_PROMISC are handled. - */ - if (ifp->if_flags & IFF_UP) { - fxp_init(sc); - } else { - if (ifp->if_flags & IFF_RUNNING) - fxp_stop(sc); - } - break; - - case SIOCADDMULTI: - case SIOCDELMULTI: - if (ifp->if_flags & IFF_ALLMULTI) - sc->flags |= FXP_FLAG_ALL_MCAST; - else - sc->flags &= ~FXP_FLAG_ALL_MCAST; - /* - * Multicast list has changed; set the hardware filter - * accordingly. - */ - if ((sc->flags & FXP_FLAG_ALL_MCAST) == 0) - fxp_mc_setup(sc); - /* - * fxp_mc_setup() can set FXP_FLAG_ALL_MCAST, so check it - * again rather than else {}. - */ - if (sc->flags & FXP_FLAG_ALL_MCAST) - fxp_init(sc); - error = 0; - break; - -#ifdef NOTUSED - case SIOCSIFMEDIA: - case SIOCGIFMEDIA: - if (sc->miibus != NULL) { - mii = device_get_softc(sc->miibus); - error = ifmedia_ioctl(ifp, ifr, - &mii->mii_media, command); - } else { - error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command); - } - break; -#endif - - case SIO_RTEMS_SHOW_STATS: - fxp_stats(sc); - break; - - default: - error = EINVAL; - } - splx(s); - return (error); -} - -/* - * Program the multicast filter. - * - * We have an artificial restriction that the multicast setup command - * must be the first command in the chain, so we take steps to ensure - * this. By requiring this, it allows us to keep up the performance of - * the pre-initialized command ring (esp. link pointers) by not actually - * inserting the mcsetup command in the ring - i.e. its link pointer - * points to the TxCB ring, but the mcsetup descriptor itself is not part - * of it. We then can do 'CU_START' on the mcsetup descriptor and have it - * lead into the regular TxCB ring when it completes. - * - * This function must be called at splimp. - */ -static void -fxp_mc_setup(struct fxp_softc *sc) -{ - struct fxp_cb_mcs *mcsp = sc->mcsp; - struct ifnet *ifp = &sc->sc_if; -#ifdef NOTUSED - struct ifmultiaddr *ifma; -#endif - int nmcasts; - int count; - - DBGLVL_PRINTK(2,"fxp_mc_setup called\n"); - - /* - * If there are queued commands, we must wait until they are all - * completed. If we are already waiting, then add a NOP command - * with interrupt option so that we're notified when all commands - * have been completed - fxp_start() ensures that no additional - * TX commands will be added when need_mcsetup is true. - */ - if (sc->tx_queued) { - struct fxp_cb_tx *txp; - - /* - * need_mcsetup will be true if we are already waiting for the - * NOP command to be completed (see below). In this case, bail. - */ - if (sc->need_mcsetup) - return; - sc->need_mcsetup = 1; - - /* - * Add a NOP command with interrupt so that we are notified when all - * TX commands have been processed. - */ - txp = sc->cbl_last->next; - txp->mb_head = NULL; - txp->cb_status = 0; - txp->cb_command = FXP_CB_COMMAND_NOP | - FXP_CB_COMMAND_S | FXP_CB_COMMAND_I; - /* - * Advance the end of list forward. - */ - sc->cbl_last->cb_command &= ~FXP_CB_COMMAND_S; - sc->cbl_last = txp; - sc->tx_queued++; - /* - * Issue a resume in case the CU has just suspended. - */ - fxp_scb_wait(sc); - fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_RESUME); - /* - * Set a 5 second timer just in case we don't hear from the - * card again. - */ - ifp->if_timer = 5; - - return; - } - sc->need_mcsetup = 0; - - /* - * Initialize multicast setup descriptor. - */ - mcsp->next = sc->cbl_base; - mcsp->mb_head = NULL; - mcsp->cb_status = 0; - mcsp->cb_command = FXP_CB_COMMAND_MCAS | - FXP_CB_COMMAND_S | FXP_CB_COMMAND_I; - mcsp->link_addr = vtophys(&sc->cbl_base->cb_status); - - nmcasts = 0; -#ifdef NOTUSED /* FIXME: Multicast not supported? */ - if ((sc->flags & FXP_FLAG_ALL_MCAST) == 0) { -#if __FreeBSD_version < 500000 - LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { -#else - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { -#endif - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - if (nmcasts >= MAXMCADDR) { - sc->flags |= FXP_FLAG_ALL_MCAST; - nmcasts = 0; - break; - } - memcpy((void *)(uintptr_t)(volatile void *) - &sc->mcsp->mc_addr[nmcasts][0], - LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 6); - nmcasts++; - } - } -#endif - mcsp->mc_cnt = nmcasts * 6; - sc->cbl_first = sc->cbl_last = (struct fxp_cb_tx *) mcsp; - sc->tx_queued = 1; - - /* - * Wait until command unit is not active. This should never - * be the case when nothing is queued, but make sure anyway. - */ - count = 100; - while ((CSR_READ_1(sc, FXP_CSR_SCB_RUSCUS) >> 6) == - FXP_SCB_CUS_ACTIVE && --count) - DELAY(10); - if (count == 0) { - device_printf(sc->dev, "command queue timeout\n"); - return; - } - - /* - * Start the multicast setup command. - */ - fxp_scb_wait(sc); - CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, vtophys(&mcsp->cb_status)); - fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_START); - - ifp->if_timer = 2; - return; - } - -#endif /* defined(__i386__) */ diff --git a/c/src/libchip/network/if_fxpreg.h b/c/src/libchip/network/if_fxpreg.h deleted file mode 100644 index 9bf4e59ff5..0000000000 --- a/c/src/libchip/network/if_fxpreg.h +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (c) 1995, David Greenman - * Copyright (c) 2001 Jonathan Lemon - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice unmodified, this list of conditions, and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/fxp/if_fxpreg.h,v 1.23.2.4 2001/08/31 02:17:02 jlemon Exp $ - */ - -#define FXP_VENDORID_INTEL 0x8086 - -#define FXP_PCI_MMBA 0x10 -#define FXP_PCI_IOBA 0x14 - -/* - * Control/status registers. - */ -#define FXP_CSR_SCB_RUSCUS 0 /* scb_rus/scb_cus (1 byte) */ -#define FXP_CSR_SCB_STATACK 1 /* scb_statack (1 byte) */ -#define FXP_CSR_SCB_COMMAND 2 /* scb_command (1 byte) */ -#define FXP_CSR_SCB_INTRCNTL 3 /* scb_intrcntl (1 byte) */ -#define FXP_CSR_SCB_GENERAL 4 /* scb_general (4 bytes) */ -#define FXP_CSR_PORT 8 /* port (4 bytes) */ -#define FXP_CSR_FLASHCONTROL 12 /* flash control (2 bytes) */ -#define FXP_CSR_EEPROMCONTROL 14 /* eeprom control (2 bytes) */ -#define FXP_CSR_MDICONTROL 16 /* mdi control (4 bytes) */ -#define FXP_CSR_FLOWCONTROL 0x19 /* flow control (2 bytes) */ -#define FXP_CSR_GENCONTROL 0x1C /* general control (1 byte) */ - -/* - * FOR REFERENCE ONLY, the old definition of FXP_CSR_SCB_RUSCUS: - * - * volatile u_int8_t :2, - * scb_rus:4, - * scb_cus:2; - */ - -#define FXP_PORT_SOFTWARE_RESET 0 -#define FXP_PORT_SELFTEST 1 -#define FXP_PORT_SELECTIVE_RESET 2 -#define FXP_PORT_DUMP 3 - -#define FXP_SCB_RUS_IDLE 0 -#define FXP_SCB_RUS_SUSPENDED 1 -#define FXP_SCB_RUS_NORESOURCES 2 -#define FXP_SCB_RUS_READY 4 -#define FXP_SCB_RUS_SUSP_NORBDS 9 -#define FXP_SCB_RUS_NORES_NORBDS 10 -#define FXP_SCB_RUS_READY_NORBDS 12 - -#define FXP_SCB_CUS_IDLE 0 -#define FXP_SCB_CUS_SUSPENDED 1 -#define FXP_SCB_CUS_ACTIVE 2 - -#define FXP_SCB_INTR_DISABLE 0x01 /* Disable all interrupts */ -#define FXP_SCB_INTR_SWI 0x02 /* Generate SWI */ -#define FXP_SCB_INTMASK_FCP 0x04 -#define FXP_SCB_INTMASK_ER 0x08 -#define FXP_SCB_INTMASK_RNR 0x10 -#define FXP_SCB_INTMASK_CNA 0x20 -#define FXP_SCB_INTMASK_FR 0x40 -#define FXP_SCB_INTMASK_CXTNO 0x80 - -#define FXP_SCB_STATACK_FCP 0x01 /* Flow Control Pause */ -#define FXP_SCB_STATACK_ER 0x02 /* Early Receive */ -#define FXP_SCB_STATACK_SWI 0x04 -#define FXP_SCB_STATACK_MDI 0x08 -#define FXP_SCB_STATACK_RNR 0x10 -#define FXP_SCB_STATACK_CNA 0x20 -#define FXP_SCB_STATACK_FR 0x40 -#define FXP_SCB_STATACK_CXTNO 0x80 - -#define FXP_SCB_COMMAND_CU_NOP 0x00 -#define FXP_SCB_COMMAND_CU_START 0x10 -#define FXP_SCB_COMMAND_CU_RESUME 0x20 -#define FXP_SCB_COMMAND_CU_DUMP_ADR 0x40 -#define FXP_SCB_COMMAND_CU_DUMP 0x50 -#define FXP_SCB_COMMAND_CU_BASE 0x60 -#define FXP_SCB_COMMAND_CU_DUMPRESET 0x70 - -#define FXP_SCB_COMMAND_RU_NOP 0 -#define FXP_SCB_COMMAND_RU_START 1 -#define FXP_SCB_COMMAND_RU_RESUME 2 -#define FXP_SCB_COMMAND_RU_ABORT 4 -#define FXP_SCB_COMMAND_RU_LOADHDS 5 -#define FXP_SCB_COMMAND_RU_BASE 6 -#define FXP_SCB_COMMAND_RU_RBDRESUME 7 - -/* - * Command block definitions - */ -struct fxp_cb_nop { - void *fill[2]; - volatile u_int16_t cb_status; - volatile u_int16_t cb_command; - volatile u_int32_t link_addr; -}; -struct fxp_cb_ias { - void *fill[2]; - volatile u_int16_t cb_status; - volatile u_int16_t cb_command; - volatile u_int32_t link_addr; - volatile u_int8_t macaddr[6]; -}; -/* I hate bit-fields :-( */ -struct fxp_cb_config { - void *fill[2]; - volatile u_int16_t cb_status; - volatile u_int16_t cb_command; - volatile u_int32_t link_addr; - volatile u_int byte_count:6, - :2; - volatile u_int rx_fifo_limit:4, - tx_fifo_limit:3, - :1; - volatile u_int8_t adaptive_ifs; - volatile u_int mwi_enable:1, /* 8,9 */ - type_enable:1, /* 8,9 */ - read_align_en:1, /* 8,9 */ - end_wr_on_cl:1, /* 8,9 */ - :4; - volatile u_int rx_dma_bytecount:7, - :1; - volatile u_int tx_dma_bytecount:7, - dma_mbce:1; - volatile u_int late_scb:1, /* 7 */ - direct_dma_dis:1, /* 8,9 */ - tno_int_or_tco_en:1, /* 7,9 */ - ci_int:1, - ext_txcb_dis:1, /* 8,9 */ - ext_stats_dis:1, /* 8,9 */ - keep_overrun_rx:1, - save_bf:1; - volatile u_int disc_short_rx:1, - underrun_retry:2, - :3, - two_frames:1, /* 8,9 */ - dyn_tbd:1; /* 8,9 */ - volatile u_int mediatype:1, /* 7 */ - :6, - csma_dis:1; /* 8,9 */ - volatile u_int tcp_udp_cksum:1, /* 9 */ - :3, - vlan_tco:1, /* 8,9 */ - link_wake_en:1, /* 8,9 */ - arp_wake_en:1, /* 8 */ - mc_wake_en:1; /* 8 */ - volatile u_int :3, - nsai:1, - preamble_length:2, - loopback:2; - volatile u_int linear_priority:3, /* 7 */ - :5; - volatile u_int linear_pri_mode:1, /* 7 */ - :3, - interfrm_spacing:4; - volatile u_int :8; - volatile u_int :8; - volatile u_int promiscuous:1, - bcast_disable:1, - wait_after_win:1, /* 8,9 */ - :1, - ignore_ul:1, /* 8,9 */ - crc16_en:1, /* 9 */ - :1, - crscdt:1; - volatile u_int fc_delay_lsb:8; /* 8,9 */ - volatile u_int fc_delay_msb:8; /* 8,9 */ - volatile u_int stripping:1, - padding:1, - rcv_crc_xfer:1, - long_rx_en:1, /* 8,9 */ - pri_fc_thresh:3, /* 8,9 */ - :1; - volatile u_int ia_wake_en:1, /* 8 */ - magic_pkt_dis:1, /* 8,9,!9ER */ - tx_fc_dis:1, /* 8,9 */ - rx_fc_restop:1, /* 8,9 */ - rx_fc_restart:1, /* 8,9 */ - fc_filter:1, /* 8,9 */ - force_fdx:1, - fdx_pin_en:1; - volatile u_int :5, - pri_fc_loc:1, /* 8,9 */ - multi_ia:1, - :1; - volatile u_int :3, - mc_all:1, - :4; -}; - -#define MAXMCADDR 80 -struct fxp_cb_mcs { - struct fxp_cb_tx *next; - struct mbuf *mb_head; - volatile u_int16_t cb_status; - volatile u_int16_t cb_command; - volatile u_int32_t link_addr; - volatile u_int16_t mc_cnt; - volatile u_int8_t mc_addr[MAXMCADDR][6]; -}; - -/* - * Number of DMA segments in a TxCB. Note that this is carefully - * chosen to make the total struct size an even power of two. It's - * critical that no TxCB be split across a page boundry since - * no attempt is made to allocate physically contiguous memory. - * - */ -#ifdef __alpha__ /* XXX - should be conditional on pointer size */ -#define FXP_NTXSEG 28 -#else -#define FXP_NTXSEG 29 -#endif - -struct fxp_tbd { - volatile u_int32_t tb_addr; - volatile u_int32_t tb_size; -}; -struct fxp_cb_tx { - struct fxp_cb_tx *next; - struct mbuf *mb_head; - volatile u_int16_t cb_status; - volatile u_int16_t cb_command; - volatile u_int32_t link_addr; - volatile u_int32_t tbd_array_addr; - volatile u_int16_t byte_count; - volatile u_int8_t tx_threshold; - volatile u_int8_t tbd_number; - /* - * The following structure isn't actually part of the TxCB, - * unless the extended TxCB feature is being used. In this - * case, the first two elements of the structure below are - * fetched along with the TxCB. - */ - volatile struct fxp_tbd tbd[FXP_NTXSEG]; -}; - -/* - * Control Block (CB) definitions - */ - -/* status */ -#define FXP_CB_STATUS_OK 0x2000 -#define FXP_CB_STATUS_C 0x8000 -/* commands */ -#define FXP_CB_COMMAND_NOP 0x0 -#define FXP_CB_COMMAND_IAS 0x1 -#define FXP_CB_COMMAND_CONFIG 0x2 -#define FXP_CB_COMMAND_MCAS 0x3 -#define FXP_CB_COMMAND_XMIT 0x4 -#define FXP_CB_COMMAND_RESRV 0x5 -#define FXP_CB_COMMAND_DUMP 0x6 -#define FXP_CB_COMMAND_DIAG 0x7 -/* command flags */ -#define FXP_CB_COMMAND_SF 0x0008 /* simple/flexible mode */ -#define FXP_CB_COMMAND_I 0x2000 /* generate interrupt on completion */ -#define FXP_CB_COMMAND_S 0x4000 /* suspend on completion */ -#define FXP_CB_COMMAND_EL 0x8000 /* end of list */ - -/* - * RFA definitions - */ - -struct fxp_rfa { - volatile u_int16_t rfa_status; - volatile u_int16_t rfa_control; - volatile u_int8_t link_addr[4]; - volatile u_int8_t rbd_addr[4]; - volatile u_int16_t actual_size; - volatile u_int16_t size; -}; -#define FXP_RFA_STATUS_RCOL 0x0001 /* receive collision */ -#define FXP_RFA_STATUS_IAMATCH 0x0002 /* 0 = matches station address */ -#define FXP_RFA_STATUS_S4 0x0010 /* receive error from PHY */ -#define FXP_RFA_STATUS_TL 0x0020 /* type/length */ -#define FXP_RFA_STATUS_FTS 0x0080 /* frame too short */ -#define FXP_RFA_STATUS_OVERRUN 0x0100 /* DMA overrun */ -#define FXP_RFA_STATUS_RNR 0x0200 /* no resources */ -#define FXP_RFA_STATUS_ALIGN 0x0400 /* alignment error */ -#define FXP_RFA_STATUS_CRC 0x0800 /* CRC error */ -#define FXP_RFA_STATUS_OK 0x2000 /* packet received okay */ -#define FXP_RFA_STATUS_C 0x8000 /* packet reception complete */ -#define FXP_RFA_CONTROL_SF 0x08 /* simple/flexible memory mode */ -#define FXP_RFA_CONTROL_H 0x10 /* header RFD */ -#define FXP_RFA_CONTROL_S 0x4000 /* suspend after reception */ -#define FXP_RFA_CONTROL_EL 0x8000 /* end of list */ - -/* - * Statistics dump area definitions - */ -struct fxp_stats { - volatile u_int32_t tx_good; - volatile u_int32_t tx_maxcols; - volatile u_int32_t tx_latecols; - volatile u_int32_t tx_underruns; - volatile u_int32_t tx_lostcrs; - volatile u_int32_t tx_deffered; - volatile u_int32_t tx_single_collisions; - volatile u_int32_t tx_multiple_collisions; - volatile u_int32_t tx_total_collisions; - volatile u_int32_t rx_good; - volatile u_int32_t rx_crc_errors; - volatile u_int32_t rx_alignment_errors; - volatile u_int32_t rx_rnr_errors; - volatile u_int32_t rx_overrun_errors; - volatile u_int32_t rx_cdt_errors; - volatile u_int32_t rx_shortframes; - volatile u_int32_t completion_status; -}; -#define FXP_STATS_DUMP_COMPLETE 0xa005 -#define FXP_STATS_DR_COMPLETE 0xa007 - -/* - * Serial EEPROM control register bits - */ -#define FXP_EEPROM_EESK 0x01 /* shift clock */ -#define FXP_EEPROM_EECS 0x02 /* chip select */ -#define FXP_EEPROM_EEDI 0x04 /* data in */ -#define FXP_EEPROM_EEDO 0x08 /* data out */ - -/* - * Serial EEPROM opcodes, including start bit - */ -#define FXP_EEPROM_OPC_ERASE 0x4 -#define FXP_EEPROM_OPC_WRITE 0x5 -#define FXP_EEPROM_OPC_READ 0x6 - -/* - * Management Data Interface opcodes - */ -#define FXP_MDI_WRITE 0x1 -#define FXP_MDI_READ 0x2 - -/* - * PHY device types - */ -#define FXP_PHY_DEVICE_MASK 0x3f00 -#define FXP_PHY_SERIAL_ONLY 0x8000 -#define FXP_PHY_NONE 0 -#define FXP_PHY_82553A 1 -#define FXP_PHY_82553C 2 -#define FXP_PHY_82503 3 -#define FXP_PHY_DP83840 4 -#define FXP_PHY_80C240 5 -#define FXP_PHY_80C24 6 -#define FXP_PHY_82555 7 -#define FXP_PHY_DP83840A 10 -#define FXP_PHY_82555B 11 diff --git a/c/src/libchip/network/open_eth.c b/c/src/libchip/network/open_eth.c deleted file mode 100644 index 88df0882cf..0000000000 --- a/c/src/libchip/network/open_eth.c +++ /dev/null @@ -1,767 +0,0 @@ -/* - * RTEMS driver for Opencores Ethernet Controller - * - * Weakly based on dec21140 rtems driver and open_eth linux driver - * Written by Jiri Gaisler, Gaisler Research - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - * - */ - -/* - * This driver current only supports architectures with the old style - * exception processing. The following checks try to keep this - * from being compiled on systems which can't support this driver. - * - * NOTE: The i386, ARM, and PowerPC use a different interrupt API than - * that used by this driver. - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#if defined(__i386__) || defined(__arm__) || defined(__PPC__) - #define OPENETH_NOT_SUPPORTED -#endif - -#if !defined(OPENETH_NOT_SUPPORTED) -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#ifdef malloc -#undef malloc -#endif -#ifdef free -#undef free -#endif - -extern rtems_isr_entry set_vector( rtems_isr_entry, rtems_vector_number, int ); - - /* -#define OPEN_ETH_DEBUG - */ - -#ifdef CPU_U32_FIX -extern void ipalign(struct mbuf *m); -#endif - -/* message descriptor entry */ -struct MDTX -{ - char *buf; -}; - -struct MDRX -{ - struct mbuf *m; -}; - -/* - * Number of OCs supported by this driver - */ -#define NOCDRIVER 1 - -/* - * Receive buffer size -- Allow for a full ethernet packet including CRC - */ -#define RBUF_SIZE 1536 - -#define ET_MINLEN 64 /* minimum message length */ - -/* - * RTEMS event used by interrupt handler to signal driver tasks. - * This must not be any of the events used by the network task synchronization. - */ -#define INTERRUPT_EVENT RTEMS_EVENT_1 - -/* - * RTEMS event used to start transmit daemon. - * This must not be the same as INTERRUPT_EVENT. - */ -#define START_TRANSMIT_EVENT RTEMS_EVENT_2 - - /* event to send when tx buffers become available */ -#define OPEN_ETH_TX_WAIT_EVENT RTEMS_EVENT_3 - - /* suspend when all TX descriptors exhausted */ - /* -#define OETH_SUSPEND_NOTXBUF - */ - -#if (MCLBYTES < RBUF_SIZE) -# error "Driver must have MCLBYTES > RBUF_SIZE" -#endif - -/* - * Per-device data - */ -struct open_eth_softc -{ - - struct arpcom arpcom; - - oeth_regs *regs; - - int acceptBroadcast; - rtems_id rxDaemonTid; - rtems_id txDaemonTid; - - unsigned int tx_ptr; - unsigned int rx_ptr; - unsigned int txbufs; - unsigned int rxbufs; - struct MDTX *txdesc; - struct MDRX *rxdesc; - rtems_vector_number vector; - unsigned int en100MHz; - - /* - * Statistics - */ - unsigned long rxInterrupts; - unsigned long rxPackets; - unsigned long rxLengthError; - unsigned long rxNonOctet; - unsigned long rxBadCRC; - unsigned long rxOverrun; - unsigned long rxMiss; - unsigned long rxCollision; - - unsigned long txInterrupts; - unsigned long txDeferred; - unsigned long txHeartbeat; - unsigned long txLateCollision; - unsigned long txRetryLimit; - unsigned long txUnderrun; - unsigned long txLostCarrier; - unsigned long txRawWait; -}; - -static struct open_eth_softc oc; - -/* OPEN_ETH interrupt handler */ - -static rtems_isr -open_eth_interrupt_handler (rtems_vector_number v) -{ - uint32_t status; - - /* read and clear interrupt cause */ - - status = oc.regs->int_src; - oc.regs->int_src = status; - - /* Frame received? */ - - if (status & (OETH_INT_RXF | OETH_INT_RXE)) - { - oc.rxInterrupts++; - rtems_bsdnet_event_send (oc.rxDaemonTid, INTERRUPT_EVENT); - } -#ifdef OETH_SUSPEND_NOTXBUF - if (status & (OETH_INT_MASK_TXB | OETH_INT_MASK_TXC | OETH_INT_MASK_TXE)) - { - oc.txInterrupts++; - rtems_bsdnet_event_send (oc.txDaemonTid, OPEN_ETH_TX_WAIT_EVENT); - } -#endif - /* -#ifdef __leon__ - LEON_Clear_interrupt(v-0x10); -#endif - */ -} - -static uint32_t read_mii(uint32_t addr) -{ - while (oc.regs->miistatus & OETH_MIISTATUS_BUSY) {} - oc.regs->miiaddress = addr << 8; - oc.regs->miicommand = OETH_MIICOMMAND_RSTAT; - while (oc.regs->miistatus & OETH_MIISTATUS_BUSY) {} - if (!(oc.regs->miistatus & OETH_MIISTATUS_NVALID)) - return(oc.regs->miirx_data); - else { - printf("open_eth: failed to read mii\n"); - return (0); - } -} - -static void write_mii(uint32_t addr, uint32_t data) -{ - while (oc.regs->miistatus & OETH_MIISTATUS_BUSY) {} - oc.regs->miiaddress = addr << 8; - oc.regs->miitx_data = data; - oc.regs->miicommand = OETH_MIICOMMAND_WCTRLDATA; - while (oc.regs->miistatus & OETH_MIISTATUS_BUSY) {} -} -/* - * Initialize the ethernet hardware - */ -static void -open_eth_initialize_hardware (struct open_eth_softc *sc) -{ - struct mbuf *m; - int i; - int mii_cr = 0; - - oeth_regs *regs; - - regs = sc->regs; - - /* Reset the controller. */ - - regs->ctrlmoder = 0; - regs->moder = OETH_MODER_RST; /* Reset ON */ - regs->moder = 0; /* Reset OFF */ - - /* reset PHY and wait for complettion */ - mii_cr = 0x3300; - if (!sc->en100MHz) mii_cr = 0; - write_mii(0, mii_cr | 0x8000); - while (read_mii(0) & 0x8000) {} - if (!sc->en100MHz) write_mii(0, 0); - mii_cr = read_mii(0); - printf("open_eth: driver attached, PHY config : 0x%04" PRIx32 "\n", read_mii(0)); - -#ifdef OPEN_ETH_DEBUG - printf("mii_cr: %04x\n", mii_cr); - for (i=0;i<21;i++) - printf("mii_reg %2d : 0x%04x\n", i, read_mii(i)); -#endif - - /* Setting TXBD base to sc->txbufs */ - - regs->tx_bd_num = sc->txbufs; - - /* Initialize rx/tx pointers. */ - - sc->rx_ptr = 0; - sc->tx_ptr = 0; - - /* Set min/max packet length */ - regs->packet_len = 0x00400600; - - /* Set IPGT register to recomended value */ - regs->ipgt = 0x00000015; - - /* Set IPGR1 register to recomended value */ - regs->ipgr1 = 0x0000000c; - - /* Set IPGR2 register to recomended value */ - regs->ipgr2 = 0x00000012; - - /* Set COLLCONF register to recomended value */ - regs->collconf = 0x000f003f; - - /* initialize TX descriptors */ - - sc->txdesc = calloc(sc->txbufs, sizeof(*sc->txdesc)); - for (i = 0; i < sc->txbufs; i++) - { - sc->regs->xd[i].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC; - sc->txdesc[i].buf = calloc(1, OETH_MAXBUF_LEN); -#ifdef OPEN_ETH_DEBUG - printf("TXBUF: %08x\n", (int) sc->txdesc[i].buf); -#endif - } - sc->regs->xd[sc->txbufs - 1].len_status |= OETH_TX_BD_WRAP; - - /* allocate RX buffers */ - - sc->rxdesc = calloc(sc->rxbufs, sizeof(*sc->rxdesc)); - for (i = 0; i < sc->rxbufs; i++) - { - - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - m->m_pkthdr.rcvif = &sc->arpcom.ac_if; - sc->rxdesc[i].m = m; - sc->regs->xd[i + sc->txbufs].addr = mtod (m, uint32_t*); - sc->regs->xd[i + sc->txbufs].len_status = - OETH_RX_BD_EMPTY | OETH_RX_BD_IRQ; -#ifdef OPEN_ETH_DEBUG - printf("RXBUF: %08x\n", (int) sc->rxdesc[i].m); -#endif - } - sc->regs->xd[sc->rxbufs + sc->txbufs - 1].len_status |= OETH_RX_BD_WRAP; - - - /* set ethernet address. */ - - regs->mac_addr1 = sc->arpcom.ac_enaddr[0] << 8 | sc->arpcom.ac_enaddr[1]; - - uint32_t mac_addr0; - mac_addr0 = sc->arpcom.ac_enaddr[2]; - mac_addr0 <<= 8; - mac_addr0 |= sc->arpcom.ac_enaddr[3]; - mac_addr0 <<= 8; - mac_addr0 |= sc->arpcom.ac_enaddr[4]; - mac_addr0 <<= 8; - mac_addr0 |= sc->arpcom.ac_enaddr[5]; - - regs->mac_addr0 = mac_addr0; - - /* install interrupt vector */ - set_vector (open_eth_interrupt_handler, sc->vector, 1); - - /* clear all pending interrupts */ - - regs->int_src = 0xffffffff; - - /* MAC mode register: PAD, IFG, CRCEN */ - - regs->moder = OETH_MODER_PAD | OETH_MODER_CRCEN | ((mii_cr & 0x100) << 2); - - /* enable interrupts */ - - regs->int_mask = OETH_INT_MASK_RXF | OETH_INT_MASK_RXE | OETH_INT_MASK_RXC; - -#ifdef OETH_SUSPEND_NOTXBUF - regs->int_mask |= OETH_INT_MASK_TXB | OETH_INT_MASK_TXC | OETH_INT_MASK_TXE | OETH_INT_BUSY;*/ - sc->regs->xd[(sc->txbufs - 1)/2].len_status |= OETH_TX_BD_IRQ; - sc->regs->xd[sc->txbufs - 1].len_status |= OETH_TX_BD_IRQ; -#endif - - regs->moder |= OETH_MODER_RXEN | OETH_MODER_TXEN; -} - -static void -open_eth_rxDaemon (void *arg) -{ - struct ether_header *eh; - struct open_eth_softc *dp = (struct open_eth_softc *) &oc; - struct ifnet *ifp = &dp->arpcom.ac_if; - struct mbuf *m; - unsigned int len; - uint32_t len_status; - unsigned int bad; - rtems_event_set events; - - - for (;;) - { - - rtems_bsdnet_event_receive (INTERRUPT_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, &events); -#ifdef OPEN_ETH_DEBUG - printf ("r\n"); -#endif - - while (! - ((len_status = - dp->regs->xd[dp->rx_ptr+dp->txbufs].len_status) & OETH_RX_BD_EMPTY)) - { - bad = 0; - if (len_status & (OETH_RX_BD_TOOLONG | OETH_RX_BD_SHORT)) - { - dp->rxLengthError++; - bad = 1; - } - if (len_status & OETH_RX_BD_DRIBBLE) - { - dp->rxNonOctet++; - bad = 1; - } - if (len_status & OETH_RX_BD_CRCERR) - { - dp->rxBadCRC++; - bad = 1; - } - if (len_status & OETH_RX_BD_OVERRUN) - { - dp->rxOverrun++; - bad = 1; - } - if (len_status & OETH_RX_BD_MISS) - { - dp->rxMiss++; - bad = 1; - } - if (len_status & OETH_RX_BD_LATECOL) - { - dp->rxCollision++; - bad = 1; - } - - if (!bad) - { - /* pass on the packet in the receive buffer */ - len = len_status >> 16; - m = (struct mbuf *) (dp->rxdesc[dp->rx_ptr].m); - m->m_len = m->m_pkthdr.len = - len - sizeof (struct ether_header); - eh = mtod (m, struct ether_header *); - m->m_data += sizeof (struct ether_header); -#ifdef CPU_U32_FIX - ipalign(m); /* Align packet on 32-bit boundary */ -#endif - - ether_input (ifp, eh, m); - - /* get a new mbuf */ - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - dp->rxdesc[dp->rx_ptr].m = m; - dp->regs->xd[dp->rx_ptr + dp->txbufs].addr = - (uint32_t*) mtod (m, void *); - dp->rxPackets++; - } - - dp->regs->xd[dp->rx_ptr+dp->txbufs].len_status = - (dp->regs->xd[dp->rx_ptr+dp->txbufs].len_status & - ~OETH_TX_BD_STATS) | OETH_TX_BD_READY; - dp->rx_ptr = (dp->rx_ptr + 1) % dp->rxbufs; - } - } -} - -static int inside = 0; -static void -sendpacket (struct ifnet *ifp, struct mbuf *m) -{ - struct open_eth_softc *dp = ifp->if_softc; - unsigned char *temp; - struct mbuf *n; - uint32_t len, len_status; - - if (inside) printf ("error: sendpacket re-entered!!\n"); - inside = 1; - /* - * Waiting for Transmitter ready - */ - n = m; - - while (dp->regs->xd[dp->tx_ptr].len_status & OETH_TX_BD_READY) - { -#ifdef OETH_SUSPEND_NOTXBUF - rtems_event_set events; - rtems_bsdnet_event_receive (OPEN_ETH_TX_WAIT_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_MILLISECONDS_TO_TICKS(500), &events); -#endif - } - - len = 0; - temp = (unsigned char *) dp->txdesc[dp->tx_ptr].buf; - dp->regs->xd[dp->tx_ptr].addr = (uint32_t*) temp; - -#ifdef OPEN_ETH_DEBUG - printf("TXD: 0x%08x\n", (int) m->m_data); -#endif - for (;;) - { -#ifdef OPEN_ETH_DEBUG - int i; - printf("MBUF: 0x%08x : ", (int) m->m_data); - for (i=0;im_len;i++) - printf("%x%x", (m->m_data[i] >> 4) & 0x0ff, m->m_data[i] & 0x0ff); - printf("\n"); -#endif - len += m->m_len; - if (len <= RBUF_SIZE) - memcpy ((void *) temp, (char *) m->m_data, m->m_len); - temp += m->m_len; - if ((m = m->m_next) == NULL) - break; - } - - m_freem (n); - - /* don't send long packets */ - - if (len <= RBUF_SIZE) { - - /* Clear all of the status flags. */ - len_status = dp->regs->xd[dp->tx_ptr].len_status & ~OETH_TX_BD_STATS; - - /* If the frame is short, tell CPM to pad it. */ - if (len < ET_MINLEN) { - len_status |= OETH_TX_BD_PAD; - len = ET_MINLEN; - } - else - len_status &= ~OETH_TX_BD_PAD; - - /* write buffer descriptor length and status */ - len_status &= 0x0000ffff; - len_status |= (len << 16) | (OETH_TX_BD_READY | OETH_TX_BD_CRC); - dp->regs->xd[dp->tx_ptr].len_status = len_status; - dp->tx_ptr = (dp->tx_ptr + 1) % dp->txbufs; - - } - inside = 0; -} - -/* - * Driver transmit daemon - */ -static void -open_eth_txDaemon (void *arg) -{ - struct open_eth_softc *sc = (struct open_eth_softc *) arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - rtems_event_set events; - - for (;;) - { - /* - * Wait for packet - */ - - rtems_bsdnet_event_receive (START_TRANSMIT_EVENT, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, &events); -#ifdef OPEN_ETH_DEBUG - printf ("t\n"); -#endif - - /* - * Send packets till queue is empty - */ - for (;;) - { - /* - * Get the next mbuf chain to transmit. - */ - IF_DEQUEUE (&ifp->if_snd, m); - if (!m) - break; - sendpacket (ifp, m); - } - ifp->if_flags &= ~IFF_OACTIVE; - } -} - - -static void -open_eth_start (struct ifnet *ifp) -{ - struct open_eth_softc *sc = ifp->if_softc; - - rtems_bsdnet_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT); - ifp->if_flags |= IFF_OACTIVE; -} - -/* - * Initialize and start the device - */ -static void -open_eth_init (void *arg) -{ - struct open_eth_softc *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - - if (sc->txDaemonTid == 0) - { - - /* - * Set up OPEN_ETH hardware - */ - open_eth_initialize_hardware (sc); - - /* - * Start driver tasks - */ - sc->rxDaemonTid = rtems_bsdnet_newproc ("DCrx", 4096, - open_eth_rxDaemon, sc); - sc->txDaemonTid = rtems_bsdnet_newproc ("DCtx", 4096, - open_eth_txDaemon, sc); - } - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; - -} - -/* - * Stop the device - */ -static void -open_eth_stop (struct open_eth_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - - ifp->if_flags &= ~IFF_RUNNING; - - sc->regs->moder = 0; /* RX/TX OFF */ - sc->regs->moder = OETH_MODER_RST; /* Reset ON */ - sc->regs->moder = 0; /* Reset OFF */ -} - - -/* - * Show interface statistics - */ -static void -open_eth_stats (struct open_eth_softc *sc) -{ - printf (" Rx Packets:%-8lu", sc->rxPackets); - printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); - printf (" Length:%-8lu", sc->rxLengthError); - printf (" Non-octet:%-8lu\n", sc->rxNonOctet); - printf (" Bad CRC:%-8lu", sc->rxBadCRC); - printf (" Overrun:%-8lu", sc->rxOverrun); - printf (" Miss:%-8lu", sc->rxMiss); - printf (" Collision:%-8lu\n", sc->rxCollision); - - printf (" Tx Interrupts:%-8lu", sc->txInterrupts); - printf (" Deferred:%-8lu", sc->txDeferred); - printf (" Missed Hearbeat:%-8lu\n", sc->txHeartbeat); - printf (" No Carrier:%-8lu", sc->txLostCarrier); - printf ("Retransmit Limit:%-8lu", sc->txRetryLimit); - printf (" Late Collision:%-8lu\n", sc->txLateCollision); - printf (" Underrun:%-8lu", sc->txUnderrun); - printf (" Raw output wait:%-8lu\n", sc->txRawWait); -} - -/* - * Driver ioctl handler - */ -static int -open_eth_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - struct open_eth_softc *sc = ifp->if_softc; - int error = 0; - - switch (command) - { - case SIOCGIFADDR: - case SIOCSIFADDR: - ether_ioctl (ifp, command, data); - break; - - case SIOCSIFFLAGS: - switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) - { - case IFF_RUNNING: - open_eth_stop (sc); - break; - - case IFF_UP: - open_eth_init (sc); - break; - - case IFF_UP | IFF_RUNNING: - open_eth_stop (sc); - open_eth_init (sc); - break; - - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - open_eth_stats (sc); - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } - - return error; -} - -/* - * Attach an OPEN_ETH driver to the system - */ -int -rtems_open_eth_driver_attach (struct rtems_bsdnet_ifconfig *config, - open_eth_configuration_t * chip) -{ - struct open_eth_softc *sc; - struct ifnet *ifp; - int mtu; - int unitNumber; - char *unitName; - - /* parse driver name */ - if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0) - return 0; - - sc = &oc; - ifp = &sc->arpcom.ac_if; - memset (sc, 0, sizeof (*sc)); - - if (config->hardware_address) - { - memcpy (sc->arpcom.ac_enaddr, config->hardware_address, - ETHER_ADDR_LEN); - } - else - { - memset (sc->arpcom.ac_enaddr, 0x08, ETHER_ADDR_LEN); - } - - if (config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - - sc->acceptBroadcast = !config->ignore_broadcast; - sc->regs = chip->base_address; - sc->vector = chip->vector; - sc->txbufs = chip->txd_count; - sc->rxbufs = chip->rxd_count; - sc->en100MHz = chip->en100MHz; - - - /* - * Set up network interface values - */ - ifp->if_softc = sc; - ifp->if_unit = unitNumber; - ifp->if_name = unitName; - ifp->if_mtu = mtu; - ifp->if_init = open_eth_init; - ifp->if_ioctl = open_eth_ioctl; - ifp->if_start = open_eth_start; - ifp->if_output = ether_output; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; - if (ifp->if_snd.ifq_maxlen == 0) - ifp->if_snd.ifq_maxlen = ifqmaxlen; - - /* - * Attach the interface - */ - if_attach (ifp); - ether_ifattach (ifp); - -#ifdef OPEN_ETH_DEBUG - printf ("OPEN_ETH : driver has been attached\n"); -#endif - return 1; -}; - -#endif /* OPENETH_NOT_SUPPORTED */ diff --git a/c/src/libchip/network/smc91111.c b/c/src/libchip/network/smc91111.c deleted file mode 100644 index 45c87e8245..0000000000 --- a/c/src/libchip/network/smc91111.c +++ /dev/null @@ -1,1653 +0,0 @@ -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include -#include - -#include - -/* - * This driver currently only supports SPARC with the old style - * exception processing and the Phytec Phycore MPC5554. - * This test keeps it from being compiled on systems which haven't been - * tested. - * - */ - -#if defined(HAS_SMC91111) - #define SMC91111_SUPPORTED -#endif - -#if defined(HAS_SMC91111) - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#define SMC91111_INTERRUPT_EVENT RTEMS_EVENT_1 /* RTEMS event used by interrupt handler to signal driver tasks. This must not be any of the events used by the network task synchronization. */ -#define SMC91111_START_TRANSMIT_EVENT RTEMS_EVENT_2 /* RTEMS event used to start transmit/receive daemon. This must not be the same as INTERRUPT_EVENT. */ -#define SMC91111_TX_WAIT_EVENT RTEMS_EVENT_3 /* event to send when tx buffers become available */ - -/* Set to perms of: - 0 disables all debug output - 1 for process debug output - 2 for added data IO output: get_reg, put_reg - 4 for packet allocation/free output - 8 for only startup status, so we can tell we're installed OK - 16 dump phy read/write - 32 precise register dump - 64 dump packets -*/ -/*#define DEBUG (-1)*/ -/*#define DEBUG (-1 & ~(16))*/ -#define DEBUG (0) -/*#define DEBUG (1)*/ - -#include "smc91111config.h" -#include - -#ifdef BSP_FEATURE_IRQ_EXTENSION - #include -#endif - -struct lan91cxx_priv_data smc91111; - -int lan91cxx_hardware_init(struct lan91cxx_priv_data *cpd); -static uint16_t lan91cxx_read_phy(struct lan91cxx_priv_data *cpd, - uint8_t phyaddr, uint8_t phyreg); -static void lan91cxx_write_phy(struct lan91cxx_priv_data *cpd, - uint8_t phyaddr, uint8_t phyreg, - uint16_t value); -static void lan91cxx_start(struct ifnet *ifp); -static void smc91111_start(struct ifnet *ifp); -static int smc_probe(struct lan91cxx_priv_data *cpd); -static void smc91111_stop(struct lan91cxx_priv_data *cpd); -static void smc91111_init(void *arg); -#ifndef BSP_FEATURE_IRQ_EXTENSION -static void lan91cxx_finish_sent(struct lan91cxx_priv_data *cpd); -#endif -#if 0 -static int lan91cxx_phy_fixed(struct lan91cxx_priv_data *cpd); -static void lan91cxx_phy_configure(struct lan91cxx_priv_data *cpd); -#endif - -#define min(l,r) ((l) < (r) ? (l) : (r)) -#define max(l,r) ((l) > (r) ? (l) : (r)) - -#ifndef BSP_FEATURE_IRQ_EXTENSION -/* \ ------------- Interrupt ------------- \ */ -static void lan91cxx_interrupt_handler(void *arg) -{ - struct lan91cxx_priv_data *cpd = arg; - unsigned short irq, event; - unsigned short oldbase; - unsigned short oldpointer; - INCR_STAT(cpd, interrupts); - DEBUG_FUNCTION(); - - HAL_READ_UINT16(cpd->base + (LAN91CXX_BS), oldbase); - oldpointer = get_reg(cpd, LAN91CXX_POINTER); - - /* Get the (unmasked) requests */ - irq = get_reg(cpd, LAN91CXX_INTERRUPT); - event = irq & (irq >> 8) & 0xff; - if (0 == event) - return; - - /*put_reg(cpd, LAN91CXX_INTERRUPT, irq ); */ /* ack interrupts */ - - if (event & LAN91CXX_INTERRUPT_ERCV_INT) { - db_printf("Early receive interrupt"); - } else if (event & LAN91CXX_INTERRUPT_EPH_INT) { - db_printf("ethernet protocol handler failures"); - } else if (event & LAN91CXX_INTERRUPT_RX_OVRN_INT) { - db_printf("receive overrun"); - } else if (event & LAN91CXX_INTERRUPT_ALLOC_INT) { - db_printf("allocation interrupt"); - } else { - - if (event & LAN91CXX_INTERRUPT_TX_SET) { - db_printf("#*tx irq\n"); - lan91cxx_finish_sent(cpd); - put_reg(cpd, LAN91CXX_INTERRUPT, - (irq & 0xff00) | LAN91CXX_INTERRUPT_TX_INT); - - /*rtems_bsdnet_event_send (cpd->txDaemonTid, SMC91111_INTERRUPT_EVENT); */ - /*put_reg(cpd, LAN91CXX_INTERRUPT, (irq & 0xff00) | LAN91CXX_INTERRUPT_TX_INT); */ - /*rtems_bsdnet_event_send (cpd->txDaemonTid, SMC91111_TX_WAIT_EVENT); */ - } - if (event & LAN91CXX_INTERRUPT_RCV_INT) { - db_printf("#*rx irq\n"); - rtems_bsdnet_event_send(cpd->rxDaemonTid, - SMC91111_INTERRUPT_EVENT); - } - if (event & - ~(LAN91CXX_INTERRUPT_TX_SET | LAN91CXX_INTERRUPT_RCV_INT)) - db_printf("Unknown interrupt\n"); - } - db_printf("out %s\n", __FUNCTION__); - - put_reg(cpd, LAN91CXX_POINTER, oldpointer); - HAL_WRITE_UINT16(cpd->base + (LAN91CXX_BS), oldbase); -} -#endif - -/* \ ------------- Rx receive ------------- \ */ - - /**/ -/* This function is called as a result of the "readpacket()" call.*/ -/* Its job is to actually fetch data for a packet from the hardware once*/ -/* memory buffers have been allocated for the packet. Note that the buffers*/ -/* may come in pieces, using a mbuf list. */ -static void lan91cxx_recv(struct lan91cxx_priv_data *cpd, struct mbuf *m) -{ - struct ifnet *ifp = &cpd->arpcom.ac_if; - struct ether_header *eh; - short mlen = 0, plen; - char *start; - rxd_t *data = NULL, val; -#if DEBUG & 64 - rxd_t lp = 0; -#else - /* start is only read with debug enabled */ - (void)start; -#endif - struct mbuf *n; - dbg_prefix = "<"; - - DEBUG_FUNCTION(); - INCR_STAT(cpd, rx_deliver); - - /* ############ read packet ############ */ - - put_reg(cpd, LAN91CXX_POINTER, - (LAN91CXX_POINTER_RCV | LAN91CXX_POINTER_READ | - LAN91CXX_POINTER_AUTO_INCR)); - val = get_data(cpd); - - /* packet length (minus header/footer) */ -#ifdef LAN91CXX_32BIT_RX - val = CYG_LE32_TO_CPU(val); - plen = (val >> 16) - 6; -#else - val = CYG_LE16_TO_CPU(val); - plen = get_data(cpd); - plen = CYG_LE16_TO_CPU(plen) - 6; -#endif - - if ( cpd->c111_reva || LAN91CXX_RX_STATUS_IS_ODD(cpd, val) ) /* RevA Odd-bit BUG */ - plen++; - - for (n = m; n; n = n->m_next) { -#ifdef LAN91CXX_32BIT_RX - if (mlen == 2) { -#if DEBUG & 64 - db_printf("Appending to last apacket\n"); -#endif - - val = get_data(cpd); - *((unsigned short *)data) = (val >> 16) & 0xffff; - plen -= 2; - data = (rxd_t *) n->m_data; - start = (char *)data; - mlen = n->m_len; - if ((data) && (mlen > 1)) { - *(unsigned short *)data = (val & 0xffff); - data = (rxd_t *)((unsigned short *)data + 1); - plen -= 2; - mlen -= 2; - } - } else { - data = (rxd_t *) n->m_data; - start = (char *)data; - mlen = n->m_len; - } -#else - data = (rxd_t *) n->m_data; - start = (char *)data; - mlen = n->m_len; -#endif - - db1_printf("<[packet : mlen 0x%x, plen 0x%x]\n", mlen, plen); - - if (data) { - while (mlen >= sizeof(*data)) { -#ifdef LAN91CXX_32BIT_RX - val = get_data(cpd); - *(unsigned short *)data = (val >> 16) & 0xffff; - data = (rxd_t *)((unsigned short *)data + 1); - *(unsigned short *)data = (val & 0xffff); - data = (rxd_t *)((unsigned short *)data + 1); -#else - *data++ = get_data(cpd); -#endif - mlen -= sizeof(*data); - plen -= sizeof(*data); - } - } else { /* must actively discard ie. read it from the chip anyway. */ - while (mlen >= sizeof(*data)) { - (void)get_data(cpd); - mlen -= sizeof(*data); - plen -= sizeof(*data); - } - } - -#if DEBUG & 64 - lp = 0; - while (((int)start) < ((int)data)) { - unsigned char a = *(start++); - unsigned char b = *(start++); - db64_printf("%02x %02x ", a, b); - lp += 2; - if (lp >= 16) { - db64_printf("\n"); - lp = 0; - } - } - db64_printf(" \n"); -#endif - } - val = get_data(cpd); /* Read control word (and potential data) unconditionally */ -#ifdef LAN91CXX_32BIT_RX - if (plen & 2) { - if (data && (mlen>1) ) { - *(unsigned short *)data = (val >> 16) & 0xffff; - data = (rxd_t *)((unsigned short *)data + 1); - val <<= 16; - mlen-=2; - } - } - if ( (plen & 1) && data && (mlen>0) ) - *(unsigned char *)data = val >> 24; -#else - val = CYG_LE16_TO_CPU(val); - cp = (unsigned char *)data; - - CYG_ASSERT(val & LAN91CXX_CONTROLBYTE_RX, "Controlbyte is not for Rx"); - CYG_ASSERT((1 == mlen) == (0 != LAN91CXX_CONTROLBYTE_IS_ODD(cpd, val)), - "Controlbyte does not match"); - if (data && (1 == mlen) && LAN91CXX_CONTROLBYTE_IS_ODD(cpd, val)) { - cval = val & 0x00ff; /* last byte contains data */ - *cp = cval; - } -#endif - - val = get_reg(cpd, LAN91CXX_FIFO_PORTS); - if (0x8000 & val) { /* Then the Rx FIFO is empty */ - db4_printf - ("<+Rx packet NOT freed, stat is %x (expected %x)\n", - val, cpd->rxpacket); - } else { - db4_printf("<+Rx packet freed %x (expected %x)\n", - 0xff & (val >> 8), cpd->rxpacket); - } - - CYG_ASSERT((0xff & (val >> 8)) == cpd->rxpacket, - "Unexpected rx packet"); - - /* ############ free packet ############ */ - /* Free packet */ - put_reg(cpd, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_remrel_rx_frame); - - dbg_prefix = ""; - - /* Remove the mac header. This is different from the NetBSD stack. */ - eh = mtod(m, struct ether_header *); - m->m_data += sizeof(struct ether_header); - m->m_len -= sizeof(struct ether_header); - m->m_pkthdr.len -= sizeof(struct ether_header); - - ether_input(ifp, eh, m); - -} - -/* allocate mbuf chain */ -static struct mbuf *smc91111_allocmbufchain(int totlen, struct ifnet *ifp) -{ - - struct mbuf *m, *m0, *newm; - int len; - - MGETHDR(m0, M_DONTWAIT, MT_DATA); - if (m0 == 0) - return (0); - m0->m_pkthdr.rcvif = ifp; - m0->m_pkthdr.len = totlen; - len = MHLEN; - m = m0; - - /* This loop goes through and allocates mbufs for all the data we will be copying in. */ - while (totlen > 0) { - if (totlen >= MINCLSIZE) { - MCLGET(m, M_DONTWAIT); - if ((m->m_flags & M_EXT) == 0) - goto bad; - len = MCLBYTES; - } - - if (m == m0) { - caddr_t newdata = (caddr_t) - ALIGN(m->m_data + - sizeof(struct ether_header)) - - sizeof(struct ether_header); - len -= newdata - m->m_data; - m->m_data = newdata; - } - - m->m_len = len = min(totlen, len); - - totlen -= len; - if (totlen > 0) { - MGET(newm, M_DONTWAIT, MT_DATA); - if (newm == 0) - goto bad; - len = MLEN; - m = m->m_next = newm; - } - } - return (m0); - - bad: - m_freem(m0); - return (0); -} - -static int readpacket(struct lan91cxx_priv_data *cpd) -{ - struct mbuf *m; - unsigned short stat, complen; - struct ifnet *ifp = &cpd->arpcom.ac_if; -#ifdef LAN91CXX_32BIT_RX - uint32_t val; -#endif - - DEBUG_FUNCTION(); - - /* ############ read packet nr ############ */ - stat = get_reg(cpd, LAN91CXX_FIFO_PORTS); - db1_printf("+LAN91CXX_FIFO_PORTS: 0x%04x\n", stat); - - if (0x8000 & stat) { - /* Then the Rx FIFO is empty */ - db4_printf("!RxEvent with empty fifo\n"); - return 0; - } - - INCR_STAT(cpd, rx_count); - - db4_printf("+Rx packet allocated %x (previous %x)\n", - 0xff & (stat >> 8), cpd->rxpacket); - - /* There is an Rx Packet ready */ - cpd->rxpacket = 0xff & (stat >> 8); - - /* ############ read packet header ############ */ - /* Read status and (word) length */ - put_reg(cpd, LAN91CXX_POINTER, - (LAN91CXX_POINTER_RCV | LAN91CXX_POINTER_READ | - LAN91CXX_POINTER_AUTO_INCR | 0x0000)); -#ifdef LAN91CXX_32BIT_RX - val = get_data(cpd); - val = CYG_LE32_TO_CPU(val); - stat = val & 0xffff; - complen = ((val >> 16) & 0xffff) - 6; /* minus header/footer words */ -#else - stat = get_data(cpd); - stat = CYG_LE16_TO_CPU(stat); - complen = get_data(cpd); - complen = CYG_LE16_TO_CPU(len) - 6; /* minus header/footer words */ -#endif - -#ifdef KEEP_STATISTICS - if (stat & LAN91CXX_RX_STATUS_ALIGNERR) - INCR_STAT(cpd, rx_align_errors); - /*if ( stat & LAN91CXX_RX_STATUS_BCAST ) INCR_STAT( ); */ - if (stat & LAN91CXX_RX_STATUS_BADCRC) - INCR_STAT(cpd, rx_crc_errors); - if (stat & LAN91CXX_RX_STATUS_TOOLONG) - INCR_STAT(cpd, rx_too_long_frames); - if (stat & LAN91CXX_RX_STATUS_TOOSHORT) - INCR_STAT(cpd, rx_short_frames); - /*if ( stat & LAN91CXX_RX_STATUS_MCAST ) INCR_STAT( ); */ -#endif /* KEEP_STATISTICS */ - - if ((stat & LAN91CXX_RX_STATUS_BAD) == 0) { - INCR_STAT(cpd, rx_good); - /* Then it's OK */ - - if (cpd->c111_reva || LAN91CXX_RX_STATUS_IS_ODD(cpd, stat)) /* RevA Odd-bit BUG */ - complen++; - -#if DEBUG & 1 - db_printf("good rx - stat: 0x%04x, len: 0x%04x\n", stat, - complen); -#endif - /* Check for bogusly short packets; can happen in promisc mode: */ - /* Asserted against and checked by upper layer driver. */ - if (complen > sizeof(struct ether_header)) { - /* then it is acceptable; offer the data to the network stack */ - - complen = ((complen + 3) & ~3); - - m = smc91111_allocmbufchain(complen, ifp); - { - struct mbuf *n = m; - db_printf("mbuf-chain:"); - while (n) { - db_printf("[%" PRIxPTR ":%x]", - mtod(n, uintptr_t), - (unsigned int)(n->m_len)); - n = n->m_next; - } - db_printf("\n"); - } - - if (m) { - /* fetch packet data into mbuf chain */ - lan91cxx_recv(cpd, m); - return 1; - } - } - /*(sc->funs->eth_drv->recv)(sc, len); */ - } - - /* Not OK for one reason or another... */ - db1_printf("!bad rx: stat: 0x%04x, len: 0x%04x\n", stat, complen); - - /* ############ free packet ############ */ - /* Free packet */ - put_reg(cpd, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_remrel_rx_frame); - return 1; - -} - -static void smc91111_rxDaemon(void *arg) -{ - struct lan91cxx_priv_data *cpd = arg; - rtems_event_set events; - DEBUG_FUNCTION(); - - for (;;) { - rtems_bsdnet_event_receive(INTERRUPT_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, &events); - - /* read until read fifo is empty */ - while (!(get_reg(cpd, LAN91CXX_FIFO_PORTS) & 0x8000)) { - readpacket(cpd); - } - } -} - -/* \ ------------- Tx send ------------- \ */ - -static void sendpacket(struct ifnet *ifp, struct mbuf *m) -{ - struct lan91cxx_priv_data *cpd = ifp->if_softc; - int i, len, plen, tcr, odd; - struct mbuf *n = m; - unsigned short *sdata = NULL; - unsigned short ints, control; - uint16_t packet, status; - dbg_prefix = ">"; - DEBUG_FUNCTION(); - - cpd->txbusy = 1; - - /* Worry about the TX engine stopping. */ - tcr = get_reg(cpd, LAN91CXX_TCR); - if (0 == (LAN91CXX_TCR_TXENA & tcr)) { - db1_printf("> ENGINE RESTART: tcr %x\n", tcr); - tcr |= LAN91CXX_TCR_TXENA; - put_reg(cpd, LAN91CXX_TCR, tcr); - } - - /* ############ packet allocation ############ */ - - /* Find packet length */ - plen = 0; - while (n) { - plen += n->m_len; - n = n->m_next; - } - - /* Alloc new TX packet */ - do { - put_reg(cpd, LAN91CXX_MMU_COMMAND, - LAN91CXX_MMU_alloc_for_tx | ((plen >> 8) & 0x07)); - - i = 1024 * 1024; - do { - status = get_reg(cpd, LAN91CXX_INTERRUPT); - } while (0 == (status & LAN91CXX_INTERRUPT_ALLOC_INT) - && (--i > 0)); - if (i) - packet = get_reg(cpd, LAN91CXX_PNR); - else - packet = 0xffff; - db1_printf(">+allocated packet %04x\n", packet); - - packet = packet >> 8; - if (packet & 0x80) { - /* Hm.. Isn't this a dead end? */ - db1_printf("Allocation failed! Retrying...\n"); - continue; - } - } while (0); - - db4_printf(">+Tx packet allocated %x (previous %x)\n", - packet, cpd->txpacket); - - cpd->txpacket = packet; - - /* ############ assemble packet data ############ */ - - /* prepare send */ - put_reg(cpd, LAN91CXX_PNR, packet); - /* Note: Check FIFO state here before continuing? */ - put_reg(cpd, LAN91CXX_POINTER, LAN91CXX_POINTER_AUTO_INCR | 0x0000); - /* Pointer is now set, and the proper bank is selected for */ - /* data writes. */ - - /* Prepare header: */ - put_data(cpd, CYG_CPU_TO_LE16(0)); /* reserve space for status word */ - /* packet length (includes status, byte-count and control shorts) */ - put_data(cpd, CYG_CPU_TO_LE16(0x7FE & (plen + 6))); /* Always even, always < 15xx(dec) */ - - /* Put data into buffer */ - odd = 0; - n = m; - while (n) { - sdata = (unsigned short *)n->m_data; - len = n->m_len; - - CYG_ASSERT(sdata, "!No sg data pointer here"); - - /* start on an odd offset? - * If last byte also (1byte mbuf with different pointer should not occur) - * let following code handle it - */ - if ( ((unsigned int)sdata & 1) && (len>1) ){ - put_data8(cpd,*(unsigned char *)sdata); - sdata = (unsigned short *)((unsigned int)sdata + 1); - odd = ~odd; - len--; - } - - /* speed up copying a bit, never copy last word */ - while(len >= 17){ - put_data(cpd, *(sdata)); - put_data(cpd, *(sdata+1)); - put_data(cpd, *(sdata+2)); - put_data(cpd, *(sdata+3)); - put_data(cpd, *(sdata+4)); - put_data(cpd, *(sdata+5)); - put_data(cpd, *(sdata+6)); - put_data(cpd, *(sdata+7)); - sdata += 8; - len -= 16; - } - - /* copy word wise, skip last word */ - while (len >= 3) { - put_data(cpd, *sdata++); - len -= sizeof(*sdata); - } - - /* one or two bytes left to put into fifo */ - if ( len > 1 ){ - /* the last 2bytes */ - if ( !odd || n->m_next ){ - put_data(cpd, *sdata++); - len -= sizeof(*sdata); - }else{ - /* write next byte, mark that we are not at an odd offset any more, - * remaining byte will be written outside while together with control byte. - */ - put_data8(cpd,*(unsigned char *)sdata); - sdata = (unsigned short *)((unsigned int)sdata + 1); - odd = 0; - len--; - /*break;*/ - } - }else if ( (len>0) && (n->m_next) ){ - /* one byte left to write, and more bytes is comming in next mbuf */ - put_data8(cpd,*(unsigned char *)sdata); - odd = ~odd; - } - - n = n->m_next; - } - - /* Lay down the control short unconditionally at the end. */ - /* (or it might use random memory contents) */ - control = 0; - if ( len > 0 ){ - if ( !odd ) { - /* Need to set ODD flag and insert the data */ - unsigned char onebyte = *(unsigned char *)sdata; - control = onebyte; - control |= LAN91CXX_CONTROLBYTE_ODD; - }else{ - put_data8(cpd,*(unsigned char *)sdata); - } - } - control |= LAN91CXX_CONTROLBYTE_CRC; /* Just in case... */ - put_data(cpd, CYG_CPU_TO_LE16(control)); - - m_freem(m); - CYG_ASSERT(sdata, "!No sg data pointer outside"); - - /* ############ start transmit ############ */ - - /* Ack TX empty int and unmask it. */ - ints = get_reg(cpd, LAN91CXX_INTERRUPT) & 0xff00; - put_reg(cpd, LAN91CXX_INTERRUPT, - ints | LAN91CXX_INTERRUPT_TX_EMPTY_INT); - put_reg(cpd, LAN91CXX_INTERRUPT, ints | LAN91CXX_INTERRUPT_TX_INT_M); /* notify on error only (Autorelease) */ - - /* Enqueue the packet */ - put_reg(cpd, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_enq_packet); - - ints = get_reg(cpd, LAN91CXX_INTERRUPT); - db1_printf(">END: ints at TX: %04x\n", ints); - dbg_prefix = ""; -} - -static void smc91111_txDaemon(void *arg) -{ - struct lan91cxx_priv_data *cpd = arg; - struct ifnet *ifp = &cpd->arpcom.ac_if; - struct mbuf *m; - rtems_event_set events; - DEBUG_FUNCTION(); - - for (;;) { - /* - * Wait for packet - */ - - rtems_bsdnet_event_receive - (SMC91111_START_TRANSMIT_EVENT, - RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events); - - /*IF_DEQUEUE (&ifp->if_snd, m); - if (m) { - sendpacket (ifp, m); - } */ - - for (;;) { - IF_DEQUEUE(&ifp->if_snd, m); - if (!m) - break; - sendpacket(ifp, m); - } - ifp->if_flags &= ~IFF_OACTIVE; - - } - -} - -/* start transmit */ -static void smc91111_start(struct ifnet *ifp) -{ - struct lan91cxx_priv_data *cpd = ifp->if_softc; - - if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) - return; - - rtems_bsdnet_event_send(cpd->txDaemonTid, START_TRANSMIT_EVENT); - ifp->if_flags |= IFF_OACTIVE; - -} - -#ifndef BSP_FEATURE_IRQ_EXTENSION -/* called after a tx error interrupt, freet the packet */ -static void lan91cxx_finish_sent(struct lan91cxx_priv_data *cpd) -{ - unsigned short packet, tcr; - int saved_packet; - - DEBUG_FUNCTION(); - - INCR_STAT(cpd, tx_complete); - - saved_packet = get_reg(cpd, LAN91CXX_PNR); - - /* Ack and mask TX interrupt set */ - /*ints = get_reg(cpd, LAN91CXX_INTERRUPT) & 0xff00; - ints |= LAN91CXX_INTERRUPT_TX_SET_ACK; - ints &= ~LAN91CXX_INTERRUPT_TX_SET_M; - put_reg(cpd, LAN91CXX_INTERRUPT, ints); */ - - /* Get number of completed packet and read the status word */ - packet = get_reg(cpd, LAN91CXX_FIFO_PORTS); - db1_printf("%s:START: fifo %04x \n", __FUNCTION__, packet); - - { - unsigned short reg; - - reg = get_reg(cpd, LAN91CXX_EPH_STATUS); - - /* Covering each bit in turn... */ - if (reg & LAN91CXX_STATUS_TX_UNRN) - INCR_STAT(cpd, tx_underrun); - if (reg & LAN91CXX_STATUS_LOST_CARR) - INCR_STAT(cpd, tx_carrier_loss); - if (reg & LAN91CXX_STATUS_LATCOL) - INCR_STAT(cpd, tx_late_collisions); - if (reg & LAN91CXX_STATUS_TX_DEFR) - INCR_STAT(cpd, tx_deferred); - if (reg & LAN91CXX_STATUS_SQET) - INCR_STAT(cpd, tx_sqetesterrors); - if (reg & LAN91CXX_STATUS_16COL) - INCR_STAT(cpd, tx_max_collisions); - if (reg & LAN91CXX_STATUS_MUL_COL) - INCR_STAT(cpd, tx_mult_collisions); - if (reg & LAN91CXX_STATUS_SNGL_COL) - INCR_STAT(cpd, tx_single_collisions); - if (reg & LAN91CXX_STATUS_TX_SUC) - INCR_STAT(cpd, tx_good); - - cpd->stats.tx_total_collisions = - cpd->stats.tx_late_collisions + - cpd->stats.tx_max_collisions + - cpd->stats.tx_mult_collisions + - cpd->stats.tx_single_collisions; - - /* We do not need to look in the Counter Register (LAN91CXX_COUNTER) - because it just mimics the info we already have above. */ - } - - /* We do not really care about Tx failure. Ethernet is not a reliable - medium. But we do care about the TX engine stopping. */ - tcr = get_reg(cpd, LAN91CXX_TCR); - if (0 == (LAN91CXX_TCR_TXENA & tcr)) { - db1_printf("%s: ENGINE RESTART: tcr %x \n", __FUNCTION__, tcr); - tcr |= LAN91CXX_TCR_TXENA; - put_reg(cpd, LAN91CXX_TCR, tcr); - } - - packet &= 0xff; - - /* and then free the packet */ - put_reg(cpd, LAN91CXX_PNR, cpd->txpacket); - put_reg(cpd, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_rel_packet); - - while (get_reg(cpd, LAN91CXX_MMU_COMMAND) & LAN91CXX_MMU_COMMAND_BUSY) ; - /* Don't change Packet Number Reg until busy bit is cleared */ - /* Per LAN91C111 Spec, Page 50 */ - put_reg(cpd, LAN91CXX_PNR, saved_packet); - -} -#endif - -/* \ ------------- Helpers ------------- \ */ - -/* - * Show interface statistics - */ -static void smc91111_stats(struct lan91cxx_priv_data *priv) -{ - printf("tx_good :%-8d\n", priv->stats.tx_good); - printf("tx_max_collisions :%-8d\n", priv->stats.tx_max_collisions); - printf("tx_late_collisions :%-8d\n", priv->stats.tx_late_collisions); - printf("tx_underrun :%-8d\n", priv->stats.tx_underrun); - printf("tx_carrier_loss :%-8d\n", priv->stats.tx_carrier_loss); - printf("tx_deferred :%-8d\n", priv->stats.tx_deferred); - printf("tx_sqetesterrors :%-8d\n", priv->stats.tx_sqetesterrors); - printf("tx_single_collisions:%-8d\n", priv->stats.tx_single_collisions); - printf("tx_mult_collisions :%-8d\n", priv->stats.tx_mult_collisions); - printf("tx_total_collisions :%-8d\n", priv->stats.tx_total_collisions); - printf("rx_good :%-8d\n", priv->stats.rx_good); - printf("rx_crc_errors :%-8d\n", priv->stats.rx_crc_errors); - printf("rx_align_errors :%-8d\n", priv->stats.rx_align_errors); - printf("rx_resource_errors :%-8d\n", priv->stats.rx_resource_errors); - printf("rx_overrun_errors :%-8d\n", priv->stats.rx_overrun_errors); - printf("rx_collisions :%-8d\n", priv->stats.rx_collisions); - printf("rx_short_frames :%-8d\n", priv->stats.rx_short_frames); - printf("rx_too_long_frames :%-8d\n", priv->stats.rx_too_long_frames); - printf("rx_symbol_errors :%-8d\n", priv->stats.rx_symbol_errors); - printf("interrupts :%-8d\n", priv->stats.interrupts); - printf("rx_count :%-8d\n", priv->stats.rx_count); - printf("rx_deliver :%-8d\n", priv->stats.rx_deliver); - printf("rx_resource :%-8d\n", priv->stats.rx_resource); - printf("rx_restart :%-8d\n", priv->stats.rx_restart); - printf("tx_count :%-8d\n", priv->stats.tx_count); - printf("tx_complete :%-8d\n", priv->stats.tx_complete); - printf("tx_dropped :%-8d\n", priv->stats.tx_dropped); -} - -/* - * Driver ioctl handler - */ -static int smc91111_ioctl(struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - struct lan91cxx_priv_data *cpd = ifp->if_softc; - int error = 0; - DEBUG_FUNCTION(); - - switch (command) { - case SIOCGIFADDR: - case SIOCSIFADDR: - db_printf("SIOCSIFADDR\n"); - ether_ioctl(ifp, command, data); - break; - - case SIOCSIFFLAGS: - db_printf("SIOCSIFFLAGS\n"); - switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { - case IFF_RUNNING: - smc91111_stop(cpd); - break; - - case IFF_UP: - smc91111_init(cpd); - break; - - case IFF_UP | IFF_RUNNING: - smc91111_stop(cpd); - smc91111_init(cpd); - break; - - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - db_printf("SIO_RTEMS_SHOW_STATS\n"); - smc91111_stats(cpd); - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } - - return error; -} - -/* - * Attach an SMC91111 driver to the system - */ -int _rtems_smc91111_driver_attach (struct rtems_bsdnet_ifconfig *config, - struct scmv91111_configuration * chip) -{ - struct ifnet *ifp; - struct lan91cxx_priv_data *cpd; - int unitNumber; - char *unitName; - int mtu; - DEBUG_FUNCTION(); - - /* parse driver name */ - if ((unitNumber = rtems_bsdnet_parse_driver_name(config, &unitName)) < 0) { - db_printf("Unitnumber < 0: %d\n", unitNumber); - return 0; - } - - db_printf("Unitnumber: %d, baseaddr: 0x%p\n", unitNumber, chip->baseaddr); - - cpd = &smc91111; - ifp = &cpd->arpcom.ac_if; - memset(cpd, 0, sizeof(*cpd)); - - cpd->config = *chip; - cpd->base = chip->baseaddr; - - if (smc_probe(cpd)) { - return 0; - } - - if (config->hardware_address) { - memcpy(cpd->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); - } else { -#ifdef SMC91111_ENADDR_IS_SETUP - /* The address was put in the chip at reset time. Retrieve it. */ - int i; - for (i = 0; i < sizeof(cpd->enaddr); i += 2) { - unsigned short r = get_reg(cpd, LAN91CXX_IA01 + i / 2); - cpd->arpcom.ac_enaddr[i] = r; - cpd->arpcom.ac_enaddr[i+1] = r >> 8; - } -#else - /* dummy default address */ - cpd->arpcom.ac_enaddr[0] = 0x12; - cpd->arpcom.ac_enaddr[1] = 0x13; - cpd->arpcom.ac_enaddr[2] = 0x14; - cpd->arpcom.ac_enaddr[3] = 0x15; - cpd->arpcom.ac_enaddr[4] = 0x16; - cpd->arpcom.ac_enaddr[5] = 0x17; -#endif - } - - cpd->enaddr[0] = cpd->arpcom.ac_enaddr[0]; - cpd->enaddr[1] = cpd->arpcom.ac_enaddr[1]; - cpd->enaddr[2] = cpd->arpcom.ac_enaddr[2]; - cpd->enaddr[3] = cpd->arpcom.ac_enaddr[3]; - cpd->enaddr[4] = cpd->arpcom.ac_enaddr[4]; - cpd->enaddr[5] = cpd->arpcom.ac_enaddr[5]; - cpd->rpc_cur_mode = - LAN91CXX_RPCR_LEDA_RX | LAN91CXX_RPCR_LEDB_LINK | - LAN91CXX_RPCR_ANEG; - - if (config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - - /* - * Set up network interface values - */ - ifp->if_softc = cpd; - ifp->if_unit = unitNumber; - ifp->if_name = unitName; - ifp->if_mtu = mtu; - ifp->if_init = smc91111_init; - ifp->if_ioctl = smc91111_ioctl; - ifp->if_start = smc91111_start; - ifp->if_output = ether_output; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; - if (ifp->if_snd.ifq_maxlen == 0) - ifp->if_snd.ifq_maxlen = ifqmaxlen; - - /* - * Attach the interface - */ - if_attach(ifp); - ether_ifattach(ifp); - -#if DEBUG - printf("SMC91111 : driver has been attached\n"); -#endif - - return 1; -}; - -/* \ ------------- Initialization ------------- \ */ - -/* - * Initialize and start the device - */ -static void smc91111_init(void *arg) -{ - struct lan91cxx_priv_data *cpd = arg; - struct ifnet *ifp = &cpd->arpcom.ac_if; - DEBUG_FUNCTION(); - - if (cpd->txDaemonTid == 0) { - - lan91cxx_hardware_init(cpd); - lan91cxx_start(ifp); - - cpd->rxDaemonTid = rtems_bsdnet_newproc("DCrx", 4096, - smc91111_rxDaemon, cpd); - cpd->txDaemonTid = - rtems_bsdnet_newproc("DCtx", 4096, smc91111_txDaemon, cpd); - } else { - lan91cxx_start(ifp); - } - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; -} - -/* - * Stop the device - */ -static void smc91111_stop(struct lan91cxx_priv_data *cpd) -{ - struct ifnet *ifp = &cpd->arpcom.ac_if; - DEBUG_FUNCTION(); - - ifp->if_flags &= ~IFF_RUNNING; - - /* Reset chip */ - put_reg(cpd, LAN91CXX_RCR, LAN91CXX_RCR_SOFT_RST); - put_reg(cpd, LAN91CXX_RCR, 0); - cpd->txbusy = cpd->within_send = 0; - -} - -int lan91cxx_hardware_init(struct lan91cxx_priv_data *cpd) -{ - unsigned short val; - int i; - - DEBUG_FUNCTION(); - - cpd->txbusy = cpd->within_send = 0; - - /* install interrupt vector */ -#ifdef BSP_FEATURE_IRQ_EXTENSION - { - rtems_status_code sc = RTEMS_SUCCESSFUL; - - sc = rtems_interrupt_handler_install( - cpd->config.vector, - cpd->config.info, - cpd->config.options, - cpd->config.interrupt_wrapper, - cpd - ); - if (sc != RTEMS_SUCCESSFUL) { - printf("rtems_interrupt_handler_install returned %d.\n", sc); - return 0; - } - } -#else - { - int rc; - - db_printf("Install lan91cxx isr at vec/irq %" PRIu32 "\n", cpd->config.vector); - rc = rtems_interrupt_handler_install(cpd->config.vector, "smc91cxx", - RTEMS_INTERRUPT_SHARED, lan91cxx_interrupt_handler, cpd); - if (rc != RTEMS_SUCCESSFUL) - return 0; - } -#endif - - /* Reset chip */ - put_reg(cpd, LAN91CXX_RCR, LAN91CXX_RCR_SOFT_RST); - put_reg(cpd, LAN91CXX_RCR, 0); - HAL_DELAY_US(100000); - put_reg(cpd, LAN91CXX_CONFIG, 0x9000); - put_reg(cpd, LAN91CXX_RCR, 0); - put_reg(cpd, LAN91CXX_TCR, 0); - put_reg(cpd, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_reset_mmu); - - val = get_reg(cpd, LAN91CXX_EPH_STATUS); - /* probe chip by reading the signature in BS register */ - val = get_banksel(cpd); - db9_printf("LAN91CXX - supposed BankReg @ %x = %04x\n", - (unsigned int)(cpd->base + LAN91CXX_BS), val); - - if ((0xff00 & val) != 0x3300) { - printf("No 91Cxx signature"); - printf("smsc_lan91cxx_init: No 91Cxx signature found\n"); - return 0; - } - - val = get_reg(cpd, LAN91CXX_REVISION); - - db9_printf("LAN91CXX - type: %01x, rev: %01x\n", - (val >> 4) & 0xf, val & 0xf); - - /* Set RevA flag for LAN91C111 so we can cope with the odd-bit bug. */ - cpd->c111_reva = (val == 0x3390); /* 90=A, 91=B, 92=C */ - - /* The controller may provide a function used to set up the ESA */ - if (cpd->config_enaddr) - (*cpd->config_enaddr) (cpd); - - db9_printf("LAN91CXX - status: %04x\n", val); - /* Use statically configured ESA from the private data */ - db9_printf - ("LAN91CXX - static ESA: %02x:%02x:%02x:%02x:%02x:%02x\n", - cpd->enaddr[0], cpd->enaddr[1], cpd->enaddr[2], - cpd->enaddr[3], cpd->enaddr[4], cpd->enaddr[5]); - /* Set up hardware address */ - for (i = 0; i < sizeof(cpd->enaddr); i += 2) - put_reg(cpd, LAN91CXX_IA01 + i / 2, - cpd->enaddr[i] | (cpd->enaddr[i + 1] << 8)); - - return 1; -} - -/* - 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. -*/ -static void lan91cxx_start(struct ifnet *ifp) -{ - struct lan91cxx_priv_data *cpd = ifp->if_softc; - - uint16_t intr; - uint16_t phy_ctl; - int delay; - DEBUG_FUNCTION(); - - HAL_DELAY_US(100000); - - /* 91C111 Errata. Internal PHY comes up disabled. Must enable here. */ - phy_ctl = lan91cxx_read_phy(cpd, 0, LAN91CXX_PHY_CTRL); - phy_ctl &= ~LAN91CXX_PHY_CTRL_MII_DIS; - lan91cxx_write_phy(cpd, 0, LAN91CXX_PHY_CTRL, phy_ctl); - - /* Start auto-negotiation */ - put_reg(cpd, LAN91CXX_RPCR, - LAN91CXX_RPCR_LEDA_RX | LAN91CXX_RPCR_LEDB_LINK | - LAN91CXX_RPCR_ANEG); - cpd->rpc_cur_mode = - LAN91CXX_RPCR_LEDA_RX | LAN91CXX_RPCR_LEDB_LINK | - LAN91CXX_RPCR_ANEG; - - /* wait for auto-negotiation to finish. */ - /* give it ~5 seconds before giving up (no cable?) */ - delay = 50; - while (!(lan91cxx_read_phy(cpd, 0, LAN91CXX_PHY_STAT) & 0x20)) { - if (--delay <= 0) { - printf("Timeout autonegotiation\n"); - break; - } - HAL_DELAY_US(100000); - } - - put_reg(cpd, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_reset_mmu); - - put_reg(cpd, LAN91CXX_INTERRUPT, 0); /* disable interrupts */ - intr = get_reg(cpd, LAN91CXX_INTERRUPT); - put_reg(cpd, LAN91CXX_INTERRUPT, intr & /* ack old interrupts */ - (LAN91CXX_INTERRUPT_TX_INT | - LAN91CXX_INTERRUPT_TX_EMPTY_INT | - LAN91CXX_INTERRUPT_RX_OVRN_INT | LAN91CXX_INTERRUPT_ERCV_INT)); - put_reg(cpd, LAN91CXX_RCR, - LAN91CXX_RCR_STRIP_CRC | LAN91CXX_RCR_RXEN | - LAN91CXX_RCR_ALMUL); - put_reg(cpd, LAN91CXX_TCR, LAN91CXX_TCR_TXENA | LAN91CXX_TCR_PAD_EN); - put_reg(cpd, LAN91CXX_CONTROL, LAN91CXX_CONTROL_AUTO_RELEASE); /* */ - put_reg(cpd, LAN91CXX_INTERRUPT, /* enable interrupts */ - LAN91CXX_INTERRUPT_RCV_INT_M); - - if ((0 -#ifdef ETH_DRV_FLAGS_PROMISC_MODE - != (flags & ETH_DRV_FLAGS_PROMISC_MODE) -#endif - ) || (ifp->if_flags & IFF_PROMISC) - ) { - /* Then we select promiscuous mode. */ - unsigned short rcr; - rcr = get_reg(cpd, LAN91CXX_RCR); - rcr |= LAN91CXX_RCR_PRMS; - put_reg(cpd, LAN91CXX_RCR, rcr); - } -} - -/* \ ------------- Probe ------------- \ */ - -static const char *chip_ids[15] = { - NULL, NULL, NULL, - /* 3 */ "SMC91C90/91C92", - /* 4 */ "SMC91C94", - /* 5 */ "SMC91C95", - /* 6 */ "SMC91C96", - /* 7 */ "SMC91C100", - /* 8 */ "SMC91C100FD", - /* 9 */ "SMC91C11xFD", - NULL, NULL, - NULL, NULL, NULL -}; - -static int smc_probe(struct lan91cxx_priv_data *cpd) -{ - unsigned short bank; - unsigned short revision_register; - - DEBUG_FUNCTION(); - - /* First, see if the high byte is 0x33 */ - HAL_READ_UINT16(cpd->base + (LAN91CXX_BS), bank); - bank = CYG_LE16_TO_CPU(bank); - if ((bank & 0xFF00) != 0x3300) { - db_printf("<1>Smc probe bank check 1 failed.\n"); - return -ENODEV; - } - /* The above MIGHT indicate a device, but I need to write to further - test this. */ - HAL_WRITE_UINT16(cpd->base + (LAN91CXX_BS), CYG_CPU_TO_LE16(0 >> 3)); - HAL_READ_UINT16(cpd->base + (LAN91CXX_BS), bank); - bank = CYG_LE16_TO_CPU(bank); - if ((bank & 0xFF00) != 0x3300) { - db_printf("<1>Smc probe bank check 2 failed.\n"); - return -ENODEV; - } -#if SMC_DEBUG > 3 - { - unsigned short bank16, bank16_0, bank16_1; - HAL_READ_UINT16(cpd->base + (LAN91CXX_BS), bank16); - bank = CYG_LE16_TO_CPU(bank); - HAL_READ_UINT8(cpd->base + (LAN91CXX_BS), bank16_0); - HAL_READ_UINT8(cpd->base + (LAN91CXX_BS + 1), bank16_1); - - db_printf - ("smc_probe:Bank read as a 16 bit value:0x%04x\n", bank16); - db_printf - ("smc_probe:Bank read as an 8 bit value:0x%02x\n", - bank16_0); - db_printf - ("smc_probe:Bank + 1 read as an 8 bit value:0x%02x\n", - bank16_1); - } -#endif - - /* check if the revision register is something that I recognize. - These might need to be added to later, as future revisions - could be added. */ - revision_register = get_reg(cpd, LAN91CXX_REVISION); - if (!chip_ids[(revision_register >> 4) & 0xF]) { - /* I don't recognize this chip, so... */ - db_printf - ("smc_probe: IO %" PRIxPTR ": Unrecognized revision register:" - " %x, Contact author. \n", (uintptr_t)cpd->base, - revision_register); - - return -ENODEV; - } - db_printf("LAN91CXX(0x%x) - type: %s, rev: %01x\n", - revision_register, - chip_ids[(revision_register >> 4) & 0xF], - revision_register & 0xf); - - /* Set RevA flag for LAN91C111 so we can cope with the odd-bit bug. */ - if (revision_register == 0x3390) { - db_printf("!Revision A\n"); - } - - return 0; -} - -#if 0 -/* \ ------------- PHY read/write ------------- \ */ -/*Sets the PHY to a configuration as determined by the user*/ -static int lan91cxx_phy_fixed(struct lan91cxx_priv_data *cpd) -{ - int my_fixed_caps; - int cfg1; - - DEBUG_FUNCTION(); - db4_printf("lan91cxx_phy_fixed: full duplex: %d, speed: %d\n", - cpd->config.ctl_rfduplx, cpd->config.ctl_rspeed); - - /* Enter Link Disable state */ - cfg1 = lan91cxx_read_phy(cpd, 0, LAN91CXX_PHY_CONFIG1); - cfg1 |= PHY_CFG1_LNKDIS; - lan91cxx_write_phy(cpd, 0, LAN91CXX_PHY_CONFIG1, cfg1); - - /* Set our fixed capabilities, Disable auto-negotiation */ - my_fixed_caps = 0; - - if (cpd->config.ctl_rfduplx) - my_fixed_caps |= LAN91CXX_PHY_CTRL_DPLX; - - if (cpd->config.ctl_rspeed == 100) - my_fixed_caps |= LAN91CXX_PHY_CTRL_SPEED; - - /* Write capabilities to the phy control register */ - lan91cxx_write_phy(cpd, 0, LAN91CXX_PHY_CTRL, my_fixed_caps); - - /* Re-Configure the Receive/Phy Control register */ - put_reg(cpd, LAN91CXX_RPCR, cpd->rpc_cur_mode); - - return (1); -} -#endif - -#if 0 -/*Configures the specified PHY using Autonegotiation. */ -static void lan91cxx_phy_configure(struct lan91cxx_priv_data *cpd) -{ - - unsigned int phyaddr; - unsigned int my_phy_caps; /* My PHY capabilities */ - unsigned int my_ad_caps; /* My Advertised capabilities */ - unsigned int status = 0; - int failed = 0, delay; - - DEBUG_FUNCTION(); - - /* Set the blocking flag */ - cpd->autoneg_active = 1; - - /* Get the detected phy address */ - phyaddr = cpd->phyaddr; - - /* Reset the PHY, setting all other bits to zero */ - lan91cxx_write_phy(cpd, 0, PHY_CNTL_REG, PHY_CNTL_RST); - - /* Wait for the reset to complete, or time out */ - delay = 50; - while (delay--) { - if (!(lan91cxx_read_phy(cpd, 0, PHY_CNTL_REG) - & PHY_CNTL_RST)) { - break; - } - HAL_DELAY_US(100000); - } - - if (delay < 1) { - db_printf("smc91111:!PHY reset timed out\n"); - goto smc_phy_configure_exit; - } - - /* Read PHY Register 18, Status Output */ - cpd->lastPhy18 = lan91cxx_read_phy(cpd, 0, PHY_INT_REG); - - /* Enable PHY Interrupts (for register 18) */ - /* Interrupts listed here are disabled */ - lan91cxx_write_phy(cpd, 0, PHY_MASK_REG, - PHY_INT_LOSSSYNC | PHY_INT_CWRD | PHY_INT_SSD - | PHY_INT_ESD | PHY_INT_RPOL | PHY_INT_JAB | - PHY_INT_SPDDET | PHY_INT_DPLXDET); - - /* Configure the Receive/Phy Control register */ - put_reg(cpd, LAN91CXX_RPCR, cpd->rpc_cur_mode); - - /* Copy our capabilities from PHY_STAT_REG to PHY_AD_REG */ - my_phy_caps = lan91cxx_read_phy(cpd, phyaddr, PHY_STAT_REG); - my_ad_caps = PHY_AD_CSMA; /* I am CSMA capable */ - - if (my_phy_caps & PHY_STAT_CAP_T4) - my_ad_caps |= PHY_AD_T4; - - if (my_phy_caps & PHY_STAT_CAP_TXF) - my_ad_caps |= PHY_AD_TX_FDX; - - if (my_phy_caps & PHY_STAT_CAP_TXH) - my_ad_caps |= PHY_AD_TX_HDX; - - if (my_phy_caps & PHY_STAT_CAP_TF) - my_ad_caps |= PHY_AD_10_FDX; - - if (my_phy_caps & PHY_STAT_CAP_TH) - my_ad_caps |= PHY_AD_10_HDX; - - /* Disable capabilities not selected by our user */ - if (cpd->config.ctl_rspeed != 100) { - my_ad_caps &= ~(PHY_AD_T4 | PHY_AD_TX_FDX | PHY_AD_TX_HDX); - } - - if (!cpd->config.ctl_rfduplx) { - my_ad_caps &= ~(PHY_AD_TX_FDX | PHY_AD_10_FDX); - } - - /* Update our Auto-Neg Advertisement Register */ - lan91cxx_write_phy(cpd, 0, PHY_AD_REG, my_ad_caps); - - db4_printf("smc91111:phy caps=%x\n", my_phy_caps); - db4_printf("smc91111:phy advertised caps=%x\n", my_ad_caps); - - /* If the user requested no auto neg, then go set his request */ - if (!(cpd->config.ctl_autoneg)) { - lan91cxx_phy_fixed(cpd); - - goto smc_phy_configure_exit; - } - - /* Restart auto-negotiation process in order to advertise my caps */ - lan91cxx_write_phy(cpd, 0, PHY_CNTL_REG, - PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST); - - /* wait for auto-negotiation to finish. */ - /* give it ~5 seconds before giving up (no cable?) */ - delay = 50; - while (! - ((status = - lan91cxx_read_phy(cpd, 0, LAN91CXX_PHY_STAT)) & 0x20)) { - if (--delay <= 0) { - printf("Timeout autonegotiation\n"); - failed = 1; - break; - } - - /* Restart auto-negotiation if remote fault */ - if (status & PHY_STAT_REM_FLT) { - db_printf("smc91111:PHY remote fault detected\n"); - - /* Restart auto-negotiation */ - db_printf("smc91111:PHY restarting auto-negotiation\n"); - lan91cxx_write_phy(cpd, 0, PHY_CNTL_REG, - PHY_CNTL_ANEG_EN | - PHY_CNTL_ANEG_RST | - PHY_CNTL_SPEED | PHY_CNTL_DPLX); - } - HAL_DELAY_US(100000); - } - - /* Fail if we detected an auto-negotiate remote fault */ - if (status & PHY_STAT_REM_FLT) { - db_printf("smc91111:PHY remote fault detected\n"); - failed = 1; - } - - /* The smc_phy_interrupt() routine will be called to update lastPhy18 */ - - /* Set our sysctl parameters to match auto-negotiation results */ - if (cpd->lastPhy18 & PHY_INT_SPDDET) { - db_printf("smc91111:PHY 100BaseT\n"); - cpd->rpc_cur_mode |= LAN91CXX_RPCR_SPEED; - } else { - db_printf("smc91111:PHY 10BaseT\n"); - cpd->rpc_cur_mode &= ~LAN91CXX_RPCR_SPEED; - } - - if (cpd->lastPhy18 & PHY_INT_DPLXDET) { - db_printf("smc91111:PHY Full Duplex\n"); - cpd->rpc_cur_mode |= LAN91CXX_RPCR_DPLX; - } else { - db_printf("smc91111:PHY Half Duplex\n"); - cpd->rpc_cur_mode &= ~LAN91CXX_RPCR_DPLX; - } - - /* Re-Configure the Receive/Phy Control register */ - put_reg(cpd, LAN91CXX_RPCR, cpd->rpc_cur_mode); - - smc_phy_configure_exit: - - /* Exit auto-negotiation */ - cpd->autoneg_active = 0; -} -#endif - -static uint16_t -lan91cxx_read_phy(struct lan91cxx_priv_data *cpd, uint8_t phyaddr, - uint8_t phyreg) -{ - int i, mask, input_idx, clk_idx = 0; - uint16_t mii_reg, value; - uint8_t bits[64]; - - /* 32 consecutive ones on MDO to establish sync */ - for (i = 0; i < 32; ++i) - bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO; - - /* Start code <01> */ - bits[clk_idx++] = LAN91CXX_MGMT_MDOE; - bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO; - - /* Read command <10> */ - bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO; - bits[clk_idx++] = LAN91CXX_MGMT_MDOE; - - /* Output the PHY address, msb first */ - for (mask = 0x10; mask; mask >>= 1) { - if (phyaddr & mask) - bits[clk_idx++] = - LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO; - else - bits[clk_idx++] = LAN91CXX_MGMT_MDOE; - } - - /* Output the phy register number, msb first */ - for (mask = 0x10; mask; mask >>= 1) { - if (phyreg & mask) - bits[clk_idx++] = - LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO; - else - bits[clk_idx++] = LAN91CXX_MGMT_MDOE; - } - - /* Tristate and turnaround (1 bit times) */ - bits[clk_idx++] = 0; - - /* Input starts at this bit time */ - input_idx = clk_idx; - - /* Will input 16 bits */ - for (i = 0; i < 16; ++i) - bits[clk_idx++] = 0; - - /* Final clock bit */ - bits[clk_idx++] = 0; - - /* Get the current MII register value */ - mii_reg = get_reg(cpd, LAN91CXX_MGMT); - - /* Turn off all MII Interface bits */ - mii_reg &= ~(LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MCLK | - LAN91CXX_MGMT_MDI | LAN91CXX_MGMT_MDO); - HAL_DELAY_US(50); - - /* Clock all 64 cycles */ - for (i = 0; i < sizeof(bits); ++i) { - /* Clock Low - output data */ - put_reg(cpd, LAN91CXX_MGMT, mii_reg | bits[i]); - HAL_DELAY_US(50); - - /* Clock Hi - input data */ - put_reg(cpd, LAN91CXX_MGMT, - mii_reg | bits[i] | LAN91CXX_MGMT_MCLK); - HAL_DELAY_US(50); - - bits[i] |= get_reg(cpd, LAN91CXX_MGMT) & LAN91CXX_MGMT_MDI; - } - - /* Return to idle state */ - put_reg(cpd, LAN91CXX_MGMT, mii_reg); - HAL_DELAY_US(50); - - /* Recover input data */ - for (value = 0, i = 0; i < 16; ++i) { - value <<= 1; - if (bits[input_idx++] & LAN91CXX_MGMT_MDI) - value |= 1; - } - - db16_printf("phy_read : %d : %04x\n", phyreg, value); - return value; -} - -static void -lan91cxx_write_phy(struct lan91cxx_priv_data *cpd, uint8_t phyaddr, - uint8_t phyreg, uint16_t value) -{ - int i, mask, clk_idx = 0; - uint16_t mii_reg; - uint8_t bits[65]; - - /* 32 consecutive ones on MDO to establish sync */ - for (i = 0; i < 32; ++i) - bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO; - - /* Start code <01> */ - bits[clk_idx++] = LAN91CXX_MGMT_MDOE; - bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO; - - /* Write command <01> */ - bits[clk_idx++] = LAN91CXX_MGMT_MDOE; - bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO; - - /* Output the PHY address, msb first */ - for (mask = 0x10; mask; mask >>= 1) { - if (phyaddr & mask) - bits[clk_idx++] = - LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO; - else - bits[clk_idx++] = LAN91CXX_MGMT_MDOE; - } - - /* Output the phy register number, msb first */ - for (mask = 0x10; mask; mask >>= 1) { - if (phyreg & mask) - bits[clk_idx++] = - LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO; - else - bits[clk_idx++] = LAN91CXX_MGMT_MDOE; - } - - /* Tristate and turnaround (2 bit times) */ - bits[clk_idx++] = 0; - bits[clk_idx++] = 0; - - /* Write out 16 bits of data, msb first */ - for (mask = 0x8000; mask; mask >>= 1) { - if (value & mask) - bits[clk_idx++] = - LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO; - else - bits[clk_idx++] = LAN91CXX_MGMT_MDOE; - } - - /* Final clock bit (tristate) */ - bits[clk_idx++] = 0; - - /* Get the current MII register value */ - mii_reg = get_reg(cpd, LAN91CXX_MGMT); - - /* Turn off all MII Interface bits */ - mii_reg &= ~(LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MCLK | - LAN91CXX_MGMT_MDI | LAN91CXX_MGMT_MDO); - HAL_DELAY_US(50); - - /* Clock all cycles */ - for (i = 0; i < sizeof(bits); ++i) { - /* Clock Low - output data */ - put_reg(cpd, LAN91CXX_MGMT, mii_reg | bits[i]); - HAL_DELAY_US(50); - - /* Clock Hi - input data */ - put_reg(cpd, LAN91CXX_MGMT, - mii_reg | bits[i] | LAN91CXX_MGMT_MCLK); - HAL_DELAY_US(50); - -/* bits[i] |= get_reg(cpd, LAN91CXX_MGMT) & LAN91CXX_MGMT_MDI;*/ - } - - /* Return to idle state */ - put_reg(cpd, LAN91CXX_MGMT, mii_reg); - HAL_DELAY_US(50); - - db16_printf("phy_write: %d : %04x\n", phyreg, value); -} - -#if 0 -void lan91cxx_print_bank(int bank){ - struct lan91cxx_priv_data *cpd = &smc91111; - int regno; - unsigned short regval[8]; - int i; - - if ( bank >= 4 ) - return; - for(i=0; i<8; i++){ - regno=i+bank<<3; - regval[i] = get_reg(cpd, regno); - } - printk("---- BANK %d ----\n\r",bank); - for(i=0; i<8; i++){ - printk("0x%x: 0x%x\n\r",i,regval[i]); - } - -} -#endif - -#endif diff --git a/c/src/libchip/network/smc91111config.h b/c/src/libchip/network/smc91111config.h deleted file mode 100644 index 8340ca23bb..0000000000 --- a/c/src/libchip/network/smc91111config.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef _SMC91111_CONFIG_H_ -#define _SMC91111_CONFIG_H_ - -/* - * RTEMS event used by interrupt handler to signal driver tasks. - * This must not be any of the events used by the network task synchronization. - */ -#define INTERRUPT_EVENT RTEMS_EVENT_1 - -/* - * RTEMS event used to start transmit daemon. - * This must not be the same as INTERRUPT_EVENT. - */ -#define START_TRANSMIT_EVENT RTEMS_EVENT_2 - - /* event to send when tx buffers become available */ -#define SMC91111_TX_WAIT_EVENT RTEMS_EVENT_3 - - -/* Number of OCs supported by this driver*/ -#define NOCDRIVER 1 - -/* Receive buffer size -- Allow for a full ethernet packet including CRC */ -#define RBUF_SIZE 1536 - -#define ET_MINLEN 64 /* minimum message length */ - -#if (MCLBYTES < RBUF_SIZE) -# error "Driver must have MCLBYTES > RBUF_SIZE" -#endif - -/* ----------------- cygdriver params ----------------- */ - -#define LAN91CXX_32BIT_RX -#define LAN91CXX_IS_LAN91C111 - -/* ----------------- compat layer ----------------- */ - -#include - -typedef uint32_t CYG_WORD; -typedef uint8_t CYG_BYTE; -typedef uint16_t CYG_WORD16; -typedef uint32_t CYG_WORD32; - -#ifndef CYG_SWAP16 -# define CYG_SWAP16(_x_) \ - ({ uint16_t _x = (_x_); ((_x << 8) | (_x >> 8)); }) -#endif - -#ifndef CYG_SWAP32 -# define CYG_SWAP32(_x_) \ - ({ uint32_t _x = (_x_); \ - ((_x << 24) | \ - ((0x0000FF00UL & _x) << 8) | \ - ((0x00FF0000UL & _x) >> 8) | \ - (_x >> 24)); }) -#endif - -# define CYG_CPU_TO_BE16(_x_) (_x_) -# define CYG_CPU_TO_BE32(_x_) (_x_) -# define CYG_BE16_TO_CPU(_x_) (_x_) -# define CYG_BE32_TO_CPU(_x_) (_x_) - -# define CYG_CPU_TO_LE16(_x_) CYG_SWAP16((_x_)) -# define CYG_CPU_TO_LE32(_x_) CYG_SWAP32((_x_)) -# define CYG_LE16_TO_CPU(_x_) CYG_SWAP16((_x_)) -# define CYG_LE32_TO_CPU(_x_) CYG_SWAP32((_x_)) - -#define CYG_MACRO_START do { -#define CYG_MACRO_END } while (0) -#define HAL_IO_BARRIER() \ - __asm__ volatile ( "" : : : "memory" ) - -#define HAL_READ_UINT8( _register_, _value_ ) \ - CYG_MACRO_START \ - ((_value_) = *((volatile CYG_BYTE *)(_register_))); \ - HAL_IO_BARRIER (); \ - CYG_MACRO_END - -#define HAL_WRITE_UINT8( _register_, _value_ ) \ - CYG_MACRO_START \ - (*((volatile CYG_BYTE *)(_register_)) = (_value_)); \ - HAL_IO_BARRIER (); \ - CYG_MACRO_END - -#define HAL_READ_UINT16( _register_, _value_ ) \ - CYG_MACRO_START \ - ((_value_) = *((volatile CYG_WORD16 *)(_register_))); \ - HAL_IO_BARRIER (); \ - CYG_MACRO_END - -#define HAL_WRITE_UINT16( _register_, _value_ ) \ - CYG_MACRO_START \ - (*((volatile CYG_WORD16 *)(_register_)) = (_value_)); \ - HAL_IO_BARRIER (); \ - CYG_MACRO_END - -#define HAL_READ_UINT32( _register_, _value_ ) \ - CYG_MACRO_START \ - ((_value_) = *((volatile CYG_WORD32 *)(_register_))); \ - HAL_IO_BARRIER (); \ - CYG_MACRO_END - -#define HAL_READ_UINT16( _register_, _value_ ) \ - CYG_MACRO_START \ - ((_value_) = *((volatile CYG_WORD16 *)(_register_))); \ - HAL_IO_BARRIER (); \ - CYG_MACRO_END - -#define CYG_ASSERT(c,p) do { if (!(c)) { while(1) { printf(p);} }; } while(0) - -#define HAL_DELAY_US(p) rtems_task_wake_after (RTEMS_MICROSECONDS_TO_TICKS (p)) - - -#endif /* _SMC_91111_CONFIG_H_ */ - - diff --git a/c/src/libchip/network/sonic.c b/c/src/libchip/network/sonic.c deleted file mode 100644 index dc97008b8d..0000000000 --- a/c/src/libchip/network/sonic.c +++ /dev/null @@ -1,1685 +0,0 @@ -/* - * RTEMS NETWORK DRIVER FOR NATIONAL DP83932 `SONIC' - * SYSTEMS-ORIENTED NETWORK INTERFACE CONTROLLER - * - * REUSABLE CHIP DRIVER - * - * References: - * - * 1) DP83932C-20/25/33 MHz SONIC(TM) Systems-Oriented Network Interface - * Controller data sheet. TL/F/10492, RRD-B30M105, National Semiconductor, - * 1995. - * - * 2) Software Driver Programmer's Guide for the DP83932 SONIC(TM), - * Application Note 746, Wesley Lee and Mike Lui, TL/F/11140, - * RRD-B30M75, National Semiconductor, March, 1991. - * - * COPYRIGHT (c) 1989-1997. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - * - * This driver was originally written and tested on a DY-4 DMV177, - * which had a 100 Mhz PPC603e. - * - * This driver also works with DP83934CVUL-20/25 MHz, tested on - * Tharsys ERC32 VME board. - * - * Rehaul to fix lost interrupts and buffers, and to use to use - * interrupt-free transmission by Jiri, 22/03/1999. - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include - -extern rtems_isr_entry set_vector( rtems_isr_entry, rtems_vector_number, int ); - -#if (SONIC_DEBUG & SONIC_DEBUG_DUMP_MBUFS) -#include -#endif - -/* - * Use the top line if you want more symbols. - */ - -#define SONIC_STATIC static - -/* - * Number of devices supported by this driver - */ -#ifndef NSONIC -# define NSONIC 1 -#endif - -/* - * - * As suggested by National Application Note 746, make the - * receive resource area bigger than the receive descriptor area. - * - * NOTE: Changing this may break this driver since it currently - * assumes a 1<->1 mapping. - */ -#define RRA_EXTRA_COUNT 0 - -/* - * RTEMS event used by interrupt handler to signal daemons. - */ -#define INTERRUPT_EVENT RTEMS_EVENT_1 - -/* - * RTEMS event used to start transmit daemon. - * This must not be the same as INTERRUPT_EVENT. - */ -#define START_TRANSMIT_EVENT RTEMS_EVENT_2 - -/* - * Largest Ethernet frame. - */ -#define MAXIMUM_FRAME_SIZE 1518 - -/* - * Receive buffer size. - * Allow for a pointer, plus a full ethernet frame (including Frame - * Check Sequence) rounded up to a 4-byte boundary. - */ -#define RBUF_SIZE ((sizeof (void *) + (MAXIMUM_FRAME_SIZE) + 3) & ~3) -/* #define RBUF_WC ((((MAXIMUM_FRAME_SIZE) + 3) & ~3) / 2) */ -#define RBUF_WC (RBUF_SIZE / 2) - -/* - * Macros for manipulating 32-bit pointers as 16-bit fragments - */ -#define LSW(p) ((uint16_t)((uintptr_t)(p))) -#define MSW(p) ((uint16_t)((uintptr_t)(p) >> 16)) -#define PTR(m,l) ((void*)(((uint16_t)(m)<<16)|(uint16_t)(l))) - -/* - * Hardware-specific storage - */ -struct sonic_softc { - /* - * Connection to networking code - * This entry *must* be the first in the sonic_softc structure. - */ - struct arpcom arpcom; - - /* - * Default location of device registers - * ===CACHE=== - * This area must be non-cacheable, guarded. - */ - void *sonic; - - /* - * Register access routines - */ - sonic_write_register_t write_register; - sonic_read_register_t read_register; - - /* - * Interrupt vector - */ - rtems_vector_number vector; - - /* - * Data Configuration Register values - */ - uint32_t dcr_value; - uint32_t dc2_value; - - /* - * Indicates configuration - */ - int acceptBroadcast; - - /* - * Task waiting for interrupts - */ - rtems_id rxDaemonTid; - rtems_id txDaemonTid; - - /* - * Receive resource area - */ - int rdaCount; - ReceiveResourcePointer_t rsa; - ReceiveResourcePointer_t rea; - CamDescriptorPointer_t cdp; - ReceiveDescriptorPointer_t rda; - ReceiveDescriptorPointer_t rdp_last; - - /* - * Transmit descriptors - */ - int tdaCount; - TransmitDescriptorPointer_t tdaHead; /* Last filled */ - TransmitDescriptorPointer_t tdaTail; /* Next to retire */ - - /* - * Statistics - */ - unsigned long Interrupts; - unsigned long rxInterrupts; - unsigned long rxMissed; - unsigned long rxGiant; - unsigned long rxNonOctet; - unsigned long rxBadCRC; - unsigned long rxCollision; - - unsigned long txInterrupts; - unsigned long txSingleCollision; - unsigned long txMultipleCollision; - unsigned long txCollision; - unsigned long txDeferred; - unsigned long txUnderrun; - unsigned long txLateCollision; - unsigned long txExcessiveCollision; - unsigned long txExcessiveDeferral; - unsigned long txLostCarrier; - unsigned long txRawWait; -}; -SONIC_STATIC struct sonic_softc sonic_softc[NSONIC]; - - -/* - ****************************************************************** - * * - * Debug Routines * - * * - ****************************************************************** - */ - -#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_DESCRIPTORS) -void sonic_print_tx_descriptor( - TransmitDescriptorPointer_t tdp -) -{ - printf( "TXD ==> %p", tdp ); - printf( " pkt_config = 0x%04x", tdp->pkt_config & 0xffff); - printf( " pkt_size = 0x%04x\n", tdp->pkt_size & 0xffff ); - printf( " frag_count = %d", tdp->frag_count & 0xffff ); - /* could print all the fragments */ - printf( " next = %p", tdp->next ); - printf( " linkp = %p\n", tdp->linkp ); - printf( " mbufp = %p", tdp->mbufp ); - if ( tdp->mbufp ) - printf( " mbufp->data = %p", mtod ( tdp->mbufp, void *) ); - puts(""); -} - -void sonic_print_rx_descriptor( - ReceiveDescriptorPointer_t rdp -) -{ - printf( "RXD ==> %p\n", rdp ); - printf( " status = 0x%04x", rdp->status & 0xffff ); - printf( " byte_count = 0x%04x\n", rdp->byte_count & 0xffff ); - printf( " pkt = 0x%04x%04x", rdp->pkt_msw, rdp->pkt_lsw ); - printf( " seq_no = %d", rdp->seq_no ); - printf( " link = %d\n", rdp->link ); - printf( " in_use = %d", rdp->in_use ); - printf( " next = %p", rdp->next ); - printf( " mbufp = %p", rdp->mbufp ); - if ( rdp->mbufp ) - printf( " mbufp->data = %p", mtod ( rdp->mbufp, void *) ); - puts(""); -} -#endif - -/* - ****************************************************************** - * * - * Support Routines * - * * - ****************************************************************** - */ - -static void sonic_enable_interrupts( - struct sonic_softc *sc, - uint32_t mask -) -{ - void *rp = sc->sonic; - rtems_interrupt_level level; - - rtems_interrupt_disable( level ); - (*sc->write_register)( - rp, - SONIC_REG_IMR, - (*sc->read_register)(rp, SONIC_REG_IMR) | mask - ); - rtems_interrupt_enable( level ); -} - -static void sonic_disable_interrupts( - struct sonic_softc *sc, - uint32_t mask -) -{ - void *rp = sc->sonic; - rtems_interrupt_level level; - - rtems_interrupt_disable( level ); - (*sc->write_register)( - rp, - SONIC_REG_IMR, - (*sc->read_register)(rp, SONIC_REG_IMR) & ~mask - ); - rtems_interrupt_enable( level ); -} - -static void sonic_clear_interrupts( - struct sonic_softc *sc, - uint32_t mask -) -{ - void *rp = sc->sonic; - rtems_interrupt_level level; - - rtems_interrupt_disable( level ); - (*sc->write_register)( rp, SONIC_REG_ISR, mask); - rtems_interrupt_enable( level ); -} - -static void sonic_command( - struct sonic_softc *sc, - uint32_t mask -) -{ - void *rp = sc->sonic; - rtems_interrupt_level level; - - rtems_interrupt_disable( level ); - (*sc->write_register)( rp, SONIC_REG_CR, mask); - rtems_interrupt_enable( level ); -} - -/* - * Allocate non-cacheable memory on a single 64k page. - * Very simple minded -- just keeps trying till the memory is on a single page. - */ -SONIC_STATIC void * sonic_allocate(unsigned int nbytes) -{ - void *p; - unsigned long a1, a2; - - for (;;) { - /* - * ===CACHE=== - * Change malloc to malloc_noncacheable_guarded. - */ - p = malloc( nbytes, M_MBUF, M_NOWAIT ); - if (p == NULL) - rtems_panic ("No memory!"); - memset (p, '\0', nbytes); - a1 = (unsigned long)p; - a2 = a1 + nbytes - 1; - if ((a1 >> 16) == (a2 >> 16)) - break; - } -#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_ALLOCATE) - printf( "sonic_allocate %d bytes at %p\n", nbytes, p ); -#endif - return p; -} - -/* - * Shut down the interface. - */ - -SONIC_STATIC void sonic_stop (struct sonic_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - - ifp->if_flags &= ~IFF_RUNNING; - - /* - * Stop the transmitter and receiver. - */ - sonic_command(sc, CR_HTX | CR_RXDIS ); -} - -/* - * Show interface statistics - */ -SONIC_STATIC void sonic_stats (struct sonic_softc *sc) -{ - printf (" Total Interrupts:%-8lu", sc->Interrupts); - printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); - printf (" Giant:%-8lu", sc->rxGiant); - printf (" Non-octet:%-8lu\n", sc->rxNonOctet); - printf (" Bad CRC:%-8lu", sc->rxBadCRC); - printf (" Collision:%-8lu", sc->rxCollision); - printf (" Missed:%-8lu\n", sc->rxMissed); - - printf ( " Tx Interrupts:%-8lu", sc->txInterrupts); - printf ( " Deferred:%-8lu", sc->txDeferred); - printf (" Lost Carrier:%-8lu\n", sc->txLostCarrier); - printf ( "Single Collisions:%-8lu", sc->txSingleCollision); - printf ( "Multiple Collisions:%-8lu", sc->txMultipleCollision); - printf ("Excessive Collisions:%-8lu\n", sc->txExcessiveCollision); - printf ( " Total Collisions:%-8lu", sc->txCollision); - printf ( " Late Collision:%-8lu", sc->txLateCollision); - printf (" Underrun:%-8lu\n", sc->txUnderrun); - printf ( " Raw output wait:%-8lu\n", sc->txRawWait); -} - -/* - ****************************************************************** - * * - * Interrupt Handler * - * * - ****************************************************************** - */ - -SONIC_STATIC rtems_isr sonic_interrupt_handler (rtems_vector_number v) -{ - struct sonic_softc *sc = sonic_softc; - uint32_t isr, imr; - void *rp; - -#if (NSONIC > 1) - /* - * Find the device which requires service - */ - for (;;) { - if (sc->vector == v) - break; - if (++sc == &sonic[NSONIC]) - return; /* Spurious interrupt? */ - } -#endif /* NSONIC > 1 */ - - /* - * Get pointer to SONIC registers - */ - rp = sc->sonic; - - sc->Interrupts++; - - isr = (*sc->read_register)( rp, SONIC_REG_ISR ); - imr = (*sc->read_register)( rp, SONIC_REG_IMR ); - - /* - * Packet received or receive buffer area exceeded? - */ - if (imr & isr & (IMR_PRXEN | IMR_RBAEEN)) { - imr &= ~(IMR_PRXEN | IMR_RBAEEN); - sc->rxInterrupts++; - rtems_bsdnet_event_send (sc->rxDaemonTid, INTERRUPT_EVENT); - (*sc->write_register)( rp, SONIC_REG_IMR, imr ); - (*sc->write_register)( rp, SONIC_REG_ISR, isr & ISR_PKTRX ); - } - - /* - * Packet started, transmitter done or transmitter error? - * TX interrupts only occur after an error or when all TDA's are - * exhausted and we are waiting for buffer to come free. - */ - if (imr & isr & (IMR_PINTEN | IMR_TXEREN)) { - sc->txInterrupts++; - rtems_bsdnet_event_send (sc->txDaemonTid, INTERRUPT_EVENT); - (*sc->write_register)( rp, SONIC_REG_ISR, ISR_PINT | ISR_TXDN | ISR_TXER ); - } - -} - -/* - ****************************************************************** - * * - * Transmitter Routines * - * * - ****************************************************************** - */ - -/* - * Soak up transmit descriptors that have been sent. - */ - -SONIC_STATIC void sonic_retire_tda (struct sonic_softc *sc) -{ - uint16_t status; - unsigned int collisions; - struct mbuf *m, *n; - - /* - * Repeat for all completed transmit descriptors. - */ - while ((status = sc->tdaTail->status) != 0) { - -#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS) - printf( "retire TDA %p (0x%04x)\n", sc->tdaTail, status ); -#endif - -#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS) - /* - * If there is an error that was not a collision, - * then someone may want to see it. - */ - - if ( (status & ~(TDA_STATUS_COLLISION_MASK|TDA_STATUS_DEF)) != 0x0001 ) - printf( "ERROR: retire TDA %p (0x%08x)\n", - sc->tdaTail, sc->tdaTail->status ); -#endif - - /* - * Check for errors which stop the transmitter. - */ - if (status & (TDA_STATUS_EXD | - TDA_STATUS_EXC | - TDA_STATUS_FU | - TDA_STATUS_BCM)) { - /* - * Restart the transmitter if there are - * packets waiting to go. - */ - uint16_t link; -#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS) - printf("restarting sonic after error\n"); -#endif - - link = *(sc->tdaTail->linkp); - - if ((link & TDA_LINK_EOL) == 0) { - void *rp = sc->sonic; - - (*sc->write_register)( rp, SONIC_REG_CTDA, link ); - sonic_command(sc, CR_TXP ); - } - } - - /* - * Update network statistics - */ - collisions = (status & TDA_STATUS_COLLISION_MASK) >> TDA_STATUS_COLLISION_SHIFT; - if (collisions) { - if (collisions == 1) - sc->txSingleCollision++; - else - sc->txMultipleCollision++; - sc->txCollision += collisions; - } - if (status & TDA_STATUS_EXC) - sc->txExcessiveCollision++; - if (status & TDA_STATUS_OWC) - sc->txLateCollision++; - if (status & TDA_STATUS_EXD) - sc->txExcessiveDeferral++; - if (status & TDA_STATUS_DEF) - sc->txDeferred++; - if (status & TDA_STATUS_FU) - sc->txUnderrun++; - if (status & TDA_STATUS_CRSL) - sc->txLostCarrier++; - - /* - * Free the packet and reset a couple of fields - */ - m = sc->tdaTail->mbufp; - while ( m ) { - MFREE(m, n); - m = n; - } - - /* - sc->tdaTail->frag[0].frag_link = LSW(sc->tdaTail->link_pad); - sc->tdaTail->frag_count = 0; - */ - sc->tdaTail->status = 0; - - /* - * Move to the next transmit descriptor - */ - sc->tdaTail = sc->tdaTail->next; -#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS) - printf( "next TDA %p\n", sc->tdaTail ); -#endif - } -} - -/* - * Send packet - */ -SONIC_STATIC void sonic_sendpacket (struct ifnet *ifp, struct mbuf *m) -{ - struct sonic_softc *sc = ifp->if_softc; - struct mbuf *l = NULL; - TransmitDescriptorPointer_t tdp; - volatile struct TransmitDescriptorFragLink *fp; - unsigned int packetSize; - int i; - rtems_event_set events; - static char padBuf[64]; - - /* printf( "sonic_sendpacket %p\n", m ); */ - - - /* - * Wait for transmit descriptor to become available. Only retire TDA's - * if there are no more free buffers to minimize TX latency. Retire TDA'a - * on the way out. - */ - - while (sc->tdaHead->next->status != 0) { - - /* - * Free up transmit descriptors - */ - sonic_retire_tda (sc); - - if (sc->tdaHead->next->status == 0) - break; - -#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS) - printf("blocking until TDAs are available\n"); -#endif - /* - * Enable PINT interrupts. - sonic_clear_interrupts( sc, ISR_PINT ); - sonic_enable_interrupts( sc, IMR_PINTEN ); - */ - - /* - * Wait for PINT TX interrupt. Every fourth TX buffer will raise PINT. - */ - rtems_bsdnet_event_receive (INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - sonic_disable_interrupts( sc, IMR_PINTEN ); - sonic_retire_tda (sc); - } - - /* - * Fill in the transmit descriptor fragment descriptors. - * ===CACHE=== - * If data cache is operating in write-back mode, flush cached - * data to memory. - */ - tdp = sc->tdaHead->next; - tdp->mbufp = m; - packetSize = 0; - fp = tdp->frag; - for (i = 0 ; i < MAXIMUM_FRAGS_PER_DESCRIPTOR ; i++, fp++) { - /* - * Throw away empty mbufs - */ - if (m->m_len) { - void *p = mtod (m, void *); - fp->frag_lsw = LSW(p); - fp->frag_msw = MSW(p); - fp->frag_size = m->m_len; - packetSize += m->m_len; -#if (SONIC_DEBUG & SONIC_DEBUG_FRAGMENTS) - printf( "fp %p 0x%04x%04x %d=%d .. %d\n", - fp, fp->frag_msw, fp->frag_lsw, fp->frag_size, m->m_len, packetSize ); -#endif -#if (SONIC_DEBUG & SONIC_DEBUG_DUMP_TX_MBUFS) - rtems_print_buffer( - p, - (fp->frag_size > MAXIMUM_FRAME_SIZE) ? MAXIMUM_FRAME_SIZE : fp->frag_size - ); -#endif - l = m; - m = m->m_next; - } - else { - struct mbuf *n; - MFREE (m, n); - m = n; - if (l != NULL) - l->m_next = m; - } - /* - * Break out of the loop if this mbuf is the last in the frame. - */ - if (m == NULL) - break; - } - - /* - * Pad short packets. - */ - if ((packetSize < 64) && (i < MAXIMUM_FRAGS_PER_DESCRIPTOR)) { - int padSize = 64 - packetSize; - fp++; - fp->frag_lsw = LSW(padBuf); - fp->frag_msw = MSW(padBuf); - fp->frag_size = padSize; -#if (SONIC_DEBUG & SONIC_DEBUG_FRAGMENTS) - printf( "PAD fp %p 0x%04x%04x %d\n", - fp, fp->frag_msw, fp->frag_lsw, fp->frag_size ); -#endif - packetSize += padSize; - i++; - } - - /* - * Fill Transmit Descriptor - */ - tdp->pkt_size = packetSize; - tdp->frag_count = i + 1; - tdp->status = 0; - - /* - * Chain onto list and start transmission. - */ - - tdp->linkp = &(fp+1)->frag_link; - *tdp->linkp = LSW(tdp->next) | TDA_LINK_EOL; - if ( sc->tdaHead->frag_count ) - *sc->tdaHead->linkp &= ~TDA_LINK_EOL; - sc->tdaHead = tdp; - - /* Start transmission */ - - sonic_command(sc, CR_TXP ); - - /* - * Free up transmit descriptors on the way out. - */ - sonic_retire_tda (sc); -} - -/* - * Driver transmit daemon - */ -SONIC_STATIC void sonic_txDaemon (void *arg) -{ - struct sonic_softc *sc = (struct sonic_softc *)arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - rtems_event_set events; - - for (;;) { - /* - * Wait for packet - */ - rtems_bsdnet_event_receive ( - START_TRANSMIT_EVENT, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, - &events - ); - - /* - * Send packets till queue is empty - */ - for (;;) { - /* - * Get the next mbuf chain to transmit. - */ - IF_DEQUEUE(&ifp->if_snd, m); - if (!m) - break; - sonic_sendpacket (ifp, m); - } - ifp->if_flags &= ~IFF_OACTIVE; - } -} - -/* - ****************************************************************** - * * - * Receiver Routines * - * * - ****************************************************************** - */ - -/* - * Wait for SONIC to hand over a Receive Descriptor. - */ - -SONIC_STATIC void sonic_rda_wait( - struct sonic_softc *sc, - ReceiveDescriptorPointer_t rdp -) -{ - int i; - void *rp = sc->sonic; - rtems_event_set events; - - /* - * Wait for Receive Descriptor. - * The order of the tests is very important. - * The RDA is checked after RBAE is detected. This ensures that - * the driver processes all RDA entries before reusing the RRA - * entry holding the giant packet. - * The event wait is done after the RDA and RBAE checks. This - * catches the possibility that a Receive Descriptor became ready - * between the call to this function and the clearing of the - * interrupt status register bit. - */ - for (;;) { - /* - * Has a giant packet arrived? - * The National DP83932C data sheet is very vague on what - * happens under this condition. The description of the - * Interrupt Status Register (Section 4.3.6) states, - * ``Reception is aborted and the SONIC fetches the next - * available resource descriptors in the RRA. The buffer - * space is not re-used and an RDA is not setup for the - * truncated packet.'' - * I take ``Reception is aborted'' to mean that the RXEN - * bit in the Command Register is cleared and must be set - * by the driver to begin reception again. - * Unfortunately, an alternative interpretation could be - * that only reception of the current packet is aborted. - * This would be more difficult to recover from.... - */ - if ((*sc->read_register)( rp, SONIC_REG_ISR ) & ISR_RBAE) { - -#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS) - printf( "ERROR: looks like a giant packet -- RBAE\n" ); -#endif - - /* - * One more check to soak up any Receive Descriptors - * that may already have been handed back to the driver. - */ - if (rdp->in_use == RDA_IN_USE) { -#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS) - printf( "ERROR: nope just an RBAE\n" ); -#endif - break; - } - - /* - * Check my interpretation of the SONIC manual. - */ - if ((*sc->read_register)( rp, SONIC_REG_CR ) & CR_RXEN) - rtems_panic ("SONIC RBAE/RXEN"); - - /* - * Update statistics - */ - sc->rxGiant++; - - /* - * Reuse receive buffer. - * Again, the manual is subject to interpretation. The - * RRP register is described as, `the lower address of - * the next descriptor the SONIC will read.'' - * Since, acording to the ISR/RBAE notes, the SONIC has - * ``fetched the next available resource descriptor in - * the RRA'', I interpret this to mean that that the - * driver has to move the RRP back *two* entries to - * reuse the receive buffer holding the giant packet. - */ - for (i = 0; i < 2; ++i) { - uint32_t rrp = (*sc->read_register)( rp, SONIC_REG_RRP ); - const uint32_t rsa = (*sc->read_register)( rp, SONIC_REG_RSA ); - - if (rrp == rsa) { - const uint32_t rea = (*sc->read_register)( rp, SONIC_REG_REA ); - (*sc->write_register)( rp, SONIC_REG_RRP, rea ); - } - - rrp = (*sc->read_register)( rp, SONIC_REG_RRP ); - (*sc->write_register)( rp, SONIC_REG_RRP, rrp - sizeof(ReceiveResource_t) ); - } - - /* - * Restart reception - */ - sonic_clear_interrupts( sc, ISR_RBAE ); - sonic_command( sc, CR_RXEN ); - } - - /* - * Has Receive Descriptor become available? - */ - if (rdp->in_use == RDA_IN_USE) - break; - - /* - * Enable interrupts. - */ - sonic_enable_interrupts( sc, (IMR_PRXEN | IMR_RBAEEN) ); - - /* - * Wait for interrupt. - */ - rtems_bsdnet_event_receive( - INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events - ); - } -#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS) - printf( "RDA %p\n", rdp ); -#endif - -#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS) - if (rdp->status & 0x000E) - printf( "ERROR: RDA %p (0x%04x)\n", rdp, rdp->status ); -#endif - -} - -#ifdef CPU_U32_FIX - -/* - * Routine to align the received packet so that the ip header - * is on a 32-bit boundary. Necessary for cpu's that do not - * allow unaligned loads and stores and when the 32-bit DMA - * mode is used. - * - * Transfers are done on word basis to avoid possibly slow byte - * and half-word writes. - */ - -void ipalign(struct mbuf *m) -{ - unsigned int *first, *last, data; - unsigned int tmp = 0; - - if ((((int) m->m_data) & 2) && (m->m_len)) { - last = (unsigned int *) ((((int) m->m_data) + m->m_len + 8) & ~3); - first = (unsigned int *) (((int) m->m_data) & ~3); - tmp = *first << 16; - first++; - do { - data = *first; - *first = tmp | (data >> 16); - tmp = data << 16; - first++; - } while (first <= last); - - m->m_data = (caddr_t)(((int) m->m_data) + 2); - } -} -#endif - -/* - * SONIC reader task - */ -SONIC_STATIC void sonic_rxDaemon (void *arg) -{ - struct sonic_softc *sc = (struct sonic_softc *)arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - void *rp = sc->sonic; - struct mbuf *m; - uint16_t status; - ReceiveDescriptorPointer_t rdp; - ReceiveResourcePointer_t rwp, rea; - uint16_t newMissedTally, oldMissedTally; - - rwp = sc->rsa; - rea = sc->rea; - rdp = sc->rda; - - /* - * Start the receiver - */ - oldMissedTally = (*sc->read_register)( rp, SONIC_REG_MPT ); - - /* - * Input packet handling loop - */ - for (;;) { - /* - * Wait till SONIC supplies a Receive Descriptor. - */ - if (rdp->in_use == RDA_FREE) { - sonic_rda_wait (sc, rdp); - } - -#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS) - printf( "Incoming packet %p status=0x%04x\n", rdp, rdp->status ); -#endif - - /* - * Check that packet is valid - */ - status = rdp->status; - if (status & RDA_STATUS_PRX) { - struct ether_header *eh; - void *p; - - /* - * Pass the packet up the chain. - * The mbuf count is reduced to remove - * the frame check sequence at the end - * of the packet. - * ===CACHE=== - * Invalidate cache entries for this memory. - */ -#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_DESCRIPTORS) - sonic_print_rx_descriptor( rdp ); - if ((LSW(rdp->mbufp->m_data) != rdp->pkt_lsw) - || (MSW(rdp->mbufp->m_data) != rdp->pkt_msw)) - printf ("SONIC RDA/RRA %p, %08x\n",rdp->mbufp->m_data,(rdp->pkt_msw << 16) | - (rdp->pkt_lsw & 0x0ffff)); -#endif - rdp->byte_count &= 0x0ffff; /* ERC32 pollutes msb of byte_count */ - m = rdp->mbufp; - m->m_len = m->m_pkthdr.len = rdp->byte_count - - sizeof(uint32_t) - - sizeof(struct ether_header); - eh = mtod (m, struct ether_header *); - m->m_data += sizeof(struct ether_header); - -#ifdef CPU_U32_FIX - ipalign(m); /* Align packet on 32-bit boundary */ -#endif - -#if (SONIC_DEBUG & SONIC_DEBUG_DUMP_RX_MBUFS) - rtems_print_buffer( (void *) eh, sizeof(struct ether_header) ); - rtems_print_buffer( (void *) m, 96 /* m->m_len*/ ); -#endif - - /* printf( "ether_input %p\n", m ); */ - /* - printf( "pkt %p, seq %04x, mbuf %p, m_data %p\n", rdp, rdp->seq_no, m, m->m_data ); - printf( "%u, %u\n", ((int*)m->m_data)[6], ((int*)m->m_data)[7]); - */ - ether_input (ifp, eh, m); - /* - */ - - /* - * Sanity check that Receive Resource Area is - * still in sync with Receive Descriptor Area - * The buffer reported in the Receive Descriptor - * should be the same as the buffer in the Receive - * Resource we are about to reuse. - */ -/* XXX figure out whether this is valid or not */ -#if 0 - if ((LSW(p) != rwp->buff_ptr_lsw) - || (MSW(p) != rwp->buff_ptr_msw)) - rtems_panic ("SONIC RDA/RRA"); -#endif - - /* - * Allocate a new mbuf. - */ - - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - rdp->mbufp = m; - p = mtod (m, void *); - - /* - * Reuse Receive Resource. - */ - - rwp->buff_ptr_lsw = LSW(p); - rwp->buff_ptr_msw = MSW(p); - rwp->buff_wc_lsw = RBUF_WC; - rwp->buff_wc_msw = 0; - rwp++; - - if (rwp == rea) { -#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY) - printf( "Wrapping RWP from %p to %p\n", rwp, sc->rsa ); -#endif - rwp = sc->rsa; - } - (*sc->write_register)( rp, SONIC_REG_RWP , LSW(rwp) ); - - /* - * Tell the SONIC to reread the RRA. - */ - if ((*sc->read_register)( rp, SONIC_REG_ISR ) & ISR_RBE) - sonic_clear_interrupts( sc, ISR_RBE ); - } - else { - if (status & RDA_STATUS_COL) - sc->rxCollision++; - if (status & RDA_STATUS_FAER) - sc->rxNonOctet++; - else if (status & RDA_STATUS_CRCR) - sc->rxBadCRC++; - } - - /* - * Count missed packets - */ - newMissedTally = (*sc->read_register)( rp, SONIC_REG_MPT ); - if (newMissedTally != oldMissedTally) { - sc->rxMissed += (newMissedTally - oldMissedTally) & 0xFFFF; - newMissedTally = oldMissedTally; - } - - /* - * Move to next receive descriptor and update EOL - */ - - rdp->link |= RDA_LINK_EOL; - rdp->in_use = RDA_FREE; - sc->rdp_last->link &= ~RDA_LINK_EOL; - sc->rdp_last = rdp; - rdp = rdp->next; - - } -} - -/* - ****************************************************************** - * * - * Initialization Routines * - * * - ****************************************************************** - */ - -/* - * Initialize the SONIC hardware - */ -SONIC_STATIC void sonic_initialize_hardware(struct sonic_softc *sc) -{ - void *rp = sc->sonic; - int i; - unsigned char *hwaddr; - TransmitDescriptorPointer_t tdp; - ReceiveDescriptorPointer_t ordp, rdp; - ReceiveResourcePointer_t rwp; - struct mbuf *m; - void *p; - CamDescriptorPointer_t cdp; - - /* - * The Revision B SONIC has a horrible bug known as the "Zero - * Length Packet bug". The initial board used to develop this - * driver had a newer revision of the SONIC so there was no reason - * to check for this. If you have the Revision B SONIC chip, then - * you need to add some code to the RX path to handle this weirdness. - */ - - if ( (*sc->read_register)( rp, SONIC_REG_SR ) <= SONIC_REVISION_B ) { - rtems_fatal_error_occurred( 0x0BADF00D ); /* don't eat this part :) */ - } - - /* - * Set up circular linked list in Transmit Descriptor Area. - * Use the PINT bit in the transmit configuration field to - * request an interrupt on every other transmitted packet. - * - * NOTE: sonic_allocate() zeroes all of the memory allocated. - */ - - sc->tdaTail = sonic_allocate(sc->tdaCount * sizeof *tdp); -#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY) - printf( "tdaTail = %p\n", sc->tdaTail ); -#endif - tdp = sc->tdaTail; - for (i = 0 ; i < sc->tdaCount ; i++) { - /* - * Start off with the table of outstanding mbuf's - */ - - /* - * status, pkt_config, pkt_size, and all fragment fields - * are set to zero by sonic_allocate. - */ - -/* XXX not used by the BSD drivers - tdp->frag[0].frag_link = LSW(tdp + 1); -*/ - if (i & 3) - tdp->pkt_config = TDA_CONFIG_PINT; - - tdp->status = 0; - tdp->frag_count = 0; - tdp->link_pad = LSW(tdp + 1) | TDA_LINK_EOL; - tdp->linkp = &((tdp + 1)->frag[0].frag_link); - tdp->next = (TransmitDescriptor_t *)(tdp + 1); -#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_DESCRIPTORS) - sonic_print_tx_descriptor( tdp ); -#endif - tdp++; - } - tdp--; - sc->tdaHead = tdp; - tdp->link_pad = LSW(sc->tdaTail) | TDA_LINK_EOL; - tdp->next = (TransmitDescriptor_t *)sc->tdaTail; - tdp->linkp = &sc->tdaTail->frag[0].frag_link; - - /* - * Set up circular linked list in Receive Descriptor Area. - * Leaves sc->rda pointing at the `beginning' of the list. - * - * NOTE: The RDA and CDP must have the same MSW for their addresses. - */ - - sc->rda = sonic_allocate( - (sc->rdaCount * sizeof(ReceiveDescriptor_t)) + - sizeof(CamDescriptor_t) ); - sc->cdp = (CamDescriptorPointer_t) ((unsigned char *)sc->rda + - (sc->rdaCount * sizeof(ReceiveDescriptor_t))); -#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY) - printf( "rda area = %p\n", sc->rda ); - printf( "cdp area = %p\n", sc->cdp ); -#endif - - ordp = rdp = sc->rda; - for (i = 0 ; i < sc->rdaCount ; i++) { - /* - * status, byte_count, pkt_ptr0, pkt_ptr1, and seq_no are set - * to zero by sonic_allocate. - */ - rdp->link = LSW(rdp + 1); - rdp->in_use = RDA_FREE; - rdp->next = (ReceiveDescriptor_t *)(rdp + 1); - ordp = rdp; - rdp++; - } - /* - * Link the last desriptor to the 1st one and mark it as the end - * of the list. - */ - ordp->next = sc->rda; - ordp->link = LSW(sc->rda) | RDA_LINK_EOL; - sc->rdp_last = ordp; - - /* - * Allocate the receive resource area. - * In accordance with National Application Note 746, make the - * receive resource area bigger than the receive descriptor area. - * This has the useful side effect of making the receive resource - * area big enough to hold the CAM descriptor area. - */ - - sc->rsa = sonic_allocate((sc->rdaCount + RRA_EXTRA_COUNT) * sizeof *sc->rsa); -#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY) - printf( "rsa area = %p\n", sc->rsa ); -#endif - - /* - * Set up list in Receive Resource Area. - * Allocate space for incoming packets. - */ - - rwp = sc->rsa; - for (i = 0 ; i < (sc->rdaCount + RRA_EXTRA_COUNT) ; i++, rwp++) { - - /* - * Allocate memory for buffer. - * Place a pointer to the mbuf at the beginning of the buffer - * so we can find the mbuf when the SONIC returns the buffer - * to the driver. - */ - - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - m->m_pkthdr.rcvif = &sc->arpcom.ac_if; - sc->rda[i].mbufp = m; - - p = mtod (m, void *); - - /* - * Set up RRA entry - */ - rwp->buff_ptr_lsw = LSW(p); - rwp->buff_ptr_msw = MSW(p); - rwp->buff_wc_lsw = RBUF_WC; - rwp->buff_wc_msw = 0; -#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_DESCRIPTORS) - sonic_print_rx_descriptor( &sc->rda[i] ); -#endif - } - sc->rea = rwp; -#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY) - printf( "rea area = %p\n", sc->rea ); -#endif - - - /* - * Issue a software reset. - */ - (*sc->write_register)( rp, SONIC_REG_CR, CR_RST | CR_STP | CR_RXDIS | CR_HTX ); - - /* - * Set up data configuration registers. - */ - (*sc->write_register)( rp, SONIC_REG_DCR, sc->dcr_value ); - (*sc->write_register)( rp, SONIC_REG_DCR2, sc->dc2_value ); - - (*sc->write_register)( rp, SONIC_REG_CR, CR_STP | CR_RXDIS | CR_HTX ); - - /* - * Mask all interrupts - */ - (*sc->write_register)( rp, SONIC_REG_IMR, 0x0 ); /* XXX was backwards */ - - /* - * Clear outstanding interrupts. - */ - (*sc->write_register)( rp, SONIC_REG_ISR, 0x7FFF ); - - /* - * Clear the tally counters - */ - - (*sc->write_register)( rp, SONIC_REG_CRCT, 0xFFFF ); - (*sc->write_register)( rp, SONIC_REG_FAET, 0xFFFF ); - (*sc->write_register)( rp, SONIC_REG_MPT, 0xFFFF ); - (*sc->write_register)( rp, SONIC_REG_RSC, 0 ); - - /* - * Set the Receiver mode - * - * Enable/disable reception of broadcast packets - */ - - if (sc->acceptBroadcast) - (*sc->write_register)( rp, SONIC_REG_RCR, RCR_BRD ); - else - (*sc->write_register)( rp, SONIC_REG_RCR, 0 ); - - /* - * Set up Resource Area pointers - */ - - (*sc->write_register)( rp, SONIC_REG_URRA, MSW(sc->rsa) ); - (*sc->write_register)( rp, SONIC_REG_RSA, LSW(sc->rsa) ); - - (*sc->write_register)( rp, SONIC_REG_REA, LSW(sc->rea) ); - - (*sc->write_register)( rp, SONIC_REG_RRP, LSW(sc->rsa) ); - (*sc->write_register)( rp, SONIC_REG_RWP, LSW(sc->rsa) ); /* XXX was rea */ - - (*sc->write_register)( rp, SONIC_REG_URDA, MSW(sc->rda) ); - (*sc->write_register)( rp, SONIC_REG_CRDA, LSW(sc->rda) ); - - (*sc->write_register)( rp, SONIC_REG_UTDA, MSW(sc->tdaTail) ); - (*sc->write_register)( rp, SONIC_REG_CTDA, LSW(sc->tdaTail) ); - - /* - * Set End Of Buffer Count register to the value recommended - * in Note 1 of Section 3.4.4.4 of the SONIC data sheet. - */ - - (*sc->write_register)( rp, SONIC_REG_EOBC, RBUF_WC - 2 ); - - /* - * Issue the load RRA command - */ - - (*sc->write_register)( rp, SONIC_REG_CR, CR_RRRA ); - while ((*sc->read_register)( rp, SONIC_REG_CR ) & CR_RRRA) - continue; - - /* - * Remove device reset - */ - - (*sc->write_register)( rp, SONIC_REG_CR, 0 ); - - /* - * Set up the SONIC CAM with our hardware address. - */ - - hwaddr = sc->arpcom.ac_enaddr; - cdp = sc->cdp; - -#if (SONIC_DEBUG & SONIC_DEBUG_CAM) - printf( "hwaddr: %2x:%2x:%2x:%2x:%2x:%2x\n", - hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5] ); -#endif - - cdp->cep = 0; /* Fill first and only entry in CAM */ - cdp->cap0 = hwaddr[1] << 8 | hwaddr[0]; - cdp->cap1 = hwaddr[3] << 8 | hwaddr[2]; - cdp->cap2 = hwaddr[5] << 8 | hwaddr[4]; - cdp->ce = 0x0001; /* Enable first entry in CAM */ - - (*sc->write_register)( rp, SONIC_REG_CDC, 1 ); /* 1 entry in CDA */ - (*sc->write_register)( rp, SONIC_REG_CDP, LSW(cdp) ); - (*sc->write_register)( rp, SONIC_REG_CR, CR_LCAM ); /* Load the CAM */ - - while ((*sc->read_register)( rp, SONIC_REG_CR ) & CR_LCAM) - continue; - - /* - * Verify that CAM was properly loaded. - */ - - (*sc->write_register)( rp, SONIC_REG_CR, CR_RST | CR_STP | CR_RXDIS | CR_HTX ); - -#if (SONIC_DEBUG & SONIC_DEBUG_CAM) - (*sc->write_register)( rp, SONIC_REG_CEP, 0 ); /* Select first entry in CAM */ - printf ("Loaded Ethernet address into SONIC CAM.\n" - " Wrote %04x%04x%04x - %#x\n" - " Read %04x%04x%04x - %#x\n", - cdp->cap2, cdp->cap1, cdp->cap0, cdp->ce, - (*sc->read_register)( rp, SONIC_REG_CAP2 ), - (*sc->read_register)( rp, SONIC_REG_CAP1 ), - (*sc->read_register)( rp, SONIC_REG_CAP0 ), - (*sc->read_register)( rp, SONIC_REG_CE )); - - (*sc->write_register)( rp, SONIC_REG_CEP, 0 ); /* Select first entry in CAM */ - if (((*sc->read_register)( rp, SONIC_REG_CAP2 ) != cdp->cap2) - || ((*sc->read_register)( rp, SONIC_REG_CAP1 ) != cdp->cap1) - || ((*sc->read_register)( rp, SONIC_REG_CAP0 ) != cdp->cap0) - || ((*sc->read_register)( rp, SONIC_REG_CE ) != cdp->ce)) { - printf ("Failed to load Ethernet address into SONIC CAM.\n" - " Wrote %04x%04x%04x - %#x\n" - " Read %04x%04x%04x - %#x\n", - cdp->cap2, cdp->cap1, cdp->cap0, cdp->ce, - (*sc->read_register)( rp, SONIC_REG_CAP2 ), - (*sc->read_register)( rp, SONIC_REG_CAP1 ), - (*sc->read_register)( rp, SONIC_REG_CAP0 ), - (*sc->read_register)( rp, SONIC_REG_CE )); - rtems_panic ("SONIC LCAM"); - } -#endif - - (*sc->write_register)(rp, SONIC_REG_CR, /* CR_TXP | */CR_RXEN | CR_STP); - - /* - * Attach SONIC interrupt handler - */ -/* XXX - (*sc->write_register)( rp, SONIC_REG_IMR, 0 ); -*/ - - /* Ignore returned old handler */ - (void) set_vector(sonic_interrupt_handler, sc->vector, 1); - - /* - * Remainder of hardware initialization is - * done by the receive and transmit daemons. - */ -} - -/* - * Send packet (caller provides header). - */ - -SONIC_STATIC void sonic_start(struct ifnet *ifp) -{ - struct sonic_softc *sc = ifp->if_softc; - - rtems_bsdnet_event_send(sc->txDaemonTid, START_TRANSMIT_EVENT); - ifp->if_flags |= IFF_OACTIVE; -} - -/* - * Initialize and start the device - */ - -SONIC_STATIC void sonic_init (void *arg) -{ - struct sonic_softc *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - void *rp = sc->sonic; - int rcr; - - if (sc->txDaemonTid == 0) { - - /* - * Set up SONIC hardware - */ - sonic_initialize_hardware (sc); - - /* - * Start driver tasks - */ - sc->rxDaemonTid = rtems_bsdnet_newproc ("SNrx", 4096, sonic_rxDaemon, sc); - sc->txDaemonTid = rtems_bsdnet_newproc ("SNtx", 4096, sonic_txDaemon, sc); - } - - /* - * Set flags appropriately - */ - rcr = (*sc->read_register)( rp, SONIC_REG_RCR ); - if (ifp->if_flags & IFF_PROMISC) - rcr |= RCR_PRO; - else - rcr &= ~RCR_PRO; - (*sc->write_register)( rp, SONIC_REG_RCR, rcr); - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; - - /* - * Enable receiver and transmitter - */ - sonic_enable_interrupts( sc, IMR_TXEREN | (IMR_PRXEN | IMR_RBAEEN) ); - sonic_command( sc, CR_RXEN ); -} - -/* - * Driver ioctl handler - */ -static int -sonic_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - struct sonic_softc *sc = ifp->if_softc; - int error = 0; - - switch (command) { - case SIOCGIFADDR: - case SIOCSIFADDR: - ether_ioctl (ifp, command, data); - break; - - case SIOCSIFFLAGS: - switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { - case IFF_RUNNING: - sonic_stop (sc); - break; - - case IFF_UP: - sonic_init (sc); - break; - - case IFF_UP | IFF_RUNNING: - sonic_stop (sc); - sonic_init (sc); - break; - - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - sonic_stats (sc); - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } - return error; -} - -/* - * Attach an SONIC driver to the system - * This is the only `extern' function in the driver. - */ - -int -rtems_sonic_driver_attach ( - struct rtems_bsdnet_ifconfig *config, - sonic_configuration_t *chip -) -{ - struct sonic_softc *sc; - struct ifnet *ifp; - int mtu; - int unitNumber; - char *unitName; - - /* - * Parse driver name - */ - if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0) - return 0; - - /* - * Is driver free? - */ - if ((unitNumber <= 0) || (unitNumber > NSONIC)) { - printf ("Bad SONIC unit number.\n"); - return 0; - } - sc = &sonic_softc[unitNumber - 1]; - ifp = &sc->arpcom.ac_if; - if (ifp->if_softc != NULL) { - printf ("Driver already in use.\n"); - return 0; - } - - /* - * zero out the control structure - */ - - memset( sc, 0, sizeof(*sc) ); - - - /* - * Process options - */ - if (config->hardware_address) { - memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); - } - else { - memset (sc->arpcom.ac_enaddr, 0x08, ETHER_ADDR_LEN); - } - if (config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - if (config->rbuf_count) - sc->rdaCount = config->rbuf_count; - else - sc->rdaCount = chip->rda_count; - if (config->xbuf_count) - sc->tdaCount = config->xbuf_count; - else - sc->tdaCount = chip->tda_count; - sc->acceptBroadcast = !config->ignore_broadcast; - - sc->sonic = chip->base_address; - sc->vector = chip->vector; - sc->dcr_value = chip->dcr_value; - sc->dc2_value = chip->dc2_value; - sc->write_register = chip->write_register; - sc->read_register = chip->read_register; - - /* - * Set up network interface values - */ - ifp->if_softc = sc; - ifp->if_unit = unitNumber; - ifp->if_name = unitName; - ifp->if_mtu = mtu; - ifp->if_init = sonic_init; - ifp->if_ioctl = sonic_ioctl; - ifp->if_start = sonic_start; - ifp->if_output = ether_output; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; - if (ifp->if_snd.ifq_maxlen == 0) - ifp->if_snd.ifq_maxlen = ifqmaxlen; - - /* - * Attach the interface - */ - if_attach (ifp); - ether_ifattach (ifp); - return 1; -} - -#if (SONIC_DEBUG & SONIC_DEBUG_PRINT_REGISTERS) -#include - -char SONIC_Reg_name[64][6]= { - "CR", /* 0x00 */ - "DCR", /* 0x01 */ - "RCR", /* 0x02 */ - "TCR", /* 0x03 */ - "IMR", /* 0x04 */ - "ISR", /* 0x05 */ - "UTDA", /* 0x06 */ - "CTDA", /* 0x07 */ - "0x08", /* 0x08 */ - "0x09", /* 0x09 */ - "0x0A", /* 0x0A */ - "0x0B", /* 0x0B */ - "0x0C", /* 0x0C */ - "URDA", /* 0x0D */ - "CRDA", /* 0x0E */ - "0x0F", /* 0x0F */ - "0x10", /* 0x10 */ - "0x11", /* 0x11 */ - "0x12", /* 0x12 */ - "EOBC", /* 0x13 */ - "URRA", /* 0x14 */ - "RSA", /* 0x15 */ - "REA", /* 0x16 */ - "RRP", /* 0x17 */ - "RWP", /* 0x18 */ - "0x19", /* 0x19 */ - "0x1A", /* 0x1A */ - "0x1B", /* 0x1B */ - "0x1C", /* 0x1C */ - "0x0D", /* 0x1D */ - "0x1E", /* 0x1E */ - "0x1F", /* 0x1F */ - "0x20", /* 0x20 */ - "CEP", /* 0x21 */ - "CAP2", /* 0x22 */ - "CAP1", /* 0x23 */ - "CAP0", /* 0x24 */ - "CE", /* 0x25 */ - "CDP", /* 0x26 */ - "CDC", /* 0x27 */ - "SR", /* 0x28 */ - "WT0", /* 0x29 */ - "WT1", /* 0x2A */ - "RSC", /* 0x2B */ - "CRCT", /* 0x2C */ - "FAET", /* 0x2D */ - "MPT", /* 0x2E */ - "MDT", /* 0x2F */ - "0x30", /* 0x30 */ - "0x31", /* 0x31 */ - "0x32", /* 0x32 */ - "0x33", /* 0x33 */ - "0x34", /* 0x34 */ - "0x35", /* 0x35 */ - "0x36", /* 0x36 */ - "0x37", /* 0x37 */ - "0x38", /* 0x38 */ - "0x39", /* 0x39 */ - "0x3A", /* 0x3A */ - "0x3B", /* 0x3B */ - "0x3C", /* 0x3C */ - "0x3D", /* 0x3D */ - "0x3E", /* 0x3E */ - "DCR2" /* 0x3F */ -}; -#endif diff --git a/c/src/libchip/rtc/README.ds1643 b/c/src/libchip/rtc/README.ds1643 deleted file mode 100644 index a3a38605c8..0000000000 --- a/c/src/libchip/rtc/README.ds1643 +++ /dev/null @@ -1,3 +0,0 @@ -The Mostek M48T08 is compatible with the Dallas Semiconductor DS1643. Please -use that driver. - diff --git a/c/src/libchip/rtc/README.icm7170 b/c/src/libchip/rtc/README.icm7170 deleted file mode 100644 index d4ecff570f..0000000000 --- a/c/src/libchip/rtc/README.icm7170 +++ /dev/null @@ -1,48 +0,0 @@ - -Configuration Table Use -======================= - -sDeviceName - - The name of this device. - -deviceType - - This field must be RTC_ICM7170. - -pDeviceFns - - The device interface control table. This must be icm7170_fns. - -deviceProbe - - This is the address of the routine which probes to see if the device - is present. - -pDeviceParams - - This field specifies the clock frequency. It may be one of the - following: - ICM7170_AT_32_KHZ - ICM7170_AT_1_MHZ - ICM7170_AT_2_MHZ - ICM7170_AT_4_MHZ - -ulCtrlPort1 - - This field is the base address of the RTC area of the chip. - -ulCtrlPort2 - - This field is ignored. - -ulDataPort - - This field is ignored. - - -getRegister -setRegister - - These follow standard conventions. - diff --git a/c/src/libchip/rtc/README.m48t08 b/c/src/libchip/rtc/README.m48t08 deleted file mode 100644 index 25c032e85e..0000000000 --- a/c/src/libchip/rtc/README.m48t08 +++ /dev/null @@ -1,44 +0,0 @@ - -Configuration Table Use -======================= - -sDeviceName - - The name of this device. - -deviceType - - This field must be RTC_M48T08. - -pDeviceFns - - The device interface control table. This must be m48t08_fns. - -deviceProbe - - This is the address of the routine which probes to see if the device - is present. - -pDeviceParams - - This is ignored and should be NULL. - -ulCtrlPort1 - - This field is the base address of the RTC area of the chip. The - NVRAM portion of the chip is ignored. - -ulCtrlPort2 - - This field is ignored. - -ulDataPort - - This field is ignored. - - -getRegister -setRegister - - These follow standard conventions. - diff --git a/c/src/libchip/rtc/README.m48t18 b/c/src/libchip/rtc/README.m48t18 deleted file mode 100644 index 0925c62115..0000000000 --- a/c/src/libchip/rtc/README.m48t18 +++ /dev/null @@ -1 +0,0 @@ -This is supported by the m48t08 driver. diff --git a/c/src/libchip/rtc/README.mc146818a b/c/src/libchip/rtc/README.mc146818a deleted file mode 100644 index e9a9c86447..0000000000 --- a/c/src/libchip/rtc/README.mc146818a +++ /dev/null @@ -1 +0,0 @@ -This is supported by the mc146818a driver. diff --git a/c/src/libchip/rtc/STATUS b/c/src/libchip/rtc/STATUS deleted file mode 100644 index a6d5c41cd5..0000000000 --- a/c/src/libchip/rtc/STATUS +++ /dev/null @@ -1,33 +0,0 @@ -General -======= - -+ It would be nice to utilize the interrupt capabilities of some - RTC parts. This could be used to trigger checking the software - clock against the hardware clock. - -+ The periodic capability of most RTCs is not suitable for use - as a general purpose flexible clock tick source. For example, - many RTCs generate only a handful of periods with 100 Hz being the - most frequent. - -+ The tick field is not set on get. Anything smaller than a second - is ignored on set and get operations. - -+ Day of week is ignored since RTEMS does not set it internally. - -+ There is no attempt in RTEMS to know about time zones. - -Harris ICM7170 -============== - -+ Tested on a DMV177. - -+ Interrupt capabilities are ignored. - -Mostek 48T08 -============ - -+ Untested. - -+ NVRAM is ignored. - diff --git a/c/src/libchip/rtc/ds1375.c b/c/src/libchip/rtc/ds1375.c deleted file mode 100644 index 4a23a0044b..0000000000 --- a/c/src/libchip/rtc/ds1375.c +++ /dev/null @@ -1,461 +0,0 @@ -/* Driver for the Maxim 1375 i2c RTC (TOD only; very simple...) */ - -/* - * Authorship - * ---------- - * This software was created by - * - * Till Straumann , 2005-2007, - * Stanford Linear Accelerator Center, Stanford University. - * - * Acknowledgement of sponsorship - * ------------------------------ - * The software was produced by - * the Stanford Linear Accelerator Center, Stanford University, - * under Contract DE-AC03-76SFO0515 with the Department of Energy. - * - * Government disclaimer of liability - * ---------------------------------- - * Neither the United States nor the United States Department of Energy, - * nor any of their employees, makes any warranty, express or implied, or - * assumes any legal liability or responsibility for the accuracy, - * completeness, or usefulness of any data, apparatus, product, or process - * disclosed, or represents that its use would not infringe privately owned - * rights. - * - * Stanford disclaimer of liability - * -------------------------------- - * Stanford University makes no representations or warranties, express or - * implied, nor assumes any liability for the use of this software. - * - * Stanford disclaimer of copyright - * -------------------------------- - * Stanford University, owner of the copyright, hereby disclaims its - * copyright and all other rights in this software. Hence, anyone may - * freely use it for any purpose without restriction. - * - * Maintenance of notices - * ---------------------- - * In the interest of clarity regarding the origin and status of this - * SLAC software, this and all the preceding Stanford University notices - * are to remain affixed to any copy or derivative of this software made - * or distributed by the recipient and are to be affixed to any copy of - * software made or distributed by the recipient that contains a copy or - * derivative of this software. - * - * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 - */ - -/* This driver uses the file-system interface to the i2c bus */ - -#include /* write, read, close */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - - -#define STATIC static -#undef DEBUG - -/* The RTC driver routines are possibly called during - * system initialization -- that would be prior to opening - * the console. At this point it is not safe to use stdio - * (printf, perror etc.). - * Our file descriptors may even be 0..2 - */ -#define STDIOSAFE(fmt,args...) \ - do { \ - if ( _System_state_Is_up( _System_state_Get() ) ) { \ - fprintf(stderr,fmt,args); \ - } else { \ - printk(fmt,args); \ - } \ - } while (0) - - -STATIC uint8_t ds1375_bcd2bin(uint8_t x) -{ - uint8_t h = x & 0xf0; - - /* 8*hi + 2*hi + lo */ - return ( h >> 1 ) + ( h >> 3 ) + ( x & 0xf ); -} - -STATIC uint8_t ds1375_bin2bcd(uint8_t x) -{ - uint8_t h = x/10; - - return ( h << 4 ) + ( x - ( ( h << 3 ) + ( h << 1 ) ) ); -} - -/* - * Register Definitions and Access Macros - * - * The xxx_REG macros are offsets into the register files - * The xxx_OFF macros are offsets into a in-memory buffer - * starting at the seconds (for the 1375 both, - * _REG and _OFF happen to be identical). - */ -#define DS1375_SEC_REG 0x0 -#define DS1375_SEC_OFF (DS1375_SEC_REG-DS1375_SEC_REG) -/* Extract seconds and convert to binary */ -#define DS1375_SEC(x) ds1375_bcd2bin( ((x)[DS1375_SEC_OFF]) & 0x7f ) - -#define DS1375_MIN_REG 0x1 -#define DS1375_MIN_OFF (DS1375_MIN_REG-DS1375_SEC_REG) -/* Extract minutes and convert to binary */ -#define DS1375_MIN(x) ds1375_bcd2bin( ((x)[DS1375_MIN_OFF]) & 0x7f ) - -#define DS1375_HR_REG 0x2 -#define DS1375_HR_OFF (DS1375_HR_REG-DS1375_SEC_REG) -#define DS1375_HR_1224 (1<<6) -#define DS1375_HR_AMPM (1<<5) -/* Are hours in AM/PM representation ? */ -#define DS1375_IS_AMPM(x) (DS1375_HR_1224 & ((x)[DS1375_HR_OFF])) -/* Are we PM ? */ -#define DS1375_IS_PM(x) (DS1375_HR_AMPM & ((x)[DS1375_HR_OFF])) -/* Extract hours (12h mode) and convert to binary */ -#define DS1375_HR_12(x) ds1375_bcd2bin( ((x)[DS1375_HR_OFF]) & 0x1f ) -/* Extract hours (24h mode) and convert to binary */ -#define DS1375_HR_24(x) ds1375_bcd2bin( ((x)[DS1375_HR_OFF]) & 0x3f ) - -#define DS1375_DAY_REG 0x3 -#define DS1375_DAY_OFF (DS1375_DAY_REG-DS1375_SEC_REG) -#define DS1375_DAT_REG 0x4 -#define DS1375_DAT_OFF (DS1375_DAT_REG-DS1375_SEC_REG) -/* Extract date and convert to binary */ -#define DS1375_DAT(x) ds1375_bcd2bin( ((x)[DS1375_DAT_OFF]) & 0x3f ) -#define DS1375_MON_REG 0x5 -#define DS1375_MON_OFF (DS1375_MON_REG-DS1375_SEC_REG) -#define DS1375_MON_CTRY (1<<7) -/* Is century bit set ? */ -#define DS1375_IS_CTRY(x) (((x)[DS1375_MON_OFF]) & DS1375_MON_CTRY) -/* Extract month and convert to binary */ -#define DS1375_MON(x) ds1375_bcd2bin( ((x)[DS1375_MON_OFF]) & 0x1f ) - -#define DS1375_YR_REG 0x6 -#define DS1375_YR_OFF (DS1375_YR_REG-DS1375_SEC_REG) -/* Extract year and convert to binary */ -#define DS1375_YR(x) ds1375_bcd2bin( ((x)[DS1375_YR_OFF]) & 0xff ) - -/* CR Register and bit definitions */ -#define DS1375_CR_REG 0xe -#define DS1375_CR_ECLK (1<<7) -#define DS1375_CR_CLKSEL1 (1<<6) -#define DS1375_CR_CLKSEL0 (1<<5) -#define DS1375_CR_RS2 (1<<4) -#define DS1375_CR_RS1 (1<<3) -#define DS1375_CR_INTCN (1<<2) -#define DS1375_CR_A2IE (1<<1) -#define DS1375_CR_A1IE (1<<0) - -#define DS1375_CSR_REG 0xf - -/* User SRAM (8 bytes) */ -#define DS1375_RAM 0x10 /* start of 8 bytes user ram */ - -/* Access Primitives */ - -STATIC int rd_bytes( - int fd, - uint32_t off, - uint8_t *buf, - int len -) -{ - uint8_t ptr = off; - - return 1 == write( fd, &ptr, 1 ) && len == read( fd, buf, len ) ? 0 : -1; -} - -STATIC int wr_bytes( - int fd, - uint32_t off, - uint8_t *buf, - int len -) -{ - uint8_t d[ len + 1 ]; - - /* Must not break up writing of the register pointer and - * the data to-be-written into multiple write() calls - * because every 'write()' operation sends START and - * the chip interprets the first byte after START as - * the register pointer. - */ - - d[0] = off; - memcpy( d + 1, buf, len ); - - return len + 1 == write( fd, d, len + 1 ) ? 0 : -1; -} - -/* Helpers */ - -static int getfd( - int minor -) -{ - return open( (const char *)RTC_Table[minor].ulCtrlPort1, O_RDWR ); -} - -/* Driver Access Functions */ - -STATIC void ds1375_initialize( - int minor -) -{ - int fd; - uint8_t cr; - - if ( ( fd = getfd( minor ) ) >= 0 ) { - if ( 0 == rd_bytes( fd, DS1375_CR_REG, &cr, 1 ) ) { - /* make sure clock is enabled */ - if ( ! ( DS1375_CR_ECLK & cr ) ) { - cr |= DS1375_CR_ECLK; - wr_bytes( fd, DS1375_CR_REG, &cr, 1 ); - } - } - close( fd ); - } - -} - -STATIC int ds1375_get_time( - int minor, - rtems_time_of_day *time -) -{ - int rval = -1; - int fd; - uint8_t buf[DS1375_YR_REG + 1 - DS1375_SEC_REG]; - - if ( time && ( ( fd = getfd( minor ) ) >= 0 ) ) { - if ( 0 == rd_bytes( fd, DS1375_SEC_REG, buf, sizeof(buf) ) ) { - time->year = DS1375_IS_CTRY( buf ) ? 2000 : 1900; - time->year += DS1375_YR ( buf ); - time->month = DS1375_MON( buf ); - time->day = DS1375_DAT( buf ); /* DAY is weekday */ - - if ( DS1375_IS_AMPM( buf ) ) { - time->hour = DS1375_HR_12 ( buf ); - if ( DS1375_IS_PM( buf ) ) - time->hour += 12; - } else { - time->hour = DS1375_HR_24 ( buf ); - } - - time->minute = DS1375_MIN( buf ); - time->second = DS1375_SEC( buf ); - time->ticks = 0; - rval = 0; - } - close( fd ); - } - return rval; -} - -STATIC int ds1375_set_time( - int minor, - const rtems_time_of_day *time -) -{ - int rval = -1; - int fd = -1; - time_t secs; - struct tm tm; - uint8_t buf[DS1375_YR_REG + 1 - DS1375_SEC_REG]; - uint8_t cr = 0xff; - - /* - * The clock hardware maintains the day-of-week as a separate counter - * so we must compute it ourselves (rtems_time_of_day doesn't come - * with a day of week). - */ - secs = _TOD_To_seconds( time ); - /* we're only interested in tm_wday... */ - gmtime_r( &secs, &tm ); - - buf[DS1375_SEC_OFF] = ds1375_bin2bcd( time->second ); - buf[DS1375_MIN_OFF] = ds1375_bin2bcd( time->minute ); - /* bin2bcd(hour) implicitly selects 24h mode since ms-bit is clear */ - buf[DS1375_HR_OFF] = ds1375_bin2bcd( time->hour ); - buf[DS1375_DAY_OFF] = tm.tm_wday + 1; - buf[DS1375_DAT_OFF] = ds1375_bin2bcd( time->day ); - buf[DS1375_MON_OFF] = ds1375_bin2bcd( time->month ); - - if ( time->year >= 2000 ) { - buf[DS1375_YR_OFF] = ds1375_bin2bcd( time->year - 2000 ); - buf[DS1375_MON_OFF] |= DS1375_MON_CTRY; - } else { - buf[DS1375_YR_OFF] = ds1375_bin2bcd( time->year - 1900 ); - } - - /* - * Stop clock; update registers and restart. This is slightly - * slower than just writing everyting but if we did that we - * could get inconsistent registers if this routine would not - * complete in less than 1s (says the datasheet) and we don't - * know if we are going to be pre-empted for some time... - */ - if ( ( fd = getfd( minor ) ) < 0 ) { - goto cleanup; - } - - if ( rd_bytes( fd, DS1375_CR_REG, &cr, 1 ) ) - goto cleanup; - - cr &= ~DS1375_CR_ECLK; - - /* This stops the clock */ - if ( wr_bytes( fd, DS1375_CR_REG, &cr, 1 ) ) - goto cleanup; - - /* write new contents */ - if ( wr_bytes( fd, DS1375_SEC_REG, buf, sizeof(buf) ) ) - goto cleanup; - - rval = 0; - -cleanup: - if ( fd >= 0 ) { - if ( ! ( DS1375_CR_ECLK & cr ) ) { - /* start clock; this handles some cases of failure - * after stopping the clock by restarting it again - */ - cr |= DS1375_CR_ECLK; - if ( wr_bytes( fd, DS1375_CR_REG, &cr, 1 ) ) - rval = -1; - } - close( fd ); - } - return rval; -} - -/* Debugging / Testing */ - -#ifdef DEBUG - -/* Don't forget to set "TZ" when using these test routines */ - -/* What is rtems_time_of_day good for ? Why not use std types ? */ - -uint32_t -ds1375_get_time_tst() -{ -rtems_time_of_day rtod; -time_t secs; - - ds1375_get_time( 0, &rtod ); - secs = _TOD_To_seconds( &rtod ); - printf( "%s\n", ctime( &secs ) ); - return secs; -} - -int -ds1375_set_time_tst( const char *datstr, rtems_time_of_day *prt ) -{ -struct tm tm; -time_t secs; -rtems_time_of_day rt; - - if ( !datstr ) - return -1; - - if ( ! strptime( datstr, "%Y-%m-%d/%T", &tm ) ) - return -2; - - if ( ! prt ) - prt = &rt; - - secs = mktime( &tm ); - - /* convert to UTC */ - gmtime_r( &secs, &tm ); - - printf("Y: %"PRIu32" ", (prt->year = tm.tm_year + 1900) ); - printf("M: %"PRIu32" ", (prt->month = tm.tm_mon + 1) ); - printf("D: %"PRIu32" ", (prt->day = tm.tm_mday ) ); - printf("h: %"PRIu32" ", (prt->hour = tm.tm_hour ) ); - printf("m: %"PRIu32" ", (prt->minute = tm.tm_min ) ); - printf("s: %"PRIu32"\n", (prt->second = tm.tm_sec ) ); - prt->ticks = 0; - - return ( prt == &rt ) ? ds1375_set_time( 0, &rt ) : 0; -} - -#endif - - -uint32_t -rtc_ds1375_get_register( uintptr_t port, uint8_t reg ) -{ -int fd; -uint8_t v; -uint32_t rval = -1; - - if ( ( fd = open( (const char*)port, O_RDWR ) ) >= 0 ) { - - if ( 0 == rd_bytes( fd, reg, &v, 1 ) ) { - rval = v; - } - close( fd ); - } - - return rval; -} - -void -rtc_ds1375_set_register( uintptr_t port, uint8_t reg, uint32_t value ) -{ -int fd; -uint8_t v = value; - - if ( ( fd = open( (const char*)port, O_RDWR ) ) >= 0 ) { - wr_bytes( fd, reg, &v, 1 ); - close( fd ); - } - -} - -bool rtc_ds1375_device_probe( - int minor -) -{ - int fd; - - if ( ( fd = getfd( minor ) ) < 0 ) { - STDIOSAFE( "ds1375_probe (open): %s\n", strerror( errno ) ); - return false; - } - - /* Try to set file pointer */ - if ( 0 != wr_bytes( fd, DS1375_SEC_REG, 0, 0 ) ) { - STDIOSAFE( "ds1375_probe (wr_bytes): %s\n", strerror( errno ) ); - close( fd ); - return false; - } - - if ( close( fd ) ) { - STDIOSAFE( "ds1375_probe (close): %s\n", strerror( errno ) ); - return false; - } - - return true; -} - -rtc_fns rtc_ds1375_fns = { - .deviceInitialize = ds1375_initialize, - .deviceGetTime = ds1375_get_time, - .deviceSetTime = ds1375_set_time, -}; diff --git a/c/src/libchip/rtc/icm7170.c b/c/src/libchip/rtc/icm7170.c deleted file mode 100644 index 1cc9e980f7..0000000000 --- a/c/src/libchip/rtc/icm7170.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * This file interfaces with the real-time clock found in - * a Harris ICM7170 - * - * Year 2K Notes: - * - * This chip only uses a two digit field to store the year. This - * code uses the RTEMS Epoch as a pivot year. This lets us map the - * two digit year field as follows: - * - * + two digit years 0-87 are mapped to 2000-2087. - * + two digit years 88-99 are mapped to 1988-1999. - * - * This is less than the time span supported by RTEMS. - * - * COPYRIGHT (c) 1989-1999. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include - -/* - * Control register bits - */ - -/* XXX */ - -/* - * icm7170_initialize - */ - -static void icm7170_initialize( - int minor -) -{ - uintptr_t icm7170; - setRegister_f setReg; - uintptr_t clock; - - icm7170 = RTC_Table[ minor ].ulCtrlPort1; - setReg = RTC_Table[ minor ].setRegister; - - /* - * Initialize the RTC with the proper clock frequency - */ - - clock = (uintptr_t) RTC_Table[ minor ].pDeviceParams; - (*setReg)( icm7170, ICM7170_CONTROL, 0x0c | clock ); -} - -/* - * icm7170_get_time - */ - -static int icm7170_get_time( - int minor, - rtems_time_of_day *time -) -{ - uint32_t icm7170; - getRegister_f getReg; - uint32_t year; - - icm7170 = RTC_Table[ minor ].ulCtrlPort1; - getReg = RTC_Table[ minor ].getRegister; - - /* - * Put the RTC into read mode - */ - - (void) (*getReg)( icm7170, ICM7170_COUNTER_HUNDREDTHS ); - - /* - * Now get the time - */ - - - year = (*getReg)( icm7170, ICM7170_YEAR ); - if ( year < 88 ) - year += 2000; - else - year += 1900; - - time->year = year; - time->month = (*getReg)( icm7170, ICM7170_MONTH ); - time->day = (*getReg)( icm7170, ICM7170_DATE ); - time->hour = (*getReg)( icm7170, ICM7170_HOUR ); - time->minute = (*getReg)( icm7170, ICM7170_MINUTE ); - time->second = (*getReg)( icm7170, ICM7170_SECOND ); - - time->ticks = 0; - - /* - * Put the RTC back into normal mode. - */ - - (void) (*getReg)( icm7170, ICM7170_COUNTER_HUNDREDTHS ); - - return 0; -} - -/* - * icm7170_set_time - */ - -static int icm7170_set_time( - int minor, - const rtems_time_of_day *time -) -{ - uintptr_t icm7170; - setRegister_f setReg; - uint32_t year; - uintptr_t clock; - - icm7170 = RTC_Table[ minor ].ulCtrlPort1; - setReg = RTC_Table[ minor ].setRegister; - clock = (uintptr_t) RTC_Table[ minor ].pDeviceParams; - - year = time->year; - - if ( year >= 2088 ) - rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER ); - - if ( year >= 2000 ) - year -= 2000; - else - year -= 1900; - - (*setReg)( icm7170, ICM7170_CONTROL, 0x04 | clock ); - - (*setReg)( icm7170, ICM7170_YEAR, year ); - (*setReg)( icm7170, ICM7170_MONTH, time->month ); - (*setReg)( icm7170, ICM7170_DATE, time->day ); - (*setReg)( icm7170, ICM7170_HOUR, time->hour ); - (*setReg)( icm7170, ICM7170_MINUTE, time->minute ); - (*setReg)( icm7170, ICM7170_SECOND, time->second ); - - /* - * This is not really right. - */ - - (*setReg)( icm7170, ICM7170_DAY_OF_WEEK, 1 ); - - /* - * Put the RTC back into normal mode. - */ - - (*setReg)( icm7170, ICM7170_CONTROL, 0x0c | clock ); - - return 0; -} - -/* - * Driver function table - */ - -rtc_fns icm7170_fns = { - icm7170_initialize, - icm7170_get_time, - icm7170_set_time -}; diff --git a/c/src/libchip/rtc/icm7170_reg.c b/c/src/libchip/rtc/icm7170_reg.c deleted file mode 100644 index 747f1f218d..0000000000 --- a/c/src/libchip/rtc/icm7170_reg.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file contains a typical set of register access routines which may be - * used with the icm7170 chip if accesses to the chip are as follows: - * - * + registers are accessed as bytes - * + registers are only byte-aligned (no address gaps) - * - * COPYRIGHT (c) 1989-1997. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include - -#ifndef _ICM7170_MULTIPLIER -#define _ICM7170_MULTIPLIER 1 -#define _ICM7170_NAME(_X) _X -#define _ICM7170_TYPE uint8_t -#endif - -#define CALCULATE_REGISTER_ADDRESS( _base, _reg ) \ - (_ICM7170_TYPE *)((_base) + ((_reg) * _ICM7170_MULTIPLIER )) - -/* - * ICM7170 Get Register Routine - */ - -uint32_t _ICM7170_NAME(icm7170_get_register)( - uintptr_t ulCtrlPort, - uint8_t ucRegNum -) -{ - _ICM7170_TYPE *port; - - port = CALCULATE_REGISTER_ADDRESS( ulCtrlPort, ucRegNum ); - - return *port; -} - -/* - * ICM7170 Set Register Routine - */ - -void _ICM7170_NAME(icm7170_set_register)( - uintptr_t ulCtrlPort, - uint8_t ucRegNum, - uint32_t ucData -) -{ - _ICM7170_TYPE *port; - - port = CALCULATE_REGISTER_ADDRESS( ulCtrlPort, ucRegNum ); - - *port = ucData; -} diff --git a/c/src/libchip/rtc/icm7170_reg2.c b/c/src/libchip/rtc/icm7170_reg2.c deleted file mode 100644 index 179d76c6f5..0000000000 --- a/c/src/libchip/rtc/icm7170_reg2.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This file contains a typical set of register access routines which may be - * used with the icm7170 chip if accesses to the chip are as follows: - * - * + registers are accessed as bytes - * + registers are on 16-bit boundaries - * - * COPYRIGHT (c) 1989-1997. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#define _ICM7170_MULTIPLIER 2 -#define _ICM7170_NAME(_X) _X##_2 -#define _ICM7170_TYPE uint8_t - -#include "icm7170_reg.c" diff --git a/c/src/libchip/rtc/icm7170_reg4.c b/c/src/libchip/rtc/icm7170_reg4.c deleted file mode 100644 index dada40961c..0000000000 --- a/c/src/libchip/rtc/icm7170_reg4.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This file contains a typical set of register access routines which may be - * used with the icm7170 chip if accesses to the chip are as follows: - * - * + registers are accessed as bytes - * + registers are on 32-bit boundaries - * - * COPYRIGHT (c) 1989-1997. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#define _ICM7170_MULTIPLIER 4 -#define _ICM7170_NAME(_X) _X##_4 -#define _ICM7170_TYPE uint8_t - -#include "icm7170_reg.c" diff --git a/c/src/libchip/rtc/icm7170_reg8.c b/c/src/libchip/rtc/icm7170_reg8.c deleted file mode 100644 index a1fb1a5ea2..0000000000 --- a/c/src/libchip/rtc/icm7170_reg8.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This file contains a typical set of register access routines which may be - * used with the icm7170 chip if accesses to the chip are as follows: - * - * + registers are accessed as bytes - * + registers are on 64-bit boundaries - * - * COPYRIGHT (c) 1989-1997. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#define _ICM7170_MULTIPLIER 8 -#define _ICM7170_NAME(_X) _X##_8 -#define _ICM7170_TYPE uint8_t - -#include "icm7170_reg.c" diff --git a/c/src/libchip/rtc/m48t08.c b/c/src/libchip/rtc/m48t08.c deleted file mode 100644 index 3b600bd995..0000000000 --- a/c/src/libchip/rtc/m48t08.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * This file interfaces with the real-time clock found in - * a Mostek M48T08 or M48T18 or compatibles. - * - * Year 2K Notes: - * - * This chip only uses a two digit field to store the year. This - * code uses the RTEMS Epoch as a pivot year. This lets us map the - * two digit year field as follows: - * - * + two digit years 0-87 are mapped to 2000-2087. - * + two digit years 88-99 are mapped to 1988-1999. - * - * This is less than the time span supported by RTEMS. - * - * COPYRIGHT (c) 1989-1999. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include - -/* - * Control register bits - */ - -#define M48T08_CONTROL_WRITE 0x80 -#define M48T08_CONTROL_READ 0x40 -#define M48T08_CONTROL_SIGN 0x20 - -/* - * m48t08_initialize - */ - -static void m48t08_initialize( - int minor -) -{ -} - -/* - * m48t08_get_time - */ - -#define From_BCD( _x ) ((((_x) >> 4) * 10) + ((_x) & 0x0F)) -#define To_BCD( _x ) ((((_x) / 10) << 4) + ((_x) % 10)) - -static int m48t08_get_time( - int minor, - rtems_time_of_day *time -) -{ - uint32_t m48t08; - getRegister_f getReg; - setRegister_f setReg; - uint8_t controlReg; - uint32_t value1; - uint32_t value2; - - m48t08 = RTC_Table[ minor ].ulCtrlPort1; - getReg = RTC_Table[ minor ].getRegister; - setReg = RTC_Table[ minor ].setRegister; - - /* - * Put the RTC into read mode - */ - - controlReg = (*getReg)( m48t08, M48T08_CONTROL ); - (*setReg)( m48t08, M48T08_CONTROL, controlReg | M48T08_CONTROL_READ ); - - value1 = (*getReg)( m48t08, M48T08_YEAR ); - value2 = From_BCD( value1 ); - if ( value2 < 88 ) - time->year = 2000 + value2; - else - time->year = 1900 + value2; - - value1 = (*getReg)( m48t08, M48T08_MONTH ); - time->month = From_BCD( value1 ); - - value1 = (*getReg)( m48t08, M48T08_DATE ); - time->day = From_BCD( value1 ); - - value1 = (*getReg)( m48t08, M48T08_HOUR ); - time->hour = From_BCD( value1 ); - - value1 = (*getReg)( m48t08, M48T08_MINUTE ); - time->minute = From_BCD( value1 ); - - value1 = (*getReg)( m48t08, M48T08_SECOND ); - time->second = From_BCD( value1 ); - - time->ticks = 0; - - /* - * Put the RTC back into normal mode. - */ - - (*setReg)( m48t08, M48T08_CONTROL, controlReg ); - - return 0; -} - -/* - * m48t08_set_time - */ - -static int m48t08_set_time( - int minor, - const rtems_time_of_day *time -) -{ - uint32_t m48t08; - getRegister_f getReg; - setRegister_f setReg; - uint8_t controlReg; - - m48t08 = RTC_Table[ minor ].ulCtrlPort1; - getReg = RTC_Table[ minor ].getRegister; - setReg = RTC_Table[ minor ].setRegister; - - /* - * Put the RTC into read mode - */ - - controlReg = (*getReg)( m48t08, M48T08_CONTROL ); - (*setReg)( m48t08, M48T08_CONTROL, controlReg | M48T08_CONTROL_WRITE ); - - if ( time->year >= 2088 ) - rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER ); - - (*setReg)( m48t08, M48T08_YEAR, To_BCD(time->year % 100) ); - (*setReg)( m48t08, M48T08_MONTH, To_BCD(time->month) ); - (*setReg)( m48t08, M48T08_DATE, To_BCD(time->day) ); - (*setReg)( m48t08, M48T08_HOUR, To_BCD(time->hour) ); - (*setReg)( m48t08, M48T08_MINUTE, To_BCD(time->minute) ); - (*setReg)( m48t08, M48T08_SECOND, To_BCD(time->second) ); - - /* - * Put the RTC back into normal mode. - */ - - (*setReg)( m48t08, M48T08_CONTROL, controlReg ); - - return 0; -} - -/* - * Driver function table - */ - -rtc_fns m48t08_fns = { - m48t08_initialize, - m48t08_get_time, - m48t08_set_time -}; diff --git a/c/src/libchip/rtc/m48t08_reg.c b/c/src/libchip/rtc/m48t08_reg.c deleted file mode 100644 index 2174496fda..0000000000 --- a/c/src/libchip/rtc/m48t08_reg.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file contains a typical set of register access routines which may be - * used with the m48t08 chip if accesses to the chip are as follows: - * - * + registers are accessed as bytes - * + registers are only byte-aligned (no address gaps) - * - * COPYRIGHT (c) 1989-1997. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include - -#ifndef _M48T08_MULTIPLIER -#define _M48T08_MULTIPLIER 1 -#define _M48T08_NAME(_X) _X -#define _M48T08_TYPE uint8_t -#endif - -#define CALCULATE_REGISTER_ADDRESS( _base, _reg ) \ - (_M48T08_TYPE *)((_base) + ((_reg) * _M48T08_MULTIPLIER )) - -/* - * M48T08 Get Register Routine - */ - -uint32_t _M48T08_NAME(m48t08_get_register)( - uintptr_t ulCtrlPort, - uint8_t ucRegNum -) -{ - _M48T08_TYPE *port; - - port = CALCULATE_REGISTER_ADDRESS( ulCtrlPort, ucRegNum ); - - return *port; -} - -/* - * M48T08 Set Register Routine - */ - -void _M48T08_NAME(m48t08_set_register)( - uintptr_t ulCtrlPort, - uint8_t ucRegNum, - uint32_t ucData -) -{ - _M48T08_TYPE *port; - - port = CALCULATE_REGISTER_ADDRESS( ulCtrlPort, ucRegNum ); - - *port = ucData; -} diff --git a/c/src/libchip/rtc/m48t08_reg2.c b/c/src/libchip/rtc/m48t08_reg2.c deleted file mode 100644 index 87d2041946..0000000000 --- a/c/src/libchip/rtc/m48t08_reg2.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This file contains a typical set of register access routines which may be - * used with the m48t08 chip if accesses to the chip are as follows: - * - * + registers are accessed as bytes - * + registers are on 16-bit boundaries - * - * COPYRIGHT (c) 1989-1997. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#define _M48T08_MULTIPLIER 2 -#define _M48T08_NAME(_X) _X##_2 -#define _M48T08_TYPE uint8_t - -#include "m48t08_reg.c" diff --git a/c/src/libchip/rtc/m48t08_reg4.c b/c/src/libchip/rtc/m48t08_reg4.c deleted file mode 100644 index 2203249503..0000000000 --- a/c/src/libchip/rtc/m48t08_reg4.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This file contains a typical set of register access routines which may be - * used with the m48t08 chip if accesses to the chip are as follows: - * - * + registers are accessed as bytes - * + registers are on 32-bit boundaries - * - * COPYRIGHT (c) 1989-1997. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#define _M48T08_MULTIPLIER 4 -#define _M48T08_NAME(_X) _X##_4 -#define _M48T08_TYPE uint8_t - -#include "m48t08_reg.c" diff --git a/c/src/libchip/rtc/m48t08_reg8.c b/c/src/libchip/rtc/m48t08_reg8.c deleted file mode 100644 index 83044d752b..0000000000 --- a/c/src/libchip/rtc/m48t08_reg8.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This file contains a typical set of register access routines which may be - * used with the m48t08 chip if accesses to the chip are as follows: - * - * + registers are accessed as bytes - * + registers are on 64-bit boundaries - * - * COPYRIGHT (c) 1989-1997. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#define _M48T08_MULTIPLIER 8 -#define _M48T08_NAME(_X) _X##_8 -#define _M48T08_TYPE uint8_t - -#include "m48t08_reg.c" diff --git a/c/src/libchip/rtc/mc146818a.c b/c/src/libchip/rtc/mc146818a.c deleted file mode 100644 index 2720ce5e8a..0000000000 --- a/c/src/libchip/rtc/mc146818a.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * This file interfaces with the real-time clock found in - * a Motorola MC146818A (common on PC hardware) - * - * Year 2K Notes: - * - * This chip only uses a two digit field to store the year. This - * code uses the RTEMS Epoch as a pivot year. This lets us map the - * two digit year field as follows: - * - * + two digit years 0-87 are mapped to 2000-2087. - * + two digit years 88-99 are mapped to 1988-1999. - * - * This is less than the time span supported by RTEMS. - * - * COPYRIGHT (c) 1989-1999. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ -#include -#include -#include - -#define From_BCD( _x ) ((((_x) >> 4) * 10) + ((_x) & 0x0F)) -#define To_BCD( _x ) ((((_x) / 10) << 4) + ((_x) % 10)) - -/* - * See if chip is present - */ -bool mc146818a_probe( - int minor -) -{ - uint32_t mc146818a; - getRegister_f getReg; - uint32_t value; - - /* - * Verify that chip is present and that time is valid - */ - mc146818a = RTC_Table[ minor ].ulCtrlPort1; - getReg = RTC_Table[ minor ].getRegister; - value = (*getReg)( mc146818a, MC146818A_STATUSD ); - if ((value == 0) || (value == 0xFF)) - return false; - return true; -} - -/* - * Initialize chip - */ -static void mc146818a_initialize( - int minor -) -{ - uintptr_t mc146818a; - setRegister_f setReg; - - mc146818a = RTC_Table[ minor ].ulCtrlPort1; - setReg = RTC_Table[ minor ].setRegister; - - (*setReg)( - mc146818a, - MC146818A_STATUSA, - MC146818ASA_DIVIDER|MC146818ASA_1024 - ); - (*setReg)( - mc146818a, - MC146818A_STATUSB, - MC146818ASB_24HR - ); -} - -/* - * Read time from chip - */ -static int mc146818a_get_time( - int minor, - rtems_time_of_day *time -) -{ - uintptr_t mc146818a; - getRegister_f getReg; - uint32_t value; - rtems_interrupt_level level; - - mc146818a = RTC_Table[ minor ].ulCtrlPort1; - getReg = RTC_Table[ minor ].getRegister; - - /* - * No time if power failed - */ - if (((*getReg)( mc146818a, MC146818A_STATUSD ) & MC146818ASD_PWR) == 0) - return -1; - - /* - * Wait for time update to complete - */ - rtems_interrupt_disable( level ); - while (((*getReg)( mc146818a, MC146818A_STATUSA ) & MC146818ASA_TUP) != 0) { - rtems_interrupt_flash( level ); - } - - /* - * Read the time (we have at least 244 usec to do this) - */ - value = (*getReg)( mc146818a, MC146818A_YEAR ); - value = From_BCD( value ); - if ( value < 88 ) - time->year = 2000 + value; - else - time->year = 1900 + value; - - value = (*getReg)( mc146818a, MC146818A_MONTH ); - time->month = From_BCD( value ); - - value = (*getReg)( mc146818a, MC146818A_DAY ); - time->day = From_BCD( value ); - - value = (*getReg)( mc146818a, MC146818A_HRS ); - time->hour = From_BCD( value ); - - value = (*getReg)( mc146818a, MC146818A_MIN ); - time->minute = From_BCD( value ); - - value = (*getReg)( mc146818a, MC146818A_SEC ); - rtems_interrupt_enable( level ); - time->second = From_BCD( value ); - time->ticks = 0; - - return 0; -} - -/* - * Set time into chip - */ -static int mc146818a_set_time( - int minor, - const rtems_time_of_day *time -) -{ - uint32_t mc146818a; - setRegister_f setReg; - - mc146818a = RTC_Table[ minor ].ulCtrlPort1; - setReg = RTC_Table[ minor ].setRegister; - - /* - * Stop the RTC - */ - (*setReg)( mc146818a, MC146818A_STATUSB, MC146818ASB_HALT|MC146818ASB_24HR ); - - if ( time->year >= 2088 ) - rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER ); - - (*setReg)( mc146818a, MC146818A_YEAR, To_BCD(time->year % 100) ); - (*setReg)( mc146818a, MC146818A_MONTH, To_BCD(time->month) ); - (*setReg)( mc146818a, MC146818A_DAY, To_BCD(time->day) ); - (*setReg)( mc146818a, MC146818A_HRS, To_BCD(time->hour) ); - (*setReg)( mc146818a, MC146818A_MIN, To_BCD(time->minute) ); - (*setReg)( mc146818a, MC146818A_SEC, To_BCD(time->second) ); - - /* - * Restart the RTC - */ - (*setReg)( mc146818a, MC146818A_STATUSB, MC146818ASB_24HR ); - return 0; -} - -/* - * Driver function table - */ -rtc_fns mc146818a_fns = { - mc146818a_initialize, - mc146818a_get_time, - mc146818a_set_time -}; diff --git a/c/src/libchip/rtc/mc146818a_ioreg.c b/c/src/libchip/rtc/mc146818a_ioreg.c deleted file mode 100644 index 4c438a516a..0000000000 --- a/c/src/libchip/rtc/mc146818a_ioreg.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file contains a typical set of register access routines which may be - * used with the MC146818A chip if accesses to the chip are as follows: - * - * + registers are in I/O space - * + registers are accessed as bytes - * + registers are only byte-aligned (no address gaps) - */ - -/* - * COPYRIGHT (c) 1989-1997. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include - -/* - * At this point, not all CPUs or BSPs have defined in/out port routines. - */ -#if defined(__i386__) || defined(__PPC__) -#if defined(inport_byte) -uint32_t mc146818a_get_register( - uintptr_t ulCtrlPort, - uint8_t ucRegNum -) -{ - uint8_t val; - uint8_t tmp; - - (void) tmp; /* eliminate warning for set but not used */ - - outport_byte( ulCtrlPort, ucRegNum ); - inport_byte( 0x84, tmp ); /* Hack a delay to give chip time to settle */ - inport_byte( ulCtrlPort+1, val ); - inport_byte( 0x84, tmp ); /* Hack a delay to give chip time to settle */ - return val; -} - -void mc146818a_set_register( - uintptr_t ulCtrlPort, - uint8_t ucRegNum, - uint32_t ucData -) -{ - outport_byte( ulCtrlPort, ucRegNum ); - outport_byte( ulCtrlPort+1, (uint8_t)ucData ); -} -#endif -#endif diff --git a/c/src/libchip/rtc/rtcprobe.c b/c/src/libchip/rtc/rtcprobe.c deleted file mode 100644 index 71472ffd7c..0000000000 --- a/c/src/libchip/rtc/rtcprobe.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - * This file contains the default Real-Time Clock probe routine. - * - * COPYRIGHT (c) 1989-1999. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include - - -bool rtc_probe( - int minor -) -{ - return true; -} diff --git a/c/src/libchip/serial/README b/c/src/libchip/serial/README deleted file mode 100644 index 59bb9e90fa..0000000000 --- a/c/src/libchip/serial/README +++ /dev/null @@ -1,13 +0,0 @@ -This is the serial controller portion of the libchip library. This -directory contains the source code for reusable console driver -support code. Each individual driver is configured using the -console_tbl data structure. This structure is defined and explained -in the console.h file. - -The reusable chip drivers do not directly access the serial controller. -They access the registers on the controller via a set of up to four -functions which are provided by the BSP. These functins set and get -general registers and data buffers. Some chips can access the data -buffers as general registers and thus the driver may not require -those interface routines. - diff --git a/c/src/libchip/serial/README.mc68681 b/c/src/libchip/serial/README.mc68681 deleted file mode 100644 index e0966d0e10..0000000000 --- a/c/src/libchip/serial/README.mc68681 +++ /dev/null @@ -1,83 +0,0 @@ -Configuration Table Use -======================= - -sDeviceName - - The name of this device. - -deviceType - - This field must be SERIAL_MC68681. - -pDeviceFns - - The device interface control table. This may be: - + mc68681_fns for interrupt driven IO - + mc68681_fns_polled for polled IO - -deviceProbe - - This is the address of the routine which probes to see if the device - is present. - -pDeviceFlow - - This field is ignored as hardware flow control is not currently supported. - -ulMargin - - This is currently unused. - -ulHysteresis - - This is currently unused. - -pDeviceParams - - This is set to the default settings. - -ulCtrlPort1 - - This field is the base address of the entire DUART. - -ulCtrlPort2 - - This field is the base address of the port specific registers. - -ulDataPort - - This field is bit mapped as follows: - bit 0: baud rate set a or b - bit 1-2: BRG selection ("Select Extend bit") - - Note: If both ports on single DUART are not configured for the same - baud rate set, then unexpected results will occur. - - Note: On the Exar 88c681, if a standard clock of 3.6864 Mhz is used - and the "Select Extend bit" is 0 (disabled), then the default - MC68681 baud rate table is selected. - -getRegister -setRegister - - These follow standard conventions. - -getData -setData - - These are unused since the TX and RX data registers can be accessed - as regular registers. - -ulClock - - This is a pointer to a baud rate mapping table. If set to - mc68681_baud_rate_table, then the CSR/ACR/X bit mappings shown - in the 68681 and 88681 manuals are used. Otherwise, the board - specific baud rate mapping is used. - - NULL is not a valid value. - -ulIntVector - - This is the interrupt vector number associated with this chip. - diff --git a/c/src/libchip/serial/README.ns16550 b/c/src/libchip/serial/README.ns16550 deleted file mode 100644 index a0c31b5506..0000000000 --- a/c/src/libchip/serial/README.ns16550 +++ /dev/null @@ -1,82 +0,0 @@ -Status -====== - -There are no known problems with this driver. - -Configuration Table Use -======================= - -sDeviceName - - The name of this device. - -deviceType - - This field must be SERIAL_NS16550. - -pDeviceFns - - The device interface control table. This may be: - + ns16550_fns for interrupt driven IO - + ns16550_fns_polled for polled IO - -deviceProbe - - This is the address of the routine which probes to see if the device - is present. - -pDeviceFlow - - This field is ignored as hardware flow control is not currently supported. - -ulMargin - - This is currently unused. - -ulHysteresis - - This is currently unused. - -pDeviceParams - - This is set to the default settings. At this point, it is the default - baud rate cast as a (void *). - -ulCtrlPort1 - - This field is the base address of this port on the UART. - -ulCtrlPort2 - - This field is unused for the NS16550. - -ulDataPort - - This field is the base address of this port on the UART. - -getRegister -setRegister - - These follow standard conventions. - -getData -setData - - These are unused since the TX and RX data registers can be accessed - as regular registers. - -ulClock - - This is the clock constant which is divided by the desired baud - to get the value programmed into the part. The formula for this - for 9600 baud is: - - chip_divisor_value = ulClock / 9600. - - NOTE: When ulClock is 0, the correct value for a PC (115,200) is - used. - -ulIntVector - - This is the interrupt vector number associated with this chip. - diff --git a/c/src/libchip/serial/README.xr88681 b/c/src/libchip/serial/README.xr88681 deleted file mode 100644 index 89b661143f..0000000000 --- a/c/src/libchip/serial/README.xr88681 +++ /dev/null @@ -1,2 +0,0 @@ -The Exar XR88681 is an enhanced version of the Motorola MC68681 and is -supported by the mc68681 driver. diff --git a/c/src/libchip/serial/README.z85c30 b/c/src/libchip/serial/README.z85c30 deleted file mode 100644 index f6e0b8cb11..0000000000 --- a/c/src/libchip/serial/README.z85c30 +++ /dev/null @@ -1,74 +0,0 @@ -Configuration Table Use -======================= - -sDeviceName - - The name of this device. - -deviceType - - This field must be SERIAL_Z85C30. - -pDeviceFns - - The device interface control table. This may be: - + z85c30_fns for interrupt driven IO - + z85c30_fns_polled for polled IO - -deviceProbe - - This is the address of the routine which probes to see if the device - is present. - -pDeviceFlow - - This field is set to one of the following values: - + NULL for no hardware flow control - + z85c30_flow_RTSCTS for RTS/CTS based flow control - + z85c30_flow_DTRCTS for DTR/CTS based flow control - -ulMargin - - This is currently unused. - -ulHysteresis - - This is currently unused. - -pDeviceParams - - This is set to the default settings. - -ulCtrlPort1 - - This field is the address of the control register for this port. - -ulCtrlPort2 - - This field is the address of the control register for chip. - -ulDataPort - - This field is the address of the data register for this port. - -getRegister -setRegister - - These follow standard conventions. - -getData -setData - - These follow standard conventions. - -ulClock - - This is the clock speed of the baud rate clock. - NULL, then the CSR/ACR/X bit mappings shown in the 68681 and 88681 - manuals are used. Otherwise, the board specific baud rate mapping - is used. - -ulIntVector - - This is the interrupt vector number associated with this chip. - diff --git a/c/src/libchip/serial/STATUS b/c/src/libchip/serial/STATUS deleted file mode 100644 index 243b1a9de5..0000000000 --- a/c/src/libchip/serial/STATUS +++ /dev/null @@ -1,48 +0,0 @@ -General -======= - -+ Hardware flow control is not currently supported. Some of the chip - drivers (in particular the z8530) have support for hardware flow control - but this has not been tested in the libchip context. There will need - to be a way to totally disabled hardware flow control which is not - currently in this. - -+ "ulClockSpeed" configuration item field to become a pointer to a table - of chip specific information. For example, the z8530 should specify - clock speed and clock divisor setting. - -+ A termios structure should be included to specify the initial settings. - Right now all drivers default to 9600, 8N1. - -+ Need to switch to passing pointers rather than a minor number to - functions which are strictly internal to each chip driver. This - should be a performance win. - -+ Need a test which prompts you for termios settings and tests them. Until - this happens, testing for the variety of settings possible will be limited. - This test should be able to test any serial port while prompts come to the - console. - -MC68681 -======= - -+ Works interrupt and polled. - -+ Hardware flow control not included. - -NS16650 -======= - -+ ns16550_set-attributes function is untested. - -+ Hardware flow control included but is currently disabled in ISR. - -Z85C30 -====== - -+ Works polled and interrupt. - -+ Hardware flow control included but is currently disabled in ISR. - -+ Needs to support mode where more specific vectors are generated. - diff --git a/c/src/libchip/serial/mc68681.c b/c/src/libchip/serial/mc68681.c deleted file mode 100644 index f4ddbd6a50..0000000000 --- a/c/src/libchip/serial/mc68681.c +++ /dev/null @@ -1,776 +0,0 @@ -/* - * This file contains the termios TTY driver for the Motorola MC68681. - * - * This part is available from a number of secondary sources. - * In particular, we know about the following: - * - * + Exar 88c681 and 68c681 - * - * COPYRIGHT (c) 1989-1999. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include "mc68681_p.h" - -/* - * Flow control is only supported when using interrupts - */ - -const console_fns mc68681_fns = -{ - libchip_serial_default_probe, /* deviceProbe */ - mc68681_open, /* deviceFirstOpen */ - NULL, /* deviceLastClose */ - NULL, /* deviceRead */ - mc68681_write_support_int, /* deviceWrite */ - mc68681_initialize_interrupts, /* deviceInitialize */ - mc68681_write_polled, /* deviceWritePolled */ - mc68681_set_attributes, /* deviceSetAttributes */ - true /* deviceOutputUsesInterrupts */ -}; - -const console_fns mc68681_fns_polled = -{ - libchip_serial_default_probe, /* deviceProbe */ - mc68681_open, /* deviceFirstOpen */ - mc68681_close, /* deviceLastClose */ - mc68681_inbyte_nonblocking_polled, /* deviceRead */ - mc68681_write_support_polled, /* deviceWrite */ - mc68681_init, /* deviceInitialize */ - mc68681_write_polled, /* deviceWritePolled */ - mc68681_set_attributes, /* deviceSetAttributes */ - false, /* deviceOutputUsesInterrupts */ -}; - - -#if (CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE) - extern void set_vector( rtems_isr_entry, rtems_vector_number, int ); -#endif - -/* - * Console Device Driver Entry Points - */ - -/* - * mc68681_baud_rate - * - * This routine returns the proper ACR bit and baud rate field values - * based on the requested baud rate. The baud rate set to be used - * must be configured by the user. - */ - -MC68681_STATIC int mc68681_baud_rate( - int minor, - int baud, - unsigned int *baud_mask_p, - unsigned int *acr_bit_p, - unsigned int *command -); - -/* - * mc68681_set_attributes - * - * This function sets the DUART channel to reflect the requested termios - * port settings. - */ - -MC68681_STATIC int mc68681_set_attributes( - int minor, - const struct termios *t -) -{ - uint32_t pMC68681_port; - uint32_t pMC68681; - unsigned int mode1; - unsigned int mode2; - unsigned int baud_mask; - unsigned int acr_bit; - unsigned int cmd = 0; - setRegister_f setReg; - rtems_interrupt_level Irql; - - pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1; - pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2; - setReg = Console_Port_Tbl[minor]->setRegister; - - /* - * Set the baud rate - */ - - if (mc68681_baud_rate( minor, t->c_cflag, &baud_mask, &acr_bit, &cmd ) == -1) - return -1; - - baud_mask |= baud_mask << 4; - acr_bit <<= 7; - - /* - * Parity - */ - - mode1 = 0; - mode2 = 0; - - if (t->c_cflag & PARENB) { - if (t->c_cflag & PARODD) - mode1 |= 0x04; - /* else - mode1 |= 0x04; */ - } else { - mode1 |= 0x10; - } - - /* - * Character Size - */ - - if (t->c_cflag & CSIZE) { - switch (t->c_cflag & CSIZE) { - case CS5: break; - case CS6: mode1 |= 0x01; break; - case CS7: mode1 |= 0x02; break; - case CS8: mode1 |= 0x03; break; - } - } else { - mode1 |= 0x03; /* default to 9600,8,N,1 */ - } - - /* - * Stop Bits - */ - - if (t->c_cflag & CSTOPB) { - mode2 |= 0x0F; /* 2 stop bits */ - } else { - if ((t->c_cflag & CSIZE) == CS5) /* CS5 and 1 stop bits not supported */ - return -1; - mode2 |= 0x07; /* 1 stop bit */ - } - - /* - * Hardware Flow Control - */ - - if(t->c_cflag & CRTSCTS) { - mode1 |= 0x80; /* Enable Rx RTS Control */ - mode2 |= 0x10; /* Enable CTS Enable Tx */ - } - - - rtems_interrupt_disable(Irql); - (*setReg)( pMC68681, MC68681_AUX_CTRL_REG, acr_bit ); - (*setReg)( pMC68681_port, MC68681_CLOCK_SELECT, baud_mask ); - if ( cmd ) { - (*setReg)( pMC68681_port, MC68681_COMMAND, cmd ); /* RX */ - (*setReg)( pMC68681_port, MC68681_COMMAND, cmd | 0x20 ); /* TX */ - } - (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_MR_PTR ); - (*setReg)( pMC68681_port, MC68681_MODE, mode1 ); - (*setReg)( pMC68681_port, MC68681_MODE, mode2 ); - rtems_interrupt_enable(Irql); - return 0; -} - -/* - * mc68681_initialize_context - * - * This function sets the default values of the per port context structure. - */ - -MC68681_STATIC void mc68681_initialize_context( - int minor, - mc68681_context *pmc68681Context -) -{ - int port; - unsigned int pMC68681; - unsigned int pMC68681_port; - - pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1; - pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2; - - pmc68681Context->mate = -1; - - for (port=0 ; portulCtrlPort1 == pMC68681 && - Console_Port_Tbl[port]->ulCtrlPort2 != pMC68681_port ) { - pmc68681Context->mate = port; - pmc68681Context->imr = 0; - break; - } - } - -} - -/* - * mc68681_init - * - * This function initializes the DUART to a quiecsent state. - */ - -MC68681_STATIC void mc68681_init(int minor) -{ - uint32_t pMC68681_port; - mc68681_context *pmc68681Context; - setRegister_f setReg; - - pmc68681Context = (mc68681_context *) malloc(sizeof(mc68681_context)); - - Console_Port_Data[minor].pDeviceContext = (void *)pmc68681Context; - - mc68681_initialize_context( minor, pmc68681Context ); - - pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2; - setReg = Console_Port_Tbl[minor]->setRegister; - - /* - * Reset everything and leave this port disabled. - */ - - (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_RX ); - (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_TX ); - (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR ); - (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_BREAK ); - (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_STOP_BREAK ); - (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX ); - (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX ); - - - (*setReg)( pMC68681_port, MC68681_MODE_REG_1A, 0x00 ); - (*setReg)( pMC68681_port, MC68681_MODE_REG_2A, 0x02 ); - - /* - * Disable interrupts on RX and TX for this port - */ - - mc68681_enable_interrupts( minor, MC68681_IMR_DISABLE_ALL ); -} - -/* - * mc68681_open - * - * This function opens a port for communication. - * - * Default state is 9600 baud, 8 bits, No parity, and 1 stop bit. - */ - -MC68681_STATIC int mc68681_open( - int major, - int minor, - void *arg -) -{ - uint32_t pMC68681; - uint32_t pMC68681_port; - unsigned int baud; - unsigned int acr_bit; - unsigned int vector; - unsigned int command = 0; - rtems_interrupt_level Irql; - setRegister_f setReg; - int status; - - - pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1; - pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2; - setReg = Console_Port_Tbl[minor]->setRegister; - vector = Console_Port_Tbl[minor]->ulIntVector; - - /* XXX default baud rate should be from configuration table */ - - status = mc68681_baud_rate( minor, B9600, &baud, &acr_bit, &command ); - if (status < 0) rtems_fatal_error_occurred (RTEMS_NOT_DEFINED); - - /* - * Set the DUART channel to a default useable state - */ - - rtems_interrupt_disable(Irql); - (*setReg)( pMC68681, MC68681_AUX_CTRL_REG, acr_bit << 7 ); - (*setReg)( pMC68681_port, MC68681_CLOCK_SELECT, baud ); - if ( command ) { - (*setReg)( pMC68681_port, MC68681_COMMAND, command ); /* RX */ - (*setReg)( pMC68681_port, MC68681_COMMAND, command | 0x20 ); /* TX */ - } - (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_MR_PTR ); - (*setReg)( pMC68681_port, MC68681_MODE, 0x13 ); - (*setReg)( pMC68681_port, MC68681_MODE, 0x07 ); - rtems_interrupt_enable(Irql); - - (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_ENABLE_TX ); - (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_ENABLE_RX ); - - (*setReg)( pMC68681, MC68681_INTERRUPT_VECTOR_REG, vector ); - - return RTEMS_SUCCESSFUL; -} - -/* - * mc68681_close - * - * This function shuts down the requested port. - */ - -MC68681_STATIC int mc68681_close( - int major, - int minor, - void *arg -) -{ - uint32_t pMC68681_port; - setRegister_f setReg; - - pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2; - setReg = Console_Port_Tbl[minor]->setRegister; - - /* - * Disable interrupts from this channel and then disable it totally. - */ - (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX ); - (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX ); - - return(RTEMS_SUCCESSFUL); -} - -/* - * mc68681_write_polled - * - * This routine polls out the requested character. - */ - -MC68681_STATIC void mc68681_write_polled( - int minor, - char cChar -) -{ - uint32_t pMC68681_port; - unsigned char ucLineStatus; - int iTimeout; - getRegister_f getReg; - setRegister_f setReg; - - pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2; - getReg = Console_Port_Tbl[minor]->getRegister; - setReg = Console_Port_Tbl[minor]->setRegister; - - /* - * wait for transmitter holding register to be empty - */ - iTimeout = 1000; - ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS); - while ((ucLineStatus & (MC68681_TX_READY|MC68681_TX_EMPTY)) == 0) { - - if ((ucLineStatus & 0xF0)) - (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR ); - - /* - * Yield while we wait - */ - -#if 0 - if(_System_state_Is_up(_System_state_Get())) { - rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); - } -#endif - ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS); - if(!--iTimeout) { - break; - } - } - - /* - * transmit character - */ - - (*setReg)(pMC68681_port, MC68681_TX_BUFFER, cChar); -} - -/* - * mc68681_isr - * - * This is the single interrupt entry point which parcels interrupts - * out to the various ports. - */ - -MC68681_STATIC rtems_isr mc68681_isr( - rtems_vector_number vector -) -{ - int minor; - - for(minor=0 ; minorulIntVector == vector && - Console_Port_Tbl[minor]->deviceType == SERIAL_MC68681 ) { - mc68681_process(minor); - } - } -} - -/* - * mc68681_initialize_interrupts - * - * This routine initializes the console's receive and transmit - * ring buffers and loads the appropriate vectors to handle the interrupts. - */ - -MC68681_STATIC void mc68681_initialize_interrupts(int minor) -{ - mc68681_init(minor); - - Console_Port_Data[minor].bActive = FALSE; - -#if (CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE) - set_vector(mc68681_isr, Console_Port_Tbl[minor]->ulIntVector, 1); -#endif - - mc68681_enable_interrupts(minor,MC68681_IMR_ENABLE_ALL_EXCEPT_TX); -} - -/* - * mc68681_write_support_int - * - * Console Termios output entry point when using interrupt driven output. - */ - -MC68681_STATIC ssize_t mc68681_write_support_int( - int minor, - const char *buf, - size_t len -) -{ - uint32_t Irql; - uint32_t pMC68681_port; - setRegister_f setReg; - - pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2; - setReg = Console_Port_Tbl[minor]->setRegister; - - /* - * We are using interrupt driven output and termios only sends us - * one character at a time. - */ - - if ( !len ) - return 0; - - /* - * Put the character out and enable interrupts if necessary. - */ - - rtems_interrupt_disable(Irql); - if ( Console_Port_Data[minor].bActive == FALSE ) { - Console_Port_Data[minor].bActive = TRUE; - mc68681_enable_interrupts(minor, MC68681_IMR_ENABLE_ALL); - } - (*setReg)(pMC68681_port, MC68681_TX_BUFFER, *buf); - rtems_interrupt_enable(Irql); - - return 0; -} - -/* - * mc68681_write_support_polled - * - * Console Termios output entry point when using polled output. - * - */ - -MC68681_STATIC ssize_t mc68681_write_support_polled( - int minor, - const char *buf, - size_t len -) -{ - int nwrite = 0; - - /* - * poll each byte in the string out of the port. - */ - while (nwrite < len) { - /* - * transmit character - */ - mc68681_write_polled(minor, *buf++); - nwrite++; - } - - /* - * return the number of bytes written. - */ - return nwrite; -} - -/* - * mc68681_inbyte_nonblocking_polled - * - * Console Termios polling input entry point. - */ - -MC68681_STATIC int mc68681_inbyte_nonblocking_polled( - int minor -) -{ - uint32_t pMC68681_port; - unsigned char ucLineStatus; - unsigned char cChar; - getRegister_f getReg; - - pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2; - getReg = Console_Port_Tbl[minor]->getRegister; - - ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS); - if(ucLineStatus & MC68681_RX_READY) { - cChar = (*getReg)(pMC68681_port, MC68681_RX_BUFFER); - return (int)cChar; - } else { - return -1; - } -} - -/* - * mc68681_baud_rate - */ - -MC68681_STATIC int mc68681_baud_rate( - int minor, - int baud, - unsigned int *baud_mask_p, - unsigned int *acr_bit_p, - unsigned int *command -) -{ - unsigned int baud_mask; - unsigned int acr_bit; - int status; - int is_extended; - int baud_requested; - mc68681_baud_table_t *baud_tbl; - - baud_mask = 0; - acr_bit = 0; - status = 0; - - if (Console_Port_Tbl[minor]->ulDataPort & MC68681_DATA_BAUD_RATE_SET_2) - { - acr_bit = 1; - } - - is_extended = 0; - - switch (Console_Port_Tbl[minor]->ulDataPort & MC68681_XBRG_MASK) { - case MC68681_XBRG_IGNORED: - *command = 0x00; - break; - case MC68681_XBRG_ENABLED: - *command = 0x80; - is_extended = 1; - break; - case MC68681_XBRG_DISABLED: - *command = 0x90; - break; - } - - baud_requested = baud; - if (!baud_requested) - baud_requested = B9600; /* default to 9600 baud */ - - baud_requested = rtems_termios_baud_to_index( baud_requested ); - if (baud_requested == -1) - return -1; - - baud_tbl = (mc68681_baud_table_t *) - ((uintptr_t)Console_Port_Tbl[minor]->ulClock); - if (!baud_tbl) - rtems_fatal_error_occurred(RTEMS_INVALID_ADDRESS); - - if ( is_extended ) - baud_mask = (unsigned int)baud_tbl[ acr_bit + 2 ][ baud_requested ]; - else - baud_mask = baud_tbl[ acr_bit ][ baud_requested ]; - - if ( baud_mask == MC68681_BAUD_NOT_VALID ) - status = -1; - - /* - * upper nibble is receiver and lower nibble is transmitter - */ - - *baud_mask_p = (baud_mask << 4) | baud_mask; - *acr_bit_p = acr_bit; - return status; -} - -/* - * mc68681_process - * - * This routine is the per port console interrupt handler. - */ - -MC68681_STATIC void mc68681_process( - int minor -) -{ - uint32_t pMC68681; - uint32_t pMC68681_port; - volatile uint8_t ucLineStatus; - volatile uint8_t ucISRStatus; - char cChar; - getRegister_f getReg; - - pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1; - pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2; - getReg = Console_Port_Tbl[minor]->getRegister; - - /* Get ISR at the beginning of the IT routine */ - ucISRStatus = (*getReg)(pMC68681, MC68681_INTERRUPT_STATUS_REG); - - /* Get good ISR a or b channel */ - if (pMC68681 != pMC68681_port){ - ucISRStatus >>= 4; - } - - /* See if is usefull to call rtems_termios_dequeue */ - if(Console_Port_Data[minor].bActive == FALSE) { - ucISRStatus = ucISRStatus & ~MC68681_IR_TX_READY; - } - - /* - * Deal with any received characters - */ - while(true) { - ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS); - if(!(ucLineStatus & MC68681_RX_READY)) { - break; - } - /* - * If there is a RX error, then dump all the data. - */ - if ( ucLineStatus & MC68681_RX_ERRORS ) { - do { - cChar = (*getReg)(pMC68681_port, MC68681_RX_BUFFER); - ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS); - } while ( ucLineStatus & MC68681_RX_READY ); - continue; - } - cChar = (*getReg)(pMC68681_port, MC68681_RX_BUFFER); - rtems_termios_enqueue_raw_characters( - Console_Port_Data[minor].termios_data, - &cChar, - 1 - ); - } - - /* - * Deal with the transmitter - */ - - if (ucISRStatus & MC68681_IR_TX_READY) { - if (!rtems_termios_dequeue_characters( - Console_Port_Data[minor].termios_data, 1)) { - /* If no more char to send, disable TX interrupt */ - Console_Port_Data[minor].bActive = FALSE; - mc68681_enable_interrupts(minor, MC68681_IMR_ENABLE_ALL_EXCEPT_TX); - } - } -} - -/* - * mc68681_build_imr - * - * This function returns the value for the interrupt mask register for this - * DUART. Since this is a shared register, we must look at the other port - * on this chip to determine whether or not it is using interrupts. - */ - -MC68681_STATIC unsigned int mc68681_build_imr( - int minor, - int enable_flag -) -{ - int mate; - int is_a; - unsigned int mask; - unsigned int mate_mask; - unsigned int pMC68681; - unsigned int pMC68681_port; - mc68681_context *pmc68681Context; - mc68681_context *mateContext; - - pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1; - pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2; - pmc68681Context = (mc68681_context *) Console_Port_Data[minor].pDeviceContext; - mate = pmc68681Context->mate; - - mask = 0; - mate_mask = 0; - - is_a = (pMC68681 == pMC68681_port); - - /* - * If there is a mate for this port, get its IMR mask. - */ - - if ( mate != -1 ) { - mateContext = Console_Port_Data[mate].pDeviceContext; - - if (mateContext) - mate_mask = mateContext->imr; - } - - /* - * Calculate this port's IMR mask and save it in the context area. - */ - - if ( Console_Port_Tbl[minor]->pDeviceFns->deviceOutputUsesInterrupts ) - mask = enable_flag; - - pmc68681Context->imr = mask; - - /* - * Now return the full IMR value - */ - - if (is_a) - return (mate_mask << 4) | mask; - - return (mask << 4) | mate_mask; -} - -/* - * mc68681_enable_interrupts - * - * This function enables specific interrupt sources on the DUART. - */ - -MC68681_STATIC void mc68681_enable_interrupts( - int minor, - int imr_mask -) -{ - uint32_t pMC68681; - setRegister_f setReg; - - pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1; - setReg = Console_Port_Tbl[minor]->setRegister; - - /* - * Enable interrupts on RX and TX -- not break - */ - - (*setReg)( - pMC68681, - MC68681_INTERRUPT_MASK_REG, - mc68681_build_imr(minor, imr_mask) - ); -} diff --git a/c/src/libchip/serial/mc68681_baud.c b/c/src/libchip/serial/mc68681_baud.c deleted file mode 100644 index 0f8e87c2c2..0000000000 --- a/c/src/libchip/serial/mc68681_baud.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * MC68681 Default Baud Rate Table - */ - -#include -#include -#include - -/* major index of 0 : ACR[7] = 0, X = 0 -- 68c681 only has these */ -/* major index of 1 : ACR[7] = 1, X = 0 -- 68c681 only has these */ -/* major index of 2 : ACR[7] = 0, X = 1 */ -/* major index of 3 : ACR[7] = 1, X = 1 */ - -/* mc68681_baud_table_t mc68681_baud_rate_table[4] = { */ -mc68681_baud_t mc68681_baud_rate_table[4][RTEMS_TERMIOS_NUMBER_BAUD_RATES] = { - { /* ACR[7] = 0, X = 0 */ - MC68681_BAUD_NOT_VALID, /* B0 */ - 0x00, /* B50 */ - MC68681_BAUD_NOT_VALID, /* B75 */ - 0x01, /* B110 */ - 0x02, /* B134 */ - MC68681_BAUD_NOT_VALID, /* B150 */ - 0x03, /* B200 */ - 0x04, /* B300 */ - 0x05, /* B600 */ - 0x06, /* B1200 */ - MC68681_BAUD_NOT_VALID, /* B1800 */ - 0x08, /* B2400 */ - 0x09, /* B4800 */ - 0x0B, /* B9600 */ - MC68681_BAUD_NOT_VALID, /* B19200 */ - 0x0C, /* B38400 */ - MC68681_BAUD_NOT_VALID, /* B7200 */ - MC68681_BAUD_NOT_VALID, /* B14400 */ - MC68681_BAUD_NOT_VALID, /* B28800 */ - MC68681_BAUD_NOT_VALID, /* B57600 */ - MC68681_BAUD_NOT_VALID, /* B76800 */ - MC68681_BAUD_NOT_VALID, /* B115200 */ - MC68681_BAUD_NOT_VALID, /* B230400 */ - MC68681_BAUD_NOT_VALID, /* B460800 */ - MC68681_BAUD_NOT_VALID /* B921600 */ - }, - { /* ACR[7] = 1, X = 0 */ - MC68681_BAUD_NOT_VALID, /* B0 */ - MC68681_BAUD_NOT_VALID, /* B50 */ - 0x00, /* B75 */ - 0x01, /* B110 */ - 0x02, /* B134 */ - 0x03, /* B150 */ - MC68681_BAUD_NOT_VALID, /* B200 */ - 0x04, /* B300 */ - 0x05, /* B600 */ - 0x06, /* B1200 */ - 0x0A, /* B1800 */ - 0x08, /* B2400 */ - 0x09, /* B4800 */ - 0x0B, /* B9600 */ - 0x0C, /* B19200 */ - MC68681_BAUD_NOT_VALID, /* B38400 */ - MC68681_BAUD_NOT_VALID, /* B7200 */ - MC68681_BAUD_NOT_VALID, /* B14400 */ - MC68681_BAUD_NOT_VALID, /* B28800 */ - MC68681_BAUD_NOT_VALID, /* B57600 */ - MC68681_BAUD_NOT_VALID, /* B76800 */ - MC68681_BAUD_NOT_VALID, /* B115200 */ - MC68681_BAUD_NOT_VALID, /* B230400 */ - MC68681_BAUD_NOT_VALID, /* B460800 */ - MC68681_BAUD_NOT_VALID /* B921600 */ - }, - { /* ACR[7] = 0, X = 1 */ - MC68681_BAUD_NOT_VALID, /* B0 */ - MC68681_BAUD_NOT_VALID, /* B50 */ - 0x00, /* B75 */ - 0x01, /* B110 */ - 0x02, /* B134 */ - 0x03, /* B150 */ - MC68681_BAUD_NOT_VALID, /* B200 */ - MC68681_BAUD_NOT_VALID, /* B300 */ - MC68681_BAUD_NOT_VALID, /* B600 */ - MC68681_BAUD_NOT_VALID, /* B1200 */ - 0x0A, /* B1800 */ - MC68681_BAUD_NOT_VALID, /* B2400 */ - 0x08, /* B4800 */ - 0x0B, /* B9600 */ - 0x0C, /* B19200 */ - MC68681_BAUD_NOT_VALID, /* B38400 */ - MC68681_BAUD_NOT_VALID, /* B7200 */ - MC68681_BAUD_NOT_VALID, /* B14400 */ - MC68681_BAUD_NOT_VALID, /* B28800 */ - 0x07, /* B57600 */ - MC68681_BAUD_NOT_VALID, /* B76800 */ - 0x08, /* B115200 */ - MC68681_BAUD_NOT_VALID, /* B230400 */ - MC68681_BAUD_NOT_VALID, /* B460800 */ - MC68681_BAUD_NOT_VALID /* B921600 */ - }, - { /* ACR[7] = 1, X = 1 */ - MC68681_BAUD_NOT_VALID, /* B0 */ - 0x00, /* B50 */ - MC68681_BAUD_NOT_VALID, /* B75 */ - 0x01, /* B110 */ - 0x02, /* B134 */ - MC68681_BAUD_NOT_VALID, /* B150 */ - 0x03, /* B200 */ - MC68681_BAUD_NOT_VALID, /* B300 */ - MC68681_BAUD_NOT_VALID, /* B600 */ - MC68681_BAUD_NOT_VALID, /* B1200 */ - MC68681_BAUD_NOT_VALID, /* B1800 */ - MC68681_BAUD_NOT_VALID, /* B2400 */ - 0x09, /* B4800 */ - 0x0B, /* B9600 */ - MC68681_BAUD_NOT_VALID, /* B19200 */ - 0x0C, /* B38400 */ - MC68681_BAUD_NOT_VALID, /* B7200 */ - MC68681_BAUD_NOT_VALID, /* B14400 */ - MC68681_BAUD_NOT_VALID, /* B28800 */ - 0x07, /* B57600 */ - MC68681_BAUD_NOT_VALID, /* B76800 */ - 0x08, /* B115200 */ - MC68681_BAUD_NOT_VALID, /* B230400 */ - MC68681_BAUD_NOT_VALID, /* B460800 */ - MC68681_BAUD_NOT_VALID /* B921600 */ - }, -}; diff --git a/c/src/libchip/serial/mc68681_p.h b/c/src/libchip/serial/mc68681_p.h deleted file mode 100644 index 4623276303..0000000000 --- a/c/src/libchip/serial/mc68681_p.h +++ /dev/null @@ -1,323 +0,0 @@ -/* - * - * COPYRIGHT (c) 1989-1999. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#ifndef _MC68681_P_H_ -#define _MC68681_P_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Define MC68681_STATIC to nothing while debugging so the entry points - * will show up in the symbol table. - */ - -#define MC68681_STATIC - -/* #define MC68681_STATIC static */ - -/* - * mc68681 register offsets Read/Write Addresses - */ - -#define MC68681_MODE_REG_1A 0 /* MR1A-MR Prior to Read */ -#define MC68681_MODE_REG_2A 0 /* MR2A-MR After Read */ - -#define MC68681_COUNT_MODE_CURRENT_MSB 6 /* CTU */ -#define MC68681_COUNTER_TIMER_UPPER_REG 6 /* CTU */ -#define MC68681_COUNT_MODE_CURRENT_LSB 7 /* CTL */ -#define MC68681_COUNTER_TIMER_LOWER_REG 7 /* CTL */ -#define MC68681_INTERRUPT_VECTOR_REG 12 /* IVR */ - -#define MC68681_MODE_REG_1B 8 /* MR1B-MR Prior to Read */ -#define MC68681_MODE_REG_2B 8 /* MR2BA-MR After Read */ - -/* - * mc68681 register offsets Read Only Addresses - */ - -#define MC68681_STATUS_REG_A 1 /* SRA */ -#define MC68681_MASK_ISR_REG 2 /* MISR */ -#define MC68681_RECEIVE_BUFFER_A 3 /* RHRA */ -#define MC68681_INPUT_PORT_CHANGE_REG 4 /* IPCR */ -#define MC68681_INTERRUPT_STATUS_REG 5 /* ISR */ -#define MC68681_STATUS_REG_B 9 /* SRB */ -#define MC68681_RECEIVE_BUFFER_B 11 /* RHRB */ -#define MC68681_INPUT_PORT 13 /* IP */ -#define MC68681_START_COUNT_CMD 14 /* SCC */ -#define MC68681_STOP_COUNT_CMD 15 /* STC */ - -/* - * mc68681 register offsets Write Only Addresses - */ - -#define MC68681_CLOCK_SELECT_REG_A 1 /* CSRA */ -#define MC68681_COMMAND_REG_A 2 /* CRA */ -#define MC68681_TRANSMIT_BUFFER_A 3 /* THRA */ -#define MC68681_AUX_CTRL_REG 4 /* ACR */ -#define MC68681_INTERRUPT_MASK_REG 5 /* IMR */ -#define MC68681_CLOCK_SELECT_REG_B 9 /* CSRB */ -#define MC68681_COMMAND_REG_B 10 /* CRB */ -#define MC68681_TRANSMIT_BUFFER_B 11 /* THRB */ -#define MC68681_OUTPUT_PORT_CONFIG_REG 13 /* OPCR */ -#define MC68681_OUTPUT_PORT_SET_REG 14 /* SOPBC */ -#define MC68681_OUTPUT_PORT_RESET_BITS 15 /* COPBC */ - -/* - * DUART Command Register Definitions: - * - * MC68681_COMMAND_REG_A,MC68681_COMMAND_REG_B - */ - -#define MC68681_MODE_REG_ENABLE_RX 0x01 -#define MC68681_MODE_REG_DISABLE_RX 0x02 -#define MC68681_MODE_REG_ENABLE_TX 0x04 -#define MC68681_MODE_REG_DISABLE_TX 0x08 -#define MC68681_MODE_REG_RESET_MR_PTR 0x10 -#define MC68681_MODE_REG_RESET_RX 0x20 -#define MC68681_MODE_REG_RESET_TX 0x30 -#define MC68681_MODE_REG_RESET_ERROR 0x40 -#define MC68681_MODE_REG_RESET_BREAK 0x50 -#define MC68681_MODE_REG_START_BREAK 0x60 -#define MC68681_MODE_REG_STOP_BREAK 0x70 -#define MC68681_MODE_REG_SET_RX_BRG 0x80 -#define MC68681_MODE_REG_CLEAR_RX_BRG 0x90 -#define MC68681_MODE_REG_SET_TX_BRG 0xa0 -#define MC68681_MODE_REG_CLEAR_TX_BRG 0xb0 -#define MC68681_MODE_REG_SET_STANDBY 0xc0 -#define MC68681_MODE_REG_SET_ACTIVE 0xd0 - -/* - * Mode Register Definitions - * - * MC68681_MODE_REG_1A - * MC68681_MODE_REG_1B - */ - -#define MC68681_5BIT_CHARS 0x00 -#define MC68681_6BIT_CHARS 0x01 -#define MC68681_7BIT_CHARS 0x02 -#define MC68681_8BIT_CHARS 0x03 - -#define MC68681_ODD_PARITY 0x00 -#define MC68681_EVEN_PARITY 0x04 - -#define MC68681_WITH_PARITY 0x00 -#define MC68681_FORCE_PARITY 0x08 -#define MC68681_NO_PARITY 0x10 -#define MC68681_MULTI_DROP 0x18 - -#define MC68681_ERR_MODE_CHAR 0x00 -#define MC68681_ERR_MODE_BLOCK 0x20 - -#define MC68681_RX_INTR_RX_READY 0x00 -#define MC68681_RX_INTR_FFULL 0x40 - -#define MC68681_NO_RX_RTS_CTL 0x00 -#define MC68681_RX_RTS_CTRL 0x80 - -/* - * Mode Register Definitions - * - * MC68681_MODE_REG_2A - * MC68681_MODE_REG_2B - */ - -#define MC68681_STOP_BIT_LENGTH__563 0x00 -#define MC68681_STOP_BIT_LENGTH__625 0x01 -#define MC68681_STOP_BIT_LENGTH__688 0x02 -#define MC68681_STOP_BIT_LENGTH__75 0x03 -#define MC68681_STOP_BIT_LENGTH__813 0x04 -#define MC68681_STOP_BIT_LENGTH__875 0x05 -#define MC68681_STOP_BIT_LENGTH__938 0x06 -#define MC68681_STOP_BIT_LENGTH_1 0x07 -#define MC68681_STOP_BIT_LENGTH_1_563 0x08 -#define MC68681_STOP_BIT_LENGTH_1_625 0x09 -#define MC68681_STOP_BIT_LENGTH_1_688 0x0a -#define MC68681_STOP_BIT_LENGTH_1_75 0x0b -#define MC68681_STOP_BIT_LENGTH_1_813 0x0c -#define MC68681_STOP_BIT_LENGTH_1_875 0x0d -#define MC68681_STOP_BIT_LENGTH_1_938 0x0e -#define MC68681_STOP_BIT_LENGTH_2 0x0f - -#define MC68681_CTS_ENABLE_TX 0x10 -#define MC68681_TX_RTS_CTRL 0x20 - -#define MC68681_CHANNEL_MODE_NORMAL 0x00 -#define MC68681_CHANNEL_MODE_ECHO 0x40 -#define MC68681_CHANNEL_MODE_LOCAL_LOOP 0x80 -#define MC68681_CHANNEL_MODE_REMOTE_LOOP 0xc0 - -/* - * Status Register Definitions - * - * MC68681_STATUS_REG_A, MC68681_STATUS_REG_B - */ - -#define MC68681_RX_READY 0x01 -#define MC68681_FFULL 0x02 -#define MC68681_TX_READY 0x04 -#define MC68681_TX_EMPTY 0x08 -#define MC68681_OVERRUN_ERROR 0x10 -#define MC68681_PARITY_ERROR 0x20 -#define MC68681_FRAMING_ERROR 0x40 -#define MC68681_RECEIVED_BREAK 0x80 - -#define MC68681_RX_ERRORS \ - (MC68681_OVERRUN_ERROR|MC68681_PARITY_ERROR| \ - MC68681_FRAMING_ERROR|MC68681_RECEIVED_BREAK) - -/* - * Interupt Status Register Definitions. - * - * MC68681_INTERRUPT_STATUS_REG - */ - -/* - * Interupt Mask Register Definitions - * - * MC68681_INTERRUPT_MASK_REG - */ - -/* These are passed to mc68681_build_imr */ -#define MC68681_IR_TX_READY 0x01 -#define MC68681_IR_RX_READY 0x02 -#define MC68681_IR_BREAK 0x04 -#define MC68681_IMR_ENABLE_ALL 0x07 -#define MC68681_IMR_DISABLE_ALL 0x00 -#define MC68681_IMR_ENABLE_ALL_EXCEPT_TX 0x06 - -#define MC68681_IR_TX_READY_A 0x01 -#define MC68681_IR_RX_READY_A 0x02 -#define MC68681_IR_BREAK_A 0x04 -#define MC68681_IR_COUNTER_READY 0x08 -#define MC68681_IR_TX_READY_B 0x10 -#define MC68681_IR_RX_READY_B 0x20 -#define MC68681_IR_BREAK_B 0x40 -#define MC68681_IR_INPUT_PORT_CHANGE 0x80 - -/* - * Status Register Definitions. - * - * MC68681_STATUS_REG_A,MC68681_STATUS_REG_B - */ - -#define MC68681_STATUS_RXRDY 0x01 -#define MC68681_STATUS_FFULL 0x02 -#define MC68681_STATUS_TXRDY 0x04 -#define MC68681_STATUS_TXEMT 0x08 -#define MC68681_STATUS_OVERRUN_ERROR 0x10 -#define MC68681_STATUS_PARITY_ERROR 0x20 -#define MC68681_STATUS_FRAMING_ERROR 0x40 -#define MC68681_STATUS_RECEIVED_BREAK 0x80 - -/* - * Definitions for the Interrupt Vector Register: - * - * MC68681_INTERRUPT_VECTOR_REG - */ - -#define MC68681_INTERRUPT_VECTOR_INIT 0x0f - -/* - * Definitions for the Auxiliary Control Register - * - * MC68681_AUX_CTRL_REG - */ - -#define MC68681_AUX_BRG_SET1 0x00 -#define MC68681_AUX_BRG_SET2 0x80 - -/* - * Per chip context control - */ - -typedef struct _mc68681_context -{ - int mate; - unsigned char imr; -} mc68681_context; - -/* - * Driver functions - */ -MC68681_STATIC void mc68681_initialize_context( - int minor, - mc68681_context *pmc68681Context -); - -MC68681_STATIC bool mc68681_probe(int minor); - -MC68681_STATIC int mc68681_set_attributes( - int minor, - const struct termios *t -); - -MC68681_STATIC void mc68681_init(int minor); - -MC68681_STATIC int mc68681_open( - int major, - int minor, - void * arg -); - -MC68681_STATIC int mc68681_close( - int major, - int minor, - void * arg -); - -MC68681_STATIC void mc68681_write_polled( - int minor, - char cChar -); - -MC68681_STATIC void mc68681_initialize_interrupts(int minor); - -MC68681_STATIC ssize_t mc68681_write_support_int( - int minor, - const char *buf, - size_t len -); - -MC68681_STATIC ssize_t mc68681_write_support_polled( - int minor, - const char *buf, - size_t len - ); - -MC68681_STATIC int mc68681_inbyte_nonblocking_polled( - int minor -); - -MC68681_STATIC unsigned int mc68681_build_imr( - int minor, - int enable_flag -); - -MC68681_STATIC void mc68681_process( - int minor -); - -MC68681_STATIC void mc68681_enable_interrupts( - int minor, - int imr_mask -); - -MC68681_STATIC rtems_isr mc68681_isr( - rtems_vector_number vector -); - -#ifdef __cplusplus -} -#endif - -#endif /* _MC68681_P_H_ */ diff --git a/c/src/libchip/serial/mc68681_reg.c b/c/src/libchip/serial/mc68681_reg.c deleted file mode 100644 index fb92b8fcd3..0000000000 --- a/c/src/libchip/serial/mc68681_reg.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file contains a typical set of register access routines which may be - * used with the mc68681 chip if accesses to the chip are as follows: - * - * + registers are accessed as bytes - * + registers are only byte-aligned (no address gaps) - * - * COPYRIGHT (c) 1989-1997. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -#include -#include - -#ifndef _MC68681_MULTIPLIER -#define _MC68681_MULTIPLIER 1 -#define _MC68681_NAME(_X) _X -#define _MC68681_TYPE uint8_t -#endif - -#define CALCULATE_REGISTER_ADDRESS( _base, _reg ) \ - (_MC68681_TYPE *)((_base) + ((_reg) * _MC68681_MULTIPLIER )) - -/* - * MC68681 Get Register Routine - */ - -uint8_t _MC68681_NAME(mc68681_get_register)( - uintptr_t ulCtrlPort, - uint8_t ucRegNum -) -{ - _MC68681_TYPE *port; - - port = CALCULATE_REGISTER_ADDRESS( ulCtrlPort, ucRegNum ); - - return *port; -} - -/* - * MC68681 Set Register Routine - */ - -void _MC68681_NAME(mc68681_set_register)( - uintptr_t ulCtrlPort, - uint8_t ucRegNum, - uint8_t ucData -) -{ - _MC68681_TYPE *port; - - port = CALCULATE_REGISTER_ADDRESS( ulCtrlPort, ucRegNum ); - - *port = ucData; -} diff --git a/c/src/libchip/serial/mc68681_reg2.c b/c/src/libchip/serial/mc68681_reg2.c deleted file mode 100644 index 0e0121eb40..0000000000 --- a/c/src/libchip/serial/mc68681_reg2.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This file contains a typical set of register access routines which may be - * used with the mc68681 chip if accesses to the chip are as follows: - * - * + registers are accessed as bytes - * + registers are on 16-bit boundaries - * - * COPYRIGHT (c) 1989-1997. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#define _MC68681_MULTIPLIER 2 -#define _MC68681_NAME(_X) _X##_2 -#define _MC68681_TYPE uint8_t - -#include "mc68681_reg.c" diff --git a/c/src/libchip/serial/mc68681_reg4.c b/c/src/libchip/serial/mc68681_reg4.c deleted file mode 100644 index e9dd94ce4b..0000000000 --- a/c/src/libchip/serial/mc68681_reg4.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This file contains a typical set of register access routines which may be - * used with the mc68681 chip if accesses to the chip are as follows: - * - * + registers are accessed as bytes - * + registers are on 32-bit boundaries - * - * COPYRIGHT (c) 1989-1997. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#define _MC68681_MULTIPLIER 4 -#define _MC68681_NAME(_X) _X##_4 -#define _MC68681_TYPE uint8_t - -#include "mc68681_reg.c" diff --git a/c/src/libchip/serial/mc68681_reg8.c b/c/src/libchip/serial/mc68681_reg8.c deleted file mode 100644 index 402c2ffe1b..0000000000 --- a/c/src/libchip/serial/mc68681_reg8.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This file contains a typical set of register access routines which may be - * used with the mc68681 chip if accesses to the chip are as follows: - * - * + registers are accessed as bytes - * + registers are on 64-bit boundaries - * - * COPYRIGHT (c) 1989-1997. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#define _MC68681_MULTIPLIER 8 -#define _MC68681_NAME(_X) _X##_8 -#define _MC68681_TYPE uint8_t - -#include "mc68681_reg.c" diff --git a/c/src/libchip/serial/ns16550-context.c b/c/src/libchip/serial/ns16550-context.c deleted file mode 100644 index b42be96a26..0000000000 --- a/c/src/libchip/serial/ns16550-context.c +++ /dev/null @@ -1,814 +0,0 @@ -/** - * @file - * - * This file contains the TTY driver for the National Semiconductor NS16550. - * - * This part is widely cloned and second sourced. It is found in a number - * of "Super IO" controllers. - * - * This driver uses the termios pseudo driver. - */ - -/* - * COPYRIGHT (c) 1998 by Radstone Technology - * - * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY - * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK - * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. - * - * You are hereby granted permission to use, copy, modify, and distribute - * this file, provided that this notice, plus the above copyright notice - * and disclaimer, appears in all copies. Radstone Technology will provide - * no support for this code. - * - * COPYRIGHT (c) 1989-2012. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -#include - -#include - -#include -#include - -#if defined(BSP_FEATURE_IRQ_EXTENSION) - #include -#elif defined(BSP_FEATURE_IRQ_LEGACY) - #include -#elif defined(__PPC__) || defined(__i386__) - #include - #define BSP_FEATURE_IRQ_LEGACY - #ifdef BSP_SHARED_HANDLER_SUPPORT - #define BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT - #endif -#endif - -static uint32_t NS16550_GetBaudDivisor(ns16550_context *ctx, uint32_t baud) -{ - uint32_t clock = ctx->clock; - uint32_t baudDivisor = (clock != 0 ? clock : 115200) / (baud * 16); - - if (ctx->has_fractional_divider_register) { - uint32_t fractionalDivider = 0x10; - uint32_t err = baud; - uint32_t mulVal; - uint32_t divAddVal; - - clock /= 16 * baudDivisor; - for (mulVal = 1; mulVal < 16; ++mulVal) { - for (divAddVal = 0; divAddVal < mulVal; ++divAddVal) { - uint32_t actual = (mulVal * clock) / (mulVal + divAddVal); - uint32_t newErr = actual > baud ? actual - baud : baud - actual; - - if (newErr < err) { - err = newErr; - fractionalDivider = (mulVal << 4) | divAddVal; - } - } - } - - (*ctx->set_reg)( - ctx->port, - NS16550_FRACTIONAL_DIVIDER, - fractionalDivider - ); - } - - return baudDivisor; -} - -/* - * ns16550_enable_interrupts - * - * This routine initializes the port to have the specified interrupts masked. - */ -static void ns16550_enable_interrupts( - ns16550_context *ctx, - int mask -) -{ - (*ctx->set_reg)(ctx->port, NS16550_INTERRUPT_ENABLE, mask); -} - -static void ns16550_clear_and_set_interrupts( - ns16550_context *ctx, - uint8_t clear, - uint8_t set -) -{ - rtems_interrupt_lock_context lock_context; - ns16550_get_reg get_reg = ctx->get_reg; - ns16550_set_reg set_reg = ctx->set_reg; - uintptr_t port = ctx->port; - uint8_t val; - - rtems_termios_device_lock_acquire(&ctx->base, &lock_context); - val = (*get_reg)(port, NS16550_INTERRUPT_ENABLE); - val &= ~clear; - val |= set; - (*set_reg)(port, NS16550_INTERRUPT_ENABLE, val); - rtems_termios_device_lock_release(&ctx->base, &lock_context); -} - -/* - * ns16550_probe - */ - -bool ns16550_probe(rtems_termios_device_context *base) -{ - ns16550_context *ctx = (ns16550_context *) base; - uintptr_t pNS16550; - uint8_t ucDataByte; - uint32_t ulBaudDivisor; - ns16550_set_reg setReg; - ns16550_get_reg getReg; - - ctx->modem_control = SP_MODEM_IRQ; - - pNS16550 = ctx->port; - setReg = ctx->set_reg; - getReg = ctx->get_reg; - - /* Clear the divisor latch, clear all interrupt enables, - * and reset and - * disable the FIFO's. - */ - - (*setReg)(pNS16550, NS16550_LINE_CONTROL, 0x0); - ns16550_enable_interrupts(ctx, NS16550_DISABLE_ALL_INTR ); - - /* Set the divisor latch and set the baud rate. */ - - ulBaudDivisor = NS16550_GetBaudDivisor(ctx, ctx->initial_baud); - ctx->baud_divisor = ulBaudDivisor; - ucDataByte = SP_LINE_DLAB; - (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte); - - /* XXX */ - (*setReg)(pNS16550,NS16550_TRANSMIT_BUFFER,(uint8_t)(ulBaudDivisor & 0xffU)); - (*setReg)( - pNS16550,NS16550_INTERRUPT_ENABLE, - (uint8_t)(( ulBaudDivisor >> 8 ) & 0xffU ) - ); - - /* Clear the divisor latch and set the character size to eight bits */ - /* with one stop bit and no parity checking. */ - ucDataByte = EIGHT_BITS; - ctx->line_control = ucDataByte; - (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte); - - /* Enable and reset transmit and receive FIFOs. TJA */ - ucDataByte = SP_FIFO_ENABLE; - (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte); - - ucDataByte = SP_FIFO_ENABLE | SP_FIFO_RXRST | SP_FIFO_TXRST; - (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte); - - ns16550_enable_interrupts(ctx, NS16550_DISABLE_ALL_INTR); - - /* Set data terminal ready. */ - /* And open interrupt tristate line */ - (*setReg)(pNS16550, NS16550_MODEM_CONTROL,ctx->modem_control); - - (*getReg)(pNS16550, NS16550_LINE_STATUS ); - (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER ); - - return true; -} - -static size_t ns16550_write_to_fifo( - const ns16550_context *ctx, - const char *buf, - size_t len -) -{ - uintptr_t port = ctx->port; - ns16550_set_reg set = ctx->set_reg; - size_t out = len > SP_FIFO_SIZE ? SP_FIFO_SIZE : len; - size_t i; - - for (i = 0; i < out; ++i) { - (*set)(port, NS16550_TRANSMIT_BUFFER, buf[i]); - } - - return out; -} - -/** - * @brief Process interrupt. - */ -static void ns16550_isr(void *arg) -{ - rtems_termios_tty *tty = arg; - ns16550_context *ctx = rtems_termios_get_device_context(tty); - uintptr_t port = ctx->port; - ns16550_get_reg get = ctx->get_reg; - int i = 0; - char buf [SP_FIFO_SIZE]; - - /* Iterate until no more interrupts are pending */ - do { - /* Fetch received characters */ - for (i = 0; i < SP_FIFO_SIZE; ++i) { - if ((get( port, NS16550_LINE_STATUS) & SP_LSR_RDY) != 0) { - buf [i] = (char) get(port, NS16550_RECEIVE_BUFFER); - } else { - break; - } - } - - /* Enqueue fetched characters */ - rtems_termios_enqueue_raw_characters(tty, buf, i); - - /* Do transmit */ - if (ctx->out_total > 0 - && (get(port, NS16550_LINE_STATUS) & SP_LSR_THOLD) != 0) { - size_t current = ctx->out_current; - - ctx->out_buf += current; - ctx->out_remaining -= current; - - if (ctx->out_remaining > 0) { - ctx->out_current = - ns16550_write_to_fifo(ctx, ctx->out_buf, ctx->out_remaining); - } else { - rtems_termios_dequeue_characters(tty, ctx->out_total); - } - } - } while ((get( port, NS16550_INTERRUPT_ID) & SP_IID_0) == 0); -} - -static void ns16550_isr_task(void *arg) -{ - rtems_termios_tty *tty = arg; - ns16550_context *ctx = rtems_termios_get_device_context(tty); - uint8_t status = (*ctx->get_reg)(ctx->port, NS16550_LINE_STATUS); - - if ((status & SP_LSR_RDY) != 0) { - ns16550_clear_and_set_interrupts(ctx, SP_INT_RX_ENABLE, 0); - rtems_termios_rxirq_occured(tty); - } - - if (ctx->out_total > 0 && (status & SP_LSR_THOLD) != 0) { - size_t current = ctx->out_current; - - ctx->out_buf += current; - ctx->out_remaining -= current; - - if (ctx->out_remaining > 0) { - ctx->out_current = - ns16550_write_to_fifo(ctx, ctx->out_buf, ctx->out_remaining); - } else { - size_t done = ctx->out_total; - - ctx->out_total = 0; - ns16550_clear_and_set_interrupts(ctx, SP_INT_TX_ENABLE, 0); - rtems_termios_dequeue_characters(tty, done); - } - } -} - -static int ns16550_read_task(rtems_termios_device_context *base) -{ - ns16550_context *ctx = (ns16550_context *) base; - uintptr_t port = ctx->port; - ns16550_get_reg get = ctx->get_reg; - char buf[SP_FIFO_SIZE]; - int i; - - for (i = 0; i < SP_FIFO_SIZE; ++i) { - if ((get(port, NS16550_LINE_STATUS) & SP_LSR_RDY) != 0) { - buf[i] = (char) get(port, NS16550_RECEIVE_BUFFER); - } else { - break; - } - } - - rtems_termios_enqueue_raw_characters(ctx->tty, buf, i); - ns16550_clear_and_set_interrupts(ctx, 0, SP_INT_RX_ENABLE); - - return -1; -} - -/* - * ns16550_initialize_interrupts - * - * This routine initializes the port to operate in interrupt driver mode. - */ -static void ns16550_initialize_interrupts( - struct rtems_termios_tty *tty, - ns16550_context *ctx, - void (*isr)(void *) -) -{ - #ifdef BSP_FEATURE_IRQ_EXTENSION - { - rtems_status_code sc = RTEMS_SUCCESSFUL; - sc = rtems_interrupt_handler_install( - ctx->irq, - "NS16550", - RTEMS_INTERRUPT_SHARED, - isr, - tty - ); - if (sc != RTEMS_SUCCESSFUL) { - /* FIXME */ - printk( "%s: Error: Install interrupt handler\n", __func__); - rtems_fatal_error_occurred( 0xdeadbeef); - } - } - #elif defined(BSP_FEATURE_IRQ_LEGACY) - { - int rv = 0; - #ifdef BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT - rtems_irq_connect_data cd = { - ctx->irq, - isr, - tty, - NULL, - NULL, - NULL, - NULL - }; - rv = BSP_install_rtems_shared_irq_handler( &cd); - #else - rtems_irq_connect_data cd = { - ctx->irq, - isr, - tty, - NULL, - NULL, - NULL - }; - rv = BSP_install_rtems_irq_handler( &cd); - #endif - if (rv == 0) { - /* FIXME */ - printk( "%s: Error: Install interrupt handler\n", __func__); - rtems_fatal_error_occurred( 0xdeadbeef); - } - } - #endif -} - -/* - * ns16550_open - */ - -static bool ns16550_open( - struct rtems_termios_tty *tty, - rtems_termios_device_context *base, - struct termios *term, - rtems_libio_open_close_args_t *args -) -{ - ns16550_context *ctx = (ns16550_context *) base; - - ctx->tty = tty; - - /* Set initial baud */ - rtems_termios_set_initial_baud(tty, ctx->initial_baud); - - if (tty->handler.mode == TERMIOS_IRQ_DRIVEN) { - ns16550_initialize_interrupts(tty, ctx, ns16550_isr); - ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR_EXCEPT_TX); - } else if (tty->handler.mode == TERMIOS_TASK_DRIVEN) { - ns16550_initialize_interrupts(tty, ctx, ns16550_isr_task); - ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR_EXCEPT_TX); - } - - return true; -} - -static void ns16550_cleanup_interrupts( - struct rtems_termios_tty *tty, - ns16550_context *ctx, - void (*isr)(void *) -) -{ - #if defined(BSP_FEATURE_IRQ_EXTENSION) - rtems_status_code sc = RTEMS_SUCCESSFUL; - sc = rtems_interrupt_handler_remove( - ctx->irq, - isr, - tty - ); - if (sc != RTEMS_SUCCESSFUL) { - /* FIXME */ - printk("%s: Error: Remove interrupt handler\n", __func__); - rtems_fatal_error_occurred(0xdeadbeef); - } - #elif defined(BSP_FEATURE_IRQ_LEGACY) - int rv = 0; - rtems_irq_connect_data cd = { - .name = ctx->irq, - .hdl = isr, - .handle = tty - }; - rv = BSP_remove_rtems_irq_handler(&cd); - if (rv == 0) { - /* FIXME */ - printk("%s: Error: Remove interrupt handler\n", __func__); - rtems_fatal_error_occurred(0xdeadbeef); - } - #endif -} - -/* - * ns16550_close - */ - -static void ns16550_close( - struct rtems_termios_tty *tty, - rtems_termios_device_context *base, - rtems_libio_open_close_args_t *args -) -{ - ns16550_context *ctx = (ns16550_context *) base; - - ns16550_enable_interrupts(ctx, NS16550_DISABLE_ALL_INTR); - - if (tty->handler.mode == TERMIOS_IRQ_DRIVEN) { - ns16550_cleanup_interrupts(tty, ctx, ns16550_isr); - } else if (tty->handler.mode == TERMIOS_TASK_DRIVEN) { - ns16550_cleanup_interrupts(tty, ctx, ns16550_isr_task); - } -} - -/** - * @brief Polled write for NS16550. - */ -void ns16550_polled_putchar(rtems_termios_device_context *base, char out) -{ - ns16550_context *ctx = (ns16550_context *) base; - uintptr_t port = ctx->port; - ns16550_get_reg get = ctx->get_reg; - ns16550_set_reg set = ctx->set_reg; - uint32_t status = 0; - rtems_interrupt_lock_context lock_context; - - /* Save port interrupt mask */ - uint32_t interrupt_mask = get( port, NS16550_INTERRUPT_ENABLE); - - /* Disable port interrupts */ - ns16550_enable_interrupts(ctx, NS16550_DISABLE_ALL_INTR); - - while (true) { - /* Try to transmit the character in a critical section */ - rtems_termios_device_lock_acquire(&ctx->base, &lock_context); - - /* Read the transmitter holding register and check it */ - status = get( port, NS16550_LINE_STATUS); - if ((status & SP_LSR_THOLD) != 0) { - /* Transmit character */ - set( port, NS16550_TRANSMIT_BUFFER, out); - - /* Finished */ - rtems_termios_device_lock_release(&ctx->base, &lock_context); - break; - } else { - rtems_termios_device_lock_release(&ctx->base, &lock_context); - } - - /* Wait for transmitter holding register to be empty */ - do { - status = get( port, NS16550_LINE_STATUS); - } while ((status & SP_LSR_THOLD) == 0); - } - - /* Restore port interrupt mask */ - set( port, NS16550_INTERRUPT_ENABLE, interrupt_mask); -} - -/* - * These routines provide control of the RTS and DTR lines - */ - -/* - * ns16550_assert_RTS - */ - -static void ns16550_assert_RTS(rtems_termios_device_context *base) -{ - ns16550_context *ctx = (ns16550_context *) base; - rtems_interrupt_lock_context lock_context; - - /* - * Assert RTS - */ - rtems_termios_device_lock_acquire(base, &lock_context); - ctx->modem_control |= SP_MODEM_RTS; - (*ctx->set_reg)(ctx->port, NS16550_MODEM_CONTROL, ctx->modem_control); - rtems_termios_device_lock_release(base, &lock_context); -} - -/* - * ns16550_negate_RTS - */ - -static void ns16550_negate_RTS(rtems_termios_device_context *base) -{ - ns16550_context *ctx = (ns16550_context *) base; - rtems_interrupt_lock_context lock_context; - - /* - * Negate RTS - */ - rtems_termios_device_lock_acquire(base, &lock_context); - ctx->modem_control &= ~SP_MODEM_RTS; - (*ctx->set_reg)(ctx->port, NS16550_MODEM_CONTROL, ctx->modem_control); - rtems_termios_device_lock_release(base, &lock_context); -} - -/* - * These flow control routines utilise a connection from the local DTR - * line to the remote CTS line - */ - -/* - * ns16550_assert_DTR - */ - -static void ns16550_assert_DTR(rtems_termios_device_context *base) -{ - ns16550_context *ctx = (ns16550_context *) base; - rtems_interrupt_lock_context lock_context; - - /* - * Assert DTR - */ - rtems_termios_device_lock_acquire(base, &lock_context); - ctx->modem_control |= SP_MODEM_DTR; - (*ctx->set_reg)(ctx->port, NS16550_MODEM_CONTROL, ctx->modem_control); - rtems_termios_device_lock_release(base, &lock_context); -} - -/* - * ns16550_negate_DTR - */ - -static void ns16550_negate_DTR(rtems_termios_device_context *base) -{ - ns16550_context *ctx = (ns16550_context *) base; - rtems_interrupt_lock_context lock_context; - - /* - * Negate DTR - */ - rtems_termios_device_lock_acquire(base, &lock_context); - ctx->modem_control &=~SP_MODEM_DTR; - (*ctx->set_reg)(ctx->port, NS16550_MODEM_CONTROL,ctx->modem_control); - rtems_termios_device_lock_release(base, &lock_context); -} - -/* - * ns16550_set_attributes - * - * This function sets the channel to reflect the requested termios - * port settings. - */ - -static bool ns16550_set_attributes( - rtems_termios_device_context *base, - const struct termios *t -) -{ - ns16550_context *ctx = (ns16550_context *) base; - uint32_t pNS16550; - uint32_t ulBaudDivisor; - uint8_t ucLineControl; - uint32_t baud_requested; - ns16550_set_reg setReg; - - pNS16550 = ctx->port; - setReg = ctx->set_reg; - - /* - * Calculate the baud rate divisor - * - * Assert ensures there is no division by 0. - */ - - baud_requested = rtems_termios_baud_to_number(t->c_ospeed); - _Assert( baud_requested != 0 ); - - ulBaudDivisor = NS16550_GetBaudDivisor(ctx, baud_requested); - - ucLineControl = 0; - - /* - * Parity - */ - - if (t->c_cflag & PARENB) { - ucLineControl |= SP_LINE_PAR; - if (!(t->c_cflag & PARODD)) - ucLineControl |= SP_LINE_ODD; - } - - /* - * Character Size - */ - - if (t->c_cflag & CSIZE) { - switch (t->c_cflag & CSIZE) { - case CS5: ucLineControl |= FIVE_BITS; break; - case CS6: ucLineControl |= SIX_BITS; break; - case CS7: ucLineControl |= SEVEN_BITS; break; - case CS8: ucLineControl |= EIGHT_BITS; break; - } - } else { - ucLineControl |= EIGHT_BITS; /* default to 9600,8,N,1 */ - } - - /* - * Stop Bits - */ - - if (t->c_cflag & CSTOPB) { - ucLineControl |= SP_LINE_STOP; /* 2 stop bits */ - } else { - ; /* 1 stop bit */ - } - - /* - * Now actually set the chip - */ - - if (ulBaudDivisor != ctx->baud_divisor || ucLineControl != ctx->line_control) { - rtems_interrupt_lock_context lock_context; - - ctx->baud_divisor = ulBaudDivisor; - ctx->line_control = ucLineControl; - - rtems_termios_device_lock_acquire(base, &lock_context); - - /* - * Set the baud rate - * - * NOTE: When the Divisor Latch Access Bit (DLAB) is set to 1, - * the transmit buffer and interrupt enable registers - * turn into the LSB and MSB divisor latch registers. - */ - - (*setReg)(pNS16550, NS16550_LINE_CONTROL, SP_LINE_DLAB); - (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, ulBaudDivisor&0xff); - (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (ulBaudDivisor>>8)&0xff); - - /* - * Now write the line control - */ - (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucLineControl ); - - rtems_termios_device_lock_release(base, &lock_context); - } - - return true; -} - -/** - * @brief Transmits up to @a len characters from @a buf. - * - * This routine is invoked either from task context with disabled interrupts to - * start a new transmission process with exactly one character in case of an - * idle output state or from the interrupt handler to refill the transmitter. - * - * Returns always zero. - */ -static void ns16550_write_support_int( - rtems_termios_device_context *base, - const char *buf, - size_t len -) -{ - ns16550_context *ctx = (ns16550_context *) base; - - ctx->out_total = len; - - if (len > 0) { - ctx->out_remaining = len; - ctx->out_buf = buf; - ctx->out_current = ns16550_write_to_fifo(ctx, buf, len); - - ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR); - } else { - ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR_EXCEPT_TX); - } -} - -static void ns16550_write_support_task( - rtems_termios_device_context *base, - const char *buf, - size_t len -) -{ - ns16550_context *ctx = (ns16550_context *) base; - - ctx->out_total = len; - - if (len > 0) { - ctx->out_remaining = len; - ctx->out_buf = buf; - ctx->out_current = ns16550_write_to_fifo(ctx, buf, len); - - ns16550_clear_and_set_interrupts(ctx, 0, SP_INT_TX_ENABLE); - } -} - -/* - * ns16550_write_support_polled - * - * Console Termios output entry point. - * - */ - -static void ns16550_write_support_polled( - rtems_termios_device_context *base, - const char *buf, - size_t len -) -{ - size_t nwrite = 0; - - /* - * poll each byte in the string out of the port. - */ - while (nwrite < len) { - /* - * transmit character - */ - ns16550_polled_putchar(base, *buf++); - nwrite++; - } -} - -/* - * Debug gets() support - */ -int ns16550_polled_getchar(rtems_termios_device_context *base) -{ - ns16550_context *ctx = (ns16550_context *) base; - uint32_t pNS16550; - unsigned char ucLineStatus; - uint8_t cChar; - ns16550_get_reg getReg; - - pNS16550 = ctx->port; - getReg = ctx->get_reg; - - ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS); - if (ucLineStatus & SP_LSR_RDY) { - cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER); - return (int)cChar; - } - return -1; -} - -/* - * Flow control is only supported when using interrupts - */ - -const rtems_termios_device_flow ns16550_flow_rtscts = { - .stop_remote_tx = ns16550_negate_RTS, - .start_remote_tx = ns16550_assert_RTS -}; - -const rtems_termios_device_flow ns16550_flow_dtrcts = { - .stop_remote_tx = ns16550_negate_DTR, - .start_remote_tx = ns16550_assert_DTR -}; - -const rtems_termios_device_handler ns16550_handler_interrupt = { - .first_open = ns16550_open, - .last_close = ns16550_close, - .poll_read = NULL, - .write = ns16550_write_support_int, - .set_attributes = ns16550_set_attributes, - .mode = TERMIOS_IRQ_DRIVEN -}; - -const rtems_termios_device_handler ns16550_handler_polled = { - .first_open = ns16550_open, - .last_close = ns16550_close, - .poll_read = ns16550_polled_getchar, - .write = ns16550_write_support_polled, - .set_attributes = ns16550_set_attributes, - .mode = TERMIOS_POLLED -}; - -const rtems_termios_device_handler ns16550_handler_task = { - .first_open = ns16550_open, - .last_close = ns16550_close, - .poll_read = ns16550_read_task, - .write = ns16550_write_support_task, - .set_attributes = ns16550_set_attributes, - .mode = TERMIOS_TASK_DRIVEN -}; diff --git a/c/src/libchip/serial/ns16550.c b/c/src/libchip/serial/ns16550.c deleted file mode 100644 index b1e5892c15..0000000000 --- a/c/src/libchip/serial/ns16550.c +++ /dev/null @@ -1,875 +0,0 @@ -/** - * @file - * - * This file contains the TTY driver for the National Semiconductor NS16550. - * - * This part is widely cloned and second sourced. It is found in a number - * of "Super IO" controllers. - * - * This driver uses the termios pseudo driver. - */ - -/* - * COPYRIGHT (c) 1998 by Radstone Technology - * - * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY - * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK - * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. - * - * You are hereby granted permission to use, copy, modify, and distribute - * this file, provided that this notice, plus the above copyright notice - * and disclaimer, appears in all copies. Radstone Technology will provide - * no support for this code. - * - * COPYRIGHT (c) 1989-2012. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include - -#if defined(BSP_FEATURE_IRQ_EXTENSION) - #include -#elif defined(BSP_FEATURE_IRQ_LEGACY) - #include -#elif defined(__PPC__) || defined(__i386__) - #include - #define BSP_FEATURE_IRQ_LEGACY - #ifdef BSP_SHARED_HANDLER_SUPPORT - #define BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT - #endif -#endif - -typedef struct { - uint8_t ucModemCtrl; - int transmitFifoChars; -} NS16550Context; - -/* - * Driver functions - */ - -NS16550_STATIC void ns16550_init(int minor); - -NS16550_STATIC int ns16550_open( - int major, - int minor, - void * arg -); - -NS16550_STATIC int ns16550_close( - int major, - int minor, - void * arg -); - -NS16550_STATIC void ns16550_write_polled( - int minor, - char cChar -); - -NS16550_STATIC int ns16550_assert_RTS( - int minor -); - -NS16550_STATIC int ns16550_negate_RTS( - int minor -); - -NS16550_STATIC int ns16550_assert_DTR( - int minor -); - -NS16550_STATIC int ns16550_negate_DTR( - int minor -); - -NS16550_STATIC void ns16550_initialize_interrupts(int minor); - -NS16550_STATIC void ns16550_cleanup_interrupts(int minor); - -NS16550_STATIC ssize_t ns16550_write_support_int( - int minor, - const char *buf, - size_t len -); - -NS16550_STATIC ssize_t ns16550_write_support_polled( - int minor, - const char *buf, - size_t len - ); - -int ns16550_inbyte_nonblocking_polled( - int minor -); - -NS16550_STATIC void ns16550_enable_interrupts( - console_tbl *c, - int mask -); - -NS16550_STATIC int ns16550_set_attributes( - int minor, - const struct termios *t -); - -#if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY) - NS16550_STATIC void ns16550_isr(void *arg); -#endif - -RTEMS_INTERRUPT_LOCK_DEFINE(static, ns16550_lock, "NS16550") - -/* - * Flow control is only supported when using interrupts - */ - -const console_flow ns16550_flow_RTSCTS = { - ns16550_negate_RTS, /* deviceStopRemoteTx */ - ns16550_assert_RTS /* deviceStartRemoteTx */ -}; - -const console_flow ns16550_flow_DTRCTS = { - ns16550_negate_DTR, /* deviceStopRemoteTx */ - ns16550_assert_DTR /* deviceStartRemoteTx */ -}; - -const console_fns ns16550_fns = { - libchip_serial_default_probe, /* deviceProbe */ - ns16550_open, /* deviceFirstOpen */ - ns16550_close, /* deviceLastClose */ - NULL, /* deviceRead */ - ns16550_write_support_int, /* deviceWrite */ - ns16550_init, /* deviceInitialize */ - ns16550_write_polled, /* deviceWritePolled */ - ns16550_set_attributes, /* deviceSetAttributes */ - true /* deviceOutputUsesInterrupts */ -}; - -const console_fns ns16550_fns_polled = { - libchip_serial_default_probe, /* deviceProbe */ - ns16550_open, /* deviceFirstOpen */ - ns16550_close, /* deviceLastClose */ - ns16550_inbyte_nonblocking_polled, /* deviceRead */ - ns16550_write_support_polled, /* deviceWrite */ - ns16550_init, /* deviceInitialize */ - ns16550_write_polled, /* deviceWritePolled */ - ns16550_set_attributes, /* deviceSetAttributes */ - false /* deviceOutputUsesInterrupts */ -}; - -static uint32_t NS16550_GetBaudDivisor(const console_tbl *c, uint32_t baud) -{ - uint32_t clock = c->ulClock; - uint32_t baudDivisor = (clock != 0 ? clock : 115200) / (baud * 16); - - if (c->deviceType == SERIAL_NS16550_WITH_FDR) { - uint32_t fractionalDivider = 0x10; - uint32_t err = baud; - uint32_t mulVal; - uint32_t divAddVal; - - clock /= 16 * baudDivisor; - for (mulVal = 1; mulVal < 16; ++mulVal) { - for (divAddVal = 0; divAddVal < mulVal; ++divAddVal) { - uint32_t actual = (mulVal * clock) / (mulVal + divAddVal); - uint32_t newErr = actual > baud ? actual - baud : baud - actual; - - if (newErr < err) { - err = newErr; - fractionalDivider = (mulVal << 4) | divAddVal; - } - } - } - - (*c->setRegister)( - c->ulCtrlPort1, - NS16550_FRACTIONAL_DIVIDER, - fractionalDivider - ); - } - - return baudDivisor; -} - -/* - * ns16550_init - */ - -void ns16550_init(int minor) -{ - uintptr_t pNS16550; - uint8_t ucDataByte; - uint32_t ulBaudDivisor; - NS16550Context *pns16550Context; - setRegister_f setReg; - getRegister_f getReg; - console_tbl *c = Console_Port_Tbl [minor]; - - pns16550Context=(NS16550Context *)malloc(sizeof(NS16550Context)); - - if (pns16550Context == NULL) { - printk( "%s: Error: Not enough memory\n", __func__); - rtems_fatal_error_occurred( 0xdeadbeef); - } - - Console_Port_Data[minor].pDeviceContext=(void *)pns16550Context; - pns16550Context->ucModemCtrl=SP_MODEM_IRQ; - - pNS16550 = c->ulCtrlPort1; - setReg = c->setRegister; - getReg = c->getRegister; - - /* Clear the divisor latch, clear all interrupt enables, - * and reset and - * disable the FIFO's. - */ - - (*setReg)(pNS16550, NS16550_LINE_CONTROL, 0x0); - ns16550_enable_interrupts( c, NS16550_DISABLE_ALL_INTR ); - - /* Set the divisor latch and set the baud rate. */ - - ulBaudDivisor = NS16550_GetBaudDivisor(c, (uintptr_t) c->pDeviceParams); - ucDataByte = SP_LINE_DLAB; - (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte); - - /* XXX */ - (*setReg)(pNS16550,NS16550_TRANSMIT_BUFFER,(uint8_t)(ulBaudDivisor & 0xffU)); - (*setReg)( - pNS16550,NS16550_INTERRUPT_ENABLE, - (uint8_t)(( ulBaudDivisor >> 8 ) & 0xffU ) - ); - - /* Clear the divisor latch and set the character size to eight bits */ - /* with one stop bit and no parity checking. */ - ucDataByte = EIGHT_BITS; - (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte); - - /* Enable and reset transmit and receive FIFOs. TJA */ - ucDataByte = SP_FIFO_ENABLE; - (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte); - - ucDataByte = SP_FIFO_ENABLE | SP_FIFO_RXRST | SP_FIFO_TXRST; - (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte); - - ns16550_enable_interrupts(c, NS16550_DISABLE_ALL_INTR); - - /* Set data terminal ready. */ - /* And open interrupt tristate line */ - (*setReg)(pNS16550, NS16550_MODEM_CONTROL,pns16550Context->ucModemCtrl); - - (*getReg)(pNS16550, NS16550_LINE_STATUS ); - (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER ); -} - -/* - * ns16550_open - */ - -int ns16550_open( - int major, - int minor, - void *arg -) -{ - rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg; - struct rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1; - console_tbl *c = Console_Port_Tbl [minor]; - console_data *d = &Console_Port_Data [minor]; - - d->termios_data = tty; - - /* Assert DTR */ - if (c->pDeviceFlow != &ns16550_flow_DTRCTS) { - ns16550_assert_DTR( minor); - } - - /* Set initial baud */ - rtems_termios_set_initial_baud( tty, (intptr_t) c->pDeviceParams); - - if (c->pDeviceFns->deviceOutputUsesInterrupts) { - ns16550_initialize_interrupts( minor); - ns16550_enable_interrupts( c, NS16550_ENABLE_ALL_INTR_EXCEPT_TX); - } - - return RTEMS_SUCCESSFUL; -} - -/* - * ns16550_close - */ - -int ns16550_close( - int major, - int minor, - void * arg -) -{ - console_tbl *c = Console_Port_Tbl [minor]; - - /* - * Negate DTR - */ - if (c->pDeviceFlow != &ns16550_flow_DTRCTS) { - ns16550_negate_DTR(minor); - } - - ns16550_enable_interrupts(c, NS16550_DISABLE_ALL_INTR); - - if (c->pDeviceFns->deviceOutputUsesInterrupts) { - ns16550_cleanup_interrupts(minor); - } - - return(RTEMS_SUCCESSFUL); -} - -/** - * @brief Polled write for NS16550. - */ -void ns16550_outch_polled(console_tbl *c, char out) -{ - uintptr_t port = c->ulCtrlPort1; - getRegister_f get = c->getRegister; - setRegister_f set = c->setRegister; - uint32_t status = 0; - rtems_interrupt_lock_context lock_context; - - /* Save port interrupt mask */ - uint32_t interrupt_mask = get( port, NS16550_INTERRUPT_ENABLE); - - /* Disable port interrupts */ - ns16550_enable_interrupts( c, NS16550_DISABLE_ALL_INTR); - - while (true) { - /* Try to transmit the character in a critical section */ - rtems_interrupt_lock_acquire(&ns16550_lock, &lock_context); - - /* Read the transmitter holding register and check it */ - status = get( port, NS16550_LINE_STATUS); - if ((status & SP_LSR_THOLD) != 0) { - /* Transmit character */ - set( port, NS16550_TRANSMIT_BUFFER, out); - - /* Finished */ - rtems_interrupt_lock_release(&ns16550_lock, &lock_context); - break; - } else { - rtems_interrupt_lock_release(&ns16550_lock, &lock_context); - } - - /* Wait for transmitter holding register to be empty */ - do { - status = get( port, NS16550_LINE_STATUS); - } while ((status & SP_LSR_THOLD) == 0); - } - - /* Restore port interrupt mask */ - set( port, NS16550_INTERRUPT_ENABLE, interrupt_mask); -} - -void ns16550_write_polled(int minor, char out) -{ - console_tbl *c = Console_Port_Tbl [minor]; - - ns16550_outch_polled( c, out ); -} - -/* - * These routines provide control of the RTS and DTR lines - */ - -/* - * ns16550_assert_RTS - */ - -NS16550_STATIC int ns16550_assert_RTS(int minor) -{ - uint32_t pNS16550; - rtems_interrupt_lock_context lock_context; - NS16550Context *pns16550Context; - setRegister_f setReg; - - pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext; - - pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1; - setReg = Console_Port_Tbl[minor]->setRegister; - - /* - * Assert RTS - */ - rtems_interrupt_lock_acquire(&ns16550_lock, &lock_context); - pns16550Context->ucModemCtrl|=SP_MODEM_RTS; - (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl); - rtems_interrupt_lock_release(&ns16550_lock, &lock_context); - return 0; -} - -/* - * ns16550_negate_RTS - */ - -NS16550_STATIC int ns16550_negate_RTS(int minor) -{ - uint32_t pNS16550; - rtems_interrupt_lock_context lock_context; - NS16550Context *pns16550Context; - setRegister_f setReg; - - pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext; - - pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1; - setReg = Console_Port_Tbl[minor]->setRegister; - - /* - * Negate RTS - */ - rtems_interrupt_lock_acquire(&ns16550_lock, &lock_context); - pns16550Context->ucModemCtrl&=~SP_MODEM_RTS; - (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl); - rtems_interrupt_lock_release(&ns16550_lock, &lock_context); - return 0; -} - -/* - * These flow control routines utilise a connection from the local DTR - * line to the remote CTS line - */ - -/* - * ns16550_assert_DTR - */ - -NS16550_STATIC int ns16550_assert_DTR(int minor) -{ - uint32_t pNS16550; - rtems_interrupt_lock_context lock_context; - NS16550Context *pns16550Context; - setRegister_f setReg; - - pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext; - - pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1; - setReg = Console_Port_Tbl[minor]->setRegister; - - /* - * Assert DTR - */ - rtems_interrupt_lock_acquire(&ns16550_lock, &lock_context); - pns16550Context->ucModemCtrl|=SP_MODEM_DTR; - (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl); - rtems_interrupt_lock_release(&ns16550_lock, &lock_context); - return 0; -} - -/* - * ns16550_negate_DTR - */ - -NS16550_STATIC int ns16550_negate_DTR(int minor) -{ - uint32_t pNS16550; - rtems_interrupt_lock_context lock_context; - NS16550Context *pns16550Context; - setRegister_f setReg; - - pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext; - - pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1; - setReg = Console_Port_Tbl[minor]->setRegister; - - /* - * Negate DTR - */ - rtems_interrupt_lock_acquire(&ns16550_lock, &lock_context); - pns16550Context->ucModemCtrl&=~SP_MODEM_DTR; - (*setReg)(pNS16550, NS16550_MODEM_CONTROL,pns16550Context->ucModemCtrl); - rtems_interrupt_lock_release(&ns16550_lock, &lock_context); - return 0; -} - -/* - * ns16550_set_attributes - * - * This function sets the channel to reflect the requested termios - * port settings. - */ - -int ns16550_set_attributes( - int minor, - const struct termios *t -) -{ - uint32_t pNS16550; - uint32_t ulBaudDivisor; - uint8_t ucLineControl; - uint32_t baud_requested; - setRegister_f setReg; - rtems_interrupt_lock_context lock_context; - const console_tbl *c = Console_Port_Tbl [minor]; - - pNS16550 = c->ulCtrlPort1; - setReg = c->setRegister; - - /* - * Calculate the baud rate divisor - * - * Assert ensures there is no division by 0. - */ - - baud_requested = rtems_termios_baud_to_number(t->c_ospeed); - _Assert( baud_requested != 0 ); - ulBaudDivisor = NS16550_GetBaudDivisor(c, baud_requested); - - ucLineControl = 0; - - /* - * Parity - */ - - if (t->c_cflag & PARENB) { - ucLineControl |= SP_LINE_PAR; - if (!(t->c_cflag & PARODD)) - ucLineControl |= SP_LINE_ODD; - } - - /* - * Character Size - */ - - if (t->c_cflag & CSIZE) { - switch (t->c_cflag & CSIZE) { - case CS5: ucLineControl |= FIVE_BITS; break; - case CS6: ucLineControl |= SIX_BITS; break; - case CS7: ucLineControl |= SEVEN_BITS; break; - case CS8: ucLineControl |= EIGHT_BITS; break; - } - } else { - ucLineControl |= EIGHT_BITS; /* default to 9600,8,N,1 */ - } - - /* - * Stop Bits - */ - - if (t->c_cflag & CSTOPB) { - ucLineControl |= SP_LINE_STOP; /* 2 stop bits */ - } else { - ; /* 1 stop bit */ - } - - /* - * Now actually set the chip - */ - - rtems_interrupt_lock_acquire(&ns16550_lock, &lock_context); - - /* - * Set the baud rate - * - * NOTE: When the Divisor Latch Access Bit (DLAB) is set to 1, - * the transmit buffer and interrupt enable registers - * turn into the LSB and MSB divisor latch registers. - */ - - (*setReg)(pNS16550, NS16550_LINE_CONTROL, SP_LINE_DLAB); - (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, ulBaudDivisor&0xff); - (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (ulBaudDivisor>>8)&0xff); - - /* - * Now write the line control - */ - (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucLineControl ); - - rtems_interrupt_lock_release(&ns16550_lock, &lock_context); - - return 0; -} - -#if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY) - -/** - * @brief Process interrupt. - */ -NS16550_STATIC void ns16550_process( int minor) -{ - console_tbl *c = Console_Port_Tbl [minor]; - console_data *d = &Console_Port_Data [minor]; - NS16550Context *ctx = d->pDeviceContext; - uint32_t port = c->ulCtrlPort1; - getRegister_f get = c->getRegister; - int i; - char buf [SP_FIFO_SIZE]; - - /* Iterate until no more interrupts are pending */ - do { - /* Fetch received characters */ - i = 0; - while ((get(port, NS16550_LINE_STATUS) & SP_LSR_RDY) != 0) { - buf[i++] = (char) get(port, NS16550_RECEIVE_BUFFER); - if (i == SP_FIFO_SIZE) { - /* Enqueue fetched characters */ - rtems_termios_enqueue_raw_characters( d->termios_data, buf, i); - i = 0; - } - } - - if (i > 0) - rtems_termios_enqueue_raw_characters( d->termios_data, buf, i); - - /* Check if we can dequeue transmitted characters */ - if (ctx->transmitFifoChars > 0 - && (get( port, NS16550_LINE_STATUS) & SP_LSR_THOLD) != 0) { - /* Dequeue transmitted characters */ - rtems_termios_dequeue_characters( - d->termios_data, - ctx->transmitFifoChars - ); - } - } while ((get( port, NS16550_INTERRUPT_ID) & SP_IID_0) == 0); -} -#endif - -/** - * @brief Transmits up to @a len characters from @a buf. - * - * This routine is invoked either from task context with disabled interrupts to - * start a new transmission process with exactly one character in case of an - * idle output state or from the interrupt handler to refill the transmitter. - * - * Returns always zero. - */ -ssize_t ns16550_write_support_int( - int minor, - const char *buf, - size_t len -) -{ - console_tbl *c = Console_Port_Tbl [minor]; - console_data *d = &Console_Port_Data [minor]; - NS16550Context *ctx = d->pDeviceContext; - uint32_t port = c->ulCtrlPort1; - setRegister_f set = c->setRegister; - int i = 0; - int out = len > SP_FIFO_SIZE ? SP_FIFO_SIZE : len; - - for (i = 0; i < out; ++i) { - set( port, NS16550_TRANSMIT_BUFFER, buf [i]); - } - - ctx->transmitFifoChars = out; - - if (out > 0) { - ns16550_enable_interrupts( c, NS16550_ENABLE_ALL_INTR); - } else { - ns16550_enable_interrupts( c, NS16550_ENABLE_ALL_INTR_EXCEPT_TX); - } - - return 0; -} - -/* - * ns16550_enable_interrupts - * - * This routine initializes the port to have the specified interrupts masked. - */ -NS16550_STATIC void ns16550_enable_interrupts( - console_tbl *c, - int mask -) -{ - uint32_t pNS16550; - setRegister_f setReg; - - pNS16550 = c->ulCtrlPort1; - setReg = c->setRegister; - - (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, mask); -} - -#if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY) - void ns16550_isr(void *arg) - { - int minor = (intptr_t) arg; - - ns16550_process( minor); - } -#endif - -/* - * ns16550_initialize_interrupts - * - * This routine initializes the port to operate in interrupt driver mode. - */ -NS16550_STATIC void ns16550_initialize_interrupts( int minor) -{ -#if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY) - console_tbl *c = Console_Port_Tbl [minor]; -#endif - - #ifdef BSP_FEATURE_IRQ_EXTENSION - { - rtems_status_code sc = RTEMS_SUCCESSFUL; - sc = rtems_interrupt_handler_install( - c->ulIntVector, - "NS16550", - RTEMS_INTERRUPT_SHARED, - ns16550_isr, - (void *) (intptr_t) minor - ); - if (sc != RTEMS_SUCCESSFUL) { - /* FIXME */ - printk( "%s: Error: Install interrupt handler\n", __func__); - rtems_fatal_error_occurred( 0xdeadbeef); - } - } - #elif defined(BSP_FEATURE_IRQ_LEGACY) - { - int rv = 0; - #ifdef BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT - rtems_irq_connect_data cd = { - c->ulIntVector, - ns16550_isr, - (void *) minor, - NULL, - NULL, - NULL, - NULL - }; - rv = BSP_install_rtems_shared_irq_handler( &cd); - #else - rtems_irq_connect_data cd = { - c->ulIntVector, - ns16550_isr, - (void *) minor, - NULL, - NULL, - NULL - }; - rv = BSP_install_rtems_irq_handler( &cd); - #endif - if (rv == 0) { - /* FIXME */ - printk( "%s: Error: Install interrupt handler\n", __func__); - rtems_fatal_error_occurred( 0xdeadbeef); - } - } - #endif -} - -NS16550_STATIC void ns16550_cleanup_interrupts(int minor) -{ - #if defined(BSP_FEATURE_IRQ_EXTENSION) - rtems_status_code sc = RTEMS_SUCCESSFUL; - console_tbl *c = Console_Port_Tbl [minor]; - sc = rtems_interrupt_handler_remove( - c->ulIntVector, - ns16550_isr, - (void *) (intptr_t) minor - ); - if (sc != RTEMS_SUCCESSFUL) { - /* FIXME */ - printk("%s: Error: Remove interrupt handler\n", __func__); - rtems_fatal_error_occurred(0xdeadbeef); - } - #elif defined(BSP_FEATURE_IRQ_LEGACY) - int rv = 0; - console_tbl *c = Console_Port_Tbl [minor]; - rtems_irq_connect_data cd = { - .name = c->ulIntVector, - .hdl = ns16550_isr, - .handle = (void *) minor - }; - rv = BSP_remove_rtems_irq_handler(&cd); - if (rv == 0) { - /* FIXME */ - printk("%s: Error: Remove interrupt handler\n", __func__); - rtems_fatal_error_occurred(0xdeadbeef); - } - #endif -} - -/* - * ns16550_write_support_polled - * - * Console Termios output entry point. - * - */ - -ssize_t ns16550_write_support_polled( - int minor, - const char *buf, - size_t len -) -{ - int nwrite = 0; - - /* - * poll each byte in the string out of the port. - */ - while (nwrite < len) { - /* - * transmit character - */ - ns16550_write_polled(minor, *buf++); - nwrite++; - } - - /* - * return the number of bytes written. - */ - return nwrite; -} - -/* - * Debug gets() support - */ -int ns16550_inch_polled( - console_tbl *c -) -{ - uint32_t pNS16550; - unsigned char ucLineStatus; - uint8_t cChar; - getRegister_f getReg; - - pNS16550 = c->ulCtrlPort1; - getReg = c->getRegister; - - ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS); - if (ucLineStatus & SP_LSR_RDY) { - cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER); - return (int)cChar; - } - return -1; -} - -/* - * ns16550_inbyte_nonblocking_polled - * - * Console Termios polling input entry point. - */ -int ns16550_inbyte_nonblocking_polled(int minor) -{ - console_tbl *c = Console_Port_Tbl [minor]; - - return ns16550_inch_polled( c ); -} diff --git a/c/src/libchip/serial/serprobe.c b/c/src/libchip/serial/serprobe.c deleted file mode 100644 index 7f8d392452..0000000000 --- a/c/src/libchip/serial/serprobe.c +++ /dev/null @@ -1,13 +0,0 @@ -#include -#include -#include - -bool libchip_serial_default_probe(int minor) -{ - /* - * If the configuration dependent probe has located the device then - * assume it is there - */ - - return true; -} diff --git a/c/src/libchip/serial/z85c30.c b/c/src/libchip/serial/z85c30.c deleted file mode 100644 index 55df9d3451..0000000000 --- a/c/src/libchip/serial/z85c30.c +++ /dev/null @@ -1,893 +0,0 @@ -/* - * This file contains the console driver chip level routines for the - * Zilog z85c30 chip. - * - * The Zilog Z8530 is also available as: - * - * + Intel 82530 - * + AMD ??? - * - * COPYRIGHT (c) 1998 by Radstone Technology - * - * - * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY - * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK - * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. - * - * You are hereby granted permission to use, copy, modify, and distribute - * this file, provided that this notice, plus the above copyright notice - * and disclaimer, appears in all copies. Radstone Technology will provide - * no support for this code. - * - * COPYRIGHT (c) 1989-1997. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include - -#include -#include -#include "z85c30_p.h" - -/* - * Flow control is only supported when using interrupts - */ - -const console_flow z85c30_flow_RTSCTS = { - z85c30_negate_RTS, /* deviceStopRemoteTx */ - z85c30_assert_RTS /* deviceStartRemoteTx */ -}; - -const console_flow z85c30_flow_DTRCTS = { - z85c30_negate_DTR, /* deviceStopRemoteTx */ - z85c30_assert_DTR /* deviceStartRemoteTx */ -}; - -/* - * Exported driver function table - */ - -const console_fns z85c30_fns = { - libchip_serial_default_probe, /* deviceProbe */ - z85c30_open, /* deviceFirstOpen */ - NULL, /* deviceLastClose */ - NULL, /* deviceRead */ - z85c30_write_support_int, /* deviceWrite */ - z85c30_initialize_interrupts, /* deviceInitialize */ - z85c30_write_polled, /* deviceWritePolled */ - NULL, /* deviceSetAttributes */ - true /* deviceOutputUsesInterrupts */ -}; - -const console_fns z85c30_fns_polled = { - libchip_serial_default_probe, /* deviceProbe */ - z85c30_open, /* deviceFirstOpen */ - z85c30_close, /* deviceLastClose */ - z85c30_inbyte_nonblocking_polled, /* deviceRead */ - z85c30_write_support_polled, /* deviceWrite */ - z85c30_init, /* deviceInitialize */ - z85c30_write_polled, /* deviceWritePolled */ - NULL, /* deviceSetAttributes */ - false /* deviceOutputUsesInterrupts */ -}; - -#if (CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE) - extern void set_vector( rtems_isr_entry, rtems_vector_number, int ); -#endif - -/* - * z85c30_initialize_port - * - * initialize a z85c30 Port - */ - -Z85C30_STATIC void z85c30_initialize_port( - int minor -) -{ - uintptr_t ulCtrlPort; - uintptr_t ulBaudDivisor; - setRegister_f setReg; - - ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1; - setReg = Console_Port_Tbl[minor]->setRegister; - - /* - * Using register 4 - * Set up the clock rate is 16 times the data - * rate, 8 bit sync char, 1 stop bit, no parity - */ - - (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR4, SCC_WR4_1_STOP | SCC_WR4_16_CLOCK ); - - /* - * Set up for 8 bits/character on receive with - * receiver disable via register 3 - */ - (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR3, SCC_WR3_RX_8_BITS ); - - /* - * Set up for 8 bits/character on transmit - * with transmitter disable via register 5 - */ - (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR5, SCC_WR5_TX_8_BITS ); - - /* - * Clear misc control bits - */ - (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR10, 0x00 ); - - /* - * Setup the source of the receive and xmit - * clock as BRG output and the transmit clock - * as the output source for TRxC pin via register 11 - */ - (*setReg)( - ulCtrlPort, - SCC_WR0_SEL_WR11, - SCC_WR11_OUT_BR_GEN | SCC_WR11_TRXC_OI | - SCC_WR11_TX_BR_GEN | SCC_WR11_RX_BR_GEN - ); - - ulBaudDivisor = Z85C30_Baud( - (uint32_t) Console_Port_Tbl[minor]->ulClock, - (uint32_t) ((uintptr_t)Console_Port_Tbl[minor]->pDeviceParams) - ); - - /* - * Setup the lower 8 bits time constants=1E. - * If the time constans=1E, then the desire - * baud rate will be equilvalent to 9600, via register 12. - */ - (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR12, ulBaudDivisor & 0xff ); - - /* - * using register 13 - * Setup the upper 8 bits time constant - */ - (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR13, (ulBaudDivisor>>8) & 0xff ); - - /* - * Enable the baud rate generator enable with clock from the - * SCC's PCLK input via register 14. - */ - (*setReg)( - ulCtrlPort, - SCC_WR0_SEL_WR14, - SCC_WR14_BR_EN | SCC_WR14_BR_SRC | SCC_WR14_NULL - ); - - /* - * We are only interested in CTS state changes - */ - (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR15, SCC_WR15_CTS_IE ); - - /* - * Reset errors - */ - (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT ); - - (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_ERR_RST ); - - /* - * Enable the receiver via register 3 - */ - (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR3, SCC_WR3_RX_8_BITS | SCC_WR3_RX_EN ); - - /* - * Enable the transmitter pins set via register 5. - */ - (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR5, SCC_WR5_TX_8_BITS | SCC_WR5_TX_EN ); - - /* - * Disable interrupts - */ - (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR1, 0 ); - - /* - * Reset TX CRC - */ - (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_CRC ); - - /* - * Reset interrupts - */ - (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT ); -} - -/* - * z85c30_open - */ - -Z85C30_STATIC int z85c30_open( - int major, - int minor, - void *arg -) -{ - - z85c30_initialize_port(minor); - - /* - * Assert DTR - */ - - if (Console_Port_Tbl[minor]->pDeviceFlow !=&z85c30_flow_DTRCTS) { - z85c30_assert_DTR(minor); - } - - return(RTEMS_SUCCESSFUL); -} - -/* - * z85c30_close - */ - -Z85C30_STATIC int z85c30_close( - int major, - int minor, - void *arg -) -{ - /* - * Negate DTR - */ - - if (Console_Port_Tbl[minor]->pDeviceFlow !=&z85c30_flow_DTRCTS) { - z85c30_negate_DTR(minor); - } - - return(RTEMS_SUCCESSFUL); -} - -/* - * z85c30_init - */ - -Z85C30_STATIC void z85c30_init(int minor) -{ - uintptr_t ulCtrlPort; - z85c30_context *pz85c30Context; - setRegister_f setReg; - getRegister_f getReg; - - ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1; - setReg = Console_Port_Tbl[minor]->setRegister; - getReg = Console_Port_Tbl[minor]->getRegister; - - pz85c30Context = (z85c30_context *)malloc(sizeof(z85c30_context)); - - Console_Port_Data[minor].pDeviceContext = (void *)pz85c30Context; - - pz85c30Context->ucModemCtrl = SCC_WR5_TX_8_BITS | SCC_WR5_TX_EN; - - if ( ulCtrlPort == Console_Port_Tbl[minor]->ulCtrlPort2 ) { - /* - * This is channel A - */ - /* - * Ensure port state machine is reset - */ - (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0); - - (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR9, SCC_WR9_CH_A_RST); - - } else { - /* - * This is channel B - */ - /* - * Ensure port state machine is reset - */ - (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0); - - (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR9, SCC_WR9_CH_B_RST); - } -} - -/* - * These routines provide control of the RTS and DTR lines - */ - -/* - * z85c30_assert_RTS - */ - -Z85C30_STATIC int z85c30_assert_RTS(int minor) -{ - rtems_interrupt_level Irql; - z85c30_context *pz85c30Context; - setRegister_f setReg; - - setReg = Console_Port_Tbl[minor]->setRegister; - - pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext; - - /* - * Assert RTS - */ - - rtems_interrupt_disable(Irql); - pz85c30Context->ucModemCtrl|=SCC_WR5_RTS; - (*setReg)( - Console_Port_Tbl[minor]->ulCtrlPort1, - SCC_WR0_SEL_WR5, - pz85c30Context->ucModemCtrl - ); - rtems_interrupt_enable(Irql); - return 0; -} - -/* - * z85c30_negate_RTS - */ - -Z85C30_STATIC int z85c30_negate_RTS(int minor) -{ - rtems_interrupt_level Irql; - z85c30_context *pz85c30Context; - setRegister_f setReg; - - setReg = Console_Port_Tbl[minor]->setRegister; - - pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext; - - /* - * Negate RTS - */ - - rtems_interrupt_disable(Irql); - pz85c30Context->ucModemCtrl&=~SCC_WR5_RTS; - (*setReg)( - Console_Port_Tbl[minor]->ulCtrlPort1, - SCC_WR0_SEL_WR5, - pz85c30Context->ucModemCtrl - ); - rtems_interrupt_enable(Irql); - return 0; -} - -/* - * These flow control routines utilise a connection from the local DTR - * line to the remote CTS line - */ - -/* - * z85c30_assert_DTR - */ - -Z85C30_STATIC int z85c30_assert_DTR(int minor) -{ - rtems_interrupt_level Irql; - z85c30_context *pz85c30Context; - setRegister_f setReg; - - setReg = Console_Port_Tbl[minor]->setRegister; - - pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext; - - /* - * Assert DTR - */ - - rtems_interrupt_disable(Irql); - pz85c30Context->ucModemCtrl|=SCC_WR5_DTR; - (*setReg)( - Console_Port_Tbl[minor]->ulCtrlPort1, - SCC_WR0_SEL_WR5, - pz85c30Context->ucModemCtrl - ); - rtems_interrupt_enable(Irql); - return 0; -} - -/* - * z85c30_negate_DTR - */ - -Z85C30_STATIC int z85c30_negate_DTR(int minor) -{ - rtems_interrupt_level Irql; - z85c30_context *pz85c30Context; - setRegister_f setReg; - - setReg = Console_Port_Tbl[minor]->setRegister; - - pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext; - - /* - * Negate DTR - */ - - rtems_interrupt_disable(Irql); - pz85c30Context->ucModemCtrl&=~SCC_WR5_DTR; - (*setReg)( - Console_Port_Tbl[minor]->ulCtrlPort1, - SCC_WR0_SEL_WR5, - pz85c30Context->ucModemCtrl - ); - rtems_interrupt_enable(Irql); - return 0; -} - -/* - * z85c30_set_attributes - * - * This function sets the SCC channel to reflect the requested termios - * port settings. - */ - -Z85C30_STATIC int z85c30_set_attributes( - int minor, - const struct termios *t -) -{ - uintptr_t ulCtrlPort; - uint32_t ulBaudDivisor; - uint32_t wr3; - uint32_t wr4; - uint32_t wr5; - int baud_requested; - uint32_t baud_number; - setRegister_f setReg; - rtems_interrupt_level Irql; - - ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1; - setReg = Console_Port_Tbl[minor]->setRegister; - - /* - * Calculate the baud rate divisor - * - * Assert ensures there is no division by 0. - */ - - baud_requested = t->c_ospeed; - if (!baud_requested) - baud_requested = B9600; /* default to 9600 baud */ - - baud_number = (uint32_t) rtems_termios_baud_to_number( baud_requested ); - _Assert( baud_number != 0 ); - - ulBaudDivisor = Z85C30_Baud( - (uint32_t) Console_Port_Tbl[minor]->ulClock, - baud_number - ); - - wr3 = SCC_WR3_RX_EN; - wr4 = SCC_WR4_16_CLOCK; - wr5 = SCC_WR5_TX_EN; - - /* - * Parity - */ - - if (t->c_cflag & PARENB) { - wr4 |= SCC_WR4_PAR_EN; - if (!(t->c_cflag & PARODD)) - wr4 |= SCC_WR4_PAR_EVEN; - } - - /* - * Character Size - */ - - if (t->c_cflag & CSIZE) { - switch (t->c_cflag & CSIZE) { - case CS5: break; - case CS6: wr3 |= SCC_WR3_RX_6_BITS; wr5 |= SCC_WR5_TX_6_BITS; break; - case CS7: wr3 |= SCC_WR3_RX_7_BITS; wr5 |= SCC_WR5_TX_7_BITS; break; - case CS8: wr3 |= SCC_WR3_RX_8_BITS; wr5 |= SCC_WR5_TX_8_BITS; break; - } - } else { - wr3 |= SCC_WR3_RX_8_BITS; /* default to 9600,8,N,1 */ - wr5 |= SCC_WR5_TX_8_BITS; /* default to 9600,8,N,1 */ - } - - /* - * Stop Bits - */ - - if (t->c_cflag & CSTOPB) { - wr4 |= SCC_WR4_2_STOP; /* 2 stop bits */ - } else { - wr4 |= SCC_WR4_1_STOP; /* 1 stop bits */ - } - - /* - * Now actually set the chip - */ - - rtems_interrupt_disable(Irql); - (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR4, wr4 ); - (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR3, wr3 ); - (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR5, wr5 ); - - /* - * Setup the lower 8 bits time constants=1E. - * If the time constans=1E, then the desire - * baud rate will be equilvalent to 9600, via register 12. - */ - - (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR12, ulBaudDivisor & 0xff ); - - /* - * using register 13 - * Setup the upper 8 bits time constant - */ - - (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR13, (ulBaudDivisor>>8) & 0xff ); - - rtems_interrupt_enable(Irql); - - return 0; -} - -/* - * z85c30_process - * - * This is the per port ISR handler. - */ - -Z85C30_STATIC void z85c30_process( - int minor, - uint8_t ucIntPend -) -{ - uint32_t ulCtrlPort; - volatile uint8_t z85c30_status; - char cChar; - setRegister_f setReg; - getRegister_f getReg; - - ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1; - setReg = Console_Port_Tbl[minor]->setRegister; - getReg = Console_Port_Tbl[minor]->getRegister; - - /* - * Deal with any received characters - */ - - while (ucIntPend&SCC_RR3_B_RX_IP) - { - z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0); - if (!Z85C30_Status_Is_RX_character_available(z85c30_status)) { - break; - } - - /* - * Return the character read. - */ - - cChar = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD8); - - rtems_termios_enqueue_raw_characters( - Console_Port_Data[minor].termios_data, - &cChar, - 1 - ); - } - - /* - * There could be a race condition here if there is not yet a TX - * interrupt pending but the buffer is empty. This condition has - * been seen before on other z8530 drivers but has not been seen - * with this one. The typical solution is to use "vector includes - * status" or to only look at the interrupts actually pending - * in RR3. - */ - - while (true) { - z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0); - if (!Z85C30_Status_Is_TX_buffer_empty(z85c30_status)) { - /* - * We'll get another interrupt when - * the transmitter holding reg. becomes - * free again and we are clear to send - */ - break; - } - -#if 0 - if (!Z85C30_Status_Is_CTS_asserted(z85c30_status)) { - /* - * We can't transmit yet - */ - (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT); - /* - * The next state change of CTS will wake us up - */ - break; - } -#endif - - rtems_termios_dequeue_characters(Console_Port_Data[minor].termios_data, 1); - if (rtems_termios_dequeue_characters( - Console_Port_Data[minor].termios_data, 1)) { - if (Console_Port_Tbl[minor]->pDeviceFlow != &z85c30_flow_RTSCTS) { - z85c30_negate_RTS(minor); - } - Console_Port_Data[minor].bActive = FALSE; - z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR_EXCEPT_TX); - (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT); - break; - } - - } - - if (ucIntPend & SCC_RR3_B_EXT_IP) { - /* - * Clear the external status interrupt - */ - (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT); - z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0); - } - - /* - * Reset interrupts - */ - (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_HI_IUS); -} - -/* - * z85c30_isr - * - * This is the ISR handler for each Z8530. - */ - -Z85C30_STATIC rtems_isr z85c30_isr( - rtems_vector_number vector -) -{ - int minor; - uint32_t ulCtrlPort; - volatile uint8_t ucIntPend; - volatile uint8_t ucIntPendPort; - getRegister_f getReg; - - for (minor=0;minorulIntVector == vector && - Console_Port_Tbl[minor]->deviceType == SERIAL_Z85C30 ) { - ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort2; - getReg = Console_Port_Tbl[minor]->getRegister; - do { - ucIntPend = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD3); - - /* - * If this is channel A select channel A status - */ - - if (ulCtrlPort == Console_Port_Tbl[minor]->ulCtrlPort1) { - ucIntPendPort = ucIntPend >> 3; - ucIntPendPort &= 7; - } else { - ucIntPendPort = ucIntPend &= 7; - } - - if (ucIntPendPort) { - z85c30_process(minor, ucIntPendPort); - } - } while (ucIntPendPort); - } - } -} - -/* - * z85c30_enable_interrupts - * - * This routine enables the specified interrupts for this minor. - */ - -Z85C30_STATIC void z85c30_enable_interrupts( - int minor, - int interrupt_mask -) -{ - uint32_t ulCtrlPort; - setRegister_f setReg; - - ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1; - setReg = Console_Port_Tbl[minor]->setRegister; - - (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR1, interrupt_mask); -} - -/* - * z85c30_initialize_interrupts - * - * This routine initializes the port to use interrupts. - */ - -Z85C30_STATIC void z85c30_initialize_interrupts( - int minor -) -{ - uint32_t ulCtrlPort1; - setRegister_f setReg; - - ulCtrlPort1 = Console_Port_Tbl[minor]->ulCtrlPort1; - setReg = Console_Port_Tbl[minor]->setRegister; - - - z85c30_init(minor); - - Console_Port_Data[minor].bActive=FALSE; - - z85c30_initialize_port( minor ); - - if (Console_Port_Tbl[minor]->pDeviceFlow != &z85c30_flow_RTSCTS) { - z85c30_negate_RTS(minor); - } - -#if (CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE) - set_vector(z85c30_isr, Console_Port_Tbl[minor]->ulIntVector, 1); -#endif - - z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR_EXCEPT_TX); - - (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR2, 0); /* XXX vector */ - (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR9, SCC_WR9_MIE); - - /* - * Reset interrupts - */ - - (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT); -} - -/* - * z85c30_write_support_int - * - * Console Termios output entry point. - * - */ - -Z85C30_STATIC ssize_t z85c30_write_support_int( - int minor, - const char *buf, - size_t len) -{ - uint32_t Irql; - uint32_t ulCtrlPort; - setRegister_f setReg; - - ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1; - setReg = Console_Port_Tbl[minor]->setRegister; - - /* - * We are using interrupt driven output and termios only sends us - * one character at a time. - */ - - if ( !len ) - return 0; - - /* - * Put the character out and enable interrupts if necessary. - */ - - if (Console_Port_Tbl[minor]->pDeviceFlow != &z85c30_flow_RTSCTS) { - z85c30_assert_RTS(minor); - } - rtems_interrupt_disable(Irql); - if ( Console_Port_Data[minor].bActive == FALSE) { - Console_Port_Data[minor].bActive = TRUE; - z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR); - } - (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR8, *buf); - rtems_interrupt_enable(Irql); - - return 0; -} - -/* - * z85c30_inbyte_nonblocking_polled - * - * This routine polls for a character. - */ - -Z85C30_STATIC int z85c30_inbyte_nonblocking_polled( - int minor -) -{ - volatile uint8_t z85c30_status; - uint32_t ulCtrlPort; - getRegister_f getReg; - - ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1; - getReg = Console_Port_Tbl[minor]->getRegister; - - /* - * return -1 if a character is not available. - */ - z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0); - if (!Z85C30_Status_Is_RX_character_available(z85c30_status)) { - return -1; - } - - /* - * Return the character read. - */ - - return (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD8); -} - -/* - * z85c30_write_support_polled - * - * Console Termios output entry point. - * - */ - -Z85C30_STATIC ssize_t z85c30_write_support_polled( - int minor, - const char *buf, - size_t len) -{ - int nwrite=0; - - /* - * poll each byte in the string out of the port. - */ - while (nwrite < len) { - z85c30_write_polled(minor, *buf++); - nwrite++; - } - - /* - * return the number of bytes written. - */ - return nwrite; -} - -/* - * z85c30_write_polled - * - * This routine transmits a character using polling. - */ - -Z85C30_STATIC void z85c30_write_polled( - int minor, - char cChar -) -{ - volatile uint8_t z85c30_status; - uint32_t ulCtrlPort; - getRegister_f getReg; - setRegister_f setReg; - - ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1; - getReg = Console_Port_Tbl[minor]->getRegister; - setReg = Console_Port_Tbl[minor]->setRegister; - - /* - * Wait for the Transmit buffer to indicate that it is empty. - */ - - z85c30_status = (*getReg)( ulCtrlPort, SCC_WR0_SEL_RD0 ); - - while (!Z85C30_Status_Is_TX_buffer_empty(z85c30_status)) { - /* - * Yield while we wait - */ -#if 0 - if (_System_state_Is_up(_System_state_Get())) { - rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); - } -#endif - z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0); - } - - /* - * Write the character. - */ - - (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR8, cChar ); -} diff --git a/c/src/libchip/serial/z85c30_p.h b/c/src/libchip/serial/z85c30_p.h deleted file mode 100644 index af2ed6507c..0000000000 --- a/c/src/libchip/serial/z85c30_p.h +++ /dev/null @@ -1,420 +0,0 @@ -/* - * This include file contains all private driver definitions for the - * Zilog z85c30. - * - * COPYRIGHT (c) 1998 by Radstone Technology - * - * - * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY - * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK - * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. - * - * You are hereby granted permission to use, copy, modify, and distribute - * this file, provided that this notice, plus the above copyright notice - * and disclaimer, appears in all copies. Radstone Technology will provide - * no support for this code. - * - * COPYRIGHT (c) 1989-1997. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may in - * the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#ifndef __Z85C30_P_H -#define __Z85C30_P_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Define Z85C30_STATIC to nothing while debugging so the entry points - * will show up in the symbol table. - */ - -#define Z85C30_STATIC - -/* #define Z85C30_STATIC static */ - -/* bit values for write register 0 */ -/* command register */ - -#define SCC_WR0_SEL_WR0 0x00 -#define SCC_WR0_SEL_WR1 0x01 -#define SCC_WR0_SEL_WR2 0x02 -#define SCC_WR0_SEL_WR3 0x03 -#define SCC_WR0_SEL_WR4 0x04 -#define SCC_WR0_SEL_WR5 0x05 -#define SCC_WR0_SEL_WR6 0x06 -#define SCC_WR0_SEL_WR7 0x07 -#define SCC_WR0_SEL_WR8 0x08 -#define SCC_WR0_SEL_WR9 0x09 -#define SCC_WR0_SEL_WR10 0x0a -#define SCC_WR0_SEL_WR11 0x0b -#define SCC_WR0_SEL_WR12 0x0c -#define SCC_WR0_SEL_WR13 0x0d -#define SCC_WR0_SEL_WR14 0x0e -#define SCC_WR0_SEL_WR15 0x0f -#define SCC_WR0_SEL_RD0 0x00 -#define SCC_WR0_SEL_RD1 0x01 -#define SCC_WR0_SEL_RD2 0x02 -#define SCC_WR0_SEL_RD3 0x03 -#define SCC_WR0_SEL_RD4 0x04 -#define SCC_WR0_SEL_RD5 0x05 -#define SCC_WR0_SEL_RD6 0x06 -#define SCC_WR0_SEL_RD7 0x07 -#define SCC_WR0_SEL_RD8 0x08 -#define SCC_WR0_SEL_RD9 0x09 -#define SCC_WR0_SEL_RD10 0x0a -#define SCC_WR0_SEL_RD11 0x0b -#define SCC_WR0_SEL_RD12 0x0c -#define SCC_WR0_SEL_RD13 0x0d -#define SCC_WR0_SEL_RD14 0x0e -#define SCC_WR0_SEL_RD15 0x0f -#define SCC_WR0_NULL_CODE 0x00 -#define SCC_WR0_RST_INT 0x10 -#define SCC_WR0_SEND_ABORT 0x18 -#define SCC_WR0_EN_INT_RX 0x20 -#define SCC_WR0_RST_TX_INT 0x28 -#define SCC_WR0_ERR_RST 0x30 -#define SCC_WR0_RST_HI_IUS 0x38 -#define SCC_WR0_RST_RX_CRC 0x40 -#define SCC_WR0_RST_TX_CRC 0x80 -#define SCC_WR0_RST_TX_UND 0xc0 - -/* write register 2 */ -/* interrupt vector */ - -/* bit values for write register 1 */ -/* tx/rx interrupt and data transfer mode definition */ - -#define SCC_WR1_EXT_INT_EN 0x01 -#define SCC_WR1_TX_INT_EN 0x02 -#define SCC_WR1_PARITY 0x04 -#define SCC_WR1_RX_INT_DIS 0x00 -#define SCC_WR1_RX_INT_FIR 0x08 -#define SCC_WR1_INT_ALL_RX 0x10 -#define SCC_WR1_RX_INT_SPE 0x18 -#define SCC_WR1_RDMA_RECTR 0x20 -#define SCC_WR1_RDMA_FUNC 0x40 -#define SCC_WR1_RDMA_EN 0x80 - -#define SCC_ENABLE_ALL_INTR \ - (SCC_WR1_EXT_INT_EN | SCC_WR1_TX_INT_EN | SCC_WR1_INT_ALL_RX) - -#define SCC_DISABLE_ALL_INTR 0x00 - -#define SCC_ENABLE_ALL_INTR_EXCEPT_TX \ - (SCC_WR1_EXT_INT_EN | SCC_WR1_INT_ALL_RX) - -/* bit values for write register 3 */ -/* receive parameters and control */ - -#define SCC_WR3_RX_EN 0x01 -#define SCC_WR3_SYNC_CHAR 0x02 -#define SCC_WR3_ADR_SEARCH 0x04 -#define SCC_WR3_RX_CRC_EN 0x08 -#define SCC_WR3_ENTER_HUNT 0x10 -#define SCC_WR3_AUTO_EN 0x20 -#define SCC_WR3_RX_5_BITS 0x00 -#define SCC_WR3_RX_7_BITS 0x40 -#define SCC_WR3_RX_6_BITS 0x80 -#define SCC_WR3_RX_8_BITS 0xc0 - -/* bit values for write register 4 */ -/* tx/rx misc parameters and modes */ - -#define SCC_WR4_PAR_EN 0x01 -#define SCC_WR4_PAR_EVEN 0x02 -#define SCC_WR4_SYNC_EN 0x00 -#define SCC_WR4_1_STOP 0x04 -#define SCC_WR4_2_STOP 0x0c -#define SCC_WR4_8_SYNC 0x00 -#define SCC_WR4_16_SYNC 0x10 -#define SCC_WR4_SDLC 0x20 -#define SCC_WR4_EXT_SYNC 0x30 -#define SCC_WR4_1_CLOCK 0x00 -#define SCC_WR4_16_CLOCK 0x40 -#define SCC_WR4_32_CLOCK 0x80 -#define SCC_WR4_64_CLOCK 0xc0 - -/* bit values for write register 5 */ -/* transmit parameter and controls */ - -#define SCC_WR5_TX_CRC_EN 0x01 -#define SCC_WR5_RTS 0x02 -#define SCC_WR5_SDLC 0x04 -#define SCC_WR5_TX_EN 0x08 -#define SCC_WR5_SEND_BRK 0x10 - -#define SCC_WR5_TX_5_BITS 0x00 -#define SCC_WR5_TX_7_BITS 0x20 -#define SCC_WR5_TX_6_BITS 0x40 -#define SCC_WR5_TX_8_BITS 0x60 -#define SCC_WR5_DTR 0x80 - -/* write register 6 */ -/* sync chars or sdlc address field */ - -/* write register 7 */ -/* sync char or sdlc flag */ - -/* write register 8 */ -/* transmit buffer */ - -/* bit values for write register 9 */ -/* master interrupt control */ - -#define SCC_WR9_VIS 0x01 -#define SCC_WR9_NV 0x02 -#define SCC_WR9_DLC 0x04 -#define SCC_WR9_MIE 0x08 -#define SCC_WR9_STATUS_HI 0x10 -#define SCC_WR9_NO_RST 0x00 -#define SCC_WR9_CH_B_RST 0x40 -#define SCC_WR9_CH_A_RST 0x80 -#define SCC_WR9_HDWR_RST 0xc0 - -/* bit values for write register 10 */ -/* misc tx/rx control bits */ - -#define SCC_WR10_6_BIT_SYNC 0x01 -#define SCC_WR10_LOOP_MODE 0x02 -#define SCC_WR10_ABORT_UND 0x04 -#define SCC_WR10_MARK_IDLE 0x08 -#define SCC_WR10_ACT_POLL 0x10 -#define SCC_WR10_NRZ 0x00 -#define SCC_WR10_NRZI 0x20 -#define SCC_WR10_FM1 0x40 -#define SCC_WR10_FM0 0x60 -#define SCC_WR10_CRC_PRESET 0x80 - -/* bit values for write register 11 */ -/* clock mode control */ - -#define SCC_WR11_OUT_XTAL 0x00 -#define SCC_WR11_OUT_TX_CLK 0x01 -#define SCC_WR11_OUT_BR_GEN 0x02 -#define SCC_WR11_OUT_DPLL 0x03 -#define SCC_WR11_TRXC_OI 0x04 -#define SCC_WR11_TX_RTXC 0x00 -#define SCC_WR11_TX_TRXC 0x08 -#define SCC_WR11_TX_BR_GEN 0x10 -#define SCC_WR11_TX_DPLL 0x18 -#define SCC_WR11_RX_RTXC 0x00 -#define SCC_WR11_RX_TRXC 0x20 -#define SCC_WR11_RX_BR_GEN 0x40 -#define SCC_WR11_RX_DPLL 0x60 -#define SCC_WR11_RTXC_XTAL 0x80 - -/* write register 12 */ -/* lower byte of baud rate generator time constant */ - -/* write register 13 */ -/* upper byte of baud rate generator time constant */ - -/* bit values for write register 14 */ -/* misc control bits */ - -#define SCC_WR14_BR_EN 0x01 -#define SCC_WR14_BR_SRC 0x02 -#define SCC_WR14_DTR_FUNC 0x04 -#define SCC_WR14_AUTO_ECHO 0x08 -#define SCC_WR14_LCL_LOOP 0x10 -#define SCC_WR14_NULL 0x00 -#define SCC_WR14_SEARCH 0x20 -#define SCC_WR14_RST_CLK 0x40 -#define SCC_WR14_DIS_DPLL 0x60 -#define SCC_WR14_SRC_BR 0x80 -#define SCC_WR14_SRC_RTXC 0xa0 -#define SCC_WR14_FM_MODE 0xc0 -#define SCC_WR14_NRZI 0xe0 - -/* bit values for write register 15 */ -/* external/status interrupt control */ - -#define SCC_WR15_ZERO_CNT 0x02 -#define SCC_WR15_CD_IE 0x08 -#define SCC_WR15_SYNC_IE 0x10 -#define SCC_WR15_CTS_IE 0x20 -#define SCC_WR15_TX_UND_IE 0x40 -#define SCC_WR15_BREAK_IE 0x80 - -/* bit values for read register 0 */ -/* tx/rx buffer status and external status */ - -#define SCC_RR0_RX_AVAIL 0x01 -#define SCC_RR0_ZERO_CNT 0x02 -#define SCC_RR0_TX_EMPTY 0x04 -#define SCC_RR0_CD 0x08 -#define SCC_RR0_SYNC 0x10 -#define SCC_RR0_CTS 0x20 -#define SCC_RR0_TX_UND 0x40 -#define SCC_RR0_BREAK 0x80 - -/* bit values for read register 1 */ - -#define SCC_RR1_ALL_SENT 0x01 -#define SCC_RR1_RES_CD_2 0x02 -#define SCC_RR1_RES_CD_1 0x01 -#define SCC_RR1_RES_CD_0 0x08 -#define SCC_RR1_PAR_ERR 0x10 -#define SCC_RR1_RX_OV_ERR 0x20 -#define SCC_RR1_CRC_ERR 0x40 -#define SCC_RR1_END_FRAME 0x80 - -/* read register 2 */ -/* interrupt vector */ - -/* bit values for read register 3 */ -/* interrupt pending register */ - -#define SCC_RR3_B_EXT_IP 0x01 -#define SCC_RR3_B_TX_IP 0x02 -#define SCC_RR3_B_RX_IP 0x04 -#define SCC_RR3_A_EXT_IP 0x08 -#define SCC_RR3_A_TX_IP 0x10 -#define SCC_RR3_A_RX_IP 0x20 - -/* read register 8 */ -/* receive data register */ - -/* bit values for read register 10 */ -/* misc status bits */ - -#define SCC_RR10_ON_LOOP 0x02 -#define SCC_RR10_LOOP_SEND 0x10 -#define SCC_RR10_2_CLK_MIS 0x40 -#define SCC_RR10_1_CLK_MIS 0x80 - -/* read register 12 */ -/* lower byte of time constant */ - -/* read register 13 */ -/* upper byte of time constant */ - -/* bit values for read register 15 */ -/* external/status ie bits */ - -#define SCC_RR15_ZERO_CNT 0x02 -#define SCC_RR15_CD_IE 0x08 -#define SCC_RR15_SYNC_IE 0x10 -#define SCC_RR15_CTS_IE 0x20 -#define SCC_RR15_TX_UND_IE 0x40 -#define SCC_RR15_BREAK_IE 0x80 - -typedef struct _z85c30_context -{ - uint8_t ucModemCtrl; -} z85c30_context; - -/* - * The following macro calculates the Baud constant. For the Z85C30 chip. - * - * Note: baud constant = ((clock frequency / Clock_X) / (2 * Baud Rate)) - 2 - * eg ((10,000,000 / 16) / (2 * Baud Rate)) - 2 - */ - -#define Z85C30_Baud( _clock, _baud_rate ) \ - ( ((_clock) /( 16 * 2 * _baud_rate)) - 2) - -#define Z85C30_Status_Is_RX_character_available(_status) \ - ((_status) & SCC_RR0_RX_AVAIL) - -#define Z85C30_Status_Is_TX_buffer_empty(_status) \ - ((_status) & SCC_RR0_TX_EMPTY) - -#define Z85C30_Status_Is_CTS_asserted(_status) \ - ((_status) & SCC_RR0_CTS) - -#define Z85C30_Status_Is_break_abort(_status) \ - ((_status) & SCC_RR0_BREAK) - -/* - * Private routines - */ - -Z85C30_STATIC void z85c30_initialize_port( - int minor -); - -Z85C30_STATIC void z85c30_init(int minor); - -Z85C30_STATIC int z85c30_set_attributes( - int minor, - const struct termios *t -); - -Z85C30_STATIC int z85c30_open( - int major, - int minor, - void * arg -); - -Z85C30_STATIC int z85c30_close( - int major, - int minor, - void * arg -); - -Z85C30_STATIC void z85c30_write_polled( - int minor, - char cChar -); - -Z85C30_STATIC int z85c30_assert_RTS( - int minor -); - -Z85C30_STATIC int z85c30_negate_RTS( - int minor -); - -Z85C30_STATIC int z85c30_assert_DTR( - int minor -); - -Z85C30_STATIC int z85c30_negate_DTR( - int minor -); - -Z85C30_STATIC void z85c30_initialize_interrupts(int minor); - -Z85C30_STATIC ssize_t z85c30_write_support_int( - int minor, - const char *buf, - size_t len -); - -Z85C30_STATIC ssize_t z85c30_write_support_polled( - int minor, - const char *buf, - size_t len -); - -Z85C30_STATIC int z85c30_inbyte_nonblocking_polled( - int minor -); - -Z85C30_STATIC void z85c30_enable_interrupts( - int minor, - int interrupt_mask -); - -Z85C30_STATIC void z85c30_process( - int minor, - uint8_t ucIntPend -); - -Z85C30_STATIC rtems_isr z85c30_isr( - rtems_vector_number vector -); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/c/src/libchip/serial/z85c30_reg.c b/c/src/libchip/serial/z85c30_reg.c deleted file mode 100644 index 6e7b5d3494..0000000000 --- a/c/src/libchip/serial/z85c30_reg.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * This file contains a typical set of register access routines which may be - * used with the z85c30 chip if accesses to the chip are as follows: - * - * + registers are accessed as bytes - * - * COPYRIGHT (c) 1989-1997. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -#include - -#ifndef _Z85C30_MULTIPLIER -#define _Z85C30_MULTIPLIER 1 -#define _Z85C30_NAME(_X) _X -#define _Z85C30_TYPE uint8_t -#endif - -/* - * Z85C30 Get Register Routine - */ - -uint8_t _Z85C30_NAME(z85c30_get_register)( - uintptr_t ulCtrlPort, - uint8_t ucRegNum -) -{ - _Z85C30_TYPE *port; - uint8_t data; - rtems_interrupt_level level; - - port = (_Z85C30_TYPE *)ulCtrlPort; - - rtems_interrupt_disable(level); - - if(ucRegNum) { - *port = ucRegNum; - } - data = *port; - rtems_interrupt_enable(level); - - return data; -} - -/* - * Z85C30 Set Register Routine - */ - -void _Z85C30_NAME(z85c30_set_register)( - uintptr_t ulCtrlPort, - uint8_t ucRegNum, - uint8_t ucData -) -{ - _Z85C30_TYPE *port; - rtems_interrupt_level level; - - port = (_Z85C30_TYPE *)ulCtrlPort; - - rtems_interrupt_disable(level); - if(ucRegNum) { - *port = ucRegNum; - } - *port = ucData; - rtems_interrupt_enable(level); -} -- cgit v1.2.3