From: "Mikael Starvik" - Lots of fixes from 2.4. - Updated for 2.6.6. - Added IDE driver Signed-off-by: Andrew Morton --- /dev/null | 127 - 25-akpm/arch/cris/Kconfig | 76 - 25-akpm/arch/cris/Makefile | 10 25-akpm/arch/cris/arch-v10/boot/compressed/misc.c | 4 25-akpm/arch/cris/arch-v10/defconfig | 1 25-akpm/arch/cris/arch-v10/drivers/Kconfig | 216 ++- 25-akpm/arch/cris/arch-v10/drivers/Makefile | 2 25-akpm/arch/cris/arch-v10/drivers/axisflashmap.c | 61 25-akpm/arch/cris/arch-v10/drivers/ds1302.c | 94 - 25-akpm/arch/cris/arch-v10/drivers/eeprom.c | 7 25-akpm/arch/cris/arch-v10/drivers/ethernet.c | 303 +++- 25-akpm/arch/cris/arch-v10/drivers/gpio.c | 84 - 25-akpm/arch/cris/arch-v10/drivers/i2c.c | 78 + 25-akpm/arch/cris/arch-v10/drivers/i2c.h | 4 25-akpm/arch/cris/arch-v10/drivers/ide.c | 945 ++++++++++++++ 25-akpm/arch/cris/arch-v10/drivers/pcf8563.c | 72 - 25-akpm/arch/cris/arch-v10/drivers/serial.c | 1436 ++++++++++++++++++---- 25-akpm/arch/cris/arch-v10/drivers/serial.h | 20 25-akpm/arch/cris/arch-v10/kernel/debugport.c | 152 -- 25-akpm/arch/cris/arch-v10/kernel/entry.S | 21 25-akpm/arch/cris/arch-v10/kernel/fasttimer.c | 17 25-akpm/arch/cris/arch-v10/kernel/head.S | 31 25-akpm/arch/cris/arch-v10/kernel/process.c | 19 25-akpm/arch/cris/arch-v10/kernel/ptrace.c | 59 25-akpm/arch/cris/arch-v10/kernel/setup.c | 9 25-akpm/arch/cris/arch-v10/kernel/signal.c | 4 25-akpm/arch/cris/arch-v10/kernel/time.c | 8 25-akpm/arch/cris/arch-v10/lib/dram_init.S | 10 25-akpm/arch/cris/arch-v10/lib/old_checksum.c | 4 25-akpm/arch/cris/arch-v10/mm/fault.c | 36 25-akpm/arch/cris/arch-v10/mm/tlb.c | 2 25-akpm/arch/cris/defconfig | 583 +++++--- 25-akpm/arch/cris/kernel/Makefile | 6 25-akpm/arch/cris/kernel/crisksyms.c | 104 + 25-akpm/arch/cris/kernel/irq.c | 21 25-akpm/arch/cris/kernel/module.c | 25 25-akpm/arch/cris/kernel/process.c | 26 25-akpm/arch/cris/kernel/setup.c | 21 25-akpm/arch/cris/kernel/sys_cris.c | 2 25-akpm/arch/cris/kernel/time.c | 74 - 25-akpm/arch/cris/kernel/traps.c | 3 25-akpm/arch/cris/mm/fault.c | 26 25-akpm/arch/cris/mm/init.c | 25 25-akpm/arch/cris/mm/ioremap.c | 25 25-akpm/include/asm-cris/arch-v10/cache.h | 1 25-akpm/include/asm-cris/arch-v10/irq.h | 5 25-akpm/include/asm-cris/arch-v10/offset.h | 2 25-akpm/include/asm-cris/bitops.h | 46 25-akpm/include/asm-cris/dma-mapping.h | 126 + 25-akpm/include/asm-cris/fasttimer.h | 4 25-akpm/include/asm-cris/io.h | 2 25-akpm/include/asm-cris/ioctl.h | 13 25-akpm/include/asm-cris/local.h | 1 25-akpm/include/asm-cris/page.h | 11 25-akpm/include/asm-cris/pci.h | 4 25-akpm/include/asm-cris/pgtable.h | 10 25-akpm/include/asm-cris/ptrace.h | 2 25-akpm/include/asm-cris/rtc.h | 4 25-akpm/include/asm-cris/sections.h | 7 25-akpm/include/asm-cris/semaphore-helper.h | 4 25-akpm/include/asm-cris/semaphore.h | 12 25-akpm/include/asm-cris/termbits.h | 2 25-akpm/include/asm-cris/types.h | 1 25-akpm/include/asm-cris/unistd.h | 16 64 files changed, 4012 insertions(+), 1114 deletions(-) diff -puN arch/cris/arch-v10/boot/compressed/misc.c~cris-architecture-update arch/cris/arch-v10/boot/compressed/misc.c --- 25/arch/cris/arch-v10/boot/compressed/misc.c~cris-architecture-update 2004-06-01 01:09:29.038985056 -0700 +++ 25-akpm/arch/cris/arch-v10/boot/compressed/misc.c 2004-06-01 01:09:29.121972440 -0700 @@ -1,7 +1,7 @@ /* * misc.c * - * $Id: misc.c,v 1.4 2003/04/09 05:20:45 starvik Exp $ + * $Id: misc.c,v 1.6 2003/10/27 08:04:31 starvik Exp $ * * This is a collection of several routines from gzip-1.0.3 * adapted for Linux. @@ -263,7 +263,7 @@ decompress_kernel() __asm__ volatile ("move vr,%0" : "=rm" (revision)); if (revision < 10) { - puts("You need an ETRAX 100LX to run linux 2.4\n"); + puts("You need an ETRAX 100LX to run linux 2.6\n"); while(1); } diff -puN arch/cris/arch-v10/defconfig~cris-architecture-update arch/cris/arch-v10/defconfig --- 25/arch/cris/arch-v10/defconfig~cris-architecture-update 2004-06-01 01:09:29.039984904 -0700 +++ 25-akpm/arch/cris/arch-v10/defconfig 2004-06-01 01:09:29.121972440 -0700 @@ -267,6 +267,7 @@ CONFIG_INET=y # CONFIG_BLK_DEV_ISAPNP is not set # CONFIG_IDE_CHIPSETS is not set # CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_IDE_MODES is not set # # SCSI support diff -puN arch/cris/arch-v10/drivers/axisflashmap.c~cris-architecture-update arch/cris/arch-v10/drivers/axisflashmap.c --- 25/arch/cris/arch-v10/drivers/axisflashmap.c~cris-architecture-update 2004-06-01 01:09:29.040984752 -0700 +++ 25-akpm/arch/cris/arch-v10/drivers/axisflashmap.c 2004-06-01 01:09:29.123972136 -0700 @@ -11,6 +11,9 @@ * partition split defined below. * * $Log: axisflashmap.c,v $ + * Revision 1.8 2004/05/14 07:58:03 starvik + * Merge of changes from 2.4 + * * Revision 1.6 2003/07/04 08:27:37 starvik * Merge of Linux 2.5.74 * @@ -153,6 +156,9 @@ /* From head.S */ extern unsigned long romfs_start, romfs_length, romfs_in_flash; +/* The master mtd for the entire flash. */ +struct mtd_info* axisflash_mtd = NULL; + /* Map driver functions. */ static __u8 flash_read8(struct map_info *map, unsigned long ofs) @@ -314,7 +320,8 @@ static struct mtd_info *probe_cs(struct { struct mtd_info *mtd_cs = NULL; - printk("%s: Probing a 0x%08lx bytes large window at 0x%08lx.\n", + printk(KERN_INFO + "%s: Probing a 0x%08lx bytes large window at 0x%08lx.\n", map_cs->name, map_cs->size, map_cs->map_priv_1); #ifdef CONFIG_MTD_AMDSTD @@ -398,7 +405,7 @@ static int __init init_axis_flash(void) struct mtd_info *mymtd; int err = 0; int pidx = 0; - struct partitiontable_head *ptable_head; + struct partitiontable_head *ptable_head = NULL; struct partitiontable_entry *ptable; int use_default_ptable = 1; /* Until proven otherwise. */ const char *pmsg = " /dev/flash%d at 0x%08x, size 0x%08x\n"; @@ -407,19 +414,22 @@ static int __init init_axis_flash(void) /* There's no reason to use this module if no flash chip can * be identified. Make sure that's understood. */ - panic("axisflashmap found no flash chip!\n"); + printk(KERN_INFO "axisflashmap: Found no flash chip.\n"); + } else { + printk(KERN_INFO "%s: 0x%08x bytes of flash memory.\n", + mymtd->name, mymtd->size); + axisflash_mtd = mymtd; } - printk("%s: 0x%08x bytes of flash memory.\n", - mymtd->name, mymtd->size); - - mymtd->owner = THIS_MODULE; - - ptable_head = (struct partitiontable_head *)(FLASH_CACHED_ADDR + - CONFIG_ETRAX_PTABLE_SECTOR + PARTITION_TABLE_OFFSET); + if (mymtd) { + mymtd->owner = THIS_MODULE; + ptable_head = (struct partitiontable_head *)(FLASH_CACHED_ADDR + + CONFIG_ETRAX_PTABLE_SECTOR + + PARTITION_TABLE_OFFSET); + } pidx++; /* First partition is always set to the default. */ - if ((ptable_head->magic == PARTITION_TABLE_MAGIC) + if (ptable_head && (ptable_head->magic == PARTITION_TABLE_MAGIC) && (ptable_head->size < (MAX_PARTITIONS * sizeof(struct partitiontable_entry) + PARTITIONTABLE_END_MARKER_SIZE)) @@ -454,7 +464,7 @@ static int __init init_axis_flash(void) ptable_ok = (csum == ptable_head->checksum); /* Read the entries and use/show the info. */ - printk(" Found a%s partition table at 0x%p-0x%p.\n", + printk(KERN_INFO " Found a%s partition table at 0x%p-0x%p.\n", (ptable_ok ? " valid" : "n invalid"), ptable_head, max_addr); @@ -486,22 +496,25 @@ static int __init init_axis_flash(void) axis_partitions[pidx].offset = romfs_start - FLASH_CACHED_ADDR; axis_partitions[pidx].mask_flags |= MTD_WRITEABLE; - printk(" Adding readonly flash partition for romfs image:\n"); + printk(KERN_INFO + " Adding readonly flash partition for romfs image:\n"); printk(pmsg, pidx, axis_partitions[pidx].offset, axis_partitions[pidx].size); pidx++; } - if (use_default_ptable) { - printk(" Using default partition table.\n"); - err = add_mtd_partitions(mymtd, axis_default_partitions, - NUM_DEFAULT_PARTITIONS); - } else { - err = add_mtd_partitions(mymtd, axis_partitions, pidx); - } + if (mymtd) { + if (use_default_ptable) { + printk(KERN_INFO " Using default partition table.\n"); + err = add_mtd_partitions(mymtd, axis_default_partitions, + NUM_DEFAULT_PARTITIONS); + } else { + err = add_mtd_partitions(mymtd, axis_partitions, pidx); + } - if (err) { - panic("axisflashmap could not add MTD partitions!\n"); + if (err) { + panic("axisflashmap could not add MTD partitions!\n"); + } } if (!romfs_in_flash) { @@ -522,7 +535,7 @@ static int __init init_axis_flash(void) "mtd_info!\n"); } - printk(" Adding RAM partition for romfs image:\n"); + printk(KERN_INFO " Adding RAM partition for romfs image:\n"); printk(pmsg, pidx, romfs_start, romfs_length); err = mtdram_init_device(mtd_ram, (void*)romfs_start, @@ -539,3 +552,5 @@ static int __init init_axis_flash(void) /* This adds the above to the kernels init-call chain. */ module_init(init_axis_flash); + +EXPORT_SYMBOL(axisflash_mtd); diff -puN arch/cris/arch-v10/drivers/ds1302.c~cris-architecture-update arch/cris/arch-v10/drivers/ds1302.c --- 25/arch/cris/arch-v10/drivers/ds1302.c~cris-architecture-update 2004-06-01 01:09:29.042984448 -0700 +++ 25-akpm/arch/cris/arch-v10/drivers/ds1302.c 2004-06-01 01:09:29.124971984 -0700 @@ -4,9 +4,18 @@ *! *! DESCRIPTION: Implements an interface for the DS1302 RTC through Etrax I/O *! -*! Functions exported: ds1302_readreg, ds1302_writereg, ds1302_init, get_rtc_status +*! Functions exported: ds1302_readreg, ds1302_writereg, ds1302_init *! *! $Log: ds1302.c,v $ +*! Revision 1.13 2004/05/28 09:26:59 starvik +*! Modified I2C initialization to work in 2.6. +*! +*! Revision 1.12 2004/05/14 07:58:03 starvik +*! Merge of changes from 2.4 +*! +*! Revision 1.10 2004/02/04 09:25:12 starvik +*! Merge of Linux 2.6.2 +*! *! Revision 1.9 2003/07/04 08:27:37 starvik *! Merge of Linux 2.5.74 *! @@ -114,7 +123,7 @@ *! *! (C) Copyright 1999, 2000, 2001 Axis Communications AB, LUND, SWEDEN *! -*! $Id: ds1302.c,v 1.9 2003/07/04 08:27:37 starvik Exp $ +*! $Id: ds1302.c,v 1.13 2004/05/28 09:26:59 starvik Exp $ *! *!***************************************************************************/ @@ -283,12 +292,23 @@ ds1302_readreg(int reg) void ds1302_writereg(int reg, unsigned char val) { - ds1302_wenable(); - start(); - out_byte(0x80 | (reg << 1)); /* write register */ - out_byte(val); - stop(); - ds1302_wdisable(); +#ifndef CONFIG_ETRAX_RTC_READONLY + int do_writereg = 1; +#else + int do_writereg = 0; + + if (reg == RTC_TRICKLECHARGER) + do_writereg = 1; +#endif + + if (do_writereg) { + ds1302_wenable(); + start(); + out_byte(0x80 | (reg << 1)); /* write register */ + out_byte(val); + stop(); + ds1302_wdisable(); + } } void @@ -426,20 +446,33 @@ rtc_ioctl(struct inode *inode, struct fi tcs_val = RTC_TCR_PATTERN | (tcs_val & 0x0F); ds1302_writereg(RTC_TRICKLECHARGER, tcs_val); return 0; - } + } + case RTC_VLOW_RD: + { + /* TODO: + * Implement voltage low detection support + */ + printk(KERN_WARNING "DS1302: RTC Voltage Low detection" + " is not supported\n"); + return 0; + } + case RTC_VLOW_SET: + { + /* TODO: + * Nothing to do since Voltage Low detection is not supported + */ + return 0; + } default: return -ENOIOCTLCMD; } } -int -get_rtc_status(char *buf) +static void +print_rtc_status(void) { - char *p; struct rtc_time tm; - p = buf; - get_rtc_time(&tm); /* @@ -447,16 +480,12 @@ get_rtc_status(char *buf) * time or for Universal Standard Time (GMT). Probably local though. */ - p += sprintf(p, - "rtc_time\t: %02d:%02d:%02d\n" - "rtc_date\t: %04d-%02d-%02d\n", - tm.tm_hour, tm.tm_min, tm.tm_sec, - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); - - return p - buf; + printk(KERN_INFO "rtc_time\t: %02d:%02d:%02d\n", + tm.tm_hour, tm.tm_min, tm.tm_sec); + printk(KERN_INFO "rtc_date\t: %04d-%02d-%02d\n", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); } - /* The various file operations we support. */ static struct file_operations rtc_fops = { @@ -487,11 +516,10 @@ ds1302_probe(void) out_byte(0xc1); /* read RAM byte 0 */ if((res = in_byte()) == MAGIC_PATTERN) { - char buf[100]; stop(); ds1302_wdisable(); - printk("%s: RTC found.\n", ds1302_name); - printk("%s: SDA, SCL, RST on PB%i, PB%i, %s%i\n", + printk(KERN_INFO "%s: RTC found.\n", ds1302_name); + printk(KERN_INFO "%s: SDA, SCL, RST on PB%i, PB%i, %s%i\n", ds1302_name, CONFIG_ETRAX_DS1302_SDABIT, CONFIG_ETRAX_DS1302_SCLBIT, @@ -501,12 +529,10 @@ ds1302_probe(void) "PB", #endif CONFIG_ETRAX_DS1302_RSTBIT); - get_rtc_status(buf); - printk(buf); + print_rtc_status(); retval = 1; } else { stop(); - printk("%s: RTC not found.\n", ds1302_name); retval = 0; } @@ -518,7 +544,9 @@ ds1302_probe(void) int __init ds1302_init(void) -{ +{ + i2c_init(); + if (!ds1302_probe()) { #ifdef CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT #if CONFIG_ETRAX_DS1302_RSTBIT == 27 @@ -539,16 +567,20 @@ ds1302_init(void) (IO_STATE(R_GEN_CONFIG, g0dir, out))); *R_GEN_CONFIG = genconfig_shadow; #endif - if (!ds1302_probe()) + if (!ds1302_probe()) { + printk(KERN_WARNING "%s: RTC not found.\n", ds1302_name); return -1; + } #else + printk(KERN_WARNING "%s: RTC not found.\n", ds1302_name); return -1; #endif } - /* Initialise trickle charger */ ds1302_writereg(RTC_TRICKLECHARGER, RTC_TCR_PATTERN |(CONFIG_ETRAX_DS1302_TRICKLE_CHARGE & 0x0F)); + /* Start clock by resetting CLOCK_HALT */ + ds1302_writereg(RTC_SECONDS, (ds1302_readreg(RTC_SECONDS) & 0x7F)); return 0; } diff -puN arch/cris/arch-v10/drivers/eeprom.c~cris-architecture-update arch/cris/arch-v10/drivers/eeprom.c --- 25/arch/cris/arch-v10/drivers/eeprom.c~cris-architecture-update 2004-06-01 01:09:29.044984144 -0700 +++ 25-akpm/arch/cris/arch-v10/drivers/eeprom.c 2004-06-01 01:09:29.125971832 -0700 @@ -20,6 +20,9 @@ *! in the spin-lock. *! *! $Log: eeprom.c,v $ +*! Revision 1.10 2003/09/11 07:29:48 starvik +*! Merge of Linux 2.6.0-test5 +*! *! Revision 1.9 2003/07/04 08:27:37 starvik *! Merge of Linux 2.5.74 *! @@ -441,9 +444,9 @@ int __init eeprom_init(void) static int eeprom_open(struct inode * inode, struct file * file) { - if(iminor(inode) != EEPROM_MINOR_NR) + if(MINOR(inode->i_rdev) != EEPROM_MINOR_NR) return -ENXIO; - if(imajor(inode) != EEPROM_MAJOR_NR) + if(MAJOR(inode->i_rdev) != EEPROM_MAJOR_NR) return -ENXIO; if( eeprom.size > 0 ) diff -puN arch/cris/arch-v10/drivers/ethernet.c~cris-architecture-update arch/cris/arch-v10/drivers/ethernet.c --- 25/arch/cris/arch-v10/drivers/ethernet.c~cris-architecture-update 2004-06-01 01:09:29.045983992 -0700 +++ 25-akpm/arch/cris/arch-v10/drivers/ethernet.c 2004-06-01 01:09:29.129971224 -0700 @@ -1,4 +1,4 @@ -/* $Id: ethernet.c,v 1.17 2003/07/04 08:27:37 starvik Exp $ +/* $Id: ethernet.c,v 1.22 2004/05/14 07:58:03 starvik Exp $ * * e100net.c: A network driver for the ETRAX 100LX network controller. * @@ -7,6 +7,15 @@ * The outline of this driver comes from skeleton.c. * * $Log: ethernet.c,v $ + * Revision 1.22 2004/05/14 07:58:03 starvik + * Merge of changes from 2.4 + * + * Revision 1.20 2004/03/11 11:38:40 starvik + * Merge of Linux 2.6.4 + * + * Revision 1.18 2003/12/03 13:45:46 starvik + * Use hardware pad for short packets to prevent information leakage. + * * Revision 1.17 2003/07/04 08:27:37 starvik * Merge of Linux 2.5.74 * @@ -258,6 +267,16 @@ typedef struct etrax_eth_descr struct sk_buff* skb; } etrax_eth_descr; +/* Some transceivers requires special handling */ +struct transceiver_ops +{ + unsigned int oui; + void (*check_speed)(void); + void (*check_duplex)(void); +}; + +struct transceiver_ops* transceiver; + /* Duplex settings */ enum duplex { @@ -278,10 +297,17 @@ enum duplex */ #define MDIO_BASE_STATUS_REG 0x1 #define MDIO_BASE_CONTROL_REG 0x0 +#define MDIO_PHY_ID_HIGH_REG 0x2 +#define MDIO_PHY_ID_LOW_REG 0x3 #define MDIO_BC_NEGOTIATE 0x0200 #define MDIO_BC_FULL_DUPLEX_MASK 0x0100 #define MDIO_BC_AUTO_NEG_MASK 0x1000 #define MDIO_BC_SPEED_SELECT_MASK 0x2000 +#define MDIO_STATUS_100_FD 0x4000 +#define MDIO_STATUS_100_HD 0x2000 +#define MDIO_STATUS_10_FD 0x1000 +#define MDIO_STATUS_10_HD 0x0800 +#define MDIO_STATUS_SPEED_DUPLEX_MASK 0x7800 #define MDIO_ADVERTISMENT_REG 0x4 #define MDIO_ADVERT_100_FD 0x100 #define MDIO_ADVERT_100_HD 0x080 @@ -295,9 +321,13 @@ enum duplex /* Broadcom specific */ #define MDIO_AUX_CTRL_STATUS_REG 0x18 -#define MDIO_FULL_DUPLEX_IND 0x1 -#define MDIO_SPEED 0x2 -#define MDIO_PHYS_ADDR 0x0 +#define MDIO_BC_FULL_DUPLEX_IND 0x1 +#define MDIO_BC_SPEED 0x2 + +/* TDK specific */ +#define MDIO_TDK_DIAGNOSTIC_REG 18 +#define MDIO_TDK_DIAGNOSTIC_RATE 0x400 +#define MDIO_TDK_DIAGNOSTIC_DPLX 0x800 /* Network flash constants */ #define NET_FLASH_TIME (HZ/50) /* 20 ms */ @@ -341,6 +371,9 @@ static etrax_eth_descr* myNextTxDesc; / static etrax_eth_descr TxDescList[NBR_OF_TX_DESC] __attribute__ ((aligned(32))); static unsigned int network_rec_config_shadow = 0; +static unsigned int mdio_phy_addr; /* Transciever address */ + +static unsigned int network_tr_ctrl_shadow = 0; /* Network speed indication. */ static struct timer_list speed_timer = TIMER_INITIALIZER(NULL, 0, 0); @@ -376,6 +409,7 @@ static void set_multicast_list(struct ne static void e100_hardware_send_packet(char *buf, int length); static void update_rx_stats(struct net_device_stats *); static void update_tx_stats(struct net_device_stats *); +static int e100_probe_transceiver(void); static void e100_check_speed(unsigned long dummy); static void e100_set_speed(unsigned long speed); @@ -393,6 +427,21 @@ static void e100_reset_transceiver(void) static void e100_clear_network_leds(unsigned long dummy); static void e100_set_network_leds(int active); +static void broadcom_check_speed(void); +static void broadcom_check_duplex(void); +static void tdk_check_speed(void); +static void tdk_check_duplex(void); +static void generic_check_speed(void); +static void generic_check_duplex(void); + +struct transceiver_ops transceivers[] = +{ + {0x1018, broadcom_check_speed, broadcom_check_duplex}, /* Broadcom */ + {0xC039, tdk_check_speed, tdk_check_duplex}, /* TDK 2120 */ + {0x039C, tdk_check_speed, tdk_check_duplex}, /* TDK 2120C */ + {0x0000, generic_check_speed, generic_check_duplex} /* Generic, must be last */ +}; + #define tx_done(dev) (*R_DMA_CH0_CMD == 0) /* @@ -409,7 +458,8 @@ etrax_ethernet_init(void) struct net_device *dev; int i, err; - printk("ETRAX 100LX 10/100MBit ethernet v2.0 (c) 2000-2003 Axis Communications AB\n"); + printk(KERN_INFO + "ETRAX 100LX 10/100MBit ethernet v2.0 (c) 2000-2003 Axis Communications AB\n"); dev = alloc_etherdev(sizeof(struct net_local)); if (!dev) @@ -496,7 +546,6 @@ etrax_ethernet_init(void) current_speed_selection = 0; /* Auto */ speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL; speed_timer.function = e100_check_speed; - add_timer(&speed_timer); clear_led_timer.function = e100_clear_network_leds; @@ -504,7 +553,6 @@ etrax_ethernet_init(void) current_duplex = autoneg; duplex_timer.expires = jiffies + NET_DUPLEX_CHECK_INTERVAL; duplex_timer.function = e100_check_duplex; - add_timer(&duplex_timer); /* Initialize group address registers to make sure that no */ /* unwanted addresses are matched */ @@ -543,7 +591,7 @@ e100_set_mac_address(struct net_device * /* show it in the log as well */ - printk("%s: changed MAC to ", dev->name); + printk(KERN_INFO "%s: changed MAC to ", dev->name); for (i = 0; i < 5; i++) printk("%02X:", dev->dev_addr[i]); @@ -569,12 +617,6 @@ e100_open(struct net_device *dev) { unsigned long flags; - /* disable the ethernet interface while we configure it */ - - *R_NETWORK_GEN_CONFIG = - IO_STATE(R_NETWORK_GEN_CONFIG, phy, mii_clk) | - IO_STATE(R_NETWORK_GEN_CONFIG, enable, off); - /* enable the MDIO output pin */ *R_NETWORK_MGM_CTRL = IO_STATE(R_NETWORK_MGM_CTRL, mdoe, enable); @@ -645,14 +687,14 @@ e100_open(struct net_device *dev) IO_STATE(R_NETWORK_GEN_CONFIG, phy, mii_clk) | IO_STATE(R_NETWORK_GEN_CONFIG, enable, on); - *R_NETWORK_TR_CTRL = - IO_STATE(R_NETWORK_TR_CTRL, clr_error, clr) | - IO_STATE(R_NETWORK_TR_CTRL, delay, none) | - IO_STATE(R_NETWORK_TR_CTRL, cancel, dont) | - IO_STATE(R_NETWORK_TR_CTRL, cd, enable) | - IO_STATE(R_NETWORK_TR_CTRL, retry, enable) | - IO_STATE(R_NETWORK_TR_CTRL, pad, enable) | - IO_STATE(R_NETWORK_TR_CTRL, crc, enable); + SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, clr); + SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, delay, none); + SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, cancel, dont); + SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, cd, enable); + SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, retry, enable); + SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, pad, enable); + SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, crc, enable); + *R_NETWORK_TR_CTRL = network_tr_ctrl_shadow; save_flags(flags); cli(); @@ -660,7 +702,8 @@ e100_open(struct net_device *dev) /* enable the irq's for ethernet DMA */ *R_IRQ_MASK2_SET = - IO_STATE(R_IRQ_MASK2_SET, dma1_eop, set); + IO_STATE(R_IRQ_MASK2_SET, dma0_eop, set) | + IO_STATE(R_IRQ_MASK2_SET, dma1_eop, set); *R_IRQ_MASK0_SET = IO_STATE(R_IRQ_MASK0_SET, overrun, set) | @@ -689,6 +732,14 @@ e100_open(struct net_device *dev) restore_flags(flags); + /* Probe for transceiver */ + if (e100_probe_transceiver()) + goto grace_exit3; + + /* Start duplex/speed timers */ + add_timer(&speed_timer); + add_timer(&duplex_timer); + /* We are now ready to accept transmit requeusts from * the queueing layer of the networking. */ @@ -696,6 +747,8 @@ e100_open(struct net_device *dev) return 0; +grace_exit3: + free_irq(NETWORK_STATUS_IRQ_NBR, (void *)dev); grace_exit2: free_irq(NETWORK_DMA_TX_IRQ_NBR, (void *)dev); grace_exit1: @@ -706,8 +759,37 @@ grace_exit0: static void +generic_check_speed(void) +{ + unsigned long data; + data = e100_get_mdio_reg(MDIO_ADVERTISMENT_REG); + if ((data & MDIO_ADVERT_100_FD) || + (data & MDIO_ADVERT_100_HD)) + current_speed = 100; + else + current_speed = 10; +} + +static void +tdk_check_speed(void) +{ + unsigned long data; + data = e100_get_mdio_reg(MDIO_TDK_DIAGNOSTIC_REG); + current_speed = (data & MDIO_TDK_DIAGNOSTIC_RATE ? 100 : 10); +} + +static void +broadcom_check_speed(void) +{ + unsigned long data; + data = e100_get_mdio_reg(MDIO_AUX_CTRL_STATUS_REG); + current_speed = (data & MDIO_BC_SPEED ? 100 : 10); +} + +static void e100_check_speed(unsigned long dummy) { + static int led_initiated = 0; unsigned long data; int old_speed = current_speed; @@ -715,12 +797,13 @@ e100_check_speed(unsigned long dummy) if (!(data & MDIO_LINK_UP_MASK)) { current_speed = 0; } else { - data = e100_get_mdio_reg(MDIO_AUX_CTRL_STATUS_REG); - current_speed = (data & MDIO_SPEED ? 100 : 10); + transceiver->check_speed(); } - if (old_speed != current_speed) + if ((old_speed != current_speed) || !led_initiated) { + led_initiated = 1; e100_set_network_leds(NO_NETWORK_ACTIVITY); + } /* Reinitialize the timer. */ speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL; @@ -781,29 +864,21 @@ e100_negotiate(void) static void e100_set_speed(unsigned long speed) { - current_speed_selection = speed; - e100_negotiate(); + if (speed != current_speed_selection) { + current_speed_selection = speed; + e100_negotiate(); + } } static void e100_check_duplex(unsigned long dummy) { - unsigned long data; - - data = e100_get_mdio_reg(MDIO_AUX_CTRL_STATUS_REG); - - if (data & MDIO_FULL_DUPLEX_IND) { - if (!full_duplex) { /* Duplex changed to full? */ - full_duplex = 1; - SETF(network_rec_config_shadow, R_NETWORK_REC_CONFIG, duplex, full_duplex); - *R_NETWORK_REC_CONFIG = network_rec_config_shadow; - } - } else { /* half */ - if (full_duplex) { /* Duplex changed to half? */ - full_duplex = 0; - SETF(network_rec_config_shadow, R_NETWORK_REC_CONFIG, duplex, full_duplex); - *R_NETWORK_REC_CONFIG = network_rec_config_shadow; - } + int old_duplex = full_duplex; + transceiver->check_duplex(); + if (old_duplex != full_duplex) { + /* Duplex changed */ + SETF(network_rec_config_shadow, R_NETWORK_REC_CONFIG, duplex, full_duplex); + *R_NETWORK_REC_CONFIG = network_rec_config_shadow; } /* Reinitialize the timer. */ @@ -811,13 +886,72 @@ e100_check_duplex(unsigned long dummy) add_timer(&duplex_timer); } +static void +generic_check_duplex(void) +{ + unsigned long data; + data = e100_get_mdio_reg(MDIO_ADVERTISMENT_REG); + if ((data & MDIO_ADVERT_100_FD) || + (data & MDIO_ADVERT_10_FD)) + full_duplex = 1; + else + full_duplex = 0; +} + +static void +tdk_check_duplex(void) +{ + unsigned long data; + data = e100_get_mdio_reg(MDIO_TDK_DIAGNOSTIC_REG); + full_duplex = (data & MDIO_TDK_DIAGNOSTIC_DPLX) ? 1 : 0; +} + +static void +broadcom_check_duplex(void) +{ + unsigned long data; + data = e100_get_mdio_reg(MDIO_AUX_CTRL_STATUS_REG); + full_duplex = (data & MDIO_BC_FULL_DUPLEX_IND) ? 1 : 0; +} + static void e100_set_duplex(enum duplex new_duplex) { - current_duplex = new_duplex; - e100_negotiate(); + if (new_duplex != current_duplex) { + current_duplex = new_duplex; + e100_negotiate(); + } } +static int +e100_probe_transceiver(void) +{ + unsigned int phyid_high; + unsigned int phyid_low; + unsigned int oui; + struct transceiver_ops* ops = NULL; + + /* Probe MDIO physical address */ + for (mdio_phy_addr = 0; mdio_phy_addr <= 31; mdio_phy_addr++) { + if (e100_get_mdio_reg(MDIO_BASE_STATUS_REG) != 0xffff) + break; + } + if (mdio_phy_addr == 32) + return -ENODEV; + + /* Get manufacturer */ + phyid_high = e100_get_mdio_reg(MDIO_PHY_ID_HIGH_REG); + phyid_low = e100_get_mdio_reg(MDIO_PHY_ID_LOW_REG); + oui = (phyid_high << 6) | (phyid_low >> 10); + + for (ops = &transceivers[0]; ops->oui; ops++) { + if (ops->oui == oui) + break; + } + transceiver = ops; + + return 0; +} static unsigned short e100_get_mdio_reg(unsigned char reg_num) @@ -827,7 +961,7 @@ e100_get_mdio_reg(unsigned char reg_num) int bitCounter; /* Start of frame, OP Code, Physical Address, Register Address */ - cmd = (MDIO_START << 14) | (MDIO_READ << 12) | (MDIO_PHYS_ADDR << 7) | + cmd = (MDIO_START << 14) | (MDIO_READ << 12) | (mdio_phy_addr << 7) | (reg_num << 2); e100_send_mdio_cmd(cmd, 0); @@ -848,7 +982,7 @@ e100_set_mdio_reg(unsigned char reg, uns int bitCounter; unsigned short cmd; - cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (MDIO_PHYS_ADDR << 7) | + cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (mdio_phy_addr << 7) | (reg << 2); e100_send_mdio_cmd(cmd, 1); @@ -916,7 +1050,7 @@ e100_reset_transceiver(void) data = e100_get_mdio_reg(MDIO_BASE_CONTROL_REG); - cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (MDIO_PHYS_ADDR << 7) | (MDIO_BASE_CONTROL_REG << 2); + cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (mdio_phy_addr << 7) | (MDIO_BASE_CONTROL_REG << 2); e100_send_mdio_cmd(cmd, 1); @@ -984,7 +1118,6 @@ static int e100_send_packet(struct sk_buff *skb, struct net_device *dev) { struct net_local *np = (struct net_local *)dev->priv; - int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; unsigned char *buf = skb->data; unsigned long flags; @@ -997,15 +1130,12 @@ e100_send_packet(struct sk_buff *skb, st dev->trans_start = jiffies; - e100_hardware_send_packet(buf, length); + e100_hardware_send_packet(buf, skb->len); myNextTxDesc = phys_to_virt(myNextTxDesc->descr.next); /* Stop queue if full */ if (myNextTxDesc == myFirstTxDesc) { - /* Enable transmit interrupt to wake up queue */ - *R_DMA_CH0_CLR_INTR = IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do); - *R_IRQ_MASK2_SET = IO_STATE(R_IRQ_MASK2_SET, dma0_eop, set); netif_stop_queue(dev); } @@ -1026,6 +1156,11 @@ e100rxtx_interrupt(int irq, void *dev_id struct net_local *np = (struct net_local *)dev->priv; unsigned long irqbits = *R_IRQ_MASK2_RD; + /* Disable RX/TX IRQs to avoid reentrancy */ + *R_IRQ_MASK2_CLR = + IO_STATE(R_IRQ_MASK2_CLR, dma0_eop, clr) | + IO_STATE(R_IRQ_MASK2_CLR, dma1_eop, clr); + /* Handle received packets */ if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma1_eop, active)) { /* acknowledge the eop interrupt */ @@ -1069,9 +1204,14 @@ e100rxtx_interrupt(int irq, void *dev_id if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma0_eop, active)) { /* acknowledge the eop interrupt and wake up queue */ *R_DMA_CH0_CLR_INTR = IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do); - *R_IRQ_MASK2_CLR = IO_STATE(R_IRQ_MASK2_CLR, dma0_eop, clr); netif_wake_queue(dev); } + + /* Enable RX/TX IRQs again */ + *R_IRQ_MASK2_SET = + IO_STATE(R_IRQ_MASK2_SET, dma0_eop, set) | + IO_STATE(R_IRQ_MASK2_SET, dma1_eop, set); + return IRQ_HANDLED; } @@ -1084,7 +1224,9 @@ e100nw_interrupt(int irq, void *dev_id, /* check for underrun irq */ if (irqbits & IO_STATE(R_IRQ_MASK0_RD, underrun, active)) { - *R_NETWORK_TR_CTRL = IO_STATE(R_NETWORK_TR_CTRL, clr_error, clr); + SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, clr); + *R_NETWORK_TR_CTRL = network_tr_ctrl_shadow; + SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, nop); np->stats.tx_errors++; D(printk("ethernet receiver underrun!\n")); } @@ -1096,6 +1238,9 @@ e100nw_interrupt(int irq, void *dev_id, } /* check for excessive collision irq */ if (irqbits & IO_STATE(R_IRQ_MASK0_RD, excessive_col, active)) { + SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, clr); + *R_NETWORK_TR_CTRL = network_tr_ctrl_shadow; + SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, nop); *R_NETWORK_TR_CTRL = IO_STATE(R_NETWORK_TR_CTRL, clr_error, clr); np->stats.tx_errors++; D(printk("ethernet excessive collisions!\n")); @@ -1210,14 +1355,10 @@ e100_close(struct net_device *dev) { struct net_local *np = (struct net_local *)dev->priv; - printk("Closing %s.\n", dev->name); + printk(KERN_INFO "Closing %s.\n", dev->name); netif_stop_queue(dev); - *R_NETWORK_GEN_CONFIG = - IO_STATE(R_NETWORK_GEN_CONFIG, phy, mii_clk) | - IO_STATE(R_NETWORK_GEN_CONFIG, enable, off); - *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, overrun, clr) | IO_STATE(R_IRQ_MASK0_CLR, underrun, clr) | @@ -1245,6 +1386,10 @@ e100_close(struct net_device *dev) update_rx_stats(&np->stats); update_tx_stats(&np->stats); + /* Stop speed/duplex timers */ + del_timer(&speed_timer); + del_timer(&duplex_timer); + return 0; } @@ -1259,7 +1404,7 @@ e100_ioctl(struct net_device *dev, struc case SIOCETHTOOL: return e100_ethtool_ioctl(dev,ifr); case SIOCGMIIPHY: /* Get PHY address */ - data->phy_id = MDIO_PHYS_ADDR; + data->phy_id = mdio_phy_addr; break; case SIOCGMIIREG: /* Read MII register */ data->val_out = e100_get_mdio_reg(data->reg_num); @@ -1278,7 +1423,7 @@ e100_ioctl(struct net_device *dev, struc case SET_ETH_SPEED_AUTO: /* Auto negotiate speed */ e100_set_speed(0); break; - case SET_ETH_DUPLEX_HALF: /* Hhalf duplex. */ + case SET_ETH_DUPLEX_HALF: /* Half duplex. */ e100_set_duplex(half); break; case SET_ETH_DUPLEX_FULL: /* Full duplex. */ @@ -1312,12 +1457,12 @@ e100_ethtool_ioctl(struct net_device *de SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full; ecmd.port = PORT_TP; ecmd.transceiver = XCVR_EXTERNAL; - ecmd.phy_address = MDIO_PHYS_ADDR; + ecmd.phy_address = mdio_phy_addr; ecmd.speed = current_speed; ecmd.duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF; ecmd.advertising = ADVERTISED_TP; if (current_duplex == autoneg && current_speed_selection == 0) - ecmd.advertising = ADVERTISED_Autoneg; + ecmd.advertising |= ADVERTISED_Autoneg; else { ecmd.advertising |= ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | @@ -1355,7 +1500,7 @@ e100_ethtool_ioctl(struct net_device *de struct ethtool_drvinfo info; memset((void *) &info, 0, sizeof (info)); strncpy(info.driver, "ETRAX 100LX", sizeof(info.driver) - 1); - strncpy(info.version, "$Revision: 1.17 $", sizeof(info.version) - 1); + strncpy(info.version, "$Revision: 1.22 $", sizeof(info.version) - 1); strncpy(info.fw_version, "N/A", sizeof(info.fw_version) - 1); strncpy(info.bus_info, "N/A", sizeof(info.bus_info) - 1); info.regdump_len = 0; @@ -1595,7 +1740,11 @@ e100_set_network_leds(int active) if (!current_speed) { /* Make LED red, link is down */ +#if defined(CONFIG_ETRAX_NETWORK_RED_ON_NO_CONNECTION) + LED_NETWORK_SET(LED_RED); +#else LED_NETWORK_SET(LED_OFF); +#endif } else if (light_leds) { if (current_speed == 10) { @@ -1615,4 +1764,26 @@ etrax_init_module(void) return etrax_ethernet_init(); } +static int __init +e100_boot_setup(char* str) +{ + struct sockaddr sa = {0}; + int i; + + /* Parse the colon separated Ethernet station address */ + for (i = 0; i < ETH_ALEN; i++) { + unsigned int tmp; + if (sscanf(str + 3*i, "%2x", &tmp) != 1) { + printk(KERN_WARNING "Malformed station address"); + return 0; + } + sa.sa_data[i] = (char)tmp; + } + + default_mac = sa; + return 1; +} + +__setup("etrax100_eth=", e100_boot_setup); + module_init(etrax_init_module); diff -puN arch/cris/arch-v10/drivers/gpio.c~cris-architecture-update arch/cris/arch-v10/drivers/gpio.c --- 25/arch/cris/arch-v10/drivers/gpio.c~cris-architecture-update 2004-06-01 01:09:29.046983840 -0700 +++ 25-akpm/arch/cris/arch-v10/drivers/gpio.c 2004-06-01 01:09:29.131970920 -0700 @@ -1,4 +1,4 @@ -/* $Id: gpio.c,v 1.8 2003/07/04 08:27:37 starvik Exp $ +/* $Id: gpio.c,v 1.11 2004/05/14 07:58:03 starvik Exp $ * * Etrax general port I/O device * @@ -9,6 +9,12 @@ * Johan Adolfsson (read/set directions, write, port G) * * $Log: gpio.c,v $ + * Revision 1.11 2004/05/14 07:58:03 starvik + * Merge of changes from 2.4 + * + * Revision 1.9 2003/09/11 07:29:48 starvik + * Merge of Linux 2.6.0-test5 + * * Revision 1.8 2003/07/04 08:27:37 starvik * Merge of Linux 2.5.74 * @@ -183,6 +189,7 @@ struct gpio_private { static struct gpio_private *alarmlist = 0; static int gpio_some_alarms = 0; /* Set if someone uses alarm */ +static unsigned long gpio_pa_irq_enabled_mask = 0; /* Port A and B use 8 bit access, but Port G is 32 bit */ #define NUM_PORTS (GPIO_MINOR_B+1) @@ -252,13 +259,19 @@ gpio_poll(struct file *file, unsigned long data; poll_wait(file, &priv->alarm_wq, wait); if (priv->minor == GPIO_MINOR_A) { + unsigned long flags; unsigned long tmp; data = *R_PORT_PA_DATA; /* PA has support for high level interrupt - * lets activate for those low and with highalarm set */ tmp = ~data & priv->highalarm & 0xFF; - *R_IRQ_MASK1_SET = (tmp << R_IRQ_MASK1_SET__pa0__BITNR); + tmp = (tmp << R_IRQ_MASK1_SET__pa0__BITNR); + save_flags(flags); cli(); + gpio_pa_irq_enabled_mask |= tmp; + *R_IRQ_MASK1_SET = tmp; + restore_flags(flags); + } else if (priv->minor == GPIO_MINOR_B) data = *R_PORT_PB_DATA; else if (priv->minor == GPIO_MINOR_G) @@ -312,12 +325,15 @@ gpio_pa_interrupt(int irq, void *dev_id, { unsigned long tmp; /* Find what PA interrupts are active */ - tmp = (*R_IRQ_READ1 >> R_IRQ_READ1__pa0__BITNR) & 0xFF; + tmp = (*R_IRQ_READ1); + + /* Find those that we have enabled */ + tmp &= gpio_pa_irq_enabled_mask; + /* Clear them.. */ - /* NOTE: Maybe we need to be more careful here if some other - * driver uses PA interrupt as well? - */ - *R_IRQ_MASK1_CLR = (tmp << R_IRQ_MASK1_CLR__pa0__BITNR); + *R_IRQ_MASK1_CLR = tmp; + gpio_pa_irq_enabled_mask &= ~tmp; + if (gpio_some_alarms) { return IRQ_RETVAL(etrax_gpio_wake_up_check()); } @@ -386,7 +402,7 @@ static int gpio_open(struct inode *inode, struct file *filp) { struct gpio_private *priv; - int p = iminor(inode); + int p = MINOR(inode->i_rdev); if (p > GPIO_MINOR_LAST) return -EINVAL; @@ -479,6 +495,7 @@ unsigned long inline setget_input(struct return ~(*priv->dir_shadow) & 0xFF; /* Only 8 bits */ } else if (priv->minor == GPIO_MINOR_G) { /* We must fiddle with R_GEN_CONFIG to change dir */ + save_flags(flags); cli(); if (((arg & dir_g_in_bits) != arg) && (arg & changeable_dir_g)) { arg &= changeable_dir_g; @@ -503,16 +520,17 @@ unsigned long inline setget_input(struct dir_g_in_bits |= (1<<24); dir_g_out_bits &= ~(1<<24); } - printk("gpio: SETINPUT on port G set " - "genconfig to 0x%08lX " - "in_bits: 0x%08lX " - "out_bits: 0x%08lX\n", - (unsigned long)genconfig_shadow, - dir_g_in_bits, dir_g_out_bits); + D(printk(KERN_INFO "gpio: SETINPUT on port G set " + "genconfig to 0x%08lX " + "in_bits: 0x%08lX " + "out_bits: 0x%08lX\n", + (unsigned long)genconfig_shadow, + dir_g_in_bits, dir_g_out_bits)); *R_GEN_CONFIG = genconfig_shadow; /* Must be a >120 ns delay before writing this again */ } + restore_flags(flags); return dir_g_in_bits; } return 0; @@ -529,6 +547,7 @@ unsigned long inline setget_output(struc return *priv->dir_shadow; } else if (priv->minor == GPIO_MINOR_G) { /* We must fiddle with R_GEN_CONFIG to change dir */ + save_flags(flags); cli(); if (((arg & dir_g_out_bits) != arg) && (arg & changeable_dir_g)) { /* Set bits in genconfig to set to output */ @@ -552,15 +571,16 @@ unsigned long inline setget_output(struc dir_g_out_bits |= (1<<24); dir_g_in_bits &= ~(1<<24); } - printk("gpio: SETOUTPUT on port G set " - "genconfig to 0x%08lX " - "in_bits: 0x%08lX " - "out_bits: 0x%08lX\n", - (unsigned long)genconfig_shadow, - dir_g_in_bits, dir_g_out_bits); + D(printk(KERN_INFO "gpio: SETOUTPUT on port G set " + "genconfig to 0x%08lX " + "in_bits: 0x%08lX " + "out_bits: 0x%08lX\n", + (unsigned long)genconfig_shadow, + dir_g_in_bits, dir_g_out_bits)); *R_GEN_CONFIG = genconfig_shadow; /* Must be a >120 ns delay before writing this again */ } + restore_flags(flags); return dir_g_out_bits & 0x7FFFFFFF; } return 0; @@ -625,6 +645,20 @@ gpio_ioctl(struct inode *inode, struct f // clear alarm for bits with 1 in arg priv->highalarm &= ~arg; priv->lowalarm &= ~arg; + { + /* Must update gpio_some_alarms */ + struct gpio_private *p = alarmlist; + int some_alarms; + some_alarms = 0; + while (p) { + if (p->highalarm | p->lowalarm) { + some_alarms = 1; + break; + } + p = p->next; + } + gpio_some_alarms = some_alarms; + } break; case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */ /* Read direction 0=input 1=output */ @@ -844,9 +878,9 @@ static void __init gpio_init_port_g(void dir_g_in_bits |= (~dir_g_shadow & changeable_dir_g); - printk("GPIO port G: in_bits: 0x%08lX out_bits: 0x%08lX val: %08lX\n", + printk(KERN_INFO "GPIO port G: in_bits: 0x%08lX out_bits: 0x%08lX val: %08lX\n", dir_g_in_bits, dir_g_out_bits, (unsigned long)*R_PORT_G_DATA); - printk("GPIO port G: dir: %08lX changeable: %08lX\n", + printk(KERN_INFO "GPIO port G: dir: %08lX changeable: %08lX\n", dir_g_shadow, changeable_dir_g); } @@ -883,7 +917,7 @@ gpio_init(void) #endif gpio_init_port_g(); - printk("ETRAX 100LX GPIO driver v2.5, (c) 2001, 2002 Axis Communications AB\n"); + printk(KERN_INFO "ETRAX 100LX GPIO driver v2.5, (c) 2001, 2002 Axis Communications AB\n"); /* We call etrax_gpio_wake_up_check() from timer interrupt and * from cpu_idle() in kernel/process.c * The check in cpu_idle() reduces latency from ~15 ms to ~6 ms @@ -891,11 +925,11 @@ gpio_init(void) */ if (request_irq(TIMER0_IRQ_NBR, gpio_poll_timer_interrupt, SA_SHIRQ | SA_INTERRUPT,"gpio poll", NULL)) { - printk("err: timer0 irq for gpio\n"); + printk(KERN_CRIT "err: timer0 irq for gpio\n"); } if (request_irq(PA_IRQ_NBR, gpio_pa_interrupt, SA_SHIRQ | SA_INTERRUPT,"gpio PA", NULL)) { - printk("err: PA irq for gpio\n"); + printk(KERN_CRIT "err: PA irq for gpio\n"); } diff -puN arch/cris/arch-v10/drivers/i2c.c~cris-architecture-update arch/cris/arch-v10/drivers/i2c.c --- 25/arch/cris/arch-v10/drivers/i2c.c~cris-architecture-update 2004-06-01 01:09:29.048983536 -0700 +++ 25-akpm/arch/cris/arch-v10/drivers/i2c.c 2004-06-01 01:09:29.132970768 -0700 @@ -12,6 +12,12 @@ *! don't use PB_I2C if DS1302 uses same bits, *! use PB. *! $Log: i2c.c,v $ +*! Revision 1.7 2004/05/28 09:26:59 starvik +*! Modified I2C initialization to work in 2.6. +*! +*! Revision 1.6 2004/05/14 07:58:03 starvik +*! Merge of changes from 2.4 +*! *! Revision 1.4 2002/12/11 13:13:57 starvik *! Added arch/ to v10 specific includes *! Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer) @@ -63,7 +69,7 @@ *! (C) Copyright 1999-2002 Axis Communications AB, LUND, SWEDEN *! *!***************************************************************************/ -/* $Id: i2c.c,v 1.4 2002/12/11 13:13:57 starvik Exp $ */ +/* $Id: i2c.c,v 1.7 2004/05/28 09:26:59 starvik Exp $ */ /****************** INCLUDE FILES SECTION ***********************************/ @@ -310,6 +316,12 @@ i2c_inbyte(void) } i2c_clk(I2C_CLOCK_HIGH); i2c_delay(CLOCK_HIGH_TIME); + + /* + * we leave the clock low, getbyte is usually followed + * by sendack/nack, they assume the clock to be low + */ + i2c_clk(I2C_CLOCK_LOW); return aBitByte; } @@ -372,6 +384,13 @@ i2c_getack(void) } /* + * our clock is high now, make sure data is low + * before we enable our output. If we keep data high + * and enable output, we would generate a stop condition. + */ + i2c_data(I2C_DATA_LOW); + + /* * end clock pulse */ i2c_enable(); @@ -428,6 +447,37 @@ i2c_sendack(void) /*#--------------------------------------------------------------------------- *# +*# FUNCTION NAME: i2c_sendnack +*# +*# DESCRIPTION : Sends NACK on received data +*# +*#--------------------------------------------------------------------------*/ +void +i2c_sendnack(void) +{ + /* + * enable output + */ + i2c_delay(CLOCK_LOW_TIME); + i2c_dir_out(); + /* + * set data high + */ + i2c_data(I2C_DATA_HIGH); + /* + * generate clock pulse + */ + i2c_delay(CLOCK_HIGH_TIME/6); + i2c_clk(I2C_CLOCK_HIGH); + i2c_delay(CLOCK_HIGH_TIME); + i2c_clk(I2C_CLOCK_LOW); + i2c_delay(CLOCK_LOW_TIME); + + i2c_dir_in(); +} + +/*#--------------------------------------------------------------------------- +*# *# FUNCTION NAME: i2c_writereg *# *# DESCRIPTION : Writes a value to an I2C device @@ -489,7 +539,7 @@ i2c_writereg(unsigned char theSlave, uns } while(error && cntr--); i2c_delay(CLOCK_LOW_TIME); - + return -error; } @@ -557,7 +607,8 @@ i2c_readreg(unsigned char theSlave, unsi */ b = i2c_inbyte(); /* - * send Ack + * last received byte needs to be nacked + * instead of acked */ i2c_sendack(); /* @@ -634,11 +685,9 @@ static struct file_operations i2c_fops = .release = i2c_release, }; -static int __init +int __init i2c_init(void) { - int res; - /* Setup and enable the Port B I2C interface */ #ifndef CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C @@ -656,21 +705,28 @@ i2c_init(void) IO_STATE(R_PORT_PB_DIR, dir0, input) | IO_STATE(R_PORT_PB_DIR, dir1, output)); - /* register char device */ + return 0; +} + +static int __init +i2c_register(void) +{ + int res; - res = register_chrdev(I2C_MAJOR, i2c_name, &i2c_fops); + i2c_init(); + res = register_chrdev(I2C_MAJOR, i2c_name, &i2c_fops); if(res < 0) { printk(KERN_ERR "i2c: couldn't get a major number.\n"); return res; } - printk("I2C driver v2.2, (c) 1999-2001 Axis Communications AB\n"); + printk(KERN_INFO "I2C driver v2.2, (c) 1999-2001 Axis Communications AB\n"); return 0; } -/* this makes sure that i2c_init is called during boot */ +/* this makes sure that i2c_register is called during boot */ -module_init(i2c_init); +module_init(i2c_register); /****************** END OF FILE i2c.c ********************************/ diff -puN arch/cris/arch-v10/drivers/i2c.h~cris-architecture-update arch/cris/arch-v10/drivers/i2c.h --- 25/arch/cris/arch-v10/drivers/i2c.h~cris-architecture-update 2004-06-01 01:09:29.049983384 -0700 +++ 25-akpm/arch/cris/arch-v10/drivers/i2c.h 2004-06-01 01:09:29.133970616 -0700 @@ -1,4 +1,6 @@ -/* $Id: i2c.h,v 1.2 2002/11/18 13:16:06 starvik Exp $ */ +/* $Id: i2c.h,v 1.3 2004/05/28 09:26:59 starvik Exp $ */ + +int i2c_init(void); /* High level I2C actions */ int i2c_writereg(unsigned char theSlave, unsigned char theReg, unsigned char theValue); diff -puN /dev/null arch/cris/arch-v10/drivers/ide.c --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25-akpm/arch/cris/arch-v10/drivers/ide.c 2004-06-01 01:09:29.138969856 -0700 @@ -0,0 +1,945 @@ +/* $Id: ide.c,v 1.1 2004/01/22 08:22:58 starvik Exp $ + * + * Etrax specific IDE functions, like init and PIO-mode setting etc. + * Almost the entire ide.c is used for the rest of the Etrax ATA driver. + * Copyright (c) 2000-2004 Axis Communications AB + * + * Authors: Bjorn Wesen (initial version) + * Mikael Starvik (pio setup stuff, Linux 2.6 port) + */ + +/* Regarding DMA: + * + * There are two forms of DMA - "DMA handshaking" between the interface and the drive, + * and DMA between the memory and the interface. We can ALWAYS use the latter, since it's + * something built-in in the Etrax. However only some drives support the DMA-mode handshaking + * on the ATA-bus. The normal PC driver and Triton interface disables memory-if DMA when the + * device can't do DMA handshaking for some stupid reason. We don't need to do that. + */ + +#undef REALLY_SLOW_IO /* most systems can safely undef this */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* number of Etrax DMA descriptors */ +#define MAX_DMA_DESCRS 64 + +/* number of times to retry busy-flags when reading/writing IDE-registers + * this can't be too high because a hung harddisk might cause the watchdog + * to trigger (sometimes INB and OUTB are called with irq's disabled) + */ + +#define IDE_REGISTER_TIMEOUT 300 + +#ifdef CONFIG_ETRAX_IDE_CSE1_16_RESET +/* address where the memory-mapped IDE reset bit lives, if used */ +static volatile unsigned long *reset_addr; +#endif + +static int e100_read_command = 0; + +#define LOWDB(x) +#define D(x) + +void +etrax100_ide_outw(unsigned short data, ide_ioreg_t reg) { + int timeleft; + LOWDB(printk("ow: data 0x%x, reg 0x%x\n", data, reg)); + + /* note the lack of handling any timeouts. we stop waiting, but we don't + * really notify anybody. + */ + + timeleft = IDE_REGISTER_TIMEOUT; + /* wait for busy flag */ + while(timeleft && (*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy))) + timeleft--; + + /* + * Fall through at a timeout, so the ongoing command will be + * aborted by the write below, which is expected to be a dummy + * command to the command register. This happens when a faulty + * drive times out on a command. See comment on timeout in + * INB. + */ + if(!timeleft) + printk("ATA timeout reg 0x%lx := 0x%x\n", reg, data); + + *R_ATA_CTRL_DATA = reg | data; /* write data to the drive's register */ + + timeleft = IDE_REGISTER_TIMEOUT; + /* wait for transmitter ready */ + while(timeleft && !(*R_ATA_STATUS_DATA & + IO_MASK(R_ATA_STATUS_DATA, tr_rdy))) + timeleft--; +} + +void +etrax100_ide_outb(unsigned char data, ide_ioreg_t reg) +{ + etrax100_ide_outw(data, reg); +} + +void +etrax100_ide_outbsync(ide_drive_t *drive, u8 addr, unsigned long port) +{ + etrax100_ide_outw(addr, port); +} + +unsigned short +etrax100_ide_inw(ide_ioreg_t reg) { + int status; + int timeleft; + + timeleft = IDE_REGISTER_TIMEOUT; + /* wait for busy flag */ + while(timeleft && (*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy))) + timeleft--; + + if(!timeleft) { + /* + * If we're asked to read the status register, like for + * example when a command does not complete for an + * extended time, but the ATA interface is stuck in a + * busy state at the *ETRAX* ATA interface level (as has + * happened repeatedly with at least one bad disk), then + * the best thing to do is to pretend that we read + * "busy" in the status register, so the IDE driver will + * time-out, abort the ongoing command and perform a + * reset sequence. Note that the subsequent OUT_BYTE + * call will also timeout on busy, but as long as the + * write is still performed, everything will be fine. + */ + if ((reg & IO_MASK (R_ATA_CTRL_DATA, addr)) + == IO_FIELD (R_ATA_CTRL_DATA, addr, IDE_STATUS_OFFSET)) + return BUSY_STAT; + else + /* For other rare cases we assume 0 is good enough. */ + return 0; + } + + *R_ATA_CTRL_DATA = reg | IO_STATE(R_ATA_CTRL_DATA, rw, read); /* read data */ + + timeleft = IDE_REGISTER_TIMEOUT; + /* wait for available */ + while(timeleft && !((status = *R_ATA_STATUS_DATA) & + IO_MASK(R_ATA_STATUS_DATA, dav))) + timeleft--; + + if(!timeleft) + return 0; + + LOWDB(printk("inb: 0x%x from reg 0x%x\n", status & 0xff, reg)); + + return (unsigned short)status; +} + +unsigned char +etrax100_ide_inb(ide_ioreg_t reg) +{ + return (unsigned char)etrax100_ide_inw(reg); +} + +/* PIO timing (in R_ATA_CONFIG) + * + * _____________________________ + * ADDRESS : ________/ + * + * _______________ + * DIOR : ____________/ \__________ + * + * _______________ + * DATA : XXXXXXXXXXXXXXXX_______________XXXXXXXX + * + * + * DIOR is unbuffered while address and data is buffered. + * This creates two problems: + * 1. The DIOR pulse is to early (because it is unbuffered) + * 2. The rise time of DIOR is long + * + * There are at least three different plausible solutions + * 1. Use a pad capable of larger currents in Etrax + * 2. Use an external buffer + * 3. Make the strobe pulse longer + * + * Some of the strobe timings below are modified to compensate + * for this. This implies a slight performance decrease. + * + * THIS SHOULD NEVER BE CHANGED! + * + * TODO: Is this true for the latest LX boards still ? + */ + +#define ATA_DMA2_STROBE 4 +#define ATA_DMA2_HOLD 0 +#define ATA_DMA1_STROBE 4 +#define ATA_DMA1_HOLD 1 +#define ATA_DMA0_STROBE 12 +#define ATA_DMA0_HOLD 9 +#define ATA_PIO4_SETUP 1 +#define ATA_PIO4_STROBE 5 +#define ATA_PIO4_HOLD 0 +#define ATA_PIO3_SETUP 1 +#define ATA_PIO3_STROBE 5 +#define ATA_PIO3_HOLD 1 +#define ATA_PIO2_SETUP 1 +#define ATA_PIO2_STROBE 6 +#define ATA_PIO2_HOLD 2 +#define ATA_PIO1_SETUP 2 +#define ATA_PIO1_STROBE 11 +#define ATA_PIO1_HOLD 4 +#define ATA_PIO0_SETUP 4 +#define ATA_PIO0_STROBE 19 +#define ATA_PIO0_HOLD 4 + +static int e100_dma_check (ide_drive_t *drive); +static int e100_dma_begin (ide_drive_t *drive); +static int e100_dma_end (ide_drive_t *drive); +static int e100_dma_read (ide_drive_t *drive); +static int e100_dma_write (ide_drive_t *drive); +static void e100_ide_input_data (ide_drive_t *drive, void *, unsigned int); +static void e100_ide_output_data (ide_drive_t *drive, void *, unsigned int); +static void e100_atapi_input_bytes(ide_drive_t *drive, void *, unsigned int); +static void e100_atapi_output_bytes(ide_drive_t *drive, void *, unsigned int); +static int e100_dma_off (ide_drive_t *drive); +static int e100_dma_verbose (ide_drive_t *drive); + + +/* + * good_dma_drives() lists the model names (from "hdparm -i") + * of drives which do not support mword2 DMA but which are + * known to work fine with this interface under Linux. + */ + +const char *good_dma_drives[] = {"Micropolis 2112A", + "CONNER CTMA 4000", + "CONNER CTT8000-A", + NULL}; + +static void tune_e100_ide(ide_drive_t *drive, byte pio) +{ + pio = 4; + /* pio = ide_get_best_pio_mode(drive, pio, 4, NULL); */ + + /* set pio mode! */ + + switch(pio) { + case 0: + *R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable, 1 ) | + IO_FIELD( R_ATA_CONFIG, dma_strobe, ATA_DMA2_STROBE ) | + IO_FIELD( R_ATA_CONFIG, dma_hold, ATA_DMA2_HOLD ) | + IO_FIELD( R_ATA_CONFIG, pio_setup, ATA_PIO0_SETUP ) | + IO_FIELD( R_ATA_CONFIG, pio_strobe, ATA_PIO0_STROBE ) | + IO_FIELD( R_ATA_CONFIG, pio_hold, ATA_PIO0_HOLD ) ); + break; + case 1: + *R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable, 1 ) | + IO_FIELD( R_ATA_CONFIG, dma_strobe, ATA_DMA2_STROBE ) | + IO_FIELD( R_ATA_CONFIG, dma_hold, ATA_DMA2_HOLD ) | + IO_FIELD( R_ATA_CONFIG, pio_setup, ATA_PIO1_SETUP ) | + IO_FIELD( R_ATA_CONFIG, pio_strobe, ATA_PIO1_STROBE ) | + IO_FIELD( R_ATA_CONFIG, pio_hold, ATA_PIO1_HOLD ) ); + break; + case 2: + *R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable, 1 ) | + IO_FIELD( R_ATA_CONFIG, dma_strobe, ATA_DMA2_STROBE ) | + IO_FIELD( R_ATA_CONFIG, dma_hold, ATA_DMA2_HOLD ) | + IO_FIELD( R_ATA_CONFIG, pio_setup, ATA_PIO2_SETUP ) | + IO_FIELD( R_ATA_CONFIG, pio_strobe, ATA_PIO2_STROBE ) | + IO_FIELD( R_ATA_CONFIG, pio_hold, ATA_PIO2_HOLD ) ); + break; + case 3: + *R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable, 1 ) | + IO_FIELD( R_ATA_CONFIG, dma_strobe, ATA_DMA2_STROBE ) | + IO_FIELD( R_ATA_CONFIG, dma_hold, ATA_DMA2_HOLD ) | + IO_FIELD( R_ATA_CONFIG, pio_setup, ATA_PIO3_SETUP ) | + IO_FIELD( R_ATA_CONFIG, pio_strobe, ATA_PIO3_STROBE ) | + IO_FIELD( R_ATA_CONFIG, pio_hold, ATA_PIO3_HOLD ) ); + break; + case 4: + *R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable, 1 ) | + IO_FIELD( R_ATA_CONFIG, dma_strobe, ATA_DMA2_STROBE ) | + IO_FIELD( R_ATA_CONFIG, dma_hold, ATA_DMA2_HOLD ) | + IO_FIELD( R_ATA_CONFIG, pio_setup, ATA_PIO4_SETUP ) | + IO_FIELD( R_ATA_CONFIG, pio_strobe, ATA_PIO4_STROBE ) | + IO_FIELD( R_ATA_CONFIG, pio_hold, ATA_PIO4_HOLD ) ); + break; + } +} + +void __init +init_e100_ide (void) +{ + volatile unsigned int dummy; + int h; + + printk("ide: ETRAX 100LX built-in ATA DMA controller\n"); + + /* first fill in some stuff in the ide_hwifs fields */ + + for(h = 0; h < MAX_HWIFS; h++) { + ide_hwif_t *hwif = &ide_hwifs[h]; + hwif->mmio = 2; + hwif->chipset = ide_etrax100; + hwif->tuneproc = &tune_e100_ide; + hwif->ata_input_data = &e100_ide_input_data; + hwif->ata_output_data = &e100_ide_output_data; + hwif->atapi_input_bytes = &e100_atapi_input_bytes; + hwif->atapi_output_bytes = &e100_atapi_output_bytes; + hwif->ide_dma_check = &e100_dma_check; + hwif->ide_dma_end = &e100_dma_end; + hwif->ide_dma_write = &e100_dma_write; + hwif->ide_dma_read = &e100_dma_read; + hwif->ide_dma_begin = &e100_dma_begin; + hwif->OUTB = &etrax100_ide_outb; + hwif->OUTW = &etrax100_ide_outw; + hwif->OUTBSYNC = &etrax100_ide_outbsync; + hwif->INB = &etrax100_ide_inb; + hwif->INW = &etrax100_ide_inw; + hwif->ide_dma_off_quietly = &e100_dma_off; + hwif->ide_dma_verbose = &e100_dma_verbose; + hwif->sg_table = + kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES, GFP_KERNEL); + } + + /* actually reset and configure the etrax100 ide/ata interface */ + + *R_ATA_CTRL_DATA = 0; + *R_ATA_TRANSFER_CNT = 0; + *R_ATA_CONFIG = 0; + + genconfig_shadow = (genconfig_shadow & + ~IO_MASK(R_GEN_CONFIG, dma2) & + ~IO_MASK(R_GEN_CONFIG, dma3) & + ~IO_MASK(R_GEN_CONFIG, ata)) | + ( IO_STATE( R_GEN_CONFIG, dma3, ata ) | + IO_STATE( R_GEN_CONFIG, dma2, ata ) | + IO_STATE( R_GEN_CONFIG, ata, select ) ); + + *R_GEN_CONFIG = genconfig_shadow; + + /* pull the chosen /reset-line low */ + +#ifdef CONFIG_ETRAX_IDE_G27_RESET + REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow, 27, 0); +#endif +#ifdef CONFIG_ETRAX_IDE_CSE1_16_RESET + REG_SHADOW_SET(port_cse1_addr, port_cse1_shadow, 16, 0); +#endif +#ifdef CONFIG_ETRAX_IDE_CSP0_8_RESET + REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, 8, 0); +#endif +#ifdef CONFIG_ETRAX_IDE_PB7_RESET + port_pb_dir_shadow = port_pb_dir_shadow | + IO_STATE(R_PORT_PB_DIR, dir7, output); + *R_PORT_PB_DIR = port_pb_dir_shadow; + REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, 7, 1); +#endif + + /* wait some */ + + udelay(25); + + /* de-assert bus-reset */ + +#ifdef CONFIG_ETRAX_IDE_CSE1_16_RESET + REG_SHADOW_SET(port_cse1_addr, port_cse1_shadow, 16, 1); +#endif +#ifdef CONFIG_ETRAX_IDE_CSP0_8_RESET + REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, 8, 1); +#endif +#ifdef CONFIG_ETRAX_IDE_G27_RESET + REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow, 27, 1); +#endif + + /* make a dummy read to set the ata controller in a proper state */ + dummy = *R_ATA_STATUS_DATA; + + *R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable, 1 ) | + IO_FIELD( R_ATA_CONFIG, dma_strobe, ATA_DMA2_STROBE ) | + IO_FIELD( R_ATA_CONFIG, dma_hold, ATA_DMA2_HOLD ) | + IO_FIELD( R_ATA_CONFIG, pio_setup, ATA_PIO4_SETUP ) | + IO_FIELD( R_ATA_CONFIG, pio_strobe, ATA_PIO4_STROBE ) | + IO_FIELD( R_ATA_CONFIG, pio_hold, ATA_PIO4_HOLD ) ); + + *R_ATA_CTRL_DATA = ( IO_STATE( R_ATA_CTRL_DATA, rw, read) | + IO_FIELD( R_ATA_CTRL_DATA, addr, 1 ) ); + + while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)); /* wait for busy flag*/ + + *R_IRQ_MASK0_SET = ( IO_STATE( R_IRQ_MASK0_SET, ata_irq0, set ) | + IO_STATE( R_IRQ_MASK0_SET, ata_irq1, set ) | + IO_STATE( R_IRQ_MASK0_SET, ata_irq2, set ) | + IO_STATE( R_IRQ_MASK0_SET, ata_irq3, set ) ); + + printk("ide: waiting %d seconds for drives to regain consciousness\n", + CONFIG_ETRAX_IDE_DELAY); + + h = jiffies + (CONFIG_ETRAX_IDE_DELAY * HZ); + while(time_before(jiffies, h)) /* nothing */ ; + + /* reset the dma channels we will use */ + + RESET_DMA(ATA_TX_DMA_NBR); + RESET_DMA(ATA_RX_DMA_NBR); + WAIT_DMA(ATA_TX_DMA_NBR); + WAIT_DMA(ATA_RX_DMA_NBR); + +} + +static int e100_dma_off (ide_drive_t *drive) +{ + return 0; +} + +static int e100_dma_verbose (ide_drive_t *drive) +{ + printk(", DMA(mode 2)"); + return 0; +} + +static etrax_dma_descr mydescr; + +/* + * The following routines are mainly used by the ATAPI drivers. + * + * These routines will round up any request for an odd number of bytes, + * so if an odd bytecount is specified, be sure that there's at least one + * extra byte allocated for the buffer. + */ +static void +e100_atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) +{ + ide_ioreg_t data_reg = IDE_DATA_REG; + + D(printk("atapi_input_bytes, dreg 0x%x, buffer 0x%x, count %d\n", + data_reg, buffer, bytecount)); + + if(bytecount & 1) { + printk("warning, odd bytecount in cdrom_in_bytes = %d.\n", bytecount); + bytecount++; /* to round off */ + } + + /* make sure the DMA channel is available */ + RESET_DMA(ATA_RX_DMA_NBR); + WAIT_DMA(ATA_RX_DMA_NBR); + + /* setup DMA descriptor */ + + mydescr.sw_len = bytecount; + mydescr.ctrl = d_eol; + mydescr.buf = virt_to_phys(buffer); + + /* start the dma channel */ + + *R_DMA_CH3_FIRST = virt_to_phys(&mydescr); + *R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, start); + + /* initiate a multi word dma read using PIO handshaking */ + + *R_ATA_TRANSFER_CNT = IO_FIELD(R_ATA_TRANSFER_CNT, count, bytecount >> 1); + + *R_ATA_CTRL_DATA = data_reg | + IO_STATE(R_ATA_CTRL_DATA, rw, read) | + IO_STATE(R_ATA_CTRL_DATA, src_dst, dma) | + IO_STATE(R_ATA_CTRL_DATA, handsh, pio) | + IO_STATE(R_ATA_CTRL_DATA, multi, on) | + IO_STATE(R_ATA_CTRL_DATA, dma_size, word); + + /* wait for completion */ + + LED_DISK_READ(1); + WAIT_DMA(ATA_RX_DMA_NBR); + LED_DISK_READ(0); + +#if 0 + /* old polled transfer code + * this should be moved into a new function that can do polled + * transfers if DMA is not available + */ + + /* initiate a multi word read */ + + *R_ATA_TRANSFER_CNT = wcount << 1; + + *R_ATA_CTRL_DATA = data_reg | + IO_STATE(R_ATA_CTRL_DATA, rw, read) | + IO_STATE(R_ATA_CTRL_DATA, src_dst, register) | + IO_STATE(R_ATA_CTRL_DATA, handsh, pio) | + IO_STATE(R_ATA_CTRL_DATA, multi, on) | + IO_STATE(R_ATA_CTRL_DATA, dma_size, word); + + /* svinto has a latency until the busy bit actually is set */ + + nop(); nop(); + nop(); nop(); + nop(); nop(); + nop(); nop(); + nop(); nop(); + + /* unit should be busy during multi transfer */ + while((status = *R_ATA_STATUS_DATA) & IO_MASK(R_ATA_STATUS_DATA, busy)) { + while(!(status & IO_MASK(R_ATA_STATUS_DATA, dav))) + status = *R_ATA_STATUS_DATA; + *ptr++ = (unsigned short)(status & 0xffff); + } +#endif +} + +static void +e100_atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) +{ + ide_ioreg_t data_reg = IDE_DATA_REG; + + D(printk("atapi_output_bytes, dreg 0x%x, buffer 0x%x, count %d\n", + data_reg, buffer, bytecount)); + + if(bytecount & 1) { + printk("odd bytecount %d in atapi_out_bytes!\n", bytecount); + bytecount++; + } + + /* make sure the DMA channel is available */ + RESET_DMA(ATA_TX_DMA_NBR); + WAIT_DMA(ATA_TX_DMA_NBR); + + /* setup DMA descriptor */ + + mydescr.sw_len = bytecount; + mydescr.ctrl = d_eol; + mydescr.buf = virt_to_phys(buffer); + + /* start the dma channel */ + + *R_DMA_CH2_FIRST = virt_to_phys(&mydescr); + *R_DMA_CH2_CMD = IO_STATE(R_DMA_CH2_CMD, cmd, start); + + /* initiate a multi word dma write using PIO handshaking */ + + *R_ATA_TRANSFER_CNT = IO_FIELD(R_ATA_TRANSFER_CNT, count, bytecount >> 1); + + *R_ATA_CTRL_DATA = data_reg | + IO_STATE(R_ATA_CTRL_DATA, rw, write) | + IO_STATE(R_ATA_CTRL_DATA, src_dst, dma) | + IO_STATE(R_ATA_CTRL_DATA, handsh, pio) | + IO_STATE(R_ATA_CTRL_DATA, multi, on) | + IO_STATE(R_ATA_CTRL_DATA, dma_size, word); + + /* wait for completion */ + + LED_DISK_WRITE(1); + WAIT_DMA(ATA_TX_DMA_NBR); + LED_DISK_WRITE(0); + +#if 0 + /* old polled write code - see comment in input_bytes */ + + /* wait for busy flag */ + while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)); + + /* initiate a multi word write */ + + *R_ATA_TRANSFER_CNT = bytecount >> 1; + + ctrl = data_reg | + IO_STATE(R_ATA_CTRL_DATA, rw, write) | + IO_STATE(R_ATA_CTRL_DATA, src_dst, register) | + IO_STATE(R_ATA_CTRL_DATA, handsh, pio) | + IO_STATE(R_ATA_CTRL_DATA, multi, on) | + IO_STATE(R_ATA_CTRL_DATA, dma_size, word); + + LED_DISK_WRITE(1); + + /* Etrax will set busy = 1 until the multi pio transfer has finished + * and tr_rdy = 1 after each successful word transfer. + * When the last byte has been transferred Etrax will first set tr_tdy = 1 + * and then busy = 0 (not in the same cycle). If we read busy before it + * has been set to 0 we will think that we should transfer more bytes + * and then tr_rdy would be 0 forever. This is solved by checking busy + * in the inner loop. + */ + + do { + *R_ATA_CTRL_DATA = ctrl | *ptr++; + while(!(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, tr_rdy)) && + (*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy))); + } while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)); + + LED_DISK_WRITE(0); +#endif + +} + +/* + * This is used for most PIO data transfers *from* the IDE interface + */ +static void +e100_ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) +{ + e100_atapi_input_bytes(drive, buffer, wcount << 2); +} + +/* + * This is used for most PIO data transfers *to* the IDE interface + */ +static void +e100_ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) +{ + e100_atapi_output_bytes(drive, buffer, wcount << 2); +} + +/* we only have one DMA channel on the chip for ATA, so we can keep these statically */ +static etrax_dma_descr ata_descrs[MAX_DMA_DESCRS]; +static unsigned int ata_tot_size; + +/* + * e100_ide_build_dmatable() prepares a dma request. + * Returns 0 if all went okay, returns 1 otherwise. + */ +static int e100_ide_build_dmatable (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct scatterlist* sg; + struct request *rq = HWGROUP(drive)->rq; + unsigned long size, addr; + unsigned int count = 0; + int i = 0; + + sg = hwif->sg_table; + + ata_tot_size = 0; + + if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) { + u8 *virt_addr = rq->buffer; + int sector_count = rq->nr_sectors; + memset(&sg[0], 0, sizeof(*sg)); + sg[0].page = virt_to_page(virt_addr); + sg[0].offset = offset_in_page(virt_addr); + sg[0].length = sector_count * SECTOR_SIZE; + hwif->sg_nents = i = 1; + } + else + { + hwif->sg_nents = i = blk_rq_map_sg(drive->queue, rq, hwif->sg_table); + } + + + while(i) { + /* + * Determine addr and size of next buffer area. We assume that + * individual virtual buffers are always composed linearly in + * physical memory. For example, we assume that any 8kB buffer + * is always composed of two adjacent physical 4kB pages rather + * than two possibly non-adjacent physical 4kB pages. + */ + /* group sequential buffers into one large buffer */ + addr = page_to_phys(sg->page) + sg->offset; + size = sg_dma_len(sg); + while (sg++, --i) { + if ((addr + size) != page_to_phys(sg->page) + sg->offset) + break; + size += sg_dma_len(sg); + } + + /* did we run out of descriptors? */ + + if(count >= MAX_DMA_DESCRS) { + printk("%s: too few DMA descriptors\n", drive->name); + return 1; + } + + /* however, this case is more difficult - R_ATA_TRANSFER_CNT cannot be more + than 65536 words per transfer, so in that case we need to either + 1) use a DMA interrupt to re-trigger R_ATA_TRANSFER_CNT and continue with + the descriptors, or + 2) simply do the request here, and get dma_intr to only ide_end_request on + those blocks that were actually set-up for transfer. + */ + + if(ata_tot_size + size > 131072) { + printk("too large total ATA DMA request, %d + %d!\n", ata_tot_size, (int)size); + return 1; + } + + /* If size > 65536 it has to be splitted into new descriptors. Since we don't handle + size > 131072 only one split is necessary */ + + if(size > 65536) { + /* ok we want to do IO at addr, size bytes. set up a new descriptor entry */ + ata_descrs[count].sw_len = 0; /* 0 means 65536, this is a 16-bit field */ + ata_descrs[count].ctrl = 0; + ata_descrs[count].buf = addr; + ata_descrs[count].next = virt_to_phys(&ata_descrs[count + 1]); + count++; + ata_tot_size += 65536; + /* size and addr should refere to not handled data */ + size -= 65536; + addr += 65536; + } + /* ok we want to do IO at addr, size bytes. set up a new descriptor entry */ + if(size == 65536) { + ata_descrs[count].sw_len = 0; /* 0 means 65536, this is a 16-bit field */ + } else { + ata_descrs[count].sw_len = size; + } + ata_descrs[count].ctrl = 0; + ata_descrs[count].buf = addr; + ata_descrs[count].next = virt_to_phys(&ata_descrs[count + 1]); + count++; + ata_tot_size += size; + } + + if (count) { + /* set the end-of-list flag on the last descriptor */ + ata_descrs[count - 1].ctrl |= d_eol; + /* return and say all is ok */ + return 0; + } + + printk("%s: empty DMA table?\n", drive->name); + return 1; /* let the PIO routines handle this weirdness */ +} + +static int config_drive_for_dma (ide_drive_t *drive) +{ + const char **list; + struct hd_driveid *id = drive->id; + + if (id && (id->capability & 1)) { + /* Enable DMA on any drive that supports mword2 DMA */ + if ((id->field_valid & 2) && (id->dma_mword & 0x404) == 0x404) { + drive->using_dma = 1; + return 0; /* DMA enabled */ + } + + /* Consult the list of known "good" drives */ + list = good_dma_drives; + while (*list) { + if (!strcmp(*list++,id->model)) { + drive->using_dma = 1; + return 0; /* DMA enabled */ + } + } + } + return 1; /* DMA not enabled */ +} + +/* + * etrax_dma_intr() is the handler for disk read/write DMA interrupts + */ +static ide_startstop_t etrax_dma_intr (ide_drive_t *drive) +{ + int i, dma_stat; + byte stat; + + LED_DISK_READ(0); + LED_DISK_WRITE(0); + + dma_stat = HWIF(drive)->ide_dma_end(drive); + stat = HWIF(drive)->INB(IDE_STATUS_REG); /* get drive status */ + if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) { + if (!dma_stat) { + struct request *rq; + rq = HWGROUP(drive)->rq; + for (i = rq->nr_sectors; i > 0;) { + i -= rq->current_nr_sectors; + DRIVER(drive)->end_request(drive, 1, rq->nr_sectors); + } + return ide_stopped; + } + printk("%s: bad DMA status\n", drive->name); + } + return DRIVER(drive)->error(drive, "dma_intr", stat); +} + +/* + * Functions below initiates/aborts DMA read/write operations on a drive. + * + * The caller is assumed to have selected the drive and programmed the drive's + * sector address using CHS or LBA. All that remains is to prepare for DMA + * and then issue the actual read/write DMA/PIO command to the drive. + * + * For ATAPI devices, we just prepare for DMA and return. The caller should + * then issue the packet command to the drive and call us again with + * ide_dma_begin afterwards. + * + * Returns 0 if all went well. + * Returns 1 if DMA read/write could not be started, in which case + * the caller should revert to PIO for the current request. + */ + +static int e100_dma_check(ide_drive_t *drive) +{ + return config_drive_for_dma (drive); +} + +static int e100_dma_end(ide_drive_t *drive) +{ + /* TODO: check if something went wrong with the DMA */ + return 0; +} + +static int e100_start_dma(ide_drive_t *drive, int atapi, int reading) +{ + if(reading) { + + RESET_DMA(ATA_RX_DMA_NBR); /* sometimes the DMA channel get stuck so we need to do this */ + WAIT_DMA(ATA_RX_DMA_NBR); + + /* set up the Etrax DMA descriptors */ + + if(e100_ide_build_dmatable (drive)) + return 1; + + if(!atapi) { + /* set the irq handler which will finish the request when DMA is done */ + + ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL); + + /* issue cmd to drive */ + if ((HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) && + (drive->addressing == 1)) { + ide_task_t *args = HWGROUP(drive)->rq->special; + etrax100_ide_outb(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + } else if (drive->addressing) { + etrax100_ide_outb(WIN_READDMA_EXT, IDE_COMMAND_REG); + } else { + etrax100_ide_outb(WIN_READDMA, IDE_COMMAND_REG); + } + } + + /* begin DMA */ + + /* need to do this before RX DMA due to a chip bug + * it is enough to just flush the part of the cache that + * corresponds to the buffers we start, but since HD transfers + * usually are more than 8 kB, it is easier to optimize for the + * normal case and just flush the entire cache. its the only + * way to be sure! (OB movie quote) + */ + flush_etrax_cache(); + *R_DMA_CH3_FIRST = virt_to_phys(ata_descrs); + *R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, start); + + /* initiate a multi word dma read using DMA handshaking */ + + *R_ATA_TRANSFER_CNT = + IO_FIELD(R_ATA_TRANSFER_CNT, count, ata_tot_size >> 1); + + *R_ATA_CTRL_DATA = + IO_FIELD(R_ATA_CTRL_DATA, data, IDE_DATA_REG) | + IO_STATE(R_ATA_CTRL_DATA, rw, read) | + IO_STATE(R_ATA_CTRL_DATA, src_dst, dma) | + IO_STATE(R_ATA_CTRL_DATA, handsh, dma) | + IO_STATE(R_ATA_CTRL_DATA, multi, on) | + IO_STATE(R_ATA_CTRL_DATA, dma_size, word); + + LED_DISK_READ(1); + + D(printk("dma read of %d bytes.\n", ata_tot_size)); + + } else { + /* writing */ + + RESET_DMA(ATA_TX_DMA_NBR); /* sometimes the DMA channel get stuck so we need to do this */ + WAIT_DMA(ATA_TX_DMA_NBR); + + /* set up the Etrax DMA descriptors */ + + if(e100_ide_build_dmatable (drive)) + return 1; + + if(!atapi) { + /* set the irq handler which will finish the request when DMA is done */ + + ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL); + + /* issue cmd to drive */ + if ((HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) && + (drive->addressing == 1)) { + ide_task_t *args = HWGROUP(drive)->rq->special; + etrax100_ide_outb(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + } else if (drive->addressing) { + etrax100_ide_outb(WIN_WRITEDMA_EXT, IDE_COMMAND_REG); + } else { + etrax100_ide_outb(WIN_WRITEDMA, IDE_COMMAND_REG); + } + } + + /* begin DMA */ + + *R_DMA_CH2_FIRST = virt_to_phys(ata_descrs); + *R_DMA_CH2_CMD = IO_STATE(R_DMA_CH2_CMD, cmd, start); + + /* initiate a multi word dma write using DMA handshaking */ + + *R_ATA_TRANSFER_CNT = + IO_FIELD(R_ATA_TRANSFER_CNT, count, ata_tot_size >> 1); + + *R_ATA_CTRL_DATA = + IO_FIELD(R_ATA_CTRL_DATA, data, IDE_DATA_REG) | + IO_STATE(R_ATA_CTRL_DATA, rw, write) | + IO_STATE(R_ATA_CTRL_DATA, src_dst, dma) | + IO_STATE(R_ATA_CTRL_DATA, handsh, dma) | + IO_STATE(R_ATA_CTRL_DATA, multi, on) | + IO_STATE(R_ATA_CTRL_DATA, dma_size, word); + + LED_DISK_WRITE(1); + + D(printk("dma write of %d bytes.\n", ata_tot_size)); + } + return 0; +} + +static int e100_dma_write(ide_drive_t *drive) +{ + e100_read_command = 0; + /* ATAPI-devices (not disks) first call ide_dma_read/write to set the direction + * then they call ide_dma_begin after they have issued the appropriate drive command + * themselves to actually start the chipset DMA. so we just return here if we're + * not a diskdrive. + */ + if (drive->media != ide_disk) + return 0; + return e100_start_dma(drive, 0, 0); +} + +static int e100_dma_read(ide_drive_t *drive) +{ + e100_read_command = 1; + /* ATAPI-devices (not disks) first call ide_dma_read/write to set the direction + * then they call ide_dma_begin after they have issued the appropriate drive command + * themselves to actually start the chipset DMA. so we just return here if we're + * not a diskdrive. + */ + if (drive->media != ide_disk) + return 0; + return e100_start_dma(drive, 0, 1); +} + +static int e100_dma_begin(ide_drive_t *drive) +{ + /* begin DMA, used by ATAPI devices which want to issue the + * appropriate IDE command themselves. + * + * they have already called ide_dma_read/write to set the + * static reading flag, now they call ide_dma_begin to do + * the real stuff. we tell our code below not to issue + * any IDE commands itself and jump into it. + */ + return e100_start_dma(drive, 1, e100_read_command); +} diff -puN arch/cris/arch-v10/drivers/Kconfig~cris-architecture-update arch/cris/arch-v10/drivers/Kconfig --- 25/arch/cris/arch-v10/drivers/Kconfig~cris-architecture-update 2004-06-01 01:09:29.050983232 -0700 +++ 25-akpm/arch/cris/arch-v10/drivers/Kconfig 2004-06-01 01:09:29.140969552 -0700 @@ -11,29 +11,6 @@ config NET_ETHERNET bool depends on ETRAX_ETHERNET default y - ---help--- - Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common - type of Local Area Network (LAN) in universities and companies. - - Common varieties of Ethernet are: 10BASE-2 or Thinnet (10 Mbps over - coaxial cable, linking computers in a chain), 10BASE-T or twisted - pair (10 Mbps over twisted pair cable, linking computers to central - hubs), 10BASE-F (10 Mbps over optical fiber links, using hubs), - 100BASE-TX (100 Mbps over two twisted pair cables, using hubs), - 100BASE-T4 (100 Mbps over 4 standard voice-grade twisted pair - cables, using hubs), 100BASE-FX (100 Mbps over optical fiber links) - [the 100BASE varieties are also known as Fast Ethernet], and Gigabit - Ethernet (1 Gbps over optical fiber or short copper links). - - If your Linux machine will be connected to an Ethernet and you have - an Ethernet network interface card (NIC) installed in your computer, - say Y here and read the Ethernet-HOWTO, available from - . You will then also have - to say Y to the driver for your particular NIC. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about Ethernet network cards. If unsure, say N. choice prompt "Network LED behavior" @@ -110,6 +87,32 @@ config ETRAX_SERIAL_PORT0 the same DMA channels. choice + prompt "Ser0 DMA out assignment" + depends on ETRAX_SERIAL_PORT0 + default ETRAX_SERIAL_PORT0_DMA6_OUT + +config CONFIG_ETRAX_SERIAL_PORT0_NO_DMA_OUT + bool "No DMA out" + +config CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT + bool "DMA 6" + +endchoice + +choice + prompt "Ser0 DMA in assignment" + depends on ETRAX_SERIAL_PORT0 + default ETRAX_SERIAL_PORT0_DMA7_IN + +config CONFIG_ETRAX_SERIAL_PORT0_NO_DMA_IN + bool "No DMA in" + +config CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN + bool "DMA 7" + +endchoice + +choice prompt "Ser0 DTR, RI, DSR and CD assignment" depends on ETRAX_SERIAL_PORT0 default ETRAX_SER0_DTR_RI_DSR_CD_ON_NONE @@ -198,6 +201,32 @@ config ETRAX_SERIAL_PORT1 Enables the ETRAX 100 serial driver for ser1 (ttyS1). choice + prompt "Ser1 DMA out assignment" + depends on ETRAX_SERIAL_PORT1 + default ETRAX_SERIAL_PORT1_DMA8_OUT + +config CONFIG_ETRAX_SERIAL_PORT1_NO_DMA_OUT + bool "No DMA out" + +config CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT + bool "DMA 8" + +endchoice + +choice + prompt "Ser1 DMA in assignment" + depends on ETRAX_SERIAL_PORT1 + default ETRAX_SERIAL_PORT1_DMA9_IN + +config CONFIG_ETRAX_SERIAL_PORT1_NO_DMA_IN + bool "No DMA in" + +config CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN + bool "DMA 9" + +endchoice + +choice prompt "Ser1 DTR, RI, DSR and CD assignment" depends on ETRAX_SERIAL_PORT1 default ETRAX_SER1_DTR_RI_DSR_CD_ON_NONE @@ -289,6 +318,32 @@ config ETRAX_SERIAL_PORT2 Enables the ETRAX 100 serial driver for ser2 (ttyS2). choice + prompt "Ser2 DMA out assignment" + depends on ETRAX_SERIAL_PORT2 + default ETRAX_SERIAL_PORT2_DMA2_OUT + +config CONFIG_ETRAX_SERIAL_PORT2_NO_DMA_OUT + bool "No DMA out" + +config CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT + bool "DMA 2" + +endchoice + +choice + prompt "Ser2 DMA in assignment" + depends on ETRAX_SERIAL_PORT2 + default ETRAX_SERIAL_PORT2_DMA3_IN + +config CONFIG_ETRAX_SERIAL_PORT2_NO_DMA_IN + bool "No DMA in" + +config CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN + bool "DMA 3" + +endchoice + +choice prompt "Ser2 DTR, RI, DSR and CD assignment" depends on ETRAX_SERIAL_PORT2 default ETRAX_SER2_DTR_RI_DSR_CD_ON_NONE @@ -377,6 +432,32 @@ config ETRAX_SERIAL_PORT3 Enables the ETRAX 100 serial driver for ser3 (ttyS3). choice + prompt "Ser3 DMA out assignment" + depends on ETRAX_SERIAL_PORT3 + default ETRAX_SERIAL_PORT3_DMA4_OUT + +config CONFIG_ETRAX_SERIAL_PORT3_NO_DMA_OUT + bool "No DMA out" + +config CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT + bool "DMA 4" + +endchoice + +choice + prompt "Ser3 DMA in assignment" + depends on ETRAX_SERIAL_PORT3 + default ETRAX_SERIAL_PORT3_DMA5_IN + +config CONFIG_ETRAX_SERIAL_PORT3_NO_DMA_IN + bool "No DMA in" + +config CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN + bool "DMA 5" + +endchoice + +choice prompt "Ser3 DTR, RI, DSR and CD assignment" depends on ETRAX_SERIAL_PORT3 default ETRAX_SER3_DTR_RI_DSR_CD_ON_NONE @@ -466,6 +547,95 @@ config ETRAX_RS485_DISABLE_RECEIVER loopback. Not all products are able to do this in software only. Axis 2400/2401 must disable receiver. +config ETRAX_IDE + bool "ATA/IDE support" + help + Enable this to get support for ATA/IDE. + You can't use parallell ports or SCSI ports + at the same time. + +# here we should add the CONFIG_'s necessary to enable the basic +# general ide drivers so the common case does not need to go +# into that config submenu. enable disk and CD support. others +# need to go fiddle in the submenu.. +config IDE + tristate + depends on ETRAX_IDE + default y + +config BLK_DEV_IDE + tristate + depends on ETRAX_IDE + default y + +config BLK_DEV_IDEDISK + tristate + depends on ETRAX_IDE + default y + +config BLK_DEV_IDECD + tristate + depends on ETRAX_IDE + default y + +config BLK_DEV_IDEDMA + bool + depends on ETRAX_IDE + default y + +config DMA_NONPCI + bool + depends on ETRAX_IDE + default y + +config ETRAX_IDE_DELAY + int "Delay for drives to regain consciousness" + depends on ETRAX_IDE + default 15 + help + Number of seconds to wait for IDE drives to spin up after an IDE + reset. +choice + prompt "IDE reset pin" + depends on ETRAX_IDE + default ETRAX_IDE_PB7_RESET + +config ETRAX_IDE_PB7_RESET + bool "Port_PB_Bit_7" + help + IDE reset on pin 7 on port B + +config ETRAX_IDE_G27_RESET + bool "Port_G_Bit_27" + help + IDE reset on pin 27 on port G + +endchoice + + +config ETRAX_USB_HOST + bool "USB host" + help + This option enables the host functionality of the ETRAX 100LX + built-in USB controller. In host mode the controller is designed + for CTRL and BULK traffic only, INTR traffic may work as well + however (depending on the requirements of timeliness). + +config USB + tristate + depends on ETRAX_USB_HOST + default y + +config ETRAX_USB_HOST_PORT1 + bool " USB port 1 enabled" + depends on ETRAX_USB_HOST + default n + +config ETRAX_USB_HOST_PORT2 + bool " USB port 2 enabled" + depends on ETRAX_USB_HOST + default n + config ETRAX_AXISFLASHMAP bool "Axis flash-map support" depends on ETRAX_ARCH_V10 diff -puN arch/cris/arch-v10/drivers/Makefile~cris-architecture-update arch/cris/arch-v10/drivers/Makefile --- 25/arch/cris/arch-v10/drivers/Makefile~cris-architecture-update 2004-06-01 01:09:29.052982928 -0700 +++ 25-akpm/arch/cris/arch-v10/drivers/Makefile 2004-06-01 01:09:29.140969552 -0700 @@ -10,5 +10,7 @@ obj-$(CONFIG_ETRAX_I2C_EEPROM) obj-$(CONFIG_ETRAX_GPIO) += gpio.o obj-$(CONFIG_ETRAX_DS1302) += ds1302.o obj-$(CONFIG_ETRAX_PCF8563) += pcf8563.o +obj-$(CONFIG_ETRAX_IDE) += ide.o +obj-$(CONFIG_ETRAX_USB_HOST) += usb-host.o diff -puN arch/cris/arch-v10/drivers/pcf8563.c~cris-architecture-update arch/cris/arch-v10/drivers/pcf8563.c --- 25/arch/cris/arch-v10/drivers/pcf8563.c~cris-architecture-update 2004-06-01 01:09:29.053982776 -0700 +++ 25-akpm/arch/cris/arch-v10/drivers/pcf8563.c 2004-06-01 01:09:29.141969400 -0700 @@ -15,7 +15,7 @@ * * Author: Tobias Anderberg . * - * $Id: pcf8563.c,v 1.1 2002/12/12 08:27:26 starvik Exp $ + * $Id: pcf8563.c,v 1.4 2004/05/28 09:26:59 starvik Exp $ */ #include @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -39,7 +40,7 @@ #define PCF8563_MAJOR 121 /* Local major number. */ #define DEVICE_NAME "rtc" /* Name which is registered in /proc/devices. */ #define PCF8563_NAME "PCF8563" -#define DRIVER_VERSION "$Revision: 1.1 $" +#define DRIVER_VERSION "$Revision: 1.4 $" /* I2C bus slave registers. */ #define RTC_I2C_READ 0xa3 @@ -85,7 +86,12 @@ pcf8563_readreg(int reg) void pcf8563_writereg(int reg, unsigned char val) { - i2c_writereg(RTC_I2C_WRITE,reg,val); +#ifdef CONFIG_ETRAX_RTC_READONLY + if (reg == RTC_CONTROL1 || (reg >= RTC_SECONDS && reg <= RTC_YEAR)) + return; +#endif + + rtc_write(reg, val); } void @@ -120,6 +126,9 @@ int __init pcf8563_init(void) { unsigned char ret; + + i2c_init(); + /* * First of all we need to reset the chip. This is done by * clearing control1, control2 and clk freq, clear the @@ -152,14 +161,6 @@ pcf8563_init(void) if (rtc_write(RTC_WEEKDAY_ALARM, 0x00) < 0) goto err; - - if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) { - printk(KERN_INFO "%s: Unable to get major numer %d for RTC device.\n", - PCF8563_NAME, PCF8563_MAJOR); - return -1; - } - - printk(KERN_INFO "%s Real-Time Clock Driver, %s\n", PCF8563_NAME, DRIVER_VERSION); /* Check for low voltage, and warn about it.. */ if (rtc_read(RTC_SECONDS) & 0x80) @@ -210,9 +211,11 @@ pcf8563_ioctl(struct inode *inode, struc break; case RTC_SET_TIME: { +#ifdef CONFIG_ETRAX_RTC_READONLY + return -EPERM; +#else int leap; int century; - unsigned long flags; struct rtc_time tm; memset(&tm, 0, sizeof (struct rtc_time)); @@ -256,8 +259,35 @@ pcf8563_ioctl(struct inode *inode, struc rtc_write(RTC_SECONDS, tm.tm_sec); return 0; +#endif /* !CONFIG_ETRAX_RTC_READONLY */ } - break; + + case RTC_VLOW_RD: + { + int vl_bit = 0; + + if (rtc_read(RTC_SECONDS) & 0x80) { + vl_bit = 1; + printk(KERN_WARNING "%s: RTC Voltage Low - reliable " + "date/time information is no longer guaranteed!\n", + PCF8563_NAME); + } + if (copy_to_user((int *) arg, &vl_bit, sizeof(int))) + return -EFAULT; + + return 0; + } + + case RTC_VLOW_SET: + { + /* Clear the VL bit in the seconds register */ + int ret = rtc_read(RTC_SECONDS); + + rtc_write(RTC_SECONDS, (ret & 0x7F)); + + return 0; + } + default: return -ENOTTY; } @@ -265,5 +295,19 @@ pcf8563_ioctl(struct inode *inode, struc return 0; } -module_init(pcf8563_init); +static int __init +pcf8563_register(void) +{ + pcf8563_init(); + if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) { + printk(KERN_INFO "%s: Unable to get major numer %d for RTC device.\n", + PCF8563_NAME, PCF8563_MAJOR); + return -1; + } + + printk(KERN_INFO "%s Real-Time Clock Driver, %s\n", PCF8563_NAME, DRIVER_VERSION); + return 0; +} + +module_init(pcf8563_register); module_exit(pcf8563_exit); diff -puN arch/cris/arch-v10/drivers/serial.c~cris-architecture-update arch/cris/arch-v10/drivers/serial.c --- 25/arch/cris/arch-v10/drivers/serial.c~cris-architecture-update 2004-06-01 01:09:29.055982472 -0700 +++ 25-akpm/arch/cris/arch-v10/drivers/serial.c 2004-06-01 01:09:29.157966968 -0700 @@ -1,4 +1,4 @@ -/* $Id: serial.c,v 1.17 2003/07/04 08:27:37 starvik Exp $ +/* $Id: serial.c,v 1.20 2004/05/24 12:00:20 starvik Exp $ * * Serial port driver for the ETRAX 100LX chip * @@ -7,6 +7,16 @@ * Many, many authors. Based once upon a time on serial.c for 16x50. * * $Log: serial.c,v $ + * Revision 1.20 2004/05/24 12:00:20 starvik + * Big merge of stuff from Linux 2.4 (e.g. manual mode for the serial port). + * + * Revision 1.19 2004/05/17 13:12:15 starvik + * Kernel console hook + * Big merge from Linux 2.4 still pending. + * + * Revision 1.18 2003/10/28 07:18:30 starvik + * Compiles with debug info + * * Revision 1.17 2003/07/04 08:27:37 starvik * Merge of Linux 2.5.74 * @@ -399,7 +409,7 @@ * */ -static char *serial_version = "$Revision: 1.17 $"; +static char *serial_version = "$Revision: 1.20 $"; #include #include @@ -447,6 +457,10 @@ static char *serial_version = "$Revision #error "RX_TIMEOUT_TICKS == 0 not allowed, use 1" #endif +#if defined(CONFIG_ETRAX_RS485_ON_PA) && defined(CONFIG_ETRAX_RS485_ON_PORT_G) +#error "Disable either CONFIG_ETRAX_RS485_ON_PA or CONFIG_ETRAX_RS485_ON_PORT_G" +#endif + /* * All of the compatibilty code so we can compile serial.c against * older kernels is hidden in serial_compat.h @@ -473,7 +487,7 @@ struct tty_driver *serial_driver; //#define SERIAL_DEBUG_DATA //#define SERIAL_DEBUG_THROTTLE //#define SERIAL_DEBUG_IO /* Debug for Extra control and status pins */ -#define SERIAL_DEBUG_LINE 0 /* What serport we want to debug */ +//#define SERIAL_DEBUG_LINE 0 /* What serport we want to debug */ /* Enable this to use serial interrupts to handle when you expect the first received event on the serial port to @@ -481,14 +495,74 @@ struct tty_driver *serial_driver; from eLinux */ #define SERIAL_HANDLE_EARLY_ERRORS -#define TTY_THROTTLE_LIMIT (TTY_FLIPBUF_SIZE/10) +/* Defined and used in n_tty.c, but we need it here as well */ +#define TTY_THRESHOLD_THROTTLE 128 +/* Due to buffersizes and threshold values, our SERIAL_DESCR_BUF_SIZE + * must not be to high or flow control won't work if we leave it to the tty + * layer so we have our own throttling in flush_to_flip + * TTY_FLIPBUF_SIZE=512, + * TTY_THRESHOLD_THROTTLE/UNTHROTTLE=128 + * BUF_SIZE can't be > 128 + */ +/* Currently 16 descriptors x 128 bytes = 2048 bytes */ #define SERIAL_DESCR_BUF_SIZE 256 +#define SERIAL_PRESCALE_BASE 3125000 /* 3.125MHz */ +#define DEF_BAUD_BASE SERIAL_PRESCALE_BASE + +/* We don't want to load the system with massive fast timer interrupt + * on high baudrates so limit it to 250 us (4kHz) */ +#define MIN_FLUSH_TIME_USEC 250 + /* Add an x here to log a lot of timer stuff */ #define TIMERD(x) +/* Debug details of interrupt handling */ +#define DINTR1(x) /* irq on/off, errors */ +#define DINTR2(x) /* tx and rx */ +/* Debug flip buffer stuff */ +#define DFLIP(x) +/* Debug flow control and overview of data flow */ +#define DFLOW(x) +#define DBAUD(x) +#define DLOG_INT_TRIG(x) +//#define DEBUG_LOG_INCLUDED +#ifndef DEBUG_LOG_INCLUDED #define DEBUG_LOG(line, string, value) +#else +struct debug_log_info +{ + unsigned long time; + unsigned long timer_data; +// int line; + const char *string; + int value; +}; +#define DEBUG_LOG_SIZE 4096 + +struct debug_log_info debug_log[DEBUG_LOG_SIZE]; +int debug_log_pos = 0; + +#define DEBUG_LOG(_line, _string, _value) do { \ + if ((_line) == SERIAL_DEBUG_LINE) {\ + debug_log_func(_line, _string, _value); \ + }\ +}while(0) + +void debug_log_func(int line, const char *string, int value) +{ + if (debug_log_pos < DEBUG_LOG_SIZE) { + debug_log[debug_log_pos].time = jiffies; + debug_log[debug_log_pos].timer_data = *R_TIMER_DATA; +// debug_log[debug_log_pos].line = line; + debug_log[debug_log_pos].string = string; + debug_log[debug_log_pos].value = value; + debug_log_pos++; + } + /*printk(string, value);*/ +} +#endif #ifndef CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS /* Default number of timer ticks before flushing rx fifo @@ -498,11 +572,14 @@ struct tty_driver *serial_driver; #define CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS 5 #endif +unsigned long timer_data_to_ns(unsigned long timer_data); + static void change_speed(struct e100_serial *info); +static void rs_throttle(struct tty_struct * tty); static void rs_wait_until_sent(struct tty_struct *tty, int timeout); static int rs_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count); -static inline int raw_write(struct tty_struct * tty, int from_user, +extern _INLINE_ int rs_raw_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count); #ifdef CONFIG_ETRAX_RS485 static int e100_write_rs485(struct tty_struct * tty, int from_user, @@ -511,7 +588,7 @@ static int e100_write_rs485(struct tty_s static int get_lsr_info(struct e100_serial * info, unsigned int *value); -#define DEF_BAUD 0x99 /* 115.2 kbit/s */ +#define DEF_BAUD 115200 /* 115.2 kbit/s */ #define STD_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) #define DEF_RX 0x20 /* or SERIAL_CTRL_W >> 8 */ /* Default value of tx_ctrl register: has txd(bit 7)=1 (idle) as default */ @@ -520,6 +597,7 @@ static int get_lsr_info(struct e100_seri /* offsets from R_SERIALx_CTRL */ #define REG_DATA 0 +#define REG_DATA_STATUS32 0 /* this is the 32 bit register R_SERIALx_READ */ #define REG_TR_DATA 0 #define REG_STATUS 1 #define REG_TR_CTRL 1 @@ -555,60 +633,162 @@ static int get_lsr_info(struct e100_seri */ +/* Mask for the irqs possibly enabled in R_IRQ_MASK1_RD etc. */ +static const unsigned long e100_ser_int_mask = 0 +#ifdef CONFIG_ETRAX_SERIAL_PORT0 +| IO_MASK(R_IRQ_MASK1_RD, ser0_data) | IO_MASK(R_IRQ_MASK1_RD, ser0_ready) +#endif +#ifdef CONFIG_ETRAX_SERIAL_PORT1 +| IO_MASK(R_IRQ_MASK1_RD, ser1_data) | IO_MASK(R_IRQ_MASK1_RD, ser1_ready) +#endif +#ifdef CONFIG_ETRAX_SERIAL_PORT2 +| IO_MASK(R_IRQ_MASK1_RD, ser2_data) | IO_MASK(R_IRQ_MASK1_RD, ser2_ready) +#endif +#ifdef CONFIG_ETRAX_SERIAL_PORT3 +| IO_MASK(R_IRQ_MASK1_RD, ser3_data) | IO_MASK(R_IRQ_MASK1_RD, ser3_ready) +#endif +; +unsigned long r_alt_ser_baudrate_shadow = 0; + /* this is the data for the four serial ports in the etrax100 */ /* DMA2(ser2), DMA4(ser3), DMA6(ser0) or DMA8(ser1) */ /* R_DMA_CHx_CLR_INTR, R_DMA_CHx_FIRST, R_DMA_CHx_CMD */ static struct e100_serial rs_table[] = { - { DEF_BAUD, (unsigned char *)R_SERIAL0_CTRL, 1U << 12, /* uses DMA 6 and 7 */ - R_DMA_CH6_CLR_INTR, R_DMA_CH6_FIRST, R_DMA_CH6_CMD, - R_DMA_CH6_STATUS, R_DMA_CH6_HWSW, R_DMA_CH6_DESCR, - R_DMA_CH7_CLR_INTR, R_DMA_CH7_FIRST, R_DMA_CH7_CMD, - R_DMA_CH7_STATUS, R_DMA_CH7_HWSW, R_DMA_CH7_DESCR, - STD_FLAGS, DEF_RX, DEF_TX, 2, + { .baud = DEF_BAUD, + .port = (unsigned char *)R_SERIAL0_CTRL, + .irq = 1U << 12, /* uses DMA 6 and 7 */ + .oclrintradr = R_DMA_CH6_CLR_INTR, + .ofirstadr = R_DMA_CH6_FIRST, + .ocmdadr = R_DMA_CH6_CMD, + .ostatusadr = R_DMA_CH6_STATUS, + .iclrintradr = R_DMA_CH7_CLR_INTR, + .ifirstadr = R_DMA_CH7_FIRST, + .icmdadr = R_DMA_CH7_CMD, + .idescradr = R_DMA_CH7_DESCR, + .flags = STD_FLAGS, + .rx_ctrl = DEF_RX, + .tx_ctrl = DEF_TX, + .iseteop = 2, #ifdef CONFIG_ETRAX_SERIAL_PORT0 - 1 + .enabled = 1, +#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT + .dma_out_enabled = 1, +#else + .dma_out_enabled = 0, +#endif +#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN + .dma_in_enabled = 1, +#else + .dma_in_enabled = 0 +#endif #else - 0 + .enabled = 0, + .dma_out_enabled = 0, + .dma_in_enabled = 0 #endif + }, /* ttyS0 */ #ifndef CONFIG_SVINTO_SIM - { DEF_BAUD, (unsigned char *)R_SERIAL1_CTRL, 1U << 16, /* uses DMA 8 and 9 */ - R_DMA_CH8_CLR_INTR, R_DMA_CH8_FIRST, R_DMA_CH8_CMD, - R_DMA_CH8_STATUS, R_DMA_CH8_HWSW, R_DMA_CH8_DESCR, - R_DMA_CH9_CLR_INTR, R_DMA_CH9_FIRST, R_DMA_CH9_CMD, - R_DMA_CH9_STATUS, R_DMA_CH9_HWSW, R_DMA_CH9_DESCR, - STD_FLAGS, DEF_RX, DEF_TX, 3 , + { .baud = DEF_BAUD, + .port = (unsigned char *)R_SERIAL1_CTRL, + .irq = 1U << 16, /* uses DMA 8 and 9 */ + .oclrintradr = R_DMA_CH8_CLR_INTR, + .ofirstadr = R_DMA_CH8_FIRST, + .ocmdadr = R_DMA_CH8_CMD, + .ostatusadr = R_DMA_CH8_STATUS, + .iclrintradr = R_DMA_CH9_CLR_INTR, + .ifirstadr = R_DMA_CH9_FIRST, + .icmdadr = R_DMA_CH9_CMD, + .idescradr = R_DMA_CH9_DESCR, + .flags = STD_FLAGS, + .rx_ctrl = DEF_RX, + .tx_ctrl = DEF_TX, + .iseteop = 3, #ifdef CONFIG_ETRAX_SERIAL_PORT1 - 1 + .enabled = 1, +#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT + .dma_out_enabled = 1, +#else + .dma_out_enabled = 0, +#endif +#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN + .dma_in_enabled = 1, +#else + .dma_in_enabled = 0 +#endif #else - 0 + .enabled = 0, + .dma_out_enabled = 0, + .dma_in_enabled = 0 #endif }, /* ttyS1 */ - { DEF_BAUD, (unsigned char *)R_SERIAL2_CTRL, 1U << 4, /* uses DMA 2 and 3 */ - R_DMA_CH2_CLR_INTR, R_DMA_CH2_FIRST, R_DMA_CH2_CMD, - R_DMA_CH2_STATUS, R_DMA_CH2_HWSW, R_DMA_CH2_DESCR, - R_DMA_CH3_CLR_INTR, R_DMA_CH3_FIRST, R_DMA_CH3_CMD, - R_DMA_CH3_STATUS, R_DMA_CH3_HWSW, R_DMA_CH3_DESCR, - STD_FLAGS, DEF_RX, DEF_TX, 0, + { .baud = DEF_BAUD, + .port = (unsigned char *)R_SERIAL2_CTRL, + .irq = 1U << 4, /* uses DMA 2 and 3 */ + .oclrintradr = R_DMA_CH2_CLR_INTR, + .ofirstadr = R_DMA_CH2_FIRST, + .ocmdadr = R_DMA_CH2_CMD, + .ostatusadr = R_DMA_CH2_STATUS, + .iclrintradr = R_DMA_CH3_CLR_INTR, + .ifirstadr = R_DMA_CH3_FIRST, + .icmdadr = R_DMA_CH3_CMD, + .idescradr = R_DMA_CH3_DESCR, + .flags = STD_FLAGS, + .rx_ctrl = DEF_RX, + .tx_ctrl = DEF_TX, + .iseteop = 0, #ifdef CONFIG_ETRAX_SERIAL_PORT2 - 1 + .enabled = 1, +#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT + .dma_out_enabled = 1, +#else + .dma_out_enabled = 0, +#endif +#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN + .dma_in_enabled = 1, #else - 0 + .dma_in_enabled = 0 +#endif +#else + .enabled = 0, + .dma_out_enabled = 0, + .dma_in_enabled = 0 #endif }, /* ttyS2 */ - { DEF_BAUD, (unsigned char *)R_SERIAL3_CTRL, 1U << 8, /* uses DMA 4 and 5 */ - R_DMA_CH4_CLR_INTR, R_DMA_CH4_FIRST, R_DMA_CH4_CMD, - R_DMA_CH4_STATUS, R_DMA_CH4_HWSW, R_DMA_CH4_DESCR, - R_DMA_CH5_CLR_INTR, R_DMA_CH5_FIRST, R_DMA_CH5_CMD, - R_DMA_CH5_STATUS, R_DMA_CH5_HWSW, R_DMA_CH5_DESCR, - STD_FLAGS, DEF_RX, DEF_TX, 1, + { .baud = DEF_BAUD, + .port = (unsigned char *)R_SERIAL3_CTRL, + .irq = 1U << 8, /* uses DMA 4 and 5 */ + .oclrintradr = R_DMA_CH4_CLR_INTR, + .ofirstadr = R_DMA_CH4_FIRST, + .ocmdadr = R_DMA_CH4_CMD, + .ostatusadr = R_DMA_CH4_STATUS, + .iclrintradr = R_DMA_CH5_CLR_INTR, + .ifirstadr = R_DMA_CH5_FIRST, + .icmdadr = R_DMA_CH5_CMD, + .idescradr = R_DMA_CH5_DESCR, + .flags = STD_FLAGS, + .rx_ctrl = DEF_RX, + .tx_ctrl = DEF_TX, + .iseteop = 1, #ifdef CONFIG_ETRAX_SERIAL_PORT3 - 1 + .enabled = 1, +#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT + .dma_out_enabled = 1, +#else + .dma_out_enabled = 0, +#endif +#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN + .dma_in_enabled = 1, #else - 0 + .dma_in_enabled = 0 +#endif +#else + .enabled = 0, + .dma_out_enabled = 0, + .dma_in_enabled = 0 #endif } /* ttyS3 */ #endif @@ -616,6 +796,9 @@ static struct e100_serial rs_table[] = { #define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial)) + +static struct termios *serial_termios[NR_PORTS]; +static struct termios *serial_termios_locked[NR_PORTS]; #ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER static struct fast_timer fast_timers[NR_PORTS]; #endif @@ -652,6 +835,9 @@ static struct fast_timer fast_timers_rs4 #if defined(CONFIG_ETRAX_RS485_ON_PA) static int rs485_pa_bit = CONFIG_ETRAX_RS485_ON_PA_BIT; #endif +#if defined(CONFIG_ETRAX_RS485_ON_PORT_G) +static int rs485_port_g_bit = CONFIG_ETRAX_RS485_ON_PORT_G_BIT; +#endif #endif /* Info and macros needed for each ports extra control/status signals. */ @@ -761,7 +947,7 @@ static unsigned char dummy_ser[NR_PORTS] # endif #endif -#define SER0_PB_BITSUM (CONFIG_ETRAX_SER1_DTR_ON_PB_BIT+CONFIG_ETRAX_SER1_RI_ON_PB_BIT+CONFIG_ETRAX_SER1_DSR_ON_PB_BIT+CONFIG_ETRAX_SER1_CD_ON_PB_BIT) +#define SER1_PB_BITSUM (CONFIG_ETRAX_SER1_DTR_ON_PB_BIT+CONFIG_ETRAX_SER1_RI_ON_PB_BIT+CONFIG_ETRAX_SER1_DSR_ON_PB_BIT+CONFIG_ETRAX_SER1_CD_ON_PB_BIT) #if SER1_PB_BITSUM != -4 # if CONFIG_ETRAX_SER1_DTR_ON_PB_BIT == -1 @@ -1081,15 +1267,9 @@ static const struct control_pins e100_mo }; #endif /* !CONFIG_ETRAX_SERX_DTR_RI_DSR_CD_MIXED */ -#if defined(CONFIG_ETRAX_RS485) && defined(CONFIG_ETRAX_RS485_ON_PA) -unsigned char rs485_pa_port = CONFIG_ETRAX_RS485_ON_PA_BIT; -#endif - - #define E100_RTS_MASK 0x20 #define E100_CTS_MASK 0x40 - /* All serial port signals are active low: * active = 0 -> 3.3V to RS-232 driver -> -12V on RS-232 level * inactive = 1 -> 0V to RS-232 driver -> +12V on RS-232 level @@ -1151,6 +1331,10 @@ static void update_char_time(struct e100 /* calc timeout */ info->char_time_usec = ((bits * 1000000) / info->baud) + 1; + info->flush_time_usec = 4*info->char_time_usec; + if (info->flush_time_usec < MIN_FLUSH_TIME_USEC) + info->flush_time_usec = MIN_FLUSH_TIME_USEC; + } /* @@ -1250,9 +1434,13 @@ static inline void e100_rts(struct e100_serial *info, int set) { #ifndef CONFIG_SVINTO_SIM + unsigned long flags; + save_flags(flags); + cli(); info->rx_ctrl &= ~E100_RTS_MASK; info->rx_ctrl |= (set ? 0 : E100_RTS_MASK); /* RTS is active low */ info->port[REG_REC_CTRL] = info->rx_ctrl; + restore_flags(flags); #ifdef SERIAL_DEBUG_IO printk("ser%i rts %i\n", info->line, set); #endif @@ -1326,6 +1514,7 @@ e100_disable_rxdma_irq(struct e100_seria #ifdef SERIAL_DEBUG_INTR printk("rxdma_irq(%d): 0\n",info->line); #endif + DINTR1(DEBUG_LOG(info->line,"IRQ disable_rxdma_irq %i\n", info->line)); *R_IRQ_MASK2_CLR = (info->irq << 2) | (info->irq << 3); } @@ -1335,30 +1524,33 @@ e100_enable_rxdma_irq(struct e100_serial #ifdef SERIAL_DEBUG_INTR printk("rxdma_irq(%d): 1\n",info->line); #endif + DINTR1(DEBUG_LOG(info->line,"IRQ enable_rxdma_irq %i\n", info->line)); *R_IRQ_MASK2_SET = (info->irq << 2) | (info->irq << 3); } /* the tx DMA uses only dma_descr interrupt */ -static inline void +static _INLINE_ void e100_disable_txdma_irq(struct e100_serial *info) { #ifdef SERIAL_DEBUG_INTR printk("txdma_irq(%d): 0\n",info->line); #endif + DINTR1(DEBUG_LOG(info->line,"IRQ disable_txdma_irq %i\n", info->line)); *R_IRQ_MASK2_CLR = info->irq; } -static inline void +static _INLINE_ void e100_enable_txdma_irq(struct e100_serial *info) { #ifdef SERIAL_DEBUG_INTR printk("txdma_irq(%d): 1\n",info->line); #endif + DINTR1(DEBUG_LOG(info->line,"IRQ enable_txdma_irq %i\n", info->line)); *R_IRQ_MASK2_SET = info->irq; } -static inline void +static _INLINE_ void e100_disable_txdma_channel(struct e100_serial *info) { unsigned long flags; @@ -1367,32 +1559,46 @@ e100_disable_txdma_channel(struct e100_s * ( set to something other then serialX) */ save_flags(flags); - cli(); + cli(); + DFLOW(DEBUG_LOG(info->line, "disable_txdma_channel %i\n", info->line)); if (info->line == 0) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma6); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma6, unused); + if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma6)) == + IO_STATE(R_GEN_CONFIG, dma6, serial0)) { + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma6); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma6, unused); + } } else if (info->line == 1) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma8); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma8, usb); + if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma8)) == + IO_STATE(R_GEN_CONFIG, dma8, serial1)) { + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma8); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma8, usb); + } } else if (info->line == 2) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma2); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma2, par0); + if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma2)) == + IO_STATE(R_GEN_CONFIG, dma2, serial2)) { + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma2); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma2, par0); + } } else if (info->line == 3) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma4); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, par1); + if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma4)) == + IO_STATE(R_GEN_CONFIG, dma4, serial3)) { + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma4); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, par1); + } } *R_GEN_CONFIG = genconfig_shadow; restore_flags(flags); } -static inline void +static _INLINE_ void e100_enable_txdma_channel(struct e100_serial *info) { unsigned long flags; save_flags(flags); - cli(); + cli(); + DFLOW(DEBUG_LOG(info->line, "enable_txdma_channel %i\n", info->line)); /* Enable output DMA channel for the serial port in question */ if (info->line == 0) { genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma6); @@ -1411,6 +1617,70 @@ e100_enable_txdma_channel(struct e100_se restore_flags(flags); } +static _INLINE_ void +e100_disable_rxdma_channel(struct e100_serial *info) +{ + unsigned long flags; + + /* Disable input DMA channel for the serial port in question + * ( set to something other then serialX) + */ + save_flags(flags); + cli(); + if (info->line == 0) { + if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma7)) == + IO_STATE(R_GEN_CONFIG, dma7, serial0)) { + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma7); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma7, unused); + } + } else if (info->line == 1) { + if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma9)) == + IO_STATE(R_GEN_CONFIG, dma9, serial1)) { + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma9); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma9, usb); + } + } else if (info->line == 2) { + if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma3)) == + IO_STATE(R_GEN_CONFIG, dma3, serial2)) { + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma3); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma3, par0); + } + } else if (info->line == 3) { + if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma5)) == + IO_STATE(R_GEN_CONFIG, dma5, serial3)) { + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma5); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma5, par1); + } + } + *R_GEN_CONFIG = genconfig_shadow; + restore_flags(flags); +} + + +static _INLINE_ void +e100_enable_rxdma_channel(struct e100_serial *info) +{ + unsigned long flags; + + save_flags(flags); + cli(); + /* Enable input DMA channel for the serial port in question */ + if (info->line == 0) { + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma7); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma7, serial0); + } else if (info->line == 1) { + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma9); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma9, serial1); + } else if (info->line == 2) { + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma3); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma3, serial2); + } else if (info->line == 3) { + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma5); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma5, serial3); + } + *R_GEN_CONFIG = genconfig_shadow; + restore_flags(flags); +} #ifdef SERIAL_HANDLE_EARLY_ERRORS /* in order to detect and fix errors on the first byte @@ -1422,6 +1692,7 @@ e100_disable_serial_data_irq(struct e100 #ifdef SERIAL_DEBUG_INTR printk("ser_irq(%d): 0\n",info->line); #endif + DINTR1(DEBUG_LOG(info->line,"IRQ disable data_irq %i\n", info->line)); *R_IRQ_MASK1_CLR = (1U << (8+2*info->line)); } @@ -1434,10 +1705,49 @@ e100_enable_serial_data_irq(struct e100_ (8+2*info->line), (1U << (8+2*info->line))); #endif + DINTR1(DEBUG_LOG(info->line,"IRQ enable data_irq %i\n", info->line)); *R_IRQ_MASK1_SET = (1U << (8+2*info->line)); } #endif +static inline void +e100_disable_serial_tx_ready_irq(struct e100_serial *info) +{ +#ifdef SERIAL_DEBUG_INTR + printk("ser_tx_irq(%d): 0\n",info->line); +#endif + DINTR1(DEBUG_LOG(info->line,"IRQ disable ready_irq %i\n", info->line)); + *R_IRQ_MASK1_CLR = (1U << (8+1+2*info->line)); +} + +static inline void +e100_enable_serial_tx_ready_irq(struct e100_serial *info) +{ +#ifdef SERIAL_DEBUG_INTR + printk("ser_tx_irq(%d): 1\n",info->line); + printk("**** %d = %d\n", + (8+1+2*info->line), + (1U << (8+1+2*info->line))); +#endif + DINTR2(DEBUG_LOG(info->line,"IRQ enable ready_irq %i\n", info->line)); + *R_IRQ_MASK1_SET = (1U << (8+1+2*info->line)); +} + +static inline void e100_enable_rx_irq(struct e100_serial *info) +{ + if (info->uses_dma_in) + e100_enable_rxdma_irq(info); + else + e100_enable_serial_data_irq(info); +} +static inline void e100_disable_rx_irq(struct e100_serial *info) +{ + if (info->uses_dma_in) + e100_disable_rxdma_irq(info); + else + e100_disable_serial_data_irq(info); +} + #if defined(CONFIG_ETRAX_RS485) /* Enable RS-485 mode on selected port. This is UGLY. */ static int @@ -1448,10 +1758,23 @@ e100_enable_rs485(struct tty_struct *tty #if defined(CONFIG_ETRAX_RS485_ON_PA) *R_PORT_PA_DATA = port_pa_data_shadow |= (1 << rs485_pa_bit); #endif +#if defined(CONFIG_ETRAX_RS485_ON_PORT_G) + REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow, + rs485_port_g_bit, 1); +#endif +#if defined(CONFIG_ETRAX_RS485_LTC1387) + REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow, + CONFIG_ETRAX_RS485_LTC1387_DXEN_PORT_G_BIT, 1); + REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow, + CONFIG_ETRAX_RS485_LTC1387_RXEN_PORT_G_BIT, 1); +#endif info->rs485.rts_on_send = 0x01 & r->rts_on_send; info->rs485.rts_after_sent = 0x01 & r->rts_after_sent; - info->rs485.delay_rts_before_send = r->delay_rts_before_send; + if (r->delay_rts_before_send >= 1000) + info->rs485.delay_rts_before_send = 1000; + else + info->rs485.delay_rts_before_send = r->delay_rts_before_send; info->rs485.enabled = r->enabled; /* printk("rts: on send = %i, after = %i, enabled = %i", info->rs485.rts_on_send, @@ -1491,7 +1814,7 @@ static void rs485_toggle_rts_timer_funct e100_rts(info, info->rs485.rts_after_sent); #if defined(CONFIG_ETRAX_RS485_DISABLE_RECEIVER) e100_enable_rx(info); - e100_enable_rxdma_irq(info); + e100_enable_rx_irq(info); #endif } #endif @@ -1513,8 +1836,12 @@ rs_stop(struct tty_struct *tty) if (info) { unsigned long flags; unsigned long xoff; - + save_flags(flags); cli(); + DFLOW(DEBUG_LOG(info->line, "XOFF rs_stop xmit %i\n", + CIRC_CNT(info->xmit.head, + info->xmit.tail,SERIAL_XMIT_SIZE))); + xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->tty)); xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, stop); if (tty->termios->c_iflag & IXON ) { @@ -1535,6 +1862,9 @@ rs_start(struct tty_struct *tty) unsigned long xoff; save_flags(flags); cli(); + DFLOW(DEBUG_LOG(info->line, "XOFF rs_start xmit %i\n", + CIRC_CNT(info->xmit.head, + info->xmit.tail,SERIAL_XMIT_SIZE))); xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(tty)); xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable); if (tty->termios->c_iflag & IXON ) { @@ -1542,6 +1872,9 @@ rs_start(struct tty_struct *tty) } *((unsigned long *)&info->port[REG_XOFF]) = xoff; + if (!info->uses_dma_out && + info->xmit.head != info->xmit.tail && info->xmit.buf) + e100_enable_serial_tx_ready_irq(info); restore_flags(flags); } @@ -1576,6 +1909,8 @@ static _INLINE_ void rs_sched_event(struct e100_serial *info, int event) { + if (info->event & (1 << event)) + return; info->event |= 1 << event; schedule_work(&info->work); } @@ -1592,7 +1927,7 @@ rs_sched_event(struct e100_serial *info, */ static void -transmit_chars(struct e100_serial *info) +transmit_chars_dma(struct e100_serial *info) { unsigned int c, sentl; struct etrax_dma_descr *descr; @@ -1600,11 +1935,11 @@ transmit_chars(struct e100_serial *info) #ifdef CONFIG_SVINTO_SIM /* This will output too little if tail is not 0 always since * we don't reloop to send the other part. Anyway this SHOULD be a - * no-op - transmit_chars would never really be called during sim + * no-op - transmit_chars_dma would never really be called during sim * since rs_write does not write into the xmit buffer then. */ if (info->xmit.tail) - printk("Error in serial.c:transmit_chars(), tail!=0\n"); + printk("Error in serial.c:transmit_chars-dma(), tail!=0\n"); if (info->xmit.head != info->xmit.tail) { SIMCOUT(info->xmit.buf + info->xmit.tail, CIRC_CNT(info->xmit.head, @@ -1626,7 +1961,7 @@ transmit_chars(struct e100_serial *info) #endif if (!info->tr_running) { /* weirdo... we shouldn't get here! */ - printk(KERN_WARNING "Achtung: transmit_chars with !tr_running\n"); + printk(KERN_WARNING "Achtung: transmit_chars_dma with !tr_running\n"); return; } @@ -1642,6 +1977,8 @@ transmit_chars(struct e100_serial *info) /* otherwise we find the amount of data sent here */ sentl = descr->hw_len; + DFLOW(DEBUG_LOG(info->line, "TX %i done\n", sentl)); + /* update stats */ info->icount.tx += sentl; @@ -1659,6 +1996,13 @@ transmit_chars(struct e100_serial *info) c = CIRC_CNT_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); + /* Don't send all in one DMA transfer - divide it so we wake up + * application before all is sent + */ + + if (c >= 4*WAKEUP_CHARS) + c = c/2; + if (c <= 0) { /* our job here is done, don't schedule any new DMA transfer */ info->tr_running = 0; @@ -1678,17 +2022,17 @@ transmit_chars(struct e100_serial *info) /* ok we can schedule a dma send of c chars starting at info->xmit.tail */ /* set up the descriptor correctly for output */ - + DFLOW(DEBUG_LOG(info->line, "TX %i\n", c)); descr->ctrl = d_int | d_eol | d_wait; /* Wait needed for tty_wait_until_sent() */ descr->sw_len = c; descr->buf = virt_to_phys(info->xmit.buf + info->xmit.tail); descr->status = 0; *info->ofirstadr = virt_to_phys(descr); /* write to R_DMAx_FIRST */ - *info->ocmdadr = 1; /* dma command start -> R_DMAx_CMD */ + *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, start); /* DMA is now running (hopefully) */ -} /* transmit_chars */ +} /* transmit_chars_dma */ static void start_transmit(struct e100_serial *info) @@ -1702,15 +2046,17 @@ start_transmit(struct e100_serial *info) info->tr_descr.hw_len = 0; info->tr_descr.status = 0; info->tr_running = 1; - - transmit_chars(info); + if (info->uses_dma_out) + transmit_chars_dma(info); + else + e100_enable_serial_tx_ready_irq(info); } /* start_transmit */ #ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER static int serial_fast_timer_started = 0; static int serial_fast_timer_expired = 0; static void flush_timeout_function(unsigned long data); -#define START_FLUSH_FAST_TIMER(info, string) {\ +#define START_FLUSH_FAST_TIMER_TIME(info, string, usec) {\ unsigned long timer_flags; \ save_flags(timer_flags); \ cli(); \ @@ -1721,7 +2067,7 @@ static void flush_timeout_function(unsig start_one_shot_timer(&fast_timers[info->line], \ flush_timeout_function, \ (unsigned long)info, \ - info->char_time_usec*4, \ + (usec), \ string); \ } \ else { \ @@ -1729,8 +2075,10 @@ static void flush_timeout_function(unsig } \ restore_flags(timer_flags); \ } +#define START_FLUSH_FAST_TIMER(info, string) START_FLUSH_FAST_TIMER_TIME(info, string, info->flush_time_usec) #else +#define START_FLUSH_FAST_TIMER_TIME(info, string, usec) #define START_FLUSH_FAST_TIMER(info, string) #endif @@ -1775,17 +2123,26 @@ static int add_char_and_flag(struct e100_serial *info, unsigned char data, unsigned char flag) { struct etrax_recv_buffer *buffer; + if (info->uses_dma_in) { + if (!(buffer = alloc_recv_buffer(4))) + return 0; - if (!(buffer = alloc_recv_buffer(4))) - return 0; - - buffer->length = 1; - buffer->error = flag; - buffer->buffer[0] = data; + buffer->length = 1; + buffer->error = flag; + buffer->buffer[0] = data; - append_recv_buffer(info, buffer); + append_recv_buffer(info, buffer); - info->icount.rx++; + info->icount.rx++; + } else { + struct tty_struct *tty = info->tty; + *tty->flip.char_buf_ptr = data; + *tty->flip.flag_buf_ptr = flag; + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + info->icount.rx++; + } return 1; } @@ -1847,7 +2204,14 @@ handle_all_descr_data(struct e100_serial /* Reset the status information */ descr->status = 0; - DEBUG_LOG(info->line, "recvl %lu\n", recvl); + DFLOW( DEBUG_LOG(info->line, "RX %lu\n", recvl); + if (info->tty->stopped) { + unsigned char *buf = phys_to_virt(descr->buf); + DEBUG_LOG(info->line, "rx 0x%02X\n", buf[0]); + DEBUG_LOG(info->line, "rx 0x%02X\n", buf[1]); + DEBUG_LOG(info->line, "rx 0x%02X\n", buf[2]); + } + ); /* update stats */ info->icount.rx += recvl; @@ -1859,7 +2223,7 @@ handle_all_descr_data(struct e100_serial } static _INLINE_ void -receive_chars(struct e100_serial *info) +receive_chars_dma(struct e100_serial *info) { struct tty_struct *tty; unsigned char rstat; @@ -1881,7 +2245,8 @@ receive_chars(struct e100_serial *info) return; #ifdef SERIAL_HANDLE_EARLY_ERRORS - e100_enable_serial_data_irq(info); + if (info->uses_dma_in) + e100_enable_serial_data_irq(info); #endif if (info->errorcode == ERRCODE_INSERT_BREAK) @@ -1891,6 +2256,9 @@ receive_chars(struct e100_serial *info) /* Read the status register to detect errors */ rstat = info->port[REG_STATUS]; + if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect) ) { + DFLOW(DEBUG_LOG(info->line, "XOFF detect stat %x\n", rstat)); + } if (rstat & SER_ERROR_MASK) { /* If we got an error, we must reset it by reading the @@ -1959,16 +2327,16 @@ start_receive(struct e100_serial *info) */ return; #endif - - /* reset the input dma channel to be sure it works */ - - *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) == - IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset)); - info->tty->flip.count = 0; + if (info->uses_dma_in) { + /* reset the input dma channel to be sure it works */ - start_recv_dma(info); + *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset); + while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) == + IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset)); + + start_recv_dma(info); + } } @@ -2014,27 +2382,27 @@ tr_interrupt(int irq, void *dev_id, stru for (i = 0; i < NR_PORTS; i++) { info = rs_table + i; - if (!info->enabled || !info->uses_dma) + if (!info->enabled || !info->uses_dma_out) continue; /* check for dma_descr (don't need to check for dma_eop in output dma for serial */ if (ireg & info->irq) { handled = 1; /* we can send a new dma bunch. make it so. */ - DEBUG_LOG(info->line, "tr_interrupt %i\n", i); + DINTR2(DEBUG_LOG(info->line, "tr_interrupt %i\n", i)); /* Read jiffies_usec first, * we want this time to be as late as possible */ PROCSTAT(ser_stat[info->line].tx_dma_ints++); info->last_tx_active_usec = GET_JIFFIES_USEC(); info->last_tx_active = jiffies; - transmit_chars(info); + transmit_chars_dma(info); } /* FIXME: here we should really check for a change in the status lines and if so call status_handle(info) */ } return IRQ_RETVAL(handled); -} +} /* tr_interrupt */ /* dma input channel interrupt handler */ @@ -2054,7 +2422,7 @@ rec_interrupt(int irq, void *dev_id, str const char *s = "What? rec_interrupt in simulator??\n"; SIMCOUT(s,strlen(s)); } - return; + return IRQ_HANDLED; #endif /* find out the line that caused this irq and get it from rs_table */ @@ -2063,20 +2431,20 @@ rec_interrupt(int irq, void *dev_id, str for (i = 0; i < NR_PORTS; i++) { info = rs_table + i; - if (!info->enabled || !info->uses_dma) + if (!info->enabled || !info->uses_dma_in) continue; /* check for both dma_eop and dma_descr for the input dma channel */ if (ireg & ((info->irq << 2) | (info->irq << 3))) { handled = 1; /* we have received something */ - receive_chars(info); + receive_chars_dma(info); } /* FIXME: here we should really check for a change in the status lines and if so call status_handle(info) */ } return IRQ_RETVAL(handled); -} +} /* rec_interrupt */ static _INLINE_ int force_eop_if_needed(struct e100_serial *info) @@ -2116,20 +2484,21 @@ force_eop_if_needed(struct e100_serial * if (!info->forced_eop) { info->forced_eop = 1; PROCSTAT(ser_stat[info->line].timeout_flush_cnt++); - DEBUG_LOG(info->line, "timeout EOP %i\n", info->line); + TIMERD(DEBUG_LOG(info->line, "timeout EOP %i\n", info->line)); FORCE_EOP(info); } return 1; } -static _INLINE_ void +extern _INLINE_ void flush_to_flip_buffer(struct e100_serial *info) { struct tty_struct *tty; struct etrax_recv_buffer *buffer; unsigned int length; unsigned long flags; + int max_flip_size; if (!info->first_recv_buffer) return; @@ -2143,12 +2512,46 @@ flush_to_flip_buffer(struct e100_serial } length = tty->flip.count; + /* Don't flip more than the ldisc has room for. + * The return value from ldisc.receive_room(tty) - might not be up to + * date, the previous flip of up to TTY_FLIPBUF_SIZE might be on the + * processed and not accounted for yet. + * Since we use DMA, 1 SERIAL_DESCR_BUF_SIZE could be on the way. + * Lets buffer data here and let flow control take care of it. + * Since we normally flip large chunks, the ldisc don't react + * with throttle until too late if we flip to much. + */ + max_flip_size = tty->ldisc.receive_room(tty); + if (max_flip_size < 0) + max_flip_size = 0; + if (max_flip_size <= (TTY_FLIPBUF_SIZE + /* Maybe not accounted for */ + length + info->recv_cnt + /* We have this queued */ + 2*SERIAL_DESCR_BUF_SIZE + /* This could be on the way */ + TTY_THRESHOLD_THROTTLE)) { /* Some slack */ + /* check TTY_THROTTLED first so it indicates our state */ + if (!test_and_set_bit(TTY_THROTTLED, &tty->flags)) { + DFLOW(DEBUG_LOG(info->line,"flush_to_flip throttles room %lu\n", max_flip_size)); + rs_throttle(tty); + } +#if 0 + else if (max_flip_size <= (TTY_FLIPBUF_SIZE + /* Maybe not accounted for */ + length + info->recv_cnt + /* We have this queued */ + SERIAL_DESCR_BUF_SIZE + /* This could be on the way */ + TTY_THRESHOLD_THROTTLE)) { /* Some slack */ + DFLOW(DEBUG_LOG(info->line,"flush_to_flip throttles again! %lu\n", max_flip_size)); + rs_throttle(tty); + } +#endif + } + + if (max_flip_size > TTY_FLIPBUF_SIZE) + max_flip_size = TTY_FLIPBUF_SIZE; - while ((buffer = info->first_recv_buffer) && length < TTY_FLIPBUF_SIZE) { + while ((buffer = info->first_recv_buffer) && length < max_flip_size) { unsigned int count = buffer->length; - if (length + count > TTY_FLIPBUF_SIZE) - count = TTY_FLIPBUF_SIZE - length; + if (length + count > max_flip_size) + count = max_flip_size - length; memcpy(tty->flip.char_buf_ptr + length, buffer->buffer, count); memset(tty->flip.flag_buf_ptr + length, TTY_NORMAL, count); @@ -2156,6 +2559,7 @@ flush_to_flip_buffer(struct e100_serial length += count; info->recv_cnt -= count; + DFLIP(DEBUG_LOG(info->line,"flip: %i\n", length)); if (count == buffer->length) { info->first_recv_buffer = buffer->next; @@ -2171,9 +2575,30 @@ flush_to_flip_buffer(struct e100_serial info->last_recv_buffer = NULL; tty->flip.count = length; - + DFLIP(if (tty->ldisc.chars_in_buffer(tty) > 3500) { + DEBUG_LOG(info->line, "ldisc %lu\n", + tty->ldisc.chars_in_buffer(tty)); + DEBUG_LOG(info->line, "flip.count %lu\n", + tty->flip.count); + } + ); restore_flags(flags); + DFLIP( + if (1) { + + if (test_bit(TTY_DONT_FLIP, &tty->flags)) { + DEBUG_LOG(info->line, "*** TTY_DONT_FLIP set flip.count %i ***\n", tty->flip.count); + DEBUG_LOG(info->line, "*** recv_cnt %i\n", info->recv_cnt); + } else { + } + DEBUG_LOG(info->line, "*** rxtot %i\n", info->icount.rx); + DEBUG_LOG(info->line, "ldisc %lu\n", tty->ldisc.chars_in_buffer(tty)); + DEBUG_LOG(info->line, "room %lu\n", tty->ldisc.receive_room(tty)); + } + + ); + /* this includes a check for low-latency */ tty_flip_buffer_push(tty); } @@ -2181,12 +2606,19 @@ flush_to_flip_buffer(struct e100_serial static _INLINE_ void check_flush_timeout(struct e100_serial *info) { - force_eop_if_needed(info); - + /* Flip what we've got (if we can) */ flush_to_flip_buffer(info); + /* We might need to flip later, but not to fast + * since the system is busy processing input... */ if (info->first_recv_buffer) - START_FLUSH_FAST_TIMER(info, "flip"); + START_FLUSH_FAST_TIMER_TIME(info, "flip", 2000); + + /* Force eop last, since data might have come while we're processing + * and if we started the slow timer above, we won't start a fast + * below. + */ + force_eop_if_needed(info); } #ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER @@ -2222,7 +2654,7 @@ timed_flush_handler(unsigned long ptr) for (i = 0; i < NR_PORTS; i++) { info = rs_table + i; - if (info->uses_dma) + if (info->uses_dma_in) check_flush_timeout(info); } @@ -2301,14 +2733,158 @@ TODO: The break will be delayed until an */ -extern irqreturn_t _INLINE_ handle_ser_interrupt(struct e100_serial *info) +extern _INLINE_ +struct e100_serial * handle_ser_rx_interrupt_no_dma(struct e100_serial *info) { - unsigned char rstat = info->port[REG_STATUS]; + unsigned long data_read; + struct tty_struct *tty = info->tty; + + if (!tty) { + printk("!NO TTY!\n"); + return info; + } + if (tty->flip.count >= TTY_FLIPBUF_SIZE - TTY_THRESHOLD_THROTTLE) { + /* check TTY_THROTTLED first so it indicates our state */ + if (!test_and_set_bit(TTY_THROTTLED, &tty->flags)) { + DFLOW(DEBUG_LOG(info->line, "rs_throttle flip.count: %i\n", tty->flip.count)); + rs_throttle(tty); + } + } + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + DEBUG_LOG(info->line, "force FLIP! %i\n", tty->flip.count); + tty->flip.work.func((void *) tty); + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + DEBUG_LOG(info->line, "FLIP FULL! %i\n", tty->flip.count); + return info; /* if TTY_DONT_FLIP is set */ + } + } + /* Read data and status at the same time */ + data_read = *((unsigned long *)&info->port[REG_DATA_STATUS32]); +more_data: + if (data_read & IO_MASK(R_SERIAL0_READ, xoff_detect) ) { + DFLOW(DEBUG_LOG(info->line, "XOFF detect\n", 0)); + } + DINTR2(DEBUG_LOG(info->line, "ser_rx %c\n", IO_EXTRACT(R_SERIAL0_READ, data_in, data_read))); + + if (data_read & ( IO_MASK(R_SERIAL0_READ, framing_err) | + IO_MASK(R_SERIAL0_READ, par_err) | + IO_MASK(R_SERIAL0_READ, overrun) )) { + /* An error */ + info->last_rx_active_usec = GET_JIFFIES_USEC(); + info->last_rx_active = jiffies; + DINTR1(DEBUG_LOG(info->line, "ser_rx err stat_data %04X\n", data_read)); + DLOG_INT_TRIG( + if (!log_int_trig1_pos) { + log_int_trig1_pos = log_int_pos; + log_int(rdpc(), 0, 0); + } + ); + + + if ( ((data_read & IO_MASK(R_SERIAL0_READ, data_in)) == 0) && + (data_read & IO_MASK(R_SERIAL0_READ, framing_err)) ) { + /* Most likely a break, but we get interrupts over and + * over again. + */ + + if (!info->break_detected_cnt) { + DEBUG_LOG(info->line, "#BRK start\n", 0); + } + if (data_read & IO_MASK(R_SERIAL0_READ, rxd)) { + /* The RX pin is high now, so the break + * must be over, but.... + * we can't really know if we will get another + * last byte ending the break or not. + * And we don't know if the byte (if any) will + * have an error or look valid. + */ + DEBUG_LOG(info->line, "# BL BRK\n", 0); + info->errorcode = ERRCODE_INSERT_BREAK; + } + info->break_detected_cnt++; + } else { + /* The error does not look like a break, but could be + * the end of one + */ + if (info->break_detected_cnt) { + DEBUG_LOG(info->line, "EBRK %i\n", info->break_detected_cnt); + info->errorcode = ERRCODE_INSERT_BREAK; + } else { + if (info->errorcode == ERRCODE_INSERT_BREAK) { + info->icount.brk++; + *tty->flip.char_buf_ptr = 0; + *tty->flip.flag_buf_ptr = TTY_BREAK; + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + info->icount.rx++; + } + *tty->flip.char_buf_ptr = IO_EXTRACT(R_SERIAL0_READ, data_in, data_read); + + if (data_read & IO_MASK(R_SERIAL0_READ, par_err)) { + info->icount.parity++; + *tty->flip.flag_buf_ptr = TTY_PARITY; + } else if (data_read & IO_MASK(R_SERIAL0_READ, overrun)) { + info->icount.overrun++; + *tty->flip.flag_buf_ptr = TTY_OVERRUN; + } else if (data_read & IO_MASK(R_SERIAL0_READ, framing_err)) { + info->icount.frame++; + *tty->flip.flag_buf_ptr = TTY_FRAME; + } + info->errorcode = 0; + } + info->break_detected_cnt = 0; + } + } else if (data_read & IO_MASK(R_SERIAL0_READ, data_avail)) { + /* No error */ + DLOG_INT_TRIG( + if (!log_int_trig1_pos) { + if (log_int_pos >= log_int_size) { + log_int_pos = 0; + } + log_int_trig0_pos = log_int_pos; + log_int(rdpc(), 0, 0); + } + ); + *tty->flip.char_buf_ptr = IO_EXTRACT(R_SERIAL0_READ, data_in, data_read); + *tty->flip.flag_buf_ptr = 0; + } else { + DEBUG_LOG(info->line, "ser_rx int but no data_avail %08lX\n", data_read); + } + + + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + info->icount.rx++; + data_read = *((unsigned long *)&info->port[REG_DATA_STATUS32]); + if (data_read & IO_MASK(R_SERIAL0_READ, data_avail)) { + DEBUG_LOG(info->line, "ser_rx %c in loop\n", IO_EXTRACT(R_SERIAL0_READ, data_in, data_read)); + goto more_data; + } + + tty_flip_buffer_push(info->tty); + return info; +} + +extern _INLINE_ +struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info) +{ + unsigned char rstat; #ifdef SERIAL_DEBUG_INTR printk("Interrupt from serport %d\n", i); #endif /* DEBUG_LOG(info->line, "ser_interrupt stat %03X\n", rstat | (i << 8)); */ + if (!info->uses_dma_in) { + return handle_ser_rx_interrupt_no_dma(info); + } + /* DMA is used */ + rstat = info->port[REG_STATUS]; + if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect) ) { + DFLOW(DEBUG_LOG(info->line, "XOFF detect\n", 0)); + } + if (rstat & SER_ERROR_MASK) { unsigned char data; @@ -2318,7 +2894,8 @@ extern irqreturn_t _INLINE_ handle_ser_i * data_in field */ data = info->port[REG_DATA]; - + DINTR1(DEBUG_LOG(info->line, "ser_rx! %c\n", data)); + DINTR1(DEBUG_LOG(info->line, "ser_rx err stat %02X\n", rstat)); if (!data && (rstat & SER_FRAMING_ERR_MASK)) { /* Most likely a break, but we get interrupts over and * over again. @@ -2347,15 +2924,22 @@ extern irqreturn_t _INLINE_ handle_ser_i DEBUG_LOG(info->line, "EBRK %i\n", info->break_detected_cnt); info->errorcode = ERRCODE_INSERT_BREAK; } else { - if (info->errorcode == ERRCODE_INSERT_BREAK) + if (info->errorcode == ERRCODE_INSERT_BREAK) { + info->icount.brk++; add_char_and_flag(info, '\0', TTY_BREAK); + } - if (rstat & SER_PAR_ERR_MASK) + if (rstat & SER_PAR_ERR_MASK) { + info->icount.parity++; add_char_and_flag(info, data, TTY_PARITY); - else if (rstat & SER_OVERRUN_MASK) + } else if (rstat & SER_OVERRUN_MASK) { + info->icount.overrun++; add_char_and_flag(info, data, TTY_OVERRUN); - else if (rstat & SER_FRAMING_ERR_MASK) + } else if (rstat & SER_FRAMING_ERR_MASK) { + info->icount.frame++; add_char_and_flag(info, data, TTY_FRAME); + } + info->errorcode = 0; } info->break_detected_cnt = 0; @@ -2379,7 +2963,7 @@ extern irqreturn_t _INLINE_ handle_ser_i if (elapsed_usec < 2*info->char_time_usec) { DEBUG_LOG(info->line, "FBRK %i\n", info->line); /* Report as BREAK (error) and let - * receive_chars() handle it + * receive_chars_dma() handle it */ info->errorcode = ERRCODE_SET_BREAK; } else { @@ -2392,38 +2976,196 @@ extern irqreturn_t _INLINE_ handle_ser_i printk("** OK, disabling ser_interrupts\n"); #endif e100_disable_serial_data_irq(info); - + DINTR2(DEBUG_LOG(info->line, "ser_rx OK %d\n", info->line)); info->break_detected_cnt = 0; PROCSTAT(ser_stat[info->line].ser_ints_ok_cnt++); - DEBUG_LOG(info->line, "ser_int OK %d\n", info->line); } - /* Restarting the DMA never hurts */ *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart); START_FLUSH_FAST_TIMER(info, "ser_int"); - return IRQ_HANDLED; -} /* handle_ser_interrupt */ + return info; +} /* handle_ser_rx_interrupt */ + +extern _INLINE_ void handle_ser_tx_interrupt(struct e100_serial *info) +{ + unsigned long flags; + + if (info->x_char) { + unsigned char rstat; + DFLOW(DEBUG_LOG(info->line, "tx_int: xchar 0x%02X\n", info->x_char)); + save_flags(flags); cli(); + rstat = info->port[REG_STATUS]; + DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat)); + + info->port[REG_TR_DATA] = info->x_char; + info->icount.tx++; + info->x_char = 0; + /* We must enable since it is disabled in ser_interrupt */ + e100_enable_serial_tx_ready_irq(info); + restore_flags(flags); + return; + } + if (info->uses_dma_out) { + unsigned char rstat; + int i; + /* We only use normal tx interrupt when sending x_char */ + DFLOW(DEBUG_LOG(info->line, "tx_int: xchar sent\n", 0)); + save_flags(flags); cli(); + rstat = info->port[REG_STATUS]; + DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat)); + e100_disable_serial_tx_ready_irq(info); + if (info->tty->stopped) + rs_stop(info->tty); + /* Enable the DMA channel and tell it to continue */ + e100_enable_txdma_channel(info); + /* Wait 12 cycles before doing the DMA command */ + for(i = 6; i > 0; i--) + nop(); + + *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, continue); + restore_flags(flags); + return; + } + /* Normal char-by-char interrupt */ + if (info->xmit.head == info->xmit.tail + || info->tty->stopped + || info->tty->hw_stopped) { + DFLOW(DEBUG_LOG(info->line, "tx_int: stopped %i\n", info->tty->stopped)); + e100_disable_serial_tx_ready_irq(info); + info->tr_running = 0; + return; + } + DINTR2(DEBUG_LOG(info->line, "tx_int %c\n", info->xmit.buf[info->xmit.tail])); + /* Send a byte, rs485 timing is critical so turn of ints */ + save_flags(flags); cli(); + info->port[REG_TR_DATA] = info->xmit.buf[info->xmit.tail]; + info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1); + info->icount.tx++; + if (info->xmit.head == info->xmit.tail) { +#if defined(CONFIG_ETRAX_RS485) && defined(CONFIG_ETRAX_FAST_TIMER) + if (info->rs485.enabled) { + /* Set a short timer to toggle RTS */ + start_one_shot_timer(&fast_timers_rs485[info->line], + rs485_toggle_rts_timer_function, + (unsigned long)info, + info->char_time_usec*2, + "RS-485"); + } +#endif /* RS485 */ + info->last_tx_active_usec = GET_JIFFIES_USEC(); + info->last_tx_active = jiffies; + e100_disable_serial_tx_ready_irq(info); + info->tr_running = 0; + DFLOW(DEBUG_LOG(info->line, "tx_int: stop2\n", 0)); + } else { + /* We must enable since it is disabled in ser_interrupt */ + e100_enable_serial_tx_ready_irq(info); + } + restore_flags(flags); + + if (CIRC_CNT(info->xmit.head, + info->xmit.tail, + SERIAL_XMIT_SIZE) < WAKEUP_CHARS) + rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); + +} /* handle_ser_tx_interrupt */ +/* result of time measurements: + * RX duration 54-60 us when doing something, otherwise 6-9 us + * ser_int duration: just sending: 8-15 us normally, up to 73 us + */ static irqreturn_t ser_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + static volatile int tx_started = 0; struct e100_serial *info; int i; + unsigned long flags; + unsigned long irq_mask1_rd; + unsigned long data_mask = (1 << (8+2*0)); /* ser0 data_avail */ int handled = 0; + static volatile unsigned long reentered_ready_mask = 0; + save_flags(flags); cli(); + irq_mask1_rd = *R_IRQ_MASK1_RD; + /* First handle all rx interrupts with ints disabled */ + info = rs_table; + irq_mask1_rd &= e100_ser_int_mask; for (i = 0; i < NR_PORTS; i++) { - info = rs_table + i; - - if (!info->enabled || !info->uses_dma) - continue; - - /* Which line caused the irq? */ - if (*R_IRQ_MASK1_RD & (1U << (8+2*info->line))) { + /* Which line caused the data irq? */ + if (irq_mask1_rd & data_mask) { handled = 1; - handle_ser_interrupt(info); + handle_ser_rx_interrupt(info); } + info += 1; + data_mask <<= 2; } + /* Handle tx interrupts with interrupts enabled so we + * can take care of new data interrupts while transmitting + * We protect the tx part with the tx_started flag. + * We disable the tr_ready interrupts we are about to handle and + * unblock the serial interrupt so new serial interrupts may come. + * + * If we get a new interrupt: + * - it migth be due to synchronous serial ports. + * - serial irq will be blocked by general irq handler. + * - async data will be handled above (sync will be ignored). + * - tx_started flag will prevent us from trying to send again and + * we will exit fast - no need to unblock serial irq. + * - Next (sync) serial interrupt handler will be runned with + * disabled interrupt due to restore_flags() at end of function, + * so sync handler will not be preempted or reentered. + */ + if (!tx_started) { + unsigned long ready_mask; + unsigned long + tx_started = 1; + /* Only the tr_ready interrupts left */ + irq_mask1_rd &= (IO_MASK(R_IRQ_MASK1_RD, ser0_ready) | + IO_MASK(R_IRQ_MASK1_RD, ser1_ready) | + IO_MASK(R_IRQ_MASK1_RD, ser2_ready) | + IO_MASK(R_IRQ_MASK1_RD, ser3_ready)); + while (irq_mask1_rd) { + /* Disable those we are about to handle */ + *R_IRQ_MASK1_CLR = irq_mask1_rd; + /* Unblock the serial interrupt */ + *R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, serial, set); + + sti(); + ready_mask = (1 << (8+1+2*0)); /* ser0 tr_ready */ + info = rs_table; + for (i = 0; i < NR_PORTS; i++) { + /* Which line caused the ready irq? */ + if (irq_mask1_rd & ready_mask) { + handled = 1; + handle_ser_tx_interrupt(info); + } + info += 1; + ready_mask <<= 2; + } + /* handle_ser_tx_interrupt enables tr_ready interrupts */ + cli(); + /* Handle reentered TX interrupt */ + irq_mask1_rd = reentered_ready_mask; + } + cli(); + tx_started = 0; + } else { + unsigned long ready_mask; + ready_mask = irq_mask1_rd & (IO_MASK(R_IRQ_MASK1_RD, ser0_ready) | + IO_MASK(R_IRQ_MASK1_RD, ser1_ready) | + IO_MASK(R_IRQ_MASK1_RD, ser2_ready) | + IO_MASK(R_IRQ_MASK1_RD, ser3_ready)); + if (ready_mask) { + reentered_ready_mask |= ready_mask; + /* Disable those we are about to handle */ + *R_IRQ_MASK1_CLR = ready_mask; + DFLOW(DEBUG_LOG(SERIAL_DEBUG_LINE, "ser_int reentered with TX %X\n", ready_mask)); + } + } + + restore_flags(flags); return IRQ_RETVAL(handled); } /* ser_interrupt */ #endif @@ -2489,7 +3231,7 @@ startup(struct e100_serial * info) info->xmit.buf = (unsigned char *) xmit_page; #ifdef SERIAL_DEBUG_OPEN - printk("starting up ttyS%d (xmit_buf 0x%p, recv_buf 0x%p)...\n", info->line, info->xmit.buf, info->recv.buf); + printk("starting up ttyS%d (xmit_buf 0x%p)...\n", info->line, info->xmit.buf); #endif #ifdef CONFIG_SVINTO_SIM @@ -2520,24 +3262,39 @@ startup(struct e100_serial * info) * Reset the DMA channels and make sure their interrupts are cleared */ - info->uses_dma = 1; - *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset); - *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset); - - /* Wait until reset cycle is complete */ - while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) == - IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset)); + if (info->dma_in_enabled) { + info->uses_dma_in = 1; + e100_enable_rxdma_channel(info); + + *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset); + + /* Wait until reset cycle is complete */ + while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) == + IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset)); + + /* Make sure the irqs are cleared */ + *info->iclrintradr = + IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) | + IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do); + } else { + e100_disable_rxdma_channel(info); + } - while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->ocmdadr) == - IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset)); + if (info->dma_out_enabled) { + info->uses_dma_out = 1; + e100_enable_txdma_channel(info); + *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset); - /* Make sure the irqs are cleared */ - *info->iclrintradr = - IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) | - IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do); - *info->oclrintradr = - IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) | - IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do); + while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->ocmdadr) == + IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset)); + + /* Make sure the irqs are cleared */ + *info->oclrintradr = + IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) | + IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do); + } else { + e100_disable_txdma_channel(info); + } if (info->tty) clear_bit(TTY_IO_ERROR, &info->tty->flags); @@ -2563,9 +3320,10 @@ startup(struct e100_serial * info) (void)info->port[REG_DATA]; /* enable the interrupts */ + if (info->uses_dma_out) + e100_enable_txdma_irq(info); - e100_enable_txdma_irq(info); - e100_enable_rxdma_irq(info); + e100_enable_rx_irq(info); info->tr_running = 0; /* to be sure we don't lock up the transmitter */ @@ -2606,20 +3364,28 @@ shutdown(struct e100_serial * info) #ifndef CONFIG_SVINTO_SIM /* shut down the transmitter and receiver */ - + DFLOW(DEBUG_LOG(info->line, "shutdown %i\n", info->line)); e100_disable_rx(info); info->port[REG_TR_CTRL] = (info->tx_ctrl &= ~0x40); - e100_disable_rxdma_irq(info); - e100_disable_txdma_irq(info); - - info->tr_running = 0; - - /* reset both dma channels */ + /* disable interrupts, reset dma channels */ + if (info->uses_dma_in) { + e100_disable_rxdma_irq(info); + *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset); + info->uses_dma_in = 0; + } else { + e100_disable_serial_data_irq(info); + } - *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset); - *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset); - info->uses_dma = 0; + if (info->uses_dma_out) { + e100_disable_txdma_irq(info); + info->tr_running = 0; + *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset); + info->uses_dma_out = 0; + } else { + e100_disable_serial_tx_ready_irq(info); + info->tr_running = 0; + } #endif /* CONFIG_SVINTO_SIM */ @@ -2667,7 +3433,7 @@ change_speed(struct e100_serial *info) { unsigned int cflag; unsigned long xoff; - + unsigned long flags; /* first some safety checks */ if (!info->tty || !info->tty->termios) @@ -2676,17 +3442,80 @@ change_speed(struct e100_serial *info) return; cflag = info->tty->termios->c_cflag; - + /* possibly, the tx/rx should be disabled first to do this safely */ /* change baud-rate and write it to the hardware */ - - info->baud = cflag_to_baud(cflag); + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) { + /* Special baudrate */ + u32 mask = 0xFF << (info->line*8); /* Each port has 8 bits */ + unsigned long alt_source = + IO_STATE(R_ALT_SER_BAUDRATE, ser0_rec, normal) | + IO_STATE(R_ALT_SER_BAUDRATE, ser0_tr, normal); + /* R_ALT_SER_BAUDRATE selects the source */ + DBAUD(printk("Custom baudrate: baud_base/divisor %lu/%i\n", + (unsigned long)info->baud_base, info->custom_divisor)); + if (info->baud_base == SERIAL_PRESCALE_BASE) { + /* 0, 2-65535 (0=65536) */ + u16 divisor = info->custom_divisor; + /* R_SERIAL_PRESCALE (upper 16 bits of R_CLOCK_PRESCALE) */ + /* baudrate is 3.125MHz/custom_divisor */ + alt_source = + IO_STATE(R_ALT_SER_BAUDRATE, ser0_rec, prescale) | + IO_STATE(R_ALT_SER_BAUDRATE, ser0_tr, prescale); + alt_source = 0x11; + DBAUD(printk("Writing SERIAL_PRESCALE: divisor %i\n", divisor)); + *R_SERIAL_PRESCALE = divisor; + info->baud = SERIAL_PRESCALE_BASE/divisor; + } +#ifdef CONFIG_ETRAX_EXTERN_PB6CLK_ENABLED + else if ((info->baud_base==CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8 && + info->custom_divisor == 1) || + (info->baud_base==CONFIG_ETRAX_EXTERN_PB6CLK_FREQ && + info->custom_divisor == 8)) { + /* ext_clk selected */ + alt_source = + IO_STATE(R_ALT_SER_BAUDRATE, ser0_rec, extern) | + IO_STATE(R_ALT_SER_BAUDRATE, ser0_tr, extern); + DBAUD(printk("using external baudrate: %lu\n", CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8)); + info->baud = CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8; + } + } +#endif + else + { + /* Bad baudbase, we don't support using timer0 + * for baudrate. + */ + printk(KERN_WARNING "Bad baud_base/custom_divisor: %lu/%i\n", + (unsigned long)info->baud_base, info->custom_divisor); + } + r_alt_ser_baudrate_shadow &= ~mask; + r_alt_ser_baudrate_shadow |= (alt_source << (info->line*8)); + *R_ALT_SER_BAUDRATE = r_alt_ser_baudrate_shadow; + } else { + /* Normal baudrate */ + /* Make sure we use normal baudrate */ + u32 mask = 0xFF << (info->line*8); /* Each port has 8 bits */ + unsigned long alt_source = + IO_STATE(R_ALT_SER_BAUDRATE, ser0_rec, normal) | + IO_STATE(R_ALT_SER_BAUDRATE, ser0_tr, normal); + r_alt_ser_baudrate_shadow &= ~mask; + r_alt_ser_baudrate_shadow |= (alt_source << (info->line*8)); +#ifndef CONFIG_SVINTO_SIM + *R_ALT_SER_BAUDRATE = r_alt_ser_baudrate_shadow; +#endif /* CONFIG_SVINTO_SIM */ + + info->baud = cflag_to_baud(cflag); +#ifndef CONFIG_SVINTO_SIM + info->port[REG_BAUD] = cflag_to_etrax_baud(cflag); +#endif /* CONFIG_SVINTO_SIM */ + } #ifndef CONFIG_SVINTO_SIM - info->port[REG_BAUD] = cflag_to_etrax_baud(cflag); /* start with default settings and then fill in changes */ - + save_flags(flags); + cli(); /* 8 bit, no/even parity */ info->rx_ctrl &= ~(IO_MASK(R_SERIAL0_REC_CTRL, rec_bitnr) | IO_MASK(R_SERIAL0_REC_CTRL, rec_par_en) | @@ -2717,24 +3546,19 @@ change_speed(struct e100_serial *info) } if (cflag & CMSPAR) { - /* enable stick parity */ + /* enable stick parity, PARODD mean Mark which matches ETRAX */ info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_stick_par, stick); info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_stick_par, stick); - if (!(cflag & PARODD)) { - /* set mark parity */ - info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_par, odd); - info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_par, odd); - } - } else { - if (cflag & PARODD) { - /* set odd parity */ - info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_par, odd); - info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_par, odd); - } + } + if (cflag & PARODD) { + /* set odd parity (or Mark if CMSPAR) */ + info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_par, odd); + info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_par, odd); } if (cflag & CRTSCTS) { /* enable automatic CTS handling */ + DFLOW(DEBUG_LOG(info->line, "FLOW auto_cts enabled\n", 0)); info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, auto_cts, active); } @@ -2750,13 +3574,16 @@ change_speed(struct e100_serial *info) xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->tty)); xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable); if (info->tty->termios->c_iflag & IXON ) { + DFLOW(DEBUG_LOG(info->line, "FLOW XOFF enabled 0x%02X\n", STOP_CHAR(info->tty))); xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); } *((unsigned long *)&info->port[REG_XOFF]) = xoff; + restore_flags(flags); #endif /* !CONFIG_SVINTO_SIM */ update_char_time(info); + } /* change_speed */ /* start transmitting chars NOW */ @@ -2786,8 +3613,8 @@ rs_flush_chars(struct tty_struct *tty) restore_flags(flags); } -extern inline int -raw_write(struct tty_struct * tty, int from_user, +extern _INLINE_ int +rs_raw_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) { int c, ret = 0; @@ -2801,7 +3628,7 @@ raw_write(struct tty_struct * tty, int f #ifdef SERIAL_DEBUG_DATA if (info->line == SERIAL_DEBUG_LINE) - printk("raw_write (%d), status %d\n", + printk("rs_raw_write (%d), status %d\n", count, info->port[REG_STATUS]); #endif @@ -2811,6 +3638,9 @@ raw_write(struct tty_struct * tty, int f return count; #endif save_flags(flags); + DFLOW(DEBUG_LOG(info->line, "write count %i ", count)); + DFLOW(DEBUG_LOG(info->line, "ldisc %i\n", tty->ldisc.chars_in_buffer(tty))); + /* the cli/restore_flags pairs below are needed because the * DMA interrupt handler moves the info->xmit values. the memcpy @@ -2878,6 +3708,7 @@ raw_write(struct tty_struct * tty, int f * this does not need IRQ protection since if tr_running == 0 * the IRQ's are not running anyway for this port. */ + DFLOW(DEBUG_LOG(info->line, "write ret %i\n", ret)); if (info->xmit.head != info->xmit.tail && !tty->stopped && @@ -2887,7 +3718,7 @@ raw_write(struct tty_struct * tty, int f } return ret; -} /* raw_write() */ +} /* raw_raw_write() */ static int rs_write(struct tty_struct * tty, int from_user, @@ -2909,7 +3740,7 @@ rs_write(struct tty_struct * tty, int fr e100_rts(info, info->rs485.rts_on_send); #if defined(CONFIG_ETRAX_RS485_DISABLE_RECEIVER) e100_disable_rx(info); - e100_disable_rxdma_irq(info); + e100_enable_rx_irq(info); #endif if (info->rs485.delay_rts_before_send > 0) { @@ -2919,7 +3750,7 @@ rs_write(struct tty_struct * tty, int fr } #endif /* CONFIG_ETRAX_RS485 */ - count = raw_write(tty, from_user, buf, count); + count = rs_raw_write(tty, from_user, buf, count); #if defined(CONFIG_ETRAX_RS485) if (info->rs485.enabled) @@ -3003,23 +3834,33 @@ rs_flush_buffer(struct tty_struct *tty) * This function is used to send a high-priority XON/XOFF character to * the device * - * Since we use DMA we don't check for info->x_char in transmit_chars, - * just disable DMA channel and write the character when possible. + * Since we use DMA we don't check for info->x_char in transmit_chars_dma(), + * but we do it in handle_ser_tx_interrupt(). + * We disable DMA channel and enable tx ready interrupt and write the + * character when possible. */ static void rs_send_xchar(struct tty_struct *tty, char ch) { struct e100_serial *info = (struct e100_serial *)tty->driver_data; + unsigned long flags; + save_flags(flags); cli(); + if (info->uses_dma_out) { + /* Put the DMA on hold and disable the channel */ + *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, hold); + while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->ocmdadr) != + IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, hold)); + e100_disable_txdma_channel(info); + } - e100_disable_txdma_channel(info); - - /* Wait for tr_ready */ - while (!(info->port[REG_STATUS] & IO_MASK(R_SERIAL0_STATUS, tr_ready))) - /* wait */; - - /* Write the XON/XOFF char */ - info->port[REG_TR_DATA] = ch; + /* Must make sure transmitter is not stopped before we can transmit */ + if (tty->stopped) + rs_start(tty); - e100_enable_txdma_channel(info); + /* Enable manual transmit interrupt and send from there */ + DFLOW(DEBUG_LOG(info->line, "rs_send_xchar 0x%02X\n", ch)); + info->x_char = ch; + e100_enable_serial_tx_ready_irq(info); + restore_flags(flags); } /* @@ -3034,21 +3875,18 @@ static void rs_throttle(struct tty_struct * tty) { struct e100_serial *info = (struct e100_serial *)tty->driver_data; - unsigned long flags; #ifdef SERIAL_DEBUG_THROTTLE char buf[64]; - printk("throttle %s: %d....\n", _tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty)); + printk("throttle %s: %lu....\n", tty_name(tty, buf), + (unsigned long)tty->ldisc.chars_in_buffer(tty)); #endif + DFLOW(DEBUG_LOG(info->line,"rs_throttle %lu\n", tty->ldisc.chars_in_buffer(tty))); /* Do RTS before XOFF since XOFF might take some time */ if (tty->termios->c_cflag & CRTSCTS) { - /* Turn off RTS line (do this atomic) */ - save_flags(flags); - cli(); + /* Turn off RTS line */ e100_rts(info, 0); - restore_flags(flags); } if (I_IXOFF(tty)) rs_send_xchar(tty, STOP_CHAR(tty)); @@ -3059,21 +3897,18 @@ static void rs_unthrottle(struct tty_struct * tty) { struct e100_serial *info = (struct e100_serial *)tty->driver_data; - unsigned long flags; #ifdef SERIAL_DEBUG_THROTTLE char buf[64]; - printk("unthrottle %s: %d....\n", _tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty)); + printk("unthrottle %s: %lu....\n", tty_name(tty, buf), + (unsigned long)tty->ldisc.chars_in_buffer(tty)); #endif - + DFLOW(DEBUG_LOG(info->line,"rs_unthrottle ldisc %d\n", tty->ldisc.chars_in_buffer(tty))); + DFLOW(DEBUG_LOG(info->line,"rs_unthrottle flip.count: %i\n", tty->flip.count)); /* Do RTS before XOFF since XOFF might take some time */ if (tty->termios->c_cflag & CRTSCTS) { - /* Assert RTS line (do this atomic) */ - save_flags(flags); - cli(); + /* Assert RTS line */ e100_rts(info, 1); - restore_flags(flags); } if (I_IXOFF(tty)) { @@ -3110,8 +3945,10 @@ get_serial_info(struct e100_serial * inf tmp.port = (int)info->port; tmp.irq = info->irq; tmp.flags = info->flags; + tmp.baud_base = info->baud_base; tmp.close_delay = info->close_delay; tmp.closing_wait = info->closing_wait; + tmp.custom_divisor = info->custom_divisor; if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) return -EFAULT; return 0; @@ -3149,8 +3986,10 @@ set_serial_info(struct e100_serial *info * At this point, we start making changes..... */ + info->baud_base = new_serial.baud_base; info->flags = ((info->flags & ~ASYNC_FLAGS) | (new_serial.flags & ASYNC_FLAGS)); + info->custom_divisor = new_serial.custom_divisor; info->type = new_serial.type; info->close_delay = new_serial.close_delay; info->closing_wait = new_serial.closing_wait; @@ -3418,6 +4257,7 @@ rs_set_termios(struct tty_struct *tty, s change_speed(info); + /* Handle turning off CRTSCTS */ if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) { tty->hw_stopped = 0; @@ -3426,6 +4266,42 @@ rs_set_termios(struct tty_struct *tty, s } +/* In debugport.c - register a console write function that uses the normal + * serial driver + */ +typedef int (*debugport_write_function)(int i, const char *buf, unsigned int len); + +extern debugport_write_function debug_write_function; + +static int rs_debug_write_function(int i, const char *buf, unsigned int len) +{ + int cnt; + struct tty_struct *tty; + static int recurse_cnt = 0; + + tty = rs_table[i].tty; + if (tty) { + unsigned long flags; + if (recurse_cnt > 5) /* We skip this debug output */ + return 1; + + local_irq_save(flags); + recurse_cnt++; + do { + cnt = rs_write(tty, 0, buf, len); + if (cnt >= 0) { + buf += cnt; + len -= cnt; + } else + len = cnt; + } while(len > 0); + recurse_cnt--; + local_irq_restore(flags); + return 1; + } + return 0; +} + /* * ------------------------------------------------------------ * rs_close() @@ -3483,6 +4359,12 @@ rs_close(struct tty_struct *tty, struct } info->flags |= ASYNC_CLOSING; /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & ASYNC_NORMAL_ACTIVE) + info->normal_termios = *tty->termios; + /* * Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. */ @@ -3499,7 +4381,7 @@ rs_close(struct tty_struct *tty, struct #ifndef CONFIG_SVINTO_SIM e100_disable_rx(info); - e100_disable_rxdma_irq(info); + e100_disable_rx_irq(info); if (info->flags & ASYNC_INITIALIZED) { /* @@ -3538,6 +4420,16 @@ rs_close(struct tty_struct *tty, struct #if defined(CONFIG_ETRAX_RS485_ON_PA) *R_PORT_PA_DATA = port_pa_data_shadow &= ~(1 << rs485_pa_bit); #endif +#if defined(CONFIG_ETRAX_RS485_ON_PORT_G) + REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow, + rs485_port_g_bit, 0); +#endif +#if defined(CONFIG_ETRAX_RS485_LTC1387) + REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow, + CONFIG_ETRAX_RS485_LTC1387_DXEN_PORT_G_BIT, 0); + REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow, + CONFIG_ETRAX_RS485_LTC1387_RXEN_PORT_G_BIT, 0); +#endif } #endif } @@ -3637,8 +4529,9 @@ block_til_ready(struct tty_struct *tty, return 0; } - if (tty->termios->c_cflag & CLOCAL) - do_clocal = 1; + if (tty->termios->c_cflag & CLOCAL) { + do_clocal = 1; + } /* * Block waiting for the carrier detect and the line to become @@ -3664,7 +4557,7 @@ block_til_ready(struct tty_struct *tty, while (1) { save_flags(flags); cli(); - /* assert RTS and DTR */ + /* assert RTS and DTR */ e100_rts(info, 1); e100_dtr(info, 1); restore_flags(flags); @@ -3681,7 +4574,7 @@ block_til_ready(struct tty_struct *tty, #endif break; } - if (!(info->flags & ASYNC_CLOSING) && do_clocal) + if (!(info->flags & ASYNC_CLOSING) && do_clocal) /* && (do_clocal || DCD_IS_ASSERTED) */ break; if (signal_pending(current)) { @@ -3787,10 +4680,21 @@ rs_open(struct tty_struct *tty, struct f #endif return retval; } - + + if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) { + *tty->termios = info->normal_termios; + change_speed(info); + } + #ifdef SERIAL_DEBUG_OPEN printk("rs_open ttyS%d successful...\n", info->line); #endif + DLOG_INT_TRIG( log_int_pos = 0); + + DFLIP( if (info->line == SERIAL_DEBUG_LINE) { + info->icount.rx = 0; + } ); + return 0; } @@ -3798,10 +4702,11 @@ rs_open(struct tty_struct *tty, struct f * /proc fs routines.... */ -extern inline int line_info(char *buf, struct e100_serial *info) +extern _INLINE_ int line_info(char *buf, struct e100_serial *info) { char stat_buf[30]; int ret; + unsigned long tmp; ret = sprintf(buf, "%d: uart:E100 port:%lX irq:%d", info->line, (unsigned long)info->port, info->irq); @@ -3831,11 +4736,39 @@ extern inline int line_info(char *buf, s ret += sprintf(buf+ret, " tx:%lu rx:%lu", (unsigned long)info->icount.tx, (unsigned long)info->icount.rx); + tmp = CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); + if (tmp) { + ret += sprintf(buf+ret, " tx_pend:%lu/%lu", + (unsigned long)tmp, + (unsigned long)SERIAL_XMIT_SIZE); + } ret += sprintf(buf+ret, " rx_pend:%lu/%lu", (unsigned long)info->recv_cnt, (unsigned long)info->max_recv_cnt); +#if 1 + if (info->tty) { + + if (info->tty->stopped) + ret += sprintf(buf+ret, " stopped:%i", + (int)info->tty->stopped); + if (info->tty->hw_stopped) + ret += sprintf(buf+ret, " hw_stopped:%i", + (int)info->tty->hw_stopped); + } + + { + unsigned char rstat = info->port[REG_STATUS]; + if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect) ) + ret += sprintf(buf+ret, " xoff_detect:1"); + } + +#endif + + + + if (info->icount.frame) ret += sprintf(buf+ret, " fe:%lu", (unsigned long)info->icount.frame); @@ -3879,6 +4812,22 @@ int rs_read_proc(char *page, char **star len = 0; } } +#ifdef DEBUG_LOG_INCLUDED + for (i = 0; i < debug_log_pos; i++) { + len += sprintf(page + len, "%-4i %lu.%lu ", i, debug_log[i].time, timer_data_to_ns(debug_log[i].timer_data)); + len += sprintf(page + len, debug_log[i].string, debug_log[i].value); + if (len+begin > off+count) + goto done; + if (len+begin < off) { + begin += len; + len = 0; + } + } + len += sprintf(page + len, "debug_log %i/%i %li bytes\n", + i, DEBUG_LOG_SIZE, begin+len); + debug_log_pos = 0; +#endif + *eof = 1; done: if (off >= len+begin) @@ -3893,7 +4842,7 @@ static void show_serial_version(void) { printk(KERN_INFO - "ETRAX 100LX serial-driver %s, (c) 2000-2003 Axis Communications AB\r\n", + "ETRAX 100LX serial-driver %s, (c) 2000-2004 Axis Communications AB\r\n", &serial_version[11]); /* "$Revision: x.yy" */ } @@ -3952,20 +4901,25 @@ rs_init(void) driver->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */ driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; + driver->termios = serial_termios; + driver->termios_locked = serial_termios_locked; + tty_set_operations(driver, &rs_ops); + serial_driver = driver; if (tty_register_driver(driver)) panic("Couldn't register serial driver\n"); - serial_driver = driver; - /* do some initializing for the separate ports */ for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) { - info->uses_dma = 0; + info->uses_dma_in = 0; + info->uses_dma_out = 0; info->line = i; info->tty = 0; info->type = PORT_ETRAX; info->tr_running = 0; info->forced_eop = 0; + info->baud_base = DEF_BAUD_BASE; + info->custom_divisor = 0; info->flags = 0; info->close_delay = 5*HZ/10; info->closing_wait = 30*HZ; @@ -3973,6 +4927,7 @@ rs_init(void) info->event = 0; info->count = 0; info->blocked_open = 0; + info->normal_termios = driver->init_termios; init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); info->xmit.buf = NULL; @@ -4009,39 +4964,62 @@ rs_init(void) #ifndef CONFIG_SVINTO_SIM /* Not needed in simulator. May only complicate stuff. */ /* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */ + + if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, SA_SHIRQ | SA_INTERRUPT, "serial ", NULL)) + panic("irq8"); + #ifdef CONFIG_ETRAX_SERIAL_PORT0 +#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT if (request_irq(SER0_DMA_TX_IRQ_NBR, tr_interrupt, SA_INTERRUPT, "serial 0 dma tr", NULL)) panic("irq22"); +#endif +#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN if (request_irq(SER0_DMA_RX_IRQ_NBR, rec_interrupt, SA_INTERRUPT, "serial 0 dma rec", NULL)) panic("irq23"); #endif -#ifdef SERIAL_HANDLE_EARLY_ERRORS - if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, SA_SHIRQ | SA_INTERRUPT, "serial ", NULL)) - panic("irq8"); #endif + #ifdef CONFIG_ETRAX_SERIAL_PORT1 +#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT if (request_irq(SER1_DMA_TX_IRQ_NBR, tr_interrupt, SA_INTERRUPT, "serial 1 dma tr", NULL)) panic("irq24"); +#endif +#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN if (request_irq(SER1_DMA_RX_IRQ_NBR, rec_interrupt, SA_INTERRUPT, "serial 1 dma rec", NULL)) panic("irq25"); #endif +#endif #ifdef CONFIG_ETRAX_SERIAL_PORT2 /* DMA Shared with par0 (and SCSI0 and ATA) */ - if (request_irq(SER2_DMA_TX_IRQ_NBR, tr_interrupt, SA_SHIRQ, "serial 2 dma tr", NULL)) +#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT + if (request_irq(SER2_DMA_TX_IRQ_NBR, tr_interrupt, SA_SHIRQ | SA_INTERRUPT, "serial 2 dma tr", NULL)) panic("irq18"); - if (request_irq(SER2_DMA_RX_IRQ_NBR, rec_interrupt, SA_SHIRQ, "serial 2 dma rec", NULL)) +#endif +#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN + if (request_irq(SER2_DMA_RX_IRQ_NBR, rec_interrupt, SA_SHIRQ | SA_INTERRUPT, "serial 2 dma rec", NULL)) panic("irq19"); #endif +#endif #ifdef CONFIG_ETRAX_SERIAL_PORT3 /* DMA Shared with par1 (and SCSI1 and Extern DMA 0) */ - if (request_irq(SER3_DMA_TX_IRQ_NBR, tr_interrupt, SA_SHIRQ, "serial 3 dma tr", NULL)) +#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT + if (request_irq(SER3_DMA_TX_IRQ_NBR, tr_interrupt, SA_SHIRQ | SA_INTERRUPT, "serial 3 dma tr", NULL)) panic("irq20"); - if (request_irq(SER3_DMA_RX_IRQ_NBR, rec_interrupt, SA_SHIRQ, "serial 3 dma rec", NULL)) +#endif +#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN + if (request_irq(SER3_DMA_RX_IRQ_NBR, rec_interrupt, SA_SHIRQ | SA_INTERRUPT, "serial 3 dma rec", NULL)) panic("irq21"); #endif +#endif +#ifdef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST + if (request_irq(TIMER1_IRQ_NBR, timeout_interrupt, SA_SHIRQ | SA_INTERRUPT, + "fast serial dma timeout", NULL)) { + printk(KERN_CRIT "err: timer1 irq\n"); + } +#endif #endif /* CONFIG_SVINTO_SIM */ - + debug_write_function = rs_debug_write_function; return 0; } diff -puN arch/cris/arch-v10/drivers/serial.h~cris-architecture-update arch/cris/arch-v10/drivers/serial.h --- 25/arch/cris/arch-v10/drivers/serial.h~cris-architecture-update 2004-06-01 01:09:29.056982320 -0700 +++ 25-akpm/arch/cris/arch-v10/drivers/serial.h 2004-06-01 01:09:29.157966968 -0700 @@ -44,15 +44,11 @@ struct e100_serial { volatile u32 *ofirstadr; /* adr to R_DMA_CHx_FIRST */ volatile u8 *ocmdadr; /* adr to R_DMA_CHx_CMD */ const volatile u8 *ostatusadr; /* adr to R_DMA_CHx_STATUS */ - volatile u32 *ohwswadr; /* adr to R_DMA_CHx_HWSW */ - volatile u32 *odescradr; /* adr to R_DMA_CHx_DESCR */ /* Input registers */ volatile u8 *iclrintradr; /* adr to R_DMA_CHx_CLR_INTR */ volatile u32 *ifirstadr; /* adr to R_DMA_CHx_FIRST */ volatile u8 *icmdadr; /* adr to R_DMA_CHx_CMD */ - const volatile u8 *istatusadr; /* adr to R_DMA_CHx_STATUS */ - volatile u32 *ihwswadr; /* adr to R_DMA_CHx_HWSW */ volatile u32 *idescradr; /* adr to R_DMA_CHx_DESCR */ int flags; /* defined in tty.h */ @@ -60,14 +56,17 @@ struct e100_serial { u8 rx_ctrl; /* shadow for R_SERIALx_REC_CTRL */ u8 tx_ctrl; /* shadow for R_SERIALx_TR_CTRL */ u8 iseteop; /* bit number for R_SET_EOP for the input dma */ - int enabled; /* Set to 1 if the port is enabled in HW config */ - - /* end of fields defined in rs_table[] in .c-file */ - int uses_dma; /* Set to 1 if DMA should be used */ - unsigned char forced_eop; /* a fifo eop has been forced */ + u8 dma_out_enabled:1; /* Set to 1 if DMA should be used */ + u8 dma_in_enabled:1; /* Set to 1 if DMA should be used */ + /* end of fields defined in rs_table[] in .c-file */ + u8 uses_dma_in; /* Set to 1 if DMA is used */ + u8 uses_dma_out; /* Set to 1 if DMA is used */ + u8 forced_eop; /* a fifo eop has been forced */ + int baud_base; /* For special baudrates */ + int custom_divisor; /* For special baudrates */ struct etrax_dma_descr tr_descr; struct etrax_dma_descr rec_descr[SERIAL_RECV_DESCRIPTORS]; int cur_rec_descr; @@ -95,6 +94,8 @@ struct e100_serial { struct work_struct work; struct async_icount icount; /* error-statistics etc.*/ + struct termios normal_termios; + struct termios callout_termios; #ifdef DECLARE_WAITQUEUE wait_queue_head_t open_wait; wait_queue_head_t close_wait; @@ -104,6 +105,7 @@ struct e100_serial { #endif unsigned long char_time_usec; /* The time for 1 char, in usecs */ + unsigned long flush_time_usec; /* How often we should flush */ unsigned long last_tx_active_usec; /* Last tx usec in the jiffies */ unsigned long last_tx_active; /* Last tx time in jiffies */ unsigned long last_rx_active_usec; /* Last rx usec in the jiffies */ diff -puN arch/cris/arch-v10/kernel/debugport.c~cris-architecture-update arch/cris/arch-v10/kernel/debugport.c --- 25/arch/cris/arch-v10/kernel/debugport.c~cris-architecture-update 2004-06-01 01:09:29.058982016 -0700 +++ 25-akpm/arch/cris/arch-v10/kernel/debugport.c 2004-06-01 01:09:29.159966664 -0700 @@ -12,6 +12,15 @@ * init_etrax_debug() * * $Log: debugport.c,v $ + * Revision 1.14 2004/05/17 13:11:29 starvik + * Disable DMA until real serial driver is up + * + * Revision 1.13 2004/05/14 07:58:01 starvik + * Merge of changes from 2.4 + * + * Revision 1.12 2003/09/11 07:29:49 starvik + * Merge of Linux 2.6.0-test5 + * * Revision 1.11 2003/07/07 09:53:36 starvik * Revert all the 2.5.74 merge changes to make the console work again * @@ -59,7 +68,7 @@ #include #include #include - +#include #include #include #include /* Get SIMCOUT. */ @@ -124,22 +133,28 @@ #define MIN_SIZE 32 /* Size that triggers the FIFO to flush characters to interface */ -/* Write a string of count length to the console (debug port) using DMA, polled - * for completion. Interrupts are disabled during the whole process. Some - * caution needs to be taken to not interfere with ttyS business on this port. - */ +static struct tty_driver *serial_driver; + +typedef int (*debugport_write_function)(int i, const char *buf, unsigned int len); + +debugport_write_function debug_write_function = NULL; + +static void +console_write_direct(struct console *co, const char *buf, unsigned int len) +{ + int i; + /* Send data */ + for (i = 0; i < len; i++) { + /* Wait until transmitter is ready and send.*/ + while(!(*DEBUG_READ & IO_MASK(R_SERIAL0_READ, tr_ready))); + *DEBUG_WRITE = buf[i]; + } +} static void console_write(struct console *co, const char *buf, unsigned int len) { - - static struct etrax_dma_descr descr; - static struct etrax_dma_descr descr2; - static char tmp_buf[MIN_SIZE]; - static int tmp_size = 0; - - unsigned long flags; - + unsigned long flags; #ifdef CONFIG_ETRAX_DEBUG_PORT_NULL /* no debug printout at all */ return; @@ -150,86 +165,18 @@ console_write(struct console *co, const SIMCOUT(buf,len); return; #endif - - local_save_flags(flags); - local_irq_disable(); #ifdef CONFIG_ETRAX_KGDB /* kgdb needs to output debug info using the gdb protocol */ putDebugString(buf, len); - local_irq_restore(flags); return; #endif - /* To make this work together with the real serial port driver - * we have to make sure that everything is flushed when we leave - * here. The following steps are made to assure this: - * 1. Wait until DMA stops, FIFO is empty and serial port pipeline empty. - * 2. Write at least half the FIFO to trigger flush to serial port. - * 3. Wait until DMA stops, FIFO is empty and serial port pipeline empty. - */ - - /* Do we have enough characters to make the DMA/FIFO happy? */ - if (tmp_size + len < MIN_SIZE) - { - int size = min((int)(MIN_SIZE - tmp_size),(int)len); - memcpy(&tmp_buf[tmp_size], buf, size); - tmp_size += size; - len -= size; - - /* Pad with space if complete line */ - if (tmp_buf[tmp_size-1] == '\n') - { - memset(&tmp_buf[tmp_size-1], ' ', MIN_SIZE - tmp_size); - tmp_buf[MIN_SIZE - 1] = '\n'; - tmp_size = MIN_SIZE; - len = 0; - } - else - { - /* Wait for more characters */ - local_irq_restore(flags); + local_irq_save(flags); + if (debug_write_function) + if (debug_write_function(co->index, buf, len)) return; - } - } - - /* make sure the transmitter is enabled. - * NOTE: this overrides any setting done in ttySx, to 8N1, no auto-CTS. - * in the future, move the tr/rec_ctrl shadows from etrax100ser.c to - * shadows.c and use it here as well... - */ - - *DEBUG_TR_CTRL = 0x40; - while(*DEBUG_OCMD & 7); /* Until DMA is not running */ - while(*DEBUG_STATUS & 0x7f); /* wait until output FIFO is empty as well */ - udelay(200); /* Wait for last two characters to leave the serial transmitter */ - - if (tmp_size) - { - descr.ctrl = len ? 0 : d_eop | d_wait | d_eol; - descr.sw_len = tmp_size; - descr.buf = virt_to_phys(tmp_buf); - descr.next = virt_to_phys(&descr2); - descr2.ctrl = d_eop | d_wait | d_eol; - descr2.sw_len = len; - descr2.buf = virt_to_phys((char*)buf); - } - else - { - descr.ctrl = d_eop | d_wait | d_eol; - descr.sw_len = len; - descr.buf = virt_to_phys((char*)buf); - } - - *DEBUG_FIRST = virt_to_phys(&descr); /* write to R_DMAx_FIRST */ - *DEBUG_OCMD = 1; /* dma command start -> R_DMAx_CMD */ - - /* wait until the output dma channel is ready again */ - while(*DEBUG_OCMD & 7); - while(*DEBUG_STATUS & 0x7f); - udelay(200); - - tmp_size = 0; + console_write_direct(co, buf, len); local_irq_restore(flags); } @@ -279,10 +226,11 @@ enableDebugIRQ(void) *DEBUG_REC_CTRL = IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable); } -static kdev_t -console_device(struct console *c) +static struct tty_driver* +console_device(struct console *c, int *index) { - return mk_kdev(TTY_MAJOR, 64 + c->index); + *index = c->index; + return serial_driver; } static int __init @@ -311,5 +259,33 @@ static struct console sercons = { void __init init_etrax_debug(void) { +#if CONFIG_ETRAX_DEBUG_PORT_NULL + return; +#endif + +#if DEBUG_PORT_IDX == 0 + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma6); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma6, unused); +#elif DEBUG_PORT_IDX == 1 + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma8); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma8, usb); +#elif DEBUG_PORT_IDX == 2 + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma2); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma2, par0); +#elif DEBUG_PORT_IDX == 3 + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma4); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, par1); +#endif + *R_GEN_CONFIG = genconfig_shadow; + register_console(&sercons); } + +int __init +init_console(void) +{ + serial_driver = alloc_tty_driver(1); + if (!serial_driver) + return -ENOMEM; + return 0; +} diff -puN arch/cris/arch-v10/kernel/entry.S~cris-architecture-update arch/cris/arch-v10/kernel/entry.S --- 25/arch/cris/arch-v10/kernel/entry.S~cris-architecture-update 2004-06-01 01:09:29.059981864 -0700 +++ 25-akpm/arch/cris/arch-v10/kernel/entry.S 2004-06-01 01:09:29.160966512 -0700 @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.16 2003/07/04 08:27:41 starvik Exp $ +/* $Id: entry.S,v 1.18 2004/05/11 12:28:25 starvik Exp $ * * linux/arch/cris/entry.S * @@ -7,6 +7,12 @@ * Authors: Bjorn Wesen (bjornw@axis.com) * * $Log: entry.S,v $ + * Revision 1.18 2004/05/11 12:28:25 starvik + * Merge of Linux 2.6.6 + * + * Revision 1.17 2003/09/11 07:29:49 starvik + * Merge of Linux 2.6.0-test5 + * * Revision 1.16 2003/07/04 08:27:41 starvik * Merge of Linux 2.5.74 * @@ -1060,6 +1066,19 @@ sys_call_table: .long sys_clock_nanosleep .long sys_statfs64 .long sys_fstatfs64 + .long sys_tgkill /* 270 */ + .long sys_utimes + .long sys_fadvise64_64 + .long sys_ni_syscall /* sys_vserver */ + .long sys_ni_syscall /* sys_mbind */ + .long sys_ni_syscall /* 275 sys_get_mempolicy */ + .long sys_ni_syscall /* sys_set_mempolicy */ + .long sys_mq_open + .long sys_mq_unlink + .long sys_mq_timedsend + .long sys_mq_timedreceive /* 280 */ + .long sys_mq_notify + .long sys_mq_getsetattr /* * NOTE!! This doesn't have to be exact - we just have diff -puN arch/cris/arch-v10/kernel/fasttimer.c~cris-architecture-update arch/cris/arch-v10/kernel/fasttimer.c --- 25/arch/cris/arch-v10/kernel/fasttimer.c~cris-architecture-update 2004-06-01 01:09:29.060981712 -0700 +++ 25-akpm/arch/cris/arch-v10/kernel/fasttimer.c 2004-06-01 01:09:29.161966360 -0700 @@ -1,10 +1,16 @@ -/* $Id: fasttimer.c,v 1.4 2003/07/04 08:27:41 starvik Exp $ +/* $Id: fasttimer.c,v 1.6 2004/05/14 10:18:39 starvik Exp $ * linux/arch/cris/kernel/fasttimer.c * * Fast timers for ETRAX100/ETRAX100LX * This may be useful in other OS than Linux so use 2 space indentation... * * $Log: fasttimer.c,v $ + * Revision 1.6 2004/05/14 10:18:39 starvik + * Export fast_timer_list + * + * Revision 1.5 2004/05/14 07:58:01 starvik + * Merge of changes from 2.4 + * * Revision 1.4 2003/07/04 08:27:41 starvik * Merge of Linux 2.5.74 * @@ -130,7 +136,7 @@ static int fast_timers_deleted = 0; static int fast_timer_is_init = 0; static int fast_timer_ints = 0; -static struct fast_timer *fast_timer_list = NULL; +struct fast_timer *fast_timer_list = NULL; #ifdef DEBUG_LOG_INCLUDED #define DEBUG_LOG_MAX 128 @@ -325,7 +331,8 @@ void start_one_shot_timer(struct fast_ti { if (tmp == t) { - printk("timer name: %s data: 0x%08lX already in list!\n", name, data); + printk(KERN_WARNING + "timer name: %s data: 0x%08lX already in list!\n", name, data); sanity_failed++; return; } @@ -784,7 +791,7 @@ static int proc_fasttimer_read(char *buf cli(); if (t->next != nextt) { - printk("timer removed!\n"); + printk(KERN_WARNING "timer removed!\n"); } t = nextt; } @@ -965,7 +972,7 @@ void fast_timer_init(void) int i; #endif - printk("fast_timer_init()\n"); + printk(KERN_INFO "fast_timer_init()\n"); #if 0 && defined(FAST_TIMER_TEST) for (i = 0; i <= TIMER0_DIV; i++) diff -puN arch/cris/arch-v10/kernel/head.S~cris-architecture-update arch/cris/arch-v10/kernel/head.S --- 25/arch/cris/arch-v10/kernel/head.S~cris-architecture-update 2004-06-01 01:09:29.062981408 -0700 +++ 25-akpm/arch/cris/arch-v10/kernel/head.S 2004-06-01 01:09:29.162966208 -0700 @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.6 2003/04/28 05:31:46 starvik Exp $ +/* $Id: head.S,v 1.7 2004/05/14 07:58:01 starvik Exp $ * * Head of the kernel - alter with care * @@ -7,6 +7,9 @@ * Authors: Bjorn Wesen (bjornw@axis.com) * * $Log: head.S,v $ + * Revision 1.7 2004/05/14 07:58:01 starvik + * Merge of changes from 2.4 + * * Revision 1.6 2003/04/28 05:31:46 starvik * Added section attributes * @@ -331,7 +334,16 @@ _inflash: move.d START_ETHERNET_CLOCK, $r0 move.d $r0, [R_NETWORK_GEN_CONFIG] #endif - + + ;; Set up waitstates etc according to kernel configuration. +#ifndef CONFIG_SVINTO_SIM + move.d CONFIG_ETRAX_DEF_R_WAITSTATES, $r0 + move.d $r0, [R_WAITSTATES] + + move.d CONFIG_ETRAX_DEF_R_BUS_CONFIG, $r0 + move.d $r0, [R_BUS_CONFIG] +#endif + ;; We need to initialze DRAM registers before we start using the DRAM cmp.d RAM_INIT_MAGIC, $r8 ; Already initialized? @@ -626,8 +638,19 @@ _start_it: | IO_STATE (R_GEN_CONFIG, dma4, extdma0),$r0 #endif -#if defined(CONFIG_BLUETOOTH) && (defined(CONFIG_BLUETOOTH_RESET_G10) || defined(CONFIG_BLUETOOTH_RESET_G11)) - or.d IO_STATE (R_GEN_CONFIG, g8_15dir, out),$r0 +#if defined(CONFIG_ETRAX_DEF_R_PORT_G0_DIR_OUT) + or.d IO_STATE (R_GEN_CONFIG, g0dir, out),$r0 +#endif + +#if defined(CONFIG_ETRAX_DEF_R_PORT_G8_15_DIR_OUT) + or.d IO_STATE (R_GEN_CONFIG, g8_15dir, out),$r0 +#endif +#if defined(CONFIG_ETRAX_DEF_R_PORT_G16_23_DIR_OUT) + or.d IO_STATE (R_GEN_CONFIG, g16_23dir, out),$r0 +#endif + +#if defined(CONFIG_ETRAX_DEF_R_PORT_G24_DIR_OUT) + or.d IO_STATE (R_GEN_CONFIG, g24dir, out),$r0 #endif move.d $r0,[genconfig_shadow] ; init a shadow register of R_GEN_CONFIG diff -puN arch/cris/arch-v10/kernel/process.c~cris-architecture-update arch/cris/arch-v10/kernel/process.c --- 25/arch/cris/arch-v10/kernel/process.c~cris-architecture-update 2004-06-01 01:09:29.063981256 -0700 +++ 25-akpm/arch/cris/arch-v10/kernel/process.c 2004-06-01 01:09:29.163966056 -0700 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.3 2003/07/04 08:27:41 starvik Exp $ +/* $Id: process.c,v 1.6 2004/05/11 12:28:25 starvik Exp $ * * linux/arch/cris/kernel/process.c * @@ -16,6 +16,7 @@ #include #include #include +#include #include #ifdef CONFIG_ETRAX_GPIO @@ -249,3 +250,19 @@ unsigned long get_wchan(struct task_stru } #undef last_sched #undef first_sched + +void show_regs(struct pt_regs * regs) +{ + unsigned long usp = rdusp(); + printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n", + regs->irp, regs->srp, regs->dccr, usp, regs->mof ); + printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n", + regs->r0, regs->r1, regs->r2, regs->r3); + printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n", + regs->r4, regs->r5, regs->r6, regs->r7); + printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n", + regs->r8, regs->r9, regs->r10, regs->r11); + printk("r12: %08lx r13: %08lx oR10: %08lx\n", + regs->r12, regs->r13, regs->orig_r10); +} + diff -puN arch/cris/arch-v10/kernel/ptrace.c~cris-architecture-update arch/cris/arch-v10/kernel/ptrace.c --- 25/arch/cris/arch-v10/kernel/ptrace.c~cris-architecture-update 2004-06-01 01:09:29.064981104 -0700 +++ 25-akpm/arch/cris/arch-v10/kernel/ptrace.c 2004-06-01 01:09:29.163966056 -0700 @@ -118,19 +118,13 @@ sys_ptrace(long request, long pid, long /* Read the word at location address in the USER area. */ case PTRACE_PEEKUSR: { unsigned long tmp; - + ret = -EIO; - if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) + if ((addr & 3) || addr < 0 || addr > PT_MAX << 2) break; - - tmp = 0; /* Default return condition */ - ret = -EIO; - - if (addr < sizeof(struct pt_regs)) { - tmp = get_reg(child, addr >> 2); - ret = put_user(tmp, (unsigned long *)data); - } - + + tmp = get_reg(child, addr >> 2); + ret = put_user(tmp, (unsigned long *)data); break; } @@ -148,28 +142,21 @@ sys_ptrace(long request, long pid, long /* Write the word at location address in the USER area. */ case PTRACE_POKEUSR: ret = -EIO; - - if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) + if ((addr & 3) || addr < 0 || addr > PT_MAX << 2) break; - if (addr < sizeof(struct pt_regs)) { - addr >>= 2; + addr >>= 2; - if (addr == PT_DCCR) { - /* - * Don't allow the tracing process to - * change stuff like interrupt enable, - * kernel/user bit, etc. - */ - data &= DCCR_MASK; - data |= get_reg(child, PT_DCCR) & ~DCCR_MASK; - } - - if (put_reg(child, addr, data)) - break; - - ret = 0; + if (addr == PT_DCCR) { + /* don't allow the tracing process to change stuff like + * interrupt enable, kernel/user bit, dma enables etc. + */ + data &= DCCR_MASK; + data |= get_reg(child, PT_DCCR) & ~DCCR_MASK; } + if (put_reg(child, addr, data)) + break; + ret = 0; break; case PTRACE_SYSCALL: @@ -237,7 +224,7 @@ sys_ptrace(long request, long pid, long if (put_user(tmp, (unsigned long *) data)) { ret = -EFAULT; - break; + goto out_tsk; } data += sizeof(long); @@ -255,7 +242,7 @@ sys_ptrace(long request, long pid, long for (i = 0; i <= PT_MAX; i++) { if (get_user(tmp, (unsigned long *) data)) { ret = -EFAULT; - break; + goto out_tsk; } if (i == PT_DCCR) { @@ -290,12 +277,10 @@ void do_syscall_trace(void) if (!(current->ptrace & PT_PTRACED)) return; - current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0); - - current->state = TASK_STOPPED; - notify_parent(current, SIGCHLD); - schedule(); + /* the 0x80 provides a way for the tracing parent to distinguish + between a syscall stop and SIGTRAP delivery */ + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0)); /* * This isn't the same as continuing with a signal, but it will do for diff -puN arch/cris/arch-v10/kernel/setup.c~cris-architecture-update arch/cris/arch-v10/kernel/setup.c --- 25/arch/cris/arch-v10/kernel/setup.c~cris-architecture-update 2004-06-01 01:09:29.065980952 -0700 +++ 25-akpm/arch/cris/arch-v10/kernel/setup.c 2004-06-01 01:09:29.164965904 -0700 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.1 2002/12/11 15:42:02 starvik Exp $ +/* * * linux/arch/cris/arch-v10/kernel/setup.c * @@ -94,3 +94,10 @@ int show_cpuinfo(struct seq_file *m, voi } #endif /* CONFIG_PROC_FS */ + +void +show_etrax_copyright(void) +{ + printk(KERN_INFO + "Linux/CRIS port on ETRAX 100LX (c) 2001 Axis Communications AB\n"); +} diff -puN arch/cris/arch-v10/kernel/signal.c~cris-architecture-update arch/cris/arch-v10/kernel/signal.c --- 25/arch/cris/arch-v10/kernel/signal.c~cris-architecture-update 2004-06-01 01:09:29.067980648 -0700 +++ 25-akpm/arch/cris/arch-v10/kernel/signal.c 2004-06-01 01:09:29.164965904 -0700 @@ -180,6 +180,9 @@ restore_sigcontext(struct pt_regs *regs, unsigned int err = 0; unsigned long old_usp; + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + /* restore the regs from &sc->regs (same as sc, since regs is first) * (sc is already checked for VERIFY_READ since the sigframe was * checked in sys_sigreturn previously) @@ -492,7 +495,6 @@ handle_signal(int canrestart, unsigned l /* If so, check system call restarting.. */ switch (regs->r10) { case -ERESTART_RESTARTBLOCK: - current_thread_info()->restart_block.fn = do_no_restart_syscall; case -ERESTARTNOHAND: /* ERESTARTNOHAND means that the syscall should only be restarted if there was no handler for the signal, and since diff -puN arch/cris/arch-v10/kernel/time.c~cris-architecture-update arch/cris/arch-v10/kernel/time.c --- 25/arch/cris/arch-v10/kernel/time.c~cris-architecture-update 2004-06-01 01:09:29.068980496 -0700 +++ 25-akpm/arch/cris/arch-v10/kernel/time.c 2004-06-01 01:09:29.165965752 -0700 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.2 2003/07/04 08:27:41 starvik Exp $ +/* $Id: time.c,v 1.3 2004/06/01 05:38:42 starvik Exp $ * * linux/arch/cris/arch-v10/kernel/time.c * @@ -277,6 +277,12 @@ time_init(void) update_xtime_from_cmos(); } + /* + * Initialize wall_to_monotonic such that adding it to xtime will yield zero, the + * tv_nsec field must be normalized (i.e., 0 <= nsec < NSEC_PER_SEC). + */ + set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); + /* Setup the etrax timers * Base frequency is 25000 hz, divider 250 -> 100 HZ * In normal mode, we use timer0, so timer1 is free. In cascade diff -puN arch/cris/arch-v10/lib/dram_init.S~cris-architecture-update arch/cris/arch-v10/lib/dram_init.S --- 25/arch/cris/arch-v10/lib/dram_init.S~cris-architecture-update 2004-06-01 01:09:29.069980344 -0700 +++ 25-akpm/arch/cris/arch-v10/lib/dram_init.S 2004-06-01 01:09:29.165965752 -0700 @@ -1,4 +1,4 @@ -/* $Id: dram_init.S,v 1.3 2003/03/31 09:38:37 starvik Exp $ +/* $Id: dram_init.S,v 1.4 2003/09/22 09:21:59 starvik Exp $ * * DRAM/SDRAM initialization - alter with care * This file is intended to be included from other assembler files @@ -11,6 +11,10 @@ * Authors: Mikael Starvik (starvik@axis.com) * * $Log: dram_init.S,v $ + * Revision 1.4 2003/09/22 09:21:59 starvik + * Decompresser is linked to 0x407xxxxx and sdram commands are at 0x000xxxxx + * so we need to mask off 12 bits. + * * Revision 1.3 2003/03/31 09:38:37 starvik * Corrected calculation of end of sdram init commands * @@ -152,9 +156,9 @@ _set_timing: ; Issue initialization command sequence move.d _sdram_commands_start, $r2 - and.d 0x00ffffff, $r2 ; Make sure commands are read from flash + and.d 0x000fffff, $r2 ; Make sure commands are read from flash move.d _sdram_commands_end, $r3 - and.d 0x00ffffff, $r3 + and.d 0x000fffff, $r3 1: clear.d $r4 move.b [$r2+], $r4 lslq 9, $r4 ; Command starts at bit 9 diff -puN arch/cris/arch-v10/lib/old_checksum.c~cris-architecture-update arch/cris/arch-v10/lib/old_checksum.c --- 25/arch/cris/arch-v10/lib/old_checksum.c~cris-architecture-update 2004-06-01 01:09:29.070980192 -0700 +++ 25-akpm/arch/cris/arch-v10/lib/old_checksum.c 2004-06-01 01:09:29.166965600 -0700 @@ -1,4 +1,4 @@ -/* $Id: old_checksum.c,v 1.2 2002/11/05 06:45:12 starvik Exp $ +/* $Id: old_checksum.c,v 1.3 2003/10/27 08:04:32 starvik Exp $ * * INET An implementation of the TCP/IP protocol suite for the LINUX * operating system. INET is implemented using the BSD Socket @@ -76,7 +76,7 @@ unsigned int csum_partial(const unsigned sum += *((unsigned short *)buff)++; } if(endMarker - buff > 0) { - sum += *buff; /* add extra byte separately */ + sum += *buff; /* add extra byte seperately */ } BITOFF; return(sum); diff -puN arch/cris/arch-v10/mm/fault.c~cris-architecture-update arch/cris/arch-v10/mm/fault.c --- 25/arch/cris/arch-v10/mm/fault.c~cris-architecture-update 2004-06-01 01:09:29.071980040 -0700 +++ 25-akpm/arch/cris/arch-v10/mm/fault.c 2004-06-01 01:09:29.167965448 -0700 @@ -30,7 +30,7 @@ extern const struct exception_table_entr *search_exception_tables(unsigned long addr); asmlinkage void do_page_fault(unsigned long address, struct pt_regs *regs, - int error_code); + int protection, int writeaccess); /* fast TLB-fill fault handler * this is called from entry.S with interrupts disabled @@ -39,8 +39,9 @@ asmlinkage void do_page_fault(unsigned l void handle_mmu_bus_fault(struct pt_regs *regs) { - int cause, select; + int cause; #ifdef DEBUG + int select; int index; int page_id; int acc, inv; @@ -48,15 +49,14 @@ handle_mmu_bus_fault(struct pt_regs *reg int miss, we, writeac; pmd_t *pmd; pte_t pte; - int errcode; unsigned long address; cause = *R_MMU_CAUSE; - select = *R_TLB_SELECT; address = cause & PAGE_MASK; /* get faulting address */ #ifdef DEBUG + select = *R_TLB_SELECT; page_id = IO_EXTRACT(R_MMU_CAUSE, page_id, cause); acc = IO_EXTRACT(R_MMU_CAUSE, acc_excp, cause); inv = IO_EXTRACT(R_MMU_CAUSE, inv_excp, cause); @@ -82,12 +82,6 @@ handle_mmu_bus_fault(struct pt_regs *reg if(writeac) regs->csrinstr &= ~(1 << 5); - /* Set errcode's R/W flag according to the mode which caused the - * fault - */ - - errcode = writeac << 1; - D(printk("bus_fault from IRP 0x%lx: addr 0x%lx, miss %d, inv %d, we %d, acc %d, dx %d pid %d\n", regs->irp, address, miss, inv, we, acc, index, page_id)); @@ -99,16 +93,20 @@ handle_mmu_bus_fault(struct pt_regs *reg */ pmd = (pmd_t *)(current_pgd + pgd_index(address)); - if (pmd_none(*pmd)) - goto dofault; + if (pmd_none(*pmd)) { + do_page_fault(address, regs, 0, writeac); + return; + } if (pmd_bad(*pmd)) { printk("bad pgdir entry 0x%lx at 0x%p\n", *(unsigned long*)pmd, pmd); pmd_clear(pmd); return; } pte = *pte_offset_kernel(pmd, address); - if (!pte_present(pte)) - goto dofault; + if (!pte_present(pte)) { + do_page_fault(address, regs, 0, writeac); + return; + } #ifdef DEBUG printk(" found pte %lx pg %p ", pte_val(pte), pte_page(pte)); @@ -143,14 +141,10 @@ handle_mmu_bus_fault(struct pt_regs *reg *R_TLB_LO = pte_val(pte); return; - } - - errcode = 1 | (we << 1); + } - dofault: - /* leave it to the MM system fault handler below */ - D(printk("do_page_fault %lx errcode %d\n", address, errcode)); - do_page_fault(address, regs, errcode); + /* leave it to the MM system fault handler */ + do_page_fault(address, regs, 1, we); } /* Called from arch/cris/mm/fault.c to find fixup code. */ diff -puN arch/cris/arch-v10/mm/tlb.c~cris-architecture-update arch/cris/arch-v10/mm/tlb.c --- 25/arch/cris/arch-v10/mm/tlb.c~cris-architecture-update 2004-06-01 01:09:29.073979736 -0700 +++ 25-akpm/arch/cris/arch-v10/mm/tlb.c 2004-06-01 01:09:29.167965448 -0700 @@ -212,7 +212,7 @@ dump_tlb_all(void) void switch_mm(struct mm_struct *prev, struct mm_struct *next, - struct task_struct *tsk, int cpu) + struct task_struct *tsk) { /* make sure we have a context */ diff -puN arch/cris/defconfig~cris-architecture-update arch/cris/defconfig --- 25/arch/cris/defconfig~cris-architecture-update 2004-06-01 01:09:29.074979584 -0700 +++ 25-akpm/arch/cris/defconfig 2004-06-01 01:09:29.170964992 -0700 @@ -1,25 +1,55 @@ # # Automatically generated make config: don't edit # +CONFIG_MMU=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set # # Code maturity level options # CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y # # General setup # -CONFIG_NET=y -CONFIG_SYSVIPC=y +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_SYSCTL is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_HOTPLUG is not set +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +# CONFIG_KALLSYMS is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# General setup +# CONFIG_BINFMT_ELF=y -# CONFIG_ETRAX_KGDB is not set -# CONFIG_ETRAX_WATCHDOG is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_ETRAX_CMDLINE="root=/dev/mtdblock3 init=/linuxrc" +CONFIG_ETRAX_WATCHDOG=y +CONFIG_ETRAX_WATCHDOG_NICE_DOGGY=y +CONFIG_ETRAX_FAST_TIMER=y +# CONFIG_PREEMPT is not set # # Hardware setup @@ -27,74 +57,170 @@ CONFIG_BINFMT_ELF=y CONFIG_ETRAX100LX=y # CONFIG_ETRAX100LX_V2 is not set # CONFIG_SVINTO_SIM is not set -CONFIG_ETRAX_DRAM_SIZE=8 +CONFIG_ETRAX_ARCH_V10=y +CONFIG_ETRAX_DRAM_SIZE=16 CONFIG_ETRAX_FLASH_BUSWIDTH=2 -CONFIG_ETRAX_ROOT_DEVICE="/dev/mtdblock3" +CONFIG_CRIS_LOW_MAP=y +CONFIG_ETRAX_DRAM_VIRTUAL_BASE=60000000 +CONFIG_ETRAX_PA_LEDS=y +# CONFIG_ETRAX_PB_LEDS is not set +# CONFIG_ETRAX_CSP0_LEDS is not set +# CONFIG_ETRAX_NO_LEDS is not set +CONFIG_ETRAX_LED1G=2 +CONFIG_ETRAX_LED1R=2 +CONFIG_ETRAX_LED2G=3 +CONFIG_ETRAX_LED2R=3 +CONFIG_ETRAX_LED3G=2 +CONFIG_ETRAX_LED3R=2 +CONFIG_ETRAX_DEBUG_PORT0=y +# CONFIG_ETRAX_DEBUG_PORT1 is not set +# CONFIG_ETRAX_DEBUG_PORT2 is not set +# CONFIG_ETRAX_DEBUG_PORT3 is not set +# CONFIG_ETRAX_DEBUG_PORT_NULL is not set +CONFIG_ETRAX_RESCUE_SER0=y +# CONFIG_ETRAX_RESCUE_SER1 is not set +# CONFIG_ETRAX_RESCUE_SER2 is not set +# CONFIG_ETRAX_RESCUE_SER3 is not set +CONFIG_ETRAX_DEF_R_WAITSTATES=0x95f8 +CONFIG_ETRAX_DEF_R_BUS_CONFIG=0x104 +CONFIG_ETRAX_SDRAM=y +CONFIG_ETRAX_DEF_R_SDRAM_CONFIG=0x00e03636 +CONFIG_ETRAX_DEF_R_SDRAM_TIMING=0x80008002 +CONFIG_ETRAX_DEF_R_PORT_PA_DIR=0x1d +CONFIG_ETRAX_DEF_R_PORT_PA_DATA=0xf0 +CONFIG_ETRAX_DEF_R_PORT_PB_CONFIG=0x00 +CONFIG_ETRAX_DEF_R_PORT_PB_DIR=0x1e +CONFIG_ETRAX_DEF_R_PORT_PB_DATA=0xf3 +# CONFIG_ETRAX_SOFT_SHUTDOWN is not set # -# Drivers for ETRAX 100LX built-in interfaces +# Drivers for built-in interfaces +# +CONFIG_ETRAX_ETHERNET=y +CONFIG_NET_ETHERNET=y +# CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK is not set +CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY=y +CONFIG_ETRAX_SERIAL=y +CONFIG_ETRAX_SERIAL_FAST_TIMER=y +CONFIG_ETRAX_SERIAL_PORT0=y +# CONFIG_CONFIG_ETRAX_SERIAL_PORT0_NO_DMA_OUT is not set +CONFIG_CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT=y +# CONFIG_CONFIG_ETRAX_SERIAL_PORT0_NO_DMA_IN is not set +CONFIG_CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN=y +CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_NONE=y +# CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_PA is not set +# CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_PB is not set +# CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED is not set +CONFIG_ETRAX_SER0_DTR_ON_PA_BIT=-1 +CONFIG_ETRAX_SER0_RI_ON_PA_BIT=-1 +CONFIG_ETRAX_SER0_DSR_ON_PA_BIT=-1 +CONFIG_ETRAX_SER0_CD_ON_PA_BIT=-1 +CONFIG_ETRAX_SER0_DTR_ON_PB_BIT=-1 +CONFIG_ETRAX_SER0_RI_ON_PB_BIT=-1 +CONFIG_ETRAX_SER0_DSR_ON_PB_BIT=-1 +CONFIG_ETRAX_SER0_CD_ON_PB_BIT=-1 +# CONFIG_ETRAX_SERIAL_PORT1 is not set +CONFIG_ETRAX_SERIAL_PORT2=y +# CONFIG_CONFIG_ETRAX_SERIAL_PORT2_NO_DMA_OUT is not set +CONFIG_CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT=y +# CONFIG_CONFIG_ETRAX_SERIAL_PORT2_NO_DMA_IN is not set +CONFIG_CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN=y +CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_ON_NONE=y +# CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_ON_PA is not set +# CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_ON_PB is not set +# CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED is not set +CONFIG_ETRAX_SER2_DTR_ON_PA_BIT=-1 +CONFIG_ETRAX_SER2_RI_ON_PA_BIT=-1 +CONFIG_ETRAX_SER2_DSR_ON_PA_BIT=-1 +CONFIG_ETRAX_SER2_CD_ON_PA_BIT=-1 +CONFIG_ETRAX_SER2_DTR_ON_PB_BIT=-1 +CONFIG_ETRAX_SER2_RI_ON_PB_BIT=-1 +CONFIG_ETRAX_SER2_DSR_ON_PB_BIT=-1 +CONFIG_ETRAX_SER2_CD_ON_PB_BIT=-1 +# CONFIG_ETRAX_SERIAL_PORT3 is not set +# CONFIG_ETRAX_RS485 is not set +# CONFIG_ETRAX_IDE is not set +# CONFIG_IDE is not set +# CONFIG_ETRAX_USB_HOST is not set +CONFIG_ETRAX_AXISFLASHMAP=y +CONFIG_ETRAX_PTABLE_SECTOR=65536 +CONFIG_MTD=y +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_OBSOLETE_CHIPS=y +CONFIG_MTD_AMDSTD=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_CONCAT=y +# CONFIG_ETRAX_I2C is not set +CONFIG_ETRAX_GPIO=y +CONFIG_ETRAX_PA_BUTTON_BITMASK=0x02 +CONFIG_ETRAX_PA_CHANGEABLE_DIR=0x00 +CONFIG_ETRAX_PA_CHANGEABLE_BITS=0xFF +CONFIG_ETRAX_PB_CHANGEABLE_DIR=0x00 +CONFIG_ETRAX_PB_CHANGEABLE_BITS=0xFF +# CONFIG_ETRAX_RTC is not set + +# +# Generic Driver Options # # # Memory Technology Devices (MTD) # -CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set # -# Disk-On-Chip Device Drivers +# User Modules And Translation Layers # -# CONFIG_MTD_DOC1000 is not set -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOCPROBE is not set +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set # -# RAM/ROM Device Drivers +# RAM/ROM/Flash chip drivers # -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_RAM is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +# CONFIG_MTD_CFI_INTELEXT is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_RAM=y # CONFIG_MTD_ROM is not set -# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_SHARP is not set +# CONFIG_MTD_JEDEC is not set # -# Linearly Mapped Flash Device Drivers +# Mapping drivers for chip access # -CONFIG_MTD_CFI=y -# CONFIG_MTD_CFI_GEOMETRY is not set -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_AMDSTD=y -# CONFIG_MTD_SHARP is not set +CONFIG_MTD_COMPLEX_MAPPINGS=y # CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_NORA is not set -# CONFIG_MTD_PNC2000 is not set -# CONFIG_MTD_RPXLITE is not set -# CONFIG_MTD_SC520CDP is not set -# CONFIG_MTD_SBC_MEDIAGX is not set -# CONFIG_MTD_ELAN_104NC is not set -# CONFIG_MTD_SA1100 is not set -# CONFIG_MTD_DC21285 is not set -# CONFIG_MTD_CSTM_CFI_JEDEC is not set -# CONFIG_MTD_JEDEC is not set -# CONFIG_MTD_MIXMEM is not set -# CONFIG_MTD_OCTAGON is not set -# CONFIG_MTD_VMAX is not set # -# NAND Flash Device Drivers +# Self-contained MTD device drivers # -# CONFIG_MTD_NAND is not set -# CONFIG_MTD_NAND_SPIA is not set +# CONFIG_MTD_SLRAM is not set +CONFIG_MTD_MTDRAM=y +CONFIG_MTDRAM_TOTAL_SIZE=0 +CONFIG_MTDRAM_ERASE_SIZE=64 +CONFIG_MTDRAM_ABS_POS=0x0 +# CONFIG_MTD_BLKMTD is not set # -# User Modules And Translation Layers +# Disk-On-Chip Device Drivers # -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set # # Parallel port support @@ -102,51 +228,98 @@ CONFIG_MTD_BLOCK=y # CONFIG_PARPORT is not set # -# Plug and Play configuration +# Plug and Play support # -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set # # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BLK_DEV_INITRD is not set # +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# ATA/ATAPI/MFM/RLL support +# + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y + +# # Networking options # -# CONFIG_PACKET is not set -# CONFIG_NETLINK is not set -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set CONFIG_UNIX=y +# CONFIG_NET_KEY is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set # CONFIG_IP_PNP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set -# CONFIG_INET_ECN is not set +# CONFIG_ARPD is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set # CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_LLC is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -159,167 +332,114 @@ CONFIG_INET=y # CONFIG_NET_SCHED is not set # -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set - -# -# ATA/IDE/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# IDE, ATA and ATAPI Block devices -# -# CONFIG_BLK_DEV_IDE is not set -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -# CONFIG_BLK_DEV_IDEDISK is not set -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_BLK_DEV_IDECS is not set -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set -# CONFIG_IDE_CHIPSETS is not set -# CONFIG_IDEDMA_AUTO is not set - -# -# SCSI support -# -# CONFIG_SCSI is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# -# Network device support +# Network testing # +# CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set -# CONFIG_NET_SB1000 is not set # # Ethernet (10 or 100Mbit) # -CONFIG_NET_ETHERNET=y -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_AT1700 is not set -# CONFIG_DEPCA is not set -# CONFIG_NET_ISA is not set -# CONFIG_NET_PCI is not set -# CONFIG_NET_POCKET is not set +# CONFIG_MII is not set # # Ethernet (1000 Mbit) # -# CONFIG_ACENIC is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set # -# Wireless LAN (non-hamradio) +# Ethernet (10000 Mbit) # -# CONFIG_NET_RADIO is not set # # Token Ring devices # -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # -# Amateur Radio support +# ISDN subsystem # -# CONFIG_HAMRADIO is not set +# CONFIG_ISDN is not set # -# IrDA (infrared) support +# Telephony Support # -# CONFIG_IRDA is not set +# CONFIG_PHONE is not set # -# ISDN subsystem +# Input device support # -# CONFIG_ISDN is not set +# CONFIG_INPUT is not set # -# CD-ROM drivers (not for SCSI or IDE/ATAPI drives) +# Userland interfaces # -# CONFIG_CD_NO_IDESCSI is not set # -# Input core support +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers # -# CONFIG_INPUT is not set # # Character devices # # CONFIG_VT is not set -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_UNIX98_PTYS is not set # -# I2C support +# Serial drivers # -# CONFIG_I2C is not set +# CONFIG_SERIAL_8250 is not set # -# Mice +# Non-8250 serial port support # -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_QIC02_TAPE is not set # -# Joysticks +# IPMI # -# CONFIG_JOYSTICK is not set -# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set -# CONFIG_NVRAM is not set # CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -330,6 +450,7 @@ CONFIG_NET_ETHERNET=y # CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set # # Multimedia devices @@ -337,76 +458,98 @@ CONFIG_NET_ETHERNET=y # CONFIG_VIDEO_DEV is not set # +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# # File systems # +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set +CONFIG_JFFS_FS=y +CONFIG_JFFS_FS_VERBOSE=0 +# CONFIG_JFFS2_FS is not set CONFIG_CRAMFS=y -CONFIG_RAMFS=y -# CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set +# CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS is not set # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_EXT2_FS is not set # CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_NFS_FS is not set -# CONFIG_NFS_V3 is not set -# CONFIG_ROOT_NFS is not set +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set # CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -# CONFIG_SUNRPC is not set -# CONFIG_LOCKD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_MOUNT_SUBDIR is not set -# CONFIG_NCPFS_NDS_DOMAINS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# # CONFIG_NLS is not set # @@ -417,9 +560,33 @@ CONFIG_MSDOS_PARTITION=y # # USB support # -# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set # # Kernel hacking # # CONFIG_PROFILE is not set +# CONFIG_ETRAX_KGDB is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_FRAME_POINTER is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y diff -puN arch/cris/Kconfig~cris-architecture-update arch/cris/Kconfig --- 25/arch/cris/Kconfig~cris-architecture-update 2004-06-01 01:09:29.075979432 -0700 +++ 25-akpm/arch/cris/Kconfig 2004-06-01 01:09:29.171964840 -0700 @@ -27,19 +27,11 @@ menu "General setup" source "fs/Kconfig.binfmt" -config ETRAX_KGDB - bool "Use kernel gdb debugger" - ---help--- - The CRIS version of gdb can be used to remotely debug a running - Linux kernel via the serial debug port. Provided you have gdb-cris - installed, run gdb-cris vmlinux, then type - - (gdb) set remotebaud 115200 <- kgdb uses 115200 as default - (gdb) target remote /dev/ttyS0 <- maybe you use another port - - This should connect you to your booted kernel (or boot it now if you - didn't before). The kernel halts when it boots, waiting for gdb if - this option is turned on! +config ETRAX_CMDLINE + string "Kernel command line" + default "root=/dev/mtdblock3" + help + Pass additional commands to the kernel. config ETRAX_WATCHDOG bool "Enable ETRAX watchdog" @@ -99,11 +91,6 @@ config SVINTO_SIM help Support the xsim ETRAX Simulator. -config ETRAX200LX - bool "ETRAX-200LX-V32" - help - Support CRIS V32. - endchoice config ETRAX_ARCH_V10 @@ -111,11 +98,6 @@ config ETRAX_ARCH_V10 default y if ETRAX100LX || ETRAX100LX_V2 default n if !(ETRAX100LX || ETRAX100LX_V2) -config ETRAX_ARCH_V32 - bool - default y if ETRAX200LX - default n if !(ETRAX200LX) - config ETRAX_DRAM_SIZE int "DRAM size (dec, in MB)" default "8" @@ -128,35 +110,18 @@ config ETRAX_FLASH_BUSWIDTH help Width in bytes of the Flash bus (1, 2 or 4). Is usually 2. -config ETRAX_ROOT_DEVICE - string "Root device name" - default "/dev/mtdblock3" - help - Specifies the device that should be mounted as root file system - when booting from flash. The axisflashmap driver adds an additional - mtd partition for the appended root file system image, so this option - should normally be the mtdblock device for the partition after the - last partition in the partition table. - -# duplicate choice configs are not yet supported, so the followinguse -# doesn't work: - source arch/cris/arch-v10/Kconfig endmenu # bring in ETRAX built-in drivers menu "Drivers for built-in interfaces" - source arch/cris/arch-v10/drivers/Kconfig endmenu source "drivers/base/Kconfig" -# bring in Etrax built-in drivers -source "arch/cris/drivers/Kconfig" - # standard linux drivers source "drivers/mtd/Kconfig" @@ -212,6 +177,37 @@ config PROFILE_SHIFT depends on PROFILE default "2" +config ETRAX_KGDB + bool "Use kernel GDB debugger" + ---help--- + The CRIS version of gdb can be used to remotely debug a running + Linux kernel via the serial debug port. Provided you have gdb-cris + installed, run gdb-cris vmlinux, then type + + (gdb) set remotebaud 115200 <- kgdb uses 115200 as default + (gdb) target remote /dev/ttyS0 <- maybe you use another port + + This should connect you to your booted kernel (or boot it now if you + didn't before). The kernel halts when it boots, waiting for gdb if + this option is turned on! + + +config DEBUG_INFO + bool "Compile the kernel with debug info" + help + If you say Y here the resulting kernel image will include + debugging info resulting in a larger kernel image. + Say Y here only if you plan to use gdb to debug the kernel. + If you don't debug the kernel, you can say N. + +config FRAME_POINTER + bool "Compile the kernel with frame pointers" + help + If you say Y here the resulting kernel image will be slightly larger + and slower, but it will give very useful debugging information. + If you don't debug the kernel, you can say N, but we may not be able + to solve problems without frame pointers. + endmenu source "security/Kconfig" diff -puN /dev/null arch/cris/kernel/crisksyms.c --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25-akpm/arch/cris/kernel/crisksyms.c 2004-06-01 01:09:29.172964688 -0700 @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void dump_thread(struct pt_regs *, struct user *); +extern unsigned long get_cmos_time(void); +extern void __Udiv(void); +extern void __Umod(void); +extern void __Div(void); +extern void __Mod(void); +extern void __ashrdi3(void); +extern void iounmap(void *addr); + +/* Platform dependent support */ +EXPORT_SYMBOL(dump_thread); +EXPORT_SYMBOL(enable_irq); +EXPORT_SYMBOL(disable_irq); +EXPORT_SYMBOL(kernel_thread); +EXPORT_SYMBOL(get_cmos_time); +EXPORT_SYMBOL(loops_per_usec); + +/* String functions */ +EXPORT_SYMBOL(memcmp); +EXPORT_SYMBOL(memmove); +EXPORT_SYMBOL(strpbrk); +EXPORT_SYMBOL(strstr); +EXPORT_SYMBOL(strcpy); +EXPORT_SYMBOL(strchr); +EXPORT_SYMBOL(strcmp); +EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL(strcat); +EXPORT_SYMBOL(strncat); +EXPORT_SYMBOL(strncmp); +EXPORT_SYMBOL(strncpy); + +/* Math functions */ +EXPORT_SYMBOL(__Udiv); +EXPORT_SYMBOL(__Umod); +EXPORT_SYMBOL(__Div); +EXPORT_SYMBOL(__Mod); +EXPORT_SYMBOL(__ashrdi3); + +/* Memory functions */ +EXPORT_SYMBOL(__ioremap); +EXPORT_SYMBOL(iounmap); + +/* Semaphore functions */ +EXPORT_SYMBOL(__up); +EXPORT_SYMBOL(__down); +EXPORT_SYMBOL(__down_interruptible); +EXPORT_SYMBOL(__down_trylock); + +/* Export shadow registers for the CPU I/O pins */ +EXPORT_SYMBOL(genconfig_shadow); +EXPORT_SYMBOL(port_pa_data_shadow); +EXPORT_SYMBOL(port_pa_dir_shadow); +EXPORT_SYMBOL(port_pb_data_shadow); +EXPORT_SYMBOL(port_pb_dir_shadow); +EXPORT_SYMBOL(port_pb_config_shadow); +EXPORT_SYMBOL(port_g_data_shadow); + +/* Userspace access functions */ +EXPORT_SYMBOL(__copy_user_zeroing); +EXPORT_SYMBOL(__copy_user); + +/* Cache flush functions */ +EXPORT_SYMBOL(flush_etrax_cache); +EXPORT_SYMBOL(prepare_rx_descriptor); + +#undef memcpy +#undef memset +extern void * memset(void *, int, __kernel_size_t); +extern void * memcpy(void *, const void *, __kernel_size_t); +EXPORT_SYMBOL_NOVERS(memcpy); +EXPORT_SYMBOL_NOVERS(memset); + +#ifdef CONFIG_ETRAX_FAST_TIMER +/* Fast timer functions */ +EXPORT_SYMBOL(fast_timer_list); +EXPORT_SYMBOL(start_one_shot_timer); +EXPORT_SYMBOL(del_fast_timer); +EXPORT_SYMBOL(schedule_usleep); +#endif + diff -L arch/cris/kernel/hexify.c -puN arch/cris/kernel/hexify.c~cris-architecture-update /dev/null --- 25/arch/cris/kernel/hexify.c +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,31 +0,0 @@ -#include - - -void main() -{ - int c; - int comma=0; - int count=0; - while((c=getchar())!=EOF) - { - unsigned char x=c; - if(comma) - printf(","); - else - comma=1; - if(count==8) - { - count=0; - printf("\n"); - } - if(count==0) - printf("\t"); - printf("0x%02X",c); - count++; - } - if(count) - printf("\n"); - exit(0); -} - - diff -puN arch/cris/kernel/irq.c~cris-architecture-update arch/cris/kernel/irq.c --- 25/arch/cris/kernel/irq.c~cris-architecture-update 2004-06-01 01:09:29.078978976 -0700 +++ 25-akpm/arch/cris/kernel/irq.c 2004-06-01 01:09:29.173964536 -0700 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.8 2003/07/04 08:27:52 starvik Exp $ +/* * * linux/arch/cris/kernel/irq.c * @@ -99,7 +99,7 @@ int show_interrupts(struct seq_file *p, if (!action) goto skip; seq_printf(p, "%2d: %10u %c %s", - i, kstat_cpu(0).irqs[i], + i, kstat_this_cpu.irqs[i], (action->flags & SA_INTERRUPT) ? '+' : ' ', action->name); for (action = action->next; action; action = action->next) { @@ -129,13 +129,12 @@ asmlinkage void do_IRQ(int irq, struct p cpu = smp_processor_id(); irq_enter(); - kstat_cpu(cpu).irqs[irq]++; + kstat_cpu(cpu).irqs[irq - FIRST_IRQ]++; + action = irq_action[irq - FIRST_IRQ]; - action = irq_action[irq]; if (action) { if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); - action = irq_action[irq]; do_random = 0; do { do_random |= action->flags; @@ -175,7 +174,7 @@ int setup_irq(int irq, struct irqaction struct irqaction *old, **p; unsigned long flags; - p = irq_action + irq; + p = irq_action + irq - FIRST_IRQ; if ((old = *p) != NULL) { /* Can't share interrupts unless both agree to */ if (!(old->flags & new->flags & SA_SHIRQ)) @@ -230,12 +229,6 @@ int request_irq(unsigned int irq, int retval; struct irqaction * action; - /* interrupts 0 and 1 are hardware breakpoint and NMI and we can't support - these yet. interrupt 15 is the multiple irq, it's special. */ - - if(irq < 2 || irq == 15 || irq >= NR_IRQS) - return -EINVAL; - if(!handler) return -EINVAL; @@ -270,7 +263,7 @@ void free_irq(unsigned int irq, void *de printk("Trying to free IRQ%d\n",irq); return; } - for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { + for (p = irq - FIRST_IRQ + irq_action; (action = *p) != NULL; p = &action->next) { if (action->dev_id != dev_id) continue; @@ -278,7 +271,7 @@ void free_irq(unsigned int irq, void *de local_save_flags(flags); local_irq_disable(); *p = action->next; - if (!irq_action[irq]) { + if (!irq_action[irq - FIRST_IRQ]) { mask_irq(irq); arch_free_irq(irq); } diff -L arch/cris/kernel/ksyms.c -puN arch/cris/kernel/ksyms.c~cris-architecture-update /dev/null --- 25/arch/cris/kernel/ksyms.c +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,96 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern void dump_thread(struct pt_regs *, struct user *); -extern unsigned long get_cmos_time(void); -extern void __Udiv(void); -extern void __Umod(void); -extern void __Div(void); -extern void __Mod(void); -extern void __ashrdi3(void); -extern void iounmap(void *addr); - -/* Platform dependent support */ -EXPORT_SYMBOL(dump_thread); -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); -EXPORT_SYMBOL(kernel_thread); -EXPORT_SYMBOL(get_cmos_time); -EXPORT_SYMBOL(loops_per_usec); - -/* String functions */ -EXPORT_SYMBOL(memcmp); -EXPORT_SYMBOL(memmove); -EXPORT_SYMBOL(strpbrk); -EXPORT_SYMBOL(strstr); -EXPORT_SYMBOL(strcpy); -EXPORT_SYMBOL(strchr); -EXPORT_SYMBOL(strcmp); -EXPORT_SYMBOL(strlen); -EXPORT_SYMBOL(strcat); -EXPORT_SYMBOL(strncat); -EXPORT_SYMBOL(strncmp); -EXPORT_SYMBOL(strncpy); - -/* Math functions */ -EXPORT_SYMBOL(__Udiv); -EXPORT_SYMBOL(__Umod); -EXPORT_SYMBOL(__Div); -EXPORT_SYMBOL(__Mod); -EXPORT_SYMBOL(__ashrdi3); - -/* Memory functions */ -EXPORT_SYMBOL(__ioremap); -EXPORT_SYMBOL(iounmap); - -/* Semaphore functions */ -EXPORT_SYMBOL(__up); -EXPORT_SYMBOL(__down); -EXPORT_SYMBOL(__down_interruptible); -EXPORT_SYMBOL(__down_trylock); - -/* Export shadow registers for the CPU I/O pins */ -EXPORT_SYMBOL(genconfig_shadow); -EXPORT_SYMBOL(port_pa_data_shadow); -EXPORT_SYMBOL(port_pa_dir_shadow); -EXPORT_SYMBOL(port_pb_data_shadow); -EXPORT_SYMBOL(port_pb_dir_shadow); -EXPORT_SYMBOL(port_pb_config_shadow); -EXPORT_SYMBOL(port_g_data_shadow); - -/* Userspace access functions */ -EXPORT_SYMBOL(__copy_user_zeroing); -EXPORT_SYMBOL(__copy_user); - -/* Cache flush functions */ -EXPORT_SYMBOL(flush_etrax_cache); -EXPORT_SYMBOL(prepare_rx_descriptor); - -#undef memcpy -#undef memset -extern void * memset(void *, int, __kernel_size_t); -extern void * memcpy(void *, const void *, __kernel_size_t); -EXPORT_SYMBOL_NOVERS(memcpy); -EXPORT_SYMBOL_NOVERS(memset); - - diff -puN arch/cris/kernel/Makefile~cris-architecture-update arch/cris/kernel/Makefile --- 25/arch/cris/kernel/Makefile~cris-architecture-update 2004-06-01 01:09:29.080978672 -0700 +++ 25-akpm/arch/cris/kernel/Makefile 2004-06-01 01:09:29.174964384 -0700 @@ -1,14 +1,14 @@ -# $Id: Makefile,v 1.8 2003/04/09 05:20:47 starvik Exp $ +# $Id: Makefile,v 1.10 2004/05/14 10:18:12 starvik Exp $ # # Makefile for the linux kernel. # -extra-y := vmlinux.lds.s +extra-y := vmlinux.lds.s obj-y := process.o traps.o irq.o ptrace.o setup.o \ time.o sys_cris.o semaphore.o -obj-$(CONFIG_MODULES) += ksyms.o +obj-$(CONFIG_MODULES) += crisksyms.o obj-$(CONFIG_MODULES) += module.o clean: diff -puN arch/cris/kernel/module.c~cris-architecture-update arch/cris/kernel/module.c --- 25/arch/cris/kernel/module.c~cris-architecture-update 2004-06-01 01:09:29.081978520 -0700 +++ 25-akpm/arch/cris/kernel/module.c 2004-06-01 01:09:29.174964384 -0700 @@ -75,8 +75,6 @@ int apply_relocate(Elf32_Shdr *sechdrs, sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + ELF32_R_SYM(rel[i].r_info); - /* TODO: This is probably not correct */ - printk("Beware: untested code in module.c!\n"); /* We add the value into the location given */ *location += sym->st_value; } @@ -89,9 +87,26 @@ int apply_relocate_add(Elf32_Shdr *sechd unsigned int relsec, struct module *me) { - printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", - me->name); - return -ENOEXEC; + unsigned int i; + Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; + + DEBUGP ("Applying relocate section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + + for (i = 0; i < sechdrs[relsec].sh_size / sizeof (*rela); i++) { + /* This is where to make the change */ + uint32_t *loc + = ((void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + + rela[i].r_offset); + /* This is the symbol it is referring to. Note that all + undefined symbols have been resolved. */ + Elf32_Sym *sym + = ((Elf32_Sym *)sechdrs[symindex].sh_addr + + ELF32_R_SYM (rela[i].r_info)); + *loc = sym->st_value + rela[i].r_addend; + } + + return 0; } int module_finalize(const Elf_Ehdr *hdr, diff -puN arch/cris/kernel/process.c~cris-architecture-update arch/cris/kernel/process.c --- 25/arch/cris/kernel/process.c~cris-architecture-update 2004-06-01 01:09:29.083978216 -0700 +++ 25-akpm/arch/cris/kernel/process.c 2004-06-01 01:09:29.175964232 -0700 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.14 2003/06/10 10:21:12 johana Exp $ +/* $Id: process.c,v 1.17 2004/04/05 13:53:48 starvik Exp $ * * linux/arch/cris/kernel/process.c * @@ -8,9 +8,18 @@ * Authors: Bjorn Wesen (bjornw@axis.com) * * $Log: process.c,v $ + * Revision 1.17 2004/04/05 13:53:48 starvik + * Merge of Linux 2.6.5 + * + * Revision 1.16 2003/10/27 08:04:33 starvik + * Merge of Linux 2.6.0-test9 + * + * Revision 1.15 2003/09/11 07:29:52 starvik + * Merge of Linux 2.6.0-test5 + * * Revision 1.14 2003/06/10 10:21:12 johana * Moved thread_saved_pc() from arch/cris/kernel/process.c to - * subarch specific process.c. + * subarch specific process.c. arch-v32 has an erp, no irp. * * Revision 1.13 2003/04/09 05:20:47 starvik * Merge of Linux 2.5.67 @@ -94,6 +103,7 @@ #include #include #include +#include #include #include #include @@ -183,13 +193,17 @@ void cpu_idle (void) { /* endless idle loop with no priority at all */ while (1) { - void (*idle)(void) = pm_idle; - if (!idle) - idle = default_idle; - while (!need_resched()) + while (!need_resched()) { + void (*idle)(void) = pm_idle; + + if (!idle) + idle = default_idle; + idle(); + } schedule(); } + } void hard_reset_now (void); diff -puN arch/cris/kernel/setup.c~cris-architecture-update arch/cris/kernel/setup.c --- 25/arch/cris/kernel/setup.c~cris-architecture-update 2004-06-01 01:09:29.085977912 -0700 +++ 25-akpm/arch/cris/kernel/setup.c 2004-06-01 01:09:29.176964080 -0700 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.7 2003/07/04 08:27:52 starvik Exp $ +/* * * linux/arch/cris/kernel/setup.c * @@ -10,6 +10,7 @@ * This file handles the architecture-dependent parts of initialization */ +#include #include #include #include @@ -35,6 +36,8 @@ extern unsigned long dram_start, dram_en extern unsigned long romfs_start, romfs_length, romfs_in_flash; /* from head.S */ +extern void show_etrax_copyright(void); /* arch-vX/kernel/setup.c */ + /* This mainly sets up the memory area, and can be really confusing. * * The physical DRAM is virtually mapped into dram_start to dram_end @@ -150,18 +153,16 @@ setup_arch(char **cmdline_p) *cmdline_p = command_line; #ifdef CONFIG_ETRAX_CMDLINE - strlcpy(command_line, CONFIG_ETRAX_CMDLINE, sizeof(command_line)); -#elif defined(CONFIG_ETRAX_ROOT_DEVICE) - strlcpy(command_line, "root=", sizeof(command_line)); - strlcat(command_line, CONFIG_ETRAX_ROOT_DEVICE, - sizeof(command_line)); -#endif + strlcpy(command_line, CONFIG_ETRAX_CMDLINE, COMMAND_LINE_SIZE); command_line[COMMAND_LINE_SIZE - 1] = '\0'; - /* give credit for the CRIS port */ - - printk("Linux/CRIS port on ETRAX 100LX (c) 2001 Axis Communications AB\n"); + /* Save command line for future references. */ + memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE); + saved_command_line[COMMAND_LINE_SIZE - 1] = '\0'; +#endif + /* give credit for the CRIS port */ + show_etrax_copyright(); } static void *c_start(struct seq_file *m, loff_t *pos) diff -puN arch/cris/kernel/sys_cris.c~cris-architecture-update arch/cris/kernel/sys_cris.c --- 25/arch/cris/kernel/sys_cris.c~cris-architecture-update 2004-06-01 01:09:29.086977760 -0700 +++ 25-akpm/arch/cris/kernel/sys_cris.c 2004-06-01 01:09:29.176964080 -0700 @@ -1,4 +1,4 @@ -/* $Id: sys_cris.c,v 1.5 2003/07/04 08:27:52 starvik Exp $ +/* $Id: sys_cris.c,v 1.6 2004/03/11 11:38:40 starvik Exp $ * * linux/arch/cris/kernel/sys_cris.c * diff -puN arch/cris/kernel/time.c~cris-architecture-update arch/cris/kernel/time.c --- 25/arch/cris/kernel/time.c~cris-architecture-update 2004-06-01 01:09:29.087977608 -0700 +++ 25-akpm/arch/cris/kernel/time.c 2004-06-01 01:09:29.177963928 -0700 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.9 2003/07/04 08:27:52 starvik Exp $ +/* $Id: time.c,v 1.14 2004/06/01 05:38:11 starvik Exp $ * * linux/arch/cris/kernel/time.c * @@ -29,6 +29,7 @@ #include #include #include +#include u64 jiffies_64 = INITIAL_JIFFIES; @@ -39,6 +40,8 @@ int have_rtc; /* used to remember if we #define TICK_SIZE tick extern unsigned long wall_jiffies; +extern unsigned long loops_per_jiffy; /* init/main.c */ +unsigned long loops_per_usec; extern unsigned long do_slow_gettimeoffset(void); static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset; @@ -62,6 +65,15 @@ void do_gettimeofday(struct timeval *tv) if (lost) usec += lost * (1000000 / HZ); } + + /* + * If time_adjust is negative then NTP is slowing the clock + * so make sure not to go into next possible interval. + * Better to lose some accuracy than have time go backwards.. + */ + if (unlikely(time_adjust < 0) && usec > tickadj) + usec = tickadj; + sec = xtime.tv_sec; usec += xtime.tv_nsec / 1000; local_irq_restore(flags); @@ -79,35 +91,33 @@ EXPORT_SYMBOL(do_gettimeofday); int do_settimeofday(struct timespec *tv) { - unsigned long flags; + time_t wtm_sec, sec = tv->tv_sec; + long wtm_nsec, nsec = tv->tv_nsec; - if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) + if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) return -EINVAL; - local_irq_save(flags); - local_irq_disable(); - - /* This is revolting. We need to set the xtime.tv_usec - * correctly. However, the value in this location is - * is value at the last tick. - * Discover what correction gettimeofday - * would have done, and then undo it! + write_seqlock_irq(&xtime_lock); + /* + * This is revolting. We need to set "xtime" correctly. However, the + * value in this location is the value at the most recent update of + * wall time. Discover what correction gettimeofday() would have + * made, and then undo it! */ - tv->tv_nsec -= do_gettimeoffset() * 1000; - tv->tv_nsec -= (jiffies - wall_jiffies) * TICK_NSEC; + nsec -= do_gettimeoffset() * NSEC_PER_USEC; + nsec -= (jiffies - wall_jiffies) * TICK_NSEC; + + wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); + wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); + + set_normalized_timespec(&xtime, sec, nsec); + set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); - while (tv->tv_nsec < 0) { - tv->tv_nsec += NSEC_PER_SEC; - tv->tv_sec--; - } - xtime.tv_sec = tv->tv_sec; - xtime.tv_nsec = tv->tv_nsec; time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; - time_state = TIME_ERROR; /* p. 24, (a) */ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; - local_irq_restore(flags); + write_sequnlock_irq(&xtime_lock); clock_was_set(); return 0; } @@ -125,7 +135,7 @@ int set_rtc_mmss(unsigned long nowtime) int retval = 0; int real_seconds, real_minutes, cmos_minutes; - printk("set_rtc_mmss(%lu)\n", nowtime); + printk(KERN_DEBUG "set_rtc_mmss(%lu)\n", nowtime); if(!have_rtc) return 0; @@ -174,7 +184,8 @@ get_cmos_time(void) mon = CMOS_READ(RTC_MONTH); year = CMOS_READ(RTC_YEAR); - printk("rtc: sec 0x%x min 0x%x hour 0x%x day 0x%x mon 0x%x year 0x%x\n", + printk(KERN_DEBUG + "rtc: sec 0x%x min 0x%x hour 0x%x day 0x%x mon 0x%x year 0x%x\n", sec, min, hour, day, mon, year); BCD_TO_BIN(sec); @@ -202,3 +213,20 @@ update_xtime_from_cmos(void) xtime.tv_nsec = 0; } } + +/* + * Scheduler clock - returns current time in nanosec units. + */ +unsigned long long sched_clock(void) +{ + return (unsigned long long)jiffies * (1000000000 / HZ); +} + +static int +__init init_udelay(void) +{ + loops_per_usec = (loops_per_jiffy * HZ) / 1000000; + return 0; +} + +__initcall(init_udelay); diff -puN arch/cris/kernel/traps.c~cris-architecture-update arch/cris/kernel/traps.c --- 25/arch/cris/kernel/traps.c~cris-architecture-update 2004-06-01 01:09:29.089977304 -0700 +++ 25-akpm/arch/cris/kernel/traps.c 2004-06-01 01:09:29.177963928 -0700 @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.7 2003/07/04 08:27:52 starvik Exp $ +/* $Id: traps.c,v 1.9 2004/05/11 12:28:26 starvik Exp $ * * linux/arch/cris/traps.c * @@ -14,6 +14,7 @@ */ #include +#include #include #include diff -puN arch/cris/Makefile~cris-architecture-update arch/cris/Makefile --- 25/arch/cris/Makefile~cris-architecture-update 2004-06-01 01:09:29.090977152 -0700 +++ 25-akpm/arch/cris/Makefile 2004-06-01 01:09:29.178963776 -0700 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.15 2003/07/04 12:47:53 tobiasa Exp $ +# $Id: Makefile,v 1.20 2004/05/14 14:35:58 orjanf Exp $ # cris/Makefile # # This file is included by the global makefile so that you can add your own @@ -34,7 +34,7 @@ AFLAGS += -mlinux CFLAGS := $(CFLAGS) -mlinux -march=$(arch-y) -pipe -ifdef CONFIG_ETRAX_KGDB +ifdef CONFIG_FRAME_POINTER CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS)) -g CFLAGS += -fno-omit-frame-pointer endif @@ -90,10 +90,14 @@ prepare: arch/$(ARCH)/.links include/asm # Create some links to make all tools happy arch/$(ARCH)/.links: + @rm -rf arch/$(ARCH)/drivers @ln -sfn $(SARCH)/drivers arch/$(ARCH)/drivers + @rm -rf arch/$(ARCH)/boot @ln -sfn $(SARCH)/boot arch/$(ARCH)/boot + @rm -rf arch/$(ARCH)/lib @ln -sfn $(SARCH)/lib arch/$(ARCH)/lib - @ln -sfn $(SARCH)/vmlinux.lds.S arch/$(ARCH)/kernel/vmlinux.lds.S + @ln -sfn $(SARCH) arch/$(ARCH)/arch + @ln -sfn ../$(SARCH)/vmlinux.lds.S arch/$(ARCH)/kernel/vmlinux.lds.S @touch $@ # Create link to sub arch includes diff -puN arch/cris/mm/fault.c~cris-architecture-update arch/cris/mm/fault.c --- 25/arch/cris/mm/fault.c~cris-architecture-update 2004-06-01 01:09:29.092976848 -0700 +++ 25-akpm/arch/cris/mm/fault.c 2004-06-01 01:09:29.179963624 -0700 @@ -6,9 +6,18 @@ * Authors: Bjorn Wesen * * $Log: fault.c,v $ + * Revision 1.11 2004/05/14 07:58:05 starvik + * Merge of changes from 2.4 + * + * Revision 1.10 2003/10/27 14:51:24 starvik + * Removed debugcode + * + * Revision 1.9 2003/10/27 14:50:42 starvik + * Changed do_page_fault signature + * * Revision 1.8 2003/07/04 13:02:48 tobiasa * Moved code snippet from arch/cris/mm/fault.c that searches for fixup code - * to separate function in arch-specific files. + * to seperate function in arch-specific files. * * Revision 1.7 2003/01/22 06:48:38 starvik * Fixed warnings issued by GCC 3.2.1 @@ -95,10 +104,6 @@ extern int find_fixup_code(struct pt_regs *); extern void die_if_kernel(const char *, struct pt_regs *, long); -asmlinkage void do_invalid_op (struct pt_regs *, unsigned long); -asmlinkage void do_page_fault(unsigned long address, struct pt_regs *regs, - int error_code); - /* debug of low-level TLB reload */ #undef DEBUG @@ -134,14 +139,16 @@ volatile pgd_t *current_pgd; asmlinkage void do_page_fault(unsigned long address, struct pt_regs *regs, - int error_code) + int protection, int writeaccess) { struct task_struct *tsk; struct mm_struct *mm; struct vm_area_struct * vma; - int writeaccess; siginfo_t info; + D(printk("Page fault for %X at %X, prot %d write %d\n", + address, regs->erp, protection, writeaccess)); + tsk = current; /* @@ -164,7 +171,7 @@ do_page_fault(unsigned long address, str */ if (address >= VMALLOC_START && - !(error_code & 1) && + !protection && !user_mode(regs)) goto vmalloc_fault; @@ -172,7 +179,6 @@ do_page_fault(unsigned long address, str sti(); mm = tsk->mm; - writeaccess = error_code & 2; info.si_code = SEGV_MAPERR; /* @@ -291,7 +297,7 @@ do_page_fault(unsigned long address, str printk(KERN_ALERT "Unable to handle kernel access"); printk(" at virtual address %08lx\n",address); - die_if_kernel("Oops", regs, error_code); + die_if_kernel("Oops", regs, (writeaccess << 1) | protection); do_exit(SIGKILL); diff -puN arch/cris/mm/init.c~cris-architecture-update arch/cris/mm/init.c --- 25/arch/cris/mm/init.c~cris-architecture-update 2004-06-01 01:09:29.093976696 -0700 +++ 25-akpm/arch/cris/mm/init.c 2004-06-01 01:09:29.179963624 -0700 @@ -7,6 +7,13 @@ * Authors: Bjorn Wesen (bjornw@axis.com) * * $Log: init.c,v $ + * Revision 1.11 2004/05/28 09:28:56 starvik + * Calculation of loops_per_usec moved because initalization order has changed + * in Linux 2.6. + * + * Revision 1.10 2004/05/14 07:58:05 starvik + * Merge of changes from 2.4 + * * Revision 1.9 2003/07/04 08:27:54 starvik * Merge of Linux 2.5.74 * @@ -120,9 +127,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_ga unsigned long empty_zero_page; -extern unsigned long loops_per_jiffy; /* init/main.c */ -unsigned long loops_per_usec; - extern char _stext, _edata, _etext; /* From linkerscript */ extern char __init_begin, __init_end; @@ -190,7 +194,8 @@ mem_init(void) datasize = (unsigned long) &_edata - (unsigned long) &_etext; initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; - printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, " + printk(KERN_INFO + "Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, " "%dk init)\n" , (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), max_mapnr << (PAGE_SHIFT-10), @@ -199,16 +204,6 @@ mem_init(void) datasize >> 10, initsize >> 10 ); - - /* HACK alert - calculate a loops_per_usec for asm/delay.h here - * since this is called just after calibrate_delay in init/main.c - * but before places which use udelay. cannot be in time.c since - * that is called _before_ calibrate_delay - */ - - loops_per_usec = (loops_per_jiffy * HZ) / 1000000; - - return; } /* free the pages occupied by initialization code */ @@ -225,6 +220,6 @@ free_initmem(void) free_page(addr); totalram_pages++; } - printk ("Freeing unused kernel memory: %luk freed\n", + printk (KERN_INFO "Freeing unused kernel memory: %luk freed\n", (unsigned long)((&__init_end - &__init_begin) >> 10)); } diff -puN arch/cris/mm/ioremap.c~cris-architecture-update arch/cris/mm/ioremap.c --- 25/arch/cris/mm/ioremap.c~cris-architecture-update 2004-06-01 01:09:29.094976544 -0700 +++ 25-akpm/arch/cris/mm/ioremap.c 2004-06-01 01:09:29.180963472 -0700 @@ -118,31 +118,6 @@ void * __ioremap(unsigned long phys_addr if (!size || last_addr < phys_addr) return NULL; -#if 0 - /* TODO: Here we can put checks for driver-writer abuse... */ - - /* - * Don't remap the low PCI/ISA area, it's always mapped.. - */ - if (phys_addr >= 0xA0000 && last_addr < 0x100000) - return phys_to_virt(phys_addr); - - /* - * Don't allow anybody to remap normal RAM that we're using.. - */ - if (phys_addr < virt_to_phys(high_memory)) { - char *t_addr, *t_end; - struct page *page; - - t_addr = __va(phys_addr); - t_end = t_addr + (size - 1); - - for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++) - if(!PageReserved(page)) - return NULL; - } -#endif - /* * Mappings have to be page-aligned */ diff -puN include/asm-cris/arch-v10/cache.h~cris-architecture-update include/asm-cris/arch-v10/cache.h --- 25/include/asm-cris/arch-v10/cache.h~cris-architecture-update 2004-06-01 01:09:29.095976392 -0700 +++ 25-akpm/include/asm-cris/arch-v10/cache.h 2004-06-01 01:09:29.180963472 -0700 @@ -3,6 +3,7 @@ /* Etrax 100LX have 32-byte cache-lines. */ #define L1_CACHE_BYTES 32 +#define L1_CACHE_SHIFT 5 #define L1_CACHE_SHIFT_MAX 5 #endif /* _ASM_ARCH_CACHE_H */ diff -puN include/asm-cris/arch-v10/irq.h~cris-architecture-update include/asm-cris/arch-v10/irq.h --- 25/include/asm-cris/arch-v10/irq.h~cris-architecture-update 2004-06-01 01:09:29.096976240 -0700 +++ 25-akpm/include/asm-cris/arch-v10/irq.h 2004-06-01 01:09:29.180963472 -0700 @@ -8,6 +8,11 @@ #include #define NR_IRQS 32 + +/* The first vector number used for IRQs in v10 is really 0x20 */ +/* but all the code and constants are offseted to make 0 the first */ +#define FIRST_IRQ 0 + #define SOME_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, some) /* 0 ? */ #define NMI_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, nmi) /* 1 */ #define TIMER0_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, timer0) /* 2 */ diff -puN include/asm-cris/arch-v10/offset.h~cris-architecture-update include/asm-cris/arch-v10/offset.h --- 25/include/asm-cris/arch-v10/offset.h~cris-architecture-update 2004-06-01 01:09:29.098975936 -0700 +++ 25-akpm/include/asm-cris/arch-v10/offset.h 2004-06-01 01:09:29.181963320 -0700 @@ -25,7 +25,7 @@ #define THREAD_usp 4 /* offsetof(struct thread_struct, usp) */ #define THREAD_dccr 8 /* offsetof(struct thread_struct, dccr) */ -#define TASK_pid 121 /* offsetof(struct task_struct, pid) */ +#define TASK_pid 133 /* offsetof(struct task_struct, pid) */ #define LCLONE_VM 256 /* CLONE_VM */ #define LCLONE_UNTRACED 8388608 /* CLONE_UNTRACED */ diff -puN include/asm-cris/bitops.h~cris-architecture-update include/asm-cris/bitops.h --- 25/include/asm-cris/bitops.h~cris-architecture-update 2004-06-01 01:09:29.099975784 -0700 +++ 25-akpm/include/asm-cris/bitops.h 2004-06-01 01:09:29.181963320 -0700 @@ -296,6 +296,50 @@ extern inline int find_next_zero_bit (vo } /** + * find_next_bit - find the first set bit in a memory region + * @addr: The address to base the search on + * @offset: The bitnumber to start searching at + * @size: The maximum size to search + */ +static __inline__ int find_next_bit(void *addr, int size, int offset) +{ + unsigned long *p = ((unsigned long *) addr) + (offset >> 5); + unsigned long result = offset & ~31UL; + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset &= 31UL; + if (offset) { + tmp = *(p++); + tmp &= (~0UL << offset); + if (size < 32) + goto found_first; + if (tmp) + goto found_middle; + size -= 32; + result += 32; + } + while (size & ~31UL) { + if ((tmp = *(p++))) + goto found_middle; + result += 32; + size -= 32; + } + if (!size) + return result; + tmp = *p; + +found_first: + tmp &= (~0UL >> (32 - size)); + if (tmp == 0UL) /* Are any bits set? */ + return result + size; /* Nope. */ +found_middle: + return result + __ffs(tmp); +} + +/** * find_first_zero_bit - find the first zero bit in a memory region * @addr: The address to start the search at * @size: The maximum size to search @@ -306,6 +350,8 @@ extern inline int find_next_zero_bit (vo #define find_first_zero_bit(addr, size) \ find_next_zero_bit((addr), (size), 0) +#define find_first_bit(addr, size) \ + find_next_bit((addr), (size), 0) #define ext2_set_bit test_and_set_bit #define ext2_set_bit_atomic(l,n,a) test_and_set_bit(n,a) diff -puN include/asm-cris/dma-mapping.h~cris-architecture-update include/asm-cris/dma-mapping.h --- 25/include/asm-cris/dma-mapping.h~cris-architecture-update 2004-06-01 01:09:29.100975632 -0700 +++ 25-akpm/include/asm-cris/dma-mapping.h 2004-06-01 01:09:29.182963168 -0700 @@ -1 +1,125 @@ -#include +#ifndef _ASM_CRIS_DMA_MAPPING_H +#define _ASM_CRIS_DMA_MAPPING_H + +#include "scatterlist.h" + +static inline int +dma_supported(struct device *dev, u64 mask) +{ + BUG(); + return 0; +} + +static inline int +dma_set_mask(struct device *dev, u64 dma_mask) +{ + BUG(); + return 1; +} + +static inline void * +dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, + int flag) +{ + BUG(); + return NULL; +} + +static inline void +dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, + dma_addr_t dma_handle) +{ + BUG(); +} + +static inline dma_addr_t +dma_map_single(struct device *dev, void *cpu_addr, size_t size, + enum dma_data_direction direction) +{ + BUG(); + return 0; +} + +static inline void +dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, + enum dma_data_direction direction) +{ + BUG(); +} + +static inline dma_addr_t +dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + BUG(); + return 0; +} + +static inline void +dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, + enum dma_data_direction direction) +{ + BUG(); +} + +static inline int +dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction direction) +{ + BUG(); + return 1; +} + +static inline void +dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, + enum dma_data_direction direction) +{ + BUG(); +} + +static inline void +dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size, + enum dma_data_direction direction) +{ + BUG(); +} + +static inline void +dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems, + enum dma_data_direction direction) +{ + BUG(); +} + +/* Now for the API extensions over the pci_ one */ + +#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) +#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) +#define dma_is_consistent(d) (1) + +static inline int +dma_get_cache_alignment(void) +{ + /* no easy way to get cache size on all processors, so return + * the maximum possible, to be safe */ + return (1 << L1_CACHE_SHIFT_MAX); +} + +static inline void +dma_sync_single_range(struct device *dev, dma_addr_t dma_handle, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + BUG(); +} + +static inline void +dma_cache_sync(void *vaddr, size_t size, + enum dma_data_direction direction) +{ + BUG(); +} + +#endif + diff -puN include/asm-cris/fasttimer.h~cris-architecture-update include/asm-cris/fasttimer.h --- 25/include/asm-cris/fasttimer.h~cris-architecture-update 2004-06-01 01:09:29.101975480 -0700 +++ 25-akpm/include/asm-cris/fasttimer.h 2004-06-01 01:09:29.182963168 -0700 @@ -1,4 +1,4 @@ -/* $Id: fasttimer.h,v 1.2 2002/12/11 13:03:43 starvik Exp $ +/* $Id: fasttimer.h,v 1.3 2004/05/14 10:19:19 starvik Exp $ * linux/include/asm-cris/fasttimer.h * * Fast timers for ETRAX100LX @@ -24,6 +24,8 @@ struct fast_timer{ /* Close to timer_lis const char *name; }; +extern struct fast_timer *fast_timer_list; + void start_one_shot_timer(struct fast_timer *t, fast_timer_function_type *function, unsigned long data, diff -puN include/asm-cris/ioctl.h~cris-architecture-update include/asm-cris/ioctl.h --- 25/include/asm-cris/ioctl.h~cris-architecture-update 2004-06-01 01:09:29.102975328 -0700 +++ 25-akpm/include/asm-cris/ioctl.h 2004-06-01 01:09:29.183963016 -0700 @@ -53,11 +53,18 @@ ((nr) << _IOC_NRSHIFT) | \ ((size) << _IOC_SIZESHIFT)) +/* provoke compile error for invalid uses of size argument */ +extern int __invalid_size_argument_for_IOC; +#define _IOC_TYPECHECK(t) \ + ((sizeof(t) == sizeof(t[1]) && \ + sizeof(t) < (1 << _IOC_SIZEBITS)) ? \ + sizeof(t) : __invalid_size_argument_for_IOC) + /* used to create numbers */ #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) -#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) -#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) -#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) +#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size))) +#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) +#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) /* used to decode ioctl numbers.. */ #define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) diff -puN include/asm-cris/io.h~cris-architecture-update include/asm-cris/io.h --- 25/include/asm-cris/io.h~cris-architecture-update 2004-06-01 01:09:29.103975176 -0700 +++ 25-akpm/include/asm-cris/io.h 2004-06-01 01:09:29.183963016 -0700 @@ -72,6 +72,8 @@ extern void iounmap(void *addr); #define IO_SPACE_LIMIT 0xffff #define inb(x) (0) +#define inw(x) (0) +#define inl(x) (0) #define outb(x,y) #define outw(x,y) #define outl(x,y) diff -puN /dev/null include/asm-cris/local.h --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25-akpm/include/asm-cris/local.h 2004-06-01 01:09:29.183963016 -0700 @@ -0,0 +1 @@ +#include diff -puN include/asm-cris/page.h~cris-architecture-update include/asm-cris/page.h --- 25/include/asm-cris/page.h~cris-architecture-update 2004-06-01 01:09:29.105974872 -0700 +++ 25-akpm/include/asm-cris/page.h 2004-06-01 01:09:29.184962864 -0700 @@ -6,7 +6,11 @@ /* PAGE_SHIFT determines the page size */ #define PAGE_SHIFT 13 +#ifndef __ASSEMBLY__ #define PAGE_SIZE (1UL << PAGE_SHIFT) +#else +#define PAGE_SIZE (1 << PAGE_SHIFT) +#endif #define PAGE_MASK (~(PAGE_SIZE-1)) #ifdef __KERNEL__ @@ -20,10 +24,12 @@ /* * These are used to make use of C type-checking.. */ +#ifndef __ASSEMBLY__ typedef struct { unsigned long pte; } pte_t; typedef struct { unsigned long pmd; } pmd_t; typedef struct { unsigned long pgd; } pgd_t; typedef struct { unsigned long pgprot; } pgprot_t; +#endif #define pte_val(x) ((x).pte) #define pmd_val(x) ((x).pmd) @@ -51,7 +57,7 @@ typedef struct { unsigned long pgprot; } #define virt_to_page(kaddr) (mem_map + (((unsigned long)(kaddr) - PAGE_OFFSET) >> PAGE_SHIFT)) #define VALID_PAGE(page) (((page) - mem_map) < max_mapnr) -#define virt_addr_valid(kaddr) pfn_valid((kaddr) >> PAGE_SHIFT) +#define virt_addr_valid(kaddr) pfn_valid((unsigned)(kaddr) >> PAGE_SHIFT) /* convert a page (based on mem_map and forward) to a physical address * do this by figuring out the virtual address and then use __pa @@ -72,8 +78,6 @@ typedef struct { unsigned long pgprot; } BUG(); \ } while (0) -#endif /* __ASSEMBLY__ */ - /* Pure 2^n version of get_order */ static inline int get_order(unsigned long size) { @@ -87,6 +91,7 @@ static inline int get_order(unsigned lon } while (size); return order; } +#endif /* __ASSEMBLY__ */ #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) diff -puN include/asm-cris/pci.h~cris-architecture-update include/asm-cris/pci.h --- 25/include/asm-cris/pci.h~cris-architecture-update 2004-06-01 01:09:29.106974720 -0700 +++ 25-akpm/include/asm-cris/pci.h 2004-06-01 01:09:29.184962864 -0700 @@ -1,9 +1,13 @@ #ifndef __ASM_CRIS_PCI_H #define __ASM_CRIS_PCI_H +#include +#include + /* ETRAX chips don't have a PCI bus. This file is just here because some stupid .c code * includes it even if CONFIG_PCI is not set. */ +#define PCI_DMA_BUS_IS_PHYS (1) #endif /* __ASM_CRIS_PCI_H */ diff -puN include/asm-cris/pgtable.h~cris-architecture-update include/asm-cris/pgtable.h --- 25/include/asm-cris/pgtable.h~cris-architecture-update 2004-06-01 01:09:29.107974568 -0700 +++ 25-akpm/include/asm-cris/pgtable.h 2004-06-01 01:09:29.185962712 -0700 @@ -5,9 +5,11 @@ #ifndef _CRIS_PGTABLE_H #define _CRIS_PGTABLE_H +#ifndef __ASSEMBLY__ #include #include #include +#endif #include /* @@ -21,8 +23,9 @@ * This file contains the functions and defines necessary to modify and use * the CRIS page table tree. */ - +#ifndef __ASSEMBLY__ extern void paging_init(void); +#endif /* Certain architectures need to do special things when pte's * within a page table are directly modified. Thus, the following @@ -72,8 +75,10 @@ extern void paging_init(void); #define FIRST_USER_PGD_NR 0 /* zero page used for uninitialized stuff */ +#ifndef __ASSEMBLY__ extern unsigned long empty_zero_page; #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) +#endif /* number of bits that fit into a memory pointer */ #define BITS_PER_PTR (8*sizeof(unsigned long)) @@ -104,6 +109,8 @@ extern unsigned long empty_zero_page; #define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT) #define pmd_clear(xp) do { pmd_val(*(xp)) = 0; } while (0) +#ifndef __ASSEMBLY__ + /* * The "pgd_xxx()" functions here are trivial for a folded two-level * setup: the pgd is never bad, and a pmd always exists (as it's folded @@ -337,4 +344,5 @@ extern inline void update_mmu_cache(stru #define pte_to_pgoff(x) (pte_val(x) >> 6) #define pgoff_to_pte(x) __pte(((x) << 6) | _PAGE_FILE) +#endif /* __ASSEMBLY__ */ #endif /* _CRIS_PGTABLE_H */ diff -puN include/asm-cris/ptrace.h~cris-architecture-update include/asm-cris/ptrace.h --- 25/include/asm-cris/ptrace.h~cris-architecture-update 2004-06-01 01:09:29.108974416 -0700 +++ 25-akpm/include/asm-cris/ptrace.h 2004-06-01 01:09:29.185962712 -0700 @@ -3,8 +3,10 @@ #include +#ifdef __KERNEL__ /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ #define PTRACE_GETREGS 12 #define PTRACE_SETREGS 13 +#endif #endif /* _CRIS_PTRACE_H */ diff -puN include/asm-cris/rtc.h~cris-architecture-update include/asm-cris/rtc.h --- 25/include/asm-cris/rtc.h~cris-architecture-update 2004-06-01 01:09:29.110974112 -0700 +++ 25-akpm/include/asm-cris/rtc.h 2004-06-01 01:09:29.186962560 -0700 @@ -100,6 +100,8 @@ struct rtc_time { #define RTC_RD_TIME _IOR(RTC_MAGIC, 0x09, struct rtc_time) /* Read RTC time. */ #define RTC_SET_TIME _IOW(RTC_MAGIC, 0x0a, struct rtc_time) /* Set RTC time. */ #define RTC_SET_CHARGE _IOW(RTC_MAGIC, 0x0b, int) -#define RTC_MAX_IOCTL 0x0b +#define RTC_VLOW_RD _IOR(RTC_MAGIC, 0x11, int) /* Voltage Low detector */ +#define RTC_VLOW_SET _IO(RTC_MAGIC, 0x12) /* Clear voltage low information */ +#define RTC_MAX_IOCTL 0x12 #endif /* __RTC_H__ */ diff -puN /dev/null include/asm-cris/sections.h --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25-akpm/include/asm-cris/sections.h 2004-06-01 01:09:29.186962560 -0700 @@ -0,0 +1,7 @@ +#ifndef _CRIS_SECTIONS_H +#define _CRIS_SECTIONS_H + +/* nothing to see, move along */ +#include + +#endif diff -puN include/asm-cris/semaphore.h~cris-architecture-update include/asm-cris/semaphore.h --- 25/include/asm-cris/semaphore.h~cris-architecture-update 2004-06-01 01:09:29.111973960 -0700 +++ 25-akpm/include/asm-cris/semaphore.h 2004-06-01 01:09:29.186962560 -0700 @@ -21,7 +21,7 @@ int printk(const char *fmt, ...); struct semaphore { - int count; /* not atomic_t since we do the atomicity here already */ + atomic_t count; atomic_t waking; wait_queue_head_t wait; #if WAITQUEUE_DEBUG @@ -36,7 +36,7 @@ struct semaphore { #endif #define __SEMAPHORE_INITIALIZER(name,count) \ - { count, ATOMIC_INIT(0), \ + { ATOMIC_INIT(count), ATOMIC_INIT(0), \ __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ __SEM_DEBUG_INIT(name) } @@ -84,7 +84,7 @@ extern inline void down(struct semaphore /* atomically decrement the semaphores count, and if its negative, we wait */ local_save_flags(flags); local_irq_disable(); - failed = --(sem->count) < 0; + failed = --(sem->count.counter) < 0; local_irq_restore(flags); if(failed) { __down(sem); @@ -110,7 +110,7 @@ extern inline int down_interruptible(str /* atomically decrement the semaphores count, and if its negative, we wait */ local_save_flags(flags); local_irq_disable(); - failed = --(sem->count) < 0; + failed = --(sem->count.counter) < 0; local_irq_restore(flags); if(failed) failed = __down_interruptible(sem); @@ -128,7 +128,7 @@ extern inline int down_trylock(struct se local_save_flags(flags); local_irq_disable(); - failed = --(sem->count) < 0; + failed = --(sem->count.counter) < 0; local_irq_restore(flags); if(failed) failed = __down_trylock(sem); @@ -153,7 +153,7 @@ extern inline void up(struct semaphore * /* atomically increment the semaphores count, and if it was negative, we wake people */ local_save_flags(flags); local_irq_disable(); - wakeup = ++(sem->count) <= 0; + wakeup = ++(sem->count.counter) <= 0; local_irq_restore(flags); if(wakeup) { __up(sem); diff -puN include/asm-cris/semaphore-helper.h~cris-architecture-update include/asm-cris/semaphore-helper.h --- 25/include/asm-cris/semaphore-helper.h~cris-architecture-update 2004-06-01 01:09:29.113973656 -0700 +++ 25-akpm/include/asm-cris/semaphore-helper.h 2004-06-01 01:09:29.187962408 -0700 @@ -52,7 +52,7 @@ extern inline int waking_non_zero_interr dec(&sem->waking); ret = 1; } else if (signal_pending(tsk)) { - count_inc(&sem->count); + inc(&sem->count); ret = -EINTR; } local_irq_restore(flags); @@ -67,7 +67,7 @@ extern inline int waking_non_zero_tryloc local_save_flags(flags); local_irq_disable(); if (read(&sem->waking) <= 0) - count_inc(&sem->count); + inc(&sem->count); else { dec(&sem->waking); ret = 0; diff -puN include/asm-cris/termbits.h~cris-architecture-update include/asm-cris/termbits.h --- 25/include/asm-cris/termbits.h~cris-architecture-update 2004-06-01 01:09:29.114973504 -0700 +++ 25-akpm/include/asm-cris/termbits.h 2004-06-01 01:09:29.187962408 -0700 @@ -154,7 +154,7 @@ struct termios { #define B6250000 0010007 /* etrax 200 supports this as well */ #define B12500000 0010010 -#define CIBAUD 002003600000 /* input baud rate */ +#define CIBAUD 002003600000 /* input baud rate (used in v32) */ /* The values for CIBAUD bits are the same as the values for CBAUD and CBAUDEX * shifted left IBSHIFT bits. */ diff -puN include/asm-cris/types.h~cris-architecture-update include/asm-cris/types.h --- 25/include/asm-cris/types.h~cris-architecture-update 2004-06-01 01:09:29.115973352 -0700 +++ 25-akpm/include/asm-cris/types.h 2004-06-01 01:09:29.187962408 -0700 @@ -50,6 +50,7 @@ typedef unsigned long long u64; /* Dma addresses are 32-bits wide, just like our other addresses. */ typedef u32 dma_addr_t; +typedef u32 dma64_addr_t; typedef unsigned int kmem_bufctl_t; diff -puN include/asm-cris/unistd.h~cris-architecture-update include/asm-cris/unistd.h --- 25/include/asm-cris/unistd.h~cris-architecture-update 2004-06-01 01:09:29.117973048 -0700 +++ 25-akpm/include/asm-cris/unistd.h 2004-06-01 01:09:29.188962256 -0700 @@ -275,8 +275,21 @@ #define __NR_clock_nanosleep (__NR_timer_create+8) #define __NR_statfs64 268 #define __NR_fstatfs64 269 +#define __NR_tgkill 270 +#define __NR_utimes 271 +#define __NR_fadvise64_64 272 +#define __NR_vserver 273 +#define __NR_mbind 274 +#define __NR_get_mempolicy 275 +#define __NR_set_mempolicy 276 +#define __NR_mq_open 277 +#define __NR_mq_unlink (__NR_mq_open+1) +#define __NR_mq_timedsend (__NR_mq_open+2) +#define __NR_mq_timedreceive (__NR_mq_open+3) +#define __NR_mq_notify (__NR_mq_open+4) +#define __NR_mq_getsetattr (__NR_mq_open+5) -#define NR_syscalls 270 +#define NR_syscalls 283 #ifdef __KERNEL__ @@ -307,6 +320,7 @@ #include #include +#include /* * we need this inline - forking from kernel space will result _