diff options
43 files changed, 4156 insertions, 500 deletions
| @@ -2354,6 +2354,46 @@ format!) to the "bootm" command:  	bash# +More About U-Boot Image Types: +------------------------------ + +U-Boot supports the following image types: + +   "Standalone Programs" are directly runnable in the environment +  	provided by U-Boot; it is expected that (if they behave +  	well) you can continue to work in U-Boot after return from +  	the Standalone Program. +   "OS Kernel Images" are usually images of some Embedded OS which +  	will take over control completely. Usually these programs +  	will install their own set of exception handlers, device +  	drivers, set up the MMU, etc. - this means, that you cannot +  	expect to re-enter U-Boot except by resetting the CPU. +   "RAMDisk Images" are more or less just data blocks, and their +  	parameters (address, size) are passed to an OS kernel that is +  	being started. +   "Multi-File Images" contain several images, typically an OS +  	(Linux) kernel image and one or more data images like +  	RAMDisks. This construct is useful for instance when you want +  	to boot over the network using BOOTP etc., where the boot +  	server provides just a single image file, but you want to get +  	for instance an OS kernel and a RAMDisk image. +   +  	"Multi-File Images" start with a list of image sizes, each +  	image size (in bytes) specified by an "uint32_t" in network +  	byte order. This list is terminated by an "(uint32_t)0". +  	Immediately after the terminating 0 follow the images, one by +  	one, all aligned on "uint32_t" boundaries (size rounded up to +  	a multiple of 4 bytes). +   +   "Firmware Images" are binary images containing firmware (like +  	U-Boot or FPGA images) which usually will be programmed to +  	flash memory. +   +   "Script files" are command sequences that will be executed by +  	U-Boot's command interpreter; this feature is especially +  	useful when you configure U-Boot to use a real shell (hush) +  	as command interpreter. +  Standalone HOWTO:  ================= diff --git a/board/sc520_cdp/sc520_cdp.c b/board/sc520_cdp/sc520_cdp.c index ba6255f4e..2809ff72a 100644 --- a/board/sc520_cdp/sc520_cdp.c +++ b/board/sc520_cdp/sc520_cdp.c @@ -31,35 +31,35 @@  static void irq_init(void)  { - +	  	/* disable global interrupt mode */ -	write_mmcr_byte(SC520_PICICR, 0x40); - +	write_mmcr_byte(SC520_PICICR, 0x40);  +	  	/* set irq0-7 to edge */  	write_mmcr_byte(SC520_MPICMODE, 0x00); - +	  	/* set irq9-12 to level, all the other (8, 13-15) are edge */  	write_mmcr_byte(SC520_SL1PICMODE, 0x1e); - +	  	/* set irq16-24 (unused slave pic2) to level */  	write_mmcr_byte(SC520_SL2PICMODE, 0xff); - -	/* active low polarity on PIC interrupt pins, +	 +	/* active low polarity on PIC interrupt pins,   	   active high polarity on all other irq pins */  	write_mmcr_word(SC520_INTPINPOL, 0);  	/* set irq number mapping */ -	write_mmcr_byte(SC520_GPTMR0MAP,0);            /* disable GP timer 0 INT */ +	write_mmcr_byte(SC520_GPTMR0MAP,0);            /* disable GP timer 0 INT */         	write_mmcr_byte(SC520_GPTMR1MAP,0);            /* disable GP timer 1 INT */  	write_mmcr_byte(SC520_GPTMR2MAP,0);            /* disable GP timer 2 INT */ -	write_mmcr_byte(SC520_PIT0MAP,0x1);            /* Set PIT timer 0 INT to IRQ0 */ +	write_mmcr_byte(SC520_PIT0MAP,0x1);            /* Set PIT timer 0 INT to IRQ0 */   	write_mmcr_byte(SC520_PIT1MAP,0);              /* diable PIT timer 1 INT */  	write_mmcr_byte(SC520_PIT2MAP,0);              /* diable PIT timer 2 INT */  	write_mmcr_byte(SC520_PCIINTAMAP,0x4);         /* Set PCI INT A to IRQ9 */  	write_mmcr_byte(SC520_PCIINTBMAP,0x5);         /* Set PCI INT B to IRQ10 */  	write_mmcr_byte(SC520_PCIINTCMAP,0x6);         /* Set PCI INT C to IRQ11 */  	write_mmcr_byte(SC520_PCIINTDMAP,0x7);         /* Set PCI INT D to IRQ12 */ -	write_mmcr_byte(SC520_DMABCINTMAP,0);          /* disable DMA INT */ +	write_mmcr_byte(SC520_DMABCINTMAP,0);          /* disable DMA INT */   	write_mmcr_byte(SC520_SSIMAP,0);               /* disable Synchronius serial INT */  	write_mmcr_byte(SC520_WDTMAP,0);               /* disable Watchdor INT */  	write_mmcr_byte(SC520_RTCMAP,0x3);             /* Set RTC int to 8 */ @@ -69,28 +69,28 @@ static void irq_init(void)  	write_mmcr_byte(SC520_GP0IMAP,6);              /* Set GPIRQ0 (ISA IRQ2) to IRQ9 */  	write_mmcr_byte(SC520_GP1IMAP,2);              /* Set GPIRQ1 (SIO IRQ1) to IRQ1 */  	write_mmcr_byte(SC520_GP2IMAP,7);              /* Set GPIRQ2 (ISA IRQ12) to IRQ12 */ - +	  	if (CFG_USE_SIO_UART) {  		write_mmcr_byte(SC520_UART1MAP,0);     /* disable internal UART1 INT */  		write_mmcr_byte(SC520_UART2MAP,0);     /* disable internal UART2 INT */ -		write_mmcr_byte(SC520_GP3IMAP,11);     /* Set GPIRQ3 (ISA IRQ3) to IRQ3 */ +		write_mmcr_byte(SC520_GP3IMAP,11);     /* Set GPIRQ3 (ISA IRQ3) to IRQ3 */   		write_mmcr_byte(SC520_GP4IMAP,12);     /* Set GPIRQ4 (ISA IRQ4) to IRQ4 */  	} else {  		write_mmcr_byte(SC520_UART1MAP,12);    /* Set internal UART2 INT to IRQ4 */  		write_mmcr_byte(SC520_UART2MAP,11);    /* Set internal UART2 INT to IRQ3 */ -		write_mmcr_byte(SC520_GP3IMAP,0);      /* disable GPIRQ3 (ISA IRQ3) */ +		write_mmcr_byte(SC520_GP3IMAP,0);      /* disable GPIRQ3 (ISA IRQ3) */   		write_mmcr_byte(SC520_GP4IMAP,0);      /* disable GPIRQ4 (ISA IRQ4) */  	} - +	  	write_mmcr_byte(SC520_GP5IMAP,13);             /* Set GPIRQ5 (ISA IRQ5) to IRQ5 */  	write_mmcr_byte(SC520_GP6IMAP,21);             /* Set GPIRQ6 (ISA IRQ6) to IRQ6 */  	write_mmcr_byte(SC520_GP7IMAP,22);             /* Set GPIRQ7 (ISA IRQ7) to IRQ7 */  	write_mmcr_byte(SC520_GP8IMAP,3);              /* Set GPIRQ8 (SIO IRQ8) to IRQ8 */  	write_mmcr_byte(SC520_GP9IMAP,4);              /* Set GPIRQ9 (ISA IRQ9) to IRQ9 */ -	write_mmcr_byte(SC520_GP10IMAP,9);             /* Set GPIRQ10 (ISA IRQ10) to IRQ10 */ +	write_mmcr_byte(SC520_GP10IMAP,9);             /* Set GPIRQ10 (ISA IRQ10) to IRQ10 */            	write_mmcr_word(SC520_PCIHOSTMAP,0x11f);       /* Map PCI hostbridge INT to NMI */  	write_mmcr_word(SC520_ECCMAP,0x100);           /* Map SDRAM ECC failure INT to NMI */ - +   }  /* PCI stuff */ @@ -98,11 +98,11 @@ static void pci_sc520_cdp_fixup_irq(struct pci_controller *hose, pci_dev_t dev)  {  	char pin;  	int irq; - - +	 +	  	pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &pin);  	irq = pin-1; - +	  	switch (PCI_DEV(dev)) {  	case 20:  		break; @@ -115,20 +115,20 @@ static void pci_sc520_cdp_fixup_irq(struct pci_controller *hose, pci_dev_t dev)  	case 17:  		irq+=3;  		break; -	default: +	default:   		return;  	} - +	  	irq&=3; /* wrap around */  	irq+=9; /* lowest IRQ is 9 */ - +	  	pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, irq); -#if 0 -	printf("fixup_irq: device %d pin %c irq %d\n", +#if 0	 +	printf("fixup_irq: device %d pin %c irq %d\n",   	       PCI_DEV(dev), 'A' + pin -1, irq);  #endif  } - +   static struct pci_controller sc520_cdp_hose = {  	fixup_irq: pci_sc520_cdp_fixup_irq,  }; @@ -147,7 +147,7 @@ static void silence_uart(int port)  void setup_ali_sio(int uart_primary)  {  	ali512x_init(); - +	  	ali512x_set_fdc(ALI_ENABLED, 0x3f2, 6, 0);  	ali512x_set_pp(ALI_ENABLED, 0x278, 7, 3);  	ali512x_set_uart(ALI_ENABLED, ALI_UART1, uart_primary?0x3f8:0x3e8, 4); @@ -155,21 +155,21 @@ void setup_ali_sio(int uart_primary)  	ali512x_set_rtc(ALI_DISABLED, 0, 0);  	ali512x_set_kbc(ALI_ENABLED, 1, 12);  	ali512x_set_cio(ALI_ENABLED); - +	  	/* IrDa pins */  	ali512x_cio_function(12, 1, 0, 0);  	ali512x_cio_function(13, 1, 0, 0); - +	  	/* SSI chip select pins */  	ali512x_cio_function(14, 0, 0, 0);  /* SSI_CS */ -	ali512x_cio_function(15, 0, 0, 0);  /* SSI_MV */ +	ali512x_cio_function(15, 0, 0, 0);  /* SSI_MV */					       	ali512x_cio_function(16, 0, 1, 0);  /* SSI_SPI# (inverted) */  	/* Board REV pins */  	ali512x_cio_function(20, 0, 0, 1);  	ali512x_cio_function(21, 0, 0, 1);  	ali512x_cio_function(22, 0, 0, 1); -	ali512x_cio_function(23, 0, 0, 1); +	ali512x_cio_function(23, 0, 0, 1);        } @@ -178,13 +178,13 @@ static void bus_init(void)  {  	/* set up the GP IO pins */ -	write_mmcr_word(SC520_PIOPFS31_16, 0xf7ff); 	/* set the GPIO pin function 31-16 reg */ +	write_mmcr_word(SC520_PIOPFS31_16, 0xf7ff); 	/* set the GPIO pin function 31-16 reg */		     	write_mmcr_word(SC520_PIOPFS15_0, 0xffff);  	/* set the GPIO pin function 15-0 reg */ -	write_mmcr_byte(SC520_CSPFS, 0xf8);  		/* set the CS pin function  reg */ +	write_mmcr_byte(SC520_CSPFS, 0xf8);  		/* set the CS pin function  reg */	  	write_mmcr_byte(SC520_CLKSEL, 0x70); - -	write_mmcr_byte(SC520_GPCSRT, 1);   /* set the GP CS offset */ +	 +	write_mmcr_byte(SC520_GPCSRT, 1);   /* set the GP CS offset */    	  	write_mmcr_byte(SC520_GPCSPW, 3);   /* set the GP CS pulse width */  	write_mmcr_byte(SC520_GPCSOFF, 1);  /* set the GP CS offset */  	write_mmcr_byte(SC520_GPRDW, 3);    /* set the RD pulse width */ @@ -192,40 +192,40 @@ static void bus_init(void)          write_mmcr_byte(SC520_GPWRW, 3);    /* set the GP WR pulse width */  	write_mmcr_byte(SC520_GPWROFF, 1);  /* set the GP WR offset */ -	write_mmcr_word(SC520_BOOTCSCTL, 0x1823);		/* set up timing of BOOTCS */ +	write_mmcr_word(SC520_BOOTCSCTL, 0x1823);		/* set up timing of BOOTCS */   	write_mmcr_word(SC520_ROMCS1CTL, 0x1823);		/* set up timing of ROMCS1 */ -	write_mmcr_word(SC520_ROMCS2CTL, 0x1823);		/* set up timing of ROMCS2 */ - +	write_mmcr_word(SC520_ROMCS2CTL, 0x1823);		/* set up timing of ROMCS2 */  +	  	/* adjust the memory map:  	 * by default the first 256MB (0x00000000 - 0x0fffffff) is mapped to SDRAM  	 * and 256MB to 1G-128k  (0x1000000 - 0x37ffffff) is mapped to PCI mmio -	 * we need to map 1G-128k - 1G (0x38000000 - 0x3fffffff) to CS1 */ - - +	 * we need to map 1G-128k - 1G (0x38000000 - 0x3fffffff) to CS1 */  +	 +		  	/* SRAM = GPCS3 128k @ d0000-effff*/ -	write_mmcr_long(SC520_PAR2,  0x4e00400d); - +	write_mmcr_long(SC520_PAR2,  0x4e00400d);		 +	  	/* IDE0 = GPCS6 1f0-1f7 */ -	write_mmcr_long(SC520_PAR3,  0x380801f0); +	write_mmcr_long(SC520_PAR3,  0x380801f0);		  	/* IDE1 = GPCS7 3f6 */ -	write_mmcr_long(SC520_PAR4,  0x3c0003f6); +	write_mmcr_long(SC520_PAR4,  0x3c0003f6);		  	/* bootcs */ -	write_mmcr_long(SC520_PAR12, 0x8bffe800); +	write_mmcr_long(SC520_PAR12, 0x8bffe800);		  	/* romcs2 */ -	write_mmcr_long(SC520_PAR13, 0xcbfff000); +	write_mmcr_long(SC520_PAR13, 0xcbfff000);		  	/* romcs1 */ -	write_mmcr_long(SC520_PAR14, 0xabfff800); +	write_mmcr_long(SC520_PAR14, 0xabfff800);		  	/* 680 LEDS */ -	write_mmcr_long(SC520_PAR15, 0x30000640); - -	asm ("wbinvd\n"); /* Flush cache, req. after setting the unchached attribute ona PAR */ +	write_mmcr_long(SC520_PAR15, 0x30000640);		 +	 +	asm ("wbinvd\n"); /* Flush cache, req. after setting the unchached attribute ona PAR */	  	if (CFG_USE_SIO_UART) { -		write_mmcr_byte(SC520_ADDDECCTL, read_mmcr_byte(SC520_ADDDECCTL) | UART2_DIS|UART1_DIS); +		write_mmcr_byte(SC520_ADDDECCTL, read_mmcr_byte(SC520_ADDDECCTL) | UART2_DIS|UART1_DIS);	  		setup_ali_sio(1);  	} else { -		write_mmcr_byte(SC520_ADDDECCTL, read_mmcr_byte(SC520_ADDDECCTL) & ~(UART2_DIS|UART1_DIS)); +		write_mmcr_byte(SC520_ADDDECCTL, read_mmcr_byte(SC520_ADDDECCTL) & ~(UART2_DIS|UART1_DIS));	  		setup_ali_sio(0);  		silence_uart(0x3e8);  		silence_uart(0x2e8); @@ -242,21 +242,21 @@ static void bus_init(void)  int board_init(void)  {  	DECLARE_GLOBAL_DATA_PTR; - -	init_sc520(); +	 +	init_sc520();	  	bus_init();  	irq_init(); - +		  	/* max drive current on SDRAM */  	write_mmcr_word(SC520_DSCTL, 0x0100); - +		  	/* enter debug mode after next reset (only if jumper is also set) */  	write_mmcr_byte(SC520_RESCFG, 0x08); - +	  	/* configure the software timer to 33.333MHz */  	write_mmcr_byte(SC520_SWTMRCFG, 0);  	gd->bus_clk = 33333000; - +	  	return 0;  } @@ -277,14 +277,14 @@ int last_stage_init(void)  {  	int minor;  	int major; - +	  	major = minor = 0;  	major |= ali512x_cio_in(23)?2:0;  	major |= ali512x_cio_in(22)?1:0;  	minor |= ali512x_cio_in(21)?2:0;  	minor |= ali512x_cio_in(20)?1:0; - +	  	printf("AMD SC520 CDP revision %d.%d\n", major, minor); - +	  	return 0;  } diff --git a/board/smdk2400/flash.c b/board/smdk2400/flash.c index c4d6bae8f..6882b8845 100644 --- a/board/smdk2400/flash.c +++ b/board/smdk2400/flash.c @@ -76,7 +76,7 @@ ulong flash_init (void)  		flash_info[i].sector_count = CFG_MAX_FLASH_SECT;  		memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);  		if (i == 0) -			flashbase = PHYS_FLASH_1; +			flashbase = CFG_FLASH_BASE;  		else  			panic ("configured too many flash banks!\n");  		for (j = 0; j < flash_info[i].sector_count; j++) { diff --git a/board/trab/flash.c b/board/trab/flash.c index 2443777ae..a4f164b46 100644 --- a/board/trab/flash.c +++ b/board/trab/flash.c @@ -26,12 +26,7 @@  #include <common.h>  #include <environment.h> -ulong myflush (void); - - -#define FLASH_BANK_SIZE	0x800000	/* 8 MB */ -/* this varies depending on the sector */ -#define MAIN_SECT_SIZE  0x20000		/* 2 x 64 kB */ +static ulong flash_get_size (vu_long *addr, flash_info_t *info);  flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; @@ -43,6 +38,7 @@ flash_info_t flash_info[CFG_MAX_FLASH_BANKS];  #define CMD_ERASE_CONFIRM	0x00300030  #define CMD_PROGRAM		0x00A000A0  #define CMD_UNLOCK_BYPASS	0x00200020 +#define CMD_READ_MANF_ID	0x00900090  #define MEM_FLASH_ADDR1		(*(volatile u32 *)(CFG_FLASH_BASE + (0x00000555 << 2)))  #define MEM_FLASH_ADDR2		(*(volatile u32 *)(CFG_FLASH_BASE + (0x000002AA << 2))) @@ -64,27 +60,38 @@ ulong flash_init (void)  	int i, j;  	ulong size = 0; -	for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) { +	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {  		ulong flashbase = 0; +		flash_info_t *info = &flash_info[i]; + +		/* Init: no FLASHes known */ +		info->flash_id = FLASH_UNKNOWN; + +		size += flash_get_size (CFG_FLASH_BASE, info); -		flash_info[i].flash_id = -			(AMD_MANUFACT  & FLASH_VENDMASK) | -			(AMD_ID_LV320B & FLASH_TYPEMASK); -		flash_info[i].size = FLASH_BANK_SIZE; -		flash_info[i].sector_count = CFG_MAX_FLASH_SECT; -		memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);  		if (i == 0) -			flashbase = PHYS_FLASH_1; +			flashbase = CFG_FLASH_BASE;  		else  			panic ("configured too many flash banks!\n"); -		for (j = 0; j < flash_info[i].sector_count; j++) { +		for (j = 0; j < info->sector_count; j++) { -			flash_info[i].start[j] = flashbase; +			info->protect[j] = 0; +			info->start[j] = flashbase; -			/* the first 8 sectors are 8 kB */ -			flashbase += (j < 8) ? 0x4000 : MAIN_SECT_SIZE; +			switch (info->flash_id & FLASH_TYPEMASK) { +			case (FLASH_AM320B & FLASH_TYPEMASK): +				/* Boot sector type: 8 x 8 + N x 128 kB */ +				flashbase += (j < 8) ? 0x4000 : 0x20000; +				break; +			case (FLASH_AM640U & FLASH_TYPEMASK): +				/* Uniform sector type: 128 kB */ +				flashbase += 0x20000; +				break; +			default: +				printf ("## Bad flash chip type 0x%04lX\n", +					info->flash_id & FLASH_TYPEMASK); +			}  		} -		size += flash_info[i].size;  	}  	/* @@ -116,7 +123,7 @@ void flash_print_info (flash_info_t * info)  	int i;  	switch (info->flash_id & FLASH_VENDMASK) { -	case (AMD_MANUFACT & FLASH_VENDMASK): +	case (FLASH_MAN_AMD & FLASH_VENDMASK):  		printf ("AMD: ");  		break;  	default: @@ -125,9 +132,12 @@ void flash_print_info (flash_info_t * info)  	}  	switch (info->flash_id & FLASH_TYPEMASK) { -	case (AMD_ID_LV320B & FLASH_TYPEMASK): +	case (FLASH_AM320B & FLASH_TYPEMASK):  		printf ("2x Am29LV320DB (32Mbit)\n");  		break; +	case (FLASH_AM640U & FLASH_TYPEMASK): +		printf ("2x Am29LV640D (64Mbit)\n"); +		break;  	default:  		printf ("Unknown Chip Type\n");  		goto Done; @@ -177,7 +187,7 @@ int flash_erase (flash_info_t * info, int s_first, int s_last)  	}  	if ((info->flash_id & FLASH_VENDMASK) != -		(AMD_MANUFACT & FLASH_VENDMASK)) { +		(FLASH_MAN_AMD & FLASH_VENDMASK)) {  		return ERR_UNKNOWN_FLASH_VENDOR;  	} @@ -265,13 +275,6 @@ int flash_erase (flash_info_t * info, int s_first, int s_last)  				rc = ERR_TIMOUT;  				goto outahere;  			} - -#if 0 -			printf ("ok.\n"); -		} else {		/* it was protected */ - -			printf ("protected!\n"); -#endif  		}  	} @@ -453,3 +456,71 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)  	return write_word (info, wp, data);  } + +/*----------------------------------------------------------------------- + */ + +static ulong flash_get_size (vu_long *addr, flash_info_t *info) +{ +	ulong value; + +	/* Write auto select command sequence and read Manufacturer ID */ +	addr[0x0555] = CMD_UNLOCK1; +	addr[0x02AA] = CMD_UNLOCK2; +	addr[0x0555] = CMD_READ_MANF_ID; + +	value = addr[0]; + +	debug ("Manuf. ID @ 0x%08lx: 0x%08lx\n", (ulong)addr, value); + +	switch (value) { +	case AMD_MANUFACT: +		info->flash_id = FLASH_MAN_AMD; +		break; + +	default: +		info->flash_id = FLASH_UNKNOWN; +		info->sector_count = 0; +		info->size = 0; +		addr[0] = 0x00FF00FF;		/* restore read mode */ +		debug ("## flash_init: unknown manufacturer\n"); +		return (0);			/* no or unknown flash	*/ +	} + +	value = addr[1];			/* device ID		*/ + +	debug ("Device ID @ 0x%08lx: 0x%08lx\n", (ulong)(&addr[1]), value); + +	switch (value) { +	case AMD_ID_LV320B: +		info->flash_id += FLASH_AM320B; +		info->sector_count = 71; +		info->size = 0x00800000; + +		addr[0] = 0x00FF00FF;		/* restore read mode */ +		break;				/* =>  8 MB		*/ + +	case AMD_ID_LV640U: +		info->flash_id += FLASH_AM640U; +		info->sector_count = 128; +		info->size = 0x01000000; + +		addr[0] = 0x00F000F0;		/* restore read mode */ +		break;				/* => 16 MB		*/ + +	default: +		debug ("## flash_init: unknown flash chip\n"); +		info->flash_id = FLASH_UNKNOWN; +		addr[0] = 0x00FF00FF;		/* restore read mode */ +		return (0);			/* => no or unknown flash */ + +	} + +	if (info->sector_count > CFG_MAX_FLASH_SECT) { +		printf ("** ERROR: sector count %d > max (%d) **\n", +			info->sector_count, CFG_MAX_FLASH_SECT); +		info->sector_count = CFG_MAX_FLASH_SECT; +	} + +	return (info->size); +} diff --git a/board/trab/trab.c b/board/trab/trab.c index 32f27efae..111c86141 100644 --- a/board/trab/trab.c +++ b/board/trab/trab.c @@ -60,11 +60,8 @@ static void udelay_no_timer (int usec)  int board_init ()  { -#if defined(CONFIG_MODEM_SUPPORT) && defined(CONFIG_VFD) -	ulong size; -	unsigned long addr; -	extern void mem_malloc_init (ulong); -	extern int drv_vfd_init(void); +#if defined(CONFIG_VFD) +	extern int vfd_init_clocks(void);  #endif  	DECLARE_GLOBAL_DATA_PTR; @@ -107,26 +104,11 @@ int board_init ()  	/* adress of boot parameters */  	gd->bd->bi_boot_params = 0x0c000100; -#ifdef CONFIG_MODEM_SUPPORT  #ifdef CONFIG_VFD -#ifndef PAGE_SIZE -#define PAGE_SIZE 4096 -#endif -	/* -	 * reserve memory for VFD display (always full pages) -	 */ -	/* armboot_real_end is defined in the board-specific linker script */ -	addr = (_armboot_real_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); -	size = vfd_setmem (addr); -	gd->fb_base = addr; -	/* round to the next page boundary */ -	addr += size; -	addr = (addr + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); -	mem_malloc_init (addr); -	/* must do this after the framebuffer is allocated */ -	drv_vfd_init(); +	vfd_init_clocks();  #endif /* CONFIG_VFD */ +#ifdef CONFIG_MODEM_SUPPORT  	udelay_no_timer (KBD_MDELAY);  	if (key_pressed()) { diff --git a/board/trab/vfd.c b/board/trab/vfd.c index 234a9d4c0..fa1194ca7 100644 --- a/board/trab/vfd.c +++ b/board/trab/vfd.c @@ -55,12 +55,16 @@  #define BLAU	0x0C  #define VIOLETT	0X0D -ulong vfdbase; -ulong frame_buf_size; +ulong	vfdbase; +ulong	frame_buf_size;  #define frame_buf_offs 4 +/* Supported VFD Types */ +#define	VFD_TYPE_T119C		1	/* Noritake T119C VFD */ +#define	VFD_TYPE_MN11236	2 +  /* taken from armboot/common/vfd.c */ -ulong         adr_vfd_table[112][18][2][4][2]; +unsigned long adr_vfd_table[112][18][2][4][2];  unsigned char bit_vfd_table[112][18][2][4][2];  /* @@ -68,26 +72,42 @@ unsigned char bit_vfd_table[112][18][2][4][2];   */  void init_grid_ctrl(void)  { +	DECLARE_GLOBAL_DATA_PTR;  	ulong adr, grid_cycle;  	unsigned int bit, display;  	unsigned char temp, bit_nr; +	ulong val; -	for (adr=vfdbase; adr<=(vfdbase+7168); adr+=4) /*clear frame buffer */ -		(*(volatile ulong*)(adr))=0; +	/* +	 * clear frame buffer (logical clear => set to "black") +	 */ +	if (gd->vfd_inv_data == 0) +		val = 0; +	else +		val = ~0; -	for(display=0;display<=3;display++) -	{ -		for(grid_cycle=0;grid_cycle<=55;grid_cycle++) -		{ -			bit = grid_cycle*256*4+(grid_cycle+200)*4+frame_buf_offs+display; +	for (adr = vfdbase; adr <= (vfdbase+7168); adr += 4) { +		(*(volatile ulong*)(adr)) = val; +	} + +	switch (gd->vfd_type) { +	case VFD_TYPE_T119C: +	    for (display=0; display<4; display++) { +		for(grid_cycle=0; grid_cycle<56; grid_cycle++) { +			bit = grid_cycle * 256  * 4 + +			     (grid_cycle + 200) * 4 + +			     frame_buf_offs + display;   			/* wrap arround if offset (see manual S3C2400) */  			if (bit>=frame_buf_size*8) -				bit = bit-(frame_buf_size*8); -			adr = vfdbase+(bit/32)*4+(3-(bit%32)/8); -			bit_nr = bit%8; -			bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4; +				bit = bit - (frame_buf_size * 8); +			adr = vfdbase + (bit/32) * 4 + (3 - (bit%32) / 8); +			bit_nr = bit % 8; +			bit_nr = (bit_nr > 3) ? bit_nr-4 : bit_nr+4;  			temp=(*(volatile unsigned char*)(adr)); -			temp|=(1<<bit_nr); +			if (gd->vfd_inv_data) +				temp &= ~(1<<bit_nr); +			else +				temp |=  (1<<bit_nr);  			(*(volatile unsigned char*)(adr))=temp;  			if(grid_cycle<55) @@ -101,9 +121,54 @@ void init_grid_ctrl(void)  			bit_nr = bit%8;  			bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4;  			temp=(*(volatile unsigned char*)(adr)); -			temp|=(1<<bit_nr); +			if (gd->vfd_inv_data) +				temp &= ~(1<<bit_nr); +			else +				temp |=  (1<<bit_nr); +			(*(volatile unsigned char*)(adr))=temp; +		} +	    } +	    break; +	case VFD_TYPE_MN11236: +	    for (display=0; display<4; display++) { +		for (grid_cycle=0; grid_cycle<38; grid_cycle++) { +			bit = grid_cycle * 256  * 4 + +			     (253 - grid_cycle) * 4 + +			     frame_buf_offs + display; +			/* wrap arround if offset (see manual S3C2400) */ +			if (bit>=frame_buf_size*8) +				bit = bit - (frame_buf_size * 8); +			adr = vfdbase + (bit/32) * 4 + (3 - (bit%32) / 8); +			bit_nr = bit % 8; +			bit_nr = (bit_nr > 3) ? bit_nr-4 : bit_nr+4; +			temp=(*(volatile unsigned char*)(adr)); +			if (gd->vfd_inv_data) +				temp &= ~(1<<bit_nr); +			else +				temp |=  (1<<bit_nr); +			(*(volatile unsigned char*)(adr))=temp; + +			if(grid_cycle<37) +				bit = grid_cycle*256*4+(252-grid_cycle)*4+frame_buf_offs+display; + +			/* wrap arround if offset (see manual S3C2400) */ +			if (bit>=frame_buf_size*8) +				bit = bit-(frame_buf_size*8); +			adr = vfdbase+(bit/32)*4+(3-(bit%32)/8); +			bit_nr = bit%8; +			bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4; +			temp=(*(volatile unsigned char*)(adr)); +			if (gd->vfd_inv_data) +				temp &= ~(1<<bit_nr); +			else +				temp |=  (1<<bit_nr);  			(*(volatile unsigned char*)(adr))=temp;  		} +	    } +	    break; +	default: +	    printf ("Warning: unknown display type\n"); +	    break;  	}  } @@ -113,175 +178,142 @@ void init_grid_ctrl(void)   */  void create_vfd_table(void)  { -	unsigned int vfd_table[112][18][2][4][2]; -	ulong adr; -	unsigned int x, y, color, display, entry, pixel, bit_nr; +	DECLARE_GLOBAL_DATA_PTR; +	unsigned long vfd_table[112][18][2][4][2]; +	unsigned int x, y, color, display, entry, pixel; +	unsigned int x_abcdef = 0; -	/* -	 * Create translation table for Noritake-T119C-VFD-specific -	 * organized frame-buffer. -	 * Created is the number of the bit in the framebuffer (the -	 * first transferred pixel of each frame is bit 0). -	 */ -	for(y=0;y<=17;y++)   /* Zeile */ -	{ -		for(x=0;x<=111;x++)  /* Spalten */ -		{ -			/*Display 0 blaue Pixel Eintrag 1 */ -			vfd_table[x][y][0][0][0]=((x%4)*4+y*16+(x/4)*2048); -			/*Display 0 rote Pixel Eintrag 1 */ -			vfd_table[x][y][1][0][0]=((x%4)*4+y*16+(x/4)*2048+512); -			if(x<=1) -			{ -				/*Display 0 blaue Pixel Eintrag 2 */ -				vfd_table[x][y][0][0][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+1024); -				/*Display 0 rote Pixel Eintrag 2 */ -				vfd_table[x][y][1][0][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+1024); -			} -			else -			{ -				/*Display 0 blaue Pixel Eintrag 2 */ -				vfd_table[x][y][0][0][1]=((x%4)*4+y*16+((x-2)/4)*2048+1024); -				/*Display 0 rote Pixel Eintrag 2 */ -				vfd_table[x][y][1][0][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+1024); -			} -			/*Display 1 blaue Pixel Eintrag 1 */ -			vfd_table[x][y][0][1][0]=((x%4)*4+y*16+(x/4)*2048+1); -			/*Display 1 rote Pixel Eintrag 1 */ -			vfd_table[x][y][1][1][0]=((x%4)*4+y*16+(x/4)*2048+512+1); -			if(x<=1) -			{ -				/*Display 1 blaue Pixel Eintrag 2 */ -				vfd_table[x][y][0][1][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+1+1024); -				/*Display 1 rote Pixel Eintrag 2 */ -				vfd_table[x][y][1][1][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+1+1024); -			} -			else -			{ -				/*Display 1 blaue Pixel Eintrag 2 */ -				vfd_table[x][y][0][1][1]=((x%4)*4+y*16+((x-2)/4)*2048+1+1024); -				/*Display 1 rote Pixel Eintrag 2 */ -				vfd_table[x][y][1][1][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+1+1024); -			} -			/*Display 2 blaue Pixel Eintrag 1 */ -			vfd_table[x][y][0][2][0]=((x%4)*4+y*16+(x/4)*2048+2); -			/*Display 2 rote Pixel Eintrag 1 */ -			vfd_table[x][y][1][2][0]=((x%4)*4+y*16+(x/4)*2048+512+2); -			if(x<=1) -			{ -				/*Display 2 blaue Pixel Eintrag 2 */ -				vfd_table[x][y][0][2][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+2+1024); -				/*Display 2 rote Pixel Eintrag 2 */ -				vfd_table[x][y][1][2][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+2+1024); -			} -			else -			{ -				/*Display 2 blaue Pixel Eintrag 2 */ -				vfd_table[x][y][0][2][1]=((x%4)*4+y*16+((x-2)/4)*2048+2+1024); -				/*Display 2 rote Pixel Eintrag 2 */ -				vfd_table[x][y][1][2][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+2+1024); -			} -			/*Display 3 blaue Pixel Eintrag 1 */ -			vfd_table[x][y][0][3][0]=((x%4)*4+y*16+(x/4)*2048+3); -			/*Display 3 rote Pixel Eintrag 1 */ -			vfd_table[x][y][1][3][0]=((x%4)*4+y*16+(x/4)*2048+512+3); -			if(x<=1) -			{ -				/*Display 3 blaue Pixel Eintrag 2 */ -				vfd_table[x][y][0][3][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+3+1024); -				/*Display 3 rote Pixel Eintrag 2 */ -				vfd_table[x][y][1][3][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+3+1024); -			} -			else -			{ -				/*Display 3 blaue Pixel Eintrag 2 */ -				vfd_table[x][y][0][3][1]=((x%4)*4+y*16+((x-2)/4)*2048+3+1024); -				/*Display 3 rote Pixel Eintrag 2 */ -				vfd_table[x][y][1][3][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+3+1024); -			} +	switch (gd->vfd_type) { +	case VFD_TYPE_T119C: +	    for(y=0; y<=17; y++) {	/* Line */ +		for(x=0; x<=111; x++) {	/* Column */ +		    for(display=0; display <=3; display++) { + +			    /* Display 0 blue pixels */ +			    vfd_table[x][y][0][display][0] = +				(x==0) ? y*16+display +				       : (x%4)*4+y*16+((x-1)/2)*1024+display; +			    /* Display 0 red pixels */ +			    vfd_table[x][y][1][display][0] = +				(x==0) ? y*16+512+display +			    	       : (x%4)*4+y*16+((x-1)/2)*1024+512+display; +		    } +		} +	    } +	    break; +	case VFD_TYPE_MN11236: +	    for(y=0; y<=17; y++) {	/* Line */ +		for(x=0; x<=111; x++) {	/* Column */ +		    for(display=0; display <=3; display++) { + +			    vfd_table[x][y][0][display][0]=0; +			    vfd_table[x][y][0][display][1]=0; +			    vfd_table[x][y][1][display][0]=0; +			    vfd_table[x][y][1][display][1]=0; + +			    switch (x%6) { +			    case 0: x_abcdef=0; break; /* a -> a */ +			    case 1: x_abcdef=2; break; /* b -> c */ +			    case 2: x_abcdef=4; break; /* c -> e */ +			    case 3: x_abcdef=5; break; /* d -> f */ +			    case 4: x_abcdef=3; break; /* e -> d */ +			    case 5: x_abcdef=1; break; /* f -> b */ +			    } + +			    /* blue pixels */ +			    vfd_table[x][y][0][display][0] = +				(x>1) ? x_abcdef*4+((x-1)/3)*1024+y*48+display +				      : x_abcdef*4+             0+y*48+display; +			    /* blue pixels */ +			    if (x>1 && (x-1)%3) +				    vfd_table[x][y][0][display][1] = x_abcdef*4+((x-1)/3+1)*1024+y*48+display; + +			    /* red pixels */ +			    vfd_table[x][y][1][display][0] = +				(x>1) ? x_abcdef*4+24+((x-1)/3)*1024+y*48+display +				      : x_abcdef*4+24+             0+y*48+display; +			    /* red pixels */ +			    if (x>1 && (x-1)%3) +				    vfd_table[x][y][1][display][1] = x_abcdef*4+24+((x-1)/3+1)*1024+y*48+display; +		    }  		} +	    } +	    break; +	default: +	    /* do nothing */ +	    return;  	}  	/* -	 * Create translation table for Noritake-T119C-VFD-specific -	 * organized frame-buffer  	 * Create table with entries for physical byte adresses and  	 * bit-number within the byte  	 * from table with bit-numbers within the total framebuffer  	 */ -	for(y=0;y<=17;y++) -	{ -		for(x=0;x<=111;x++) -		{ -			for(color=0;color<=1;color++) -			{ -				for(display=0;display<=3;display++) -				{ -					for(entry=0;entry<=1;entry++) -					{ -						pixel  = vfd_table[x][y][color][display][entry] + frame_buf_offs; -						 /* -						  * wrap arround if offset -						  * (see manual S3C2400) -						  */ -						if (pixel>=frame_buf_size*8) -							pixel = pixel-(frame_buf_size*8); -						adr    = vfdbase+(pixel/32)*4+(3-(pixel%32)/8); -						bit_nr = pixel%8; -						bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4; -						adr_vfd_table[x][y][color][display][entry] = adr; -						bit_vfd_table[x][y][color][display][entry] = bit_nr; -					} -				} +	for(y=0;y<18;y++) { +	    for(x=0;x<112;x++) { +		for(color=0;color<2;color++) { +		    for(display=0;display<4;display++) { +			for(entry=0;entry<2;entry++) { +			    unsigned long adr  = vfdbase; +			    unsigned int bit_nr = 0; +			     +			    if (vfd_table[x][y][color][display][entry]) { + +				pixel  = vfd_table[x][y][color][display][entry] + frame_buf_offs; +				 /* +				  * wrap arround if offset +				  * (see manual S3C2400) +				  */ +				if (pixel>=frame_buf_size*8) +					pixel = pixel-(frame_buf_size*8); +				adr    = vfdbase+(pixel/32)*4+(3-(pixel%32)/8); +				bit_nr = pixel%8; +				bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4; +			    } +			    adr_vfd_table[x][y][color][display][entry] = adr; +			    bit_vfd_table[x][y][color][display][entry] = bit_nr;  			} +		    }  		} +	    }  	}  }  /*   * Set/clear pixel of the VFDs   */ -void set_vfd_pixel(unsigned char x, unsigned char y, unsigned char color, unsigned char display, unsigned char value) +void set_vfd_pixel(unsigned char x, unsigned char y, +		   unsigned char color, unsigned char display, +		   unsigned char value)  { +	DECLARE_GLOBAL_DATA_PTR;  	ulong adr;  	unsigned char bit_nr, temp; -	if (value!=0) -	{ -		/* Pixel-Eintrag Nr. 1 */ -		adr = adr_vfd_table[x][y][color][display][0]; -		/* Pixel-Eintrag Nr. 1 */ -		bit_nr = bit_vfd_table[x][y][color][display][0]; -		temp=(*(volatile unsigned char*)(adr)); -		temp|=1<<bit_nr; -		(*(volatile unsigned char*)(adr))=temp; - -		/* Pixel-Eintrag Nr. 2 */ -		adr = adr_vfd_table[x][y][color][display][1]; -		/* Pixel-Eintrag Nr. 2 */ -		bit_nr = bit_vfd_table[x][y][color][display][1]; -		temp=(*(volatile unsigned char*)(adr)); -		temp|=1<<bit_nr; -		(*(volatile unsigned char*)(adr))=temp; +	if (! gd->vfd_type) { +		/* Unknown type. */ +		return;  	} -	else -	{ -		/* Pixel-Eintrag Nr. 1 */ -		adr = adr_vfd_table[x][y][color][display][0]; -		/* Pixel-Eintrag Nr. 1 */ -		bit_nr = bit_vfd_table[x][y][color][display][0]; -		temp=(*(volatile unsigned char*)(adr)); -		temp&=~(1<<bit_nr); -		(*(volatile unsigned char*)(adr))=temp; -		/* Pixel-Eintrag Nr. 2 */ -		adr = adr_vfd_table[x][y][color][display][1]; -		/* Pixel-Eintrag Nr. 2 */ -		bit_nr = bit_vfd_table[x][y][color][display][1]; -		temp=(*(volatile unsigned char*)(adr)); -		temp&=~(1<<bit_nr); -		(*(volatile unsigned char*)(adr))=temp; +	/* Pixel-Eintrag Nr. 1 */ +	adr = adr_vfd_table[x][y][color][display][0]; +	/* Pixel-Eintrag Nr. 1 */ +	bit_nr = bit_vfd_table[x][y][color][display][0]; +	temp=(*(volatile unsigned char*)(adr)); + +	if (gd->vfd_inv_data) { +		if (value) +			temp &= ~(1<<bit_nr); +		else +			temp |=  (1<<bit_nr); +	} else { +		if (value) +			temp |=  (1<<bit_nr); +		else +			temp &= ~(1<<bit_nr);  	} +	 +	(*(volatile unsigned char*)(adr))=temp;  }  /* @@ -334,12 +366,36 @@ void transfer_pic(int display, unsigned char *adr, int height, int width)  }  /* + * This function initializes VFD clock that is needed for the CPLD that + * manages the keyboard. + */ +int vfd_init_clocks(void) +{ +	/* Port-Pins als LCD-Ausgang */ +	rPCCON =   (rPCCON & 0xFFFFFF00)| 0x000000AA; +	/* Port-Pins als LCD-Ausgang */ +	rPDCON =   (rPDCON & 0xFFFFFF03)| 0x000000A8; +#ifdef WITH_VFRAME +	/* mit VFRAME zum Messen */ +	rPDCON =   (rPDCON & 0xFFFFFF00)| 0x000000AA; +#endif + +	rLCDCON2 = 0x000DC000; +	rLCDCON3 = 0x0051000A; +	rLCDCON4 = 0x00000001; +	rLCDCON5 = 0x00000440; +	rLCDCON1 = 0x00000B75; +} + +/*   * initialize LCD-Controller of the S3C2400 for using VFDs   */  int drv_vfd_init(void)  { +	char *tmp;  	ulong palette;  	static int vfd_init_done = 0; +	int vfd_id;  	DECLARE_GLOBAL_DATA_PTR; @@ -347,10 +403,58 @@ int drv_vfd_init(void)  		return (0);  	vfd_init_done = 1; +	/* try to determine display type from the value +	 * defined by pull-ups +	 */ +	rPCUP  = (rPCUP | 0x000F);	/* activate  GPC0...GPC3 pullups */ +	rPCCON = (rPCCON & 0xFFFFFF00);	/* configure GPC0...GPC3 as inputs */ + +	vfd_id = (~rPCDAT) & 0x000F;	/* read GPC0...GPC3 port pins */ +	debug("Detecting Revison of WA4-VFD: ID=0x%X\n", vfd_id); + +	switch (vfd_id) { +	case 0:				/* board revision <= Rev.100 */ +/*-----*/ +		gd->vfd_inv_data = 0; +		if (0) +			gd->vfd_type = VFD_TYPE_MN11236; +		else +			gd->vfd_type = VFD_TYPE_T119C; +/*-----*/ +		if ((tmp = getenv ("vfd_type")) == NULL) { +			break; +		} +		if (strcmp(tmp, "T119C") == 0) { +			gd->vfd_type = VFD_TYPE_T119C; +		} else if (strcmp(tmp, "MN11236") == 0) { +			gd->vfd_type = VFD_TYPE_MN11236; +		} else { +			/* cannot use printf for a warning here */ +			gd->vfd_type = 0;	/* unknown */ +		} +		gd->vfd_inv_data = 0; + +		break; +	default:			/* default to MN11236, data inverted */ +		gd->vfd_type = VFD_TYPE_MN11236; +		gd->vfd_inv_data = 1; +		setenv ("vfd_type", "MN11236"); +	} +	debug ("VFD type: %s%s\n", +		(gd->vfd_type == VFD_TYPE_T119C)   ? "T119C" : +		(gd->vfd_type == VFD_TYPE_MN11236) ? "MN11236" : +		"unknown", +		gd->vfd_inv_data ? ", inverted data" : ""); +  	vfdbase = gd->fb_base;  	create_vfd_table();  	init_grid_ctrl(); +	for (palette=0; palette < 16; palette++) +		(*(volatile unsigned int*)(PALETTE+(palette*4)))=palette; +	for (palette=16; palette < 256; palette++) +		(*(volatile unsigned int*)(PALETTE+(palette*4)))=0x00; +  	/*  	 * Hinweis: Der Framebuffer ist um genau ein Nibble verschoben  	 * Das erste angezeigte Pixel wird aus dem zweiten Nibble geholt @@ -364,30 +468,10 @@ int drv_vfd_init(void)  	rLCDSADDR2 = (vfdbase + frame_buf_size) >> 1;  	rLCDSADDR3 = ((256/4)); -	/* Port-Pins als LCD-Ausgang */ -	rPCCON =   (rPCCON & 0xFFFFFF00)| 0x000000AA; -	/* Port-Pins als LCD-Ausgang */ -	rPDCON =   (rPDCON & 0xFFFFFF03)| 0x000000A8; -#ifdef WITH_VFRAME -	/* mit VFRAME zum Messen */ -	rPDCON =   (rPDCON & 0xFFFFFF00)| 0x000000AA; -#endif - -	rLCDCON2 = 0x000DC000; -	rLCDCON3 = 0x0051000A; -	rLCDCON4 = 0x00000001; -	rLCDCON5 = 0x00000440; -	rLCDCON1 = 0x00000B75; -  	debug ("LCDSADDR1: %lX\n", rLCDSADDR1);  	debug ("LCDSADDR2: %lX\n", rLCDSADDR2);  	debug ("LCDSADDR3: %lX\n", rLCDSADDR3); -	for(palette=0;palette<=15;palette++) -		(*(volatile unsigned int*)(PALETTE+(palette*4)))=palette; -	for(palette=16;palette<=255;palette++) -		(*(volatile unsigned int*)(PALETTE+(palette*4)))=0x00; -  	return 0;  } diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index e138d78b9..2ac576307 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -192,6 +192,8 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	if (hdr->ih_arch != IH_CPU_ARM)  #elif defined(__I386__)  	if (hdr->ih_arch != IH_CPU_I386) +#elif defined(__mips__) +	if (hdr->ih_arch != IH_CPU_MIPS)	  #else  # error Unknown CPU type  #endif diff --git a/common/cmd_elf.c b/common/cmd_elf.c index 149ffa3da..74957622b 100644 --- a/common/cmd_elf.c +++ b/common/cmd_elf.c @@ -252,11 +252,13 @@ int valid_elf_image (unsigned long addr)  		return 0;  	} +#if 0  	if (ehdr->e_machine != EM_PPC) {  		printf ("## Not a PowerPC elf image at address 0x%08lx\n",  			addr);  		return 0;  	} +#endif  	return 1;  } diff --git a/common/cmd_ide.c b/common/cmd_ide.c index d082d5e9b..94fc89b42 100644 --- a/common/cmd_ide.c +++ b/common/cmd_ide.c @@ -489,11 +489,14 @@ void ide_init (void)  #ifdef CONFIG_IDE_8xx_PCCARD  	extern int pcmcia_on (void); +	extern int ide_devices_found; /* Initialized in check_ide_device() */  	WATCHDOG_RESET(); +	ide_devices_found = 0;  	/* initialize the PCMCIA IDE adapter card */ -	if (pcmcia_on()) +	pcmcia_on(); +	if (!ide_devices_found)  		return;  	udelay (1000000);	/* 1 s */  #endif	/* CONFIG_IDE_8xx_PCCARD */ @@ -550,6 +553,13 @@ void ide_init (void)  		int dev = bus * (CFG_IDE_MAXDEVICE / max_bus_scan);  #endif +#ifdef CONFIG_IDE_8xx_PCCARD +		/* Skip non-ide devices from probing */ +		if ((ide_devices_found & (1 << bus)) == 0) { +			ide_led ((LED_IDE1 | LED_IDE2), 0); /* LED's off */ +			continue; +		} +#endif  		printf ("Bus %d: ", bus);  		ide_bus_ok[bus] = 0; diff --git a/common/cmd_pcmcia.c b/common/cmd_pcmcia.c index f9bd0ba89..31abbaf72 100644 --- a/common/cmd_pcmcia.c +++ b/common/cmd_pcmcia.c @@ -268,6 +268,7 @@ static int pcmcia_off (void)  #define	MAX_TUPEL_SZ	512  #define MAX_FEATURES	4 +int ide_devices_found;  static int check_ide_device (int slot)  {  	volatile uchar *ident = NULL; @@ -347,6 +348,8 @@ static int check_ide_device (int slot)  		return (1);  	} +	ide_devices_found |= (1 << slot); +  	/* set I/O area in config reg -> only valid for ARGOSY D5!!! */  	*((uchar *)(addr + config_base)) = 1; diff --git a/drivers/Makefile b/drivers/Makefile index afea75224..65de8b5c3 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -28,12 +28,13 @@ include $(TOPDIR)/config.mk  LIB	= libdrivers.a  OBJS	= 3c589.o 5701rls.o bcm570x.o bcm570x_autoneg.o \ -	  cfb_console.o cs8900.o dc2114x.o eepro100.o \ -	  i8042.o natsemi.o ns16550.o ns8382x.o ns87308.o \ +	  cfb_console.o cs8900.o ct69000.o dc2114x.o \ +	  eepro100.o i8042.o inca-ip_sw.o \ +	  natsemi.o ns16550.o ns8382x.o ns87308.o \  	  pci.o pci_auto.o pci_indirect.o \  	  pcnet.o sed13806.o serial.o \  	  smc91111.o smiLynxEM.o sym53c8xx.o \ -	  tigon3.o w83c553f.o ct69000.o +	  tigon3.o w83c553f.o  all:	$(LIB) diff --git a/drivers/cs8900.c b/drivers/cs8900.c index ecc7c13b1..7165d60bd 100644 --- a/drivers/cs8900.c +++ b/drivers/cs8900.c @@ -1,6 +1,10 @@  /*   * Cirrus Logic CS8900A Ethernet   * + * (C) 2003 Wolfgang Denk, wd@denx.de + *     Extension to synchronize ethaddr environment variable + *     against value in EEPROM + *   * (C) Copyright 2002   * Sysgo Real-Time Solutions, GmbH <www.elinos.com>   * Marius Groeger <mgroeger@sysgo.de> @@ -48,188 +52,226 @@  /* we don't need 16 bit initialisation on 32 bit bus */  #define get_reg_init_bus(x) get_reg((x))  #else -static unsigned short get_reg_init_bus(int regno) +static unsigned short get_reg_init_bus (int regno)  { -    /* force 16 bit busmode */ -    volatile unsigned char c; -    c = CS8900_BUS16_0; -    c = CS8900_BUS16_1; -    c = CS8900_BUS16_0; -    c = CS8900_BUS16_1; -    c = CS8900_BUS16_0; +	/* force 16 bit busmode */ +	volatile unsigned char c; + +	c = CS8900_BUS16_0; +	c = CS8900_BUS16_1; +	c = CS8900_BUS16_0; +	c = CS8900_BUS16_1; +	c = CS8900_BUS16_0; -    CS8900_PPTR = regno; -    return (unsigned short) CS8900_PDATA; +	CS8900_PPTR = regno; +	return (unsigned short) CS8900_PDATA;  }  #endif -static unsigned short -get_reg(int regno) +static unsigned short get_reg (int regno)  { -    CS8900_PPTR = regno; -    return (unsigned short) CS8900_PDATA; +	CS8900_PPTR = regno; +	return (unsigned short) CS8900_PDATA;  } -static void put_reg(int regno, unsigned short val) +static void put_reg (int regno, unsigned short val)  { -    CS8900_PPTR = regno; -    CS8900_PDATA = val; +	CS8900_PPTR = regno; +	CS8900_PDATA = val;  } -static void eth_reset(void) +static void eth_reset (void)  { -    int tmo; -    unsigned short us; +	int tmo; +	unsigned short us; -    /* reset NIC */ -    put_reg(PP_SelfCTL, get_reg(PP_SelfCTL) | PP_SelfCTL_Reset ); +	/* reset NIC */ +	put_reg (PP_SelfCTL, get_reg (PP_SelfCTL) | PP_SelfCTL_Reset); -    /* wait for 200ms */ -    udelay(200000); -    /* Wait until the chip is reset */ +	/* wait for 200ms */ +	udelay (200000); +	/* Wait until the chip is reset */ -    tmo = get_timer(0) + 1 * CFG_HZ; -    while ((((us = get_reg_init_bus(PP_SelfSTAT)) & PP_SelfSTAT_InitD) == 0) -	   && tmo < get_timer(0)) -      /*NOP*/; +	tmo = get_timer (0) + 1 * CFG_HZ; +	while ((((us = get_reg_init_bus (PP_SelfSTAT)) & PP_SelfSTAT_InitD) == 0) +		   && tmo < get_timer (0)) +		/*NOP*/;  } -void cs8900_get_enetaddr (uchar *addr) +void cs8900_get_enetaddr (uchar * addr)  { -    int i; -    /* verify chip id */ -    if (get_reg_init_bus(PP_ChipID) != 0x630e) -	return; -    eth_reset(); -    if ((get_reg(PP_SelfST) & (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) == -	      (PP_SelfSTAT_EEPROM|PP_SelfSTAT_EEPROM_OK)) { -	/* Load the MAC from EEPROM */ -	for (i=0; i<6/2; i++) { -	    unsigned int Addr; -	    Addr = get_reg(PP_IA+i*2); -	    addr[i*2] = Addr & 0xFF; -	    addr[i*2+1] = Addr >> 8; +	int i; +	unsigned char env_enetaddr[6]; +	char *tmp = getenv ("ethaddr"); +	char *end; + +	for (i=0; i<6; i++) { +		env_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0; +		if (tmp) +			tmp = (*end) ? end+1 : end; +	} + +	/* verify chip id */ +	if (get_reg_init_bus (PP_ChipID) != 0x630e) +		return; +	eth_reset (); +	if ((get_reg (PP_SelfST) & (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) == +			(PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) { + +		/* Load the MAC from EEPROM */ +		for (i = 0; i < 6 / 2; i++) { +			unsigned int Addr; + +			Addr = get_reg (PP_IA + i * 2); +			addr[i * 2] = Addr & 0xFF; +			addr[i * 2 + 1] = Addr >> 8; +		} + +		if (memcmp(env_enetaddr, "\0\0\0\0\0\0", 6) != 0 && +		    memcmp(env_enetaddr, addr, 6) != 0) { +			printf ("\nWarning: MAC addresses don't match:\n"); +			printf ("\tHW MAC address:  " +				"%02X:%02X:%02X:%02X:%02X:%02X\n", +				addr[0], addr[1], +				addr[2], addr[3], +				addr[4], addr[5] ); +			printf ("\t\"ethaddr\" value: " +				"%02X:%02X:%02X:%02X:%02X:%02X\n", +				env_enetaddr[0], env_enetaddr[1], +				env_enetaddr[2], env_enetaddr[3], +				env_enetaddr[4], env_enetaddr[5]) ; +			debug ("### Set MAC addr from environment\n"); +			memcpy (addr, env_enetaddr, 6); +		} +		if (!tmp) { +			char ethaddr[20]; +			sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X", +				 addr[0], addr[1], +				 addr[2], addr[3], +				 addr[4], addr[5]) ; +			debug ("### Set environment from HW MAC addr = \"%s\"\n",				ethaddr); +			setenv ("ethaddr", ethaddr); +		} +  	} -    }  } -void eth_halt( void ) +void eth_halt (void)  { -    /* disable transmitter/receiver mode */ -    put_reg(PP_LineCTL, 0); +	/* disable transmitter/receiver mode */ +	put_reg (PP_LineCTL, 0); -    /* "shutdown" to show ChipID or kernel wouldn't find he cs8900 ... */ -    get_reg_init_bus(PP_ChipID); +	/* "shutdown" to show ChipID or kernel wouldn't find he cs8900 ... */ +	get_reg_init_bus (PP_ChipID);  } -int eth_init( bd_t *bd ) +int eth_init (bd_t * bd)  { -    /* verify chip id */ -    if (get_reg_init_bus(PP_ChipID) != 0x630e) -    { -	printf( "CS8900 Ethernet chip not found?!\n" ); -	return 0; -    } +	/* verify chip id */ +	if (get_reg_init_bus (PP_ChipID) != 0x630e) { +		printf ("CS8900 Ethernet chip not found?!\n"); +		return 0; +	} -    eth_reset(); -    /* set the ethernet address */ -    put_reg(PP_IA + 0, bd->bi_enetaddr[0] | (bd->bi_enetaddr[1] << 8)); -    put_reg(PP_IA + 2, bd->bi_enetaddr[2] | (bd->bi_enetaddr[3] << 8)); -    put_reg(PP_IA + 4, bd->bi_enetaddr[4] | (bd->bi_enetaddr[5] << 8)); +	eth_reset (); +	/* set the ethernet address */ +	put_reg (PP_IA + 0, bd->bi_enetaddr[0] | (bd->bi_enetaddr[1] << 8)); +	put_reg (PP_IA + 2, bd->bi_enetaddr[2] | (bd->bi_enetaddr[3] << 8)); +	put_reg (PP_IA + 4, bd->bi_enetaddr[4] | (bd->bi_enetaddr[5] << 8)); -    /* receive only error free packets addressed to this card */ -    put_reg(PP_RxCTL, PP_RxCTL_IA | PP_RxCTL_Broadcast | PP_RxCTL_RxOK); +	/* receive only error free packets addressed to this card */ +	put_reg (PP_RxCTL, PP_RxCTL_IA | PP_RxCTL_Broadcast | PP_RxCTL_RxOK); -    /* do not generate any interrupts on receive operations */ -    put_reg(PP_RxCFG, 0); +	/* do not generate any interrupts on receive operations */ +	put_reg (PP_RxCFG, 0); -    /* do not generate any interrupts on transmit operations */ -    put_reg(PP_TxCFG, 0); +	/* do not generate any interrupts on transmit operations */ +	put_reg (PP_TxCFG, 0); -    /* do not generate any interrupts on buffer operations */ -    put_reg(PP_BufCFG, 0); +	/* do not generate any interrupts on buffer operations */ +	put_reg (PP_BufCFG, 0); -    /* enable transmitter/receiver mode */ -    put_reg(PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx); +	/* enable transmitter/receiver mode */ +	put_reg (PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx); -    return 0; +	return 0;  }  /* Get a data block via Ethernet */ -extern int eth_rx(void) +extern int eth_rx (void)  { -    int i; -    unsigned short rxlen; -    unsigned short *addr; -    unsigned short status; +	int i; +	unsigned short rxlen; +	unsigned short *addr; +	unsigned short status; -    status = get_reg(PP_RER); +	status = get_reg (PP_RER); -    if ((status & PP_RER_RxOK) == 0) -      return 0; +	if ((status & PP_RER_RxOK) == 0) +		return 0; -    status = CS8900_RTDATA;       /* stat */ -    rxlen = CS8900_RTDATA;        /* len */ +	status = CS8900_RTDATA;		/* stat */ +	rxlen = CS8900_RTDATA;		/* len */ -    if(rxlen > PKTSIZE_ALIGN + PKTALIGN) -      printf("packet too big!\n"); +	if (rxlen > PKTSIZE_ALIGN + PKTALIGN) +		printf ("packet too big!\n"); -    for(addr = (unsigned short *)NetRxPackets[0], i = rxlen >> 1; i > 0; i-- ) -      *addr++ = CS8900_RTDATA; -    if(rxlen & 1) -      *addr++ = CS8900_RTDATA; +	for (addr = (unsigned short *) NetRxPackets[0], i = rxlen >> 1; i > 0; +		 i--) +		*addr++ = CS8900_RTDATA; +	if (rxlen & 1) +		*addr++ = CS8900_RTDATA; -    /* Pass the packet up to the protocol layers. */ -    NetReceive(NetRxPackets[0], rxlen); +	/* Pass the packet up to the protocol layers. */ +	NetReceive (NetRxPackets[0], rxlen); -    return rxlen; +	return rxlen;  }  /* Send a data block via Ethernet. */ -extern int eth_send(volatile void *packet, int length) +extern int eth_send (volatile void *packet, int length)  { -    volatile unsigned short *addr; -    int tmo; -    unsigned short s; +	volatile unsigned short *addr; +	int tmo; +	unsigned short s;  retry: -    /* initiate a transmit sequence */ -    CS8900_TxCMD = PP_TxCmd_TxStart_Full; -    CS8900_TxLEN = length; +	/* initiate a transmit sequence */ +	CS8900_TxCMD = PP_TxCmd_TxStart_Full; +	CS8900_TxLEN = length; -    /* Test to see if the chip has allocated memory for the packet */ -    if ((get_reg(PP_BusSTAT) & PP_BusSTAT_TxRDY) == 0) { -	/* Oops... this should not happen! */ -	printf("cs: unable to send packet; retrying...\n"); -	for (tmo = get_timer(0) + 5 * CFG_HZ; get_timer(0) < tmo; ) -	  /*NOP*/; -	eth_reset(); -	goto retry; -    } +	/* Test to see if the chip has allocated memory for the packet */ +	if ((get_reg (PP_BusSTAT) & PP_BusSTAT_TxRDY) == 0) { +		/* Oops... this should not happen! */ +		printf ("cs: unable to send packet; retrying...\n"); +		for (tmo = get_timer (0) + 5 * CFG_HZ; get_timer (0) < tmo;) +			/*NOP*/; +		eth_reset (); +		goto retry; +	} -    /* Write the contents of the packet */ -    /* assume even number of bytes */ -    for(addr = packet; length > 0; length -= 2 ) -      CS8900_RTDATA = *addr++; +	/* Write the contents of the packet */ +	/* assume even number of bytes */ +	for (addr = packet; length > 0; length -= 2) +		CS8900_RTDATA = *addr++; -    /* wait for transfer to succeed */ -    tmo = get_timer(0) + 5 * CFG_HZ; -    while((s = get_reg(PP_TER) & ~0x1F) == 0) -    { -	if (get_timer(0) >= tmo) -	  break; -    } +	/* wait for transfer to succeed */ +	tmo = get_timer (0) + 5 * CFG_HZ; +	while ((s = get_reg (PP_TER) & ~0x1F) == 0) { +		if (get_timer (0) >= tmo) +			break; +	} -      /* nothing */ ; -    if ((s & (PP_TER_CRS | PP_TER_TxOK)) != PP_TER_TxOK) { -	printf("\ntransmission error %#x\n", s); -    } +	/* nothing */ ; +	if ((s & (PP_TER_CRS | PP_TER_TxOK)) != PP_TER_TxOK) { +		printf ("\ntransmission error %#x\n", s); +	} -    return 0; +	return 0;  } -#endif /* COMMANDS & CFG_NET */ +#endif	/* COMMANDS & CFG_NET */ -#endif /* CONFIG_DRIVER_CS8900 */ +#endif	/* CONFIG_DRIVER_CS8900 */ diff --git a/drivers/tigon3.c b/drivers/tigon3.c index 5883744db..c20dbe5cd 100644 --- a/drivers/tigon3.c +++ b/drivers/tigon3.c @@ -11,7 +11,6 @@  /* History:                                                                   */  /******************************************************************************/  #include <common.h> -#include "bcm570x_mm.h"  #include <asm/types.h>  #if (CONFIG_COMMANDS & CFG_CMD_NET) && !defined(CONFIG_NET_MULTI) && \  	defined(CONFIG_TIGON3) @@ -20,6 +19,7 @@  #endif  #include <malloc.h>  #include <linux/byteorder/big_endian.h> +#include "bcm570x_mm.h"  #define EMBEDDED 1  /******************************************************************************/ diff --git a/examples/Makefile b/examples/Makefile index b7d6f94e4..e6a302391 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -27,6 +27,10 @@ include $(TOPDIR)/config.mk  SREC	= hello_world.srec +ifeq ($(CPU),mips) +SREC = +endif +  # The following example is pretty 8xx specific...  ifeq ($(CPU),mpc8xx)  SREC   += timer.srec diff --git a/examples/syscall.S b/examples/syscall.S index a952fd774..510807bc9 100644 --- a/examples/syscall.S +++ b/examples/syscall.S @@ -37,7 +37,37 @@ mon_free:  	stmfd   sp!, {fp, ip, lr, pc}  	sub     fp, ip, #4  	ldmea   fp, {fp, sp, pc} -#else /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ +#elif defined(CONFIG_MIPS)/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ +#warning MIPS version not implemented yet +	.global	mon_getc +	.type	mon_getc,function +mon_getc: +	.global	mon_tstc +	.type	mon_tstc,function +mon_tstc: +	.global	mon_putc +	.type	mon_putc,function +mon_putc: +	.global	mon_puts +	.type	mon_puts,function +mon_puts: +	.global	mon_printf +	.type	mon_printf,function +mon_printf: +	.global	mon_install_hdlr +	.type	mon_install_hdlr,function +mon_install_hdlr: +	.global	mon_free_hdlr +	.type	mon_free_hdlr,function +mon_free_hdlr: +	.global	mon_malloc +	.type	mon_malloc,function +mon_malloc: +	.global	mon_free +	.type	mon_free,function +mon_free: + +#else  #ifdef CONFIG_I386 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */  #define SYMBOL_NAME(X) 	X diff --git a/include/asm-arm/global_data.h b/include/asm-arm/global_data.h index bf26d0b4a..e0a95e081 100644 --- a/include/asm-arm/global_data.h +++ b/include/asm-arm/global_data.h @@ -43,6 +43,8 @@ typedef	struct	global_data {  	unsigned long	env_valid;	/* Checksum of Environment valid? */  #ifdef CONFIG_VFD  	unsigned long	fb_base;	/* base address of frame buffer */ +	unsigned char	vfd_type;	/* display type */ +	unsigned char	vfd_inv_data;	/* inverted data lines ? */  #endif  #if 0  	unsigned long	cpu_clk;	/* CPU clock in Hz!		*/ diff --git a/include/asm-mips/addrspace.h b/include/asm-mips/addrspace.h new file mode 100644 index 000000000..0d1bf3246 --- /dev/null +++ b/include/asm-mips/addrspace.h @@ -0,0 +1,70 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996 by Ralf Baechle + * Copyright (C) 2000 by Maciej W. Rozycki + * + * Defitions for the address spaces of the MIPS CPUs. + */ +#ifndef __ASM_MIPS_ADDRSPACE_H +#define __ASM_MIPS_ADDRSPACE_H + +/* + * Memory segments (32bit kernel mode addresses) + */ +#define KUSEG                   0x00000000 +#define KSEG0                   0x80000000 +#define KSEG1                   0xa0000000 +#define KSEG2                   0xc0000000 +#define KSEG3                   0xe0000000 + +#define K0BASE  KSEG0 + +/* + * Returns the kernel segment base of a given address + */ +#ifndef __ASSEMBLY__ +#define KSEGX(a)                (((unsigned long)(a)) & 0xe0000000) +#else +#define KSEGX(a)                ((a) & 0xe0000000) +#endif + +/* + * Returns the physical address of a KSEG0/KSEG1 address + */ +#ifndef __ASSEMBLY__ +#define PHYSADDR(a)		(((unsigned long)(a)) & 0x1fffffff) +#else +#define PHYSADDR(a)		((a) & 0x1fffffff) +#endif + +/* + * Map an address to a certain kernel segment + */ +#ifndef __ASSEMBLY__ +#define KSEG0ADDR(a)		((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG0)) +#define KSEG1ADDR(a)		((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG1)) +#define KSEG2ADDR(a)		((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG2)) +#define KSEG3ADDR(a)		((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG3)) +#else +#define KSEG0ADDR(a)		(((a) & 0x1fffffff) | KSEG0) +#define KSEG1ADDR(a)		(((a) & 0x1fffffff) | KSEG1) +#define KSEG2ADDR(a)		(((a) & 0x1fffffff) | KSEG2) +#define KSEG3ADDR(a)		(((a) & 0x1fffffff) | KSEG3) +#endif + +/* + * Memory segments (64bit kernel mode addresses) + */ +#define XKUSEG                  0x0000000000000000 +#define XKSSEG                  0x4000000000000000 +#define XKPHYS                  0x8000000000000000 +#define XKSEG                   0xc000000000000000 +#define CKSEG0                  0xffffffff80000000 +#define CKSEG1                  0xffffffffa0000000 +#define CKSSEG                  0xffffffffc0000000 +#define CKSEG3                  0xffffffffe0000000 + +#endif /* __ASM_MIPS_ADDRSPACE_H */ diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h new file mode 100644 index 000000000..edff4c0fe --- /dev/null +++ b/include/asm-mips/bitops.h @@ -0,0 +1,912 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 1994 - 1997, 1999, 2000  Ralf Baechle (ralf@gnu.org) + * Copyright (c) 2000  Silicon Graphics, Inc. + */ +#ifndef _ASM_BITOPS_H +#define _ASM_BITOPS_H + +#include <linux/types.h> +#include <asm/byteorder.h>		/* sigh ... */ + +#ifdef __KERNEL__ + +#include <asm/sgidefs.h> +#include <asm/system.h> +#include <linux/config.h> + +/* + * clear_bit() doesn't provide any barrier for the compiler. + */ +#define smp_mb__before_clear_bit()	barrier() +#define smp_mb__after_clear_bit()	barrier() + +/* + * Only disable interrupt for kernel mode stuff to keep usermode stuff + * that dares to use kernel include files alive. + */ +#define __bi_flags unsigned long flags +#define __bi_cli() __cli() +#define __bi_save_flags(x) __save_flags(x) +#define __bi_save_and_cli(x) __save_and_cli(x) +#define __bi_restore_flags(x) __restore_flags(x) +#else +#define __bi_flags +#define __bi_cli() +#define __bi_save_flags(x) +#define __bi_save_and_cli(x) +#define __bi_restore_flags(x) +#endif /* __KERNEL__ */ + +#ifdef CONFIG_CPU_HAS_LLSC + +#include <asm/mipsregs.h> + +/* + * These functions for MIPS ISA > 1 are interrupt and SMP proof and + * interrupt friendly + */ + +/* + * set_bit - Atomically set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * This function is atomic and may not be reordered.  See __set_bit() + * if you do not require the atomic guarantees. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +extern __inline__ void +set_bit(int nr, volatile void *addr) +{ +	unsigned long *m = ((unsigned long *) addr) + (nr >> 5); +	unsigned long temp; + +	__asm__ __volatile__( +		"1:\tll\t%0, %1\t\t# set_bit\n\t" +		"or\t%0, %2\n\t" +		"sc\t%0, %1\n\t" +		"beqz\t%0, 1b" +		: "=&r" (temp), "=m" (*m) +		: "ir" (1UL << (nr & 0x1f)), "m" (*m)); +} + +/* + * __set_bit - Set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike set_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +extern __inline__ void __set_bit(int nr, volatile void * addr) +{ +	unsigned long * m = ((unsigned long *) addr) + (nr >> 5); + +	*m |= 1UL << (nr & 31); +} + +/* + * clear_bit - Clears a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * clear_bit() is atomic and may not be reordered.  However, it does + * not contain a memory barrier, so if it is used for locking purposes, + * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() + * in order to ensure changes are visible on other processors. + */ +extern __inline__ void +clear_bit(int nr, volatile void *addr) +{ +	unsigned long *m = ((unsigned long *) addr) + (nr >> 5); +	unsigned long temp; + +	__asm__ __volatile__( +		"1:\tll\t%0, %1\t\t# clear_bit\n\t" +		"and\t%0, %2\n\t" +		"sc\t%0, %1\n\t" +		"beqz\t%0, 1b\n\t" +		: "=&r" (temp), "=m" (*m) +		: "ir" (~(1UL << (nr & 0x1f))), "m" (*m)); +} + +/* + * change_bit - Toggle a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * change_bit() is atomic and may not be reordered. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +extern __inline__ void +change_bit(int nr, volatile void *addr) +{ +	unsigned long *m = ((unsigned long *) addr) + (nr >> 5); +	unsigned long temp; + +	__asm__ __volatile__( +		"1:\tll\t%0, %1\t\t# change_bit\n\t" +		"xor\t%0, %2\n\t" +		"sc\t%0, %1\n\t" +		"beqz\t%0, 1b" +		: "=&r" (temp), "=m" (*m) +		: "ir" (1UL << (nr & 0x1f)), "m" (*m)); +} + +/* + * __change_bit - Toggle a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike change_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +extern __inline__ void __change_bit(int nr, volatile void * addr) +{ +	unsigned long * m = ((unsigned long *) addr) + (nr >> 5); + +	*m ^= 1UL << (nr & 31); +} + +/* + * test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered.   + * It also implies a memory barrier. + */ +extern __inline__ int +test_and_set_bit(int nr, volatile void *addr) +{ +	unsigned long *m = ((unsigned long *) addr) + (nr >> 5); +	unsigned long temp, res; + +	__asm__ __volatile__( +		".set\tnoreorder\t\t# test_and_set_bit\n" +		"1:\tll\t%0, %1\n\t" +		"or\t%2, %0, %3\n\t" +		"sc\t%2, %1\n\t" +		"beqz\t%2, 1b\n\t" +		" and\t%2, %0, %3\n\t" +		".set\treorder" +		: "=&r" (temp), "=m" (*m), "=&r" (res) +		: "r" (1UL << (nr & 0x1f)), "m" (*m) +		: "memory"); + +	return res != 0; +} + +/* + * __test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered.   + * If two examples of this operation race, one can appear to succeed + * but actually fail.  You must protect multiple accesses with a lock. + */ +extern __inline__ int __test_and_set_bit(int nr, volatile void * addr) +{ +	int mask, retval; +	volatile int *a = addr; + +	a += nr >> 5; +	mask = 1 << (nr & 0x1f); +	retval = (mask & *a) != 0; +	*a |= mask; + +	return retval; +} + +/* + * test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered.   + * It also implies a memory barrier. + */ +extern __inline__ int +test_and_clear_bit(int nr, volatile void *addr) +{ +	unsigned long *m = ((unsigned long *) addr) + (nr >> 5); +	unsigned long temp, res; + +	__asm__ __volatile__( +		".set\tnoreorder\t\t# test_and_clear_bit\n" +		"1:\tll\t%0, %1\n\t" +		"or\t%2, %0, %3\n\t" +		"xor\t%2, %3\n\t" +		"sc\t%2, %1\n\t" +		"beqz\t%2, 1b\n\t" +		" and\t%2, %0, %3\n\t" +		".set\treorder" +		: "=&r" (temp), "=m" (*m), "=&r" (res) +		: "r" (1UL << (nr & 0x1f)), "m" (*m) +		: "memory"); + +	return res != 0; +} + +/* + * __test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered.   + * If two examples of this operation race, one can appear to succeed + * but actually fail.  You must protect multiple accesses with a lock. + */ +extern __inline__ int __test_and_clear_bit(int nr, volatile void * addr) +{ +	int	mask, retval; +	volatile int	*a = addr; + +	a += nr >> 5; +	mask = 1 << (nr & 0x1f); +	retval = (mask & *a) != 0; +	*a &= ~mask; + +	return retval; +} + +/* + * test_and_change_bit - Change a bit and return its new value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered.   + * It also implies a memory barrier. + */ +extern __inline__ int +test_and_change_bit(int nr, volatile void *addr) +{ +	unsigned long *m = ((unsigned long *) addr) + (nr >> 5); +	unsigned long temp, res; + +	__asm__ __volatile__( +		".set\tnoreorder\t\t# test_and_change_bit\n" +		"1:\tll\t%0, %1\n\t" +		"xor\t%2, %0, %3\n\t" +		"sc\t%2, %1\n\t" +		"beqz\t%2, 1b\n\t" +		" and\t%2, %0, %3\n\t" +		".set\treorder" +		: "=&r" (temp), "=m" (*m), "=&r" (res) +		: "r" (1UL << (nr & 0x1f)), "m" (*m) +		: "memory"); + +	return res != 0; +} + +/* + * __test_and_change_bit - Change a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered.   + * If two examples of this operation race, one can appear to succeed + * but actually fail.  You must protect multiple accesses with a lock. + */ +extern __inline__ int __test_and_change_bit(int nr, volatile void * addr) +{ +	int	mask, retval; +	volatile int	*a = addr; + +	a += nr >> 5; +	mask = 1 << (nr & 0x1f); +	retval = (mask & *a) != 0; +	*a ^= mask; + +	return retval; +} + +#else /* MIPS I */ + +/* + * set_bit - Atomically set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * This function is atomic and may not be reordered.  See __set_bit() + * if you do not require the atomic guarantees. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +extern __inline__ void set_bit(int nr, volatile void * addr) +{ +	int	mask; +	volatile int	*a = addr; +	__bi_flags; + +	a += nr >> 5; +	mask = 1 << (nr & 0x1f); +	__bi_save_and_cli(flags); +	*a |= mask; +	__bi_restore_flags(flags); +} + +/* + * __set_bit - Set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike set_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +extern __inline__ void __set_bit(int nr, volatile void * addr) +{ +	int	mask; +	volatile int	*a = addr; + +	a += nr >> 5; +	mask = 1 << (nr & 0x1f); +	*a |= mask; +} + +/* + * clear_bit - Clears a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * clear_bit() is atomic and may not be reordered.  However, it does + * not contain a memory barrier, so if it is used for locking purposes, + * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() + * in order to ensure changes are visible on other processors. + */ +extern __inline__ void clear_bit(int nr, volatile void * addr) +{ +	int	mask; +	volatile int	*a = addr; +	__bi_flags; + +	a += nr >> 5; +	mask = 1 << (nr & 0x1f); +	__bi_save_and_cli(flags); +	*a &= ~mask; +	__bi_restore_flags(flags); +} + +/* + * change_bit - Toggle a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * change_bit() is atomic and may not be reordered. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +extern __inline__ void change_bit(int nr, volatile void * addr) +{ +	int	mask; +	volatile int	*a = addr; +	__bi_flags; + +	a += nr >> 5; +	mask = 1 << (nr & 0x1f); +	__bi_save_and_cli(flags); +	*a ^= mask; +	__bi_restore_flags(flags); +} + +/* + * __change_bit - Toggle a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike change_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +extern __inline__ void __change_bit(int nr, volatile void * addr) +{ +	unsigned long * m = ((unsigned long *) addr) + (nr >> 5); + +	*m ^= 1UL << (nr & 31); +} + +/* + * test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered.   + * It also implies a memory barrier. + */ +extern __inline__ int test_and_set_bit(int nr, volatile void * addr) +{ +	int	mask, retval; +	volatile int	*a = addr; +	__bi_flags; + +	a += nr >> 5; +	mask = 1 << (nr & 0x1f); +	__bi_save_and_cli(flags); +	retval = (mask & *a) != 0; +	*a |= mask; +	__bi_restore_flags(flags); + +	return retval; +} + +/* + * __test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered.   + * If two examples of this operation race, one can appear to succeed + * but actually fail.  You must protect multiple accesses with a lock. + */ +extern __inline__ int __test_and_set_bit(int nr, volatile void * addr) +{ +	int	mask, retval; +	volatile int	*a = addr; + +	a += nr >> 5; +	mask = 1 << (nr & 0x1f); +	retval = (mask & *a) != 0; +	*a |= mask; + +	return retval; +} + +/* + * test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered.   + * It also implies a memory barrier. + */ +extern __inline__ int test_and_clear_bit(int nr, volatile void * addr) +{ +	int	mask, retval; +	volatile int	*a = addr; +	__bi_flags; + +	a += nr >> 5; +	mask = 1 << (nr & 0x1f); +	__bi_save_and_cli(flags); +	retval = (mask & *a) != 0; +	*a &= ~mask; +	__bi_restore_flags(flags); + +	return retval; +} + +/* + * __test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered.   + * If two examples of this operation race, one can appear to succeed + * but actually fail.  You must protect multiple accesses with a lock. + */ +extern __inline__ int __test_and_clear_bit(int nr, volatile void * addr) +{ +	int	mask, retval; +	volatile int	*a = addr; + +	a += nr >> 5; +	mask = 1 << (nr & 0x1f); +	retval = (mask & *a) != 0; +	*a &= ~mask; + +	return retval; +} + +/* + * test_and_change_bit - Change a bit and return its new value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered.   + * It also implies a memory barrier. + */ +extern __inline__ int test_and_change_bit(int nr, volatile void * addr) +{ +	int	mask, retval; +	volatile int	*a = addr; +	__bi_flags; + +	a += nr >> 5; +	mask = 1 << (nr & 0x1f); +	__bi_save_and_cli(flags); +	retval = (mask & *a) != 0; +	*a ^= mask; +	__bi_restore_flags(flags); + +	return retval; +} + +/* + * __test_and_change_bit - Change a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered.   + * If two examples of this operation race, one can appear to succeed + * but actually fail.  You must protect multiple accesses with a lock. + */ +extern __inline__ int __test_and_change_bit(int nr, volatile void * addr) +{ +	int	mask, retval; +	volatile int	*a = addr; + +	a += nr >> 5; +	mask = 1 << (nr & 0x1f); +	retval = (mask & *a) != 0; +	*a ^= mask; + +	return retval; +} + +#undef __bi_flags +#undef __bi_cli +#undef __bi_save_flags +#undef __bi_restore_flags + +#endif /* MIPS I */ + +/* + * test_bit - Determine whether a bit is set + * @nr: bit number to test + * @addr: Address to start counting from + */ +extern __inline__ int test_bit(int nr, volatile void *addr) +{ +	return ((1UL << (nr & 31)) & (((const unsigned int *) addr)[nr >> 5])) != 0; +} + +#ifndef __MIPSEB__ + +/* Little endian versions. */ + +/* + * 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 + * + * Returns the bit-number of the first zero bit, not the number of the byte + * containing a bit. + */ +extern __inline__ int find_first_zero_bit (void *addr, unsigned size) +{ +	unsigned long dummy; +	int res; + +	if (!size) +		return 0; + +	__asm__ (".set\tnoreorder\n\t" +		".set\tnoat\n" +		"1:\tsubu\t$1,%6,%0\n\t" +		"blez\t$1,2f\n\t" +		"lw\t$1,(%5)\n\t" +		"addiu\t%5,4\n\t" +#if (_MIPS_ISA == _MIPS_ISA_MIPS2 ) || (_MIPS_ISA == _MIPS_ISA_MIPS3 ) || \ +    (_MIPS_ISA == _MIPS_ISA_MIPS4 ) || (_MIPS_ISA == _MIPS_ISA_MIPS5 ) || \ +    (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64) +		"beql\t%1,$1,1b\n\t" +		"addiu\t%0,32\n\t" +#else +		"addiu\t%0,32\n\t" +		"beq\t%1,$1,1b\n\t" +		"nop\n\t" +		"subu\t%0,32\n\t" +#endif +#ifdef __MIPSEB__ +#error "Fix this for big endian" +#endif /* __MIPSEB__ */ +		"li\t%1,1\n" +		"1:\tand\t%2,$1,%1\n\t" +		"beqz\t%2,2f\n\t" +		"sll\t%1,%1,1\n\t" +		"bnez\t%1,1b\n\t" +		"add\t%0,%0,1\n\t" +		".set\tat\n\t" +		".set\treorder\n" +		"2:" +		: "=r" (res), "=r" (dummy), "=r" (addr) +		: "0" ((signed int) 0), "1" ((unsigned int) 0xffffffff), +		  "2" (addr), "r" (size) +		: "$1"); + +	return res; +} + +/* + * find_next_zero_bit - find the first zero 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 + */ +extern __inline__ int find_next_zero_bit (void * addr, int size, int offset) +{ +	unsigned int *p = ((unsigned int *) addr) + (offset >> 5); +	int set = 0, bit = offset & 31, res; +	unsigned long dummy; +	 +	if (bit) { +		/* +		 * Look for zero in first byte +		 */ +#ifdef __MIPSEB__ +#error "Fix this for big endian byte order" +#endif +		__asm__(".set\tnoreorder\n\t" +			".set\tnoat\n" +			"1:\tand\t$1,%4,%1\n\t" +			"beqz\t$1,1f\n\t" +			"sll\t%1,%1,1\n\t" +			"bnez\t%1,1b\n\t" +			"addiu\t%0,1\n\t" +			".set\tat\n\t" +			".set\treorder\n" +			"1:" +			: "=r" (set), "=r" (dummy) +			: "0" (0), "1" (1 << bit), "r" (*p) +			: "$1"); +		if (set < (32 - bit)) +			return set + offset; +		set = 32 - bit; +		p++; +	} +	/* +	 * No zero yet, search remaining full bytes for a zero +	 */ +	res = find_first_zero_bit(p, size - 32 * (p - (unsigned int *) addr)); +	return offset + set + res; +} + +#endif /* !(__MIPSEB__) */ + +/* + * ffz - find first zero in word. + * @word: The word to search + * + * Undefined if no zero exists, so code should check against ~0UL first. + */ +extern __inline__ unsigned long ffz(unsigned long word) +{ +	unsigned int	__res; +	unsigned int	mask = 1; + +	__asm__ ( +		".set\tnoreorder\n\t" +		".set\tnoat\n\t" +		"move\t%0,$0\n" +		"1:\tand\t$1,%2,%1\n\t" +		"beqz\t$1,2f\n\t" +		"sll\t%1,1\n\t" +		"bnez\t%1,1b\n\t" +		"addiu\t%0,1\n\t" +		".set\tat\n\t" +		".set\treorder\n" +		"2:\n\t" +		: "=&r" (__res), "=r" (mask) +		: "r" (word), "1" (mask) +		: "$1"); + +	return __res; +} + +#ifdef __KERNEL__ + +/** + * ffs - find first bit set + * @x: the word to search + * + * This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ + +#define ffs(x) generic_ffs(x) + +/* + * hweightN - returns the hamming weight of a N-bit word + * @x: the word to weigh + * + * The Hamming Weight of a number is the total number of bits set in it. + */ + +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + +#endif /* __KERNEL__ */ + +#ifdef __MIPSEB__ +/* + * find_next_zero_bit - find the first zero 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 + */ +extern __inline__ int find_next_zero_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 >> (32-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 << size; +found_middle: +	return result + ffz(tmp); +} + +/* Linus sez that gcc can optimize the following correctly, we'll see if this + * holds on the Sparc as it does for the ALPHA. + */ + +#if 0 /* Fool kernel-doc since it doesn't do macros yet */ +/* + * 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 + * + * Returns the bit-number of the first zero bit, not the number of the byte + * containing a bit. + */ +extern int find_first_zero_bit (void *addr, unsigned size); +#endif + +#define find_first_zero_bit(addr, size) \ +        find_next_zero_bit((addr), (size), 0) + +#endif /* (__MIPSEB__) */ + +/* Now for the ext2 filesystem bit operations and helper routines. */ + +#ifdef __MIPSEB__ +extern __inline__ int ext2_set_bit(int nr, void * addr) +{ +	int		mask, retval, flags; +	unsigned char	*ADDR = (unsigned char *) addr; + +	ADDR += nr >> 3; +	mask = 1 << (nr & 0x07); +	save_and_cli(flags); +	retval = (mask & *ADDR) != 0; +	*ADDR |= mask; +	restore_flags(flags); +	return retval; +} + +extern __inline__ int ext2_clear_bit(int nr, void * addr) +{ +	int		mask, retval, flags; +	unsigned char	*ADDR = (unsigned char *) addr; + +	ADDR += nr >> 3; +	mask = 1 << (nr & 0x07); +	save_and_cli(flags); +	retval = (mask & *ADDR) != 0; +	*ADDR &= ~mask; +	restore_flags(flags); +	return retval; +} + +extern __inline__ int ext2_test_bit(int nr, const void * addr) +{ +	int			mask; +	const unsigned char	*ADDR = (const unsigned char *) addr; + +	ADDR += nr >> 3; +	mask = 1 << (nr & 0x07); +	return ((mask & *ADDR) != 0); +} + +#define ext2_find_first_zero_bit(addr, size) \ +        ext2_find_next_zero_bit((addr), (size), 0) + +extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long 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) { +		/* We hold the little endian value in tmp, but then the +		 * shift is illegal. So we could keep a big endian value +		 * in tmp, like this: +		 * +		 * tmp = __swab32(*(p++)); +		 * tmp |= ~0UL >> (32-offset); +		 * +		 * but this would decrease preformance, so we change the +		 * shift: +		 */ +		tmp = *(p++); +		tmp |= __swab32(~0UL >> (32-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 is little endian, so we would have to swab the shift, +	 * see above. But then we have to swab tmp below for ffz, so +	 * we might as well do this here. +	 */ +	return result + ffz(__swab32(tmp) | (~0UL << size)); +found_middle: +	return result + ffz(__swab32(tmp)); +} +#else /* !(__MIPSEB__) */ + +/* Native ext2 byte ordering, just collapse using defines. */ +#define ext2_set_bit(nr, addr) test_and_set_bit((nr), (addr)) +#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr), (addr)) +#define ext2_test_bit(nr, addr) test_bit((nr), (addr)) +#define ext2_find_first_zero_bit(addr, size) find_first_zero_bit((addr), (size)) +#define ext2_find_next_zero_bit(addr, size, offset) \ +                find_next_zero_bit((addr), (size), (offset)) +  +#endif /* !(__MIPSEB__) */ + +/* + * Bitmap functions for the minix filesystem. + * FIXME: These assume that Minix uses the native byte/bitorder. + * This limits the Minix filesystem's value for data exchange very much. + */ +#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr) +#define minix_set_bit(nr,addr) set_bit(nr,addr) +#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr) +#define minix_test_bit(nr,addr) test_bit(nr,addr) +#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) + +#endif /* _ASM_BITOPS_H */ diff --git a/include/asm-mips/byteorder.h b/include/asm-mips/byteorder.h new file mode 100644 index 000000000..b9604cf20 --- /dev/null +++ b/include/asm-mips/byteorder.h @@ -0,0 +1,31 @@ +/* $Id: byteorder.h,v 1.8 1998/11/02 09:29:32 ralf Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) by Ralf Baechle + */ +#ifndef _MIPS_BYTEORDER_H +#define _MIPS_BYTEORDER_H + +#include <asm/types.h> + +#ifdef __GNUC__ + +#if !defined(__STRICT_ANSI__) || defined(__KERNEL__) +#  define __BYTEORDER_HAS_U64__ +#  define __SWAB_64_THRU_32__ +#endif + +#endif /* __GNUC__ */ + +#if defined (__MIPSEB__) +#  include <linux/byteorder/big_endian.h> +#elif defined (__MIPSEL__) +#  include <linux/byteorder/little_endian.h> +#else +#  error "MIPS, but neither __MIPSEB__, nor __MIPSEL__???" +#endif + +#endif /* _MIPS_BYTEORDER_H */ diff --git a/include/asm-mips/cachectl.h b/include/asm-mips/cachectl.h new file mode 100644 index 000000000..9cc2b8721 --- /dev/null +++ b/include/asm-mips/cachectl.h @@ -0,0 +1,24 @@ +/* + * cachectl.h -- defines for MIPS cache control system calls + * + * Copyright (C) 1994, 1995, 1996 by Ralf Baechle + */ +#ifndef	__ASM_MIPS_CACHECTL +#define	__ASM_MIPS_CACHECTL + +/* + * Options for cacheflush system call + */ +#define	ICACHE	(1<<0)		/* flush instruction cache        */ +#define	DCACHE	(1<<1)		/* writeback and flush data cache */ +#define	BCACHE	(ICACHE|DCACHE)	/* flush both caches              */ + +/* + * Caching modes for the cachectl(2) call + * + * cachectl(2) is currently not supported and returns ENOSYS. + */ +#define CACHEABLE	0	/* make pages cacheable */ +#define UNCACHEABLE	1	/* make pages uncacheable */ + +#endif	/* __ASM_MIPS_CACHECTL */ diff --git a/include/asm-mips/cacheops.h b/include/asm-mips/cacheops.h new file mode 100644 index 000000000..66b0b361f --- /dev/null +++ b/include/asm-mips/cacheops.h @@ -0,0 +1,47 @@ +/* + * Cache operations for the cache instruction. + * + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * (C) Copyright 1996, 1997 by Ralf Baechle + */ +#ifndef	__ASM_MIPS_CACHEOPS_H +#define	__ASM_MIPS_CACHEOPS_H + +/* + * Cache Operations + */ +#define Index_Invalidate_I      0x00 +#define Index_Writeback_Inv_D   0x01 +#define Index_Invalidate_SI     0x02 +#define Index_Writeback_Inv_SD  0x03 +#define Index_Load_Tag_I	0x04 +#define Index_Load_Tag_D	0x05 +#define Index_Load_Tag_SI	0x06 +#define Index_Load_Tag_SD	0x07 +#define Index_Store_Tag_I	0x08 +#define Index_Store_Tag_D	0x09 +#define Index_Store_Tag_SI	0x0A +#define Index_Store_Tag_SD	0x0B +#define Create_Dirty_Excl_D	0x0d +#define Create_Dirty_Excl_SD	0x0f +#define Hit_Invalidate_I	0x10 +#define Hit_Invalidate_D	0x11 +#define Hit_Invalidate_SI	0x12 +#define Hit_Invalidate_SD	0x13 +#define Fill			0x14 +#define Hit_Writeback_Inv_D	0x15 +					/* 0x16 is unused */ +#define Hit_Writeback_Inv_SD	0x17 +#define Hit_Writeback_I		0x18 +#define Hit_Writeback_D		0x19 +					/* 0x1a is unused */ +#define Hit_Writeback_SD	0x1b +					/* 0x1c is unused */ +					/* 0x1e is unused */ +#define Hit_Set_Virtual_SI	0x1e +#define Hit_Set_Virtual_SD	0x1f + +#endif	/* __ASM_MIPS_CACHEOPS_H */ diff --git a/include/asm-mips/global_data.h b/include/asm-mips/global_data.h new file mode 100644 index 000000000..72d0cb074 --- /dev/null +++ b/include/asm-mips/global_data.h @@ -0,0 +1,58 @@ +/* + * (C) Copyright 2002-2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef	__ASM_GBL_DATA_H +#define __ASM_GBL_DATA_H + +#include <asm/regdef.h> + +/* + * The following data structure is placed in some memory wich is + * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or + * some locked parts of the data cache) to allow for a minimum set of + * global variables during system initialization (until we have set + * up the memory controller so that we can use RAM). + * + * Keep it *SMALL* and remember to set CFG_GBL_DATA_SIZE > sizeof(gd_t) + */ + +typedef	struct	global_data { +	bd_t		*bd; +	unsigned long	flags; +	unsigned long	baudrate; +	unsigned long	have_console;	/* serial_init() was called */ +	unsigned long	ram_size;	/* RAM size */ +	unsigned long	reloc_off;	/* Relocation Offset */ +	unsigned long	env_addr;	/* Address  of Environment struct */ +	unsigned long	env_valid;	/* Checksum of Environment valid? */ +} gd_t; + +/* + * Global Data Flags + */ +#define	GD_FLG_RELOC	0x00001		/* Code was relocated to RAM     */ +#define	GD_FLG_DEVINIT	0x00002		/* Devices have been initialized */ + +#define DECLARE_GLOBAL_DATA_PTR     register gd_t *gd asm ("k0") + +#endif /* __ASM_GBL_DATA_H */ diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h new file mode 100644 index 000000000..9a7aaf7f4 --- /dev/null +++ b/include/asm-mips/io.h @@ -0,0 +1,450 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 1995 Waldorf GmbH + * Copyright (C) 1994 - 2000 Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 FSMLabs, Inc. + */ +#ifndef _ASM_IO_H +#define _ASM_IO_H + +#include <linux/config.h> +#if 0 +#include <linux/pagemap.h> +#endif +#include <asm/addrspace.h> +#include <asm/byteorder.h> + +/* + * Slowdown I/O port space accesses for antique hardware. + */ +#undef CONF_SLOWDOWN_IO + +/* + * Sane hardware offers swapping of I/O space accesses in hardware; less + * sane hardware forces software to fiddle with this ... + */ +#if defined(CONFIG_SWAP_IO_SPACE) && defined(__MIPSEB__) + +#define __ioswab8(x) (x) +#define __ioswab16(x) swab16(x) +#define __ioswab32(x) swab32(x) + +#else + +#define __ioswab8(x) (x) +#define __ioswab16(x) (x) +#define __ioswab32(x) (x) + +#endif + +/* + * This file contains the definitions for the MIPS counterpart of the + * x86 in/out instructions. This heap of macros and C results in much + * better code than the approach of doing it in plain C.  The macros + * result in code that is to fast for certain hardware.  On the other + * side the performance of the string functions should be improved for + * sake of certain devices like EIDE disks that do highspeed polled I/O. + * + *   Ralf + * + * This file contains the definitions for the x86 IO instructions + * inb/inw/inl/outb/outw/outl and the "string versions" of the same + * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing" + * versions of the single-IO instructions (inb_p/inw_p/..). + * + * This file is not meant to be obfuscating: it's just complicated + * to (a) handle it all in a way that makes gcc able to optimize it + * as well as possible and (b) trying to avoid writing the same thing + * over and over again with slight variations and possibly making a + * mistake somewhere. + */ + +/* + * On MIPS I/O ports are memory mapped, so we access them using normal + * load/store instructions. mips_io_port_base is the virtual address to + * which all ports are being mapped.  For sake of efficiency some code + * assumes that this is an address that can be loaded with a single lui + * instruction, so the lower 16 bits must be zero.  Should be true on + * on any sane architecture; generic code does not use this assumption. + */ +extern unsigned long mips_io_port_base; + +/* + * Thanks to James van Artsdalen for a better timing-fix than + * the two short jumps: using outb's to a nonexistent port seems + * to guarantee better timings even on fast machines. + * + * On the other hand, I'd like to be sure of a non-existent port: + * I feel a bit unsafe about using 0x80 (should be safe, though) + * + *		Linus + * + */ + +#define __SLOW_DOWN_IO \ +	__asm__ __volatile__( \ +		"sb\t$0,0x80(%0)" \ +		: : "r" (mips_io_port_base)); + +#ifdef CONF_SLOWDOWN_IO +#ifdef REALLY_SLOW_IO +#define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; } +#else +#define SLOW_DOWN_IO __SLOW_DOWN_IO +#endif +#else +#define SLOW_DOWN_IO +#endif + +/* + * Change virtual addresses to physical addresses and vv. + * These are trivial on the 1:1 Linux/MIPS mapping + */ +extern inline unsigned long virt_to_phys(volatile void * address) +{ +	return PHYSADDR(address); +} + +extern inline void * phys_to_virt(unsigned long address) +{ +	return (void *)KSEG0ADDR(address); +} + +/* + * IO bus memory addresses are also 1:1 with the physical address + */ +extern inline unsigned long virt_to_bus(volatile void * address) +{ +	return PHYSADDR(address); +} + +extern inline void * bus_to_virt(unsigned long address) +{ +	return (void *)KSEG0ADDR(address); +} + +/* + * isa_slot_offset is the address where E(ISA) busaddress 0 is mapped + * for the processor. + */ +extern unsigned long isa_slot_offset; + +extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags); + +#if 0 +extern inline void *ioremap(unsigned long offset, unsigned long size) +{ +	return __ioremap(offset, size, _CACHE_UNCACHED); +} + +extern inline void *ioremap_nocache(unsigned long offset, unsigned long size) +{ +	return __ioremap(offset, size, _CACHE_UNCACHED); +} + +extern void iounmap(void *addr); +#endif + +/* + * XXX We need system specific versions of these to handle EISA address bits + * 24-31 on SNI. + * XXX more SNI hacks. + */ +#define readb(addr) (*(volatile unsigned char *)(addr)) +#define readw(addr) __ioswab16((*(volatile unsigned short *)(addr))) +#define readl(addr) __ioswab32((*(volatile unsigned int *)(addr))) +#define __raw_readb readb +#define __raw_readw readw +#define __raw_readl readl + +#define writeb(b,addr) (*(volatile unsigned char *)(addr)) = (b) +#define writew(b,addr) (*(volatile unsigned short *)(addr)) = (__ioswab16(b)) +#define writel(b,addr) (*(volatile unsigned int *)(addr)) = (__ioswab32(b)) +#define __raw_writeb writeb +#define __raw_writew writew +#define __raw_writel writel + +#define memset_io(a,b,c)	memset((void *)(a),(b),(c)) +#define memcpy_fromio(a,b,c)	memcpy((a),(void *)(b),(c)) +#define memcpy_toio(a,b,c)	memcpy((void *)(a),(b),(c)) + +/* END SNI HACKS ... */ + +/* + * ISA space is 'always mapped' on currently supported MIPS systems, no need + * to explicitly ioremap() it. The fact that the ISA IO space is mapped + * to PAGE_OFFSET is pure coincidence - it does not mean ISA values + * are physical addresses. The following constant pointer can be + * used as the IO-area pointer (it can be iounmapped as well, so the + * analogy with PCI is quite large): + */ +#define __ISA_IO_base ((char *)(PAGE_OFFSET)) + +#define isa_readb(a) readb(a) +#define isa_readw(a) readw(a) +#define isa_readl(a) readl(a) +#define isa_writeb(b,a) writeb(b,a) +#define isa_writew(w,a) writew(w,a) +#define isa_writel(l,a) writel(l,a) + +#define isa_memset_io(a,b,c)     memset_io((a),(b),(c)) +#define isa_memcpy_fromio(a,b,c) memcpy_fromio((a),(b),(c)) +#define isa_memcpy_toio(a,b,c)   memcpy_toio((a),(b),(c)) + +/* + * We don't have csum_partial_copy_fromio() yet, so we cheat here and + * just copy it. The net code will then do the checksum later. + */ +#define eth_io_copy_and_sum(skb,src,len,unused) memcpy_fromio((skb)->data,(src),(len)) +#define isa_eth_io_copy_and_sum(a,b,c,d) eth_copy_and_sum((a),(b),(c),(d)) + +static inline int check_signature(unsigned long io_addr, +                                  const unsigned char *signature, int length) +{ +	int retval = 0; +	do { +		if (readb(io_addr) != *signature) +			goto out; +		io_addr++; +		signature++; +		length--; +	} while (length); +	retval = 1; +out: +	return retval; +} +#define isa_check_signature(io, s, l) check_signature(i,s,l) + +/* + * Talk about misusing macros.. + */ + +#define __OUT1(s) \ +extern inline void __out##s(unsigned int value, unsigned int port) { + +#define __OUT2(m) \ +__asm__ __volatile__ ("s" #m "\t%0,%1(%2)" + +#define __OUT(m,s,w) \ +__OUT1(s) __OUT2(m) : : "r" (__ioswab##w(value)), "i" (0), "r" (mips_io_port_base+port)); } \ +__OUT1(s##c) __OUT2(m) : : "r" (__ioswab##w(value)), "ir" (port), "r" (mips_io_port_base)); } \ +__OUT1(s##_p) __OUT2(m) : : "r" (__ioswab##w(value)), "i" (0), "r" (mips_io_port_base+port)); \ +	SLOW_DOWN_IO; } \ +__OUT1(s##c_p) __OUT2(m) : : "r" (__ioswab##w(value)), "ir" (port), "r" (mips_io_port_base)); \ +	SLOW_DOWN_IO; } + +#define __IN1(t,s) \ +extern __inline__ t __in##s(unsigned int port) { t _v; + +/* + * Required nops will be inserted by the assembler + */ +#define __IN2(m) \ +__asm__ __volatile__ ("l" #m "\t%0,%1(%2)" + +#define __IN(t,m,s,w) \ +__IN1(t,s) __IN2(m) : "=r" (_v) : "i" (0), "r" (mips_io_port_base+port)); return __ioswab##w(_v); } \ +__IN1(t,s##c) __IN2(m) : "=r" (_v) : "ir" (port), "r" (mips_io_port_base)); return __ioswab##w(_v); } \ +__IN1(t,s##_p) __IN2(m) : "=r" (_v) : "i" (0), "r" (mips_io_port_base+port)); SLOW_DOWN_IO; return __ioswab##w(_v); } \ +__IN1(t,s##c_p) __IN2(m) : "=r" (_v) : "ir" (port), "r" (mips_io_port_base)); SLOW_DOWN_IO; return __ioswab##w(_v); } + +#define __INS1(s) \ +extern inline void __ins##s(unsigned int port, void * addr, unsigned long count) { + +#define __INS2(m) \ +if (count) \ +__asm__ __volatile__ ( \ +	".set\tnoreorder\n\t" \ +	".set\tnoat\n" \ +	"1:\tl" #m "\t$1,%4(%5)\n\t" \ +	"subu\t%1,1\n\t" \ +	"s" #m "\t$1,(%0)\n\t" \ +	"bne\t$0,%1,1b\n\t" \ +	"addiu\t%0,%6\n\t" \ +	".set\tat\n\t" \ +	".set\treorder" + +#define __INS(m,s,i) \ +__INS1(s) __INS2(m) \ +	: "=r" (addr), "=r" (count) \ +	: "0" (addr), "1" (count), "i" (0), \ +	  "r" (mips_io_port_base+port), "I" (i) \ +	: "$1");} \ +__INS1(s##c) __INS2(m) \ +	: "=r" (addr), "=r" (count) \ +	: "0" (addr), "1" (count), "ir" (port), \ +	  "r" (mips_io_port_base), "I" (i) \ +	: "$1");} + +#define __OUTS1(s) \ +extern inline void __outs##s(unsigned int port, const void * addr, unsigned long count) { + +#define __OUTS2(m) \ +if (count) \ +__asm__ __volatile__ ( \ +        ".set\tnoreorder\n\t" \ +        ".set\tnoat\n" \ +        "1:\tl" #m "\t$1,(%0)\n\t" \ +        "subu\t%1,1\n\t" \ +        "s" #m "\t$1,%4(%5)\n\t" \ +        "bne\t$0,%1,1b\n\t" \ +        "addiu\t%0,%6\n\t" \ +        ".set\tat\n\t" \ +        ".set\treorder" + +#define __OUTS(m,s,i) \ +__OUTS1(s) __OUTS2(m) \ +	: "=r" (addr), "=r" (count) \ +	: "0" (addr), "1" (count), "i" (0), "r" (mips_io_port_base+port), "I" (i) \ +	: "$1");} \ +__OUTS1(s##c) __OUTS2(m) \ +	: "=r" (addr), "=r" (count) \ +	: "0" (addr), "1" (count), "ir" (port), "r" (mips_io_port_base), "I" (i) \ +	: "$1");} + +__IN(unsigned char,b,b,8) +__IN(unsigned short,h,w,16) +__IN(unsigned int,w,l,32) + +__OUT(b,b,8) +__OUT(h,w,16) +__OUT(w,l,32) + +__INS(b,b,1) +__INS(h,w,2) +__INS(w,l,4) + +__OUTS(b,b,1) +__OUTS(h,w,2) +__OUTS(w,l,4) + + +/* + * Note that due to the way __builtin_constant_p() works, you + *  - can't use it inside an inline function (it will never be true) + *  - you don't have to worry about side effects within the __builtin.. + */ +#define outb(val,port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ +	__outbc((val),(port)) : \ +	__outb((val),(port))) + +#define inb(port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ +	__inbc(port) : \ +	__inb(port)) + +#define outb_p(val,port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ +	__outbc_p((val),(port)) : \ +	__outb_p((val),(port))) + +#define inb_p(port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ +	__inbc_p(port) : \ +	__inb_p(port)) + +#define outw(val,port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ +	__outwc((val),(port)) : \ +	__outw((val),(port))) + +#define inw(port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ +	__inwc(port) : \ +	__inw(port)) + +#define outw_p(val,port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ +	__outwc_p((val),(port)) : \ +	__outw_p((val),(port))) + +#define inw_p(port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ +	__inwc_p(port) : \ +	__inw_p(port)) + +#define outl(val,port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ +	__outlc((val),(port)) : \ +	__outl((val),(port))) + +#define inl(port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ +	__inlc(port) : \ +	__inl(port)) + +#define outl_p(val,port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ +	__outlc_p((val),(port)) : \ +	__outl_p((val),(port))) + +#define inl_p(port) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ +	__inlc_p(port) : \ +	__inl_p(port)) + + +#define outsb(port,addr,count) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ +	__outsbc((port),(addr),(count)) : \ +	__outsb ((port),(addr),(count))) + +#define insb(port,addr,count) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ +	__insbc((port),(addr),(count)) : \ +	__insb((port),(addr),(count))) + +#define outsw(port,addr,count) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ +	__outswc((port),(addr),(count)) : \ +	__outsw ((port),(addr),(count))) + +#define insw(port,addr,count) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ +	__inswc((port),(addr),(count)) : \ +	__insw((port),(addr),(count))) + +#define outsl(port,addr,count) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ +	__outslc((port),(addr),(count)) : \ +	__outsl ((port),(addr),(count))) + +#define insl(port,addr,count) \ +((__builtin_constant_p((port)) && (port) < 32768) ? \ +	__inslc((port),(addr),(count)) : \ +	__insl((port),(addr),(count))) + +#define IO_SPACE_LIMIT 0xffff + +/* + * The caches on some architectures aren't dma-coherent and have need to + * handle this in software.  There are three types of operations that + * can be applied to dma buffers. + * + *  - dma_cache_wback_inv(start, size) makes caches and coherent by + *    writing the content of the caches back to memory, if necessary. + *    The function also invalidates the affected part of the caches as + *    necessary before DMA transfers from outside to memory. + *  - dma_cache_wback(start, size) makes caches and coherent by + *    writing the content of the caches back to memory, if necessary. + *    The function also invalidates the affected part of the caches as + *    necessary before DMA transfers from outside to memory. + *  - dma_cache_inv(start, size) invalidates the affected parts of the + *    caches.  Dirty lines of the caches may be written back or simply + *    be discarded.  This operation is necessary before dma operations + *    to the memory. + */ +extern void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size); +extern void (*_dma_cache_wback)(unsigned long start, unsigned long size); +extern void (*_dma_cache_inv)(unsigned long start, unsigned long size); + +#define dma_cache_wback_inv(start,size)	_dma_cache_wback_inv(start,size) +#define dma_cache_wback(start,size)	_dma_cache_wback(start,size) +#define dma_cache_inv(start,size)	_dma_cache_inv(start,size) + +#endif /* _ASM_IO_H */ diff --git a/include/asm-mips/isadep.h b/include/asm-mips/isadep.h new file mode 100644 index 000000000..3cd1eb8eb --- /dev/null +++ b/include/asm-mips/isadep.h @@ -0,0 +1,35 @@ +/* + * Various ISA level dependant constants. + * Most of the following constants reflect the different layout + * of Coprocessor 0 registers. + * + * Copyright (c) 1998 Harald Koerfgen + */ +#include <linux/config.h> + +#ifndef __ASM_ISADEP_H +#define __ASM_ISADEP_H + +#if defined(CONFIG_CPU_R3000) +/* + * R2000 or R3000 + */ + +/* + * kernel or user mode? (CP0_STATUS) + */ +#define KU_MASK 0x08 +#define	KU_USER 0x08 +#define KU_KERN 0x00 + +#else +/* + * kernel or user mode? + */ +#define KU_MASK 0x18 +#define	KU_USER 0x10 +#define KU_KERN 0x00 + +#endif + +#endif /* __ASM_ISADEP_H */ diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h new file mode 100644 index 000000000..56fc3da78 --- /dev/null +++ b/include/asm-mips/mipsregs.h @@ -0,0 +1,540 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle + * Copyright (C) 2000 Silicon Graphics, Inc. + * Modified for further R[236]000 support by Paul M. Antoine, 1996. + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved. + */ +#ifndef _ASM_MIPSREGS_H +#define _ASM_MIPSREGS_H + +#if 0 +#include <linux/linkage.h> +#endif + +/* + * The following macros are especially useful for __asm__ + * inline assembler. + */ +#ifndef __STR +#define __STR(x) #x +#endif +#ifndef STR +#define STR(x) __STR(x) +#endif + +/* + * Coprocessor 0 register names + */ +#define CP0_INDEX $0 +#define CP0_RANDOM $1 +#define CP0_ENTRYLO0 $2 +#define CP0_ENTRYLO1 $3 +#define CP0_CONF $3 +#define CP0_CONTEXT $4 +#define CP0_PAGEMASK $5 +#define CP0_WIRED $6 +#define CP0_INFO $7 +#define CP0_BADVADDR $8 +#define CP0_COUNT $9 +#define CP0_ENTRYHI $10 +#define CP0_COMPARE $11 +#define CP0_STATUS $12 +#define CP0_CAUSE $13 +#define CP0_EPC $14 +#define CP0_PRID $15 +#define CP0_CONFIG $16 +#define CP0_LLADDR $17 +#define CP0_WATCHLO $18 +#define CP0_WATCHHI $19 +#define CP0_XCONTEXT $20 +#define CP0_FRAMEMASK $21 +#define CP0_DIAGNOSTIC $22 +#define CP0_PERFORMANCE $25 +#define CP0_ECC $26 +#define CP0_CACHEERR $27 +#define CP0_TAGLO $28 +#define CP0_TAGHI $29 +#define CP0_ERROREPC $30 + +/* + * R4640/R4650 cp0 register names.  These registers are listed + * here only for completeness; without MMU these CPUs are not useable + * by Linux.  A future ELKS port might take make Linux run on them + * though ... + */ +#define CP0_IBASE $0 +#define CP0_IBOUND $1 +#define CP0_DBASE $2 +#define CP0_DBOUND $3 +#define CP0_CALG $17 +#define CP0_IWATCH $18 +#define CP0_DWATCH $19 + +/*  + * Coprocessor 0 Set 1 register names + */ +#define CP0_S1_DERRADDR0  $26 +#define CP0_S1_DERRADDR1  $27 +#define CP0_S1_INTCONTROL $20 +/* + * Coprocessor 1 (FPU) register names + */ +#define CP1_REVISION   $0 +#define CP1_STATUS     $31 + +/* + * FPU Status Register Values + */ +/* + * Status Register Values + */ + +#define FPU_CSR_FLUSH   0x01000000      /* flush denormalised results to 0 */ +#define FPU_CSR_COND    0x00800000      /* $fcc0 */ +#define FPU_CSR_COND0   0x00800000      /* $fcc0 */ +#define FPU_CSR_COND1   0x02000000      /* $fcc1 */ +#define FPU_CSR_COND2   0x04000000      /* $fcc2 */ +#define FPU_CSR_COND3   0x08000000      /* $fcc3 */ +#define FPU_CSR_COND4   0x10000000      /* $fcc4 */ +#define FPU_CSR_COND5   0x20000000      /* $fcc5 */ +#define FPU_CSR_COND6   0x40000000      /* $fcc6 */ +#define FPU_CSR_COND7   0x80000000      /* $fcc7 */ + +/* + * X the exception cause indicator + * E the exception enable + * S the sticky/flag bit +*/ +#define FPU_CSR_ALL_X 0x0003f000 +#define FPU_CSR_UNI_X   0x00020000 +#define FPU_CSR_INV_X   0x00010000 +#define FPU_CSR_DIV_X   0x00008000 +#define FPU_CSR_OVF_X   0x00004000 +#define FPU_CSR_UDF_X   0x00002000 +#define FPU_CSR_INE_X   0x00001000 + +#define FPU_CSR_ALL_E   0x00000f80 +#define FPU_CSR_INV_E   0x00000800 +#define FPU_CSR_DIV_E   0x00000400 +#define FPU_CSR_OVF_E   0x00000200 +#define FPU_CSR_UDF_E   0x00000100 +#define FPU_CSR_INE_E   0x00000080 + +#define FPU_CSR_ALL_S   0x0000007c +#define FPU_CSR_INV_S   0x00000040 +#define FPU_CSR_DIV_S   0x00000020 +#define FPU_CSR_OVF_S   0x00000010 +#define FPU_CSR_UDF_S   0x00000008 +#define FPU_CSR_INE_S   0x00000004 + +/* rounding mode */ +#define FPU_CSR_RN      0x0     /* nearest */ +#define FPU_CSR_RZ      0x1     /* towards zero */ +#define FPU_CSR_RU      0x2     /* towards +Infinity */ +#define FPU_CSR_RD      0x3     /* towards -Infinity */ + + +/* + * Values for PageMask register + */ +#include <linux/config.h> +#ifdef CONFIG_CPU_VR41XX +#define PM_1K   0x00000000 +#define PM_4K   0x00001800 +#define PM_16K  0x00007800 +#define PM_64K  0x0001f800 +#define PM_256K 0x0007f800 +#else +#define PM_4K   0x00000000 +#define PM_16K  0x00006000 +#define PM_64K  0x0001e000 +#define PM_256K 0x0007e000 +#define PM_1M   0x001fe000 +#define PM_4M   0x007fe000 +#define PM_16M  0x01ffe000 +#endif + +/* + * Values used for computation of new tlb entries + */ +#define PL_4K   12 +#define PL_16K  14 +#define PL_64K  16 +#define PL_256K 18 +#define PL_1M   20 +#define PL_4M   22 +#define PL_16M  24 + +/* + * Macros to access the system control coprocessor + */ +#define read_32bit_cp0_register(source)                         \ +({ int __res;                                                   \ +        __asm__ __volatile__(                                   \ +	".set\tpush\n\t"					\ +	".set\treorder\n\t"					\ +        "mfc0\t%0,"STR(source)"\n\t"                            \ +	".set\tpop"						\ +        : "=r" (__res));                                        \ +        __res;}) + +#define read_32bit_cp0_set1_register(source)                    \ +({ int __res;                                                   \ +        __asm__ __volatile__(                                   \ +	".set\tpush\n\t"					\ +	".set\treorder\n\t"					\ +        "cfc0\t%0,"STR(source)"\n\t"                            \ +	".set\tpop"						\ +        : "=r" (__res));                                        \ +        __res;}) + +/* + * For now use this only with interrupts disabled! + */ +#define read_64bit_cp0_register(source)                         \ +({ int __res;                                                   \ +        __asm__ __volatile__(                                   \ +        ".set\tmips3\n\t"                                       \ +        "dmfc0\t%0,"STR(source)"\n\t"                           \ +        ".set\tmips0"                                           \ +        : "=r" (__res));                                        \ +        __res;}) + +#define write_32bit_cp0_register(register,value)                \ +        __asm__ __volatile__(                                   \ +        "mtc0\t%0,"STR(register)"\n\t"				\ +	"nop"							\ +        : : "r" (value)); + +#define write_32bit_cp0_set1_register(register,value)           \ +        __asm__ __volatile__(                                   \ +        "ctc0\t%0,"STR(register)"\n\t"				\ +	"nop"							\ +        : : "r" (value)); + +#define write_64bit_cp0_register(register,value)                \ +        __asm__ __volatile__(                                   \ +        ".set\tmips3\n\t"                                       \ +        "dmtc0\t%0,"STR(register)"\n\t"                         \ +        ".set\tmips0"                                           \ +        : : "r" (value)) + +/*  + * This should be changed when we get a compiler that support the MIPS32 ISA.  + */ +#define read_mips32_cp0_config1()                               \ +({ int __res;                                                   \ +        __asm__ __volatile__(                                   \ +	".set\tnoreorder\n\t"                                   \ +	".set\tnoat\n\t"                                        \ +     	".word\t0x40018001\n\t"                                 \ +	"move\t%0,$1\n\t"                                       \ +	".set\tat\n\t"                                          \ +	".set\treorder"                                         \ +	:"=r" (__res));                                         \ +        __res;}) + +/* + * R4x00 interrupt enable / cause bits + */ +#define IE_SW0          (1<< 8) +#define IE_SW1          (1<< 9) +#define IE_IRQ0         (1<<10) +#define IE_IRQ1         (1<<11) +#define IE_IRQ2         (1<<12) +#define IE_IRQ3         (1<<13) +#define IE_IRQ4         (1<<14) +#define IE_IRQ5         (1<<15) + +/* + * R4x00 interrupt cause bits + */ +#define C_SW0           (1<< 8) +#define C_SW1           (1<< 9) +#define C_IRQ0          (1<<10) +#define C_IRQ1          (1<<11) +#define C_IRQ2          (1<<12) +#define C_IRQ3          (1<<13) +#define C_IRQ4          (1<<14) +#define C_IRQ5          (1<<15) + +#ifndef _LANGUAGE_ASSEMBLY +/* + * Manipulate the status register. + * Mostly used to access the interrupt bits. + */ +#define __BUILD_SET_CP0(name,register)                          \ +extern __inline__ unsigned int                                  \ +set_cp0_##name(unsigned int set)				\ +{                                                               \ +	unsigned int res;                                       \ +                                                                \ +	res = read_32bit_cp0_register(register);                \ +	res |= set;						\ +	write_32bit_cp0_register(register, res);        	\ +                                                                \ +	return res;                                             \ +}								\ +								\ +extern __inline__ unsigned int                                  \ +clear_cp0_##name(unsigned int clear)				\ +{                                                               \ +	unsigned int res;                                       \ +                                                                \ +	res = read_32bit_cp0_register(register);                \ +	res &= ~clear;						\ +	write_32bit_cp0_register(register, res);		\ +                                                                \ +	return res;                                             \ +}								\ +								\ +extern __inline__ unsigned int                                  \ +change_cp0_##name(unsigned int change, unsigned int new)	\ +{                                                               \ +	unsigned int res;                                       \ +                                                                \ +	res = read_32bit_cp0_register(register);                \ +	res &= ~change;                                         \ +	res |= (new & change);                                  \ +	if(change)                                              \ +		write_32bit_cp0_register(register, res);        \ +                                                                \ +	return res;                                             \ +} + +__BUILD_SET_CP0(status,CP0_STATUS) +__BUILD_SET_CP0(cause,CP0_CAUSE) +__BUILD_SET_CP0(config,CP0_CONFIG) + +#endif /* defined (_LANGUAGE_ASSEMBLY) */ + +/* + * Bitfields in the R4xx0 cp0 status register + */ +#define ST0_IE			0x00000001 +#define ST0_EXL			0x00000002 +#define ST0_ERL			0x00000004 +#define ST0_KSU			0x00000018 +#  define KSU_USER		0x00000010 +#  define KSU_SUPERVISOR	0x00000008 +#  define KSU_KERNEL		0x00000000 +#define ST0_UX			0x00000020 +#define ST0_SX			0x00000040 +#define ST0_KX 			0x00000080 +#define ST0_DE			0x00010000 +#define ST0_CE			0x00020000 + +/* + * Bitfields in the R[23]000 cp0 status register. + */ +#define ST0_IEC                 0x00000001 +#define ST0_KUC			0x00000002 +#define ST0_IEP			0x00000004 +#define ST0_KUP			0x00000008 +#define ST0_IEO			0x00000010 +#define ST0_KUO			0x00000020 +/* bits 6 & 7 are reserved on R[23]000 */ +#define ST0_ISC			0x00010000 +#define ST0_SWC			0x00020000 +#define ST0_CM			0x00080000 + +/* + * Bits specific to the R4640/R4650 + */ +#define ST0_UM                 (1   <<  4) +#define ST0_IL                 (1   << 23) +#define ST0_DL                 (1   << 24) + +/* + * Bitfields in the TX39 family CP0 Configuration Register 3 + */ +#define TX39_CONF_ICS_SHIFT	19 +#define TX39_CONF_ICS_MASK	0x00380000 +#define TX39_CONF_ICS_1KB 	0x00000000 +#define TX39_CONF_ICS_2KB 	0x00080000 +#define TX39_CONF_ICS_4KB 	0x00100000 +#define TX39_CONF_ICS_8KB 	0x00180000 +#define TX39_CONF_ICS_16KB 	0x00200000 + +#define TX39_CONF_DCS_SHIFT	16 +#define TX39_CONF_DCS_MASK	0x00070000 +#define TX39_CONF_DCS_1KB 	0x00000000 +#define TX39_CONF_DCS_2KB 	0x00010000 +#define TX39_CONF_DCS_4KB 	0x00020000 +#define TX39_CONF_DCS_8KB 	0x00030000 +#define TX39_CONF_DCS_16KB 	0x00040000 + +#define TX39_CONF_CWFON 	0x00004000 +#define TX39_CONF_WBON  	0x00002000 +#define TX39_CONF_RF_SHIFT	10 +#define TX39_CONF_RF_MASK	0x00000c00 +#define TX39_CONF_DOZE		0x00000200 +#define TX39_CONF_HALT		0x00000100 +#define TX39_CONF_LOCK		0x00000080 +#define TX39_CONF_ICE		0x00000020 +#define TX39_CONF_DCE		0x00000010 +#define TX39_CONF_IRSIZE_SHIFT	2 +#define TX39_CONF_IRSIZE_MASK	0x0000000c +#define TX39_CONF_DRSIZE_SHIFT	0 +#define TX39_CONF_DRSIZE_MASK	0x00000003 + +/* + * Status register bits available in all MIPS CPUs. + */ +#define ST0_IM			0x0000ff00 +#define  STATUSB_IP0		8 +#define  STATUSF_IP0		(1   <<  8) +#define  STATUSB_IP1		9 +#define  STATUSF_IP1		(1   <<  9) +#define  STATUSB_IP2		10 +#define  STATUSF_IP2		(1   << 10) +#define  STATUSB_IP3		11 +#define  STATUSF_IP3		(1   << 11) +#define  STATUSB_IP4		12 +#define  STATUSF_IP4		(1   << 12) +#define  STATUSB_IP5		13 +#define  STATUSF_IP5		(1   << 13) +#define  STATUSB_IP6		14 +#define  STATUSF_IP6		(1   << 14) +#define  STATUSB_IP7		15 +#define  STATUSF_IP7		(1   << 15) +#define  STATUSB_IP8		0 +#define  STATUSF_IP8		(1   << 0) +#define  STATUSB_IP9		1 +#define  STATUSF_IP9		(1   << 1) +#define  STATUSB_IP10		2 +#define  STATUSF_IP10		(1   << 2) +#define  STATUSB_IP11		3 +#define  STATUSF_IP11		(1   << 3) +#define  STATUSB_IP12		4 +#define  STATUSF_IP12		(1   << 4) +#define  STATUSB_IP13		5 +#define  STATUSF_IP13		(1   << 5) +#define  STATUSB_IP14		6 +#define  STATUSF_IP14		(1   << 6) +#define  STATUSB_IP15		7 +#define  STATUSF_IP15		(1   << 7) +#define ST0_CH			0x00040000 +#define ST0_SR			0x00100000 +#define ST0_BEV			0x00400000 +#define ST0_RE			0x02000000 +#define ST0_FR			0x04000000 +#define ST0_CU			0xf0000000 +#define ST0_CU0			0x10000000 +#define ST0_CU1			0x20000000 +#define ST0_CU2			0x40000000 +#define ST0_CU3			0x80000000 +#define ST0_XX			0x80000000	/* MIPS IV naming */ + +/* + * Bitfields and bit numbers in the coprocessor 0 cause register. + * + * Refer to your MIPS R4xx0 manual, chapter 5 for explanation. + */ +#define  CAUSEB_EXCCODE		2 +#define  CAUSEF_EXCCODE		(31  <<  2) +#define  CAUSEB_IP		8 +#define  CAUSEF_IP		(255 <<  8) +#define  CAUSEB_IP0		8 +#define  CAUSEF_IP0		(1   <<  8) +#define  CAUSEB_IP1		9 +#define  CAUSEF_IP1		(1   <<  9) +#define  CAUSEB_IP2		10 +#define  CAUSEF_IP2		(1   << 10) +#define  CAUSEB_IP3		11 +#define  CAUSEF_IP3		(1   << 11) +#define  CAUSEB_IP4		12 +#define  CAUSEF_IP4		(1   << 12) +#define  CAUSEB_IP5		13 +#define  CAUSEF_IP5		(1   << 13) +#define  CAUSEB_IP6		14 +#define  CAUSEF_IP6		(1   << 14) +#define  CAUSEB_IP7		15 +#define  CAUSEF_IP7		(1   << 15) +#define  CAUSEB_IV		23 +#define  CAUSEF_IV		(1   << 23) +#define  CAUSEB_CE		28 +#define  CAUSEF_CE		(3   << 28) +#define  CAUSEB_BD		31 +#define  CAUSEF_BD		(1   << 31) + +/* + * Bits in the coprozessor 0 config register. + */ +#define CONF_CM_CACHABLE_NO_WA		0 +#define CONF_CM_CACHABLE_WA		1 +#define CONF_CM_UNCACHED		2 +#define CONF_CM_CACHABLE_NONCOHERENT	3 +#define CONF_CM_CACHABLE_CE		4 +#define CONF_CM_CACHABLE_COW		5 +#define CONF_CM_CACHABLE_CUW		6 +#define CONF_CM_CACHABLE_ACCELERATED	7 +#define CONF_CM_CMASK			7 +#define CONF_DB				(1 <<  4) +#define CONF_IB				(1 <<  5) +#define CONF_SC				(1 << 17) +#define CONF_AC                         (1 << 23) +#define CONF_HALT                       (1 << 25) + +/* + * R10000 performance counter definitions. + * + * FIXME: The R10000 performance counter opens a nice way to implement CPU + *        time accounting with a precission of one cycle.  I don't have + *        R10000 silicon but just a manual, so ... + */ + +/* + * Events counted by counter #0 + */ +#define CE0_CYCLES			0 +#define CE0_INSN_ISSUED			1 +#define CE0_LPSC_ISSUED			2 +#define CE0_S_ISSUED			3 +#define CE0_SC_ISSUED			4 +#define CE0_SC_FAILED			5 +#define CE0_BRANCH_DECODED		6 +#define CE0_QW_WB_SECONDARY		7 +#define CE0_CORRECTED_ECC_ERRORS	8 +#define CE0_ICACHE_MISSES		9 +#define CE0_SCACHE_I_MISSES		10 +#define CE0_SCACHE_I_WAY_MISSPREDICTED	11 +#define CE0_EXT_INTERVENTIONS_REQ	12 +#define CE0_EXT_INVALIDATE_REQ		13 +#define CE0_VIRTUAL_COHERENCY_COND	14 +#define CE0_INSN_GRADUATED		15 + +/* + * Events counted by counter #1 + */ +#define CE1_CYCLES			0 +#define CE1_INSN_GRADUATED		1 +#define CE1_LPSC_GRADUATED		2 +#define CE1_S_GRADUATED			3 +#define CE1_SC_GRADUATED		4 +#define CE1_FP_INSN_GRADUATED		5 +#define CE1_QW_WB_PRIMARY		6 +#define CE1_TLB_REFILL			7 +#define CE1_BRANCH_MISSPREDICTED	8 +#define CE1_DCACHE_MISS			9 +#define CE1_SCACHE_D_MISSES		10 +#define CE1_SCACHE_D_WAY_MISSPREDICTED	11 +#define CE1_EXT_INTERVENTION_HITS	12 +#define CE1_EXT_INVALIDATE_REQ		13 +#define CE1_SP_HINT_TO_CEXCL_SC_BLOCKS	14 +#define CE1_SP_HINT_TO_SHARED_SC_BLOCKS	15 + +/* + * These flags define in which priviledge mode the counters count events + */ +#define CEB_USER	8	/* Count events in user mode, EXL = ERL = 0 */ +#define CEB_SUPERVISOR	4	/* Count events in supvervisor mode EXL = ERL = 0 */ +#define CEB_KERNEL	2	/* Count events in kernel mode EXL = ERL = 0 */ +#define CEB_EXL		1	/* Count events with EXL = 1, ERL = 0 */ + +#endif /* _ASM_MIPSREGS_H */ diff --git a/include/asm-mips/posix_types.h b/include/asm-mips/posix_types.h new file mode 100644 index 000000000..6c48b3f83 --- /dev/null +++ b/include/asm-mips/posix_types.h @@ -0,0 +1,123 @@ +/* $Id: posix_types.h,v 1.6 2000/02/04 23:32:54 ralf Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1997, 1998, 2000 by Ralf Baechle + */ +#ifndef _ASM_POSIX_TYPES_H +#define _ASM_POSIX_TYPES_H + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc.  Also, we cannot + * assume GCC is being used. + */ + +typedef unsigned int	__kernel_dev_t; +typedef unsigned long	__kernel_ino_t; +typedef unsigned int	__kernel_mode_t; +typedef int		__kernel_nlink_t; +typedef long		__kernel_off_t; +typedef int		__kernel_pid_t; +typedef int		__kernel_ipc_pid_t; +typedef int		__kernel_uid_t; +typedef int		__kernel_gid_t; +typedef unsigned int	__kernel_size_t; +typedef int		__kernel_ssize_t; +typedef int		__kernel_ptrdiff_t; +typedef long		__kernel_time_t; +typedef long		__kernel_suseconds_t; +typedef long		__kernel_clock_t; +typedef long		__kernel_daddr_t; +typedef char *		__kernel_caddr_t; + +typedef unsigned short	__kernel_uid16_t; +typedef unsigned short	__kernel_gid16_t; +typedef int		__kernel_uid32_t; +typedef int		__kernel_gid32_t; +typedef __kernel_uid_t	__kernel_old_uid_t; +typedef __kernel_gid_t	__kernel_old_gid_t; + +#ifdef __GNUC__ +typedef long long      __kernel_loff_t; +#endif + +typedef struct { +        long    val[2]; +} __kernel_fsid_t; + +#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) + +#undef __FD_SET +static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp) +{ +	unsigned long __tmp = __fd / __NFDBITS; +	unsigned long __rem = __fd % __NFDBITS; +	__fdsetp->fds_bits[__tmp] |= (1UL<<__rem); +} + +#undef __FD_CLR +static __inline__ void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp) +{ +	unsigned long __tmp = __fd / __NFDBITS; +	unsigned long __rem = __fd % __NFDBITS; +	__fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem); +} + +#undef __FD_ISSET +static __inline__ int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p) +{  +	unsigned long __tmp = __fd / __NFDBITS; +	unsigned long __rem = __fd % __NFDBITS; +	return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0; +} + +/* + * This will unroll the loop for the normal constant case (8 ints, + * for a 256-bit fd_set) + */ +#undef __FD_ZERO +static __inline__ void __FD_ZERO(__kernel_fd_set *__p) +{ +	unsigned long *__tmp = __p->fds_bits; +	int __i; + +	if (__builtin_constant_p(__FDSET_LONGS)) { +		switch (__FDSET_LONGS) { +		case 16: +			__tmp[ 0] = 0; __tmp[ 1] = 0; +			__tmp[ 2] = 0; __tmp[ 3] = 0; +			__tmp[ 4] = 0; __tmp[ 5] = 0; +			__tmp[ 6] = 0; __tmp[ 7] = 0; +			__tmp[ 8] = 0; __tmp[ 9] = 0; +			__tmp[10] = 0; __tmp[11] = 0; +			__tmp[12] = 0; __tmp[13] = 0; +			__tmp[14] = 0; __tmp[15] = 0; +			return; + +		case 8: +			__tmp[ 0] = 0; __tmp[ 1] = 0; +			__tmp[ 2] = 0; __tmp[ 3] = 0; +			__tmp[ 4] = 0; __tmp[ 5] = 0; +			__tmp[ 6] = 0; __tmp[ 7] = 0; +			return; + +		case 4: +			__tmp[ 0] = 0; __tmp[ 1] = 0; +			__tmp[ 2] = 0; __tmp[ 3] = 0; +			return; +		} +	} +	__i = __FDSET_LONGS; +	while (__i) { +		__i--; +		*__tmp = 0; +		__tmp++; +	} +} + +#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ + +#endif /* _ASM_POSIX_TYPES_H */ diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h new file mode 100644 index 000000000..8c3de908d --- /dev/null +++ b/include/asm-mips/processor.h @@ -0,0 +1,283 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 Waldorf GMBH + * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2001 Ralf Baechle + * Copyright (C) 1996 Paul M. Antoine + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_PROCESSOR_H +#define _ASM_PROCESSOR_H + +#include <linux/config.h> + +#include <asm/isadep.h> + +/* + * Default implementation of macro that returns current + * instruction pointer ("program counter"). + */ +#define current_text_addr() ({ __label__ _l; _l: &&_l;}) + +#if !defined (_LANGUAGE_ASSEMBLY) +#if 0 +#include <linux/threads.h> +#endif +#include <asm/cachectl.h> +#include <asm/mipsregs.h> +#include <asm/reg.h> +#include <asm/system.h> + +struct mips_cpuinfo { +	unsigned long udelay_val; +	unsigned long *pgd_quick; +	unsigned long *pte_quick; +	unsigned long pgtable_cache_sz; +}; + +/* + * System setup and hardware flags.. + * XXX: Should go into mips_cpuinfo. + */ +extern void (*cpu_wait)(void);	/* only available on R4[26]00 and R3081 */ +extern void r3081_wait(void); +extern void r4k_wait(void); +extern char cyclecounter_available;	/* only available from R4000 upwards. */ + +extern struct mips_cpuinfo boot_cpu_data; +extern unsigned int vced_count, vcei_count; + +#ifdef CONFIG_SMP +extern struct mips_cpuinfo cpu_data[]; +#define current_cpu_data cpu_data[smp_processor_id()] +#else +#define cpu_data &boot_cpu_data +#define current_cpu_data boot_cpu_data +#endif + +/* + * Bus types (default is ISA, but people can check others with these..) + * MCA_bus hardcoded to 0 for now. + * + * This needs to be extended since MIPS systems are being delivered with + * numerous different types of bus systems. + */ +extern int EISA_bus; +#define MCA_bus 0 +#define MCA_bus__is_a_macro /* for versions in ksyms.c */ + +/* + * MIPS has no problems with write protection + */ +#define wp_works_ok 1 +#define wp_works_ok__is_a_macro /* for versions in ksyms.c */ + +/* Lazy FPU handling on uni-processor */ +extern struct task_struct *last_task_used_math; + +/* + * User space process size: 2GB. This is hardcoded into a few places, + * so don't change it unless you know what you are doing.  TASK_SIZE + * for a 64 bit kernel expandable to 8192EB, of which the current MIPS + * implementations will "only" be able to use 1TB ... + */ +#define TASK_SIZE	(0x7fff8000UL) + +/* This decides where the kernel will search for a free chunk of vm + * space during mmap's. + */ +#define TASK_UNMAPPED_BASE	(TASK_SIZE / 3) + +/* + * Size of io_bitmap in longwords: 32 is ports 0-0x3ff. + */ +#define IO_BITMAP_SIZE	32 + +#define NUM_FPU_REGS	32 + +struct mips_fpu_hard_struct { +	double fp_regs[NUM_FPU_REGS]; +	unsigned int control; +}; + +/* + * It would be nice to add some more fields for emulator statistics, but there + * are a number of fixed offsets in offset.h and elsewhere that would have to + * be recalculated by hand.  So the additional information will be private to + * the FPU emulator for now.  See asm-mips/fpu_emulator.h. + */ +typedef u64 fpureg_t; +struct mips_fpu_soft_struct { +	fpureg_t	regs[NUM_FPU_REGS]; +	unsigned int	sr; +}; + +union mips_fpu_union { +        struct mips_fpu_hard_struct hard; +        struct mips_fpu_soft_struct soft; +}; + +#define INIT_FPU { \ +	{{0,},} \ +} + +typedef struct { +	unsigned long seg; +} mm_segment_t; + +/* + * If you change thread_struct remember to change the #defines below too! + */ +struct thread_struct { +	/* Saved main processor registers. */ +	unsigned long reg16; +	unsigned long reg17, reg18, reg19, reg20, reg21, reg22, reg23; +	unsigned long reg29, reg30, reg31; + +	/* Saved cp0 stuff. */ +	unsigned long cp0_status; + +	/* Saved fpu/fpu emulator stuff. */ +	union mips_fpu_union fpu; + +	/* Other stuff associated with the thread. */ +	unsigned long cp0_badvaddr;	/* Last user fault */ +	unsigned long cp0_baduaddr;	/* Last kernel fault accessing USEG */ +	unsigned long error_code; +	unsigned long trap_no; +#define MF_FIXADE 1			/* Fix address errors in software */ +#define MF_LOGADE 2			/* Log address errors to syslog */ +	unsigned long mflags; +	mm_segment_t current_ds; +	unsigned long irix_trampoline;  /* Wheee... */ +	unsigned long irix_oldctx; + +	/* +	 * These are really only needed if the full FPU emulator is configured. +	 * Would be made conditional on MIPS_FPU_EMULATOR if it weren't for the +	 * fact that having offset.h rebuilt differently for different config +	 * options would be asking for trouble. +	 * +	 * Saved EPC during delay-slot emulation (see math-emu/cp1emu.c) +	 */ +	unsigned long dsemul_epc; + +	/* +	 * Pointer to instruction used to induce address error +	 */ +	unsigned long dsemul_aerpc; +}; + +#endif /* !defined (_LANGUAGE_ASSEMBLY) */ + +#define INIT_THREAD  { \ +        /* \ +         * saved main processor registers \ +         */ \ +	0, 0, 0, 0, 0, 0, 0, 0, \ +	               0, 0, 0, \ +	/* \ +	 * saved cp0 stuff \ +	 */ \ +	0, \ +	/* \ +	 * saved fpu/fpu emulator stuff \ +	 */ \ +	INIT_FPU, \ +	/* \ +	 * Other stuff associated with the process \ +	 */ \ +	0, 0, 0, 0, \ +	/* \ +	 * For now the default is to fix address errors \ +	 */ \ +	MF_FIXADE, { 0 }, 0, 0, \ +	/* \ +	 * dsemul_epc and dsemul_aerpc should never be used uninitialized, \ +	 * but... \ +	 */ \ +	0 ,0 \ +} + +#ifdef __KERNEL__ + +#define KERNEL_STACK_SIZE 8192 + +#if !defined (_LANGUAGE_ASSEMBLY) + +/* Free all resources held by a thread. */ +#define release_thread(thread) do { } while(0) + +extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); + +/* Copy and release all segment info associated with a VM */ +#define copy_segments(p, mm) do { } while(0) +#define release_segments(mm) do { } while(0) + +/* + * Return saved PC of a blocked thread. + */ +extern inline unsigned long thread_saved_pc(struct thread_struct *t) +{ +	extern void ret_from_fork(void); + +	/* New born processes are a special case */ +	if (t->reg31 == (unsigned long) ret_from_fork) +		return t->reg31; + +	return ((unsigned long *)t->reg29)[10]; +} + +/* + * Do necessary setup to start up a newly executed thread. + */ +#define start_thread(regs, new_pc, new_sp) do {				\ +	/* New thread looses kernel privileges. */			\ +	regs->cp0_status = (regs->cp0_status & ~(ST0_CU0|ST0_KSU)) | KU_USER;\ +	regs->cp0_epc = new_pc;						\ +	regs->regs[29] = new_sp;					\ +	current->thread.current_ds = USER_DS;				\ +} while (0) + +unsigned long get_wchan(struct task_struct *p); + +#define __PT_REG(reg) ((long)&((struct pt_regs *)0)->reg - sizeof(struct pt_regs)) +#define __KSTK_TOS(tsk) ((unsigned long)(tsk) + KERNEL_STACK_SIZE - 32) +#define KSTK_EIP(tsk) (*(unsigned long *)(__KSTK_TOS(tsk) + __PT_REG(cp0_epc))) +#define KSTK_ESP(tsk) (*(unsigned long *)(__KSTK_TOS(tsk) + __PT_REG(regs[29]))) + +/* Allocation and freeing of basic task resources. */ +/* + * NOTE! The task struct and the stack go together + */ +#define THREAD_SIZE (2*PAGE_SIZE) +#define alloc_task_struct() \ +	((struct task_struct *) __get_free_pages(GFP_KERNEL,1)) +#define free_task_struct(p)	free_pages((unsigned long)(p),1) +#define get_task_struct(tsk)      atomic_inc(&virt_to_page(tsk)->count) + +#define init_task	(init_task_union.task) +#define init_stack	(init_task_union.stack) + +#define cpu_relax()	do { } while (0) + +#endif /* !defined (_LANGUAGE_ASSEMBLY) */ +#endif /* __KERNEL__ */ + +/* + * Return_address is a replacement for __builtin_return_address(count) + * which on certain architectures cannot reasonably be implemented in GCC + * (MIPS, Alpha) or is unuseable with -fomit-frame-pointer (i386). + * Note that __builtin_return_address(x>=1) is forbidden because GCC + * aborts compilation on some CPUs.  It's simply not possible to unwind + * some CPU's stackframes. + * + * __builtin_return_address works only for non-leaf functions.  We avoid the + * overhead of a function call by forcing the compiler to save the return + * address register on the stack. + */ +#define return_address() ({__asm__ __volatile__("":::"$31");__builtin_return_address(0);}) + +#endif /* _ASM_PROCESSOR_H */ diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h new file mode 100644 index 000000000..2517adb2a --- /dev/null +++ b/include/asm-mips/ptrace.h @@ -0,0 +1,86 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000 by Ralf Baechle + * + * Machine dependent structs and defines to help the user use + * the ptrace system call. + */ +#ifndef _ASM_PTRACE_H +#define _ASM_PTRACE_H + +#include <asm/isadep.h> +#include <linux/types.h> + +/* 0 - 31 are integer registers, 32 - 63 are fp registers.  */ +#define FPR_BASE	32 +#define PC		64 +#define CAUSE		65 +#define BADVADDR	66 +#define MMHI		67 +#define MMLO		68 +#define FPC_CSR		69 +#define FPC_EIR		70 + +#ifndef _LANGUAGE_ASSEMBLY +/* + * This struct defines the way the registers are stored on the stack during a + * system call/exception. As usual the registers k0/k1 aren't being saved. + */ +struct pt_regs { +	/* Pad bytes for argument save space on the stack. */ +	unsigned long pad0[6]; + +	/* Saved main processor registers. */ +	unsigned long regs[32]; + +	/* Other saved registers. */ +	unsigned long lo; +	unsigned long hi; + +	/* +	 * saved cp0 registers +	 */ +	unsigned long cp0_epc; +	unsigned long cp0_badvaddr; +	unsigned long cp0_status; +	unsigned long cp0_cause; +}; + +#endif /* !(_LANGUAGE_ASSEMBLY) */ + +/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ +/* #define PTRACE_GETREGS		12 */ +/* #define PTRACE_SETREGS		13 */ +/* #define PTRACE_GETFPREGS		14 */ +/* #define PTRACE_SETFPREGS		15 */ +/* #define PTRACE_GETFPXREGS		18 */ +/* #define PTRACE_SETFPXREGS		19 */ + +#define PTRACE_SETOPTIONS	21 + +/* options set using PTRACE_SETOPTIONS */ +#define PTRACE_O_TRACESYSGOOD	0x00000001 + +#if 0 /* def _LANGUAGE_ASSEMBLY */ +#include <asm/offset.h> +#endif + +#ifdef __KERNEL__ + +#ifndef _LANGUAGE_ASSEMBLY +/* + * Does the process account for user or for system time? + */ +#define user_mode(regs) (((regs)->cp0_status & KU_MASK) == KU_USER) + +#define instruction_pointer(regs) ((regs)->cp0_epc) + +extern void show_regs(struct pt_regs *); +#endif /* !(_LANGUAGE_ASSEMBLY) */ + +#endif + +#endif /* _ASM_PTRACE_H */ diff --git a/include/asm-mips/reg.h b/include/asm-mips/reg.h new file mode 100644 index 000000000..35505b70f --- /dev/null +++ b/include/asm-mips/reg.h @@ -0,0 +1,66 @@ +/* + * Various register offset definitions for debuggers, core file + * examiners and whatnot. + * + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 1999 by Ralf Baechle + */ +#ifndef __ASM_MIPS_REG_H +#define __ASM_MIPS_REG_H + +/* + * This defines/structures correspond to the register layout on stack - + * if the order here is changed, it needs to be updated in + * include/asm-mips/stackframe.h + */ +#define EF_REG0			6 +#define EF_REG1			7 +#define EF_REG2			8 +#define EF_REG3			9 +#define EF_REG4			10 +#define EF_REG5			11 +#define EF_REG6			12 +#define EF_REG7			13 +#define EF_REG8			14 +#define EF_REG9			15 +#define EF_REG10		16 +#define EF_REG11		17 +#define EF_REG12		18 +#define EF_REG13		19 +#define EF_REG14		20 +#define EF_REG15		21 +#define EF_REG16		22 +#define EF_REG17		23 +#define EF_REG18		24 +#define EF_REG19		25 +#define EF_REG20		26 +#define EF_REG21		27 +#define EF_REG22		28 +#define EF_REG23		29 +#define EF_REG24		30 +#define EF_REG25		31 +/* + * k0/k1 unsaved + */ +#define EF_REG28		34 +#define EF_REG29		35 +#define EF_REG30		36 +#define EF_REG31		37 + +/* + * Saved special registers + */ +#define EF_LO			38 +#define EF_HI			39 + +#define EF_CP0_EPC		40 +#define EF_CP0_BADVADDR		41 +#define EF_CP0_STATUS		42 +#define EF_CP0_CAUSE		44 + +#define EF_SIZE			180	/* size in bytes */ + +#endif /* __ASM_MIPS_REG_H */ diff --git a/include/asm-mips/regdef.h b/include/asm-mips/regdef.h new file mode 100644 index 000000000..691d047b6 --- /dev/null +++ b/include/asm-mips/regdef.h @@ -0,0 +1,52 @@ +/* + * include/asm-mips/regdefs.h + * + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 1995 by Ralf Baechle + */ + +#ifndef __ASM_MIPS_REGDEF_H +#define __ASM_MIPS_REGDEF_H + +/* + * Symbolic register names for 32 bit ABI + */ +#define zero    $0      /* wired zero */ +#define AT      $1      /* assembler temp  - uppercase because of ".set at" */ +#define v0      $2      /* return value */ +#define v1      $3 +#define a0      $4      /* argument registers */ +#define a1      $5 +#define a2      $6 +#define a3      $7 +#define t0      $8      /* caller saved */ +#define t1      $9 +#define t2      $10 +#define t3      $11 +#define t4      $12 +#define t5      $13 +#define t6      $14 +#define t7      $15 +#define s0      $16     /* callee saved */ +#define s1      $17 +#define s2      $18 +#define s3      $19 +#define s4      $20 +#define s5      $21 +#define s6      $22 +#define s7      $23 +#define t8      $24     /* caller saved */ +#define t9      $25 +#define jp      $25     /* PIC jump register */ +#define k0      $26     /* kernel scratch */ +#define k1      $27 +#define gp      $28     /* global pointer */ +#define sp      $29     /* stack pointer */ +#define fp      $30     /* frame pointer */ +#define s8	$30	/* same like fp! */ +#define ra      $31     /* return address */ + +#endif /* __ASM_MIPS_REGDEF_H */ diff --git a/include/asm-mips/sgidefs.h b/include/asm-mips/sgidefs.h new file mode 100644 index 000000000..67f265895 --- /dev/null +++ b/include/asm-mips/sgidefs.h @@ -0,0 +1,44 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1999, 2001 Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 2001 MIPS Technologies, Inc. + */ +#ifndef __ASM_SGIDEFS_H +#define __ASM_SGIDEFS_H + +/* + * Using a Linux compiler for building Linux seems logic but not to + * everybody. + */ +#if 0 /* ndef __linux__ */ +#error Use a Linux compiler or give up. +#endif + +/* + * Definitions for the ISA levels + * + * With the introduction of MIPS32 / MIPS64 instruction sets definitions + * MIPS ISAs are no longer subsets of each other.  Therefore comparisons + * on these symbols except with == may result in unexpected results and + * are forbidden! + */ +#define _MIPS_ISA_MIPS1		1 +#define _MIPS_ISA_MIPS2		2 +#define _MIPS_ISA_MIPS3		3 +#define _MIPS_ISA_MIPS4		4 +#define _MIPS_ISA_MIPS5		5 +#define _MIPS_ISA_MIPS32	6 +#define _MIPS_ISA_MIPS64	7 + +/* + * Subprogram calling convention + */ +#define _MIPS_SIM_ABI32		1 +#define _MIPS_SIM_NABI32	2 +#define _MIPS_SIM_ABI64		3 + +#endif /* __ASM_SGIDEFS_H */ diff --git a/include/asm-mips/string.h b/include/asm-mips/string.h new file mode 100644 index 000000000..343b45eba --- /dev/null +++ b/include/asm-mips/string.h @@ -0,0 +1,157 @@ +/* $Id: string.h,v 1.13 2000/02/19 14:12:14 harald Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 1994, 1995, 1996, 1997, 1998 by Ralf Baechle + */ +#ifndef __ASM_MIPS_STRING_H +#define __ASM_MIPS_STRING_H + +#include <linux/config.h> + +#define __HAVE_ARCH_STRCPY +extern __inline__ char *strcpy(char *__dest, __const__ char *__src) +{ +  char *__xdest = __dest; + +  __asm__ __volatile__( +	".set\tnoreorder\n\t" +	".set\tnoat\n" +	"1:\tlbu\t$1,(%1)\n\t" +	"addiu\t%1,1\n\t" +	"sb\t$1,(%0)\n\t" +	"bnez\t$1,1b\n\t" +	"addiu\t%0,1\n\t" +	".set\tat\n\t" +	".set\treorder" +	: "=r" (__dest), "=r" (__src) +        : "0" (__dest), "1" (__src) +	: "$1","memory"); + +  return __xdest; +} + +#define __HAVE_ARCH_STRNCPY +extern __inline__ char *strncpy(char *__dest, __const__ char *__src, size_t __n) +{ +  char *__xdest = __dest; + +  if (__n == 0) +    return __xdest; + +  __asm__ __volatile__( +	".set\tnoreorder\n\t" +	".set\tnoat\n" +	"1:\tlbu\t$1,(%1)\n\t" +	"subu\t%2,1\n\t" +	"sb\t$1,(%0)\n\t" +	"beqz\t$1,2f\n\t" +	"addiu\t%0,1\n\t" +	"bnez\t%2,1b\n\t" +	"addiu\t%1,1\n" +	"2:\n\t" +	".set\tat\n\t" +	".set\treorder" +        : "=r" (__dest), "=r" (__src), "=r" (__n) +        : "0" (__dest), "1" (__src), "2" (__n) +        : "$1","memory"); + +  return __dest; +} + +#define __HAVE_ARCH_STRCMP +extern __inline__ int strcmp(__const__ char *__cs, __const__ char *__ct) +{ +  int __res; + +  __asm__ __volatile__( +	".set\tnoreorder\n\t" +	".set\tnoat\n\t" +	"lbu\t%2,(%0)\n" +	"1:\tlbu\t$1,(%1)\n\t" +	"addiu\t%0,1\n\t" +	"bne\t$1,%2,2f\n\t" +	"addiu\t%1,1\n\t" +	"bnez\t%2,1b\n\t" +	"lbu\t%2,(%0)\n\t" +#if defined(CONFIG_CPU_R3000) +	"nop\n\t" +#endif +	"move\t%2,$1\n" +	"2:\tsubu\t%2,$1\n" +	"3:\t.set\tat\n\t" +	".set\treorder" +	: "=r" (__cs), "=r" (__ct), "=r" (__res) +	: "0" (__cs), "1" (__ct) +	: "$1"); + +  return __res; +} + +#define __HAVE_ARCH_STRNCMP +extern __inline__ int +strncmp(__const__ char *__cs, __const__ char *__ct, size_t __count) +{ +	int __res; + +	__asm__ __volatile__( +	".set\tnoreorder\n\t" +	".set\tnoat\n" +	"1:\tlbu\t%3,(%0)\n\t" +	"beqz\t%2,2f\n\t" +	"lbu\t$1,(%1)\n\t" +	"subu\t%2,1\n\t" +	"bne\t$1,%3,3f\n\t" +	"addiu\t%0,1\n\t" +	"bnez\t%3,1b\n\t" +	"addiu\t%1,1\n" +	"2:\n\t" +#if defined(CONFIG_CPU_R3000) +	"nop\n\t" +#endif	 +	"move\t%3,$1\n" +	"3:\tsubu\t%3,$1\n\t" +	".set\tat\n\t" +	".set\treorder" +	: "=r" (__cs), "=r" (__ct), "=r" (__count), "=r" (__res) +	: "0" (__cs), "1" (__ct), "2" (__count) +	: "$1"); + +	return __res; +} + +#undef __HAVE_ARCH_MEMSET +extern void *memset(void *__s, int __c, size_t __count); + +#undef __HAVE_ARCH_MEMCPY +extern void *memcpy(void *__to, __const__ void *__from, size_t __n); + +#undef __HAVE_ARCH_MEMMOVE +extern void *memmove(void *__dest, __const__ void *__src, size_t __n); + +/* Don't build bcopy at all ...  */ +#define __HAVE_ARCH_BCOPY + +#define __HAVE_ARCH_MEMSCAN +extern __inline__ void *memscan(void *__addr, int __c, size_t __size) +{ +	char *__end = (char *)__addr + __size; + +	__asm__(".set\tpush\n\t" +		".set\tnoat\n\t" +		".set\treorder\n\t" +		"1:\tbeq\t%0,%1,2f\n\t" +		"addiu\t%0,1\n\t" +		"lb\t$1,-1(%0)\n\t" +		"bne\t$1,%4,1b\n" +		"2:\t.set\tpop" +		: "=r" (__addr), "=r" (__end) +		: "0" (__addr), "1" (__end), "r" (__c) +		: "$1"); + +	return __addr; +} + +#endif /* __ASM_MIPS_STRING_H */ diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h new file mode 100644 index 000000000..4b45847e9 --- /dev/null +++ b/include/asm-mips/system.h @@ -0,0 +1,268 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 - 1999 by Ralf Baechle + * Copyright (C) 1996 by Paul M. Antoine + * Copyright (C) 1994 - 1999 by Ralf Baechle + * + * Changed set_except_vector declaration to allow return of previous + * vector address value - necessary for "borrowing" vectors.  + * + * Kevin D. Kissell, kevink@mips.org and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. + */ +#ifndef _ASM_SYSTEM_H +#define _ASM_SYSTEM_H + +#include <linux/config.h> +#include <asm/sgidefs.h> +#include <asm/ptrace.h> +#if 0 +#include <linux/kernel.h> +#endif + +extern __inline__ void +__sti(void) +{ +	__asm__ __volatile__( +		".set\tpush\n\t" +		".set\treorder\n\t" +		".set\tnoat\n\t" +		"mfc0\t$1,$12\n\t" +		"ori\t$1,0x1f\n\t" +		"xori\t$1,0x1e\n\t" +		"mtc0\t$1,$12\n\t" +		".set\tpop\n\t" +		: /* no outputs */ +		: /* no inputs */ +		: "$1", "memory"); +} + +/* + * For cli() we have to insert nops to make shure that the new value + * has actually arrived in the status register before the end of this + * macro. + * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs + * no nops at all. + */ +extern __inline__ void +__cli(void) +{ +	__asm__ __volatile__( +		".set\tpush\n\t" +		".set\treorder\n\t" +		".set\tnoat\n\t" +		"mfc0\t$1,$12\n\t" +		"ori\t$1,1\n\t" +		"xori\t$1,1\n\t" +		".set\tnoreorder\n\t" +		"mtc0\t$1,$12\n\t" +		"nop\n\t" +		"nop\n\t" +		"nop\n\t" +		".set\tpop\n\t" +		: /* no outputs */ +		: /* no inputs */ +		: "$1", "memory"); +} + +#define __save_flags(x)							\ +__asm__ __volatile__(							\ +	".set\tpush\n\t"						\ +	".set\treorder\n\t"						\ +	"mfc0\t%0,$12\n\t"						\ +	".set\tpop\n\t"							\ +	: "=r" (x)) + +#define __save_and_cli(x)						\ +__asm__ __volatile__(							\ +	".set\tpush\n\t"						\ +	".set\treorder\n\t"						\ +	".set\tnoat\n\t"						\ +	"mfc0\t%0,$12\n\t"						\ +	"ori\t$1,%0,1\n\t"						\ +	"xori\t$1,1\n\t"						\ +	".set\tnoreorder\n\t"						\ +	"mtc0\t$1,$12\n\t"						\ +	"nop\n\t"							\ +	"nop\n\t"							\ +	"nop\n\t"							\ +	".set\tpop\n\t"							\ +	: "=r" (x)							\ +	: /* no inputs */						\ +	: "$1", "memory") + +#define __restore_flags(flags)						\ +do {									\ +	unsigned long __tmp1;						\ +									\ +	__asm__ __volatile__(						\ +		".set\tnoreorder\t\t\t# __restore_flags\n\t"		\ +		".set\tnoat\n\t"					\ +		"mfc0\t$1, $12\n\t"					\ +		"andi\t%0, 1\n\t"					\ +		"ori\t$1, 1\n\t"					\ +		"xori\t$1, 1\n\t"					\ +		"or\t%0, $1\n\t"					\ +		"mtc0\t%0, $12\n\t"					\ +		"nop\n\t"						\ +		"nop\n\t"						\ +		"nop\n\t"						\ +		".set\tat\n\t"						\ +		".set\treorder"						\ +		: "=r" (__tmp1)						\ +		: "0" (flags)						\ +		: "$1", "memory");					\ +} while(0) + +#ifdef CONFIG_SMP + +extern void __global_sti(void); +extern void __global_cli(void); +extern unsigned long __global_save_flags(void); +extern void __global_restore_flags(unsigned long); +#  define sti() __global_sti() +#  define cli() __global_cli()  +#  define save_flags(x) do { x = __global_save_flags(); } while (0) +#  define restore_flags(x) __global_restore_flags(x) +#  define save_and_cli(x) do { save_flags(x); cli(); } while(0) + +#else /* Single processor */ + +#  define sti() __sti() +#  define cli() __cli() +#  define save_flags(x) __save_flags(x) +#  define save_and_cli(x) __save_and_cli(x) +#  define restore_flags(x) __restore_flags(x) + +#endif /* SMP */ + +/* For spinlocks etc */ +#define local_irq_save(x)	__save_and_cli(x); +#define local_irq_restore(x)	__restore_flags(x); +#define local_irq_disable()	__cli(); +#define local_irq_enable()	__sti(); + +/* + * These are probably defined overly paranoid ... + */ +#ifdef CONFIG_CPU_HAS_WB + +#include <asm/wbflush.h> +#define rmb()	do { } while(0) +#define wmb()	wbflush() +#define mb()	wbflush() + +#else /* CONFIG_CPU_HAS_WB  */ + +#define mb()						\ +__asm__ __volatile__(					\ +	"# prevent instructions being moved around\n\t"	\ +	".set\tnoreorder\n\t"				\ +	"# 8 nops to fool the R4400 pipeline\n\t"	\ +	"nop;nop;nop;nop;nop;nop;nop;nop\n\t"		\ +	".set\treorder"					\ +	: /* no output */				\ +	: /* no input */				\ +	: "memory") +#define rmb() mb() +#define wmb() mb() + +#endif /* CONFIG_CPU_HAS_WB  */ + +#ifdef CONFIG_SMP +#define smp_mb()	mb() +#define smp_rmb()	rmb() +#define smp_wmb()	wmb() +#else +#define smp_mb()	barrier() +#define smp_rmb()	barrier() +#define smp_wmb()	barrier() +#endif + +#define set_mb(var, value) \ +do { var = value; mb(); } while (0) + +#define set_wmb(var, value) \ +do { var = value; wmb(); } while (0) + +#if !defined (_LANGUAGE_ASSEMBLY) +/* + * switch_to(n) should switch tasks to task nr n, first + * checking that n isn't the current task, in which case it does nothing. + */ +#if 0 +extern asmlinkage void *resume(void *last, void *next); +#endif +#endif /* !defined (_LANGUAGE_ASSEMBLY) */ + +#define prepare_to_switch()	do { } while(0) +#define switch_to(prev,next,last) \ +do { \ +	(last) = resume(prev, next); \ +} while(0) + +/* + * For 32 and 64 bit operands we can take advantage of ll and sc. + * FIXME: This doesn't work for R3000 machines. + */ +extern __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val) +{ +#ifdef CONFIG_CPU_HAS_LLSC +	unsigned long dummy; + +	__asm__ __volatile__( +		".set\tnoreorder\t\t\t# xchg_u32\n\t" +		".set\tnoat\n\t" +		"ll\t%0, %3\n" +		"1:\tmove\t$1, %2\n\t" +		"sc\t$1, %1\n\t" +		"beqzl\t$1, 1b\n\t" +		" ll\t%0, %3\n\t" +		".set\tat\n\t" +		".set\treorder" +		: "=r" (val), "=o" (*m), "=r" (dummy) +		: "o" (*m), "2" (val) +		: "memory"); + +	return val; +#else +	unsigned long flags, retval; + +	save_flags(flags); +	cli(); +	retval = *m; +	*m = val; +	restore_flags(flags); +	return retval; +#endif /* Processor-dependent optimization */ +} + +#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) +#define tas(ptr) (xchg((ptr),1)) + +static __inline__ unsigned long +__xchg(unsigned long x, volatile void * ptr, int size) +{ +	switch (size) { +		case 4: +			return xchg_u32(ptr, x); +	} +	return x; +} + +extern void *set_except_vector(int n, void *addr); + +extern void __die(const char *, struct pt_regs *, const char *where, +	unsigned long line) __attribute__((noreturn)); +extern void __die_if_kernel(const char *, struct pt_regs *, const char *where, +	unsigned long line); + +#define die(msg, regs)							\ +	__die(msg, regs, __FILE__ ":"__FUNCTION__, __LINE__) +#define die_if_kernel(msg, regs)					\ +	__die_if_kernel(msg, regs, __FILE__ ":"__FUNCTION__, __LINE__) + +#endif /* _ASM_SYSTEM_H */ diff --git a/include/asm-mips/types.h b/include/asm-mips/types.h new file mode 100644 index 000000000..638f75163 --- /dev/null +++ b/include/asm-mips/types.h @@ -0,0 +1,77 @@ +/* $Id: types.h,v 1.3 1999/08/18 23:37:50 ralf Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 1995, 1996, 1999 by Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_TYPES_H +#define _ASM_TYPES_H + +typedef unsigned short umode_t; + +/* + * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the + * header files exported to user space + */ + +typedef __signed__ char __s8; +typedef unsigned char __u8; + +typedef __signed__ short __s16; +typedef unsigned short __u16; + +typedef __signed__ int __s32; +typedef unsigned int __u32; + +#if (_MIPS_SZLONG == 64) + +typedef __signed__ long __s64; +typedef unsigned long __u64; + +#else +  +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +typedef __signed__ long long __s64; +typedef unsigned long long __u64; +#endif +  +#endif + +/* + * These aren't exported outside the kernel to avoid name space clashes + */ +#ifdef __KERNEL__ + +typedef __signed char s8; +typedef unsigned char u8; + +typedef __signed short s16; +typedef unsigned short u16; + +typedef __signed int s32; +typedef unsigned int u32; + +#if (_MIPS_SZLONG == 64) + +typedef __signed__ long s64; +typedef unsigned long u64; + +#else + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +typedef __signed__ long long s64; +typedef unsigned long long u64; +#endif + +#endif + +#define BITS_PER_LONG _MIPS_SZLONG + +typedef unsigned long dma_addr_t; + +#endif /* __KERNEL__ */ + +#endif /* _ASM_TYPES_H */ diff --git a/include/asm-mips/u-boot.h b/include/asm-mips/u-boot.h new file mode 100644 index 000000000..ff189d936 --- /dev/null +++ b/include/asm-mips/u-boot.h @@ -0,0 +1,44 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, <wd@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _U_BOOT_H_ +#define _U_BOOT_H_	1 + +typedef struct bd_info { +    int			bi_baudrate;	/* serial console baudrate */ +    unsigned long	bi_ip_addr;	/* IP Address */ +    unsigned char	bi_enetaddr[6]; /* Ethernet adress */ +    struct environment_s	       *bi_env; +    ulong	        bi_arch_number;	/* unique id for this board */ +    ulong	        bi_boot_params;	/* where this board expects params */ +    struct				/* RAM configuration */ +    { +	ulong start; +	ulong size; +    } 			bi_dram[CONFIG_NR_DRAM_BANKS]; +} bd_t; + +#define bi_env_data bi_env->data +#define bi_env_crc  bi_env->crc + +#endif	/* _U_BOOT_H_ */ diff --git a/include/common.h b/include/common.h index 9f22b2f8d..bce0132af 100644 --- a/include/common.h +++ b/include/common.h @@ -149,7 +149,7 @@ void    setenv       (char *, char *);  # include <asm/u-boot-arm.h>	/* ARM version to be fixed! */  #endif /* CONFIG_ARM */  #ifdef CONFIG_I386		/* x86 version to be fixed! */ -# include <asm/ppcboot-i386.h> +# include <asm/ppcboot-i386.h>    #endif /* CONFIG_I386 */  void    pci_init      (void); diff --git a/include/configs/smdk2400.h b/include/configs/smdk2400.h index c60e74607..d0ad65ef2 100644 --- a/include/configs/smdk2400.h +++ b/include/configs/smdk2400.h @@ -162,10 +162,7 @@  #define PHYS_SDRAM_1		0x0c000000 /* SDRAM Bank #1 */  #define PHYS_SDRAM_1_SIZE	0x02000000 /* 32 MB */ -#define PHYS_FLASH_1		0x00000000 /* Flash Bank #1 */ -#define PHYS_FLASH_SIZE		0x00800000 /* 8 MB */ - -#define CFG_FLASH_BASE		PHYS_FLASH_1 +#define CFG_FLASH_BASE		0x00000000 /* Flash Bank #1 */  /*-----------------------------------------------------------------------   * FLASH and environment organization @@ -180,7 +177,7 @@  #define	CFG_ENV_IS_IN_FLASH	1  /* Address and size of Primary Environment Sector	*/ -#define CFG_ENV_ADDR		(PHYS_FLASH_1 + 0x40000) +#define CFG_ENV_ADDR		(CFG_FLASH_BASE + 0x40000)  #define CFG_ENV_SIZE		0x40000  /* Address and size of Redundant Environment Sector	*/ diff --git a/include/configs/trab.h b/include/configs/trab.h index c6144119e..086294e48 100644 --- a/include/configs/trab.h +++ b/include/configs/trab.h @@ -121,9 +121,8 @@  #define CONFIG_BOOTDELAY	5  #define CONFIG_PREBOOT		"echo;echo *** booting ***;echo"  #define CONFIG_BOOTARGS    	"console=ttyS0" -#define CONFIG_ETHADDR		00:D0:93:00:61:11 -#define CONFIG_NETMASK          255.255.255.0 -#define CONFIG_IPADDR		192.168.3.27 +#define CONFIG_NETMASK          255.255.0.0 +#define CONFIG_IPADDR		192.168.3.68  #define CONFIG_SERVERIP		192.168.3.1  #define CONFIG_BOOTCOMMAND	"run flash_nfs"  #define	CONFIG_EXTRA_ENV_SETTINGS	\ @@ -211,20 +210,17 @@  #define PHYS_SDRAM_1		0x0c000000 /* SDRAM Bank #1 */  #define PHYS_SDRAM_1_SIZE	0x01000000 /* 16 MB */ -#define PHYS_FLASH_1		0x00000000 /* Flash Bank #1 */ -#define PHYS_FLASH_SIZE		0x00800000 /* 8 MB */ +#define CFG_FLASH_BASE		0x00000000 /* Flash Bank #1 */  /* The following #defines are needed to get flash environment right */ -#define	CFG_MONITOR_BASE	PHYS_FLASH_1 +#define	CFG_MONITOR_BASE	CFG_FLASH_BASE  #define	CFG_MONITOR_LEN		(256 << 10) -#define CFG_FLASH_BASE		PHYS_FLASH_1 -  /*-----------------------------------------------------------------------   * FLASH and environment organization   */  #define CFG_MAX_FLASH_BANKS	1	/* max number of memory banks */ -#define CFG_MAX_FLASH_SECT	(71)	/* max number of sectors on one chip */ +#define CFG_MAX_FLASH_SECT	128	/* max number of sectors on one chip */  /* timeout values are in ticks */  #define CFG_FLASH_ERASE_TOUT	(2*CFG_HZ) /* Timeout for Flash Erase */ @@ -233,7 +229,7 @@  #define	CFG_ENV_IS_IN_FLASH	1  /* Address and size of Primary Environment Sector	*/ -#define CFG_ENV_ADDR		(PHYS_FLASH_1 + 0x4000) +#define CFG_ENV_ADDR		(CFG_FLASH_BASE + 0x4000)  #define CFG_ENV_SIZE		0x4000  /* Address and size of Redundant Environment Sector	*/ diff --git a/include/version.h b/include/version.h index 5249f2a59..042befe04 100644 --- a/include/version.h +++ b/include/version.h @@ -1,5 +1,5 @@  /* - * (C) Copyright 2000-2002 + * (C) Copyright 2000-2003   * Wolfgang Denk, DENX Software Engineering, wd@denx.de.   *   * See file CREDITS for list of people who contributed to this @@ -24,6 +24,6 @@  #ifndef	__VERSION_H__  #define	__VERSION_H__ -#define	U_BOOT_VERSION	"U-Boot 0.2.2" +#define	U_BOOT_VERSION	"U-Boot 0.2.3"  #endif	/* __VERSION_H__ */ diff --git a/lib_arm/board.c b/lib_arm/board.c index b6b5cdb76..31cdd9ccd 100644 --- a/lib_arm/board.c +++ b/lib_arm/board.c @@ -46,9 +46,7 @@ static ulong mem_malloc_start = 0;  static ulong mem_malloc_end = 0;  static ulong mem_malloc_brk = 0; -#if !defined(CONFIG_MODEM_SUPPORT)  static -#endif  void mem_malloc_init (ulong dest_addr)  {  	mem_malloc_start = dest_addr; @@ -187,7 +185,7 @@ void start_armboot (void)  	gd_t gd_data;  	bd_t bd_data;  	init_fnc_t **init_fnc_ptr; -#if defined(CONFIG_VFD) && !defined(CONFIG_MODEM_SUPPORT) +#if defined(CONFIG_VFD)  	unsigned long addr;  #endif @@ -208,10 +206,9 @@ void start_armboot (void)  	display_flash_config (size);  #ifdef CONFIG_VFD -#ifndef CONFIG_MODEM_SUPPORT -#ifndef PAGE_SIZE -#define PAGE_SIZE 4096 -#endif +#  ifndef PAGE_SIZE +#   define PAGE_SIZE 4096 +#  endif  	/*  	 * reserve memory for VFD display (always full pages)  	 */ @@ -223,20 +220,18 @@ void start_armboot (void)  	addr += size;  	addr = (addr + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);  	mem_malloc_init (addr); -#endif /* CONFIG_MODEM_SUPPORT */  #else  	/* armboot_real_end is defined in the board-specific linker script */  	mem_malloc_init (_armboot_real_end);  #endif /* CONFIG_VFD */ +	/* initialize environment */ +	env_relocate (); +  #ifdef CONFIG_VFD -#ifndef CONFIG_MODEM_SUPPORT  	/* must do this after the framebuffer is allocated */  	drv_vfd_init(); -#endif /* CONFIG_MODEM_SUPPORT */  #endif -	/* initialize environment */ -	env_relocate ();  	/* IP Address */  	bd_data.bi_ip_addr = getenv_IPaddr ("ipaddr"); @@ -267,15 +262,15 @@ void start_armboot (void)  	enable_interrupts ();  #ifdef CONFIG_DRIVER_CS8900 -	if (!getenv ("ethaddr")) { -		cs8900_get_enetaddr (gd->bd->bi_enetaddr); -	} +	cs8900_get_enetaddr (gd->bd->bi_enetaddr);  #endif  #ifdef BOARD_POST_INIT  	board_post_init ();  #endif +printf ("### vfd_type=0x%02X vfd_data_lines_inv=%d\n",gd->vfd_type,gd->vfd_inv_data); +  	/* main_loop() can return to retry autoboot, if so just run it again. */  	for (;;) {  		main_loop (); diff --git a/mips_config.mk b/mips_config.mk new file mode 100644 index 000000000..d8aa5fa77 --- /dev/null +++ b/mips_config.mk @@ -0,0 +1,24 @@ +# +# (C) Copyright 2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +PLATFORM_CPPFLAGS += -DCONFIG_MIPS -D__MIPS__ @@ -39,6 +39,7 @@ extern int eth_3com_initialize(bd_t*);  extern int pcnet_initialize(bd_t*);  extern int fec_initialize(bd_t*);  extern int scc_initialize(bd_t*); +extern int inca_switch_initialize(bd_t*);  static struct eth_device *eth_devices, *eth_current; @@ -95,6 +96,9 @@ int eth_initialize(bd_t *bis)  	eth_devices = NULL;  	eth_current = NULL; +#ifdef CONFIG_INCA_IP_SWITCH +	inca_switch_initialize(bis); +#endif  #ifdef CONFIG_EEPRO100  	eepro100_initialize(bis);  #endif @@ -153,7 +157,7 @@ int eth_initialize(bd_t *bis)  				if (memcmp(dev->enetaddr, "\0\0\0\0\0\0", 6) &&  				    memcmp(dev->enetaddr, env_enetaddr, 6))  				{ -					printf("\nWarning: %s HW address don't match:\n", dev->name); +					printf("\nWarning: %s MAC addresses don't match:\n", dev->name);  					printf("Address in SROM is         "  					       "%02X:%02X:%02X:%02X:%02X:%02X\n",  					       dev->enetaddr[0], dev->enetaddr[1], diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c index de10b02ea..b60395ecb 100644 --- a/tools/env/fw_env.c +++ b/tools/env/fw_env.c @@ -390,8 +390,8 @@ static int flash_io (int mode)  	char *data;  	if ((fd = open(DEVNAME(curdev), mode)) < 0) { -		fprintf (stderr, -				 "Can't open %s: %s\n", +		fprintf (stderr,  +				 "Can't open %s: %s\n",   				 DEVNAME(curdev), strerror(errno));  		return (-1);  	} @@ -406,8 +406,8 @@ static int flash_io (int mode)  			/* switch to next partition for writing */  			otherdev = !curdev;  			if ((fdr = open(DEVNAME(otherdev), mode)) < 0) { -				fprintf (stderr, -						 "Can't open %s: %s\n", +				fprintf (stderr,  +						 "Can't open %s: %s\n",   						 DEVNAME(otherdev), strerror(errno));  				return (-1);  			} @@ -431,20 +431,20 @@ static int flash_io (int mode)  		resid = DEVESIZE(otherdev) - CFG_ENV_SIZE;  		if (resid) {  			if ((data = malloc(resid)) == NULL) { -				fprintf(stderr, +				fprintf(stderr,   				  "Cannot malloc %d bytes: %s\n",  				  resid, strerror(errno));  				return (-1);  			}  			if (lseek (fdr, DEVOFFSET(otherdev) + CFG_ENV_SIZE, SEEK_SET) == -1) {  				fprintf (stderr, -				  "seek error on %s: %s\n", +				  "seek error on %s: %s\n",   				   DEVNAME(otherdev), strerror(errno));  				return (-1);  			}  			if ((rc = read (fdr, data, resid)) != resid) {  				fprintf (stderr, -				  "read error on %s: %s\n", +				  "read error on %s: %s\n",   				  DEVNAME(otherdev), strerror(errno));  				return (-1);  			} @@ -465,26 +465,26 @@ static int flash_io (int mode)  		printf("Writing environment to %s...\n",DEVNAME(otherdev));  		if (lseek (fdr, DEVOFFSET(otherdev), SEEK_SET) == -1) {  			fprintf (stderr, -			  "seek error on %s: %s\n", +			  "seek error on %s: %s\n",   			  DEVNAME(otherdev), strerror(errno));  			return (-1);  		}  		if (write(fdr, &environment, len) != len) {  			fprintf (stderr, -			  "CRC write error on %s: %s\n", +			  "CRC write error on %s: %s\n",   			  DEVNAME(otherdev), strerror(errno));  			return (-1);  		}  		if (write(fdr, environment.data, ENV_SIZE) != ENV_SIZE) {  			fprintf (stderr, -			  "Write error on %s: %s\n", +			  "Write error on %s: %s\n",   			  DEVNAME(otherdev), strerror(errno));  			return (-1);  		}  		if (resid) {  			if (write (fdr, data, resid) != resid) {  				fprintf (stderr, -				 "write error on %s: %s\n", +				 "write error on %s: %s\n",   				  DEVNAME(curdev), strerror(errno));  				return (-1);  			} @@ -494,14 +494,14 @@ static int flash_io (int mode)  			/* change flag on current active env partition */  			if (lseek (fd, DEVOFFSET(curdev) + sizeof(ulong), SEEK_SET) == -1) {  				fprintf (stderr, -						 "seek error on %s: %s\n", +						 "seek error on %s: %s\n",   						 DEVNAME(curdev), strerror(errno));  				return (-1);  			} -			if (write (fd, &obsolete_flag, sizeof(obsolete_flag)) != +			if (write (fd, &obsolete_flag, sizeof(obsolete_flag)) !=   				sizeof(obsolete_flag)) {  				fprintf (stderr, -						 "Write error on %s: %s\n", +						 "Write error on %s: %s\n",   						 DEVNAME(curdev), strerror(errno));  				return (-1);  			} @@ -517,7 +517,7 @@ static int flash_io (int mode)  			ioctl (fd, MEMLOCK, &erase);  			if (close(fdr)) {  				fprintf (stderr, -						 "I/O error on %s: %s\n", +						 "I/O error on %s: %s\n",   						 DEVNAME(otherdev), strerror(errno));  				return (-1);  			} @@ -527,19 +527,19 @@ static int flash_io (int mode)  		if (lseek (fd, DEVOFFSET(curdev), SEEK_SET) == -1) {  			fprintf (stderr, -					 "seek error on %s: %s\n", +					 "seek error on %s: %s\n",   					 DEVNAME(curdev), strerror(errno));  			return (-1);  		}  		if (read (fd, &environment, len) != len) {  			fprintf (stderr, -			 "CRC read error on %s: %s\n", +			 "CRC read error on %s: %s\n",   			 DEVNAME(curdev), strerror(errno));  			return (-1);  		}  		if ((rc = read (fd, environment.data, ENV_SIZE)) != ENV_SIZE) {  			fprintf (stderr, -			 "Read error on %s: %s\n", +			 "Read error on %s: %s\n",   			  DEVNAME(curdev), strerror(errno));  			return (-1);  		} @@ -547,7 +547,7 @@ static int flash_io (int mode)  	if (close(fd)) {  		fprintf (stderr, -		  "I/O error on %s: %s\n", +		  "I/O error on %s: %s\n",   		  DEVNAME(curdev), strerror(errno));  		return (-1);  	} @@ -587,50 +587,50 @@ static int env_init(void)  	if (parse_config()) /* should fill envdevices */  		return 1; - +	  	if ((addr1 = calloc (1, ENV_SIZE)) == NULL) { -		fprintf (stderr, +		fprintf (stderr,   				 "Not enough memory for environment (%ld bytes)\n",  				 ENV_SIZE);  		return (errno);  	} - +	  	/* read environment from FLASH to local buffer */  	environment.data = addr1;  	curdev = 0;  	if (flash_io (O_RDONLY)) {  		return (errno);  	} - -	crc1_ok = ((crc1 = crc32(0, environment.data, ENV_SIZE)) +	 +	crc1_ok = ((crc1 = crc32(0, environment.data, ENV_SIZE))   			   == environment.crc);  	if (!HaveRedundEnv) {  		if (!crc1_ok) { -			fprintf (stderr, +			fprintf (stderr,   					 "Warning: Bad CRC, using default environment\n");  			environment.data = default_environment;  			free(addr1);  		}  	} else {  		flag1 = environment.flags; - +		  		curdev = 1;  		if ((addr2 = calloc (1, ENV_SIZE)) == NULL) { -			fprintf (stderr, +			fprintf (stderr,   					 "Not enough memory for environment (%ld bytes)\n",  					 ENV_SIZE);  			return (errno); -		} +		}		  		environment.data = addr2; - +		  		if (flash_io (O_RDONLY)) {  			return (errno);  		} - -		crc2_ok = ((crc2 = crc32(0, environment.data, ENV_SIZE)) +		 +		crc2_ok = ((crc2 = crc32(0, environment.data, ENV_SIZE))   				   == environment.crc);  		flag2 = environment.flags; - +		  		if (crc1_ok && ! crc2_ok) {  			environment.data  = addr1;  			environment.flags = flag1; @@ -646,7 +646,7 @@ static int env_init(void)  			free(addr1);  		}  		else if (! crc1_ok && ! crc2_ok) { -			fprintf (stderr, +			fprintf (stderr,   					 "Warning: Bad CRC, using default environment\n");  			environment.data = default_environment;  			curdev = 0; @@ -720,15 +720,15 @@ static int parse_config()  #endif  #endif  	if (stat (DEVNAME(0), &st)) { -		fprintf (stderr, -		 "Cannot access MTD device %s: %s\n", +		fprintf (stderr,  +		 "Cannot access MTD device %s: %s\n",   		 DEVNAME(0), strerror(errno));  		return 1;  	} - +	  	if (HaveRedundEnv && stat (DEVNAME(1), &st)) { -		fprintf (stderr, -		 "Cannot access MTD device %s: %s\n", +		fprintf (stderr,  +		 "Cannot access MTD device %s: %s\n",   		 DEVNAME(2), strerror(errno));  		return 1;  	} @@ -747,12 +747,12 @@ static int get_config (char *fname)  		return 1;  	} -	while ((i < 2) && +	while ((i < 2) &&   		   ((rc = fscanf (fp, "%s %lx %lx %lx",  						  DEVNAME(i), &DEVOFFSET(i), &ENVSIZE(i), &DEVESIZE(i))) != EOF)) {  		/* Skip incomplete conversions and comment strings */ -		if ((rc < 3) || (*DEVNAME(i) == '#')) { +		if ((rc < 3) || (*DEVNAME(i) == '#')) {   			fgets (dump, sizeof(dump), fp); /* Consume till end */  			continue;  		} @@ -760,7 +760,7 @@ static int get_config (char *fname)  		i++;  	}  	fclose(fp); - +	  	HaveRedundEnv = i - 1;  	if (!i) { /* No valid entries found */  		errno = EINVAL; |