mirror of
https://github.com/Stichting-MINIX-Research-Foundation/u-boot.git
synced 2025-09-13 05:55:02 -04:00
Merge branch 'master' of /home/wd/git/u-boot/master/
This commit is contained in:
commit
356cd17cc2
@ -607,7 +607,7 @@ Thomas Lange <thomas@corelatus.se>
|
|||||||
dbau1x00 MIPS32 Au1000
|
dbau1x00 MIPS32 Au1000
|
||||||
gth2 MIPS32 Au1000
|
gth2 MIPS32 Au1000
|
||||||
|
|
||||||
Vlad Lungu <vlad@comsys.ro>
|
Vlad Lungu <vlad.lungu@windriver.com>
|
||||||
qemu_mips MIPS32
|
qemu_mips MIPS32
|
||||||
|
|
||||||
#########################################################################
|
#########################################################################
|
||||||
|
2
Makefile
2
Makefile
@ -424,7 +424,7 @@ $(obj)System.map: $(obj)u-boot
|
|||||||
# This target actually generates 2 files; autoconf.mk and autoconf.mk.dep.
|
# This target actually generates 2 files; autoconf.mk and autoconf.mk.dep.
|
||||||
# the dep file is only include in this top level makefile to determine when
|
# the dep file is only include in this top level makefile to determine when
|
||||||
# to regenerate the autoconf.mk file.
|
# to regenerate the autoconf.mk file.
|
||||||
$(obj)include/autoconf.mk: $(obj)include/config.h $(VERSION_FILE)
|
$(obj)include/autoconf.mk: $(obj)include/config.h
|
||||||
@$(XECHO) Generating include/autoconf.mk ; \
|
@$(XECHO) Generating include/autoconf.mk ; \
|
||||||
set -e ; \
|
set -e ; \
|
||||||
: Generate the dependancies ; \
|
: Generate the dependancies ; \
|
||||||
|
1
README
1
README
@ -623,7 +623,6 @@ The following options need to be configured:
|
|||||||
CONFIG_CMD_SPI * SPI serial bus support
|
CONFIG_CMD_SPI * SPI serial bus support
|
||||||
CONFIG_CMD_USB * USB support
|
CONFIG_CMD_USB * USB support
|
||||||
CONFIG_CMD_VFD * VFD support (TRAB)
|
CONFIG_CMD_VFD * VFD support (TRAB)
|
||||||
CONFIG_CMD_BSP * Board SPecific functions
|
|
||||||
CONFIG_CMD_CDP * Cisco Discover Protocol support
|
CONFIG_CMD_CDP * Cisco Discover Protocol support
|
||||||
CONFIG_CMD_FSL * Microblaze FSL support
|
CONFIG_CMD_FSL * Microblaze FSL support
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
By Vlad Lungu vlad@comsys.ro 2007-Oct-01
|
By Vlad Lungu vlad.lungu@windriver.com 2007-Oct-01
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
Qemu is a full system emulator. See
|
Qemu is a full system emulator. See
|
||||||
|
|
||||||
@ -9,3 +9,7 @@ Limitations & comments
|
|||||||
Supports the "-m mips" configuration of qemu: serial,NE2000,IDE.
|
Supports the "-m mips" configuration of qemu: serial,NE2000,IDE.
|
||||||
Support is big endian only for now (or at least this is what I tested).
|
Support is big endian only for now (or at least this is what I tested).
|
||||||
Derived from au1x00 with a lot of things cut out.
|
Derived from au1x00 with a lot of things cut out.
|
||||||
|
|
||||||
|
Supports emulated flash (patch Jean-Christophe PLAGNIOL-VILLARD) with
|
||||||
|
recent qemu versions. When using emulated flash, launch with
|
||||||
|
-pflash <filename> and erase mips_bios.bin.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* (C) Copyright 2007
|
* (C) Copyright 2007
|
||||||
* Vlad Lungu vlad@comsys.ro
|
* Vlad Lungu vlad.lungu@windriver.com
|
||||||
*
|
*
|
||||||
* See file CREDITS for list of people who contributed to this
|
* See file CREDITS for list of people who contributed to this
|
||||||
* project.
|
* project.
|
||||||
|
@ -52,10 +52,6 @@
|
|||||||
# include <status_led.h>
|
# include <status_led.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __PPC__
|
|
||||||
#include <asm/io.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_IDE_8xx_DIRECT
|
#ifdef CONFIG_IDE_8xx_DIRECT
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
#endif
|
#endif
|
||||||
|
@ -93,6 +93,7 @@ static table_entry_t uimage_arch[] = {
|
|||||||
{ IH_ARCH_MIPS64, "mips64", "MIPS 64 Bit", },
|
{ IH_ARCH_MIPS64, "mips64", "MIPS 64 Bit", },
|
||||||
{ IH_ARCH_NIOS, "nios", "NIOS", },
|
{ IH_ARCH_NIOS, "nios", "NIOS", },
|
||||||
{ IH_ARCH_NIOS2, "nios2", "NIOS II", },
|
{ IH_ARCH_NIOS2, "nios2", "NIOS II", },
|
||||||
|
{ IH_ARCH_PPC, "powerpc", "PowerPC", },
|
||||||
{ IH_ARCH_PPC, "ppc", "PowerPC", },
|
{ IH_ARCH_PPC, "ppc", "PowerPC", },
|
||||||
{ IH_ARCH_S390, "s390", "IBM S390", },
|
{ IH_ARCH_S390, "s390", "IBM S390", },
|
||||||
{ IH_ARCH_SH, "sh", "SuperH", },
|
{ IH_ARCH_SH, "sh", "SuperH", },
|
||||||
|
@ -329,14 +329,28 @@ _GLOBAL(dcache_status)
|
|||||||
blr
|
blr
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Invalidate L2 cache using L2I and polling L2IP
|
* Invalidate L2 cache using L2I and polling L2IP or L2I
|
||||||
*/
|
*/
|
||||||
_GLOBAL(l2cache_invalidate)
|
_GLOBAL(l2cache_invalidate)
|
||||||
sync
|
sync
|
||||||
|
mfspr r3, l2cr
|
||||||
oris r3, r3, L2CR_L2I@h
|
oris r3, r3, L2CR_L2I@h
|
||||||
sync
|
sync
|
||||||
mtspr l2cr, r3
|
mtspr l2cr, r3
|
||||||
sync
|
sync
|
||||||
|
mfspr r3, PVR
|
||||||
|
sync
|
||||||
|
rlwinm r3, r3, 16,16,31
|
||||||
|
cmpli 0,r3,0x8000 /* 7451, 7441 */
|
||||||
|
beq 0,inv_7450
|
||||||
|
cmpli 0,r3,0x8001 /* 7455, 7445 */
|
||||||
|
beq 0,inv_7450
|
||||||
|
cmpli 0,r3,0x8002 /* 7457, 7447 */
|
||||||
|
beq 0,inv_7450
|
||||||
|
cmpli 0,r3,0x8003 /* 7447A */
|
||||||
|
beq 0,inv_7450
|
||||||
|
cmpli 0,r3,0x8004 /* 7448 */
|
||||||
|
beq 0,inv_7450
|
||||||
invl2:
|
invl2:
|
||||||
mfspr r3, l2cr
|
mfspr r3, l2cr
|
||||||
andi. r3, r3, L2CR_L2IP
|
andi. r3, r3, L2CR_L2IP
|
||||||
@ -348,6 +362,11 @@ invl2:
|
|||||||
mtspr l2cr, r3
|
mtspr l2cr, r3
|
||||||
sync
|
sync
|
||||||
blr
|
blr
|
||||||
|
inv_7450:
|
||||||
|
mfspr r3, l2cr
|
||||||
|
andis. r3, r3, L2CR_L2I@h
|
||||||
|
bne inv_7450
|
||||||
|
blr
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enable L2 cache
|
* Enable L2 cache
|
||||||
|
@ -69,4 +69,4 @@ int usb_cpu_init_fail (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
# endif /* defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) */
|
# endif /* defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) */
|
||||||
#endif /* defined(CONFIG_USB_OHCI) && defined(CFG_USB_OHCI_CPU_INIT) */
|
#endif /* defined(CONFIG_USB_OHCI_NEW) && defined(CFG_USB_OHCI_CPU_INIT) */
|
||||||
|
@ -338,7 +338,7 @@ _GLOBAL(l2cache_invalidate)
|
|||||||
|
|
||||||
invl2:
|
invl2:
|
||||||
mfspr r3, l2cr
|
mfspr r3, l2cr
|
||||||
andi. r3, r3, L2CR_L2I@h
|
andis. r3, r3, L2CR_L2I@h
|
||||||
bne invl2
|
bne invl2
|
||||||
blr
|
blr
|
||||||
|
|
||||||
|
72
disk/part.c
72
disk/part.c
@ -109,43 +109,44 @@ void dev_print (block_dev_desc_t *dev_desc)
|
|||||||
lbaint_t lba512;
|
lbaint_t lba512;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (dev_desc->type==DEV_TYPE_UNKNOWN) {
|
switch (dev_desc->type) {
|
||||||
puts ("not available\n");
|
case IF_TYPE_SCSI:
|
||||||
return;
|
printf ("(%d:%d) Vendor: %s Prod.: %s Rev: %s\n",
|
||||||
}
|
dev_desc->target,dev_desc->lun,
|
||||||
if (dev_desc->if_type==IF_TYPE_SCSI) {
|
|
||||||
printf ("(%d:%d) ", dev_desc->target,dev_desc->lun);
|
|
||||||
}
|
|
||||||
if (dev_desc->if_type==IF_TYPE_IDE) {
|
|
||||||
printf ("Model: %s Firm: %s Ser#: %s\n",
|
|
||||||
dev_desc->vendor,
|
|
||||||
dev_desc->revision,
|
|
||||||
dev_desc->product);
|
|
||||||
}
|
|
||||||
if (dev_desc->if_type==IF_TYPE_SATA) {
|
|
||||||
printf ("Model: %s Firm: %s Ser#: %s\n",
|
|
||||||
dev_desc->vendor,
|
|
||||||
dev_desc->revision,
|
|
||||||
dev_desc->product);
|
|
||||||
} else {
|
|
||||||
printf ("Vendor: %s Prod.: %s Rev: %s\n",
|
|
||||||
dev_desc->vendor,
|
dev_desc->vendor,
|
||||||
dev_desc->product,
|
dev_desc->product,
|
||||||
dev_desc->revision);
|
dev_desc->revision);
|
||||||
|
break;
|
||||||
|
case IF_TYPE_IDE:
|
||||||
|
case IF_TYPE_SATA:
|
||||||
|
printf ("Model: %s Firm: %s Ser#: %s\n",
|
||||||
|
dev_desc->vendor,
|
||||||
|
dev_desc->revision,
|
||||||
|
dev_desc->product);
|
||||||
|
break;
|
||||||
|
case DEV_TYPE_UNKNOWN:
|
||||||
|
default:
|
||||||
|
puts ("not available\n");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
puts (" Type: ");
|
puts (" Type: ");
|
||||||
if (dev_desc->removable)
|
if (dev_desc->removable)
|
||||||
puts ("Removable ");
|
puts ("Removable ");
|
||||||
switch (dev_desc->type & 0x1F) {
|
switch (dev_desc->type & 0x1F) {
|
||||||
case DEV_TYPE_HARDDISK: puts ("Hard Disk");
|
case DEV_TYPE_HARDDISK:
|
||||||
|
puts ("Hard Disk");
|
||||||
break;
|
break;
|
||||||
case DEV_TYPE_CDROM: puts ("CD ROM");
|
case DEV_TYPE_CDROM:
|
||||||
|
puts ("CD ROM");
|
||||||
break;
|
break;
|
||||||
case DEV_TYPE_OPDISK: puts ("Optical Device");
|
case DEV_TYPE_OPDISK:
|
||||||
|
puts ("Optical Device");
|
||||||
break;
|
break;
|
||||||
case DEV_TYPE_TAPE: puts ("Tape");
|
case DEV_TYPE_TAPE:
|
||||||
|
puts ("Tape");
|
||||||
break;
|
break;
|
||||||
default: printf ("# %02X #", dev_desc->type & 0x1F);
|
default:
|
||||||
|
printf ("# %02X #", dev_desc->type & 0x1F);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
puts ("\n");
|
puts ("\n");
|
||||||
@ -281,19 +282,26 @@ static void print_part_header (const char *type, block_dev_desc_t * dev_desc)
|
|||||||
{
|
{
|
||||||
puts ("\nPartition Map for ");
|
puts ("\nPartition Map for ");
|
||||||
switch (dev_desc->if_type) {
|
switch (dev_desc->if_type) {
|
||||||
case IF_TYPE_IDE: puts ("IDE");
|
case IF_TYPE_IDE:
|
||||||
|
puts ("IDE");
|
||||||
break;
|
break;
|
||||||
case IF_TYPE_SATA: puts ("SATA");
|
case IF_TYPE_SATA:
|
||||||
|
puts ("SATA");
|
||||||
break;
|
break;
|
||||||
case IF_TYPE_SCSI: puts ("SCSI");
|
case IF_TYPE_SCSI:
|
||||||
|
puts ("SCSI");
|
||||||
break;
|
break;
|
||||||
case IF_TYPE_ATAPI: puts ("ATAPI");
|
case IF_TYPE_ATAPI:
|
||||||
|
puts ("ATAPI");
|
||||||
break;
|
break;
|
||||||
case IF_TYPE_USB: puts ("USB");
|
case IF_TYPE_USB:
|
||||||
|
puts ("USB");
|
||||||
break;
|
break;
|
||||||
case IF_TYPE_DOC: puts ("DOC");
|
case IF_TYPE_DOC:
|
||||||
|
puts ("DOC");
|
||||||
break;
|
break;
|
||||||
default: puts ("UNKNOWN");
|
default:
|
||||||
|
puts ("UNKNOWN");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf (" device %d -- Partition Type: %s\n\n",
|
printf (" device %d -- Partition Type: %s\n\n",
|
||||||
|
@ -9,7 +9,7 @@ The PPC440EP(x)/GR(x) cpu's can boot directly from NAND FLASH,
|
|||||||
completely without NOR FLASH. This can be done by using the NAND
|
completely without NOR FLASH. This can be done by using the NAND
|
||||||
boot feature of the 440 NAND flash controller (NDFC).
|
boot feature of the 440 NAND flash controller (NDFC).
|
||||||
|
|
||||||
Here a short desciption of the different boot stages:
|
Here a short description of the different boot stages:
|
||||||
|
|
||||||
a) IPL (Initial Program Loader, integrated inside CPU)
|
a) IPL (Initial Program Loader, integrated inside CPU)
|
||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
|
4
include/.gitignore
vendored
4
include/.gitignore
vendored
@ -1,7 +1,7 @@
|
|||||||
/autoconf.mk*
|
/autoconf.mk*
|
||||||
/asm
|
/asm
|
||||||
/asm-blackfin/arch
|
/asm-*/arch
|
||||||
/asm-ppc/arch
|
/asm-*/proc
|
||||||
/bmp_logo.h
|
/bmp_logo.h
|
||||||
/config.h
|
/config.h
|
||||||
/config.mk
|
/config.mk
|
||||||
|
@ -56,9 +56,11 @@
|
|||||||
/* ethernet */
|
/* ethernet */
|
||||||
#ifdef XILINX_EMAC_BASEADDR
|
#ifdef XILINX_EMAC_BASEADDR
|
||||||
#define CONFIG_XILINX_EMAC 1
|
#define CONFIG_XILINX_EMAC 1
|
||||||
|
#define CFG_ENET
|
||||||
#else
|
#else
|
||||||
#ifdef XILINX_EMACLITE_BASEADDR
|
#ifdef XILINX_EMACLITE_BASEADDR
|
||||||
#define CONFIG_XILINX_EMACLITE 1
|
#define CONFIG_XILINX_EMACLITE 1
|
||||||
|
#define CFG_ENET
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#undef ET_DEBUG
|
#undef ET_DEBUG
|
||||||
@ -70,18 +72,28 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* interrupt controller */
|
/* interrupt controller */
|
||||||
|
#ifdef XILINX_INTC_BASEADDR
|
||||||
#define CFG_INTC_0 1
|
#define CFG_INTC_0 1
|
||||||
#define CFG_INTC_0_ADDR XILINX_INTC_BASEADDR
|
#define CFG_INTC_0_ADDR XILINX_INTC_BASEADDR
|
||||||
#define CFG_INTC_0_NUM XILINX_INTC_NUM_INTR_INPUTS
|
#define CFG_INTC_0_NUM XILINX_INTC_NUM_INTR_INPUTS
|
||||||
|
#endif
|
||||||
|
|
||||||
/* timer */
|
/* timer */
|
||||||
|
#ifdef XILINX_TIMER_BASEADDR
|
||||||
|
#if (XILINX_TIMER_IRQ != -1)
|
||||||
#define CFG_TIMER_0 1
|
#define CFG_TIMER_0 1
|
||||||
#define CFG_TIMER_0_ADDR XILINX_TIMER_BASEADDR
|
#define CFG_TIMER_0_ADDR XILINX_TIMER_BASEADDR
|
||||||
#define CFG_TIMER_0_IRQ XILINX_TIMER_IRQ
|
#define CFG_TIMER_0_IRQ XILINX_TIMER_IRQ
|
||||||
#define FREQUENCE XILINX_CLOCK_FREQ
|
#define FREQUENCE XILINX_CLOCK_FREQ
|
||||||
#define CFG_TIMER_0_PRELOAD ( FREQUENCE/1000 )
|
#define CFG_TIMER_0_PRELOAD ( FREQUENCE/1000 )
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#ifdef XILINX_CLOCK_FREQ
|
||||||
#define CONFIG_XILINX_CLOCK_FREQ XILINX_CLOCK_FREQ
|
#define CONFIG_XILINX_CLOCK_FREQ XILINX_CLOCK_FREQ
|
||||||
|
#else
|
||||||
|
#error BAD CLOCK FREQ
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
/* FSL */
|
/* FSL */
|
||||||
/* #define CFG_FSL_2 */
|
/* #define CFG_FSL_2 */
|
||||||
/* #define FSL_INTR_2 1 */
|
/* #define FSL_INTR_2 1 */
|
||||||
@ -195,7 +207,12 @@
|
|||||||
#define CONFIG_CMD_CACHE
|
#define CONFIG_CMD_CACHE
|
||||||
#define CONFIG_CMD_IRQ
|
#define CONFIG_CMD_IRQ
|
||||||
#define CONFIG_CMD_MFSL
|
#define CONFIG_CMD_MFSL
|
||||||
|
|
||||||
|
#ifndef CFG_ENET
|
||||||
|
#undef CONFIG_CMD_NET
|
||||||
|
#else
|
||||||
#define CONFIG_CMD_PING
|
#define CONFIG_CMD_PING
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_SYSTEMACE)
|
#if defined(CONFIG_SYSTEMACE)
|
||||||
#define CONFIG_CMD_EXT2
|
#define CONFIG_CMD_EXT2
|
||||||
|
@ -63,9 +63,11 @@
|
|||||||
/* ethernet */
|
/* ethernet */
|
||||||
#ifdef XILINX_EMAC_BASEADDR
|
#ifdef XILINX_EMAC_BASEADDR
|
||||||
#define CONFIG_XILINX_EMAC 1
|
#define CONFIG_XILINX_EMAC 1
|
||||||
|
#define CFG_ENET
|
||||||
#else
|
#else
|
||||||
#ifdef XILINX_EMACLITE_BASEADDR
|
#ifdef XILINX_EMACLITE_BASEADDR
|
||||||
#define CONFIG_XILINX_EMACLITE 1
|
#define CONFIG_XILINX_EMACLITE 1
|
||||||
|
#define CFG_ENET
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#undef ET_DEBUG
|
#undef ET_DEBUG
|
||||||
@ -77,18 +79,28 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* interrupt controller */
|
/* interrupt controller */
|
||||||
|
#ifdef XILINX_INTC_BASEADDR
|
||||||
#define CFG_INTC_0 1
|
#define CFG_INTC_0 1
|
||||||
#define CFG_INTC_0_ADDR XILINX_INTC_BASEADDR
|
#define CFG_INTC_0_ADDR XILINX_INTC_BASEADDR
|
||||||
#define CFG_INTC_0_NUM XILINX_INTC_NUM_INTR_INPUTS
|
#define CFG_INTC_0_NUM XILINX_INTC_NUM_INTR_INPUTS
|
||||||
|
#endif
|
||||||
|
|
||||||
/* timer */
|
/* timer */
|
||||||
|
#ifdef XILINX_TIMER_BASEADDR
|
||||||
|
#if (XILINX_TIMER_IRQ != -1)
|
||||||
#define CFG_TIMER_0 1
|
#define CFG_TIMER_0 1
|
||||||
#define CFG_TIMER_0_ADDR XILINX_TIMER_BASEADDR
|
#define CFG_TIMER_0_ADDR XILINX_TIMER_BASEADDR
|
||||||
#define CFG_TIMER_0_IRQ XILINX_TIMER_IRQ
|
#define CFG_TIMER_0_IRQ XILINX_TIMER_IRQ
|
||||||
#define FREQUENCE XILINX_CLOCK_FREQ
|
#define FREQUENCE XILINX_CLOCK_FREQ
|
||||||
#define CFG_TIMER_0_PRELOAD ( FREQUENCE/1000 )
|
#define CFG_TIMER_0_PRELOAD ( FREQUENCE/1000 )
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#ifdef XILINX_CLOCK_FREQ
|
||||||
#define CONFIG_XILINX_CLOCK_FREQ XILINX_CLOCK_FREQ
|
#define CONFIG_XILINX_CLOCK_FREQ XILINX_CLOCK_FREQ
|
||||||
|
#else
|
||||||
|
#error BAD CLOCK FREQ
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
* memory layout - Example
|
* memory layout - Example
|
||||||
* TEXT_BASE = 0x3600_0000;
|
* TEXT_BASE = 0x3600_0000;
|
||||||
@ -162,7 +174,12 @@
|
|||||||
#define CONFIG_CMD_ASKENV
|
#define CONFIG_CMD_ASKENV
|
||||||
#define CONFIG_CMD_CACHE
|
#define CONFIG_CMD_CACHE
|
||||||
#define CONFIG_CMD_IRQ
|
#define CONFIG_CMD_IRQ
|
||||||
|
|
||||||
|
#ifndef CFG_ENET
|
||||||
|
#undef CONFIG_CMD_NET
|
||||||
|
#else
|
||||||
#define CONFIG_CMD_PING
|
#define CONFIG_CMD_PING
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef XILINX_SYSACE_BASEADDR
|
#ifdef XILINX_SYSACE_BASEADDR
|
||||||
#define CONFIG_CMD_EXT2
|
#define CONFIG_CMD_EXT2
|
||||||
|
Loading…
x
Reference in New Issue
Block a user