summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/Makefile14
-rw-r--r--drivers/acpi/acpi_ksyms.c83
-rw-r--r--drivers/acpi/cmbatt.c26
-rw-r--r--drivers/acpi/common/cmalloc.c8
-rw-r--r--drivers/acpi/common/cmclib.c9
-rw-r--r--drivers/acpi/common/cmcopy.c12
-rw-r--r--drivers/acpi/common/cmdebug.c6
-rw-r--r--drivers/acpi/common/cmdelete.c4
-rw-r--r--drivers/acpi/common/cmeval.c24
-rw-r--r--drivers/acpi/common/cmglobal.c13
-rw-r--r--drivers/acpi/common/cminit.c49
-rw-r--r--drivers/acpi/common/cmobject.c6
-rw-r--r--drivers/acpi/common/cmutils.c16
-rw-r--r--drivers/acpi/common/cmxface.c18
-rw-r--r--drivers/acpi/cpu.c51
-rw-r--r--drivers/acpi/dispatcher/dsfield.c4
-rw-r--r--drivers/acpi/dispatcher/dsmethod.c4
-rw-r--r--drivers/acpi/dispatcher/dsmthdat.c47
-rw-r--r--drivers/acpi/dispatcher/dsobject.c20
-rw-r--r--drivers/acpi/dispatcher/dsopcode.c12
-rw-r--r--drivers/acpi/dispatcher/dsutils.c6
-rw-r--r--drivers/acpi/dispatcher/dswexec.c16
-rw-r--r--drivers/acpi/dispatcher/dswload.c4
-rw-r--r--drivers/acpi/dispatcher/dswscope.c4
-rw-r--r--drivers/acpi/dispatcher/dswstate.c59
-rw-r--r--drivers/acpi/driver.c28
-rw-r--r--drivers/acpi/ec.c29
-rw-r--r--drivers/acpi/events/evevent.c4
-rw-r--r--drivers/acpi/events/evmisc.c4
-rw-r--r--drivers/acpi/events/evregion.c24
-rw-r--r--drivers/acpi/events/evrgnini.c4
-rw-r--r--drivers/acpi/events/evsci.c4
-rw-r--r--drivers/acpi/events/evxface.c244
-rw-r--r--drivers/acpi/events/evxfevnt.c4
-rw-r--r--drivers/acpi/events/evxfregn.c4
-rw-r--r--drivers/acpi/hardware/hwacpi.c52
-rw-r--r--drivers/acpi/hardware/hwgpe.c5
-rw-r--r--drivers/acpi/hardware/hwregs.c57
-rw-r--r--drivers/acpi/hardware/hwsleep.c189
-rw-r--r--drivers/acpi/hardware/hwtimer.c196
-rw-r--r--drivers/acpi/include/accommon.h15
-rw-r--r--drivers/acpi/include/acconfig.h10
-rw-r--r--drivers/acpi/include/acdebug.h4
-rw-r--r--drivers/acpi/include/acdispat.h4
-rw-r--r--drivers/acpi/include/acenv.h30
-rw-r--r--drivers/acpi/include/acevents.h4
-rw-r--r--drivers/acpi/include/acexcep.h10
-rw-r--r--drivers/acpi/include/acgcc.h4
-rw-r--r--drivers/acpi/include/acglobal.h8
-rw-r--r--drivers/acpi/include/achware.h98
-rw-r--r--drivers/acpi/include/acinterp.h93
-rw-r--r--drivers/acpi/include/aclinux.h4
-rw-r--r--drivers/acpi/include/aclocal.h130
-rw-r--r--drivers/acpi/include/acmacros.h29
-rw-r--r--drivers/acpi/include/acnamesp.h4
-rw-r--r--drivers/acpi/include/acobject.h14
-rw-r--r--drivers/acpi/include/acoutput.h5
-rw-r--r--drivers/acpi/include/acparser.h4
-rw-r--r--drivers/acpi/include/acpi.h4
-rw-r--r--drivers/acpi/include/acpiosxf.h6
-rw-r--r--drivers/acpi/include/acpixf.h6
-rw-r--r--drivers/acpi/include/acresrc.h4
-rw-r--r--drivers/acpi/include/actables.h4
-rw-r--r--drivers/acpi/include/actbl.h4
-rw-r--r--drivers/acpi/include/actbl1.h4
-rw-r--r--drivers/acpi/include/actbl2.h8
-rw-r--r--drivers/acpi/include/actbl71.h4
-rw-r--r--drivers/acpi/include/actypes.h44
-rw-r--r--drivers/acpi/include/amlcode.h49
-rw-r--r--drivers/acpi/interpreter/amconfig.c10
-rw-r--r--drivers/acpi/interpreter/amconvrt.c525
-rw-r--r--drivers/acpi/interpreter/amcreate.c6
-rw-r--r--drivers/acpi/interpreter/amdyadic.c369
-rw-r--r--drivers/acpi/interpreter/amfield.c9
-rw-r--r--drivers/acpi/interpreter/amfldio.c84
-rw-r--r--drivers/acpi/interpreter/ammisc.c70
-rw-r--r--drivers/acpi/interpreter/ammonad.c68
-rw-r--r--drivers/acpi/interpreter/amnames.c4
-rw-r--r--drivers/acpi/interpreter/amprep.c4
-rw-r--r--drivers/acpi/interpreter/amregion.c10
-rw-r--r--drivers/acpi/interpreter/amresnte.c26
-rw-r--r--drivers/acpi/interpreter/amresolv.c30
-rw-r--r--drivers/acpi/interpreter/amresop.c89
-rw-r--r--drivers/acpi/interpreter/amstore.c455
-rw-r--r--drivers/acpi/interpreter/amstoren.c490
-rw-r--r--drivers/acpi/interpreter/amstorob.c524
-rw-r--r--drivers/acpi/interpreter/amsystem.c8
-rw-r--r--drivers/acpi/interpreter/amutils.c21
-rw-r--r--drivers/acpi/interpreter/amxface.c4
-rw-r--r--drivers/acpi/namespace/nsaccess.c16
-rw-r--r--drivers/acpi/namespace/nsalloc.c4
-rw-r--r--drivers/acpi/namespace/nseval.c4
-rw-r--r--drivers/acpi/namespace/nsinit.c15
-rw-r--r--drivers/acpi/namespace/nsload.c4
-rw-r--r--drivers/acpi/namespace/nsnames.c4
-rw-r--r--drivers/acpi/namespace/nsobject.c6
-rw-r--r--drivers/acpi/namespace/nssearch.c6
-rw-r--r--drivers/acpi/namespace/nsutils.c4
-rw-r--r--drivers/acpi/namespace/nswalk.c4
-rw-r--r--drivers/acpi/namespace/nsxfname.c4
-rw-r--r--drivers/acpi/namespace/nsxfobj.c5
-rw-r--r--drivers/acpi/os.c2
-rw-r--r--drivers/acpi/parser/psargs.c4
-rw-r--r--drivers/acpi/parser/psopcode.c171
-rw-r--r--drivers/acpi/parser/psparse.c10
-rw-r--r--drivers/acpi/parser/psscope.c4
-rw-r--r--drivers/acpi/parser/pstree.c4
-rw-r--r--drivers/acpi/parser/psutils.c4
-rw-r--r--drivers/acpi/parser/pswalk.c4
-rw-r--r--drivers/acpi/parser/psxface.c10
-rw-r--r--drivers/acpi/power.c4
-rw-r--r--drivers/acpi/resources/rsaddr.c4
-rw-r--r--drivers/acpi/resources/rscalc.c4
-rw-r--r--drivers/acpi/resources/rscreate.c18
-rw-r--r--drivers/acpi/resources/rsdump.c4
-rw-r--r--drivers/acpi/resources/rsio.c4
-rw-r--r--drivers/acpi/resources/rsirq.c4
-rw-r--r--drivers/acpi/resources/rslist.c4
-rw-r--r--drivers/acpi/resources/rsmemory.c4
-rw-r--r--drivers/acpi/resources/rsmisc.c4
-rw-r--r--drivers/acpi/resources/rsutils.c4
-rw-r--r--drivers/acpi/resources/rsxface.c4
-rw-r--r--drivers/acpi/sys.c70
-rw-r--r--drivers/acpi/table.c21
-rw-r--r--drivers/acpi/tables/tbconvrt.c21
-rw-r--r--drivers/acpi/tables/tbget.c16
-rw-r--r--drivers/acpi/tables/tbinstal.c4
-rw-r--r--drivers/acpi/tables/tbutils.c4
-rw-r--r--drivers/acpi/tables/tbxface.c4
-rw-r--r--drivers/acpi/tables/tbxfroot.c4
-rw-r--r--drivers/atm/Makefile2
-rw-r--r--drivers/block/DAC960.c8
-rw-r--r--drivers/block/cciss.c1
-rw-r--r--drivers/block/cpqarray.c158
-rw-r--r--drivers/block/elevator.c130
-rw-r--r--drivers/block/ll_rw_blk.c335
-rw-r--r--drivers/block/paride/pd.c2
-rw-r--r--drivers/block/paride/pf.c2
-rw-r--r--drivers/cdrom/cdrom.c4
-rw-r--r--drivers/char/agp/agpgart_be.c11
-rw-r--r--drivers/char/drm/Config.in3
-rw-r--r--drivers/char/drm/Makefile17
-rw-r--r--drivers/char/drm/drm.h187
-rw-r--r--drivers/char/drm/radeon_bufs.c298
-rw-r--r--drivers/char/drm/radeon_context.c215
-rw-r--r--drivers/char/drm/radeon_cp.c1314
-rw-r--r--drivers/char/drm/radeon_drm.h325
-rw-r--r--drivers/char/drm/radeon_drv.c702
-rw-r--r--drivers/char/drm/radeon_drv.h709
-rw-r--r--drivers/char/drm/radeon_state.c1447
-rw-r--r--drivers/char/misc.c4
-rw-r--r--drivers/char/n_tty.c36
-rw-r--r--drivers/i2o/i2o_block.c7
-rw-r--r--drivers/ide/hpt366.c9
-rw-r--r--drivers/ide/ide-cd.c37
-rw-r--r--drivers/ide/ide-dma.c8
-rw-r--r--drivers/ide/ide-probe.c7
-rw-r--r--drivers/ide/via82cxxx.c2
-rw-r--r--drivers/isdn/hisax/Makefile4
-rw-r--r--drivers/isdn/hisax/config.c4
-rw-r--r--drivers/isdn/hisax/isdnl3.c2
-rw-r--r--drivers/isdn/hisax/md5sums.asc12
-rw-r--r--drivers/isdn/isdn_common.c5
-rw-r--r--drivers/isdn/isdn_net.c1
-rw-r--r--drivers/isdn/isdn_ppp.c14
-rw-r--r--drivers/isdn/isdn_v110.c4
-rw-r--r--drivers/md/Config.in5
-rw-r--r--drivers/md/lvm-snap.c32
-rw-r--r--drivers/md/lvm-snap.h47
-rw-r--r--drivers/md/lvm.c632
-rw-r--r--drivers/md/md.c112
-rw-r--r--drivers/md/raid5.c5
-rw-r--r--drivers/md/xor.c3
-rw-r--r--drivers/net/3c59x.c108
-rw-r--r--drivers/net/Makefile2
-rw-r--r--drivers/net/depca.c4
-rw-r--r--drivers/net/dmfe.c4
-rw-r--r--drivers/net/eepro100.c15
-rw-r--r--drivers/net/hamradio/mkiss.c2
-rw-r--r--drivers/net/hamradio/scc.c4
-rw-r--r--drivers/net/myri_sbus.c10
-rw-r--r--drivers/net/pcnet32.c2
-rw-r--r--drivers/net/ppp_async.c89
-rw-r--r--drivers/net/pppoe.c40
-rw-r--r--drivers/net/sunbmac.c61
-rw-r--r--drivers/net/tulip/ChangeLog36
-rw-r--r--drivers/net/tulip/eeprom.c12
-rw-r--r--drivers/net/tulip/media.c6
-rw-r--r--drivers/net/tulip/tulip_core.c2
-rw-r--r--drivers/net/wan/lapbether.c172
-rw-r--r--drivers/net/wan/lmc/lmc.h3
-rw-r--r--drivers/net/wan/lmc/lmc_media.h3
-rw-r--r--drivers/net/wan/lmc/lmc_prot.h3
-rw-r--r--drivers/net/wan/lmc/lmc_proto.h3
-rw-r--r--drivers/net/wan/sdla.c2
-rw-r--r--drivers/pnp/isapnp_proc.c17
-rw-r--r--drivers/s390/block/dasd.c1
-rw-r--r--drivers/sbus/audio/Config.in6
-rw-r--r--drivers/sbus/audio/amd7930.c6
-rw-r--r--drivers/sbus/audio/dbri.c6
-rw-r--r--drivers/sbus/char/Makefile1
-rw-r--r--drivers/sbus/char/bpp.c34
-rw-r--r--drivers/sbus/char/cpwatchdog.c838
-rw-r--r--drivers/sbus/char/flash.c17
-rw-r--r--drivers/sbus/char/jsflash.c2
-rw-r--r--drivers/sbus/char/pcikbd.c19
-rw-r--r--drivers/sbus/char/rtc.c50
-rw-r--r--drivers/sbus/char/sunkbd.c11
-rw-r--r--drivers/sbus/char/sunmouse.c11
-rw-r--r--drivers/sbus/char/vfc_dev.c28
-rw-r--r--drivers/sbus/sbus.c14
-rw-r--r--drivers/scsi/constants.c2
-rw-r--r--drivers/scsi/ibmmca.c9
-rw-r--r--drivers/scsi/megaraid.c1
-rw-r--r--drivers/scsi/ppa.c2
-rw-r--r--drivers/scsi/scsi_lib.c191
-rw-r--r--drivers/scsi/scsi_merge.c12
-rw-r--r--drivers/scsi/sg.c1
-rw-r--r--drivers/scsi/sr.c10
-rw-r--r--drivers/sound/Config.in6
-rw-r--r--drivers/sound/Makefile4
-rw-r--r--drivers/sound/emu10k1/audio.c33
-rw-r--r--drivers/sound/trix.c1
-rw-r--r--drivers/sound/via82cxxx_audio.c707
-rw-r--r--drivers/sound/ymfpci.c998
-rw-r--r--drivers/sound/ymfpci.h116
-rw-r--r--drivers/usb/rio500.c3
-rw-r--r--drivers/usb/serial/Config.in1
-rw-r--r--drivers/usb/serial/usbserial.c23
-rw-r--r--drivers/usb/serial/visor.c7
-rw-r--r--drivers/usb/storage/debug.h2
-rw-r--r--drivers/usb/storage/scsiglue.c2
-rw-r--r--drivers/usb/storage/unusual_devs.h232
-rw-r--r--drivers/usb/storage/usb.c425
-rw-r--r--drivers/usb/storage/usb.h9
-rw-r--r--drivers/video/sbusfb.c6
-rw-r--r--drivers/video/vfb.c2
237 files changed, 12132 insertions, 4450 deletions
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 307cb08ad..e1e0745a4 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -4,7 +4,7 @@
O_TARGET := acpi.o
-export-objs := ksyms.o
+export-objs := acpi_ksyms.o
export ACPI_CFLAGS
ACPI_CFLAGS := -D_LINUX
@@ -20,18 +20,26 @@ EXTRA_CFLAGS += -I./include
EXTRA_CFLAGS += $(ACPI_CFLAGS)
+# genksyms only reads $(CFLAGS), it should really read $(EXTRA_CFLAGS) as well.
+# Without EXTRA_CFLAGS the gcc pass for genksyms fails, resulting in an empty
+# include/linux/modules/acpi_ksyms.ver. Changing genkyms to use EXTRA_CFLAGS
+# will hit everything, too risky in 2.4.0-prerelease. Bandaid by tweaking
+# CFLAGS only for .ver targets. Review after 2.4.0 release. KAO
+
+$(MODINCL)/%.ver: CFLAGS := -I./include $(CFLAGS)
+
acpi-subdirs := common dispatcher events hardware \
interpreter namespace parser resources tables
subdir-$(CONFIG_ACPI) += $(acpi-subdirs)
obj-$(CONFIG_ACPI) := $(patsubst %,%.o,$(acpi-subdirs))
-obj-$(CONFIG_ACPI) += os.o ksyms.o
+obj-$(CONFIG_ACPI) += os.o acpi_ksyms.o
ifdef CONFIG_ACPI_KERNEL_CONFIG
obj-$(CONFIG_ACPI) += acpiconf.o osconf.o
else
- obj-$(CONFIG_ACPI) += driver.o cmbatt.o cpu.o ec.o ksyms.o sys.o table.o power.o
+ obj-$(CONFIG_ACPI) += driver.o cmbatt.o cpu.o ec.o acpi_ksyms.o sys.o table.o power.o
endif
include $(TOPDIR)/Rules.make
diff --git a/drivers/acpi/acpi_ksyms.c b/drivers/acpi/acpi_ksyms.c
new file mode 100644
index 000000000..8e1774c9a
--- /dev/null
+++ b/drivers/acpi/acpi_ksyms.c
@@ -0,0 +1,83 @@
+/*
+ * ksyms.c - ACPI exported symbols
+ *
+ * Copyright (C) 2000 Andrew Grover
+ *
+ * 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
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/acpi.h>
+#include "acpi.h"
+#include "acdebug.h"
+
+extern int acpi_in_debugger;
+
+#define _COMPONENT OS_DEPENDENT
+ MODULE_NAME ("symbols")
+
+#ifdef ENABLE_DEBUGGER
+EXPORT_SYMBOL(acpi_in_debugger);
+EXPORT_SYMBOL(acpi_db_user_commands);
+#endif
+
+EXPORT_SYMBOL(acpi_os_free);
+EXPORT_SYMBOL(acpi_os_breakpoint);
+EXPORT_SYMBOL(acpi_os_printf);
+EXPORT_SYMBOL(acpi_os_callocate);
+EXPORT_SYMBOL(acpi_os_sleep);
+EXPORT_SYMBOL(acpi_os_sleep_usec);
+EXPORT_SYMBOL(acpi_os_in8);
+EXPORT_SYMBOL(acpi_os_out8);
+EXPORT_SYMBOL(acpi_os_queue_for_execution);
+
+EXPORT_SYMBOL(acpi_dbg_layer);
+EXPORT_SYMBOL(acpi_dbg_level);
+EXPORT_SYMBOL(function_exit);
+EXPORT_SYMBOL(function_trace);
+EXPORT_SYMBOL(function_status_exit);
+EXPORT_SYMBOL(function_value_exit);
+EXPORT_SYMBOL(debug_print_raw);
+EXPORT_SYMBOL(debug_print_prefix);
+
+EXPORT_SYMBOL(acpi_cm_strncmp);
+EXPORT_SYMBOL(acpi_cm_memcpy);
+EXPORT_SYMBOL(acpi_cm_memset);
+
+EXPORT_SYMBOL(acpi_get_handle);
+EXPORT_SYMBOL(acpi_get_parent);
+EXPORT_SYMBOL(acpi_get_type);
+EXPORT_SYMBOL(acpi_get_name);
+EXPORT_SYMBOL(acpi_get_object_info);
+EXPORT_SYMBOL(acpi_get_next_object);
+EXPORT_SYMBOL(acpi_evaluate_object);
+
+EXPORT_SYMBOL(acpi_install_notify_handler);
+EXPORT_SYMBOL(acpi_remove_notify_handler);
+EXPORT_SYMBOL(acpi_install_gpe_handler);
+EXPORT_SYMBOL(acpi_remove_gpe_handler);
+EXPORT_SYMBOL(acpi_install_address_space_handler);
+EXPORT_SYMBOL(acpi_remove_address_space_handler);
+
+EXPORT_SYMBOL(acpi_get_current_resources);
+EXPORT_SYMBOL(acpi_get_possible_resources);
+EXPORT_SYMBOL(acpi_set_current_resources);
+
+EXPORT_SYMBOL(acpi_enable_event);
+EXPORT_SYMBOL(acpi_disable_event);
+EXPORT_SYMBOL(acpi_clear_event);
diff --git a/drivers/acpi/cmbatt.c b/drivers/acpi/cmbatt.c
index c45aa810c..d5dc5977a 100644
--- a/drivers/acpi/cmbatt.c
+++ b/drivers/acpi/cmbatt.c
@@ -113,10 +113,10 @@ acpi_get_battery_status(ACPI_HANDLE handle, struct cmbatt_status *result)
obj = (ACPI_OBJECT *) buf.pointer;
objs = obj->package.elements;
- result->state = objs[0].number.value;
- result->present_rate = objs[1].number.value;
- result->remaining_capacity = objs[2].number.value;
- result->present_voltage = objs[3].number.value;
+ result->state = objs[0].integer.value;
+ result->present_rate = objs[1].integer.value;
+ result->remaining_capacity = objs[2].integer.value;
+ result->present_voltage = objs[3].integer.value;
kfree(buf.pointer);
@@ -153,15 +153,15 @@ acpi_get_battery_info(ACPI_HANDLE handle, struct cmbatt_info *result)
obj = (ACPI_OBJECT *) buf.pointer;
objs = obj->package.elements;
- result->power_unit=objs[0].number.value;
- result->design_capacity=objs[1].number.value;
- result->last_full_capacity=objs[2].number.value;
- result->battery_technology=objs[3].number.value;
- result->design_voltage=objs[4].number.value;
- result->design_capacity_warning=objs[5].number.value;
- result->design_capacity_low=objs[6].number.value;
- result->battery_capacity_granularity_1=objs[7].number.value;
- result->battery_capacity_granularity_2=objs[8].number.value;
+ result->power_unit=objs[0].integer.value;
+ result->design_capacity=objs[1].integer.value;
+ result->last_full_capacity=objs[2].integer.value;
+ result->battery_technology=objs[3].integer.value;
+ result->design_voltage=objs[4].integer.value;
+ result->design_capacity_warning=objs[5].integer.value;
+ result->design_capacity_low=objs[6].integer.value;
+ result->battery_capacity_granularity_1=objs[7].integer.value;
+ result->battery_capacity_granularity_2=objs[8].integer.value;
/* BUG: trailing NULL issue */
strncpy(result->model_number, objs[9].string.pointer, MAX_BATT_STRLEN-1);
diff --git a/drivers/acpi/common/cmalloc.c b/drivers/acpi/common/cmalloc.c
index b7a64e5b6..d8514698f 100644
--- a/drivers/acpi/common/cmalloc.c
+++ b/drivers/acpi/common/cmalloc.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: cmalloc - local memory allocation routines
- * $Revision: 79 $
+ * $Revision: 84 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -57,8 +57,6 @@ _cm_allocate (
u32 line)
{
void *address = NULL;
- DEBUG_ONLY_MEMBERS (\
- ACPI_STATUS status)
/* Check for an inadvertent size of zero bytes */
@@ -107,8 +105,6 @@ _cm_callocate (
u32 line)
{
void *address = NULL;
- DEBUG_ONLY_MEMBERS (\
- ACPI_STATUS status)
/* Check for an inadvertent size of zero bytes */
diff --git a/drivers/acpi/common/cmclib.c b/drivers/acpi/common/cmclib.c
index 5146b09c5..88e92d17f 100644
--- a/drivers/acpi/common/cmclib.c
+++ b/drivers/acpi/common/cmclib.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: cmclib - Local implementation of C library functions
- * $Revision: 28 $
+ * $Revision: 32 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -347,7 +347,7 @@ acpi_cm_memcpy (
void *
acpi_cm_memset (
void *dest,
- u32 value,
+ NATIVE_UINT value,
NATIVE_UINT count)
{
NATIVE_CHAR *new = (NATIVE_CHAR *) dest;
@@ -522,6 +522,7 @@ static const u8 _acpi_ctype[257] = {
#define IS_LOWER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO))
#define IS_DIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_DI))
#define IS_SPACE(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_SP))
+#define IS_XDIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_XD))
/*******************************************************************************
@@ -658,7 +659,7 @@ u32
acpi_cm_strtoul (
const NATIVE_CHAR *string,
NATIVE_CHAR **terminator,
- u32 base)
+ NATIVE_UINT base)
{
u32 converted = 0;
u32 index;
diff --git a/drivers/acpi/common/cmcopy.c b/drivers/acpi/common/cmcopy.c
index 68b7bda01..da3851c17 100644
--- a/drivers/acpi/common/cmcopy.c
+++ b/drivers/acpi/common/cmcopy.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: cmcopy - Internal to external object translation utilities
- * $Revision: 61 $
+ * $Revision: 62 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -118,9 +118,9 @@ acpi_cm_build_external_simple_object (
break;
- case ACPI_TYPE_NUMBER:
+ case ACPI_TYPE_INTEGER:
- external_obj->number.value= internal_obj->number.value;
+ external_obj->integer.value= internal_obj->integer.value;
break;
@@ -469,11 +469,11 @@ acpi_cm_build_internal_simple_object (
break;
- case ACPI_TYPE_NUMBER:
+ case ACPI_TYPE_INTEGER:
/*
* Number is included in the object itself
*/
- internal_obj->number.value = external_obj->number.value;
+ internal_obj->integer.value = external_obj->integer.value;
break;
diff --git a/drivers/acpi/common/cmdebug.c b/drivers/acpi/common/cmdebug.c
index a55372d5c..2d0022ac3 100644
--- a/drivers/acpi/common/cmdebug.c
+++ b/drivers/acpi/common/cmdebug.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: cmdebug - Debug print routines
- * $Revision: 61 $
+ * $Revision: 64 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -281,7 +281,7 @@ function_value_exit (
u32 line_number,
u32 component_id,
NATIVE_CHAR *function_name,
- NATIVE_UINT value)
+ ACPI_INTEGER value)
{
debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS,
diff --git a/drivers/acpi/common/cmdelete.c b/drivers/acpi/common/cmdelete.c
index a6e74c12f..b516b691c 100644
--- a/drivers/acpi/common/cmdelete.c
+++ b/drivers/acpi/common/cmdelete.c
@@ -1,12 +1,12 @@
/*******************************************************************************
*
* Module Name: cmdelete - object deletion and reference count utilities
- * $Revision: 60 $
+ * $Revision: 62 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/common/cmeval.c b/drivers/acpi/common/cmeval.c
index 29a5cefa6..653e26a47 100644
--- a/drivers/acpi/common/cmeval.c
+++ b/drivers/acpi/common/cmeval.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: cmeval - Object evaluation
- * $Revision: 19 $
+ * $Revision: 21 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -77,7 +77,7 @@ acpi_cm_evaluate_numeric_object (
/* Is the return object of the correct type? */
- if (obj_desc->common.type != ACPI_TYPE_NUMBER) {
+ if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
status = AE_TYPE;
}
else {
@@ -85,7 +85,7 @@ acpi_cm_evaluate_numeric_object (
* Since the structure is a union, setting any field will set all
* of the variables in the union
*/
- *address = obj_desc->number.value;
+ *address = obj_desc->integer.value;
}
/* On exit, we must delete the return object */
@@ -142,17 +142,17 @@ acpi_cm_execute_HID (
* a string
*/
- if ((obj_desc->common.type != ACPI_TYPE_NUMBER) &&
+ if ((obj_desc->common.type != ACPI_TYPE_INTEGER) &&
(obj_desc->common.type != ACPI_TYPE_STRING))
{
status = AE_TYPE;
}
else {
- if (obj_desc->common.type == ACPI_TYPE_NUMBER) {
+ if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
/* Convert the Numeric HID to string */
- acpi_aml_eisa_id_to_string ((u32) obj_desc->number.value, hid->buffer);
+ acpi_aml_eisa_id_to_string ((u32) obj_desc->integer.value, hid->buffer);
}
else {
@@ -217,17 +217,17 @@ acpi_cm_execute_UID (
* a string
*/
- if ((obj_desc->common.type != ACPI_TYPE_NUMBER) &&
+ if ((obj_desc->common.type != ACPI_TYPE_INTEGER) &&
(obj_desc->common.type != ACPI_TYPE_STRING))
{
status = AE_TYPE;
}
else {
- if (obj_desc->common.type == ACPI_TYPE_NUMBER) {
+ if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
/* Convert the Numeric UID to string */
- acpi_aml_unsigned_integer_to_string (obj_desc->number.value, uid->buffer);
+ acpi_aml_unsigned_integer_to_string (obj_desc->integer.value, uid->buffer);
}
else {
@@ -289,14 +289,14 @@ acpi_cm_execute_STA (
/* Is the return object of the correct type? */
- if (obj_desc->common.type != ACPI_TYPE_NUMBER) {
+ if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
status = AE_TYPE;
}
else {
/* Extract the status flags */
- *flags = (u32) obj_desc->number.value;
+ *flags = (u32) obj_desc->integer.value;
}
/* On exit, we must delete the return object */
diff --git a/drivers/acpi/common/cmglobal.c b/drivers/acpi/common/cmglobal.c
index 4b4460f46..a388907f3 100644
--- a/drivers/acpi/common/cmglobal.c
+++ b/drivers/acpi/common/cmglobal.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: cmglobal - Global variables for the ACPI subsystem
- * $Revision: 112 $
+ * $Revision: 116 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -95,7 +95,7 @@ PREDEFINED_NAMES acpi_gbl_pre_defined_names[] =
{"_SB_", INTERNAL_TYPE_DEF_ANY},
{"_SI_", INTERNAL_TYPE_DEF_ANY},
{"_TZ_", INTERNAL_TYPE_DEF_ANY},
- {"_REV", ACPI_TYPE_NUMBER, "2"},
+ {"_REV", ACPI_TYPE_INTEGER, "2"},
{"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME},
{"_GL_", ACPI_TYPE_MUTEX, "0"},
@@ -152,6 +152,13 @@ u8 acpi_gbl_ns_properties[] =
};
+/* Hex to ASCII conversion table */
+
+NATIVE_CHAR acpi_gbl_hex_to_ascii[] =
+ {'0','1','2','3','4','5','6','7',
+ '8','9','A','B','C','D','E','F'};
+
+
/******************************************************************************
*
* Table globals
diff --git a/drivers/acpi/common/cminit.c b/drivers/acpi/common/cminit.c
index e6cfb7655..0952720f1 100644
--- a/drivers/acpi/common/cminit.c
+++ b/drivers/acpi/common/cminit.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: cminit - Common ACPI subsystem initialization
- * $Revision: 91 $
+ * $Revision: 93 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -35,6 +35,9 @@
MODULE_NAME ("cminit")
+#define ACPI_OFFSET(d,o) ((u32) &(((d *)0)->o))
+#define ACPI_FADT_OFFSET(o) ACPI_OFFSET (FADT_DESCRIPTOR, o)
+
/*******************************************************************************
*
* FUNCTION: Acpi_cm_fadt_register_error
@@ -53,12 +56,13 @@
static ACPI_STATUS
acpi_cm_fadt_register_error (
NATIVE_CHAR *register_name,
- u32 value)
+ u32 value,
+ u32 offset)
{
REPORT_ERROR (
- ("Invalid FADT register value, %s=%X (FADT=%p)\n",
- register_name, value, acpi_gbl_FADT));
+ ("Invalid FADT value %s=%lX at offset %lX FADT=%p\n",
+ register_name, value, offset, acpi_gbl_FADT));
return (AE_BAD_VALUE);
@@ -91,39 +95,42 @@ acpi_cm_validate_fadt (
if (acpi_gbl_FADT->pm1_evt_len < 4) {
status = acpi_cm_fadt_register_error ("PM1_EVT_LEN",
- (u32) acpi_gbl_FADT->pm1_evt_len);
+ (u32) acpi_gbl_FADT->pm1_evt_len,
+ ACPI_FADT_OFFSET (pm1_evt_len));
}
if (!acpi_gbl_FADT->pm1_cnt_len) {
- status = acpi_cm_fadt_register_error ("PM1_CNT_LEN",
- 0);
+ status = acpi_cm_fadt_register_error ("PM1_CNT_LEN", 0,
+ ACPI_FADT_OFFSET (pm1_cnt_len));
}
if (!ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1a_evt_blk.address)) {
- status = acpi_cm_fadt_register_error ("PM1a_EVT_BLK",
- 0);
+ status = acpi_cm_fadt_register_error ("X_PM1a_EVT_BLK", 0,
+ ACPI_FADT_OFFSET (Xpm1a_evt_blk.address));
}
if (!ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1a_cnt_blk.address)) {
- status = acpi_cm_fadt_register_error ("PM1a_CNT_BLK",
- 0);
+ status = acpi_cm_fadt_register_error ("X_PM1a_CNT_BLK", 0,
+ ACPI_FADT_OFFSET (Xpm1a_cnt_blk.address));
}
if (!ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm_tmr_blk.address)) {
- status = acpi_cm_fadt_register_error ("PM_TMR_BLK",
- 0);
+ status = acpi_cm_fadt_register_error ("X_PM_TMR_BLK", 0,
+ ACPI_FADT_OFFSET (Xpm_tmr_blk.address));
}
if ((ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm2_cnt_blk.address) &&
!acpi_gbl_FADT->pm2_cnt_len))
{
status = acpi_cm_fadt_register_error ("PM2_CNT_LEN",
- (u32) acpi_gbl_FADT->pm2_cnt_len);
+ (u32) acpi_gbl_FADT->pm2_cnt_len,
+ ACPI_FADT_OFFSET (pm2_cnt_len));
}
if (acpi_gbl_FADT->pm_tm_len < 4) {
status = acpi_cm_fadt_register_error ("PM_TM_LEN",
- (u32) acpi_gbl_FADT->pm_tm_len);
+ (u32) acpi_gbl_FADT->pm_tm_len,
+ ACPI_FADT_OFFSET (pm_tm_len));
}
/* length of GPE blocks must be a multiple of 2 */
@@ -132,15 +139,17 @@ acpi_cm_validate_fadt (
if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) &&
(acpi_gbl_FADT->gpe0blk_len & 1))
{
- status = acpi_cm_fadt_register_error ("GPE0_BLK_LEN",
- (u32) acpi_gbl_FADT->gpe0blk_len);
+ status = acpi_cm_fadt_register_error ("(x)GPE0_BLK_LEN",
+ (u32) acpi_gbl_FADT->gpe0blk_len,
+ ACPI_FADT_OFFSET (gpe0blk_len));
}
if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) &&
(acpi_gbl_FADT->gpe1_blk_len & 1))
{
- status = acpi_cm_fadt_register_error ("GPE1_BLK_LEN",
- (u32) acpi_gbl_FADT->gpe1_blk_len);
+ status = acpi_cm_fadt_register_error ("(x)GPE1_BLK_LEN",
+ (u32) acpi_gbl_FADT->gpe1_blk_len,
+ ACPI_FADT_OFFSET (gpe1_blk_len));
}
return (status);
diff --git a/drivers/acpi/common/cmobject.c b/drivers/acpi/common/cmobject.c
index 95e70fb14..5f73abaaf 100644
--- a/drivers/acpi/common/cmobject.c
+++ b/drivers/acpi/common/cmobject.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: cmobject - ACPI object create/delete/size/cache routines
- * $Revision: 34 $
+ * $Revision: 35 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -434,7 +434,7 @@ acpi_cm_get_simple_object_size (
break;
- case ACPI_TYPE_NUMBER:
+ case ACPI_TYPE_INTEGER:
case ACPI_TYPE_PROCESSOR:
case ACPI_TYPE_POWER:
diff --git a/drivers/acpi/common/cmutils.c b/drivers/acpi/common/cmutils.c
index cb3d959c8..b0ee8b4d9 100644
--- a/drivers/acpi/common/cmutils.c
+++ b/drivers/acpi/common/cmutils.c
@@ -1,12 +1,12 @@
/*******************************************************************************
*
* Module Name: cmutils - common utility procedures
- * $Revision: 21 $
+ * $Revision: 23 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -647,16 +647,16 @@ acpi_cm_resolve_package_references (
if (sub_object->common.type == INTERNAL_TYPE_REFERENCE) {
if (sub_object->reference.op_code == AML_ZERO_OP) {
- sub_object->common.type = ACPI_TYPE_NUMBER;
- sub_object->number.value = 0;
+ sub_object->common.type = ACPI_TYPE_INTEGER;
+ sub_object->integer.value = 0;
}
else if (sub_object->reference.op_code == AML_ONE_OP) {
- sub_object->common.type = ACPI_TYPE_NUMBER;
- sub_object->number.value = 1;
+ sub_object->common.type = ACPI_TYPE_INTEGER;
+ sub_object->integer.value = 1;
}
else if (sub_object->reference.op_code == AML_ONES_OP) {
- sub_object->common.type = ACPI_TYPE_NUMBER;
- sub_object->number.value = ACPI_INTEGER_MAX;
+ sub_object->common.type = ACPI_TYPE_INTEGER;
+ sub_object->integer.value = ACPI_INTEGER_MAX;
}
}
}
diff --git a/drivers/acpi/common/cmxface.c b/drivers/acpi/common/cmxface.c
index fc063850c..ce87b50d2 100644
--- a/drivers/acpi/common/cmxface.c
+++ b/drivers/acpi/common/cmxface.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: cmxface - External interfaces for "global" ACPI functions
- * $Revision: 55 $
+ * $Revision: 62 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -304,16 +304,22 @@ acpi_get_system_info (
out_buffer->length = sizeof (ACPI_SYSTEM_INFO);
info_ptr = (ACPI_SYSTEM_INFO *) out_buffer->pointer;
- /* TBD [Future]: need a version number, or use the version string */
- info_ptr->acpi_ca_version = 0x1234;
+ info_ptr->acpi_ca_version = ACPI_CA_VERSION;
/* System flags (ACPI capabilities) */
info_ptr->flags = acpi_gbl_system_flags;
/* Timer resolution - 24 or 32 bits */
-
- info_ptr->timer_resolution = acpi_hw_pmt_resolution ();
+ if (!acpi_gbl_FADT) {
+ info_ptr->timer_resolution = 0;
+ }
+ else if (acpi_gbl_FADT->tmr_val_ext == 0) {
+ info_ptr->timer_resolution = 24;
+ }
+ else {
+ info_ptr->timer_resolution = 32;
+ }
/* Clear the reserved fields */
diff --git a/drivers/acpi/cpu.c b/drivers/acpi/cpu.c
index 00ec59da5..3e4adcee2 100644
--- a/drivers/acpi/cpu.c
+++ b/drivers/acpi/cpu.c
@@ -39,6 +39,9 @@ static int acpi_c3_tested = 0;
static int acpi_max_c_state = 1;
static int acpi_pm_tmr_len;
+#define MAX_C2_LATENCY 100
+#define MAX_C3_LATENCY 1000
+
/*
* Clear busmaster activity flag
*/
@@ -251,10 +254,7 @@ static ACPI_STATUS
acpi_found_cpu(ACPI_HANDLE handle, u32 level, void *ctx, void **value)
{
ACPI_OBJECT obj;
- ACPI_CX_STATE lat[4];
- ACPI_CPU_THROTTLING_STATE throttle[ACPI_MAX_THROTTLE];
ACPI_BUFFER buf;
- int i, count;
buf.length = sizeof(obj);
buf.pointer = &obj;
@@ -273,41 +273,28 @@ acpi_found_cpu(ACPI_HANDLE handle, u32 level, void *ctx, void **value)
acpi_pblk = obj.processor.pblk_address;
- buf.length = sizeof(lat);
- buf.pointer = lat;
- if (!ACPI_SUCCESS(acpi_get_processor_cx_info(handle, &buf)))
- return AE_OK;
+ if (acpi_fadt.plvl2_lat
+ && acpi_fadt.plvl2_lat <= MAX_C2_LATENCY) {
+ acpi_c2_exit_latency
+ = ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl2_lat);
+ acpi_c2_enter_latency
+ = ACPI_MICROSEC_TO_TMR_TICKS(ACPI_TMR_HZ / 1000);
+ acpi_max_c_state = 2;
- if (lat[2].latency < MAX_CX_STATE_LATENCY) {
printk(KERN_INFO "ACPI: System firmware supports: C2");
- acpi_c2_exit_latency = lat[2].latency;
- acpi_max_c_state = 2;
- if (lat[3].latency < MAX_CX_STATE_LATENCY) {
- printk(" C3");
- acpi_c3_exit_latency = lat[3].latency;
+ if (acpi_fadt.plvl3_lat
+ && acpi_fadt.plvl3_lat <= MAX_C3_LATENCY) {
+ acpi_c3_exit_latency
+ = ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl3_lat);
+ acpi_c3_enter_latency
+ = ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl3_lat * 5);
acpi_max_c_state = 3;
- }
- printk("\n");
- }
- memset(throttle, 0, sizeof(throttle));
- buf.length = sizeof(throttle);
- buf.pointer = throttle;
-
- if (!ACPI_SUCCESS(acpi_get_processor_throttling_info(handle, &buf)))
- return AE_OK;
-
- for (i = 0, count = 0; i < ACPI_MAX_THROTTLE; i++) {
- if (throttle[i].percent_of_clock)
- count++;
- }
-
- /* 0% throttled really doesn't count */
- count--;
+ printk(" C3");
+ }
- if (count > 0) {
- DEBUG_PRINT(ACPI_INFO, ("%d throttling states\n", count));
+ printk("\n");
}
return AE_OK;
diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c
index 1ce75dbdb..897324547 100644
--- a/drivers/acpi/dispatcher/dsfield.c
+++ b/drivers/acpi/dispatcher/dsfield.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: dsfield - Dispatcher field routines
- * $Revision: 29 $
+ * $Revision: 31 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index d9d73ccea..4834f47ec 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: dsmethod - Parser/Interpreter interface - control method parsing
- * $Revision: 53 $
+ * $Revision: 56 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c
index e6913fabf..dfaa2a103 100644
--- a/drivers/acpi/dispatcher/dsmthdat.c
+++ b/drivers/acpi/dispatcher/dsmthdat.c
@@ -1,12 +1,12 @@
/*******************************************************************************
*
* Module Name: dsmthdat - control method arguments and local variables
- * $Revision: 36 $
+ * $Revision: 39 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -40,7 +40,7 @@
*
* FUNCTION: Acpi_ds_method_data_init
*
- * PARAMETERS: *Obj_desc
+ * PARAMETERS: Walk_state - Current walk state object
*
* RETURN: Status
*
@@ -97,7 +97,7 @@ acpi_ds_method_data_init (
*
* FUNCTION: Acpi_ds_method_data_delete_all
*
- * PARAMETERS: None
+ * PARAMETERS: Walk_state - Current walk state object
*
* RETURN: Status
*
@@ -153,7 +153,9 @@ acpi_ds_method_data_delete_all (
*
* FUNCTION: Acpi_ds_method_data_init_args
*
- * PARAMETERS: None
+ * PARAMETERS: *Params - Pointer to a parameter list for the method
+ * Max_param_count - The arg count for this method
+ * Walk_state - Current walk state object
*
* RETURN: Status
*
@@ -214,6 +216,7 @@ acpi_ds_method_data_init_args (
* Index - Which local_var or argument to get
* Entry - Pointer to where a pointer to the stack
* entry is returned.
+ * Walk_state - Current walk state object
*
* RETURN: Status
*
@@ -276,6 +279,7 @@ acpi_ds_method_data_get_entry (
* PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG
* Index - Which local_var or argument to get
* Object - Object to be inserted into the stack entry
+ * Walk_state - Current walk state object
*
* RETURN: Status
*
@@ -320,6 +324,7 @@ acpi_ds_method_data_set_entry (
* PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG
* Index - Which local_var or argument whose type
* to get
+ * Walk_state - Current walk state object
*
* RETURN: Data type of selected Arg or Local
* Used only in Exec_monadic2()/Type_op.
@@ -366,6 +371,7 @@ acpi_ds_method_data_get_type (
* PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG
* Index - Which local_var or argument whose type
* to get
+ * Walk_state - Current walk state object
*
* RETURN: Get the Node associated with a local or arg.
*
@@ -418,7 +424,8 @@ acpi_ds_method_data_get_nte (
*
* PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG
* Index - Which local_var or argument to get
- * *Dest_desc - Descriptor into which selected Arg
+ * Walk_state - Current walk state object
+ * *Dest_desc - Ptr to Descriptor into which selected Arg
* or Local value should be copied
*
* RETURN: Status
@@ -474,10 +481,12 @@ acpi_ds_method_data_get_value (
switch (type)
{
case MTH_TYPE_ARG:
+
return (AE_AML_UNINITIALIZED_ARG);
break;
case MTH_TYPE_LOCAL:
+
return (AE_AML_UNINITIALIZED_LOCAL);
break;
}
@@ -502,6 +511,7 @@ acpi_ds_method_data_get_value (
*
* PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG
* Index - Which local_var or argument to delete
+ * Walk_state - Current walk state object
*
* RETURN: Status
*
@@ -548,7 +558,6 @@ acpi_ds_method_data_delete_value (
* Decrement the reference count by one to balance the
* increment when the object was stored in the slot.
*/
-
acpi_cm_remove_reference (object);
}
@@ -563,18 +572,14 @@ acpi_ds_method_data_delete_value (
*
* PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG
* Index - Which local_var or argument to set
- * *Src_desc - Value to be stored
- * *Dest_desc - Descriptor into which *Src_desc
- * can be copied, or NULL if one must
- * be allocated for the purpose. If
- * provided, this descriptor will be
- * used for the new value.
+ * Src_desc - Value to be stored
+ * Walk_state - Current walk state
*
* RETURN: Status
*
* DESCRIPTION: Store a value in an Arg or Local. The Src_desc is installed
* as the new value for the Arg or Local and the reference count
- * is incremented.
+ * for Src_desc is incremented.
*
******************************************************************************/
@@ -644,7 +649,6 @@ acpi_ds_method_data_set_value (
* Store this object into the Node
* (do the indirect store)
*/
-
status = acpi_ns_attach_object ((ACPI_NAMESPACE_NODE *) *entry, src_desc,
src_desc->common.type);
return (status);
@@ -652,10 +656,18 @@ acpi_ds_method_data_set_value (
/*
- * Otherwise, just delete the existing object
- * before storing the new one
+ * Perform "Implicit conversion" of the new object to the type of the
+ * existing object
*/
+ status = acpi_aml_convert_to_target_type ((*entry)->common.type, &src_desc, walk_state);
+ if (ACPI_FAILURE (status)) {
+ goto cleanup;
+ }
+ /*
+ * Delete the existing object
+ * before storing the new one
+ */
acpi_ds_method_data_delete_value (type, index, walk_state);
}
@@ -666,7 +678,6 @@ acpi_ds_method_data_set_value (
* Install the new object in the stack entry
* (increments the object reference count by one)
*/
-
status = acpi_ds_method_data_set_entry (type, index, src_desc, walk_state);
if (ACPI_FAILURE (status)) {
goto cleanup;
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c
index 042cc4a80..0a6c88b4d 100644
--- a/drivers/acpi/dispatcher/dsobject.c
+++ b/drivers/acpi/dispatcher/dsobject.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: dsobject - Dispatcher object management routines
- * $Revision: 53 $
+ * $Revision: 56 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -241,14 +241,14 @@ acpi_ds_init_object_from_op (
/* We are expecting a number */
- if (arg_desc->common.type != ACPI_TYPE_NUMBER) {
+ if (arg_desc->common.type != ACPI_TYPE_INTEGER) {
acpi_cm_remove_reference (arg_desc);
return (AE_TYPE);
}
/* Get the value, delete the internal object */
- (*obj_desc)->buffer.length = (u32) arg_desc->number.value;
+ (*obj_desc)->buffer.length = (u32) arg_desc->integer.value;
acpi_cm_remove_reference (arg_desc);
/* Allocate the buffer */
@@ -304,8 +304,8 @@ acpi_ds_init_object_from_op (
status = acpi_ds_build_internal_object (walk_state, op, obj_desc);
break;
- case ACPI_TYPE_NUMBER:
- (*obj_desc)->number.value = op->value.integer;
+ case ACPI_TYPE_INTEGER:
+ (*obj_desc)->integer.value = op->value.integer;
break;
@@ -411,18 +411,20 @@ acpi_ds_build_internal_simple_obj (
acpi_ns_externalize_name (ACPI_UINT32_MAX, op->value.string, &length, &name);
if (name) {
- REPORT_WARNING (("Reference %s AML %X not found\n",
+ REPORT_WARNING (("Reference %s at AML %X not found\n",
name, op->aml_offset));
acpi_cm_free (name);
}
else {
- REPORT_WARNING (("Reference %s AML %X not found\n",
+ REPORT_WARNING (("Reference %s at AML %X not found\n",
op->value.string, op->aml_offset));
}
*obj_desc_ptr = NULL;
}
- return (status);
+ else {
+ return (status);
+ }
}
}
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
index 21e15bc26..ba06cf4db 100644
--- a/drivers/acpi/dispatcher/dsopcode.c
+++ b/drivers/acpi/dispatcher/dsopcode.c
@@ -2,12 +2,12 @@
*
* Module Name: dsopcode - Dispatcher Op Region support and handling of
* "control" opcodes
- * $Revision: 28 $
+ * $Revision: 30 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -355,7 +355,7 @@ acpi_ds_eval_field_unit_operands (
}
- offset = (u32) off_desc->number.value;
+ offset = (u32) off_desc->integer.value;
/*
@@ -427,7 +427,7 @@ acpi_ds_eval_field_unit_operands (
/* Offset is in bits, count is in bits */
bit_offset = offset;
- bit_count = (u16) cnt_desc->number.value;
+ bit_count = (u16) cnt_desc->integer.value;
break;
@@ -586,7 +586,7 @@ acpi_ds_eval_region_operands (
*/
operand_desc = walk_state->operands[walk_state->num_operands - 1];
- obj_desc->region.length = (u32) operand_desc->number.value;
+ obj_desc->region.length = (u32) operand_desc->integer.value;
acpi_cm_remove_reference (operand_desc);
/*
@@ -595,7 +595,7 @@ acpi_ds_eval_region_operands (
*/
operand_desc = walk_state->operands[walk_state->num_operands - 2];
- obj_desc->region.address = (ACPI_PHYSICAL_ADDRESS) operand_desc->number.value;
+ obj_desc->region.address = (ACPI_PHYSICAL_ADDRESS) operand_desc->integer.value;
acpi_cm_remove_reference (operand_desc);
diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c
index 2efa43e51..d31464840 100644
--- a/drivers/acpi/dispatcher/dsutils.c
+++ b/drivers/acpi/dispatcher/dsutils.c
@@ -1,12 +1,12 @@
/*******************************************************************************
*
* Module Name: dsutils - Dispatcher utilities
- * $Revision: 50 $
+ * $Revision: 52 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -566,7 +566,7 @@ acpi_ds_map_opcode_to_data_type (
case AML_WORD_OP:
case AML_DWORD_OP:
- data_type = ACPI_TYPE_NUMBER;
+ data_type = ACPI_TYPE_INTEGER;
break;
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c
index 1f7e329ad..a2e1b73d3 100644
--- a/drivers/acpi/dispatcher/dswexec.c
+++ b/drivers/acpi/dispatcher/dswexec.c
@@ -2,12 +2,12 @@
*
* Module Name: dswexec - Dispatcher method execution callbacks;
* dispatch to interpreter.
- * $Revision: 50 $
+ * $Revision: 55 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -46,7 +46,7 @@
*
* RETURN: Status
*
- * DESCRIPTION:
+ * DESCRIPTION: Get the result of a predicate evaluation
*
****************************************************************************/
@@ -93,22 +93,22 @@ acpi_ds_get_predicate_value (
* be a number
*/
- if (obj_desc->common.type != ACPI_TYPE_NUMBER) {
+ if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
status = AE_AML_OPERAND_TYPE;
goto cleanup;
}
- /* TBD: 64/32-bit */
+ /* Truncate the predicate to 32-bits if necessary */
- obj_desc->number.value &= (UINT64) 0x00000000FFFFFFFF;
+ acpi_aml_truncate_for32bit_table (obj_desc, walk_state);
/*
* Save the result of the predicate evaluation on
* the control stack
*/
- if (obj_desc->number.value) {
+ if (obj_desc->integer.value) {
walk_state->control_state->common.value = TRUE;
}
@@ -330,6 +330,8 @@ acpi_ds_exec_end_op (
walk_state->num_operands = 0;
walk_state->return_desc = NULL;
+ walk_state->op_info = op_info;
+ walk_state->opcode = opcode;
/* Call debugger for single step support (DEBUG build only) */
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c
index b3f1dc062..300d02b7f 100644
--- a/drivers/acpi/dispatcher/dswload.c
+++ b/drivers/acpi/dispatcher/dswload.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: dswload - Dispatcher namespace load callbacks
- * $Revision: 24 $
+ * $Revision: 26 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/dispatcher/dswscope.c b/drivers/acpi/dispatcher/dswscope.c
index 11b6a6cb9..332ab4ffd 100644
--- a/drivers/acpi/dispatcher/dswscope.c
+++ b/drivers/acpi/dispatcher/dswscope.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: dswscope - Scope stack manipulation
- * $Revision: 40 $
+ * $Revision: 42 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c
index a15a6f5f7..a436945df 100644
--- a/drivers/acpi/dispatcher/dswstate.c
+++ b/drivers/acpi/dispatcher/dswstate.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: dswstate - Dispatcher parse tree walk management routines
- * $Revision: 36 $
+ * $Revision: 38 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -37,31 +37,6 @@
/*******************************************************************************
*
- * FUNCTION: Acpi_ds_result_stack_clear
- *
- * PARAMETERS: Walk_state - Current Walk state
- *
- * RETURN: Status
- *
- * DESCRIPTION: Reset this walk's result stack pointers to zero, thus setting
- * the stack to zero.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-xxx_acpi_ds_result_stack_clear (
- ACPI_WALK_STATE *walk_state)
-{
-/*
- Walk_state->Num_results = 0;
- Walk_state->Current_result = 0;
-*/
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: Acpi_ds_result_insert
*
* PARAMETERS: Object - Object to push
@@ -135,7 +110,7 @@ acpi_ds_result_remove (
/* Check for a valid result object */
if (!state->results.obj_desc [index]) {
- return (AE_AML_NO_OPERAND);
+ return (AE_AML_NO_RETURN_VALUE);
}
/* Remove the object */
@@ -179,7 +154,7 @@ acpi_ds_result_pop (
if (!state->results.num_results) {
- return (AE_STACK_UNDERFLOW);
+ return (AE_AML_NO_RETURN_VALUE);
}
/* Remove top element */
@@ -198,12 +173,12 @@ acpi_ds_result_pop (
}
- return (AE_STACK_UNDERFLOW);
+ return (AE_AML_NO_RETURN_VALUE);
}
/*******************************************************************************
*
- * FUNCTION: Acpi_ds_result_pop
+ * FUNCTION: Acpi_ds_result_pop_from_bottom
*
* PARAMETERS: Object - Where to return the popped object
* Walk_state - Current Walk state
@@ -231,7 +206,7 @@ acpi_ds_result_pop_from_bottom (
if (!state->results.num_results) {
- return (AE_STACK_UNDERFLOW);
+ return (AE_AML_NO_RETURN_VALUE);
}
/* Remove Bottom element */
@@ -250,7 +225,7 @@ acpi_ds_result_pop_from_bottom (
/* Check for a valid result object */
if (!*object) {
- return (AE_AML_NO_OPERAND);
+ return (AE_AML_NO_RETURN_VALUE);
}
@@ -260,15 +235,14 @@ acpi_ds_result_pop_from_bottom (
/*******************************************************************************
*
- * FUNCTION: Acpi_ds_result_pop
+ * FUNCTION: Acpi_ds_result_push
*
* PARAMETERS: Object - Where to return the popped object
* Walk_state - Current Walk state
*
* RETURN: Status
*
- * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In
- * other words, this is a FIFO.
+ * DESCRIPTION: Push an object onto the current result stack
*
******************************************************************************/
@@ -282,7 +256,7 @@ acpi_ds_result_push (
state = walk_state->results;
if (!state) {
- return (AE_OK);
+ return (AE_AML_INTERNAL);
}
if (state->results.num_results == OBJ_NUM_OPERANDS) {
@@ -719,6 +693,7 @@ acpi_ds_create_walk_state (
ACPI_WALK_LIST *walk_list)
{
ACPI_WALK_STATE *walk_state;
+ ACPI_STATUS status;
acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
@@ -736,7 +711,7 @@ acpi_ds_create_walk_state (
acpi_gbl_walk_state_cache_depth--;
acpi_cm_release_mutex (ACPI_MTX_CACHES);
- }
+ }
else {
/* The cache is empty, create a new object */
@@ -762,6 +737,14 @@ acpi_ds_create_walk_state (
acpi_ds_method_data_init (walk_state);
#endif
+ /* Create an initial result stack entry */
+
+ status = acpi_ds_result_stack_push (walk_state);
+ if (ACPI_FAILURE (status)) {
+ return (NULL);
+ }
+
+
/* Put the new state at the head of the walk list */
acpi_ds_push_walk_state (walk_state, walk_list);
diff --git a/drivers/acpi/driver.c b/drivers/acpi/driver.c
index 222598120..241528fc6 100644
--- a/drivers/acpi/driver.c
+++ b/drivers/acpi/driver.c
@@ -55,7 +55,7 @@ struct acpi_run_entry
static spinlock_t acpi_event_lock = SPIN_LOCK_UNLOCKED;
static volatile u32 acpi_event_status = 0;
-static volatile acpi_sstate_t acpi_event_state = ACPI_S0;
+static volatile acpi_sstate_t acpi_event_state = ACPI_STATE_S0;
static DECLARE_WAIT_QUEUE_HEAD(acpi_event_wait);
static volatile int acpi_thread_pid = -1;
@@ -243,7 +243,7 @@ acpi_do_event(ctl_table * ctl,
/*
* Enter system sleep state
*/
-static int
+/*static int
acpi_do_sleep(ctl_table * ctl,
int write,
struct file *file,
@@ -257,13 +257,13 @@ acpi_do_sleep(ctl_table * ctl,
}
}
else {
- int status = acpi_enter_sx(ACPI_S1);
+ int status = acpi_enter_sx(ACPI_STATE_S1);
if (status)
return status;
}
file->f_pos += *len;
return 0;
-}
+}*/
/*
@@ -382,7 +382,8 @@ static struct ctl_table acpi_table[] =
&acpi_c3_enter_latency, sizeof(acpi_c3_enter_latency),
0644, NULL, &acpi_do_ulong},
- {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &acpi_do_sleep},
+/* until it actually works */
+/* {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &acpi_do_sleep},*/
{ACPI_EVENT, "event", NULL, 0, 0400, NULL, &acpi_do_event},
@@ -415,7 +416,9 @@ static struct ctl_table acpi_dir_table[] =
static int
acpi_thread(void *context)
{
- ACPI_PHYSICAL_ADDRESS rsdp_phys;
+ ACPI_PHYSICAL_ADDRESS rsdp_phys;
+ ACPI_BUFFER buffer;
+ ACPI_SYSTEM_INFO sys_info;
/*
* initialize
@@ -437,8 +440,6 @@ acpi_thread(void *context)
rsdp_phys = efi.acpi;
#endif
- printk(KERN_ERR "ACPI: System description tables found\n");
-
if (!ACPI_SUCCESS(acpi_find_and_load_tables(rsdp_phys)))
return -ENODEV;
@@ -448,6 +449,17 @@ acpi_thread(void *context)
return -ENODEV;
}
+ buffer.length = sizeof(sys_info);
+ buffer.pointer = &sys_info;
+
+ if (!ACPI_SUCCESS (acpi_get_system_info(&buffer))) {
+ printk(KERN_ERR "ACPI: Could not get system info\n");
+ acpi_terminate();
+ return -ENODEV;
+ }
+
+ printk(KERN_INFO "ACPI: Core Subsystem version [%x]\n", sys_info.acpi_ca_version);
+
if (!ACPI_SUCCESS(acpi_enable_subsystem(ACPI_FULL_INITIALIZATION))) {
printk(KERN_ERR "ACPI: Subsystem enable failed\n");
acpi_terminate();
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 8f6f61e36..5e42683c6 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -270,25 +270,6 @@ ec_transaction (
return_ACPI_STATUS(status);
}
-static ACPI_STATUS
-ec_space_setup (
- ACPI_HANDLE region_handle,
- UINT32 function,
- void *handler_context,
- void **return_context)
-{
- // TODO: What is this function for?
- /*
- * The ec object is in the handler context and is needed
- * when calling the ec_space_handler.
- */
- *return_context = handler_context;
-
- return AE_OK;
-}
-
-
-
static void
ec_query_handler (
@@ -419,8 +400,6 @@ ec_region_setup (
{
FUNCTION_TRACE("acpi_ec_region_setup");
- printk("acpi_ec_region_setup\n");
-
if (function == ACPI_REGION_DEACTIVATE)
{
if (*region_context)
@@ -556,10 +535,10 @@ found_ec(
buf.length = sizeof(obj);
buf.pointer = &obj;
if (!ACPI_SUCCESS(acpi_evaluate_object(handle, "_GPE", NULL, &buf))
- || obj.type != ACPI_TYPE_NUMBER)
+ || obj.type != ACPI_TYPE_INTEGER)
return AE_OK;
- ec_cxt->gpe_bit = obj.number.value;
+ ec_cxt->gpe_bit = obj.integer.value;
/* determine if we need the Global Lock when accessing */
buf.length = sizeof(obj);
@@ -568,12 +547,12 @@ found_ec(
status = acpi_evaluate_object(handle, "_GLK", NULL, &buf);
if (status == AE_NOT_FOUND)
ec_cxt->need_global_lock = 0;
- else if (!ACPI_SUCCESS(status) || obj.type != ACPI_TYPE_NUMBER) {
+ else if (!ACPI_SUCCESS(status) || obj.type != ACPI_TYPE_INTEGER) {
DEBUG_PRINT(ACPI_ERROR, ("_GLK failed\n"));
return AE_OK;
}
- ec_cxt->need_global_lock = obj.number.value;
+ ec_cxt->need_global_lock = obj.integer.value;
printk(KERN_INFO "ACPI: found EC @ (0x%02x,0x%02x,gpe %d GL %d)\n",
ec_cxt->data_port, ec_cxt->status_port, ec_cxt->gpe_bit,
diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c
index d5ce143a8..afdd477db 100644
--- a/drivers/acpi/events/evevent.c
+++ b/drivers/acpi/events/evevent.c
@@ -2,12 +2,12 @@
*
* Module Name: evevent - Fixed and General Purpose Acpi_event
* handling and dispatch
- * $Revision: 32 $
+ * $Revision: 33 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
index a52f2dc3d..cae4a44b2 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/events/evmisc.c
@@ -2,12 +2,12 @@
*
* Module Name: evmisc - ACPI device notification handler dispatch
* and ACPI Global Lock support
- * $Revision: 20 $
+ * $Revision: 22 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c
index 53cae6392..071639a27 100644
--- a/drivers/acpi/events/evregion.c
+++ b/drivers/acpi/events/evregion.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: evregion - ACPI Address_space (Op_region) handler dispatch
- * $Revision: 93 $
+ * $Revision: 94 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -122,8 +122,8 @@ acpi_ev_execute_reg_method (
u32 function)
{
ACPI_OPERAND_OBJECT *params[3];
- ACPI_OPERAND_OBJECT space_iD_obj;
- ACPI_OPERAND_OBJECT function_obj;
+ ACPI_OPERAND_OBJECT space_id_desc;
+ ACPI_OPERAND_OBJECT function_desc;
ACPI_STATUS status;
@@ -141,24 +141,24 @@ acpi_ev_execute_reg_method (
* Passed as a parameter
*/
- acpi_cm_init_static_object (&space_iD_obj);
- acpi_cm_init_static_object (&function_obj);
+ acpi_cm_init_static_object (&space_id_desc);
+ acpi_cm_init_static_object (&function_desc);
/*
* Method requires two parameters.
*/
- params [0] = &space_iD_obj;
- params [1] = &function_obj;
+ params [0] = &space_id_desc;
+ params [1] = &function_desc;
params [2] = NULL;
/*
* Set up the parameter objects
*/
- space_iD_obj.common.type = ACPI_TYPE_NUMBER;
- space_iD_obj.number.value = region_obj->region.space_id;
+ space_id_desc.common.type = ACPI_TYPE_INTEGER;
+ space_id_desc.integer.value = region_obj->region.space_id;
- function_obj.common.type = ACPI_TYPE_NUMBER;
- function_obj.number.value = function;
+ function_desc.common.type = ACPI_TYPE_INTEGER;
+ function_desc.integer.value = function;
/*
* Execute the method, no return value
diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c
index 92e5f198f..eb5e2033e 100644
--- a/drivers/acpi/events/evrgnini.c
+++ b/drivers/acpi/events/evrgnini.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: evrgnini- ACPI Address_space (Op_region) init
- * $Revision: 31 $
+ * $Revision: 33 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/events/evsci.c b/drivers/acpi/events/evsci.c
index 02320e93c..369d2f184 100644
--- a/drivers/acpi/events/evsci.c
+++ b/drivers/acpi/events/evsci.c
@@ -2,12 +2,12 @@
*
* Module Name: evsci - System Control Interrupt configuration and
* legacy to ACPI mode state transition functions
- * $Revision: 67 $
+ * $Revision: 69 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
index c3bbad0ff..f0e62934f 100644
--- a/drivers/acpi/events/evxface.c
+++ b/drivers/acpi/events/evxface.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: evxface - External interfaces for ACPI events
- * $Revision: 97 $
+ * $Revision: 101 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -187,26 +187,25 @@ acpi_install_notify_handler (
return (AE_BAD_PARAMETER);
}
- /* Convert and validate the device handle */
-
acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+ /* Convert and validate the device handle */
+
device_node = acpi_ns_convert_handle_to_entry (device);
if (!device_node) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
-
/*
- * Support for global notify handlers. These handlers are invoked for
- * every notifiy of the type specifiec
+ * Root Object:
+ * ------------
+ * Registering a notify handler on the root object indicates that the
+ * caller wishes to receive notifications for all objects. Note that
+ * only one <external> global handler can be regsitered (per notify type).
*/
-
if (device == ACPI_ROOT_OBJECT) {
- /*
- * Make sure the handler is not already installed.
- */
+ /* Make sure the handler is not already installed */
if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
acpi_gbl_sys_notify.handler) ||
@@ -222,94 +221,89 @@ acpi_install_notify_handler (
acpi_gbl_sys_notify.handler = handler;
acpi_gbl_sys_notify.context = context;
}
-
- else {
+ else /* ACPI_DEVICE_NOTIFY */ {
acpi_gbl_drv_notify.node = device_node;
acpi_gbl_drv_notify.handler = handler;
acpi_gbl_drv_notify.context = context;
}
-
/* Global notify handler installed */
-
- goto unlock_and_exit;
}
-
/*
- * These are the ONLY objects that can receive ACPI notifications
+ * Other Objects:
+ * --------------
+ * Caller will only receive notifications specific to the target object.
+ * Note that only certain object types can receive notifications.
*/
-
- if ((device_node->type != ACPI_TYPE_DEVICE) &&
- (device_node->type != ACPI_TYPE_PROCESSOR) &&
- (device_node->type != ACPI_TYPE_POWER) &&
- (device_node->type != ACPI_TYPE_THERMAL))
- {
- status = AE_BAD_PARAMETER;
- goto unlock_and_exit;
- }
-
- /* Check for an existing internal object */
-
- obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) device_node);
- if (obj_desc) {
+ else {
/*
- * The object exists.
- * Make sure the handler is not already installed.
+ * These are the ONLY objects that can receive ACPI notifications
*/
-
- if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
- obj_desc->device.sys_handler) ||
- ((handler_type == ACPI_DEVICE_NOTIFY) &&
- obj_desc->device.drv_handler))
+ if ((device_node->type != ACPI_TYPE_DEVICE) &&
+ (device_node->type != ACPI_TYPE_PROCESSOR) &&
+ (device_node->type != ACPI_TYPE_POWER) &&
+ (device_node->type != ACPI_TYPE_THERMAL))
{
- status = AE_EXIST;
+ status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
- }
- else {
- /* Create a new object */
+ /* Check for an existing internal object */
- obj_desc = acpi_cm_create_internal_object (device_node->type);
- if (!obj_desc) {
- status = AE_NO_MEMORY;
- goto unlock_and_exit;
+ obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) device_node);
+ if (obj_desc) {
+
+ /* Object exists - make sure there's no handler */
+
+ if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
+ obj_desc->device.sys_handler) ||
+ ((handler_type == ACPI_DEVICE_NOTIFY) &&
+ obj_desc->device.drv_handler))
+ {
+ status = AE_EXIST;
+ goto unlock_and_exit;
+ }
}
- /* Attach new object to the Node */
+ else {
+ /* Create a new object */
- status = acpi_ns_attach_object (device, obj_desc, (u8) device_node->type);
+ obj_desc = acpi_cm_create_internal_object (device_node->type);
+ if (!obj_desc) {
+ status = AE_NO_MEMORY;
+ goto unlock_and_exit;
+ }
- if (ACPI_FAILURE (status)) {
- goto unlock_and_exit;
- }
- }
+ /* Attach new object to the Node */
+ status = acpi_ns_attach_object (device, obj_desc, (u8) device_node->type);
- /*
- * If we get here, we know that there is no handler installed
- * so let's party
- */
- notify_obj = acpi_cm_create_internal_object (INTERNAL_TYPE_NOTIFY);
- if (!notify_obj) {
- status = AE_NO_MEMORY;
- goto unlock_and_exit;
- }
+ if (ACPI_FAILURE (status)) {
+ goto unlock_and_exit;
+ }
+ }
- notify_obj->notify_handler.node = device_node;
- notify_obj->notify_handler.handler = handler;
- notify_obj->notify_handler.context = context;
+ /* Install the handler */
+ notify_obj = acpi_cm_create_internal_object (INTERNAL_TYPE_NOTIFY);
+ if (!notify_obj) {
+ status = AE_NO_MEMORY;
+ goto unlock_and_exit;
+ }
- if (handler_type == ACPI_SYSTEM_NOTIFY) {
- obj_desc->device.sys_handler = notify_obj;
- }
+ notify_obj->notify_handler.node = device_node;
+ notify_obj->notify_handler.handler = handler;
+ notify_obj->notify_handler.context = context;
- else {
- obj_desc->device.drv_handler = notify_obj;
- }
+ if (handler_type == ACPI_SYSTEM_NOTIFY) {
+ obj_desc->device.sys_handler = notify_obj;
+ }
+ else /* ACPI_DEVICE_NOTIFY */ {
+ obj_desc->device.drv_handler = notify_obj;
+ }
+ }
unlock_and_exit:
acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
@@ -343,7 +337,6 @@ acpi_remove_notify_handler (
ACPI_NAMESPACE_NODE *device_node;
ACPI_STATUS status = AE_OK;
-
/* Parameter validation */
if ((!handler) ||
@@ -363,63 +356,92 @@ acpi_remove_notify_handler (
}
/*
- * These are the ONLY objects that can receive ACPI notifications
+ * Root Object:
+ * ------------
*/
+ if (device == ACPI_ROOT_OBJECT) {
- if ((device_node->type != ACPI_TYPE_DEVICE) &&
- (device_node->type != ACPI_TYPE_PROCESSOR) &&
- (device_node->type != ACPI_TYPE_POWER) &&
- (device_node->type != ACPI_TYPE_THERMAL))
- {
- status = AE_BAD_PARAMETER;
- goto unlock_and_exit;
- }
-
- /* Check for an existing internal object */
+ if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
+ !acpi_gbl_sys_notify.handler) ||
+ ((handler_type == ACPI_DEVICE_NOTIFY) &&
+ !acpi_gbl_drv_notify.handler))
+ {
+ status = AE_NOT_EXIST;
+ goto unlock_and_exit;
+ }
- obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) device_node);
- if (!obj_desc) {
- status = AE_NOT_EXIST;
- goto unlock_and_exit;
+ if (handler_type == ACPI_SYSTEM_NOTIFY) {
+ acpi_gbl_sys_notify.node = NULL;
+ acpi_gbl_sys_notify.handler = NULL;
+ acpi_gbl_sys_notify.context = NULL;
+ }
+ else {
+ acpi_gbl_drv_notify.node = NULL;
+ acpi_gbl_drv_notify.handler = NULL;
+ acpi_gbl_drv_notify.context = NULL;
+ }
}
/*
- * The object exists.
- *
- * Make sure the handler is installed.
+ * Other Objects:
+ * --------------
*/
-
- if (handler_type == ACPI_SYSTEM_NOTIFY) {
- notify_obj = obj_desc->device.sys_handler;
- }
else {
- notify_obj = obj_desc->device.drv_handler;
- }
+ /*
+ * These are the ONLY objects that can receive ACPI notifications
+ */
+ if ((device_node->type != ACPI_TYPE_DEVICE) &&
+ (device_node->type != ACPI_TYPE_PROCESSOR) &&
+ (device_node->type != ACPI_TYPE_POWER) &&
+ (device_node->type != ACPI_TYPE_THERMAL))
+ {
+ status = AE_BAD_PARAMETER;
+ goto unlock_and_exit;
+ }
- if ((!notify_obj) ||
- (notify_obj->notify_handler.handler != handler))
- {
- status = AE_BAD_PARAMETER;
- goto unlock_and_exit;
- }
+ /* Check for an existing internal object */
- /*
- * Now we can remove the handler
- */
- if (handler_type == ACPI_SYSTEM_NOTIFY) {
- obj_desc->device.sys_handler = NULL;
- }
- else {
- obj_desc->device.drv_handler = NULL;
+ obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) device_node);
+ if (!obj_desc) {
+ status = AE_NOT_EXIST;
+ goto unlock_and_exit;
+ }
+
+ /* Object exists - make sure there's an existing handler */
+
+ if (handler_type == ACPI_SYSTEM_NOTIFY) {
+ notify_obj = obj_desc->device.sys_handler;
+ }
+ else {
+ notify_obj = obj_desc->device.drv_handler;
+ }
+
+ if ((!notify_obj) ||
+ (notify_obj->notify_handler.handler != handler))
+ {
+ status = AE_BAD_PARAMETER;
+ goto unlock_and_exit;
+ }
+
+ /* Remove the handler */
+
+ if (handler_type == ACPI_SYSTEM_NOTIFY) {
+ obj_desc->device.sys_handler = NULL;
+ }
+ else {
+ obj_desc->device.drv_handler = NULL;
+ }
+
+ acpi_cm_remove_reference (notify_obj);
}
- acpi_cm_remove_reference (notify_obj);
unlock_and_exit:
acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
return (status);
}
+
/******************************************************************************
*
* FUNCTION: Acpi_install_gpe_handler
diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c
index 5b7652e52..9864301a3 100644
--- a/drivers/acpi/events/evxfevnt.c
+++ b/drivers/acpi/events/evxfevnt.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: evxfevnt - External Interfaces, ACPI event disable/enable
- * $Revision: 26 $
+ * $Revision: 28 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c
index 71116cfc8..e54bbab24 100644
--- a/drivers/acpi/events/evxfregn.c
+++ b/drivers/acpi/events/evxfregn.c
@@ -2,12 +2,12 @@
*
* Module Name: evxfregn - External Interfaces, ACPI Operation Regions and
* Address Spaces.
- * $Revision: 26 $
+ * $Revision: 27 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/hardware/hwacpi.c b/drivers/acpi/hardware/hwacpi.c
index d2154a1a2..304d3dec6 100644
--- a/drivers/acpi/hardware/hwacpi.c
+++ b/drivers/acpi/hardware/hwacpi.c
@@ -1,12 +1,13 @@
+
/******************************************************************************
*
- * Module Name: hwacpi - ACPI hardware functions - mode and timer
- * $Revision: 34 $
+ * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface
+ * $Revision: 36 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -304,48 +305,3 @@ acpi_hw_get_mode_capabilities (void)
}
-/******************************************************************************
- *
- * FUNCTION: Acpi_hw_pmt_ticks
- *
- * PARAMETERS: none
- *
- * RETURN: Current value of the ACPI PMT (timer)
- *
- * DESCRIPTION: Obtains current value of ACPI PMT
- *
- ******************************************************************************/
-
-u32
-acpi_hw_pmt_ticks (void)
-{
- u32 ticks;
-
- ticks = acpi_os_in32 ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm_tmr_blk.address));
-
- return (ticks);
-}
-
-
-/******************************************************************************
- *
- * FUNCTION: Acpi_hw_pmt_resolution
- *
- * PARAMETERS: none
- *
- * RETURN: Number of bits of resolution in the PMT (either 24 or 32)
- *
- * DESCRIPTION: Obtains resolution of the ACPI PMT (either 24bit or 32bit)
- *
- ******************************************************************************/
-
-u32
-acpi_hw_pmt_resolution (void)
-{
- if (0 == acpi_gbl_FADT->tmr_val_ext) {
- return (24);
- }
-
- return (32);
-}
-
diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c
index 2b413fac8..b7b777df6 100644
--- a/drivers/acpi/hardware/hwgpe.c
+++ b/drivers/acpi/hardware/hwgpe.c
@@ -1,12 +1,13 @@
+
/******************************************************************************
*
* Module Name: hwgpe - Low level GPE enable/disable/clear functions
- * $Revision: 25 $
+ * $Revision: 28 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c
index 77b6a1c8c..fc96c51fb 100644
--- a/drivers/acpi/hardware/hwregs.c
+++ b/drivers/acpi/hardware/hwregs.c
@@ -3,12 +3,12 @@
*
* Module Name: hwregs - Read/write access functions for the various ACPI
* control and status registers.
- * $Revision: 86 $
+ * $Revision: 88 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -37,7 +37,7 @@
/* This matches the #defines in actypes.h. */
NATIVE_CHAR *sleep_state_table[] = {"\\_S0_","\\_S1_","\\_S2_","\\_S3_",
- "\\_S4_","\\_S4_b","\\_S5_"};
+ "\\_S4_","\\_S5_","\\_S4_b"};
/*******************************************************************************
@@ -53,7 +53,7 @@ NATIVE_CHAR *sleep_state_table[] = {"\\_S0_","\\_S1_","\\_S2_","
*
******************************************************************************/
-static u32
+u32
acpi_hw_get_bit_shift (
u32 mask)
{
@@ -185,9 +185,9 @@ acpi_hw_obtain_sleep_type_register_data (
}
else if (((obj_desc->package.elements[0])->common.type !=
- ACPI_TYPE_NUMBER) ||
+ ACPI_TYPE_INTEGER) ||
((obj_desc->package.elements[1])->common.type !=
- ACPI_TYPE_NUMBER))
+ ACPI_TYPE_INTEGER))
{
/* Must have two */
@@ -199,9 +199,9 @@ acpi_hw_obtain_sleep_type_register_data (
/*
* Valid _Sx_ package size, type, and value
*/
- *slp_typ_a = (u8) (obj_desc->package.elements[0])->number.value;
+ *slp_typ_a = (u8) (obj_desc->package.elements[0])->integer.value;
- *slp_typ_b = (u8) (obj_desc->package.elements[1])->number.value;
+ *slp_typ_b = (u8) (obj_desc->package.elements[1])->integer.value;
}
@@ -581,13 +581,8 @@ acpi_hw_register_read (
case PM1_CONTROL: /* 16-bit access */
- if (register_id != SLP_TYPE_B) {
- value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
- }
-
- if (register_id != SLP_TYPE_A) {
- value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
- }
+ value = acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
+ value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
break;
@@ -696,30 +691,20 @@ acpi_hw_register_write (
case PM1_CONTROL: /* 16-bit access */
- /*
- * If SLP_TYP_A or SLP_TYP_B, only write to one reg block.
- * Otherwise, write to both.
- */
- if (register_id == SLP_TYPE_A) {
- acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
- }
- else if (register_id == SLP_TYPE_B) {
- acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
- }
- else {
- /* disable/re-enable interrupts if sleeping */
- if (register_id == SLP_EN) {
- disable();
- }
+ acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
+ acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
+ break;
- acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
- acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
- if (register_id == SLP_EN) {
- enable();
- }
- }
+ case PM1_a_CONTROL: /* 16-bit access */
+
+ acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
+ break;
+
+
+ case PM1_b_CONTROL: /* 16-bit access */
+ acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
break;
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
new file mode 100644
index 000000000..892c721c6
--- /dev/null
+++ b/drivers/acpi/hardware/hwsleep.c
@@ -0,0 +1,189 @@
+
+/******************************************************************************
+ *
+ * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface
+ * $Revision: 5 $
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000, 2001 R. Byron Moore
+ *
+ * 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
+ */
+
+#include "acpi.h"
+#include "acnamesp.h"
+#include "achware.h"
+
+#define _COMPONENT HARDWARE
+ MODULE_NAME ("hwsleep")
+
+
+/******************************************************************************
+ *
+ * FUNCTION: Acpi_set_firmware_waking_vector
+ *
+ * PARAMETERS: Physical_address - Physical address of ACPI real mode
+ * entry point.
+ *
+ * RETURN: AE_OK or AE_ERROR
+ *
+ * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_set_firmware_waking_vector (
+ ACPI_PHYSICAL_ADDRESS physical_address)
+{
+
+
+ /* Make sure that we have an FACS */
+
+ if (!acpi_gbl_FACS) {
+ return (AE_NO_ACPI_TABLES);
+ }
+
+ /* Set the vector */
+
+ if (acpi_gbl_FACS->vector_width == 32) {
+ * (u32 *) acpi_gbl_FACS->firmware_waking_vector = (u32) physical_address;
+ }
+ else {
+ *acpi_gbl_FACS->firmware_waking_vector = physical_address;
+ }
+
+ return (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: Acpi_get_firmware_waking_vector
+ *
+ * PARAMETERS: *Physical_address - Output buffer where contents of
+ * the Firmware_waking_vector field of
+ * the FACS will be stored.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_get_firmware_waking_vector (
+ ACPI_PHYSICAL_ADDRESS *physical_address)
+{
+
+
+ if (!physical_address) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /* Make sure that we have an FACS */
+
+ if (!acpi_gbl_FACS) {
+ return (AE_NO_ACPI_TABLES);
+ }
+
+ /* Get the vector */
+
+ if (acpi_gbl_FACS->vector_width == 32) {
+ *physical_address = * (u32 *) acpi_gbl_FACS->firmware_waking_vector;
+ }
+ else {
+ *physical_address = *acpi_gbl_FACS->firmware_waking_vector;
+ }
+
+ return (AE_OK);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION: Acpi_enter_sleep_state
+ *
+ * PARAMETERS: Sleep_state - Which sleep state to enter
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231)
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_enter_sleep_state (
+ u8 sleep_state)
+{
+ ACPI_STATUS status;
+ ACPI_OBJECT_LIST arg_list;
+ ACPI_OBJECT arg;
+ u8 type_a;
+ u8 type_b;
+ u16 PM1_acontrol;
+ u16 PM1_bcontrol;
+
+ /*
+ * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
+ */
+
+ status = acpi_hw_obtain_sleep_type_register_data(sleep_state, &type_a, &type_b);
+
+ if (!ACPI_SUCCESS(status)) {
+ return status;
+ }
+
+ /* run the _PTS and _GTS methods */
+ MEMSET(&arg_list, 0, sizeof(arg_list));
+ arg_list.count = 1;
+ arg_list.pointer = &arg;
+
+ MEMSET(&arg, 0, sizeof(arg));
+ arg.type = ACPI_TYPE_INTEGER;
+ arg.integer.value = sleep_state;
+
+ acpi_evaluate_object(NULL, "\\_PTS", &arg_list, NULL);
+ acpi_evaluate_object(NULL, "\\_GTS", &arg_list, NULL);
+
+ /* clear wake status */
+ acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, WAK_STS, 1);
+
+ PM1_acontrol = (u16) acpi_hw_register_read(ACPI_MTX_LOCK, PM1_CONTROL);
+
+ /* mask off SLP_EN and SLP_TYP fields */
+ PM1_acontrol &= 0xC3FF;
+
+ /* mask in SLP_EN */
+ PM1_acontrol |= (1 << acpi_hw_get_bit_shift (SLP_EN_MASK));
+
+ PM1_bcontrol = PM1_acontrol;
+
+ /* mask in SLP_TYP */
+ PM1_acontrol |= (type_a << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK));
+ PM1_bcontrol |= (type_b << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK));
+
+ /* the old version was disabling interrupts. let's try it without
+ * and see how that works
+ */
+ /*disable();*/
+
+ acpi_hw_register_write(ACPI_MTX_LOCK, PM1_a_CONTROL, PM1_acontrol);
+ acpi_hw_register_write(ACPI_MTX_LOCK, PM1_b_CONTROL, PM1_bcontrol);
+
+ /*enable();*/
+
+ return (AE_OK);
+}
diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c
new file mode 100644
index 000000000..b7f529ccf
--- /dev/null
+++ b/drivers/acpi/hardware/hwtimer.c
@@ -0,0 +1,196 @@
+
+/******************************************************************************
+ *
+ * Name: hwtimer.c - ACPI Power Management Timer Interface
+ * $Revision: 4 $
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000, 2001 R. Byron Moore
+ *
+ * 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
+ */
+
+#include "acpi.h"
+#include "achware.h"
+
+#define _COMPONENT HARDWARE
+ MODULE_NAME ("hwtimer")
+
+
+/******************************************************************************
+ *
+ * FUNCTION: Acpi_get_timer_resolution
+ *
+ * PARAMETERS: none
+ *
+ * RETURN: Number of bits of resolution in the PM Timer (24 or 32).
+ *
+ * DESCRIPTION: Obtains resolution of the ACPI PM Timer.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_get_timer_resolution (
+ u32 *resolution)
+{
+ if (!resolution) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ if (0 == acpi_gbl_FADT->tmr_val_ext) {
+ *resolution = 24;
+ }
+ else {
+ *resolution = 32;
+ }
+
+ return (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: Acpi_get_timer
+ *
+ * PARAMETERS: none
+ *
+ * RETURN: Current value of the ACPI PM Timer (in ticks).
+ *
+ * DESCRIPTION: Obtains current value of ACPI PM Timer.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_get_timer (
+ u32 *ticks)
+{
+ if (!ticks) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ *ticks = acpi_os_in32 ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm_tmr_blk.address));
+
+ return (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: Acpi_get_timer_duration
+ *
+ * PARAMETERS: Start_ticks
+ * End_ticks
+ * Time_elapsed
+ *
+ * RETURN: Time_elapsed
+ *
+ * DESCRIPTION: Computes the time elapsed (in microseconds) between two
+ * PM Timer time stamps, taking into account the possibility of
+ * rollovers, the timer resolution, and timer frequency.
+ *
+ * The PM Timer's clock ticks at roughly 3.6 times per
+ * _microsecond_, and its clock continues through Cx state
+ * transitions (unlike many CPU timestamp counters) -- making it
+ * a versatile and accurate timer.
+ *
+ * Note that this function accomodates only a single timer
+ * rollover. Thus for 24-bit timers, this function should only
+ * be used for calculating durations less than ~4.6 seconds
+ * (~20 hours for 32-bit timers).
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_get_timer_duration (
+ u32 start_ticks,
+ u32 end_ticks,
+ u32 *time_elapsed)
+{
+ u32 delta_ticks = 0;
+ u32 seconds = 0;
+ u32 milliseconds = 0;
+ u32 microseconds = 0;
+ u32 remainder = 0;
+
+ if (!time_elapsed) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /*
+ * Compute Tick Delta:
+ * -------------------
+ * Handle timer rollovers on 24- versus 32-bit timers.
+ */
+ if (start_ticks < end_ticks) {
+ delta_ticks = end_ticks - start_ticks;
+ }
+ else if (start_ticks > end_ticks) {
+ /* 24-bit Timer */
+ if (0 == acpi_gbl_FADT->tmr_val_ext) {
+ delta_ticks = (0x00FFFFFF - start_ticks) + end_ticks;
+ }
+ /* 32-bit Timer */
+ else {
+ delta_ticks = (0xFFFFFFFF - start_ticks) + end_ticks;
+ }
+ }
+
+ /*
+ * Compute Duration:
+ * -----------------
+ * Since certain compilers (gcc/Linux, argh!) don't support 64-bit
+ * divides in kernel-space we have to do some trickery to preserve
+ * accuracy while using 32-bit math.
+ *
+ * TODO: Change to use 64-bit math when supported.
+ *
+ * The process is as follows:
+ * 1. Compute the number of seconds by dividing Delta Ticks by
+ * the timer frequency.
+ * 2. Compute the number of milliseconds in the remainder from step #1
+ * by multiplying by 1000 and then dividing by the timer frequency.
+ * 3. Compute the number of microseconds in the remainder from step #2
+ * by multiplying by 1000 and then dividing by the timer frequency.
+ * 4. Add the results from steps 1, 2, and 3 to get the total duration.
+ *
+ * Example: The time elapsed for Delta_ticks = 0xFFFFFFFF should be
+ * 1199864031 microseconds. This is computed as follows:
+ * Step #1: Seconds = 1199; Remainder = 3092840
+ * Step #2: Milliseconds = 864; Remainder = 113120
+ * Step #3: Microseconds = 31; Remainder = <don't care!>
+ */
+
+ /* Step #1 */
+ seconds = delta_ticks / PM_TIMER_FREQUENCY;
+ remainder = delta_ticks % PM_TIMER_FREQUENCY;
+
+ /* Step #2 */
+ milliseconds = (remainder * 1000) / PM_TIMER_FREQUENCY;
+ remainder = (remainder * 1000) % PM_TIMER_FREQUENCY;
+
+ /* Step #3 */
+ microseconds = (remainder * 1000) / PM_TIMER_FREQUENCY;
+
+ /* Step #4 */
+ *time_elapsed = seconds * 1000000;
+ *time_elapsed += milliseconds * 1000;
+ *time_elapsed += microseconds;
+
+ return (AE_OK);
+}
+
+
diff --git a/drivers/acpi/include/accommon.h b/drivers/acpi/include/accommon.h
index 37e13b228..61d54a220 100644
--- a/drivers/acpi/include/accommon.h
+++ b/drivers/acpi/include/accommon.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: accommon.h -- prototypes for the common (subsystem-wide) procedures
- * $Revision: 82 $
+ * $Revision: 87 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -100,6 +100,8 @@ acpi_cm_allocate_owner_id (
* Cm_clib - Local implementations of C library functions
*/
+#ifndef ACPI_USE_SYSTEM_CLIBRARY
+
NATIVE_UINT
acpi_cm_strlen (
const NATIVE_CHAR *string);
@@ -141,7 +143,7 @@ u32
acpi_cm_strtoul (
const NATIVE_CHAR *string,
NATIVE_CHAR **terminator,
- u32 base);
+ NATIVE_UINT base);
NATIVE_CHAR *
acpi_cm_strstr (
@@ -161,7 +163,7 @@ acpi_cm_memcpy (
void *
acpi_cm_memset (
void *dest,
- u32 value,
+ NATIVE_UINT value,
NATIVE_UINT count);
u32
@@ -172,6 +174,7 @@ u32
acpi_cm_to_lower (
u32 c);
+#endif /* ACPI_USE_SYSTEM_CLIBRARY */
/*
* Cm_copy - Object construction and conversion interfaces
@@ -297,7 +300,7 @@ function_value_exit (
u32 line_number,
u32 component_id,
NATIVE_CHAR *function_name,
- NATIVE_UINT value);
+ ACPI_INTEGER value);
void
function_ptr_exit (
@@ -596,7 +599,7 @@ acpi_cm_init_static_object (
#define acpi_cm_callocate(a) _cm_callocate(a, _COMPONENT,_THIS_MODULE,__LINE__)
#define acpi_cm_free(a) _cm_free(a,_COMPONENT,_THIS_MODULE,__LINE__)
-#ifndef ACPI_DEBUG
+#ifndef ACPI_DEBUG_TRACK_ALLOCATIONS
#define acpi_cm_add_element_to_alloc_list(a,b,c,d,e,f)
#define acpi_cm_delete_element_from_alloc_list(a,b,c,d)
diff --git a/drivers/acpi/include/acconfig.h b/drivers/acpi/include/acconfig.h
index 2b210339b..ea9be649d 100644
--- a/drivers/acpi/include/acconfig.h
+++ b/drivers/acpi/include/acconfig.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: acconfig.h - Global configuration constants
- * $Revision: 48 $
+ * $Revision: 53 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -53,7 +53,7 @@
/* Version string */
-#define ACPI_CA_VERSION __DATE__
+#define ACPI_CA_VERSION 0x20010125
/* Maximum objects in the various object caches */
@@ -122,6 +122,10 @@
#define MTH_NUM_ARGS 7
#define MTH_MAX_ARG 6
+/* Maximum length of resulting string when converting from a buffer */
+
+#define ACPI_MAX_STRING_CONVERSION 200
+
/*
* Operand Stack (in WALK_STATE), Must be large enough to contain MTH_MAX_ARG
*/
diff --git a/drivers/acpi/include/acdebug.h b/drivers/acpi/include/acdebug.h
index 2bc9e7165..f1fa7094e 100644
--- a/drivers/acpi/include/acdebug.h
+++ b/drivers/acpi/include/acdebug.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: acdebug.h - ACPI/AML debugger
- * $Revision: 37 $
+ * $Revision: 39 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/include/acdispat.h b/drivers/acpi/include/acdispat.h
index 599e46c36..f5d52cc41 100644
--- a/drivers/acpi/include/acdispat.h
+++ b/drivers/acpi/include/acdispat.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: acdispat.h - dispatcher (parser to interpreter interface)
- * $Revision: 33 $
+ * $Revision: 35 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/include/acenv.h b/drivers/acpi/include/acenv.h
index f867a348f..9e4e62339 100644
--- a/drivers/acpi/include/acenv.h
+++ b/drivers/acpi/include/acenv.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: acenv.h - Generation environment specific items
- * $Revision: 65 $
+ * $Revision: 70 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -28,7 +28,7 @@
/*
- * Configuration for ACPI Utilities
+ * Configuration for ACPI tools and utilities
*/
#ifdef _ACPI_DUMP_APP
@@ -55,6 +55,16 @@
#define ACPI_USE_SYSTEM_CLIBRARY
#endif
+/*
+ * Memory allocation tracking. Used only if
+ * 1) This is the debug version
+ * 2) This is NOT a 16-bit version of the code (not enough real-mode memory)
+ */
+#ifdef ACPI_DEBUG
+#ifndef _IA16
+#define ACPI_DEBUG_TRACK_ALLOCATIONS
+#endif
+#endif
/*
* Environment configuration. The purpose of this file is to interface to the
@@ -154,17 +164,17 @@
#define STRUPR(s) strupr((s))
#define STRLEN(s) strlen((s))
#define STRCPY(d,s) strcpy((d), (s))
-#define STRNCPY(d,s,n) strncpy((d), (s), (n))
-#define STRNCMP(d,s,n) strncmp((d), (s), (n))
+#define STRNCPY(d,s,n) strncpy((d), (s), (NATIVE_INT)(n))
+#define STRNCMP(d,s,n) strncmp((d), (s), (NATIVE_INT)(n))
#define STRCMP(d,s) strcmp((d), (s))
#define STRCAT(d,s) strcat((d), (s))
-#define STRNCAT(d,s,n) strncat((d), (s), (n))
-#define STRTOUL(d,s,n) strtoul((d), (s), (n))
-#define MEMCPY(d,s,n) memcpy((d), (s), (n))
-#define MEMSET(d,s,n) memset((d), (s), (n))
+#define STRNCAT(d,s,n) strncat((d), (s), (NATIVE_INT)(n))
+#define STRTOUL(d,s,n) strtoul((d), (s), (NATIVE_INT)(n))
+#define MEMCPY(d,s,n) memcpy((d), (s), (NATIVE_INT)(n))
+#define MEMSET(d,s,n) memset((d), (s), (NATIVE_INT)(n))
#define TOUPPER toupper
#define TOLOWER tolower
-
+#define IS_XDIGIT isxdigit
/******************************************************************************
*
diff --git a/drivers/acpi/include/acevents.h b/drivers/acpi/include/acevents.h
index 3e76370bf..b7d335451 100644
--- a/drivers/acpi/include/acevents.h
+++ b/drivers/acpi/include/acevents.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: acevents.h - Event subcomponent prototypes and defines
- * $Revision: 62 $
+ * $Revision: 63 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/include/acexcep.h b/drivers/acpi/include/acexcep.h
index 1629a0934..8fb267585 100644
--- a/drivers/acpi/include/acexcep.h
+++ b/drivers/acpi/include/acexcep.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: acexcep.h - Exception codes returned by the ACPI subsystem
- * $Revision: 37 $
+ * $Revision: 41 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -116,8 +116,10 @@
#define AE_AML_NAME_NOT_FOUND (ACPI_STATUS) (0x0010 | AE_CODE_AML)
#define AE_AML_INTERNAL (ACPI_STATUS) (0x0011 | AE_CODE_AML)
#define AE_AML_INVALID_SPACE_ID (ACPI_STATUS) (0x0012 | AE_CODE_AML)
+#define AE_AML_STRING_LIMIT (ACPI_STATUS) (0x0013 | AE_CODE_AML)
+#define AE_AML_NO_RETURN_VALUE (ACPI_STATUS) (0x0014 | AE_CODE_AML)
-#define AE_CODE_AML_MAX 0x0012
+#define AE_CODE_AML_MAX 0x0014
/*
* Internal exceptions used for control
@@ -202,6 +204,8 @@ static NATIVE_CHAR *acpi_gbl_exception_names_aml[] =
"AE_AML_NAME_NOT_FOUND",
"AE_AML_INTERNAL",
"AE_AML_INVALID_SPACE_ID",
+ "AE_AML_STRING_LIMIT",
+ "AE_AML_NO_RETURN_VALUE",
};
static NATIVE_CHAR *acpi_gbl_exception_names_ctrl[] =
diff --git a/drivers/acpi/include/acgcc.h b/drivers/acpi/include/acgcc.h
index 5992f493d..82b1e5139 100644
--- a/drivers/acpi/include/acgcc.h
+++ b/drivers/acpi/include/acgcc.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: acgcc.h - GCC specific defines, etc.
- * $Revision: 2 $
+ * $Revision: 4 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/include/acglobal.h b/drivers/acpi/include/acglobal.h
index 248f72c9d..36444038c 100644
--- a/drivers/acpi/include/acglobal.h
+++ b/drivers/acpi/include/acglobal.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: acglobal.h - Declarations for global variables
- * $Revision: 92 $
+ * $Revision: 96 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -154,7 +154,6 @@ ACPI_EXTERN u8 acpi_gbl_global_lock_set; /* TBD: [Restr
ACPI_EXTERN u8 acpi_gbl_step_to_next_call;
ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present;
-
ACPI_EXTERN ACPI_OBJECT_NOTIFY_HANDLER acpi_gbl_drv_notify;
ACPI_EXTERN ACPI_OBJECT_NOTIFY_HANDLER acpi_gbl_sys_notify;
@@ -162,7 +161,8 @@ ACPI_EXTERN ACPI_OBJECT_NOTIFY_HANDLER acpi_gbl_sys_notify;
extern u8 acpi_gbl_shutdown;
extern u32 acpi_gbl_system_flags;
extern u32 acpi_gbl_startup_flags;
-extern u8 acpi_gbl_decode_to8bit[];
+extern u8 acpi_gbl_decode_to8bit[8];
+extern NATIVE_CHAR acpi_gbl_hex_to_ascii[];
/*****************************************************************************
diff --git a/drivers/acpi/include/achware.h b/drivers/acpi/include/achware.h
index 1a206e8d2..efb97bd2f 100644
--- a/drivers/acpi/include/achware.h
+++ b/drivers/acpi/include/achware.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: achware.h -- hardware specific interfaces
- * $Revision: 48 $
+ * $Revision: 53 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -27,6 +27,10 @@
#define __ACHWARE_H__
+/* PM Timer ticks per second (HZ) */
+#define PM_TIMER_FREQUENCY 3579545
+
+
/* Prototypes */
@@ -92,6 +96,10 @@ void
acpi_hw_clear_acpi_status (
void);
+u32
+acpi_hw_get_bit_shift (
+ u32 mask);
+
/* GPE support */
@@ -121,89 +129,21 @@ acpi_hw_obtain_sleep_type_register_data (
u8 *slp_typ_b);
-/* Cx State Prototypes */
-
-ACPI_STATUS
-acpi_hw_enter_c1(
- ACPI_IO_ADDRESS pblk_address,
- u32 *pm_timer_ticks);
-
-ACPI_STATUS
-acpi_hw_enter_c2(
- ACPI_IO_ADDRESS pblk_address,
- u32 *pm_timer_ticks);
-
-ACPI_STATUS
-acpi_hw_enter_c3(
- ACPI_IO_ADDRESS pblk_address,
- u32 *pm_timer_ticks);
-
-ACPI_STATUS
-acpi_hw_enter_cx (
- ACPI_IO_ADDRESS pblk_address,
- u32 *pm_timer_ticks);
-
-ACPI_STATUS
-acpi_hw_set_cx (
- u32 cx_state);
-
-ACPI_STATUS
-acpi_hw_get_cx_info (
- u32 cx_states[]);
+/* ACPI Timer prototypes */
ACPI_STATUS
-acpi_hw_get_cx_handler (
- u32 cx_state,
- ACPI_C_STATE_HANDLER *handler);
+acpi_get_timer_resolution (
+ u32 *resolution);
ACPI_STATUS
-acpi_hw_set_cx_handler (
- u32 cx_state,
- ACPI_C_STATE_HANDLER handler);
-
-
-/* Throttling Prototypes */
-
-void
-acpi_hw_enable_throttling (
- ACPI_IO_ADDRESS pblk_address);
-
-void
-acpi_hw_disable_throttling (
- ACPI_IO_ADDRESS pblk_address);
-
-u32
-acpi_hw_get_duty_cycle (
- u8 duty_offset,
- ACPI_IO_ADDRESS pblk_address,
- u32 num_throttle_states);
-
-void
-acpi_hw_program_duty_cycle (
- u8 duty_offset,
- u32 duty_cycle,
- ACPI_IO_ADDRESS pblk_address,
- u32 num_throttle_states);
-
-NATIVE_UINT
-acpi_hw_local_pow (
- NATIVE_UINT x,
- NATIVE_UINT y);
-
-
-/* ACPI Timer prototypes */
-
-u32
-acpi_hw_pmt_ticks (
- void);
-
-u32
-acpi_hw_pmt_resolution (
- void);
+acpi_get_timer (
+ u32 *ticks);
ACPI_STATUS
-acpi_get_timer (
- u32 *out_ticks);
+acpi_get_timer_duration (
+ u32 start_ticks,
+ u32 end_ticks,
+ u32 *time_elapsed);
#endif /* __ACHWARE_H__ */
diff --git a/drivers/acpi/include/acinterp.h b/drivers/acpi/include/acinterp.h
index c8c967492..6eb571e5f 100644
--- a/drivers/acpi/include/acinterp.h
+++ b/drivers/acpi/include/acinterp.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: acinterp.h - Interpreter subcomponent prototypes and defines
- * $Revision: 86 $
+ * $Revision: 91 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -70,9 +70,34 @@ acpi_aml_execute_method (
/*
- * amfield - ACPI AML (p-code) execution - field manipulation
+ * amconvrt - object conversion
*/
+ACPI_STATUS
+acpi_aml_convert_to_integer (
+ ACPI_OPERAND_OBJECT **obj_desc,
+ ACPI_WALK_STATE *walk_state);
+
+ACPI_STATUS
+acpi_aml_convert_to_buffer (
+ ACPI_OPERAND_OBJECT **obj_desc,
+ ACPI_WALK_STATE *walk_state);
+
+ACPI_STATUS
+acpi_aml_convert_to_string (
+ ACPI_OPERAND_OBJECT **obj_desc,
+ ACPI_WALK_STATE *walk_state);
+
+ACPI_STATUS
+acpi_aml_convert_to_target_type (
+ OBJECT_TYPE_INTERNAL destination_type,
+ ACPI_OPERAND_OBJECT **obj_desc,
+ ACPI_WALK_STATE *walk_state);
+
+
+/*
+ * amfield - ACPI AML (p-code) execution - field manipulation
+ */
ACPI_STATUS
acpi_aml_read_field (
@@ -419,17 +444,75 @@ acpi_aml_exec_store (
ACPI_WALK_STATE *walk_state);
ACPI_STATUS
-acpi_aml_store_object_to_object (
+acpi_aml_store_object_to_index (
ACPI_OPERAND_OBJECT *val_desc,
ACPI_OPERAND_OBJECT *dest_desc,
ACPI_WALK_STATE *walk_state);
ACPI_STATUS
acpi_aml_store_object_to_node (
- ACPI_OPERAND_OBJECT *val_desc,
+ ACPI_OPERAND_OBJECT *source_desc,
ACPI_NAMESPACE_NODE *node,
ACPI_WALK_STATE *walk_state);
+ACPI_STATUS
+acpi_aml_store_object_to_object (
+ ACPI_OPERAND_OBJECT *source_desc,
+ ACPI_OPERAND_OBJECT *dest_desc,
+ ACPI_WALK_STATE *walk_state);
+
+
+/*
+ *
+ */
+
+ACPI_STATUS
+acpi_aml_resolve_object (
+ ACPI_OPERAND_OBJECT **source_desc_ptr,
+ OBJECT_TYPE_INTERNAL target_type,
+ ACPI_WALK_STATE *walk_state);
+
+ACPI_STATUS
+acpi_aml_store_object (
+ ACPI_OPERAND_OBJECT *source_desc,
+ OBJECT_TYPE_INTERNAL target_type,
+ ACPI_OPERAND_OBJECT **target_desc_ptr,
+ ACPI_WALK_STATE *walk_state);
+
+
+/*
+ * amcopy - object copy
+ */
+
+ACPI_STATUS
+acpi_aml_copy_buffer_to_buffer (
+ ACPI_OPERAND_OBJECT *source_desc,
+ ACPI_OPERAND_OBJECT *target_desc);
+
+ACPI_STATUS
+acpi_aml_copy_string_to_string (
+ ACPI_OPERAND_OBJECT *source_desc,
+ ACPI_OPERAND_OBJECT *target_desc);
+
+ACPI_STATUS
+acpi_aml_copy_integer_to_index_field (
+ ACPI_OPERAND_OBJECT *source_desc,
+ ACPI_OPERAND_OBJECT *target_desc);
+
+ACPI_STATUS
+acpi_aml_copy_integer_to_bank_field (
+ ACPI_OPERAND_OBJECT *source_desc,
+ ACPI_OPERAND_OBJECT *target_desc);
+
+ACPI_STATUS
+acpi_aml_copy_data_to_named_field (
+ ACPI_OPERAND_OBJECT *source_desc,
+ ACPI_NAMESPACE_NODE *node);
+
+ACPI_STATUS
+acpi_aml_copy_integer_to_field_unit (
+ ACPI_OPERAND_OBJECT *source_desc,
+ ACPI_OPERAND_OBJECT *target_desc);
/*
* amutils - interpreter/scanner utilities
diff --git a/drivers/acpi/include/aclinux.h b/drivers/acpi/include/aclinux.h
index 673d5f96b..0cf0e2845 100644
--- a/drivers/acpi/include/aclinux.h
+++ b/drivers/acpi/include/aclinux.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: aclinux.h - OS specific defines, etc.
- * $Revision: 6 $
+ * $Revision: 7 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/include/aclocal.h b/drivers/acpi/include/aclocal.h
index a647026f1..2d931387e 100644
--- a/drivers/acpi/include/aclocal.h
+++ b/drivers/acpi/include/aclocal.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: aclocal.h - Internal data types used across the ACPI subsystem
- * $Revision: 95 $
+ * $Revision: 100 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -74,7 +74,7 @@ typedef u32 ACPI_MUTEX_HANDLE;
#define NUM_MTX MAX_MTX+1
-#ifdef ACPI_DEBUG
+#if defined(ACPI_DEBUG) || defined(ENABLE_DEBUGGER)
#ifdef DEFINE_ACPI_GLOBALS
/* Names for the mutexes used in the subsystem */
@@ -476,7 +476,9 @@ typedef struct acpi_opcode_info
u32 parse_args; /* Grammar/Parse time arguments */
u32 runtime_args; /* Interpret time arguments */
- DEBUG_ONLY_MEMBERS (NATIVE_CHAR *name) /* op name (debug only) */
+#ifdef _OPCODE_NAMES
+ NATIVE_CHAR *name; /* op name (debug only) */
+#endif
} ACPI_OPCODE_INFO;
@@ -591,6 +593,7 @@ typedef struct acpi_walk_state
ACPI_GENERIC_STATE *scope_info; /* Stack of nested scopes */
ACPI_PARSE_STATE *parser_state; /* Current state of parser */
u8 *aml_last_while;
+ ACPI_OPCODE_INFO *op_info; /* Info on current opcode */
ACPI_PARSE_DOWNWARDS descending_callback;
ACPI_PARSE_UPWARDS ascending_callback;
@@ -605,6 +608,7 @@ typedef struct acpi_walk_state
u32 parse_flags;
u8 walk_type;
u8 return_used;
+ u16 opcode; /* Current AML opcode */
u32 prev_arg_types;
/* Debug support */
@@ -728,14 +732,16 @@ typedef struct acpi_get_devices_info
#define PM1_STS 0x0100
#define PM1_EN 0x0200
#define PM1_CONTROL 0x0300
-#define PM2_CONTROL 0x0400
-#define PM_TIMER 0x0500
-#define PROCESSOR_BLOCK 0x0600
-#define GPE0_STS_BLOCK 0x0700
-#define GPE0_EN_BLOCK 0x0800
-#define GPE1_STS_BLOCK 0x0900
-#define GPE1_EN_BLOCK 0x0A00
-#define SMI_CMD_BLOCK 0x0B00
+#define PM1_a_CONTROL 0x0400
+#define PM1_b_CONTROL 0x0500
+#define PM2_CONTROL 0x0600
+#define PM_TIMER 0x0700
+#define PROCESSOR_BLOCK 0x0800
+#define GPE0_STS_BLOCK 0x0900
+#define GPE0_EN_BLOCK 0x0A00
+#define GPE1_STS_BLOCK 0x0B00
+#define GPE1_EN_BLOCK 0x0C00
+#define SMI_CMD_BLOCK 0x0D00
/*
* Address space bitmasks for mmio or io spaces
@@ -751,66 +757,66 @@ typedef struct acpi_get_devices_info
/*
* Control bit definitions
*/
-#define TMR_STS (PM1_STS | 0x01)
-#define BM_STS (PM1_STS | 0x02)
-#define GBL_STS (PM1_STS | 0x03)
-#define PWRBTN_STS (PM1_STS | 0x04)
-#define SLPBTN_STS (PM1_STS | 0x05)
-#define RTC_STS (PM1_STS | 0x06)
-#define WAK_STS (PM1_STS | 0x07)
-
-#define TMR_EN (PM1_EN | 0x01)
+#define TMR_STS (PM1_STS | 0x01)
+#define BM_STS (PM1_STS | 0x02)
+#define GBL_STS (PM1_STS | 0x03)
+#define PWRBTN_STS (PM1_STS | 0x04)
+#define SLPBTN_STS (PM1_STS | 0x05)
+#define RTC_STS (PM1_STS | 0x06)
+#define WAK_STS (PM1_STS | 0x07)
+
+#define TMR_EN (PM1_EN | 0x01)
/* no BM_EN */
-#define GBL_EN (PM1_EN | 0x03)
-#define PWRBTN_EN (PM1_EN | 0x04)
-#define SLPBTN_EN (PM1_EN | 0x05)
-#define RTC_EN (PM1_EN | 0x06)
-#define WAK_EN (PM1_EN | 0x07)
+#define GBL_EN (PM1_EN | 0x03)
+#define PWRBTN_EN (PM1_EN | 0x04)
+#define SLPBTN_EN (PM1_EN | 0x05)
+#define RTC_EN (PM1_EN | 0x06)
+#define WAK_EN (PM1_EN | 0x07)
-#define SCI_EN (PM1_CONTROL | 0x01)
-#define BM_RLD (PM1_CONTROL | 0x02)
-#define GBL_RLS (PM1_CONTROL | 0x03)
-#define SLP_TYPE_A (PM1_CONTROL | 0x04)
-#define SLP_TYPE_B (PM1_CONTROL | 0x05)
-#define SLP_EN (PM1_CONTROL | 0x06)
+#define SCI_EN (PM1_CONTROL | 0x01)
+#define BM_RLD (PM1_CONTROL | 0x02)
+#define GBL_RLS (PM1_CONTROL | 0x03)
+#define SLP_TYPE_A (PM1_CONTROL | 0x04)
+#define SLP_TYPE_B (PM1_CONTROL | 0x05)
+#define SLP_EN (PM1_CONTROL | 0x06)
-#define ARB_DIS (PM2_CONTROL | 0x01)
+#define ARB_DIS (PM2_CONTROL | 0x01)
-#define TMR_VAL (PM_TIMER | 0x01)
+#define TMR_VAL (PM_TIMER | 0x01)
-#define GPE0_STS (GPE0_STS_BLOCK | 0x01)
-#define GPE0_EN (GPE0_EN_BLOCK | 0x01)
+#define GPE0_STS (GPE0_STS_BLOCK | 0x01)
+#define GPE0_EN (GPE0_EN_BLOCK | 0x01)
-#define GPE1_STS (GPE1_STS_BLOCK | 0x01)
-#define GPE1_EN (GPE1_EN_BLOCK | 0x01)
+#define GPE1_STS (GPE1_STS_BLOCK | 0x01)
+#define GPE1_EN (GPE1_EN_BLOCK | 0x01)
-#define TMR_STS_MASK 0x0001
-#define BM_STS_MASK 0x0010
-#define GBL_STS_MASK 0x0020
-#define PWRBTN_STS_MASK 0x0100
-#define SLPBTN_STS_MASK 0x0200
-#define RTC_STS_MASK 0x0400
-#define WAK_STS_MASK 0x8000
+#define TMR_STS_MASK 0x0001
+#define BM_STS_MASK 0x0010
+#define GBL_STS_MASK 0x0020
+#define PWRBTN_STS_MASK 0x0100
+#define SLPBTN_STS_MASK 0x0200
+#define RTC_STS_MASK 0x0400
+#define WAK_STS_MASK 0x8000
-#define ALL_FIXED_STS_BITS (TMR_STS_MASK | BM_STS_MASK | GBL_STS_MASK \
- | PWRBTN_STS_MASK | SLPBTN_STS_MASK \
- | RTC_STS_MASK | WAK_STS_MASK)
+#define ALL_FIXED_STS_BITS (TMR_STS_MASK | BM_STS_MASK | GBL_STS_MASK \
+ | PWRBTN_STS_MASK | SLPBTN_STS_MASK \
+ | RTC_STS_MASK | WAK_STS_MASK)
-#define TMR_EN_MASK 0x0001
-#define GBL_EN_MASK 0x0020
-#define PWRBTN_EN_MASK 0x0100
-#define SLPBTN_EN_MASK 0x0200
-#define RTC_EN_MASK 0x0400
+#define TMR_EN_MASK 0x0001
+#define GBL_EN_MASK 0x0020
+#define PWRBTN_EN_MASK 0x0100
+#define SLPBTN_EN_MASK 0x0200
+#define RTC_EN_MASK 0x0400
-#define SCI_EN_MASK 0x0001
-#define BM_RLD_MASK 0x0002
-#define GBL_RLS_MASK 0x0004
-#define SLP_TYPE_X_MASK 0x1C00
-#define SLP_EN_MASK 0x2000
+#define SCI_EN_MASK 0x0001
+#define BM_RLD_MASK 0x0002
+#define GBL_RLS_MASK 0x0004
+#define SLP_TYPE_X_MASK 0x1C00
+#define SLP_EN_MASK 0x2000
-#define ARB_DIS_MASK 0x0001
-#define TMR_VAL_MASK 0xFFFFFFFF
+#define ARB_DIS_MASK 0x0001
+#define TMR_VAL_MASK 0xFFFFFFFF
#define GPE0_STS_MASK
#define GPE0_EN_MASK
@@ -819,8 +825,8 @@ typedef struct acpi_get_devices_info
#define GPE1_EN_MASK
-#define ACPI_READ 1
-#define ACPI_WRITE 2
+#define ACPI_READ 1
+#define ACPI_WRITE 2
/* Plug and play */
diff --git a/drivers/acpi/include/acmacros.h b/drivers/acpi/include/acmacros.h
index 19cfa0591..7bed83ddd 100644
--- a/drivers/acpi/include/acmacros.h
+++ b/drivers/acpi/include/acmacros.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: acmacros.h - C macros for the entire subsystem.
- * $Revision: 59 $
+ * $Revision: 62 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -30,6 +30,14 @@
* Data manipulation macros
*/
+#ifndef LODWORD
+#define LODWORD(l) ((u32)(UINT64)(l))
+#endif
+
+#ifndef HIDWORD
+#define HIDWORD(l) ((u32)((((UINT64)(l)) >> 32) & 0xFFFFFFFF))
+#endif
+
#ifndef LOWORD
#define LOWORD(l) ((u16)(NATIVE_UINT)(l))
#endif
@@ -64,10 +72,18 @@
#ifdef _IA16
+/*
+ * For 16-bit addresses, we have to assume that the upper 32 bits
+ * are zero.
+ */
#define ACPI_GET_ADDRESS(a) ((a).lo)
#define ACPI_STORE_ADDRESS(a,b) {(a).hi=0;(a).lo=(b);}
-#define ACPI_VALID_ADDRESS(a) ((a).hi && (a).lo)
+#define ACPI_VALID_ADDRESS(a) ((a).hi | (a).lo)
+
#else
+/*
+ * Full 64-bit address on 32-bit and 64-bit platforms
+ */
#define ACPI_GET_ADDRESS(a) (a)
#define ACPI_STORE_ADDRESS(a,b) ((a)=(b))
#define ACPI_VALID_ADDRESS(a) (a)
@@ -335,7 +351,7 @@
*/
#define return_VOID {function_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name);return;}
#define return_ACPI_STATUS(s) {function_status_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name,s);return(s);}
-#define return_VALUE(s) {function_value_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name,(NATIVE_UINT)s);return(s);}
+#define return_VALUE(s) {function_value_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name,(ACPI_INTEGER)s);return(s);}
#define return_PTR(s) {function_ptr_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name,(u8 *)s);return(s);}
@@ -346,6 +362,8 @@
#define DEBUG_DEFINE(a) a;
#define DEBUG_ONLY_MEMBERS(a) a;
+#define _OPCODE_NAMES
+#define _VERBOSE_STRUCTURES
/* Stack and buffer dumping */
@@ -458,9 +476,8 @@
*/
#ifdef _IA16
#undef DEBUG_ONLY_MEMBERS
+#undef _VERBOSE_STRUCTURES
#define DEBUG_ONLY_MEMBERS(a)
-#undef OP_INFO_ENTRY
-#define OP_INFO_ENTRY(flags,name,Pargs,Iargs) {flags,Pargs,Iargs}
#endif
diff --git a/drivers/acpi/include/acnamesp.h b/drivers/acpi/include/acnamesp.h
index e010a8118..d6acb8444 100644
--- a/drivers/acpi/include/acnamesp.h
+++ b/drivers/acpi/include/acnamesp.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: acnamesp.h - Namespace subcomponent prototypes and defines
- * $Revision: 100 $
+ * $Revision: 101 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/include/acobject.h b/drivers/acpi/include/acobject.h
index c801ff117..9394b470a 100644
--- a/drivers/acpi/include/acobject.h
+++ b/drivers/acpi/include/acobject.h
@@ -2,12 +2,12 @@
/******************************************************************************
*
* Name: acobject.h - Definition of ACPI_OPERAND_OBJECT (Internal object only)
- * $Revision: 75 $
+ * $Revision: 78 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -113,10 +113,10 @@ typedef struct /* NUMBER - has value */
ACPI_INTEGER value;
-} ACPI_OBJECT_NUMBER;
+} ACPI_OBJECT_INTEGER;
-typedef struct /* STRING - has length and pointer */
+typedef struct /* STRING - has length and pointer - Null terminated, ASCII characters only */
{
ACPI_OBJECT_COMMON_HEADER
@@ -126,13 +126,11 @@ typedef struct /* STRING - has length and pointer */
} ACPI_OBJECT_STRING;
-typedef struct /* BUFFER - has length, sequence, and pointer */
+typedef struct /* BUFFER - has length and pointer - not null terminated */
{
ACPI_OBJECT_COMMON_HEADER
u32 length;
- u32 sequence; /* Sequential count of buffers created */
-
u8 *pointer; /* points to the buffer in allocated space */
} ACPI_OBJECT_BUFFER;
@@ -398,7 +396,7 @@ typedef union acpi_operand_obj
{
ACPI_OBJECT_COMMON common;
ACPI_OBJECT_CACHE_LIST cache;
- ACPI_OBJECT_NUMBER number;
+ ACPI_OBJECT_INTEGER integer;
ACPI_OBJECT_STRING string;
ACPI_OBJECT_BUFFER buffer;
ACPI_OBJECT_PACKAGE package;
diff --git a/drivers/acpi/include/acoutput.h b/drivers/acpi/include/acoutput.h
index 664a5f8a8..5c20943cb 100644
--- a/drivers/acpi/include/acoutput.h
+++ b/drivers/acpi/include/acoutput.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: acoutput.h -- debug output
- * $Revision: 66 $
+ * $Revision: 69 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -58,6 +58,7 @@
#define BATTERY 0x00040000
#define DEBUGGER 0x00100000
+#define COMPILER 0x00200000
#define ALL_COMPONENTS 0x001FFFFF
#define COMPONENT_DEFAULT (ALL_COMPONENTS)
diff --git a/drivers/acpi/include/acparser.h b/drivers/acpi/include/acparser.h
index d657749da..9b4bfabea 100644
--- a/drivers/acpi/include/acparser.h
+++ b/drivers/acpi/include/acparser.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: acparser.h - AML Parser subcomponent prototypes and defines
- * $Revision: 47 $
+ * $Revision: 49 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/include/acpi.h b/drivers/acpi/include/acpi.h
index 4896c4a7f..344b01a77 100644
--- a/drivers/acpi/include/acpi.h
+++ b/drivers/acpi/include/acpi.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: acpi.h - Master include file, Publics and external data.
- * $Revision: 48 $
+ * $Revision: 50 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/include/acpiosxf.h b/drivers/acpi/include/acpiosxf.h
index 2f9eb4c13..ee289f33e 100644
--- a/drivers/acpi/include/acpiosxf.h
+++ b/drivers/acpi/include/acpiosxf.h
@@ -9,7 +9,7 @@
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -121,6 +121,10 @@ acpi_os_unmap_memory (
void *logical_address,
u32 length);
+ACPI_STATUS
+acpi_os_get_physical_address (
+ void *logical_address,
+ ACPI_PHYSICAL_ADDRESS *physical_address);
/*
* Interrupt handlers
diff --git a/drivers/acpi/include/acpixf.h b/drivers/acpi/include/acpixf.h
index d70fa75a7..8d293818f 100644
--- a/drivers/acpi/include/acpixf.h
+++ b/drivers/acpi/include/acpixf.h
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -285,6 +285,10 @@ acpi_get_firmware_waking_vector (
ACPI_PHYSICAL_ADDRESS *physical_address);
ACPI_STATUS
+acpi_enter_sleep_state (
+ u8 sleep_state);
+
+ACPI_STATUS
acpi_get_processor_throttling_info (
ACPI_HANDLE processor_handle,
ACPI_BUFFER *user_buffer);
diff --git a/drivers/acpi/include/acresrc.h b/drivers/acpi/include/acresrc.h
index 3bb19490d..0852367d2 100644
--- a/drivers/acpi/include/acresrc.h
+++ b/drivers/acpi/include/acresrc.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: acresrc.h - Resource Manager function prototypes
- * $Revision: 20 $
+ * $Revision: 22 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/include/actables.h b/drivers/acpi/include/actables.h
index 4dd724517..be8b5e3b0 100644
--- a/drivers/acpi/include/actables.h
+++ b/drivers/acpi/include/actables.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: actables.h - ACPI table management
- * $Revision: 27 $
+ * $Revision: 29 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/include/actbl.h b/drivers/acpi/include/actbl.h
index 34631e820..7a41842d2 100644
--- a/drivers/acpi/include/actbl.h
+++ b/drivers/acpi/include/actbl.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: actbl.h - Table data structures defined in ACPI specification
- * $Revision: 43 $
+ * $Revision: 45 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/include/actbl1.h b/drivers/acpi/include/actbl1.h
index 019ba1680..5c68ca050 100644
--- a/drivers/acpi/include/actbl1.h
+++ b/drivers/acpi/include/actbl1.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: actbl1.h - ACPI 1.0 tables
- * $Revision: 15 $
+ * $Revision: 17 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/include/actbl2.h b/drivers/acpi/include/actbl2.h
index e3ccf2188..0a05efa1c 100644
--- a/drivers/acpi/include/actbl2.h
+++ b/drivers/acpi/include/actbl2.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: actbl2.h - ACPI Specification Revision 2.0 Tables
- * $Revision: 19 $
+ * $Revision: 21 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -142,8 +142,8 @@ typedef struct
u16 plvl3_lat; /* worst case HW latency to enter/exit C3 state */
u16 flush_size; /* number of flush strides that need to be read */
u16 flush_stride; /* Processor's memory cache line width, in bytes */
- u8 duty_offset; /* Processor’s duty cycle index in processor's P_CNT reg*/
- u8 duty_width; /* Processor’s duty cycle value bit width in P_CNT register.*/
+ u8 duty_offset; /* Processor_’s duty cycle index in processor's P_CNT reg*/
+ u8 duty_width; /* Processor_’s duty cycle value bit width in P_CNT register.*/
u8 day_alrm; /* index to day-of-month alarm in RTC CMOS RAM */
u8 mon_alrm; /* index to month-of-year alarm in RTC CMOS RAM */
u8 century; /* index to century in RTC CMOS RAM */
diff --git a/drivers/acpi/include/actbl71.h b/drivers/acpi/include/actbl71.h
index 408ec402e..095806ccb 100644
--- a/drivers/acpi/include/actbl71.h
+++ b/drivers/acpi/include/actbl71.h
@@ -3,12 +3,12 @@
* Name: actbl71.h - IA-64 Extensions to the ACPI Spec Rev. 0.71
* This file includes tables specific to this
* specification revision.
- * $Revision: 7 $
+ * $Revision: 9 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/include/actypes.h b/drivers/acpi/include/actypes.h
index dfa28a9d9..826fc8901 100644
--- a/drivers/acpi/include/actypes.h
+++ b/drivers/acpi/include/actypes.h
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Name: actypes.h - Common data types for the entire ACPI subsystem
- * $Revision: 159 $
+ * $Revision: 163 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -97,7 +97,7 @@ typedef INT16 NATIVE_INT;
typedef UINT32 ACPI_TBLPTR;
typedef UINT32 ACPI_IO_ADDRESS;
-typedef void *ACPI_PHYSICAL_ADDRESS;
+typedef char *ACPI_PHYSICAL_ADDRESS;
#define ALIGNED_ADDRESS_BOUNDARY 0x00000002
#define _HW_ALIGNMENT_SUPPORT
@@ -249,8 +249,9 @@ typedef UINT64 ACPI_INTEGER;
#define ACPI_STATE_S2 (u8) 2
#define ACPI_STATE_S3 (u8) 3
#define ACPI_STATE_S4 (u8) 4
-#define ACPI_STATE_S4_bIOS (u8) 5
-#define ACPI_STATE_S5 (u8) 6
+#define ACPI_STATE_S5 (u8) 5
+/* let's pretend S4_bIOS didn't exist for now. ASG */
+#define ACPI_STATE_S4_bIOS (u8) 6
#define ACPI_S_STATES_MAX ACPI_STATE_S5
@@ -284,8 +285,37 @@ typedef u32 ACPI_TABLE_TYPE;
typedef u32 ACPI_OBJECT_TYPE;
typedef u8 OBJECT_TYPE_INTERNAL;
+#define ACPI_BTYPE_ANY 0x00000000
+#define ACPI_BTYPE_INTEGER 0x00000001
+#define ACPI_BTYPE_STRING 0x00000002
+#define ACPI_BTYPE_BUFFER 0x00000004
+#define ACPI_BTYPE_PACKAGE 0x00000008
+#define ACPI_BTYPE_FIELD_UNIT 0x00000010
+#define ACPI_BTYPE_DEVICE 0x00000020
+#define ACPI_BTYPE_EVENT 0x00000040
+#define ACPI_BTYPE_METHOD 0x00000080
+#define ACPI_BTYPE_MUTEX 0x00000100
+#define ACPI_BTYPE_REGION 0x00000200
+#define ACPI_BTYPE_POWER 0x00000400
+#define ACPI_BTYPE_PROCESSOR 0x00000800
+#define ACPI_BTYPE_THERMAL 0x00001000
+#define ACPI_BTYPE_BUFFER_FIELD 0x00002000
+#define ACPI_BTYPE_DDB_HANDLE 0x00004000
+#define ACPI_BTYPE_DEBUG_OBJECT 0x00008000
+#define ACPI_BTYPE_REFERENCE 0x00010000
+#define ACPI_BTYPE_RESOURCE 0x00020000
+
+#define ACPI_BTYPE_COMPUTE_DATA (ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER)
+
+#define ACPI_BTYPE_DATA (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_PACKAGE)
+#define ACPI_BTYPE_DATA_REFERENCE (ACPI_BTYPE_DATA | ACPI_BTYPE_REFERENCE | ACPI_BTYPE_DDB_HANDLE)
+#define ACPI_BTYPE_DEVICE_OBJECTS (ACPI_BTYPE_DEVICE | ACPI_BTYPE_THERMAL | ACPI_BTYPE_PROCESSOR)
+#define ACPI_BTYPE_OBJECTS_AND_REFS 0x00017FFF /* ARG or LOCAL */
+#define ACPI_BTYPE_ALL_OBJECTS 0x00007FFF
+
+
#define ACPI_TYPE_ANY 0 /* 0x00 */
-#define ACPI_TYPE_NUMBER 1 /* 0x01 Byte/Word/Dword/Zero/One/Ones */
+#define ACPI_TYPE_INTEGER 1 /* 0x01 Byte/Word/Dword/Zero/One/Ones */
#define ACPI_TYPE_STRING 2 /* 0x02 */
#define ACPI_TYPE_BUFFER 3 /* 0x03 */
#define ACPI_TYPE_PACKAGE 4 /* 0x04 Byte_const, multiple Data_term/Constant/Super_name */
@@ -432,7 +462,7 @@ typedef union acpi_obj
{
ACPI_OBJECT_TYPE type;
ACPI_INTEGER value; /* The actual number */
- } number;
+ } integer;
struct
{
diff --git a/drivers/acpi/include/amlcode.h b/drivers/acpi/include/amlcode.h
index 9a5cb2c52..707e7535d 100644
--- a/drivers/acpi/include/amlcode.h
+++ b/drivers/acpi/include/amlcode.h
@@ -3,12 +3,12 @@
* Name: amlcode.h - Definitions for AML, as included in "definition blocks"
* Declarations and definitions contained herein are derived
* directly from the ACPI specification.
- * $Revision: 42 $
+ * $Revision: 46 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -211,27 +211,42 @@
#define ARGP_TERMARG 0x0E
#define ARGP_TERMLIST 0x0F
#define ARGP_WORDDATA 0x10
+#define ARGP_QWORDDATA 0x11
+#define ARGP_SIMPLENAME 0x12
/*
* Resolved argument types for the AML Interpreter
* Each field in the Arg_types u32 is 5 bits, allowing for a maximum of 6 arguments.
- * There can be up to 31 unique argument types
+ * There can be up to 31 unique argument types (0 is end-of-arg-list indicator)
*/
-#define ARGI_ANYTYPE 0x01
-#define ARGI_TARGETREF 0x02
-#define ARGI_REFERENCE 0x03
-#define ARGI_IF 0x04
-#define ARGI_NUMBER 0x05
-#define ARGI_STRING 0x06
-#define ARGI_BUFFER 0x07
-#define ARGI_PACKAGE 0x08
-#define ARGI_DATAOBJECT 0x09 /* Buffer, string, package or reference to a Node - Used only by Size_of operator*/
-#define ARGI_COMPLEXOBJ 0x0A /* Buffer or package */
-#define ARGI_MUTEX 0x0B
-#define ARGI_EVENT 0x0C
-#define ARGI_REGION 0x0D
-#define ARGI_DDBHANDLE 0x0E
+/* "Standard" ACPI types are 1-15 (0x0F) */
+
+#define ARGI_INTEGER ACPI_TYPE_INTEGER /* 1 */
+#define ARGI_STRING ACPI_TYPE_STRING /* 2 */
+#define ARGI_BUFFER ACPI_TYPE_BUFFER /* 3 */
+#define ARGI_PACKAGE ACPI_TYPE_PACKAGE /* 4 */
+#define ARGI_EVENT ACPI_TYPE_EVENT
+#define ARGI_MUTEX ACPI_TYPE_MUTEX
+#define ARGI_REGION ACPI_TYPE_REGION
+#define ARGI_DDBHANDLE ACPI_TYPE_DDB_HANDLE
+
+/* Custom types are 0x10 through 0x1F */
+
+#define ARGI_IF 0x10
+#define ARGI_ANYOBJECT 0x11
+#define ARGI_ANYTYPE 0x12
+#define ARGI_COMPUTEDATA 0x13 /* Buffer, String, or Integer */
+#define ARGI_DATAOBJECT 0x14 /* Buffer, string, package or reference to a Node - Used only by Size_of operator*/
+#define ARGI_COMPLEXOBJ 0x15 /* Buffer or package */
+#define ARGI_INTEGER_REF 0x16
+#define ARGI_OBJECT_REF 0x17
+#define ARGI_DEVICE_REF 0x18
+#define ARGI_REFERENCE 0x19
+#define ARGI_TARGETREF 0x1A /* Target, subject to implicit conversion */
+#define ARGI_FIXED_TARGET 0x1B /* Target, no implicit conversion */
+#define ARGI_SIMPLE_TARGET 0x1C /* Name, Local, Arg -- no implicit conversion */
+#define ARGI_BUFFERSTRING 0x1D
#define ARGI_INVALID_OPCODE 0xFFFFFFFF
diff --git a/drivers/acpi/interpreter/amconfig.c b/drivers/acpi/interpreter/amconfig.c
index 55e5b0510..497f35375 100644
--- a/drivers/acpi/interpreter/amconfig.c
+++ b/drivers/acpi/interpreter/amconfig.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: amconfig - Namespace reconfiguration (Load/Unload opcodes)
- * $Revision: 26 $
+ * $Revision: 29 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -73,7 +73,8 @@ acpi_aml_exec_load_table (
table_header.length = 0;
for (i = 0; i < sizeof (ACPI_TABLE_HEADER); i++) {
status = acpi_ev_address_space_dispatch (rgn_desc, ADDRESS_SPACE_READ,
- i, 8, (u32 *) ((u8 *) &table_header + i));
+ (ACPI_PHYSICAL_ADDRESS) i, 8,
+ (u32 *) ((u8 *) &table_header + i));
if (ACPI_FAILURE (status)) {
return (status);
}
@@ -96,7 +97,8 @@ acpi_aml_exec_load_table (
for (i = 0; i < table_header.length; i++) {
status = acpi_ev_address_space_dispatch (rgn_desc, ADDRESS_SPACE_READ,
- i, 8, (u32 *) (table_data_ptr + i));
+ (ACPI_PHYSICAL_ADDRESS)i, 8,
+ (u32 *) (table_data_ptr + i));
if (ACPI_FAILURE (status)) {
goto cleanup;
}
diff --git a/drivers/acpi/interpreter/amconvrt.c b/drivers/acpi/interpreter/amconvrt.c
new file mode 100644
index 000000000..4c895c7ed
--- /dev/null
+++ b/drivers/acpi/interpreter/amconvrt.c
@@ -0,0 +1,525 @@
+/******************************************************************************
+ *
+ * Module Name: amconvrt - Object conversion routines
+ * $Revision: 3 $
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000, 2001 R. Byron Moore
+ *
+ * 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
+ */
+
+
+#include "acpi.h"
+#include "acparser.h"
+#include "acnamesp.h"
+#include "acinterp.h"
+#include "acevents.h"
+#include "amlcode.h"
+#include "acdispat.h"
+
+
+#define _COMPONENT INTERPRETER
+ MODULE_NAME ("amconvrt")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_aml_convert_to_target_type
+ *
+ * PARAMETERS: *Obj_desc - Object to be converted.
+ * Walk_state - Current method state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION:
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_convert_to_target_type (
+ OBJECT_TYPE_INTERNAL destination_type,
+ ACPI_OPERAND_OBJECT **obj_desc,
+ ACPI_WALK_STATE *walk_state)
+{
+ ACPI_STATUS status = AE_OK;
+
+
+ /*
+ * If required by the target,
+ * perform implicit conversion on the source before we store it.
+ */
+
+ switch (GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args))
+ {
+ case ARGI_SIMPLE_TARGET:
+ case ARGI_FIXED_TARGET:
+ case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */
+
+ switch (destination_type)
+ {
+ case INTERNAL_TYPE_DEF_FIELD:
+ /*
+ * Named field can always handle conversions
+ */
+ break;
+
+ default:
+ /* No conversion allowed for these types */
+
+ if (destination_type != (*obj_desc)->common.type) {
+ status = AE_TYPE;
+ }
+ }
+ break;
+
+
+ case ARGI_TARGETREF:
+
+ switch (destination_type)
+ {
+ case ACPI_TYPE_INTEGER:
+ case ACPI_TYPE_FIELD_UNIT:
+ case INTERNAL_TYPE_BANK_FIELD:
+ case INTERNAL_TYPE_INDEX_FIELD:
+ /*
+ * These types require an Integer operand. We can convert
+ * a Buffer or a String to an Integer if necessary.
+ */
+ status = acpi_aml_convert_to_integer (obj_desc, walk_state);
+ break;
+
+
+ case ACPI_TYPE_STRING:
+
+ /*
+ * The operand must be a String. We can convert an
+ * Integer or Buffer if necessary
+ */
+ status = acpi_aml_convert_to_string (obj_desc, walk_state);
+ break;
+
+
+ case ACPI_TYPE_BUFFER:
+
+ /*
+ * The operand must be a String. We can convert an
+ * Integer or Buffer if necessary
+ */
+ status = acpi_aml_convert_to_buffer (obj_desc, walk_state);
+ break;
+ }
+ break;
+
+
+ case ARGI_REFERENCE:
+ /*
+ * Create_xxxx_field cases - we are storing the field object into the name
+ */
+ break;
+
+
+ default:
+ status = AE_AML_INTERNAL;
+ }
+
+
+ /*
+ * Source-to-Target conversion semantics:
+ *
+ * If conversion to the target type cannot be performed, then simply
+ * overwrite the target with the new object and type.
+ */
+ if (status == AE_TYPE) {
+ status = AE_OK;
+ }
+
+ return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_aml_convert_to_integer
+ *
+ * PARAMETERS: *Obj_desc - Object to be converted. Must be an
+ * Integer, Buffer, or String
+ * Walk_state - Current method state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert an ACPI Object to an integer.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_convert_to_integer (
+ ACPI_OPERAND_OBJECT **obj_desc,
+ ACPI_WALK_STATE *walk_state)
+{
+ u32 i;
+ ACPI_OPERAND_OBJECT *ret_desc;
+ u32 count;
+ char *pointer;
+ ACPI_INTEGER result;
+ u32 integer_size = sizeof (ACPI_INTEGER);
+
+
+ switch ((*obj_desc)->common.type)
+ {
+ case ACPI_TYPE_INTEGER:
+ return (AE_OK);
+
+ case ACPI_TYPE_STRING:
+ pointer = (*obj_desc)->string.pointer;
+ count = (*obj_desc)->string.length;
+ break;
+
+ case ACPI_TYPE_BUFFER:
+ pointer = (char *) (*obj_desc)->buffer.pointer;
+ count = (*obj_desc)->buffer.length;
+ break;
+
+ default:
+ return (AE_TYPE);
+ }
+
+ /*
+ * Create a new integer
+ */
+ ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
+ if (!ret_desc) {
+ return (AE_NO_MEMORY);
+ }
+
+
+ /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
+
+ if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
+ /*
+ * We are running a method that exists in a 32-bit ACPI table.
+ * Truncate the value to 32 bits by zeroing out the upper 32-bit field
+ */
+ integer_size = sizeof (u32);
+ }
+
+
+ /*
+ * Convert the buffer/string to an integer. Note that both buffers and
+ * strings are treated as raw data - we don't convert ascii to hex for
+ * strings.
+ *
+ * There are two terminating conditions for the loop:
+ * 1) The size of an integer has been reached, or
+ * 2) The end of the buffer or string has been reached
+ */
+ result = 0;
+
+ /* Transfer no more than an integer's worth of data */
+
+ if (count > integer_size) {
+ count = integer_size;
+ }
+
+ /*
+ * String conversion is different than Buffer conversion
+ */
+ switch ((*obj_desc)->common.type)
+ {
+ case ACPI_TYPE_STRING:
+
+ /* TBD: Need to use 64-bit STRTOUL */
+
+ /*
+ * Convert string to an integer
+ * String must be hexadecimal as per the ACPI specification
+ */
+
+ result = STRTOUL (pointer, NULL, 16);
+ break;
+
+
+ case ACPI_TYPE_BUFFER:
+
+ /*
+ * Buffer conversion - we simply grab enough raw data from the
+ * buffer to fill an integer
+ */
+ for (i = 0; i < count; i++) {
+ /*
+ * Get next byte and shift it into the Result.
+ * Little endian is used, meaning that the first byte of the buffer
+ * is the LSB of the integer
+ */
+ result |= (((ACPI_INTEGER) pointer[i]) << (i * 8));
+ }
+
+ break;
+ }
+
+ /* Save the Result, delete original descriptor, store new descriptor */
+
+ ret_desc->integer.value = result;
+
+ if (walk_state->opcode != AML_STORE_OP) {
+ acpi_cm_remove_reference (*obj_desc);
+ }
+
+ *obj_desc = ret_desc;
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_aml_convert_to_buffer
+ *
+ * PARAMETERS: *Obj_desc - Object to be converted. Must be an
+ * Integer, Buffer, or String
+ * Walk_state - Current method state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert an ACPI Object to an Buffer
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_convert_to_buffer (
+ ACPI_OPERAND_OBJECT **obj_desc,
+ ACPI_WALK_STATE *walk_state)
+{
+ ACPI_OPERAND_OBJECT *ret_desc;
+ u32 i;
+ u32 integer_size = sizeof (ACPI_INTEGER);
+ u8 *new_buf;
+
+
+ switch ((*obj_desc)->common.type)
+ {
+ case ACPI_TYPE_INTEGER:
+
+ /*
+ * Create a new Buffer
+ */
+ ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_BUFFER);
+ if (!ret_desc) {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
+
+ if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
+ /*
+ * We are running a method that exists in a 32-bit ACPI table.
+ * Truncate the value to 32 bits by zeroing out the upper
+ * 32-bit field
+ */
+ integer_size = sizeof (u32);
+ }
+
+ /* Need enough space for one integers */
+
+ ret_desc->buffer.length = integer_size;
+ new_buf = acpi_cm_callocate (integer_size);
+ if (!new_buf) {
+ REPORT_ERROR
+ (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
+ acpi_cm_remove_reference (ret_desc);
+ return (AE_NO_MEMORY);
+ }
+
+ /* Copy the integer to the buffer */
+
+ for (i = 0; i < integer_size; i++) {
+ new_buf[i] = (u8) ((*obj_desc)->integer.value >> (i * 8));
+ }
+ ret_desc->buffer.pointer = new_buf;
+
+ /* Return the new buffer descriptor */
+
+ if (walk_state->opcode != AML_STORE_OP) {
+ acpi_cm_remove_reference (*obj_desc);
+ }
+ *obj_desc = ret_desc;
+ break;
+
+
+ case ACPI_TYPE_STRING:
+ break;
+
+
+ case ACPI_TYPE_BUFFER:
+ break;
+
+
+ default:
+ return (AE_TYPE);
+ break;
+ }
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_aml_convert_to_string
+ *
+ * PARAMETERS: *Obj_desc - Object to be converted. Must be an
+ * Integer, Buffer, or String
+ * Walk_state - Current method state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert an ACPI Object to a string
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_convert_to_string (
+ ACPI_OPERAND_OBJECT **obj_desc,
+ ACPI_WALK_STATE *walk_state)
+{
+ ACPI_OPERAND_OBJECT *ret_desc;
+ u32 i;
+ u32 index;
+ u32 integer_size = sizeof (ACPI_INTEGER);
+ u8 *new_buf;
+ u8 *pointer;
+
+
+ switch ((*obj_desc)->common.type)
+ {
+ case ACPI_TYPE_INTEGER:
+
+ /*
+ * Create a new String
+ */
+ ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING);
+ if (!ret_desc) {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
+
+ if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
+ /*
+ * We are running a method that exists in a 32-bit ACPI table.
+ * Truncate the value to 32 bits by zeroing out the upper
+ * 32-bit field
+ */
+ integer_size = sizeof (u32);
+ }
+
+ /* Need enough space for one ASCII integer plus null terminator */
+
+ ret_desc->string.length = (integer_size * 2) + 1;
+ new_buf = acpi_cm_callocate (ret_desc->string.length);
+ if (!new_buf) {
+ REPORT_ERROR
+ (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
+ acpi_cm_remove_reference (ret_desc);
+ return (AE_NO_MEMORY);
+ }
+
+ /* Copy the integer to the buffer */
+
+ for (i = 0; i < (integer_size * 2); i++) {
+ new_buf[i] = acpi_gbl_hex_to_ascii [((*obj_desc)->integer.value >> (i * 4)) & 0xF];
+ }
+
+ /* Null terminate */
+
+ new_buf [i] = 0;
+ ret_desc->buffer.pointer = new_buf;
+
+ /* Return the new buffer descriptor */
+
+ if (walk_state->opcode != AML_STORE_OP) {
+ acpi_cm_remove_reference (*obj_desc);
+ }
+ *obj_desc = ret_desc;
+
+ return (AE_OK);
+
+
+ case ACPI_TYPE_BUFFER:
+
+ if (((*obj_desc)->buffer.length * 3) > ACPI_MAX_STRING_CONVERSION) {
+ return (AE_AML_STRING_LIMIT);
+ }
+
+ /*
+ * Create a new String
+ */
+ ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING);
+ if (!ret_desc) {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Need enough space for one ASCII integer plus null terminator */
+
+ ret_desc->string.length = (*obj_desc)->buffer.length * 3;
+ new_buf = acpi_cm_callocate (ret_desc->string.length + 1);
+ if (!new_buf) {
+ REPORT_ERROR
+ (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
+ acpi_cm_remove_reference (ret_desc);
+ return (AE_NO_MEMORY);
+ }
+
+ /*
+ * Convert each byte of the buffer to two ASCII characters plus a space.
+ */
+ pointer = (*obj_desc)->buffer.pointer;
+ index = 0;
+ for (i = 0; i < (*obj_desc)->buffer.length; i++) {
+ new_buf[index + 0] = acpi_gbl_hex_to_ascii [pointer[i] & 0x0F];
+ new_buf[index + 1] = acpi_gbl_hex_to_ascii [(pointer[i] >> 4) & 0x0F];
+ new_buf[index + 2] = ' ';
+ index += 3;
+ }
+
+ /* Null terminate */
+
+ new_buf [index] = 0;
+ ret_desc->buffer.pointer = new_buf;
+
+ /* Return the new buffer descriptor */
+
+ if (walk_state->opcode != AML_STORE_OP) {
+ acpi_cm_remove_reference (*obj_desc);
+ }
+ *obj_desc = ret_desc;
+ break;
+
+
+ case ACPI_TYPE_STRING:
+ break;
+
+
+ default:
+ return (AE_TYPE);
+ break;
+ }
+
+ return (AE_OK);
+}
+
+
diff --git a/drivers/acpi/interpreter/amcreate.c b/drivers/acpi/interpreter/amcreate.c
index 02d7933e1..f19c422ce 100644
--- a/drivers/acpi/interpreter/amcreate.c
+++ b/drivers/acpi/interpreter/amcreate.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: amcreate - Named object creation
- * $Revision: 51 $
+ * $Revision: 53 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -353,7 +353,7 @@ acpi_aml_exec_create_mutex (
goto cleanup;
}
- obj_desc->mutex.sync_level = (u8) sync_desc->number.value;
+ obj_desc->mutex.sync_level = (u8) sync_desc->integer.value;
/* Obj_desc was on the stack top, and the name is below it */
diff --git a/drivers/acpi/interpreter/amdyadic.c b/drivers/acpi/interpreter/amdyadic.c
index ba67b062a..a02173f29 100644
--- a/drivers/acpi/interpreter/amdyadic.c
+++ b/drivers/acpi/interpreter/amdyadic.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: amdyadic - ACPI AML (p-code) execution for dyadic operators
- * $Revision: 68 $
+ * $Revision: 71 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -37,7 +37,174 @@
MODULE_NAME ("amdyadic")
-/*****************************************************************************
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_aml_do_concatenate
+ *
+ * PARAMETERS: *Obj_desc - Object to be converted. Must be an
+ * Integer, Buffer, or String
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Concatenate two objects OF THE SAME TYPE.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_do_concatenate (
+ ACPI_OPERAND_OBJECT *obj_desc,
+ ACPI_OPERAND_OBJECT *obj_desc2,
+ ACPI_OPERAND_OBJECT **actual_ret_desc,
+ ACPI_WALK_STATE *walk_state)
+{
+ ACPI_STATUS status;
+ u32 i;
+ ACPI_INTEGER this_integer;
+ ACPI_OPERAND_OBJECT *ret_desc;
+ NATIVE_CHAR *new_buf;
+ u32 integer_size = sizeof (ACPI_INTEGER);
+
+
+ /*
+ * There are three cases to handle:
+ * 1) Two Integers concatenated to produce a buffer
+ * 2) Two Strings concatenated to produce a string
+ * 3) Two Buffers concatenated to produce a buffer
+ */
+ switch (obj_desc->common.type)
+ {
+ case ACPI_TYPE_INTEGER:
+
+ /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
+
+ if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
+ /*
+ * We are running a method that exists in a 32-bit ACPI table.
+ * Truncate the value to 32 bits by zeroing out the upper
+ * 32-bit field
+ */
+ integer_size = sizeof (u32);
+ }
+
+ /* Result of two integers is a buffer */
+
+ ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_BUFFER);
+ if (!ret_desc) {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Need enough space for two integers */
+
+ ret_desc->buffer.length = integer_size * 2;
+ new_buf = acpi_cm_callocate (ret_desc->buffer.length);
+ if (!new_buf) {
+ REPORT_ERROR
+ (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
+ status = AE_NO_MEMORY;
+ goto cleanup;
+ }
+
+ ret_desc->buffer.pointer = (u8 *) new_buf;
+
+ /* Convert the first integer */
+
+ this_integer = obj_desc->integer.value;
+ for (i = 0; i < integer_size; i++) {
+ new_buf[i] = (u8) this_integer;
+ this_integer >>= 8;
+ }
+
+ /* Convert the second integer */
+
+ this_integer = obj_desc2->integer.value;
+ for (; i < (integer_size * 2); i++) {
+ new_buf[i] = (u8) this_integer;
+ this_integer >>= 8;
+ }
+
+ break;
+
+
+ case ACPI_TYPE_STRING:
+
+ ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING);
+ if (!ret_desc) {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Operand1 is string */
+
+ new_buf = acpi_cm_allocate (obj_desc->string.length +
+ obj_desc2->string.length + 1);
+ if (!new_buf) {
+ REPORT_ERROR
+ (("Aml_exec_dyadic2_r/Concat_op: String allocation failure\n"));
+ status = AE_NO_MEMORY;
+ goto cleanup;
+ }
+
+ STRCPY (new_buf, obj_desc->string.pointer);
+ STRCPY (new_buf + obj_desc->string.length,
+ obj_desc2->string.pointer);
+
+ /* Point the return object to the new string */
+
+ ret_desc->string.pointer = new_buf;
+ ret_desc->string.length = obj_desc->string.length +=
+ obj_desc2->string.length;
+ break;
+
+
+ case ACPI_TYPE_BUFFER:
+
+ /* Operand1 is a buffer */
+
+ ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_BUFFER);
+ if (!ret_desc) {
+ return (AE_NO_MEMORY);
+ }
+
+ new_buf = acpi_cm_allocate (obj_desc->buffer.length +
+ obj_desc2->buffer.length);
+ if (!new_buf) {
+ REPORT_ERROR
+ (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
+ status = AE_NO_MEMORY;
+ goto cleanup;
+ }
+
+ MEMCPY (new_buf, obj_desc->buffer.pointer,
+ obj_desc->buffer.length);
+ MEMCPY (new_buf + obj_desc->buffer.length, obj_desc2->buffer.pointer,
+ obj_desc2->buffer.length);
+
+ /*
+ * Point the return object to the new buffer
+ */
+
+ ret_desc->buffer.pointer = (u8 *) new_buf;
+ ret_desc->buffer.length = obj_desc->buffer.length +
+ obj_desc2->buffer.length;
+ break;
+
+ default:
+ status = AE_AML_INTERNAL;
+ ret_desc = NULL;
+ }
+
+
+ *actual_ret_desc = ret_desc;
+ return (AE_OK);
+
+
+cleanup:
+
+ acpi_cm_remove_reference (ret_desc);
+ return (status);
+}
+
+
+/*******************************************************************************
*
* FUNCTION: Acpi_aml_exec_dyadic1
*
@@ -50,7 +217,7 @@
*
* ALLOCATION: Deletes both operands
*
- ****************************************************************************/
+ ******************************************************************************/
ACPI_STATUS
acpi_aml_exec_dyadic1 (
@@ -106,7 +273,7 @@ acpi_aml_exec_dyadic1 (
/* Dispatch the notify to the appropriate handler */
- acpi_ev_notify_dispatch (node, (u32) val_desc->number.value);
+ acpi_ev_notify_dispatch (node, (u32) val_desc->integer.value);
break;
default:
@@ -135,7 +302,7 @@ cleanup:
}
-/*****************************************************************************
+/*******************************************************************************
*
* FUNCTION: Acpi_aml_exec_dyadic2_r
*
@@ -148,7 +315,7 @@ cleanup:
*
* ALLOCATION: Deletes one operand descriptor -- other remains on stack
*
- ****************************************************************************/
+ ******************************************************************************/
ACPI_STATUS
acpi_aml_exec_dyadic2_r (
@@ -164,7 +331,6 @@ acpi_aml_exec_dyadic2_r (
ACPI_OPERAND_OBJECT *ret_desc2 = NULL;
ACPI_STATUS status = AE_OK;
u32 num_operands = 3;
- NATIVE_CHAR *new_buf;
/* Resolve all operands */
@@ -201,7 +367,7 @@ acpi_aml_exec_dyadic2_r (
case AML_SHIFT_RIGHT_OP:
case AML_SUBTRACT_OP:
- ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+ ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
if (!ret_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -222,8 +388,8 @@ acpi_aml_exec_dyadic2_r (
case AML_ADD_OP:
- ret_desc->number.value = obj_desc->number.value +
- obj_desc2->number.value;
+ ret_desc->integer.value = obj_desc->integer.value +
+ obj_desc2->integer.value;
break;
@@ -231,8 +397,8 @@ acpi_aml_exec_dyadic2_r (
case AML_BIT_AND_OP:
- ret_desc->number.value = obj_desc->number.value &
- obj_desc2->number.value;
+ ret_desc->integer.value = obj_desc->integer.value &
+ obj_desc2->integer.value;
break;
@@ -240,8 +406,8 @@ acpi_aml_exec_dyadic2_r (
case AML_BIT_NAND_OP:
- ret_desc->number.value = ~(obj_desc->number.value &
- obj_desc2->number.value);
+ ret_desc->integer.value = ~(obj_desc->integer.value &
+ obj_desc2->integer.value);
break;
@@ -249,8 +415,8 @@ acpi_aml_exec_dyadic2_r (
case AML_BIT_OR_OP:
- ret_desc->number.value = obj_desc->number.value |
- obj_desc2->number.value;
+ ret_desc->integer.value = obj_desc->integer.value |
+ obj_desc2->integer.value;
break;
@@ -258,8 +424,8 @@ acpi_aml_exec_dyadic2_r (
case AML_BIT_NOR_OP:
- ret_desc->number.value = ~(obj_desc->number.value |
- obj_desc2->number.value);
+ ret_desc->integer.value = ~(obj_desc->integer.value |
+ obj_desc2->integer.value);
break;
@@ -267,16 +433,16 @@ acpi_aml_exec_dyadic2_r (
case AML_BIT_XOR_OP:
- ret_desc->number.value = obj_desc->number.value ^
- obj_desc2->number.value;
+ ret_desc->integer.value = obj_desc->integer.value ^
+ obj_desc2->integer.value;
break;
- /* Def_divide := Divide_op Dividend Divisor Remainder Quotient */
+ /* Def_divide := Divide_op Dividend Divisor Remainder Quotient */
case AML_DIVIDE_OP:
- if (!obj_desc2->number.value) {
+ if (!obj_desc2->integer.value) {
REPORT_ERROR
(("Aml_exec_dyadic2_r/Divide_op: Divide by zero\n"));
@@ -284,7 +450,7 @@ acpi_aml_exec_dyadic2_r (
goto cleanup;
}
- ret_desc2 = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+ ret_desc2 = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
if (!ret_desc2) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -292,13 +458,13 @@ acpi_aml_exec_dyadic2_r (
/* Remainder (modulo) */
- ret_desc->number.value = ACPI_MODULO (obj_desc->number.value,
- obj_desc2->number.value);
+ ret_desc->integer.value = ACPI_MODULO (obj_desc->integer.value,
+ obj_desc2->integer.value);
/* Result (what we used to call the quotient) */
- ret_desc2->number.value = ACPI_DIVIDE (obj_desc->number.value,
- obj_desc2->number.value);
+ ret_desc2->integer.value = ACPI_DIVIDE (obj_desc->integer.value,
+ obj_desc2->integer.value);
break;
@@ -306,8 +472,8 @@ acpi_aml_exec_dyadic2_r (
case AML_MULTIPLY_OP:
- ret_desc->number.value = obj_desc->number.value *
- obj_desc2->number.value;
+ ret_desc->integer.value = obj_desc->integer.value *
+ obj_desc2->integer.value;
break;
@@ -315,8 +481,8 @@ acpi_aml_exec_dyadic2_r (
case AML_SHIFT_LEFT_OP:
- ret_desc->number.value = obj_desc->number.value <<
- obj_desc2->number.value;
+ ret_desc->integer.value = obj_desc->integer.value <<
+ obj_desc2->integer.value;
break;
@@ -324,8 +490,8 @@ acpi_aml_exec_dyadic2_r (
case AML_SHIFT_RIGHT_OP:
- ret_desc->number.value = obj_desc->number.value >>
- obj_desc2->number.value;
+ ret_desc->integer.value = obj_desc->integer.value >>
+ obj_desc2->integer.value;
break;
@@ -333,8 +499,8 @@ acpi_aml_exec_dyadic2_r (
case AML_SUBTRACT_OP:
- ret_desc->number.value = obj_desc->number.value -
- obj_desc2->number.value;
+ ret_desc->integer.value = obj_desc->integer.value -
+ obj_desc2->integer.value;
break;
@@ -342,79 +508,54 @@ acpi_aml_exec_dyadic2_r (
case AML_CONCAT_OP:
- if (obj_desc2->common.type != obj_desc->common.type) {
- status = AE_AML_OPERAND_TYPE;
- goto cleanup;
- }
- /* Both operands are now known to be the same */
-
- if (ACPI_TYPE_STRING == obj_desc->common.type) {
- ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING);
- if (!ret_desc) {
- status = AE_NO_MEMORY;
- goto cleanup;
- }
+ /*
+ * Convert the second operand if necessary. The first operand
+ * determines the type of the second operand, (See the Data Types
+ * section of the ACPI specification.) Both object types are
+ * guaranteed to be either Integer/String/Buffer by the operand
+ * resolution mechanism above.
+ */
- /* Operand1 is string */
+ switch (obj_desc->common.type)
+ {
+ case ACPI_TYPE_INTEGER:
+ status = acpi_aml_convert_to_integer (&obj_desc2, walk_state);
+ break;
- new_buf = acpi_cm_allocate (obj_desc->string.length +
- obj_desc2->string.length + 1);
- if (!new_buf) {
- REPORT_ERROR
- (("Aml_exec_dyadic2_r/Concat_op: String allocation failure\n"));
- status = AE_NO_MEMORY;
- goto cleanup;
- }
+ case ACPI_TYPE_STRING:
+ status = acpi_aml_convert_to_string (&obj_desc2, walk_state);
+ break;
- STRCPY (new_buf, obj_desc->string.pointer);
- STRCPY (new_buf + obj_desc->string.length,
- obj_desc2->string.pointer);
+ case ACPI_TYPE_BUFFER:
+ status = acpi_aml_convert_to_buffer (&obj_desc2, walk_state);
+ break;
- /* Point the return object to the new string */
-
- ret_desc->string.pointer = new_buf;
- ret_desc->string.length = obj_desc->string.length +=
- obj_desc2->string.length;
+ default:
+ status = AE_AML_INTERNAL;
}
- else {
- /* Operand1 is not a string ==> must be a buffer */
-
- ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_BUFFER);
- if (!ret_desc) {
- status = AE_NO_MEMORY;
- goto cleanup;
- }
-
- new_buf = acpi_cm_allocate (obj_desc->buffer.length +
- obj_desc2->buffer.length);
- if (!new_buf) {
- REPORT_ERROR
- (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
- status = AE_NO_MEMORY;
- goto cleanup;
- }
-
- MEMCPY (new_buf, obj_desc->buffer.pointer,
- obj_desc->buffer.length);
- MEMCPY (new_buf + obj_desc->buffer.length, obj_desc2->buffer.pointer,
- obj_desc2->buffer.length);
+ if (ACPI_FAILURE (status)) {
+ goto cleanup;
+ }
- /*
- * Point the return object to the new buffer
- */
- ret_desc->buffer.pointer = (u8 *) new_buf;
- ret_desc->buffer.length = obj_desc->buffer.length +
- obj_desc2->buffer.length;
+ /*
+ * Both operands are now known to be the same object type
+ * (Both are Integer, String, or Buffer), and we can now perform the
+ * concatenation.
+ */
+ status = acpi_aml_do_concatenate (obj_desc, obj_desc2, &ret_desc, walk_state);
+ if (ACPI_FAILURE (status)) {
+ goto cleanup;
}
break;
default:
- REPORT_ERROR (("Acpi_aml_exec_dyadic2_r: Unknown dyadic opcode %X\n", opcode));
+ REPORT_ERROR (("Acpi_aml_exec_dyadic2_r: Unknown dyadic opcode %X\n",
+ opcode));
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
@@ -474,7 +615,7 @@ cleanup:
}
-/*****************************************************************************
+/*******************************************************************************
*
* FUNCTION: Acpi_aml_exec_dyadic2_s
*
@@ -486,7 +627,7 @@ cleanup:
*
* ALLOCATION: Deletes one operand descriptor -- other remains on stack
*
- ****************************************************************************/
+ ******************************************************************************/
ACPI_STATUS
acpi_aml_exec_dyadic2_s (
@@ -516,7 +657,7 @@ acpi_aml_exec_dyadic2_s (
/* Create the internal return object */
- ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+ ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
if (!ret_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -524,7 +665,7 @@ acpi_aml_exec_dyadic2_s (
/* Default return value is FALSE, operation did not time out */
- ret_desc->number.value = 0;
+ ret_desc->integer.value = 0;
/* Examine the opcode */
@@ -562,7 +703,7 @@ acpi_aml_exec_dyadic2_s (
*/
if (status == AE_TIME) {
- ret_desc->number.value = ACPI_INTEGER_MAX; /* TRUE, op timed out */
+ ret_desc->integer.value = ACPI_INTEGER_MAX; /* TRUE, op timed out */
status = AE_OK;
}
@@ -591,7 +732,7 @@ cleanup:
}
-/*****************************************************************************
+/*******************************************************************************
*
* FUNCTION: Acpi_aml_exec_dyadic2
*
@@ -605,7 +746,7 @@ cleanup:
* ALLOCATION: Deletes one operand descriptor -- other remains on stack
* containing result value
*
- ****************************************************************************/
+ ******************************************************************************/
ACPI_STATUS
acpi_aml_exec_dyadic2 (
@@ -636,7 +777,7 @@ acpi_aml_exec_dyadic2 (
/* Create the internal return object */
- ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+ ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
if (!ret_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -654,8 +795,8 @@ acpi_aml_exec_dyadic2 (
case AML_LAND_OP:
- lboolean = (u8) (obj_desc->number.value &&
- obj_desc2->number.value);
+ lboolean = (u8) (obj_desc->integer.value &&
+ obj_desc2->integer.value);
break;
@@ -663,8 +804,8 @@ acpi_aml_exec_dyadic2 (
case AML_LEQUAL_OP:
- lboolean = (u8) (obj_desc->number.value ==
- obj_desc2->number.value);
+ lboolean = (u8) (obj_desc->integer.value ==
+ obj_desc2->integer.value);
break;
@@ -672,8 +813,8 @@ acpi_aml_exec_dyadic2 (
case AML_LGREATER_OP:
- lboolean = (u8) (obj_desc->number.value >
- obj_desc2->number.value);
+ lboolean = (u8) (obj_desc->integer.value >
+ obj_desc2->integer.value);
break;
@@ -681,8 +822,8 @@ acpi_aml_exec_dyadic2 (
case AML_LLESS_OP:
- lboolean = (u8) (obj_desc->number.value <
- obj_desc2->number.value);
+ lboolean = (u8) (obj_desc->integer.value <
+ obj_desc2->integer.value);
break;
@@ -690,8 +831,8 @@ acpi_aml_exec_dyadic2 (
case AML_LOR_OP:
- lboolean = (u8) (obj_desc->number.value ||
- obj_desc2->number.value);
+ lboolean = (u8) (obj_desc->integer.value ||
+ obj_desc2->integer.value);
break;
@@ -707,10 +848,10 @@ acpi_aml_exec_dyadic2 (
/* Set return value to logical TRUE (all ones) or FALSE (zero) */
if (lboolean) {
- ret_desc->number.value = ACPI_INTEGER_MAX;
+ ret_desc->integer.value = ACPI_INTEGER_MAX;
}
else {
- ret_desc->number.value = 0;
+ ret_desc->integer.value = 0;
}
diff --git a/drivers/acpi/interpreter/amfield.c b/drivers/acpi/interpreter/amfield.c
index 356be14c2..3ed442c95 100644
--- a/drivers/acpi/interpreter/amfield.c
+++ b/drivers/acpi/interpreter/amfield.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: amfield - ACPI AML (p-code) execution - field manipulation
- * $Revision: 74 $
+ * $Revision: 77 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -174,7 +174,8 @@ acpi_aml_access_named_field (
u32 byte_field_length;
- /* Basic data checking */
+ /* Parameter validation */
+
if ((!named_field) || (ACPI_READ == mode && !buffer)) {
return (AE_AML_INTERNAL);
}
@@ -227,7 +228,7 @@ acpi_aml_access_named_field (
/* TBD: should these round down to a power of 2? */
- if (DIV_8(bit_granularity) > byte_field_length) {
+ if (DIV_8 (bit_granularity) > byte_field_length) {
bit_granularity = MUL_8(byte_field_length);
}
diff --git a/drivers/acpi/interpreter/amfldio.c b/drivers/acpi/interpreter/amfldio.c
index ce877c982..d16cd3d9b 100644
--- a/drivers/acpi/interpreter/amfldio.c
+++ b/drivers/acpi/interpreter/amfldio.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: amfldio - Aml Field I/O
- * $Revision: 32 $
+ * $Revision: 37 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -132,7 +132,7 @@ acpi_aml_read_field (
u32 this_field_byte_offset;
u32 this_field_datum_offset;
u32 previous_raw_datum;
- u32 this_raw_datum;
+ u32 this_raw_datum = 0;
u32 valid_field_bits;
u32 mask;
u32 merged_datum = 0;
@@ -203,32 +203,46 @@ acpi_aml_read_field (
while (this_field_datum_offset < datum_length) {
/*
- * Get the next raw datum, it contains bits of the current
- * field datum
+ * If the field is aligned on a byte boundary, we don't want
+ * to perform a final read, since this would potentially read
+ * past the end of the region.
+ *
+ * TBD: [Investigate] It may make more sense to just split the aligned
+ * and non-aligned cases since the aligned case is so very simple,
*/
-
- status = acpi_aml_read_field_data (obj_desc,
- this_field_byte_offset + byte_granularity,
- bit_granularity, &this_raw_datum);
- if (ACPI_FAILURE (status)) {
- goto cleanup;
- }
-
- /* Before merging the data, make sure the unused bits are clear */
-
- switch (byte_granularity)
+ if ((obj_desc->field.bit_offset != 0) ||
+ ((obj_desc->field.bit_offset == 0) &&
+ (this_field_datum_offset < (datum_length -1))))
{
- case 1:
- this_raw_datum &= 0x000000FF;
- previous_raw_datum &= 0x000000FF;
- break;
-
- case 2:
- this_raw_datum &= 0x0000FFFF;
- previous_raw_datum &= 0x0000FFFF;
- break;
+ /*
+ * Get the next raw datum, it contains some or all bits
+ * of the current field datum
+ */
+
+ status = acpi_aml_read_field_data (obj_desc,
+ this_field_byte_offset + byte_granularity,
+ bit_granularity, &this_raw_datum);
+ if (ACPI_FAILURE (status)) {
+ goto cleanup;
+ }
+
+ /* Before merging the data, make sure the unused bits are clear */
+
+ switch (byte_granularity)
+ {
+ case 1:
+ this_raw_datum &= 0x000000FF;
+ previous_raw_datum &= 0x000000FF;
+ break;
+
+ case 2:
+ this_raw_datum &= 0x0000FFFF;
+ previous_raw_datum &= 0x0000FFFF;
+ break;
+ }
}
+
/*
* Put together bits of the two raw data to make a complete
* field datum
@@ -391,8 +405,6 @@ acpi_aml_write_field_data_with_update_rule (
merged_value = field_value;
- /* Check if update rule needs to be applied (not if mask is all ones) */
-
/* Decode the update rule */
@@ -401,13 +413,17 @@ acpi_aml_write_field_data_with_update_rule (
case UPDATE_PRESERVE:
- /*
- * Read the current contents of the byte/word/dword containing
- * the field, and merge with the new field value.
- */
- status = acpi_aml_read_field_data (obj_desc, this_field_byte_offset,
- bit_granularity, &current_value);
- merged_value |= (current_value & ~mask);
+ /* Check if update rule needs to be applied (not if mask is all ones) */
+
+ if (((1 << bit_granularity) -1) & ~mask) {
+ /*
+ * Read the current contents of the byte/word/dword containing
+ * the field, and merge with the new field value.
+ */
+ status = acpi_aml_read_field_data (obj_desc, this_field_byte_offset,
+ bit_granularity, &current_value);
+ merged_value |= (current_value & ~mask);
+ }
break;
diff --git a/drivers/acpi/interpreter/ammisc.c b/drivers/acpi/interpreter/ammisc.c
index 907169dfc..3c58daeab 100644
--- a/drivers/acpi/interpreter/ammisc.c
+++ b/drivers/acpi/interpreter/ammisc.c
@@ -2,12 +2,12 @@
/******************************************************************************
*
* Module Name: ammisc - ACPI AML (p-code) execution - specific opcodes
- * $Revision: 71 $
+ * $Revision: 73 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -172,7 +172,7 @@ acpi_aml_exec_index (
if (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
/* Object to be indexed is a Package */
- if (idx_desc->number.value >= obj_desc->package.count) {
+ if (idx_desc->integer.value >= obj_desc->package.count) {
status = AE_AML_PACKAGE_LIMIT;
goto cleanup;
}
@@ -195,7 +195,7 @@ acpi_aml_exec_index (
* we are after.
*/
- tmp_desc = obj_desc->package.elements[idx_desc->number.value];
+ tmp_desc = obj_desc->package.elements[idx_desc->integer.value];
ret_desc->reference.op_code = AML_INDEX_OP;
ret_desc->reference.target_type = tmp_desc->common.type;
ret_desc->reference.object = tmp_desc;
@@ -210,13 +210,13 @@ acpi_aml_exec_index (
*/
ret_desc->reference.op_code = AML_INDEX_OP;
ret_desc->reference.target_type = ACPI_TYPE_PACKAGE;
- ret_desc->reference.where = &obj_desc->package.elements[idx_desc->number.value];
+ ret_desc->reference.where = &obj_desc->package.elements[idx_desc->integer.value];
}
else {
/* Object to be indexed is a Buffer */
- if (idx_desc->number.value >= obj_desc->buffer.length) {
+ if (idx_desc->integer.value >= obj_desc->buffer.length) {
status = AE_AML_BUFFER_LIMIT;
goto cleanup;
}
@@ -224,7 +224,7 @@ acpi_aml_exec_index (
ret_desc->reference.op_code = AML_INDEX_OP;
ret_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD;
ret_desc->reference.object = obj_desc;
- ret_desc->reference.offset = (u32) idx_desc->number.value;
+ ret_desc->reference.offset = (u32) idx_desc->integer.value;
status = acpi_aml_exec_store (ret_desc, res_desc, walk_state);
}
@@ -314,20 +314,20 @@ acpi_aml_exec_match (
/* Validate match comparison sub-opcodes */
- if ((op1_desc->number.value > MAX_MATCH_OPERATOR) ||
- (op2_desc->number.value > MAX_MATCH_OPERATOR))
+ if ((op1_desc->integer.value > MAX_MATCH_OPERATOR) ||
+ (op2_desc->integer.value > MAX_MATCH_OPERATOR))
{
status = AE_AML_OPERAND_VALUE;
goto cleanup;
}
- index = (u32) start_desc->number.value;
+ index = (u32) start_desc->integer.value;
if (index >= (u32) pkg_desc->package.count) {
status = AE_AML_PACKAGE_LIMIT;
goto cleanup;
}
- ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+ ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
if (!ret_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -351,7 +351,7 @@ acpi_aml_exec_match (
* should we examine its value?
*/
if (!pkg_desc->package.elements[index] ||
- ACPI_TYPE_NUMBER != pkg_desc->package.elements[index]->common.type)
+ ACPI_TYPE_INTEGER != pkg_desc->package.elements[index]->common.type)
{
continue;
}
@@ -362,7 +362,7 @@ acpi_aml_exec_match (
* "continue" (proceed to next iteration of enclosing
* "for" loop) signifies a non-match.
*/
- switch (op1_desc->number.value)
+ switch (op1_desc->integer.value)
{
case MATCH_MTR: /* always true */
@@ -372,8 +372,8 @@ acpi_aml_exec_match (
case MATCH_MEQ: /* true if equal */
- if (pkg_desc->package.elements[index]->number.value
- != V1_desc->number.value)
+ if (pkg_desc->package.elements[index]->integer.value
+ != V1_desc->integer.value)
{
continue;
}
@@ -382,8 +382,8 @@ acpi_aml_exec_match (
case MATCH_MLE: /* true if less than or equal */
- if (pkg_desc->package.elements[index]->number.value
- > V1_desc->number.value)
+ if (pkg_desc->package.elements[index]->integer.value
+ > V1_desc->integer.value)
{
continue;
}
@@ -392,8 +392,8 @@ acpi_aml_exec_match (
case MATCH_MLT: /* true if less than */
- if (pkg_desc->package.elements[index]->number.value
- >= V1_desc->number.value)
+ if (pkg_desc->package.elements[index]->integer.value
+ >= V1_desc->integer.value)
{
continue;
}
@@ -402,8 +402,8 @@ acpi_aml_exec_match (
case MATCH_MGE: /* true if greater than or equal */
- if (pkg_desc->package.elements[index]->number.value
- < V1_desc->number.value)
+ if (pkg_desc->package.elements[index]->integer.value
+ < V1_desc->integer.value)
{
continue;
}
@@ -412,8 +412,8 @@ acpi_aml_exec_match (
case MATCH_MGT: /* true if greater than */
- if (pkg_desc->package.elements[index]->number.value
- <= V1_desc->number.value)
+ if (pkg_desc->package.elements[index]->integer.value
+ <= V1_desc->integer.value)
{
continue;
}
@@ -426,7 +426,7 @@ acpi_aml_exec_match (
}
- switch(op2_desc->number.value)
+ switch(op2_desc->integer.value)
{
case MATCH_MTR:
@@ -436,8 +436,8 @@ acpi_aml_exec_match (
case MATCH_MEQ:
- if (pkg_desc->package.elements[index]->number.value
- != V2_desc->number.value)
+ if (pkg_desc->package.elements[index]->integer.value
+ != V2_desc->integer.value)
{
continue;
}
@@ -446,8 +446,8 @@ acpi_aml_exec_match (
case MATCH_MLE:
- if (pkg_desc->package.elements[index]->number.value
- > V2_desc->number.value)
+ if (pkg_desc->package.elements[index]->integer.value
+ > V2_desc->integer.value)
{
continue;
}
@@ -456,8 +456,8 @@ acpi_aml_exec_match (
case MATCH_MLT:
- if (pkg_desc->package.elements[index]->number.value
- >= V2_desc->number.value)
+ if (pkg_desc->package.elements[index]->integer.value
+ >= V2_desc->integer.value)
{
continue;
}
@@ -466,8 +466,8 @@ acpi_aml_exec_match (
case MATCH_MGE:
- if (pkg_desc->package.elements[index]->number.value
- < V2_desc->number.value)
+ if (pkg_desc->package.elements[index]->integer.value
+ < V2_desc->integer.value)
{
continue;
}
@@ -476,8 +476,8 @@ acpi_aml_exec_match (
case MATCH_MGT:
- if (pkg_desc->package.elements[index]->number.value
- <= V2_desc->number.value)
+ if (pkg_desc->package.elements[index]->integer.value
+ <= V2_desc->integer.value)
{
continue;
}
@@ -497,7 +497,7 @@ acpi_aml_exec_match (
/* Match_value is the return value */
- ret_desc->number.value = match_value;
+ ret_desc->integer.value = match_value;
cleanup:
diff --git a/drivers/acpi/interpreter/ammonad.c b/drivers/acpi/interpreter/ammonad.c
index df9671c06..ea8834a5c 100644
--- a/drivers/acpi/interpreter/ammonad.c
+++ b/drivers/acpi/interpreter/ammonad.c
@@ -2,12 +2,12 @@
/******************************************************************************
*
* Module Name: ammonad - ACPI AML (p-code) execution for monadic operators
- * $Revision: 88 $
+ * $Revision: 89 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -180,7 +180,7 @@ acpi_aml_exec_monadic1 (
case AML_SLEEP_OP:
- acpi_aml_system_do_suspend ((u32) obj_desc->number.value);
+ acpi_aml_system_do_suspend ((u32) obj_desc->integer.value);
break;
@@ -188,7 +188,7 @@ acpi_aml_exec_monadic1 (
case AML_STALL_OP:
- acpi_aml_system_do_stall ((u32) obj_desc->number.value);
+ acpi_aml_system_do_stall ((u32) obj_desc->integer.value);
break;
@@ -267,7 +267,7 @@ acpi_aml_exec_monadic2_r (
case AML_TO_BCD_OP:
case AML_COND_REF_OF_OP:
- ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+ ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
if (!ret_desc) {
status = AE_NO_MEMORY;
goto cleanup;
@@ -283,7 +283,7 @@ acpi_aml_exec_monadic2_r (
case AML_BIT_NOT_OP:
- ret_desc->number.value = ~obj_desc->number.value;
+ ret_desc->integer.value = ~obj_desc->integer.value;
break;
@@ -291,17 +291,17 @@ acpi_aml_exec_monadic2_r (
case AML_FIND_SET_LEFT_BIT_OP:
- ret_desc->number.value = obj_desc->number.value;
+ ret_desc->integer.value = obj_desc->integer.value;
/*
* Acpi specification describes Integer type as a little
* endian unsigned value, so this boundry condition is valid.
*/
- for (res_val = 0; ret_desc->number.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) {
- ret_desc->number.value >>= 1;
+ for (res_val = 0; ret_desc->integer.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) {
+ ret_desc->integer.value >>= 1;
}
- ret_desc->number.value = res_val;
+ ret_desc->integer.value = res_val;
break;
@@ -309,19 +309,19 @@ acpi_aml_exec_monadic2_r (
case AML_FIND_SET_RIGHT_BIT_OP:
- ret_desc->number.value = obj_desc->number.value;
+ ret_desc->integer.value = obj_desc->integer.value;
/*
* Acpi specification describes Integer type as a little
* endian unsigned value, so this boundry condition is valid.
*/
- for (res_val = 0; ret_desc->number.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) {
- ret_desc->number.value <<= 1;
+ for (res_val = 0; ret_desc->integer.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) {
+ ret_desc->integer.value <<= 1;
}
/* Since returns must be 1-based, subtract from 33 (65) */
- ret_desc->number.value = res_val == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - res_val;
+ ret_desc->integer.value = res_val == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - res_val;
break;
@@ -332,11 +332,11 @@ acpi_aml_exec_monadic2_r (
/*
* The 64-bit ACPI integer can hold 16 4-bit BCD integers
*/
- ret_desc->number.value = 0;
+ ret_desc->integer.value = 0;
for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) {
/* Get one BCD digit */
- digit = (ACPI_INTEGER) ((obj_desc->number.value >> (i * 4)) & 0xF);
+ digit = (ACPI_INTEGER) ((obj_desc->integer.value >> (i * 4)) & 0xF);
/* Check the range of the digit */
@@ -352,7 +352,7 @@ acpi_aml_exec_monadic2_r (
digit *= 10;
}
- ret_desc->number.value += digit;
+ ret_desc->integer.value += digit;
}
}
break;
@@ -363,16 +363,16 @@ acpi_aml_exec_monadic2_r (
case AML_TO_BCD_OP:
- if (obj_desc->number.value > ACPI_MAX_BCD_VALUE) {
+ if (obj_desc->integer.value > ACPI_MAX_BCD_VALUE) {
status = AE_AML_NUMERIC_OVERFLOW;
goto cleanup;
}
- ret_desc->number.value = 0;
+ ret_desc->integer.value = 0;
for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) {
/* Divide by nth factor of 10 */
- digit = obj_desc->number.value;
+ digit = obj_desc->integer.value;
for (j = 0; j < i; j++) {
digit /= 10;
}
@@ -380,7 +380,7 @@ acpi_aml_exec_monadic2_r (
/* Create the BCD digit */
if (digit > 0) {
- ret_desc->number.value += (ACPI_MODULO (digit, 10) << (i * 4));
+ ret_desc->integer.value += (ACPI_MODULO (digit, 10) << (i * 4));
}
}
break;
@@ -402,7 +402,7 @@ acpi_aml_exec_monadic2_r (
* return FALSE
*/
- ret_desc->number.value = 0;
+ ret_desc->integer.value = 0;
/*
* Must delete the result descriptor since there is no reference
@@ -424,7 +424,7 @@ acpi_aml_exec_monadic2_r (
/* The object exists in the namespace, return TRUE */
- ret_desc->number.value = ACPI_INTEGER_MAX;
+ ret_desc->integer.value = ACPI_INTEGER_MAX;
goto cleanup;
break;
@@ -579,13 +579,13 @@ acpi_aml_exec_monadic2 (
case AML_LNOT_OP:
- ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+ ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
if (!ret_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
- ret_desc->number.value = !obj_desc->number.value;
+ ret_desc->integer.value = !obj_desc->integer.value;
break;
@@ -638,10 +638,10 @@ acpi_aml_exec_monadic2 (
/* Do the actual increment or decrement */
if (AML_INCREMENT_OP == opcode) {
- ret_desc->number.value++;
+ ret_desc->integer.value++;
}
else {
- ret_desc->number.value--;
+ ret_desc->integer.value--;
}
/* Store the result back in the original descriptor */
@@ -672,7 +672,7 @@ acpi_aml_exec_monadic2 (
/* Constants are of type Number */
- type = ACPI_TYPE_NUMBER;
+ type = ACPI_TYPE_INTEGER;
break;
@@ -733,13 +733,13 @@ acpi_aml_exec_monadic2 (
/* Allocate a descriptor to hold the type. */
- ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+ ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
if (!ret_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
- ret_desc->number.value = type;
+ ret_desc->integer.value = type;
break;
@@ -793,13 +793,13 @@ acpi_aml_exec_monadic2 (
* object to hold the value
*/
- ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+ ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
if (!ret_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
- ret_desc->number.value = value;
+ ret_desc->integer.value = value;
break;
@@ -910,14 +910,14 @@ acpi_aml_exec_monadic2 (
* sub-buffer of the main buffer, it is only a pointer to a
* single element (byte) of the buffer!
*/
- ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+ ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
if (!ret_desc) {
status = AE_NO_MEMORY;
goto cleanup;
}
tmp_desc = obj_desc->reference.object;
- ret_desc->number.value =
+ ret_desc->integer.value =
tmp_desc->buffer.pointer[obj_desc->reference.offset];
/* TBD: [Investigate] (see below) Don't add an additional
diff --git a/drivers/acpi/interpreter/amnames.c b/drivers/acpi/interpreter/amnames.c
index ea4c26e08..07be1a37c 100644
--- a/drivers/acpi/interpreter/amnames.c
+++ b/drivers/acpi/interpreter/amnames.c
@@ -2,12 +2,12 @@
/******************************************************************************
*
* Module Name: amnames - interpreter/scanner name load/execute
- * $Revision: 71 $
+ * $Revision: 73 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/interpreter/amprep.c b/drivers/acpi/interpreter/amprep.c
index 266cb0105..2a56d4826 100644
--- a/drivers/acpi/interpreter/amprep.c
+++ b/drivers/acpi/interpreter/amprep.c
@@ -2,12 +2,12 @@
/******************************************************************************
*
* Module Name: amprep - ACPI AML (p-code) execution - field prep utilities
- * $Revision: 72 $
+ * $Revision: 73 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/interpreter/amregion.c b/drivers/acpi/interpreter/amregion.c
index dfe4fab85..1a2e7351d 100644
--- a/drivers/acpi/interpreter/amregion.c
+++ b/drivers/acpi/interpreter/amregion.c
@@ -2,12 +2,12 @@
/******************************************************************************
*
* Module Name: amregion - ACPI default Op_region (address space) handlers
- * $Revision: 41 $
+ * $Revision: 44 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -99,8 +99,8 @@ acpi_aml_system_memory_space_handler (
*/
if ((address < mem_info->mapped_physical_address) ||
- ((address + length) >
- (mem_info->mapped_physical_address + mem_info->mapped_length)))
+ (((ACPI_INTEGER) address + length) >
+ ((ACPI_INTEGER) mem_info->mapped_physical_address + mem_info->mapped_length)))
{
/*
* The request cannot be resolved by the current memory mapping;
@@ -139,7 +139,7 @@ acpi_aml_system_memory_space_handler (
/* TBD: should these pointers go to 64-bit in all cases ? */
logical_addr_ptr = mem_info->mapped_logical_address +
- (address - mem_info->mapped_physical_address);
+ ((ACPI_INTEGER) address - (ACPI_INTEGER) mem_info->mapped_physical_address);
/* Perform the memory read or write */
diff --git a/drivers/acpi/interpreter/amresnte.c b/drivers/acpi/interpreter/amresnte.c
index 20c6a0b11..0dc67b613 100644
--- a/drivers/acpi/interpreter/amresnte.c
+++ b/drivers/acpi/interpreter/amresnte.c
@@ -2,12 +2,12 @@
/******************************************************************************
*
* Module Name: amresnte - AML Interpreter object resolution
- * $Revision: 25 $
+ * $Revision: 27 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -55,7 +55,7 @@
* can be either a pointer to an actual internal object or a pointer into the
* AML stream itself. These types are currently:
*
- * ACPI_TYPE_NUMBER
+ * ACPI_TYPE_INTEGER
* ACPI_TYPE_STRING
* ACPI_TYPE_BUFFER
* ACPI_TYPE_MUTEX
@@ -208,14 +208,14 @@ acpi_aml_resolve_node_to_value (
break;
- case ACPI_TYPE_NUMBER:
+ case ACPI_TYPE_INTEGER:
/*
* The Node has an attached internal object, make sure that it's a
* number
*/
- if (ACPI_TYPE_NUMBER != val_desc->common.type) {
+ if (ACPI_TYPE_INTEGER != val_desc->common.type) {
return (AE_AML_OPERAND_TYPE);
}
@@ -244,7 +244,7 @@ acpi_aml_resolve_node_to_value (
object_type = ACPI_TYPE_BUFFER;
}
else {
- object_type = ACPI_TYPE_NUMBER;
+ object_type = ACPI_TYPE_INTEGER;
}
/*
@@ -282,7 +282,7 @@ acpi_aml_resolve_node_to_value (
return (status);
}
- obj_desc->number.value = temp_val;
+ obj_desc->integer.value = temp_val;
}
@@ -330,12 +330,12 @@ acpi_aml_resolve_node_to_value (
/* Create an object for the result */
- obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+ obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
if (!obj_desc) {
return (AE_NO_MEMORY);
}
- obj_desc->number.value = temp_val;
+ obj_desc->integer.value = temp_val;
break;
@@ -378,12 +378,12 @@ acpi_aml_resolve_node_to_value (
/* Create an object for the result */
- obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+ obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
if (!obj_desc) {
return (AE_NO_MEMORY);
}
- obj_desc->number.value = temp_val;
+ obj_desc->integer.value = temp_val;
break;
@@ -477,12 +477,12 @@ acpi_aml_resolve_node_to_value (
/* Create object for result */
- obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+ obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
if (!obj_desc) {
return (AE_NO_MEMORY);
}
- obj_desc->number.value = temp_val;
+ obj_desc->integer.value = temp_val;
/* Truncate value if we are executing from a 32-bit ACPI table */
diff --git a/drivers/acpi/interpreter/amresolv.c b/drivers/acpi/interpreter/amresolv.c
index 2fa59e9bb..c08a4731c 100644
--- a/drivers/acpi/interpreter/amresolv.c
+++ b/drivers/acpi/interpreter/amresolv.c
@@ -2,12 +2,12 @@
/******************************************************************************
*
* Module Name: amresolv - AML Interpreter object resolution
- * $Revision: 78 $
+ * $Revision: 81 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -118,19 +118,19 @@ acpi_aml_get_field_unit_value (
mask = ACPI_UINT32_MAX;
}
- result_desc->number.type = (u8) ACPI_TYPE_NUMBER;
+ result_desc->integer.type = (u8) ACPI_TYPE_INTEGER;
/* Get the 32 bit value at the location */
- MOVE_UNALIGNED32_TO_32 (&result_desc->number.value, location);
+ MOVE_UNALIGNED32_TO_32 (&result_desc->integer.value, location);
/*
* Shift the 32-bit word containing the field, and mask off the
* resulting value
*/
- result_desc->number.value =
- (result_desc->number.value >> field_desc->field_unit.bit_offset) & mask;
+ result_desc->integer.value =
+ (result_desc->integer.value >> field_desc->field_unit.bit_offset) & mask;
/* Release global lock if we acquired it earlier */
@@ -150,7 +150,7 @@ acpi_aml_get_field_unit_value (
*
* RETURN: Status
*
- * DESCRIPTION: Convert Reference entries on Obj_stack to Rvalues
+ * DESCRIPTION: Convert Reference objects to values
*
******************************************************************************/
@@ -279,7 +279,7 @@ acpi_aml_resolve_object_to_value (
acpi_cm_remove_reference (stack_desc);
*stack_ptr = obj_desc;
- if (ACPI_TYPE_NUMBER == obj_desc->common.type) {
+ if (ACPI_TYPE_INTEGER == obj_desc->common.type) {
/* Value is a Number */
}
@@ -311,7 +311,7 @@ acpi_aml_resolve_object_to_value (
acpi_cm_remove_reference (stack_desc);
*stack_ptr = obj_desc;
- if (ACPI_TYPE_NUMBER == obj_desc->common.type) {
+ if (ACPI_TYPE_INTEGER == obj_desc->common.type) {
/* Value is a Number */
}
@@ -326,22 +326,22 @@ acpi_aml_resolve_object_to_value (
case AML_ZERO_OP:
- stack_desc->common.type = (u8) ACPI_TYPE_NUMBER;
- stack_desc->number.value = 0;
+ stack_desc->common.type = (u8) ACPI_TYPE_INTEGER;
+ stack_desc->integer.value = 0;
break;
case AML_ONE_OP:
- stack_desc->common.type = (u8) ACPI_TYPE_NUMBER;
- stack_desc->number.value = 1;
+ stack_desc->common.type = (u8) ACPI_TYPE_INTEGER;
+ stack_desc->integer.value = 1;
break;
case AML_ONES_OP:
- stack_desc->common.type = (u8) ACPI_TYPE_NUMBER;
- stack_desc->number.value = ACPI_INTEGER_MAX;
+ stack_desc->common.type = (u8) ACPI_TYPE_INTEGER;
+ stack_desc->integer.value = ACPI_INTEGER_MAX;
/* Truncate value if we are executing from a 32-bit ACPI table */
diff --git a/drivers/acpi/interpreter/amresop.c b/drivers/acpi/interpreter/amresop.c
index 83fda4455..a837fd66b 100644
--- a/drivers/acpi/interpreter/amresop.c
+++ b/drivers/acpi/interpreter/amresop.c
@@ -2,12 +2,12 @@
/******************************************************************************
*
* Module Name: amresop - AML Interpreter operand/object resolution
- * $Revision: 18 $
+ * $Revision: 22 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -214,8 +214,13 @@ acpi_aml_resolve_operands (
switch (this_arg_type)
{
- case ARGI_REFERENCE: /* Reference */
- case ARGI_TARGETREF:
+ case ARGI_REFERENCE: /* References */
+ case ARGI_INTEGER_REF:
+ case ARGI_OBJECT_REF:
+ case ARGI_DEVICE_REF:
+ case ARGI_TARGETREF: /* TBD: must implement implicit conversion rules before store */
+ case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */
+ case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion */
/* Need an operand of type INTERNAL_TYPE_REFERENCE */
@@ -283,20 +288,6 @@ acpi_aml_resolve_operands (
* For the simple cases, only one type of resolved object
* is allowed
*/
- case ARGI_NUMBER: /* Number */
-
- /* Need an operand of type ACPI_TYPE_NUMBER */
-
- type_needed = ACPI_TYPE_NUMBER;
- break;
-
- case ARGI_BUFFER:
-
- /* Need an operand of type ACPI_TYPE_BUFFER */
-
- type_needed = ACPI_TYPE_BUFFER;
- break;
-
case ARGI_MUTEX:
/* Need an operand of type ACPI_TYPE_MUTEX */
@@ -344,11 +335,69 @@ acpi_aml_resolve_operands (
* The more complex cases allow multiple resolved object types
*/
+ case ARGI_INTEGER: /* Number */
+
+ /*
+ * Need an operand of type ACPI_TYPE_INTEGER,
+ * But we can implicitly convert from a STRING or BUFFER
+ */
+ status = acpi_aml_convert_to_integer (stack_ptr, walk_state);
+ if (ACPI_FAILURE (status)) {
+ if (status == AE_TYPE) {
+ return (AE_AML_OPERAND_TYPE);
+ }
+
+ return (status);
+ }
+
+ goto next_operand;
+ break;
+
+
+ case ARGI_BUFFER:
+
+ /*
+ * Need an operand of type ACPI_TYPE_BUFFER,
+ * But we can implicitly convert from a STRING or INTEGER
+ */
+ status = acpi_aml_convert_to_buffer (stack_ptr, walk_state);
+ if (ACPI_FAILURE (status)) {
+ if (status == AE_TYPE) {
+ return (AE_AML_OPERAND_TYPE);
+ }
+
+ return (status);
+ }
+
+ goto next_operand;
+ break;
+
+
case ARGI_STRING:
- /* Need an operand of type ACPI_TYPE_STRING or ACPI_TYPE_BUFFER */
+ /*
+ * Need an operand of type ACPI_TYPE_STRING,
+ * But we can implicitly convert from a BUFFER or INTEGER
+ */
+ status = acpi_aml_convert_to_string (stack_ptr, walk_state);
+ if (ACPI_FAILURE (status)) {
+ if (status == AE_TYPE) {
+ return (AE_AML_OPERAND_TYPE);
+ }
+
+ return (status);
+ }
+
+ goto next_operand;
+ break;
+
+
+ case ARGI_COMPUTEDATA:
+
+ /* Need an operand of type INTEGER, STRING or BUFFER */
- if ((ACPI_TYPE_STRING != (*stack_ptr)->common.type) &&
+ if ((ACPI_TYPE_INTEGER != (*stack_ptr)->common.type) &&
+ (ACPI_TYPE_STRING != (*stack_ptr)->common.type) &&
(ACPI_TYPE_BUFFER != (*stack_ptr)->common.type))
{
return (AE_AML_OPERAND_TYPE);
diff --git a/drivers/acpi/interpreter/amstore.c b/drivers/acpi/interpreter/amstore.c
index 8887e0997..9f350bb29 100644
--- a/drivers/acpi/interpreter/amstore.c
+++ b/drivers/acpi/interpreter/amstore.c
@@ -2,12 +2,12 @@
/******************************************************************************
*
* Module Name: amstore - AML Interpreter object store support
- * $Revision: 117 $
+ * $Revision: 121 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -64,12 +64,7 @@ acpi_aml_exec_store (
ACPI_WALK_STATE *walk_state)
{
ACPI_STATUS status = AE_OK;
- ACPI_OPERAND_OBJECT *delete_dest_desc = NULL;
- ACPI_OPERAND_OBJECT *tmp_desc;
- ACPI_NAMESPACE_NODE *node = NULL;
- u8 value = 0;
- u32 length;
- u32 i;
+ ACPI_OPERAND_OBJECT *ref_desc = dest_desc;
/* Validate parameters */
@@ -78,27 +73,23 @@ acpi_aml_exec_store (
return (AE_AML_NO_OPERAND);
}
- /* Examine the datatype of the Dest_desc */
+ /* Dest_desc can be either a namespace node or an ACPI object */
if (VALID_DESCRIPTOR_TYPE (dest_desc, ACPI_DESC_TYPE_NAMED)) {
- /* Dest is an ACPI_HANDLE, create a new object */
-
- node = (ACPI_NAMESPACE_NODE *) dest_desc;
- dest_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE);
- if (!dest_desc) {
- /* Allocation failure */
-
- return (AE_NO_MEMORY);
- }
+ /*
+ * Dest is a namespace node,
+ * Storing an object into a Name "container"
+ */
+ status = acpi_aml_store_object_to_node (val_desc,
+ (ACPI_NAMESPACE_NODE *) dest_desc, walk_state);
- /* Build a new Reference wrapper around the handle */
+ /* All done, that's it */
- dest_desc->reference.op_code = AML_NAME_OP;
- dest_desc->reference.object = node;
+ return (status);
}
- /* Destination object must be of type Reference */
+ /* Destination object must be an object of type Reference */
if (dest_desc->common.type != INTERNAL_TYPE_REFERENCE) {
/* Destination is not an Reference */
@@ -106,36 +97,130 @@ acpi_aml_exec_store (
return (AE_AML_OPERAND_TYPE);
}
- /* Examine the Reference opcode */
- switch (dest_desc->reference.op_code)
+ /*
+ * Examine the Reference opcode. These cases are handled:
+ *
+ * 1) Store to Name (Change the object associated with a name)
+ * 2) Store to an indexed area of a Buffer or Package
+ * 3) Store to a Method Local or Arg
+ * 4) Store to the debug object
+ * 5) Store to a constant -- a noop
+ */
+
+ switch (ref_desc->reference.op_code)
{
case AML_NAME_OP:
- /*
- * Storing into a Name
- */
- delete_dest_desc = dest_desc;
- status = acpi_aml_store_object_to_node (val_desc, dest_desc->reference.object,
- walk_state);
+ /* Storing an object into a Name "container" */
- break; /* Case Name_op */
+ status = acpi_aml_store_object_to_node (val_desc, ref_desc->reference.object,
+ walk_state);
+ break;
case AML_INDEX_OP:
- delete_dest_desc = dest_desc;
+ /* Storing to an Index (pointer into a packager or buffer) */
+
+ status = acpi_aml_store_object_to_index (val_desc, ref_desc, walk_state);
+ break;
+
+
+ case AML_LOCAL_OP:
+
+ status = acpi_ds_method_data_set_value (MTH_TYPE_LOCAL,
+ (ref_desc->reference.offset), val_desc, walk_state);
+ break;
+
+
+ case AML_ARG_OP:
+
+ status = acpi_ds_method_data_set_value (MTH_TYPE_ARG,
+ (ref_desc->reference.offset), val_desc, walk_state);
+ break;
+
+
+ case AML_DEBUG_OP:
/*
- * Valid source value and destination reference pointer.
+ * Storing to the Debug object causes the value stored to be
+ * displayed and otherwise has no effect -- see ACPI Specification
*
- * ACPI Specification 1.0B section 15.2.3.4.2.13:
- * Destination should point to either a buffer or a package
+ * TBD: print known object types "prettier".
*/
+ break;
+
+
+ case AML_ZERO_OP:
+ case AML_ONE_OP:
+ case AML_ONES_OP:
+
/*
- * Actually, storing to a package is not so simple. The source must be
+ * Storing to a constant is a no-op -- see ACPI Specification
+ * Delete the reference descriptor, however
+ */
+ break;
+
+
+ default:
+
+ /* TBD: [Restructure] use object dump routine !! */
+
+ status = AE_AML_INTERNAL;
+ break;
+
+ } /* switch (Ref_desc->Reference.Op_code) */
+
+
+ /* Always delete the reference descriptor object */
+
+ if (ref_desc) {
+ acpi_cm_remove_reference (ref_desc);
+ }
+
+ return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_aml_store_object_to_index
+ *
+ * PARAMETERS: *Val_desc - Value to be stored
+ * *Node - Named object to recieve the value
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Store the object to the named object.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_store_object_to_index (
+ ACPI_OPERAND_OBJECT *val_desc,
+ ACPI_OPERAND_OBJECT *dest_desc,
+ ACPI_WALK_STATE *walk_state)
+{
+ ACPI_STATUS status = AE_OK;
+ ACPI_OPERAND_OBJECT *obj_desc;
+ u32 length;
+ u32 i;
+ u8 value = 0;
+
+
+ /*
+ * Destination must be a reference pointer, and
+ * must point to either a buffer or a package
+ */
+
+ switch (dest_desc->reference.target_type)
+ {
+ case ACPI_TYPE_PACKAGE:
+ /*
+ * Storing to a package element is not simple. The source must be
* evaluated and converted to the type of the destination and then the
* source is copied into the destination - we can't just point to the
* source object.
@@ -145,8 +230,8 @@ acpi_aml_exec_store (
* The object at *(Dest_desc->Reference.Where) is the
* element within the package that is to be modified.
*/
- tmp_desc = *(dest_desc->reference.where);
- if (tmp_desc) {
+ obj_desc = *(dest_desc->reference.where);
+ if (obj_desc) {
/*
* If the Destination element is a package, we will delete
* that object and construct a new one.
@@ -155,41 +240,39 @@ acpi_aml_exec_store (
* to be packages?
* && (Val_desc->Common.Type == ACPI_TYPE_PACKAGE)
*/
- if (tmp_desc->common.type == ACPI_TYPE_PACKAGE) {
+ if (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
/*
* Take away the reference for being part of a package and
* delete
*/
- acpi_cm_remove_reference (tmp_desc);
- acpi_cm_remove_reference (tmp_desc);
+ acpi_cm_remove_reference (obj_desc);
+ acpi_cm_remove_reference (obj_desc);
- tmp_desc = NULL;
+ obj_desc = NULL;
}
}
- if (!tmp_desc) {
+ if (!obj_desc) {
/*
- * If the Tmp_desc is NULL, that means an uninitialized package
- * has been used as a destination, therefore, we must create
- * the destination element to match the type of the source
- * element NOTE: Val_desc can be of any type.
+ * If the Obj_desc is NULL, it means that an uninitialized package
+ * element has been used as a destination (this is OK), therefore,
+ * we must create the destination element to match the type of the
+ * source element NOTE: Val_desc can be of any type.
*/
- tmp_desc = acpi_cm_create_internal_object (val_desc->common.type);
- if (!tmp_desc) {
- status = AE_NO_MEMORY;
- goto cleanup;
+ obj_desc = acpi_cm_create_internal_object (val_desc->common.type);
+ if (!obj_desc) {
+ return (AE_NO_MEMORY);
}
/*
* If the source is a package, copy the source to the new dest
*/
- if (ACPI_TYPE_PACKAGE == tmp_desc->common.type) {
+ if (ACPI_TYPE_PACKAGE == obj_desc->common.type) {
status = acpi_aml_build_copy_internal_package_object (
- val_desc, tmp_desc, walk_state);
+ val_desc, obj_desc, walk_state);
if (ACPI_FAILURE (status)) {
- acpi_cm_remove_reference (tmp_desc);
- tmp_desc = NULL;
- goto cleanup;
+ acpi_cm_remove_reference (obj_desc);
+ return (status);
}
}
@@ -199,38 +282,31 @@ acpi_aml_exec_store (
* part of the parent package
*/
- *(dest_desc->reference.where) = tmp_desc;
- acpi_cm_add_reference (tmp_desc);
+ *(dest_desc->reference.where) = obj_desc;
+ acpi_cm_add_reference (obj_desc);
}
- if (ACPI_TYPE_PACKAGE != tmp_desc->common.type) {
+ if (ACPI_TYPE_PACKAGE != obj_desc->common.type) {
/*
* The destination element is not a package, so we need to
* convert the contents of the source (Val_desc) and copy into
- * the destination (Tmp_desc)
+ * the destination (Obj_desc)
*/
- status = acpi_aml_store_object_to_object (val_desc, tmp_desc,
+ status = acpi_aml_store_object_to_object (val_desc, obj_desc,
walk_state);
if (ACPI_FAILURE (status)) {
/*
* An error occurrered when copying the internal object
* so delete the reference.
*/
- status = AE_AML_OPERAND_TYPE;
+ return (AE_AML_OPERAND_TYPE);
}
}
-
- break;
}
+ break;
- /*
- * Check that the destination is a Buffer Field type
- */
- if (dest_desc->reference.target_type != ACPI_TYPE_BUFFER_FIELD) {
- status = AE_AML_OPERAND_TYPE;
- break;
- }
+ case ACPI_TYPE_BUFFER_FIELD:
/*
* Storing into a buffer at a location defined by an Index.
*
@@ -239,13 +315,11 @@ acpi_aml_exec_store (
*/
/*
- * Set the Tmp_desc to the destination object and type check.
+ * Set the Obj_desc to the destination object and type check.
*/
- tmp_desc = dest_desc->reference.object;
-
- if (tmp_desc->common.type != ACPI_TYPE_BUFFER) {
- status = AE_AML_OPERAND_TYPE;
- break;
+ obj_desc = dest_desc->reference.object;
+ if (obj_desc->common.type != ACPI_TYPE_BUFFER) {
+ return (AE_AML_OPERAND_TYPE);
}
/*
@@ -256,15 +330,15 @@ acpi_aml_exec_store (
switch (val_desc->common.type)
{
/*
- * If the type is Integer, the Length is 4.
+ * If the type is Integer, assign bytewise
* This loop to assign each of the elements is somewhat
- * backward because of the Big Endian-ness of IA-64
+ * backward because of the Big Endian-ness of IA-64
*/
- case ACPI_TYPE_NUMBER:
- length = 4;
+ case ACPI_TYPE_INTEGER:
+ length = sizeof (ACPI_INTEGER);
for (i = length; i != 0; i--) {
- value = (u8)(val_desc->number.value >> (MUL_8 (i - 1)));
- tmp_desc->buffer.pointer[dest_desc->reference.offset] = value;
+ value = (u8)(val_desc->integer.value >> (MUL_8 (i - 1)));
+ obj_desc->buffer.pointer[dest_desc->reference.offset] = value;
}
break;
@@ -276,7 +350,7 @@ acpi_aml_exec_store (
length = val_desc->buffer.length;
for (i = 0; i < length; i++) {
value = *(val_desc->buffer.pointer + i);
- tmp_desc->buffer.pointer[dest_desc->reference.offset] = value;
+ obj_desc->buffer.pointer[dest_desc->reference.offset] = value;
}
break;
@@ -288,7 +362,7 @@ acpi_aml_exec_store (
length = val_desc->string.length;
for (i = 0; i < length; i++) {
value = *(val_desc->string.pointer + i);
- tmp_desc->buffer.pointer[dest_desc->reference.offset] = value;
+ obj_desc->buffer.pointer[dest_desc->reference.offset] = value;
}
break;
@@ -299,80 +373,207 @@ acpi_aml_exec_store (
status = AE_AML_OPERAND_TYPE;
break;
}
+ break;
- /*
- * If we had an error, break out of this case statement.
- */
- if (ACPI_FAILURE (status)) {
- break;
- }
-
- /*
- * Set the return pointer
- */
- dest_desc = tmp_desc;
+ default:
+ status = AE_AML_OPERAND_TYPE;
break;
+ }
- case AML_ZERO_OP:
- case AML_ONE_OP:
- case AML_ONES_OP:
- /*
- * Storing to a constant is a no-op -- see ACPI Specification
- * Delete the result descriptor.
- */
+ return (status);
+}
- delete_dest_desc = dest_desc;
- break;
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_aml_store_object_to_node
+ *
+ * PARAMETERS: *Source_desc - Value to be stored
+ * *Node - Named object to recieve the value
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Store the object to the named object.
+ *
+ * The Assignment of an object to a named object is handled here
+ * The val passed in will replace the current value (if any)
+ * with the input value.
+ *
+ * When storing into an object the data is converted to the
+ * target object type then stored in the object. This means
+ * that the target object type (for an initialized target) will
+ * not be changed by a store operation.
+ *
+ * NOTE: the global lock is acquired early. This will result
+ * in the global lock being held a bit longer. Also, if the
+ * function fails during set up we may get the lock when we
+ * don't really need it. I don't think we care.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_store_object_to_node (
+ ACPI_OPERAND_OBJECT *source_desc,
+ ACPI_NAMESPACE_NODE *node,
+ ACPI_WALK_STATE *walk_state)
+{
+ ACPI_STATUS status = AE_OK;
+ ACPI_OPERAND_OBJECT *target_desc;
+ OBJECT_TYPE_INTERNAL target_type = ACPI_TYPE_ANY;
- case AML_LOCAL_OP:
+ /*
+ * Assuming the parameters were already validated
+ */
+ ACPI_ASSERT((node) && (source_desc));
- status = acpi_ds_method_data_set_value (MTH_TYPE_LOCAL,
- (dest_desc->reference.offset), val_desc, walk_state);
- delete_dest_desc = dest_desc;
- break;
+ /*
+ * Get current type of the node, and object attached to Node
+ */
+ target_type = acpi_ns_get_type (node);
+ target_desc = acpi_ns_get_attached_object (node);
- case AML_ARG_OP:
- status = acpi_ds_method_data_set_value (MTH_TYPE_ARG,
- (dest_desc->reference.offset), val_desc, walk_state);
- delete_dest_desc = dest_desc;
+ /*
+ * Resolve the source object to an actual value
+ * (If it is a reference object)
+ */
+ status = acpi_aml_resolve_object (&source_desc, target_type, walk_state);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+
+ /*
+ * Do the actual store operation
+ */
+ switch (target_type)
+ {
+ case INTERNAL_TYPE_DEF_FIELD:
+
+ /* Raw data copy for target types Integer/String/Buffer */
+
+ status = acpi_aml_copy_data_to_named_field (source_desc, node);
break;
- case AML_DEBUG_OP:
+ case ACPI_TYPE_INTEGER:
+ case ACPI_TYPE_STRING:
+ case ACPI_TYPE_BUFFER:
+ case INTERNAL_TYPE_BANK_FIELD:
+ case INTERNAL_TYPE_INDEX_FIELD:
+ case ACPI_TYPE_FIELD_UNIT:
/*
- * Storing to the Debug object causes the value stored to be
- * displayed and otherwise has no effect -- see ACPI Specification
+ * These target types are all of type Integer/String/Buffer, and
+ * therefore support implicit conversion before the store.
+ *
+ * Copy and/or convert the source object to a new target object
*/
+ status = acpi_aml_store_object (source_desc, target_type, &target_desc, walk_state);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
- delete_dest_desc = dest_desc;
+ /*
+ * Store the new Target_desc as the new value of the Name, and set
+ * the Name's type to that of the value being stored in it.
+ * Source_desc reference count is incremented by Attach_object.
+ */
+ status = acpi_ns_attach_object (node, target_desc, target_type);
break;
default:
- /* TBD: [Restructure] use object dump routine !! */
+ /* No conversions for all other types. Just attach the source object */
- delete_dest_desc = dest_desc;
- status = AE_AML_INTERNAL;
+ status = acpi_ns_attach_object (node, source_desc, source_desc->common.type);
- } /* switch(Dest_desc->Reference.Op_code) */
+ break;
+ }
-cleanup:
+ return (status);
+}
- /* Cleanup and exit*/
- if (delete_dest_desc) {
- acpi_cm_remove_reference (delete_dest_desc);
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_aml_store_object_to_object
+ *
+ * PARAMETERS: *Source_desc - Value to be stored
+ * *Dest_desc - Object to receive the value
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Store an object to another object.
+ *
+ * The Assignment of an object to another (not named) object
+ * is handled here.
+ * The val passed in will replace the current value (if any)
+ * with the input value.
+ *
+ * When storing into an object the data is converted to the
+ * target object type then stored in the object. This means
+ * that the target object type (for an initialized target) will
+ * not be changed by a store operation.
+ *
+ * This module allows destination types of Number, String,
+ * and Buffer.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_store_object_to_object (
+ ACPI_OPERAND_OBJECT *source_desc,
+ ACPI_OPERAND_OBJECT *dest_desc,
+ ACPI_WALK_STATE *walk_state)
+{
+ ACPI_STATUS status = AE_OK;
+ OBJECT_TYPE_INTERNAL destination_type = dest_desc->common.type;
+
+
+ /*
+ * Assuming the parameters are valid!
+ */
+ ACPI_ASSERT((dest_desc) && (source_desc));
+
+
+ /*
+ * From this interface, we only support Integers/Strings/Buffers
+ */
+ switch (destination_type)
+ {
+ case ACPI_TYPE_INTEGER:
+ case ACPI_TYPE_STRING:
+ case ACPI_TYPE_BUFFER:
+ break;
+
+ default:
+ return (AE_NOT_IMPLEMENTED);
}
+
+ /*
+ * Resolve the source object to an actual value
+ * (If it is a reference object)
+ */
+ status = acpi_aml_resolve_object (&source_desc, destination_type, walk_state);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+
+ /*
+ * Copy and/or convert the source object to the destination object
+ */
+ status = acpi_aml_store_object (source_desc, destination_type, &dest_desc, walk_state);
+
+
return (status);
}
-
diff --git a/drivers/acpi/interpreter/amstoren.c b/drivers/acpi/interpreter/amstoren.c
index 91b2095c5..eb62ed2f1 100644
--- a/drivers/acpi/interpreter/amstoren.c
+++ b/drivers/acpi/interpreter/amstoren.c
@@ -2,13 +2,13 @@
/******************************************************************************
*
* Module Name: amstoren - AML Interpreter object store support,
- * Store to Node (namespace object)
- * $Revision: 24 $
+ * Store to Node (namespace object)
+ * $Revision: 28 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -41,127 +41,72 @@
/*******************************************************************************
*
- * FUNCTION: Acpi_aml_store_object_to_node
+ * FUNCTION: Acpi_aml_resolve_object
*
- * PARAMETERS: *Val_desc - Value to be stored
- * *Node - Named object to recieve the value
+ * PARAMETERS: Source_desc_ptr - Pointer to the source object
+ * Target_type - Current type of the target
+ * Walk_state - Current walk state
*
- * RETURN: Status
- *
- * DESCRIPTION: Store the object to the named object.
- *
- * The Assignment of an object to a named object is handled here
- * The val passed in will replace the current value (if any)
- * with the input value.
+ * RETURN: Status, resolved object in Source_desc_ptr.
*
- * When storing into an object the data is converted to the
- * target object type then stored in the object. This means
- * that the target object type (for an initialized target) will
- * not be changed by a store operation.
- *
- * NOTE: the global lock is acquired early. This will result
- * in the global lock being held a bit longer. Also, if the
- * function fails during set up we may get the lock when we
- * don't really need it. I don't think we care.
+ * DESCRIPTION: Resolve an object. If the object is a reference, dereference
+ * it and return the actual object in the Source_desc_ptr.
*
******************************************************************************/
ACPI_STATUS
-acpi_aml_store_object_to_node (
- ACPI_OPERAND_OBJECT *val_desc,
- ACPI_NAMESPACE_NODE *node,
+acpi_aml_resolve_object (
+ ACPI_OPERAND_OBJECT **source_desc_ptr,
+ OBJECT_TYPE_INTERNAL target_type,
ACPI_WALK_STATE *walk_state)
{
+ ACPI_OPERAND_OBJECT *source_desc = *source_desc_ptr;
ACPI_STATUS status = AE_OK;
- u8 *buffer = NULL;
- u32 length = 0;
- u32 mask;
- u32 new_value;
- u8 locked = FALSE;
- u8 *location=NULL;
- ACPI_OPERAND_OBJECT *dest_desc;
- OBJECT_TYPE_INTERNAL destination_type = ACPI_TYPE_ANY;
/*
- * Assuming the parameters are valid!!!
+ * Ensure we have a Source that can be stored in the target
*/
- ACPI_ASSERT((node) && (val_desc));
+ switch (target_type)
+ {
- destination_type = acpi_ns_get_type (node);
+ /* This case handles the "interchangeable" types Integer, String, and Buffer. */
/*
- * First ensure we have a value that can be stored in the target
+ * These cases all require only Integers or values that
+ * can be converted to Integers (Strings or Buffers)
*/
- switch (destination_type)
- {
- /* Type of Name's existing value */
-
- case INTERNAL_TYPE_ALIAS:
-
- /*
- * Aliases are resolved by Acpi_aml_prep_operands
- */
-
- status = AE_AML_INTERNAL;
- break;
-
-
+ case ACPI_TYPE_INTEGER:
+ case ACPI_TYPE_FIELD_UNIT:
case INTERNAL_TYPE_BANK_FIELD:
case INTERNAL_TYPE_INDEX_FIELD:
- case ACPI_TYPE_FIELD_UNIT:
- case ACPI_TYPE_NUMBER:
-
- /*
- * These cases all require only number values or values that
- * can be converted to numbers.
- *
- * If value is not a Number, try to resolve it to one.
- */
-
- if (val_desc->common.type != ACPI_TYPE_NUMBER) {
- /*
- * Initially not a number, convert
- */
- status = acpi_aml_resolve_to_value (&val_desc, walk_state);
- if (ACPI_SUCCESS (status) &&
- (val_desc->common.type != ACPI_TYPE_NUMBER))
- {
- /*
- * Conversion successful but still not a number
- */
- status = AE_AML_OPERAND_TYPE;
- }
- }
-
- break;
+ /*
+ * Stores into a Field/Region or into a Buffer/String
+ * are all essentially the same.
+ */
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
case INTERNAL_TYPE_DEF_FIELD:
/*
- * Storing into a Field in a region or into a buffer or into
- * a string all is essentially the same.
- *
- * If value is not a valid type, try to resolve it to one.
+ * If Source_desc is not a valid type, try to resolve it to one.
*/
-
- if ((val_desc->common.type != ACPI_TYPE_NUMBER) &&
- (val_desc->common.type != ACPI_TYPE_BUFFER) &&
- (val_desc->common.type != ACPI_TYPE_STRING))
+ if ((source_desc->common.type != ACPI_TYPE_INTEGER) &&
+ (source_desc->common.type != ACPI_TYPE_BUFFER) &&
+ (source_desc->common.type != ACPI_TYPE_STRING))
{
/*
- * Initially not a valid type, convert
+ * Initially not a valid type, convert
*/
- status = acpi_aml_resolve_to_value (&val_desc, walk_state);
+ status = acpi_aml_resolve_to_value (source_desc_ptr, walk_state);
if (ACPI_SUCCESS (status) &&
- (val_desc->common.type != ACPI_TYPE_NUMBER) &&
- (val_desc->common.type != ACPI_TYPE_BUFFER) &&
- (val_desc->common.type != ACPI_TYPE_STRING))
+ (source_desc->common.type != ACPI_TYPE_INTEGER) &&
+ (source_desc->common.type != ACPI_TYPE_BUFFER) &&
+ (source_desc->common.type != ACPI_TYPE_STRING))
{
/*
- * Conversion successful but still not a valid type
+ * Conversion successful but still not a valid type
*/
status = AE_AML_OPERAND_TYPE;
}
@@ -169,347 +114,133 @@ acpi_aml_store_object_to_node (
break;
- case ACPI_TYPE_PACKAGE:
+ case INTERNAL_TYPE_ALIAS:
/*
- * TBD: [Unhandled] Not real sure what to do here
+ * Aliases are resolved by Acpi_aml_prep_operands
*/
- status = AE_NOT_IMPLEMENTED;
+ status = AE_AML_INTERNAL;
break;
+ case ACPI_TYPE_PACKAGE:
default:
/*
- * All other types than Alias and the various Fields come here.
- * Store Val_desc as the new value of the Name, and set
- * the Name's type to that of the value being stored in it.
- * Val_desc reference count is incremented by Attach_object.
+ * All other types than Alias and the various Fields come here,
+ * including the untyped case - ACPI_TYPE_ANY.
*/
-
- status = acpi_ns_attach_object (node, val_desc, val_desc->common.type);
-
- goto clean_up_and_bail_out;
break;
}
- /* Exit now if failure above */
+ return (status);
+}
+
- if (ACPI_FAILURE (status)) {
- goto clean_up_and_bail_out;
- }
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_aml_store_object
+ *
+ * PARAMETERS: Source_desc - Object to store
+ * Target_type - Current type of the target
+ * Target_desc_ptr - Pointer to the target
+ * Walk_state - Current walk state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: "Store" an object to another object. This may include
+ * converting the source type to the target type (implicit
+ * conversion), and a copy of the value of the source to
+ * the target.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_store_object (
+ ACPI_OPERAND_OBJECT *source_desc,
+ OBJECT_TYPE_INTERNAL target_type,
+ ACPI_OPERAND_OBJECT **target_desc_ptr,
+ ACPI_WALK_STATE *walk_state)
+{
+ ACPI_OPERAND_OBJECT *target_desc = *target_desc_ptr;
+ ACPI_STATUS status;
- /*
- * Get descriptor for object attached to Node
- */
- dest_desc = acpi_ns_get_attached_object (node);
- if (!dest_desc) {
- /*
- * There is no existing object attached to this Node
- */
- status = AE_AML_INTERNAL;
- goto clean_up_and_bail_out;
- }
/*
- * Make sure the destination Object is the same as the Node
+ * Perform the "implicit conversion" of the source to the current type
+ * of the target - As per the ACPI specification.
+ *
+ * If no conversion performed, Source_desc is left alone, otherwise it
+ * is updated with a new object.
*/
- if (dest_desc->common.type != (u8) destination_type) {
- status = AE_AML_INTERNAL;
- goto clean_up_and_bail_out;
+ status = acpi_aml_convert_to_target_type (target_type, &source_desc, walk_state);
+ if (ACPI_FAILURE (status)) {
+ return (status);
}
+
/*
- * Acpi_everything is ready to execute now, We have
- * a value we can handle, just perform the update
+ * We now have two objects of identical types, and we can perform a
+ * copy of the *value* of the source object.
*/
-
- switch (destination_type)
+ switch (target_type)
{
- /* Type of Name's existing value */
-
- case INTERNAL_TYPE_BANK_FIELD:
+ case ACPI_TYPE_ANY:
+ case INTERNAL_TYPE_DEF_ANY:
/*
- * Get the global lock if needed
+ * The target namespace node is uninitialized (has no target object),
+ * and will take on the type of the source object
*/
- locked = acpi_aml_acquire_global_lock (dest_desc->bank_field.lock_rule);
-
- /*
- * Set Bank value to select proper Bank
- * Perform the update (Set Bank Select)
- */
-
- status = acpi_aml_access_named_field (ACPI_WRITE,
- dest_desc->bank_field.bank_select,
- &dest_desc->bank_field.value,
- sizeof (dest_desc->bank_field.value));
- if (ACPI_SUCCESS (status)) {
- /* Set bank select successful, set data value */
-
- status = acpi_aml_access_named_field (ACPI_WRITE,
- dest_desc->bank_field.bank_select,
- &val_desc->bank_field.value,
- sizeof (val_desc->bank_field.value));
- }
+ *target_desc_ptr = source_desc;
break;
- case INTERNAL_TYPE_DEF_FIELD:
-
- /*
- * Get the global lock if needed
- */
- locked = acpi_aml_acquire_global_lock (val_desc->field.lock_rule);
-
- /*
- * Perform the update
- */
+ case ACPI_TYPE_INTEGER:
- switch (val_desc->common.type)
- {
- case ACPI_TYPE_NUMBER:
- buffer = (u8 *) &val_desc->number.value;
- length = sizeof (val_desc->number.value);
- break;
-
- case ACPI_TYPE_BUFFER:
- buffer = (u8 *) val_desc->buffer.pointer;
- length = val_desc->buffer.length;
- break;
-
- case ACPI_TYPE_STRING:
- buffer = (u8 *) val_desc->string.pointer;
- length = val_desc->string.length;
- break;
- }
-
- status = acpi_aml_access_named_field (ACPI_WRITE,
- node, buffer, length);
-
- break; /* Global Lock released below */
+ target_desc->integer.value = source_desc->integer.value;
+ /* Truncate value if we are executing from a 32-bit ACPI table */
- case ACPI_TYPE_STRING:
-
- /*
- * Perform the update
- */
-
- switch (val_desc->common.type)
- {
- case ACPI_TYPE_NUMBER:
- buffer = (u8 *) &val_desc->number.value;
- length = sizeof (val_desc->number.value);
- break;
-
- case ACPI_TYPE_BUFFER:
- buffer = (u8 *) val_desc->buffer.pointer;
- length = val_desc->buffer.length;
- break;
-
- case ACPI_TYPE_STRING:
- buffer = (u8 *) val_desc->string.pointer;
- length = val_desc->string.length;
- break;
- }
-
- /*
- * Setting a string value replaces the old string
- */
-
- if (length < dest_desc->string.length) {
- /*
- * Zero fill, not willing to do pointer arithmetic for
- * archetecture independance. Just clear the whole thing
- */
- MEMSET(dest_desc->string.pointer, 0, dest_desc->string.length);
- MEMCPY(dest_desc->string.pointer, buffer, length);
- }
- else {
- /*
- * Free the current buffer, then allocate a buffer
- * large enough to hold the value
- */
- if ( dest_desc->string.pointer &&
- !acpi_tb_system_table_pointer (dest_desc->string.pointer))
- {
- /*
- * Only free if not a pointer into the DSDT
- */
-
- acpi_cm_free(dest_desc->string.pointer);
- }
+ acpi_aml_truncate_for32bit_table (target_desc, walk_state);
+ break;
- dest_desc->string.pointer = acpi_cm_allocate (length + 1);
- dest_desc->string.length = length;
- if (!dest_desc->string.pointer) {
- status = AE_NO_MEMORY;
- goto clean_up_and_bail_out;
- }
+ case ACPI_TYPE_FIELD_UNIT:
- MEMCPY(dest_desc->string.pointer, buffer, length);
- }
+ status = acpi_aml_copy_integer_to_field_unit (source_desc, target_desc);
break;
- case ACPI_TYPE_BUFFER:
-
- /*
- * Perform the update to the buffer
- */
-
- switch (val_desc->common.type)
- {
- case ACPI_TYPE_NUMBER:
- buffer = (u8 *) &val_desc->number.value;
- length = sizeof (val_desc->number.value);
- break;
-
- case ACPI_TYPE_BUFFER:
- buffer = (u8 *) val_desc->buffer.pointer;
- length = val_desc->buffer.length;
- break;
-
- case ACPI_TYPE_STRING:
- buffer = (u8 *) val_desc->string.pointer;
- length = val_desc->string.length;
- break;
- }
+ case INTERNAL_TYPE_BANK_FIELD:
- /*
- * Buffer is a static allocation,
- * only place what will fit in the buffer.
- */
- if (length <= dest_desc->buffer.length) {
- /*
- * Zero fill first, not willing to do pointer arithmetic for
- * archetecture independence. Just clear the whole thing
- */
- MEMSET(dest_desc->buffer.pointer, 0, dest_desc->buffer.length);
- MEMCPY(dest_desc->buffer.pointer, buffer, length);
- }
- else {
- /*
- * truncate, copy only what will fit
- */
- MEMCPY(dest_desc->buffer.pointer, buffer, dest_desc->buffer.length);
- }
+ status = acpi_aml_copy_integer_to_bank_field (source_desc, target_desc);
break;
case INTERNAL_TYPE_INDEX_FIELD:
- /*
- * Get the global lock if needed
- */
- locked = acpi_aml_acquire_global_lock (dest_desc->index_field.lock_rule);
-
- /*
- * Set Index value to select proper Data register
- * perform the update (Set index)
- */
-
- status = acpi_aml_access_named_field (ACPI_WRITE,
- dest_desc->index_field.index,
- &dest_desc->index_field.value,
- sizeof (dest_desc->index_field.value));
-
- if (ACPI_SUCCESS (status)) {
- /* set index successful, next set Data value */
-
- status = acpi_aml_access_named_field (ACPI_WRITE,
- dest_desc->index_field.data,
- &val_desc->number.value,
- sizeof (val_desc->number.value));
- }
+ status = acpi_aml_copy_integer_to_index_field (source_desc, target_desc);
break;
- case ACPI_TYPE_FIELD_UNIT:
-
-
- /*
- * If the Field Buffer and Index have not been previously evaluated,
- * evaluate them and save the results.
- */
- if (!(dest_desc->common.flags & AOPOBJ_DATA_VALID)) {
- status = acpi_ds_get_field_unit_arguments (dest_desc);
- if (ACPI_FAILURE (status)) {
- return (status);
- }
- }
-
- if ((!dest_desc->field_unit.container ||
- ACPI_TYPE_BUFFER != dest_desc->field_unit.container->common.type))
- {
- status = AE_AML_INTERNAL;
- goto clean_up_and_bail_out;
- }
-
- /*
- * Get the global lock if needed
- */
- locked = acpi_aml_acquire_global_lock (dest_desc->field_unit.lock_rule);
-
- /*
- * TBD: [Unhandled] REMOVE this limitation
- * Make sure the operation is within the limits of our implementation
- * this is not a Spec limitation!!
- */
- if (dest_desc->field_unit.length + dest_desc->field_unit.bit_offset > 32) {
- status = AE_NOT_IMPLEMENTED;
- goto clean_up_and_bail_out;
- }
-
- /* Field location is (base of buffer) + (byte offset) */
-
- location = dest_desc->field_unit.container->buffer.pointer
- + dest_desc->field_unit.offset;
-
- /*
- * Construct Mask with 1 bits where the field is,
- * 0 bits elsewhere
- */
- mask = ((u32) 1 << dest_desc->field_unit.length) - ((u32)1
- << dest_desc->field_unit.bit_offset);
-
- /* Zero out the field in the buffer */
-
- MOVE_UNALIGNED32_TO_32 (&new_value, location);
- new_value &= ~mask;
-
- /*
- * Shift and mask the new value into position,
- * and or it into the buffer.
- */
- new_value |= (val_desc->number.value << dest_desc->field_unit.bit_offset) &
- mask;
-
- /* Store back the value */
-
- MOVE_UNALIGNED32_TO_32 (location, &new_value);
+ case ACPI_TYPE_STRING:
+ status = acpi_aml_copy_string_to_string (source_desc, target_desc);
break;
- case ACPI_TYPE_NUMBER:
-
-
- dest_desc->number.value = val_desc->number.value;
-
- /* Truncate value if we are executing from a 32-bit ACPI table */
+ case ACPI_TYPE_BUFFER:
- acpi_aml_truncate_for32bit_table (dest_desc, walk_state);
+ status = acpi_aml_copy_buffer_to_buffer (source_desc, target_desc);
break;
case ACPI_TYPE_PACKAGE:
/*
- * TBD: [Unhandled] Not real sure what to do here
+ * TBD: [Unhandled] Not real sure what to do here
*/
status = AE_NOT_IMPLEMENTED;
break;
@@ -518,24 +249,13 @@ acpi_aml_store_object_to_node (
default:
/*
- * All other types than Alias and the various Fields come here.
- * Store Val_desc as the new value of the Name, and set
- * the Name's type to that of the value being stored in it.
- * Val_desc reference count is incremented by Attach_object.
+ * All other types come here.
*/
-
status = AE_NOT_IMPLEMENTED;
break;
}
-clean_up_and_bail_out:
-
- /*
- * Release global lock if we acquired it earlier
- */
- acpi_aml_release_global_lock (locked);
-
return (status);
}
diff --git a/drivers/acpi/interpreter/amstorob.c b/drivers/acpi/interpreter/amstorob.c
index f3a098bd2..8118f08bd 100644
--- a/drivers/acpi/interpreter/amstorob.c
+++ b/drivers/acpi/interpreter/amstorob.c
@@ -2,12 +2,12 @@
/******************************************************************************
*
* Module Name: amstorob - AML Interpreter object store support, store to object
- * $Revision: 18 $
+ * $Revision: 22 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -40,281 +40,383 @@
/*******************************************************************************
*
- * FUNCTION: Acpi_aml_store_object_to_object
+ * FUNCTION: Acpi_aml_copy_buffer_to_buffer
*
- * PARAMETERS: *Val_desc - Value to be stored
- * *Dest_desc - Object to receive the value
+ * PARAMETERS: Source_desc - Source object to copy
+ * Target_desc - Destination object of the copy
*
* RETURN: Status
*
- * DESCRIPTION: Store an object to another object.
+ * DESCRIPTION: Copy a buffer object to another buffer object.
*
- * The Assignment of an object to another (not named) object
- * is handled here.
- * The val passed in will replace the current value (if any)
- * with the input value.
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_copy_buffer_to_buffer (
+ ACPI_OPERAND_OBJECT *source_desc,
+ ACPI_OPERAND_OBJECT *target_desc)
+{
+ u32 length;
+ u8 *buffer;
+
+ /*
+ * We know that Source_desc is a buffer by now
+ */
+ buffer = (u8 *) source_desc->buffer.pointer;
+ length = source_desc->buffer.length;
+
+ /*
+ * Buffer is a static allocation,
+ * only place what will fit in the buffer.
+ */
+ if (length <= target_desc->buffer.length) {
+ /* Clear existing buffer and copy in the new one */
+
+ MEMSET(target_desc->buffer.pointer, 0, target_desc->buffer.length);
+ MEMCPY(target_desc->buffer.pointer, buffer, length);
+ }
+
+ else {
+ /*
+ * Truncate the source, copy only what will fit
+ */
+ MEMCPY(target_desc->buffer.pointer, buffer, target_desc->buffer.length);
+
+ }
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
*
- * When storing into an object the data is converted to the
- * target object type then stored in the object. This means
- * that the target object type (for an initialized target) will
- * not be changed by a store operation.
+ * FUNCTION: Acpi_aml_copy_string_to_string
+ *
+ * PARAMETERS: Source_desc - Source object to copy
+ * Target_desc - Destination object of the copy
+ *
+ * RETURN: Status
*
- * This module allows destination types of Number, String,
- * and Buffer.
+ * DESCRIPTION: Copy a String object to another String object
*
******************************************************************************/
ACPI_STATUS
-acpi_aml_store_object_to_object (
- ACPI_OPERAND_OBJECT *val_desc,
- ACPI_OPERAND_OBJECT *dest_desc,
- ACPI_WALK_STATE *walk_state)
+acpi_aml_copy_string_to_string (
+ ACPI_OPERAND_OBJECT *source_desc,
+ ACPI_OPERAND_OBJECT *target_desc)
{
- ACPI_STATUS status = AE_OK;
- u8 *buffer = NULL;
- u32 length = 0;
- OBJECT_TYPE_INTERNAL destination_type = dest_desc->common.type;
+ u32 length;
+ u8 *buffer;
/*
- * Assuming the parameters are valid!!!
+ * We know that Source_desc is a string by now.
*/
- ACPI_ASSERT((dest_desc) && (val_desc));
+ buffer = (u8 *) source_desc->string.pointer;
+ length = source_desc->string.length;
/*
- * First ensure we have a value that can be stored in the target
+ * Setting a string value replaces the old string
*/
- switch (destination_type)
- {
- /* Type of Name's existing value */
+ if (length < target_desc->string.length) {
+ /* Clear old string and copy in the new one */
- case ACPI_TYPE_NUMBER:
+ MEMSET(target_desc->string.pointer, 0, target_desc->string.length);
+ MEMCPY(target_desc->string.pointer, buffer, length);
+ }
+ else {
/*
- * These cases all require only number values or values that
- * can be converted to numbers.
- *
- * If value is not a Number, try to resolve it to one.
+ * Free the current buffer, then allocate a buffer
+ * large enough to hold the value
*/
-
- if (val_desc->common.type != ACPI_TYPE_NUMBER) {
+ if (target_desc->string.pointer &&
+ !acpi_tb_system_table_pointer (target_desc->string.pointer))
+ {
/*
- * Initially not a number, convert
+ * Only free if not a pointer into the DSDT
*/
- status = acpi_aml_resolve_to_value (&val_desc, walk_state);
- if (ACPI_SUCCESS (status) &&
- (val_desc->common.type != ACPI_TYPE_NUMBER))
- {
- /*
- * Conversion successful but still not a number
- */
- status = AE_AML_OPERAND_TYPE;
- }
+ acpi_cm_free(target_desc->string.pointer);
}
- break;
+ target_desc->string.pointer = acpi_cm_allocate (length + 1);
+ target_desc->string.length = length;
- case ACPI_TYPE_STRING:
- case ACPI_TYPE_BUFFER:
+ if (!target_desc->string.pointer) {
+ return (AE_NO_MEMORY);
+ }
- /*
- * Storing into a Field in a region or into a buffer or into
- * a string all is essentially the same.
- *
- * If value is not a valid type, try to resolve it to one.
- */
+ MEMCPY(target_desc->string.pointer, buffer, length);
+ }
- if ((val_desc->common.type != ACPI_TYPE_NUMBER) &&
- (val_desc->common.type != ACPI_TYPE_BUFFER) &&
- (val_desc->common.type != ACPI_TYPE_STRING))
- {
- /*
- * Initially not a valid type, convert
- */
- status = acpi_aml_resolve_to_value (&val_desc, walk_state);
- if (ACPI_SUCCESS (status) &&
- (val_desc->common.type != ACPI_TYPE_NUMBER) &&
- (val_desc->common.type != ACPI_TYPE_BUFFER) &&
- (val_desc->common.type != ACPI_TYPE_STRING))
- {
- /*
- * Conversion successful but still not a valid type
- */
- status = AE_AML_OPERAND_TYPE;
- }
- }
- break;
+ return (AE_OK);
+}
- default:
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_aml_copy_integer_to_index_field
+ *
+ * PARAMETERS: Source_desc - Source object to copy
+ * Target_desc - Destination object of the copy
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Write an Integer to an Index Field
+ *
+ ******************************************************************************/
- /*
- * TBD: [Unhandled] What other combinations must be implemented?
- */
- status = AE_NOT_IMPLEMENTED;
- break;
- }
+ACPI_STATUS
+acpi_aml_copy_integer_to_index_field (
+ ACPI_OPERAND_OBJECT *source_desc,
+ ACPI_OPERAND_OBJECT *target_desc)
+{
+ ACPI_STATUS status;
+ u8 locked;
+
+
+ /*
+ * Get the global lock if needed
+ */
+ locked = acpi_aml_acquire_global_lock (target_desc->index_field.lock_rule);
- /* Exit now if failure above */
+ /*
+ * Set Index value to select proper Data register
+ * perform the update (Set index)
+ */
+ status = acpi_aml_access_named_field (ACPI_WRITE,
+ target_desc->index_field.index,
+ &target_desc->index_field.value,
+ sizeof (target_desc->index_field.value));
+ if (ACPI_SUCCESS (status)) {
+ /* Set_index was successful, next set Data value */
+
+ status = acpi_aml_access_named_field (ACPI_WRITE,
+ target_desc->index_field.data,
+ &source_desc->integer.value,
+ sizeof (source_desc->integer.value));
- if (ACPI_FAILURE (status)) {
- goto clean_up_and_bail_out;
}
+
+
/*
- * Acpi_everything is ready to execute now, We have
- * a value we can handle, just perform the update
+ * Release global lock if we acquired it earlier
*/
+ acpi_aml_release_global_lock (locked);
- switch (destination_type)
- {
+ return (status);
+}
- case ACPI_TYPE_STRING:
- /*
- * Perform the update
- */
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_aml_copy_integer_to_bank_field
+ *
+ * PARAMETERS: Source_desc - Source object to copy
+ * Target_desc - Destination object of the copy
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Write an Integer to a Bank Field
+ *
+ ******************************************************************************/
- switch (val_desc->common.type)
- {
- case ACPI_TYPE_NUMBER:
- buffer = (u8 *) &val_desc->number.value;
- length = sizeof (val_desc->number.value);
- break;
-
- case ACPI_TYPE_BUFFER:
- buffer = (u8 *) val_desc->buffer.pointer;
- length = val_desc->buffer.length;
- break;
-
- case ACPI_TYPE_STRING:
- buffer = (u8 *) val_desc->string.pointer;
- length = val_desc->string.length;
- break;
- }
+ACPI_STATUS
+acpi_aml_copy_integer_to_bank_field (
+ ACPI_OPERAND_OBJECT *source_desc,
+ ACPI_OPERAND_OBJECT *target_desc)
+{
+ ACPI_STATUS status;
+ u8 locked;
- /*
- * Setting a string value replaces the old string
- */
- if (length < dest_desc->string.length) {
- /*
- * Zero fill, not willing to do pointer arithmetic for
- * architecture independence. Just clear the whole thing
- */
- MEMSET(dest_desc->string.pointer, 0, dest_desc->string.length);
- MEMCPY(dest_desc->string.pointer, buffer, length);
- }
- else {
- /*
- * Free the current buffer, then allocate a buffer
- * large enough to hold the value
- */
- if ( dest_desc->string.pointer &&
- !acpi_tb_system_table_pointer (dest_desc->string.pointer))
- {
- /*
- * Only free if not a pointer into the DSDT
- */
+ /*
+ * Get the global lock if needed
+ */
+ locked = acpi_aml_acquire_global_lock (target_desc->index_field.lock_rule);
- acpi_cm_free(dest_desc->string.pointer);
- }
- dest_desc->string.pointer = acpi_cm_allocate (length + 1);
- dest_desc->string.length = length;
+ /*
+ * Set Bank value to select proper Bank
+ * Perform the update (Set Bank Select)
+ */
- if (!dest_desc->string.pointer) {
- status = AE_NO_MEMORY;
- goto clean_up_and_bail_out;
- }
+ status = acpi_aml_access_named_field (ACPI_WRITE,
+ target_desc->bank_field.bank_select,
+ &target_desc->bank_field.value,
+ sizeof (target_desc->bank_field.value));
+ if (ACPI_SUCCESS (status)) {
+ /* Set bank select successful, set data value */
+
+ status = acpi_aml_access_named_field (ACPI_WRITE,
+ target_desc->bank_field.bank_select,
+ &source_desc->bank_field.value,
+ sizeof (source_desc->bank_field.value));
+ }
- MEMCPY(dest_desc->string.pointer, buffer, length);
- }
- break;
- case ACPI_TYPE_BUFFER:
+ /*
+ * Release global lock if we acquired it earlier
+ */
+ acpi_aml_release_global_lock (locked);
- /*
- * Perform the update to the buffer
- */
+ return (status);
+}
- switch (val_desc->common.type)
- {
- case ACPI_TYPE_NUMBER:
- buffer = (u8 *) &val_desc->number.value;
- length = sizeof (val_desc->number.value);
- break;
-
- case ACPI_TYPE_BUFFER:
- buffer = (u8 *) val_desc->buffer.pointer;
- length = val_desc->buffer.length;
- break;
-
- case ACPI_TYPE_STRING:
- buffer = (u8 *) val_desc->string.pointer;
- length = val_desc->string.length;
- break;
- }
- /*
- * If the buffer is uninitialized,
- * memory needs to be allocated for the copy.
- */
- if(0 == dest_desc->buffer.length) {
- dest_desc->buffer.pointer = acpi_cm_callocate(length);
- dest_desc->buffer.length = length;
-
- if (!dest_desc->buffer.pointer) {
- status = AE_NO_MEMORY;
- goto clean_up_and_bail_out;
- }
- }
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_aml_copy_data_to_named_field
+ *
+ * PARAMETERS: Source_desc - Source object to copy
+ * Node - Destination Namespace node
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Copy raw data to a Named Field. No implicit conversion
+ * is performed on the source object
+ *
+ ******************************************************************************/
- /*
- * Buffer is a static allocation,
- * only place what will fit in the buffer.
- */
- if (length <= dest_desc->buffer.length) {
- /*
- * Zero fill first, not willing to do pointer arithmetic for
- * architecture independence. Just clear the whole thing
- */
- MEMSET(dest_desc->buffer.pointer, 0, dest_desc->buffer.length);
- MEMCPY(dest_desc->buffer.pointer, buffer, length);
- }
- else {
- /*
- * truncate, copy only what will fit
- */
- MEMCPY(dest_desc->buffer.pointer, buffer, dest_desc->buffer.length);
- }
- break;
+ACPI_STATUS
+acpi_aml_copy_data_to_named_field (
+ ACPI_OPERAND_OBJECT *source_desc,
+ ACPI_NAMESPACE_NODE *node)
+{
+ ACPI_STATUS status;
+ u8 locked;
+ u32 length;
+ u8 *buffer;
- case ACPI_TYPE_NUMBER:
- dest_desc->number.value = val_desc->number.value;
+ /*
+ * Named fields (Create_xxx_field) - We don't perform any conversions on the
+ * source operand, just use the raw data
+ */
+ switch (source_desc->common.type)
+ {
+ case ACPI_TYPE_INTEGER:
+ buffer = (u8 *) &source_desc->integer.value;
+ length = sizeof (source_desc->integer.value);
+ break;
- /* Truncate value if we are executing from a 32-bit ACPI table */
+ case ACPI_TYPE_BUFFER:
+ buffer = (u8 *) source_desc->buffer.pointer;
+ length = source_desc->buffer.length;
+ break;
- acpi_aml_truncate_for32bit_table (dest_desc, walk_state);
+ case ACPI_TYPE_STRING:
+ buffer = (u8 *) source_desc->string.pointer;
+ length = source_desc->string.length;
break;
default:
+ return (AE_TYPE);
+ }
- /*
- * All other types than Alias and the various Fields come here.
- * Store Val_desc as the new value of the Name, and set
- * the Name's type to that of the value being stored in it.
- * Val_desc reference count is incremented by Attach_object.
- */
+ /*
+ * Get the global lock if needed before the update
+ * TBD: not needed!
+ */
+ locked = acpi_aml_acquire_global_lock (source_desc->field.lock_rule);
- status = AE_NOT_IMPLEMENTED;
- break;
- }
+ status = acpi_aml_access_named_field (ACPI_WRITE,
+ node, buffer, length);
-clean_up_and_bail_out:
+ acpi_aml_release_global_lock (locked);
return (status);
}
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_aml_copy_integer_to_field_unit
+ *
+ * PARAMETERS: Source_desc - Source object to copy
+ * Target_desc - Destination object of the copy
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Write an Integer to a Field Unit.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_copy_integer_to_field_unit (
+ ACPI_OPERAND_OBJECT *source_desc,
+ ACPI_OPERAND_OBJECT *target_desc)
+{
+ ACPI_STATUS status = AE_OK;
+ u8 *location = NULL;
+ u32 mask;
+ u32 new_value;
+ u8 locked = FALSE;
+
+
+ /*
+ * If the Field Buffer and Index have not been previously evaluated,
+ * evaluate them and save the results.
+ */
+ if (!(target_desc->common.flags & AOPOBJ_DATA_VALID)) {
+ status = acpi_ds_get_field_unit_arguments (target_desc);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+ }
+
+ if ((!target_desc->field_unit.container ||
+ ACPI_TYPE_BUFFER != target_desc->field_unit.container->common.type))
+ {
+ return (AE_AML_INTERNAL);
+ }
+
+ /*
+ * Get the global lock if needed
+ */
+ locked = acpi_aml_acquire_global_lock (target_desc->field_unit.lock_rule);
+
+ /*
+ * TBD: [Unhandled] REMOVE this limitation
+ * Make sure the operation is within the limits of our implementation
+ * this is not a Spec limitation!!
+ */
+ if (target_desc->field_unit.length + target_desc->field_unit.bit_offset > 32) {
+ return (AE_NOT_IMPLEMENTED);
+ }
+
+ /* Field location is (base of buffer) + (byte offset) */
+
+ location = target_desc->field_unit.container->buffer.pointer
+ + target_desc->field_unit.offset;
+
+ /*
+ * Construct Mask with 1 bits where the field is,
+ * 0 bits elsewhere
+ */
+ mask = ((u32) 1 << target_desc->field_unit.length) - ((u32)1
+ << target_desc->field_unit.bit_offset);
+
+ /* Zero out the field in the buffer */
+
+ MOVE_UNALIGNED32_TO_32 (&new_value, location);
+ new_value &= ~mask;
+
+ /*
+ * Shift and mask the new value into position,
+ * and or it into the buffer.
+ */
+ new_value |= (source_desc->integer.value << target_desc->field_unit.bit_offset) &
+ mask;
+
+ /* Store back the value */
+
+ MOVE_UNALIGNED32_TO_32 (location, &new_value);
+
+ return (AE_OK);
+}
+
+
diff --git a/drivers/acpi/interpreter/amsystem.c b/drivers/acpi/interpreter/amsystem.c
index 9ad72c161..5e60538af 100644
--- a/drivers/acpi/interpreter/amsystem.c
+++ b/drivers/acpi/interpreter/amsystem.c
@@ -2,12 +2,12 @@
/******************************************************************************
*
* Module Name: amsystem - Interface to OS services
- * $Revision: 52 $
+ * $Revision: 54 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -202,7 +202,7 @@ acpi_aml_system_acquire_mutex (
}
status = acpi_aml_system_wait_semaphore (obj_desc->mutex.semaphore,
- (u32) time_desc->number.value);
+ (u32) time_desc->integer.value);
return (status);
}
@@ -299,7 +299,7 @@ acpi_aml_system_wait_event (
if (obj_desc) {
status = acpi_aml_system_wait_semaphore (obj_desc->event.semaphore,
- (u32) time_desc->number.value);
+ (u32) time_desc->integer.value);
}
diff --git a/drivers/acpi/interpreter/amutils.c b/drivers/acpi/interpreter/amutils.c
index 4e1359888..e3456099c 100644
--- a/drivers/acpi/interpreter/amutils.c
+++ b/drivers/acpi/interpreter/amutils.c
@@ -2,12 +2,12 @@
/******************************************************************************
*
* Module Name: amutils - interpreter/scanner utilities
- * $Revision: 66 $
+ * $Revision: 68 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -46,14 +46,11 @@ typedef struct internal_search_st
/* Used to traverse nested packages when copying*/
+/* TBD: This must be removed! */
INTERNAL_PKG_SEARCH_INFO copy_level[MAX_PACKAGE_DEPTH];
-static NATIVE_CHAR hex[] =
- {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
-
-
/*******************************************************************************
*
* FUNCTION: Acpi_aml_enter_interpreter
@@ -156,7 +153,7 @@ acpi_aml_truncate_for32bit_table (
*/
if ((!obj_desc) ||
- (obj_desc->common.type != ACPI_TYPE_NUMBER) ||
+ (obj_desc->common.type != ACPI_TYPE_INTEGER) ||
(!walk_state->method_node))
{
return;
@@ -167,7 +164,7 @@ acpi_aml_truncate_for32bit_table (
* We are running a method that exists in a 32-bit ACPI table.
* Truncate the value to 32 bits by zeroing out the upper 32-bit field
*/
- obj_desc->number.value &= (ACPI_INTEGER) ACPI_UINT32_MAX;
+ obj_desc->integer.value &= (ACPI_INTEGER) ACPI_UINT32_MAX;
}
}
@@ -343,10 +340,10 @@ acpi_aml_eisa_id_to_string (
out_string[0] = (char) ('@' + ((id >> 26) & 0x1f));
out_string[1] = (char) ('@' + ((id >> 21) & 0x1f));
out_string[2] = (char) ('@' + ((id >> 16) & 0x1f));
- out_string[3] = hex[(id >> 12) & 0xf];
- out_string[4] = hex[(id >> 8) & 0xf];
- out_string[5] = hex[(id >> 4) & 0xf];
- out_string[6] = hex[id & 0xf];
+ out_string[3] = acpi_gbl_hex_to_ascii[(id >> 12) & 0xf];
+ out_string[4] = acpi_gbl_hex_to_ascii[(id >> 8) & 0xf];
+ out_string[5] = acpi_gbl_hex_to_ascii[(id >> 4) & 0xf];
+ out_string[6] = acpi_gbl_hex_to_ascii[id & 0xf];
out_string[7] = 0;
return (AE_OK);
diff --git a/drivers/acpi/interpreter/amxface.c b/drivers/acpi/interpreter/amxface.c
index fd589d39b..20cf9820e 100644
--- a/drivers/acpi/interpreter/amxface.c
+++ b/drivers/acpi/interpreter/amxface.c
@@ -2,12 +2,12 @@
/******************************************************************************
*
* Module Name: amxface - External interpreter interfaces
- * $Revision: 22 $
+ * $Revision: 24 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c
index 27c02e22a..c2e6a71e0 100644
--- a/drivers/acpi/namespace/nsaccess.c
+++ b/drivers/acpi/namespace/nsaccess.c
@@ -1,12 +1,12 @@
/*******************************************************************************
*
* Module Name: nsaccess - Top-level functions for accessing ACPI namespace
- * $Revision: 117 $
+ * $Revision: 119 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -117,9 +117,9 @@ acpi_ns_root_initialize (void)
switch (init_val->type)
{
- case ACPI_TYPE_NUMBER:
+ case ACPI_TYPE_INTEGER:
- obj_desc->number.value =
+ obj_desc->integer.value =
(ACPI_INTEGER) STRTOUL (init_val->val, NULL, 10);
break;
@@ -239,7 +239,7 @@ acpi_ns_lookup (
ACPI_NAMESPACE_NODE **return_node)
{
ACPI_STATUS status;
- ACPI_NAMESPACE_NODE *prefix_node;
+ ACPI_NAMESPACE_NODE *prefix_node;
ACPI_NAMESPACE_NODE *current_node = NULL;
ACPI_NAMESPACE_NODE *scope_to_push = NULL;
ACPI_NAMESPACE_NODE *this_node = NULL;
@@ -248,8 +248,7 @@ acpi_ns_lookup (
u8 null_name_path = FALSE;
OBJECT_TYPE_INTERNAL type_to_check_for;
OBJECT_TYPE_INTERNAL this_search_type;
-
- DEBUG_ONLY_MEMBERS (u32 i)
+ u32 local_flags = flags & ~NS_ERROR_IF_FOUND;
if (!return_node) {
@@ -437,6 +436,7 @@ acpi_ns_lookup (
this_search_type = ACPI_TYPE_ANY;
if (!num_segments) {
this_search_type = type;
+ local_flags = flags;
}
/* Pluck one ACPI name from the front of the pathname */
@@ -447,7 +447,7 @@ acpi_ns_lookup (
status = acpi_ns_search_and_enter (simple_name, walk_state,
current_node, interpreter_mode,
- this_search_type, flags,
+ this_search_type, local_flags,
&this_node);
if (ACPI_FAILURE (status)) {
diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c
index 9f1d5377e..5cac5d111 100644
--- a/drivers/acpi/namespace/nsalloc.c
+++ b/drivers/acpi/namespace/nsalloc.c
@@ -1,12 +1,12 @@
/*******************************************************************************
*
* Module Name: nsalloc - Namespace allocation and deletion utilities
- * $Revision: 43 $
+ * $Revision: 45 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
index fbba7840c..6c040d22e 100644
--- a/drivers/acpi/namespace/nseval.c
+++ b/drivers/acpi/namespace/nseval.c
@@ -2,12 +2,12 @@
*
* Module Name: nseval - Object evaluation interfaces -- includes control
* method lookup and execution.
- * $Revision: 79 $
+ * $Revision: 81 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
index ddacd7b8c..76b535205 100644
--- a/drivers/acpi/namespace/nsinit.c
+++ b/drivers/acpi/namespace/nsinit.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: nsinit - namespace initialization
- * $Revision: 9 $
+ * $Revision: 12 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -239,7 +239,9 @@ acpi_ns_init_one_device (
status = acpi_cm_execute_STA (node, &flags);
if (ACPI_FAILURE (status)) {
- return (status);
+ /* Ignore error and move on to next device */
+
+ return (AE_OK);
}
info->num_STA++;
@@ -260,12 +262,15 @@ acpi_ns_init_one_device (
}
else if (ACPI_FAILURE (status)) {
- return (status);
+ /* Ignore error and move on to next device */
+
}
else {
+ /* Count of successfull INIs */
+
info->num_INI++;
}
- return (status);
+ return (AE_OK);
}
diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c
index 28a26376d..f0eaf273b 100644
--- a/drivers/acpi/namespace/nsload.c
+++ b/drivers/acpi/namespace/nsload.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: nsload - namespace loading/expanding/contracting procedures
- * $Revision: 33 $
+ * $Revision: 35 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c
index faf8fe56a..c2fb49163 100644
--- a/drivers/acpi/namespace/nsnames.c
+++ b/drivers/acpi/namespace/nsnames.c
@@ -1,12 +1,12 @@
/*******************************************************************************
*
* Module Name: nsnames - Name manipulation and search
- * $Revision: 51 $
+ * $Revision: 53 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c
index 6d41b91ce..493cb1317 100644
--- a/drivers/acpi/namespace/nsobject.c
+++ b/drivers/acpi/namespace/nsobject.c
@@ -2,12 +2,12 @@
*
* Module Name: nsobject - Utilities for objects attached to namespace
* table entries
- * $Revision: 47 $
+ * $Revision: 49 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -205,7 +205,7 @@ acpi_ns_attach_object (
case AML_ZERO_OP: case AML_ONES_OP: case AML_ONE_OP:
case AML_BYTE_OP: case AML_WORD_OP: case AML_DWORD_OP:
- obj_type = ACPI_TYPE_NUMBER;
+ obj_type = ACPI_TYPE_INTEGER;
break;
diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c
index 001f57d9d..7a29e7542 100644
--- a/drivers/acpi/namespace/nssearch.c
+++ b/drivers/acpi/namespace/nssearch.c
@@ -1,12 +1,12 @@
/*******************************************************************************
*
* Module Name: nssearch - Namespace search
- * $Revision: 62 $
+ * $Revision: 64 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -70,8 +70,6 @@ acpi_ns_search_node (
ACPI_NAMESPACE_NODE *next_node;
-
-
/*
* Search for name in this table, which is to say that we must search
* for the name among the children of this object
diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c
index 593064dbb..11457b33f 100644
--- a/drivers/acpi/namespace/nsutils.c
+++ b/drivers/acpi/namespace/nsutils.c
@@ -2,12 +2,12 @@
*
* Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
* parents and siblings and Scope manipulation
- * $Revision: 74 $
+ * $Revision: 77 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c
index 3682266b3..cf84be326 100644
--- a/drivers/acpi/namespace/nswalk.c
+++ b/drivers/acpi/namespace/nswalk.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: nswalk - Functions for walking the APCI namespace
- * $Revision: 17 $
+ * $Revision: 19 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c
index 2947f7f06..957481a6d 100644
--- a/drivers/acpi/namespace/nsxfname.c
+++ b/drivers/acpi/namespace/nsxfname.c
@@ -2,12 +2,12 @@
*
* Module Name: nsxfname - Public interfaces to the ACPI subsystem
* ACPI Namespace oriented interfaces
- * $Revision: 73 $
+ * $Revision: 75 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c
index d4432ee8a..742c5da66 100644
--- a/drivers/acpi/namespace/nsxfobj.c
+++ b/drivers/acpi/namespace/nsxfobj.c
@@ -2,12 +2,12 @@
*
* Module Name: nsxfobj - Public interfaces to the ACPI subsystem
* ACPI Object oriented interfaces
- * $Revision: 75 $
+ * $Revision: 78 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -695,4 +695,3 @@ acpi_get_devices (
return (status);
}
-
diff --git a/drivers/acpi/os.c b/drivers/acpi/os.c
index 7bf86171b..172b6659b 100644
--- a/drivers/acpi/os.c
+++ b/drivers/acpi/os.c
@@ -24,8 +24,8 @@
#include <linux/mm.h>
#include <linux/pci.h>
#include <linux/acpi.h>
+#include <linux/delay.h>
#include <asm/io.h>
-#include <asm/delay.h>
#include "acpi.h"
#include "driver.h"
diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c
index 35d623668..da3ef9b30 100644
--- a/drivers/acpi/parser/psargs.c
+++ b/drivers/acpi/parser/psargs.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: psargs - Parse AML opcode arguments
- * $Revision: 42 $
+ * $Revision: 43 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c
index a7f061363..90a73f45b 100644
--- a/drivers/acpi/parser/psopcode.c
+++ b/drivers/acpi/parser/psopcode.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: psopcode - Parser opcode information table
- * $Revision: 24 $
+ * $Revision: 27 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -44,7 +44,7 @@
#define _PFX 0x6D
#define _UNKNOWN_OPCODE 0x02 /* An example unknown opcode */
-#define MAX_EXTENDED_OPCODE 0x87
+#define MAX_EXTENDED_OPCODE 0x88
#define NUM_EXTENDED_OPCODE MAX_EXTENDED_OPCODE + 1
#define MAX_INTERNAL_OPCODE
#define NUM_INTERNAL_OPCODE MAX_INTERNAL_OPCODE + 1
@@ -83,9 +83,11 @@
#define ARGP_WORD_OP ARGP_LIST1 (ARGP_WORDDATA)
#define ARGP_DWORD_OP ARGP_LIST1 (ARGP_DWORDDATA)
#define ARGP_STRING_OP ARGP_LIST1 (ARGP_CHARLIST)
+#define ARGP_QWORD_OP ARGP_LIST1 (ARGP_QWORDDATA)
#define ARGP_SCOPE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_TERMLIST)
#define ARGP_BUFFER_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_BYTELIST)
#define ARGP_PACKAGE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_BYTEDATA, ARGP_DATAOBJLIST)
+#define ARGP_VAR_PACKAGE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_BYTEDATA, ARGP_DATAOBJLIST)
#define ARGP_METHOD_OP ARGP_LIST4 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_BYTEDATA, ARGP_TERMLIST)
#define ARGP_LOCAL0 ARG_NONE
#define ARGP_LOCAL1 ARG_NONE
@@ -122,6 +124,8 @@
#define ARGP_FIND_SET_LEFT_BIT_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
#define ARGP_FIND_SET_RIGHT_BIT_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
#define ARGP_DEREF_OF_OP ARGP_LIST1 (ARGP_TERMARG)
+#define ARGP_CONCAT_RES_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
+#define ARGP_MOD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_NOTIFY_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_TERMARG)
#define ARGP_SIZE_OF_OP ARGP_LIST1 (ARGP_SUPERNAME)
#define ARGP_INDEX_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
@@ -131,12 +135,21 @@
#define ARGP_BYTE_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
#define ARGP_BIT_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
#define ARGP_TYPE_OP ARGP_LIST1 (ARGP_SUPERNAME)
+#define ARGP_QWORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
#define ARGP_LAND_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_LOR_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_LNOT_OP ARGP_LIST1 (ARGP_TERMARG)
#define ARGP_LEQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_LGREATER_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_LLESS_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
+#define ARGP_TO_BUFFER_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
+#define ARGP_TO_DEC_STR_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
+#define ARGP_TO_HEX_STR_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
+#define ARGP_TO_INTEGER_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
+#define ARGP_TO_STRING_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
+#define ARGP_COPY_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_SIMPLENAME)
+#define ARGP_MID_OP ARGP_LIST4 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
+#define ARGP_CONTINUE_OP ARG_NONE
#define ARGP_IF_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_TERMLIST)
#define ARGP_ELSE_OP ARGP_LIST2 (ARGP_PKGLENGTH, ARGP_TERMLIST)
#define ARGP_WHILE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_TERMLIST)
@@ -149,6 +162,7 @@
#define ARGP_EVENT_OP ARGP_LIST1 (ARGP_NAME)
#define ARGP_COND_REF_OF_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_SUPERNAME)
#define ARGP_CREATE_FIELD_OP ARGP_LIST4 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
+#define ARGP_LOAD_TABLE_OP ARGP_LIST6 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_LOAD_OP ARGP_LIST2 (ARGP_NAMESTRING, ARGP_SUPERNAME)
#define ARGP_STALL_OP ARGP_LIST1 (ARGP_TERMARG)
#define ARGP_SLEEP_OP ARGP_LIST1 (ARGP_TERMARG)
@@ -171,6 +185,7 @@
#define ARGP_THERMAL_ZONE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_OBJLIST)
#define ARGP_INDEX_FIELD_OP ARGP_LIST5 (ARGP_PKGLENGTH, ARGP_NAMESTRING, ARGP_NAMESTRING,ARGP_BYTEDATA, ARGP_FIELDLIST)
#define ARGP_BANK_FIELD_OP ARGP_LIST6 (ARGP_PKGLENGTH, ARGP_NAMESTRING, ARGP_NAMESTRING,ARGP_TERMARG, ARGP_BYTEDATA, ARGP_FIELDLIST)
+#define ARGP_DATA_REGION_OP ARGP_LIST4 (ARGP_NAMESTRING, ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_LNOTEQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_LLESSEQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_LGREATEREQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG)
@@ -187,7 +202,7 @@
* All AML opcodes and the runtime arguments for each. Used by the AML interpreter Each list is compressed
* into a 32-bit number and stored in the master opcode table at the end of this file.
*
- * (Used by Acpi_aml_prep_operands procedure)
+ * (Used by Acpi_aml_prep_operands procedure and the ASL Compiler)
*/
#define ARGI_ZERO_OP ARG_NONE
@@ -198,9 +213,11 @@
#define ARGI_WORD_OP ARGI_INVALID_OPCODE
#define ARGI_DWORD_OP ARGI_INVALID_OPCODE
#define ARGI_STRING_OP ARGI_INVALID_OPCODE
+#define ARGI_QWORD_OP ARGI_INVALID_OPCODE
#define ARGI_SCOPE_OP ARGI_INVALID_OPCODE
#define ARGI_BUFFER_OP ARGI_INVALID_OPCODE
#define ARGI_PACKAGE_OP ARGI_INVALID_OPCODE
+#define ARGI_VAR_PACKAGE_OP ARGI_INVALID_OPCODE
#define ARGI_METHOD_OP ARGI_INVALID_OPCODE
#define ARGI_LOCAL0 ARG_NONE
#define ARGI_LOCAL1 ARG_NONE
@@ -218,40 +235,51 @@
#define ARGI_ARG5 ARG_NONE
#define ARGI_ARG6 ARG_NONE
#define ARGI_STORE_OP ARGI_LIST2 (ARGI_ANYTYPE, ARGI_TARGETREF)
-#define ARGI_REF_OF_OP ARGI_LIST1 (ARGI_REFERENCE)
-#define ARGI_ADD_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF)
-#define ARGI_CONCAT_OP ARGI_LIST3 (ARGI_STRING, ARGI_STRING, ARGI_TARGETREF)
-#define ARGI_SUBTRACT_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF)
-#define ARGI_INCREMENT_OP ARGI_LIST1 (ARGI_REFERENCE)
-#define ARGI_DECREMENT_OP ARGI_LIST1 (ARGI_REFERENCE)
-#define ARGI_MULTIPLY_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF)
-#define ARGI_DIVIDE_OP ARGI_LIST4 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF, ARGI_TARGETREF)
-#define ARGI_SHIFT_LEFT_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF)
-#define ARGI_SHIFT_RIGHT_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF)
-#define ARGI_BIT_AND_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF)
-#define ARGI_BIT_NAND_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF)
-#define ARGI_BIT_OR_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF)
-#define ARGI_BIT_NOR_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF)
-#define ARGI_BIT_XOR_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_TARGETREF)
-#define ARGI_BIT_NOT_OP ARGI_LIST2 (ARGI_NUMBER, ARGI_TARGETREF)
-#define ARGI_FIND_SET_LEFT_BIT_OP ARGI_LIST2 (ARGI_NUMBER, ARGI_TARGETREF)
-#define ARGI_FIND_SET_RIGHT_BIT_OP ARGI_LIST2 (ARGI_NUMBER, ARGI_TARGETREF)
+#define ARGI_REF_OF_OP ARGI_LIST1 (ARGI_OBJECT_REF)
+#define ARGI_ADD_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
+#define ARGI_CONCAT_OP ARGI_LIST3 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA, ARGI_TARGETREF)
+#define ARGI_SUBTRACT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
+#define ARGI_INCREMENT_OP ARGI_LIST1 (ARGI_INTEGER_REF)
+#define ARGI_DECREMENT_OP ARGI_LIST1 (ARGI_INTEGER_REF)
+#define ARGI_MULTIPLY_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
+#define ARGI_DIVIDE_OP ARGI_LIST4 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF, ARGI_TARGETREF)
+#define ARGI_SHIFT_LEFT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
+#define ARGI_SHIFT_RIGHT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
+#define ARGI_BIT_AND_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
+#define ARGI_BIT_NAND_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
+#define ARGI_BIT_OR_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
+#define ARGI_BIT_NOR_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
+#define ARGI_BIT_XOR_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
+#define ARGI_BIT_NOT_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF)
+#define ARGI_FIND_SET_LEFT_BIT_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF)
+#define ARGI_FIND_SET_RIGHT_BIT_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_DEREF_OF_OP ARGI_LIST1 (ARGI_REFERENCE)
-#define ARGI_NOTIFY_OP ARGI_LIST2 (ARGI_REFERENCE, ARGI_NUMBER)
+#define ARGI_CONCAT_RES_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_BUFFER, ARGI_TARGETREF)
+#define ARGI_MOD_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
+#define ARGI_NOTIFY_OP ARGI_LIST2 (ARGI_DEVICE_REF, ARGI_INTEGER)
#define ARGI_SIZE_OF_OP ARGI_LIST1 (ARGI_DATAOBJECT)
-#define ARGI_INDEX_OP ARGI_LIST3 (ARGI_COMPLEXOBJ, ARGI_NUMBER, ARGI_TARGETREF)
-#define ARGI_MATCH_OP ARGI_LIST6 (ARGI_PACKAGE, ARGI_NUMBER, ARGI_NUMBER, ARGI_NUMBER, ARGI_NUMBER, ARGI_NUMBER)
-#define ARGI_DWORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_NUMBER, ARGI_REFERENCE)
-#define ARGI_WORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_NUMBER, ARGI_REFERENCE)
-#define ARGI_BYTE_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_NUMBER, ARGI_REFERENCE)
-#define ARGI_BIT_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_NUMBER, ARGI_REFERENCE)
+#define ARGI_INDEX_OP ARGI_LIST3 (ARGI_COMPLEXOBJ, ARGI_INTEGER, ARGI_TARGETREF)
+#define ARGI_MATCH_OP ARGI_LIST6 (ARGI_PACKAGE, ARGI_INTEGER, ARGI_INTEGER, ARGI_INTEGER, ARGI_INTEGER, ARGI_INTEGER)
+#define ARGI_DWORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE)
+#define ARGI_WORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE)
+#define ARGI_BYTE_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE)
+#define ARGI_BIT_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE)
#define ARGI_TYPE_OP ARGI_LIST1 (ARGI_ANYTYPE)
-#define ARGI_LAND_OP ARGI_LIST2 (ARGI_NUMBER, ARGI_NUMBER)
-#define ARGI_LOR_OP ARGI_LIST2 (ARGI_NUMBER, ARGI_NUMBER)
-#define ARGI_LNOT_OP ARGI_LIST1 (ARGI_NUMBER)
-#define ARGI_LEQUAL_OP ARGI_LIST2 (ARGI_NUMBER, ARGI_NUMBER)
-#define ARGI_LGREATER_OP ARGI_LIST2 (ARGI_NUMBER, ARGI_NUMBER)
-#define ARGI_LLESS_OP ARGI_LIST2 (ARGI_NUMBER, ARGI_NUMBER)
+#define ARGI_QWORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE)
+#define ARGI_LAND_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER)
+#define ARGI_LOR_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER)
+#define ARGI_LNOT_OP ARGI_LIST1 (ARGI_INTEGER)
+#define ARGI_LEQUAL_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER)
+#define ARGI_LGREATER_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER)
+#define ARGI_LLESS_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER)
+#define ARGI_TO_BUFFER_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
+#define ARGI_TO_DEC_STR_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
+#define ARGI_TO_HEX_STR_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
+#define ARGI_TO_INTEGER_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
+#define ARGI_TO_STRING_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_FIXED_TARGET)
+#define ARGI_COPY_OP ARGI_LIST2 (ARGI_ANYTYPE, ARGI_SIMPLE_TARGET)
+#define ARGI_MID_OP ARGI_LIST4 (ARGI_BUFFERSTRING,ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
+#define ARGI_CONTINUE_OP ARGI_INVALID_OPCODE
#define ARGI_IF_OP ARGI_INVALID_OPCODE
#define ARGI_ELSE_OP ARGI_INVALID_OPCODE
#define ARGI_WHILE_OP ARGI_INVALID_OPCODE
@@ -262,23 +290,24 @@
#define ARGI_ONES_OP ARG_NONE
#define ARGI_MUTEX_OP ARGI_INVALID_OPCODE
#define ARGI_EVENT_OP ARGI_INVALID_OPCODE
-#define ARGI_COND_REF_OF_OP ARGI_LIST2 (ARGI_REFERENCE, ARGI_TARGETREF)
-#define ARGI_CREATE_FIELD_OP ARGI_LIST4 (ARGI_BUFFER, ARGI_NUMBER, ARGI_NUMBER, ARGI_REFERENCE)
+#define ARGI_COND_REF_OF_OP ARGI_LIST2 (ARGI_OBJECT_REF, ARGI_TARGETREF)
+#define ARGI_CREATE_FIELD_OP ARGI_LIST4 (ARGI_BUFFER, ARGI_INTEGER, ARGI_INTEGER, ARGI_REFERENCE)
+#define ARGI_LOAD_TABLE_OP ARGI_LIST6 (ARGI_STRING, ARGI_STRING, ARGI_STRING, ARGI_STRING, ARGI_STRING, ARGI_TARGETREF)
#define ARGI_LOAD_OP ARGI_LIST2 (ARGI_REGION, ARGI_TARGETREF)
-#define ARGI_STALL_OP ARGI_LIST1 (ARGI_NUMBER)
-#define ARGI_SLEEP_OP ARGI_LIST1 (ARGI_NUMBER)
-#define ARGI_ACQUIRE_OP ARGI_LIST2 (ARGI_MUTEX, ARGI_NUMBER)
+#define ARGI_STALL_OP ARGI_LIST1 (ARGI_INTEGER)
+#define ARGI_SLEEP_OP ARGI_LIST1 (ARGI_INTEGER)
+#define ARGI_ACQUIRE_OP ARGI_LIST2 (ARGI_MUTEX, ARGI_INTEGER)
#define ARGI_SIGNAL_OP ARGI_LIST1 (ARGI_EVENT)
-#define ARGI_WAIT_OP ARGI_LIST2 (ARGI_EVENT, ARGI_NUMBER)
+#define ARGI_WAIT_OP ARGI_LIST2 (ARGI_EVENT, ARGI_INTEGER)
#define ARGI_RESET_OP ARGI_LIST1 (ARGI_EVENT)
#define ARGI_RELEASE_OP ARGI_LIST1 (ARGI_MUTEX)
-#define ARGI_FROM_BCD_OP ARGI_LIST2 (ARGI_NUMBER, ARGI_TARGETREF)
-#define ARGI_TO_BCD_OP ARGI_LIST2 (ARGI_NUMBER, ARGI_TARGETREF)
+#define ARGI_FROM_BCD_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF)
+#define ARGI_TO_BCD_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_FIXED_TARGET)
#define ARGI_UNLOAD_OP ARGI_LIST1 (ARGI_DDBHANDLE)
#define ARGI_REVISION_OP ARG_NONE
#define ARGI_DEBUG_OP ARG_NONE
-#define ARGI_FATAL_OP ARGI_LIST3 (ARGI_NUMBER, ARGI_NUMBER, ARGI_NUMBER)
-#define ARGI_REGION_OP ARGI_LIST2 (ARGI_NUMBER, ARGI_NUMBER)
+#define ARGI_FATAL_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_INTEGER)
+#define ARGI_REGION_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER)
#define ARGI_DEF_FIELD_OP ARGI_INVALID_OPCODE
#define ARGI_DEVICE_OP ARGI_INVALID_OPCODE
#define ARGI_PROCESSOR_OP ARGI_INVALID_OPCODE
@@ -286,6 +315,7 @@
#define ARGI_THERMAL_ZONE_OP ARGI_INVALID_OPCODE
#define ARGI_INDEX_FIELD_OP ARGI_INVALID_OPCODE
#define ARGI_BANK_FIELD_OP ARGI_INVALID_OPCODE
+#define ARGI_DATA_REGION_OP ARGI_LIST3 (ARGI_STRING, ARGI_STRING, ARGI_STRING)
#define ARGI_LNOTEQUAL_OP ARGI_INVALID_OPCODE
#define ARGI_LLESSEQUAL_OP ARGI_INVALID_OPCODE
#define ARGI_LGREATEREQUAL_OP ARGI_INVALID_OPCODE
@@ -307,8 +337,8 @@ static ACPI_OPCODE_INFO aml_op_info[] =
{
/* Index Opcode Type Class Has Arguments? Name Parser Args Interpreter Args */
-/* 00 */ /* AML_ZERO_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "Zero_op", ARGP_ZERO_OP, ARGI_ZERO_OP),
-/* 01 */ /* AML_ONE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "One_op", ARGP_ONE_OP, ARGI_ONE_OP),
+/* 00 */ /* AML_ZERO_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "Zero", ARGP_ZERO_OP, ARGI_ZERO_OP),
+/* 01 */ /* AML_ONE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "One", ARGP_ONE_OP, ARGI_ONE_OP),
/* 02 */ /* AML_ALIAS_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Alias", ARGP_ALIAS_OP, ARGI_ALIAS_OP),
/* 03 */ /* AML_NAME_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Name", ARGP_NAME_OP, ARGI_NAME_OP),
/* 04 */ /* AML_BYTE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "Byte_const", ARGP_BYTE_OP, ARGI_BYTE_OP),
@@ -337,7 +367,7 @@ static ACPI_OPCODE_INFO aml_op_info[] =
/* 1_b */ /* AML_STORE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Store", ARGP_STORE_OP, ARGI_STORE_OP),
/* 1_c */ /* AML_REF_OF_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Ref_of", ARGP_REF_OF_OP, ARGI_REF_OF_OP),
/* 1_d */ /* AML_ADD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Add", ARGP_ADD_OP, ARGI_ADD_OP),
-/* 1_e */ /* AML_CONCAT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Concat", ARGP_CONCAT_OP, ARGI_CONCAT_OP),
+/* 1_e */ /* AML_CONCAT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Concatenate", ARGP_CONCAT_OP, ARGI_CONCAT_OP),
/* 1_f */ /* AML_SUBTRACT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Subtract", ARGP_SUBTRACT_OP, ARGI_SUBTRACT_OP),
/* 20 */ /* AML_INCREMENT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Increment", ARGP_INCREMENT_OP, ARGI_INCREMENT_OP),
/* 21 */ /* AML_DECREMENT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Decrement", ARGP_DECREMENT_OP, ARGI_DECREMENT_OP),
@@ -376,7 +406,7 @@ static ACPI_OPCODE_INFO aml_op_info[] =
/* 42 */ /* AML_RETURN_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_HAS_ARGS, "Return", ARGP_RETURN_OP, ARGI_RETURN_OP),
/* 43 */ /* AML_BREAK_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_NO_ARGS, "Break", ARGP_BREAK_OP, ARGI_BREAK_OP),
/* 44 */ /* AML_BREAK_POINT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_NO_ARGS, "Break_point", ARGP_BREAK_POINT_OP, ARGI_BREAK_POINT_OP),
-/* 45 */ /* AML_ONES_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "Ones_op", ARGP_ONES_OP, ARGI_ONES_OP),
+/* 45 */ /* AML_ONES_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "Ones", ARGP_ONES_OP, ARGI_ONES_OP),
/* Prefixed opcodes (Two-byte opcodes with a prefix op) */
@@ -402,7 +432,7 @@ static ACPI_OPCODE_INFO aml_op_info[] =
/* 59 */ /* AML_DEF_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Field", ARGP_DEF_FIELD_OP, ARGI_DEF_FIELD_OP),
/* 5_a */ /* AML_DEVICE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP),
/* 5_b */ /* AML_PROCESSOR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Processor", ARGP_PROCESSOR_OP, ARGI_PROCESSOR_OP),
-/* 5_c */ /* AML_POWER_RES_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Power_res", ARGP_POWER_RES_OP, ARGI_POWER_RES_OP),
+/* 5_c */ /* AML_POWER_RES_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Power_resource", ARGP_POWER_RES_OP, ARGI_POWER_RES_OP),
/* 5_d */ /* AML_THERMAL_ZONE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Thermal_zone", ARGP_THERMAL_ZONE_OP, ARGI_THERMAL_ZONE_OP),
/* 5_e */ /* AML_INDEX_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Index_field", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP),
/* 5_f */ /* AML_BANK_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Bank_field", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP),
@@ -423,6 +453,26 @@ static ACPI_OPCODE_INFO aml_op_info[] =
/* 6_b */ /* UNKNOWN OPCODES */ OP_INFO_ENTRY (ACPI_OP_TYPE_UNKNOWN | OPTYPE_BOGUS| AML_HAS_ARGS, "UNKNOWN_OP!", ARG_NONE, ARG_NONE),
/* 6_c */ /* ASCII CHARACTERS */ OP_INFO_ENTRY (ACPI_OP_TYPE_ASCII | OPTYPE_BOGUS| AML_HAS_ARGS, "ASCII_ONLY!", ARG_NONE, ARG_NONE),
/* 6_d */ /* PREFIX CHARACTERS */ OP_INFO_ENTRY (ACPI_OP_TYPE_PREFIX | OPTYPE_BOGUS| AML_HAS_ARGS, "PREFIX_ONLY!", ARG_NONE, ARG_NONE),
+
+
+/* ACPI 2.0 (new) opcodes */
+
+/* 6_e */ /* AML_QWORD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "Qword_const", ARGP_QWORD_OP, ARGI_QWORD_OP),
+/* 6_f */ /* AML_VAR_PACKAGE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DATA_TERM| AML_HAS_ARGS, "Var_package", ARGP_VAR_PACKAGE_OP, ARGI_VAR_PACKAGE_OP),
+/* 70 */ /* AML_CONCAT_RES_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Concat_res", ARGP_CONCAT_RES_OP, ARGI_CONCAT_RES_OP),
+/* 71 */ /* AML_MOD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Mod", ARGP_MOD_OP, ARGI_MOD_OP),
+/* 72 */ /* AML_QWORD_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CREATE_FIELD| AML_HAS_ARGS, "Create_qWord_field", ARGP_QWORD_FIELD_OP, ARGI_QWORD_FIELD_OP),
+/* 73 */ /* AML_TO_BUFFER_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_buffer", ARGP_TO_BUFFER_OP, ARGI_TO_BUFFER_OP),
+/* 74 */ /* AML_TO_DEC_STR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_dec_string", ARGP_TO_DEC_STR_OP, ARGI_TO_DEC_STR_OP),
+/* 75 */ /* AML_TO_HEX_STR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_hex_string", ARGP_TO_HEX_STR_OP, ARGI_TO_HEX_STR_OP),
+/* 76 */ /* AML_TO_INTEGER_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_integer", ARGP_TO_INTEGER_OP, ARGI_TO_INTEGER_OP),
+/* 77 */ /* AML_TO_STRING_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_string", ARGP_TO_STRING_OP, ARGI_TO_STRING_OP),
+/* 78 */ /* AML_COPY_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Copy", ARGP_COPY_OP, ARGI_COPY_OP),
+/* 79 */ /* AML_MID_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Mid", ARGP_MID_OP, ARGI_MID_OP),
+/* 7_a */ /* AML_CONTINUE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_NO_ARGS, "Continue", ARGP_CONTINUE_OP, ARGI_CONTINUE_OP),
+/* 7_b */ /* AML_LOAD_TABLE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Load_table", ARGP_LOAD_TABLE_OP, ARGI_LOAD_TABLE_OP),
+/* 7_c */ /* AML_DATA_REGION_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Data_op_region", ARGP_DATA_REGION_OP, ARGI_DATA_REGION_OP),
+
};
/*
@@ -433,9 +483,10 @@ static ACPI_OPCODE_INFO aml_op_info[] =
static u8 aml_short_op_info_index[256] =
{
/* 0 1 2 3 4 5 6 7 */
+/* 8 9 A B C D E F */
/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK,
-/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, _UNK, _UNK,
-/* 0x10 */ 0x08, 0x09, 0x0a, _UNK, 0x0b, _UNK, _UNK, _UNK,
+/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK,
+/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK,
/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX,
@@ -449,10 +500,10 @@ static u8 aml_short_op_info_index[256] =
/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK,
/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
-/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, _UNK, _UNK, 0x2f, 0x30,
-/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, _UNK,
-/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, _UNK, _UNK,
-/* 0x98 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30,
+/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72,
+/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74,
+/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A,
/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61,
/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
@@ -471,10 +522,11 @@ static u8 aml_short_op_info_index[256] =
static u8 aml_long_op_info_index[NUM_EXTENDED_OPCODE] =
{
/* 0 1 2 3 4 5 6 7 */
+/* 8 9 A B C D E F */
/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK,
/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK,
-/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B,
/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51,
/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK,
/* 0x30 */ 0x55, 0x56, 0x57, _UNK, _UNK, _UNK, _UNK, _UNK,
@@ -488,13 +540,10 @@ static u8 aml_long_op_info_index[NUM_EXTENDED_OPCODE] =
/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+/* 0x88 */ 0x7C,
};
-/* 0 1 2 3 4 5 6 7 */
-/* 0x00 */
-
-
/*******************************************************************************
*
* FUNCTION: Acpi_ps_get_opcode_info
diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c
index 7471efdcb..7373013da 100644
--- a/drivers/acpi/parser/psparse.c
+++ b/drivers/acpi/parser/psparse.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: psparse - Parser top level AML parse routines
- * $Revision: 71 $
+ * $Revision: 74 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -537,6 +537,12 @@ acpi_ps_parse_loop (
*/
status = acpi_ds_get_predicate_value (walk_state, NULL, TRUE);
+ if (ACPI_FAILURE (status) &&
+ ((status & AE_CODE_MASK) != AE_CODE_CONTROL))
+ {
+ return (status);
+ }
+
status = acpi_ps_next_parse_state (walk_state, op, status);
}
diff --git a/drivers/acpi/parser/psscope.c b/drivers/acpi/parser/psscope.c
index 2e8926ad1..37b5d2265 100644
--- a/drivers/acpi/parser/psscope.c
+++ b/drivers/acpi/parser/psscope.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: psscope - Parser scope stack management routines
- * $Revision: 22 $
+ * $Revision: 24 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/parser/pstree.c b/drivers/acpi/parser/pstree.c
index a22bb646d..dc2e6d4d7 100644
--- a/drivers/acpi/parser/pstree.c
+++ b/drivers/acpi/parser/pstree.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: pstree - Parser op tree manipulation/traversal/search
- * $Revision: 25 $
+ * $Revision: 27 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c
index 3bac4a647..94518a920 100644
--- a/drivers/acpi/parser/psutils.c
+++ b/drivers/acpi/parser/psutils.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: psutils - Parser miscellaneous utilities (Parser only)
- * $Revision: 30 $
+ * $Revision: 32 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c
index 04a75917d..48c11eff3 100644
--- a/drivers/acpi/parser/pswalk.c
+++ b/drivers/acpi/parser/pswalk.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: pswalk - Parser routines to walk parsed op tree(s)
- * $Revision: 50 $
+ * $Revision: 52 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c
index a33ace051..328c755d9 100644
--- a/drivers/acpi/parser/psxface.c
+++ b/drivers/acpi/parser/psxface.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: psxface - Parser external interfaces
- * $Revision: 37 $
+ * $Revision: 40 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -121,6 +121,12 @@ acpi_psx_execute (
return (AE_NO_MEMORY);
}
+
+ /* Init new op with the method name and pointer back to the NS node */
+
+ acpi_ps_set_name (op, method_node->name);
+ op->node = method_node;
+
/*
* The walk of the parse tree is where we actually execute the method
*/
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 0422bf94d..d24392895 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -81,12 +81,12 @@ proc_read_ac_adapter_status(char *page, char **start, off_t off,
buf.length = sizeof(obj);
buf.pointer = &obj;
if (!ACPI_SUCCESS(acpi_evaluate_object(ac_handle, "_PSR", NULL, &buf))
- || obj.type != ACPI_TYPE_NUMBER) {
+ || obj.type != ACPI_TYPE_INTEGER) {
p += sprintf(p, "Could not read AC status\n");
goto end;
}
- if (obj.number.value)
+ if (obj.integer.value)
p += sprintf(p, "on-line\n");
else
p += sprintf(p, "off-line\n");
diff --git a/drivers/acpi/resources/rsaddr.c b/drivers/acpi/resources/rsaddr.c
index e48666113..af91bc59f 100644
--- a/drivers/acpi/resources/rsaddr.c
+++ b/drivers/acpi/resources/rsaddr.c
@@ -4,12 +4,12 @@
* Acpi_rs_address16_stream
* Acpi_rs_address32_resource
* Acpi_rs_address32_stream
- * $Revision: 12 $
+ * $Revision: 14 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c
index 2874aa3d0..86ff91be8 100644
--- a/drivers/acpi/resources/rscalc.c
+++ b/drivers/acpi/resources/rscalc.c
@@ -2,12 +2,12 @@
*
* Module Name: rscalc - Acpi_rs_calculate_byte_stream_length
* Acpi_rs_calculate_list_length
- * $Revision: 16 $
+ * $Revision: 18 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c
index bc95686a7..f221a41dc 100644
--- a/drivers/acpi/resources/rscreate.c
+++ b/drivers/acpi/resources/rscreate.c
@@ -3,12 +3,12 @@
* Module Name: rscreate - Acpi_rs_create_resource_list
* Acpi_rs_create_pci_routing_table
* Acpi_rs_create_byte_stream
- * $Revision: 22 $
+ * $Revision: 24 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -223,9 +223,9 @@ acpi_rs_create_pci_routing_table (
/*
* Dereference the Address
*/
- if (ACPI_TYPE_NUMBER == (*sub_object_list)->common.type) {
+ if (ACPI_TYPE_INTEGER == (*sub_object_list)->common.type) {
user_prt->data.address =
- (*sub_object_list)->number.value;
+ (*sub_object_list)->integer.value;
}
else {
@@ -237,9 +237,9 @@ acpi_rs_create_pci_routing_table (
*/
sub_object_list++;
- if (ACPI_TYPE_NUMBER == (*sub_object_list)->common.type) {
+ if (ACPI_TYPE_INTEGER == (*sub_object_list)->common.type) {
user_prt->data.pin =
- (u32) (*sub_object_list)->number.value;
+ (u32) (*sub_object_list)->integer.value;
}
else {
@@ -267,7 +267,7 @@ acpi_rs_create_pci_routing_table (
* is NULL, since the entire buffer was zeroed
* out, we can leave this alone.
*/
- if (ACPI_TYPE_NUMBER == (*sub_object_list)->common.type) {
+ if (ACPI_TYPE_INTEGER == (*sub_object_list)->common.type) {
/*
* Add to the Length field the length of
* the u32 NULL
@@ -289,9 +289,9 @@ acpi_rs_create_pci_routing_table (
*/
sub_object_list++;
- if (ACPI_TYPE_NUMBER == (*sub_object_list)->common.type) {
+ if (ACPI_TYPE_INTEGER == (*sub_object_list)->common.type) {
user_prt->data.source_index =
- (u32) (*sub_object_list)->number.value;
+ (u32) (*sub_object_list)->integer.value;
}
else {
diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c
index 073f4ddd4..03d2da6f2 100644
--- a/drivers/acpi/resources/rsdump.c
+++ b/drivers/acpi/resources/rsdump.c
@@ -1,12 +1,12 @@
/*******************************************************************************
*
* Module Name: rsdump - Functions do dump out the resource structures.
- * $Revision: 13 $
+ * $Revision: 15 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/resources/rsio.c b/drivers/acpi/resources/rsio.c
index 0d6c507c0..58fcf8cd8 100644
--- a/drivers/acpi/resources/rsio.c
+++ b/drivers/acpi/resources/rsio.c
@@ -6,12 +6,12 @@
* Acpi_rs_fixed_io_stream
* Acpi_rs_dma_resource
* Acpi_rs_dma_stream
- * $Revision: 10 $
+ * $Revision: 12 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/resources/rsirq.c b/drivers/acpi/resources/rsirq.c
index 28a3a5045..eb47669ad 100644
--- a/drivers/acpi/resources/rsirq.c
+++ b/drivers/acpi/resources/rsirq.c
@@ -4,12 +4,12 @@
* Acpi_rs_irq_stream
* Acpi_rs_extended_irq_resource
* Acpi_rs_extended_irq_stream
- * $Revision: 11 $
+ * $Revision: 13 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c
index 8e39ddded..de47563d0 100644
--- a/drivers/acpi/resources/rslist.c
+++ b/drivers/acpi/resources/rslist.c
@@ -2,12 +2,12 @@
*
* Module Name: rslist - Acpi_rs_byte_stream_to_list
* Acpi_list_to_byte_stream
- * $Revision: 8 $
+ * $Revision: 10 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/resources/rsmemory.c b/drivers/acpi/resources/rsmemory.c
index 8aa4914f4..f9437e60c 100644
--- a/drivers/acpi/resources/rsmemory.c
+++ b/drivers/acpi/resources/rsmemory.c
@@ -6,12 +6,12 @@
* Acpi_rs_fixed_memory32_resource
* Acpi_rs_memory32_range_stream
* Acpi_rs_fixed_memory32_stream
- * $Revision: 10 $
+ * $Revision: 12 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c
index 01bbb377e..be0a1a6a0 100644
--- a/drivers/acpi/resources/rsmisc.c
+++ b/drivers/acpi/resources/rsmisc.c
@@ -8,12 +8,12 @@
* Acpi_rs_end_dependent_functions_resource
* Acpi_rs_start_dependent_functions_stream
* Acpi_rs_end_dependent_functions_stream
- * $Revision: 10 $
+ * $Revision: 12 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c
index 0a3f76668..2994bf0d3 100644
--- a/drivers/acpi/resources/rsutils.c
+++ b/drivers/acpi/resources/rsutils.c
@@ -1,12 +1,12 @@
/*******************************************************************************
*
* Module Name: rsutils - Utilities for the resource manager
- * $Revision: 12 $
+ * $Revision: 14 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c
index 8691f8200..5c126aaa5 100644
--- a/drivers/acpi/resources/rsxface.c
+++ b/drivers/acpi/resources/rsxface.c
@@ -1,12 +1,12 @@
/*******************************************************************************
*
* Module Name: rsxface - Public interfaces to the ACPI subsystem
- * $Revision: 8 $
+ * $Revision: 10 $
*
******************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/sys.c b/drivers/acpi/sys.c
index 13648c255..2011174a1 100644
--- a/drivers/acpi/sys.c
+++ b/drivers/acpi/sys.c
@@ -27,18 +27,13 @@
#define _COMPONENT OS_DEPENDENT
MODULE_NAME ("sys")
-#define ACPI_SLP_TYP(typa, typb) (((int)(typa) << 8) | (int)(typb))
-#define ACPI_SLP_TYPA(value) ((value) >> 8)
-#define ACPI_SLP_TYPB(value) ((value) & 0xff)
-
struct acpi_enter_sx_ctx
{
wait_queue_head_t wait;
unsigned int state;
};
-volatile acpi_sstate_t acpi_sleep_state = ACPI_S0;
-static unsigned long acpi_slptyp[ACPI_S5 + 1] = {ACPI_INVALID,};
+volatile acpi_sstate_t acpi_sleep_state = ACPI_STATE_S0;
/*
* Enter system sleep state
@@ -50,56 +45,32 @@ acpi_enter_sx_async(void *context)
ACPI_OBJECT_LIST arg_list;
ACPI_OBJECT arg;
- /*
- * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
- */
-
- // run the _PTS method
- memset(&arg_list, 0, sizeof(arg_list));
- arg_list.count = 1;
- arg_list.pointer = &arg;
-
- memset(&arg, 0, sizeof(arg));
- arg.type = ACPI_TYPE_NUMBER;
- arg.number.value = ctx->state;
+ acpi_enter_sleep_state(ctx->state);
- acpi_evaluate_object(NULL, "\\_PTS", &arg_list, NULL);
-
- // clear wake status by writing a 1
- acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, WAK_STS, 1);
-
- acpi_sleep_state = ctx->state;
-
- // set ACPI_SLP_TYPA/b and ACPI_SLP_EN
- acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, SLP_TYPE_A,
- ACPI_SLP_TYPA(acpi_slptyp[ctx->state]));
- acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, SLP_TYPE_B,
- ACPI_SLP_TYPB(acpi_slptyp[ctx->state]));
- acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, SLP_EN, 1);
-
- if (ctx->state != ACPI_S1) {
- /* we should have just shut off - what are we doing here? */
- printk(KERN_ERR "ACPI: S%d failed\n", ctx->state);
+ /* either we are in S1, or the transition failed, as the other states resume
+ from the waking vector */
+ if (ctx->state != ACPI_STATE_S1) {
+ printk(KERN_ERR "Could not enter S%d\n", ctx->state);
goto out;
}
- // wait until S1 is entered
+ /* wait until S1 is entered */
while (!(acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_LOCK, WAK_STS)))
safe_halt();
- // run the _WAK method
+ /* run the _WAK method */
memset(&arg_list, 0, sizeof(arg_list));
arg_list.count = 1;
arg_list.pointer = &arg;
memset(&arg, 0, sizeof(arg));
- arg.type = ACPI_TYPE_NUMBER;
- arg.number.value = ctx->state;
+ arg.type = ACPI_TYPE_INTEGER;
+ arg.integer.value = ctx->state;
acpi_evaluate_object(NULL, "\\_WAK", &arg_list, NULL);
out:
- acpi_sleep_state = ACPI_S0;
+ acpi_sleep_state = ACPI_STATE_S0;
if (waitqueue_active(&ctx->wait))
wake_up_interruptible(&ctx->wait);
@@ -112,13 +83,9 @@ static void
acpi_power_off(void)
{
struct acpi_enter_sx_ctx ctx;
-
- if ((STRNCMP(acpi_fadt.header.signature, ACPI_FADT_SIGNATURE, ACPI_SIG_LEN) != 0)
- || acpi_slptyp[ACPI_S5] == ACPI_INVALID)
- return;
init_waitqueue_head(&ctx.wait);
- ctx.state = ACPI_S5;
+ ctx.state = ACPI_STATE_S5;
acpi_enter_sx_async(&ctx);
}
@@ -132,10 +99,6 @@ acpi_enter_sx(acpi_sstate_t state)
DECLARE_WAITQUEUE(wait, current);
int ret = 0;
- if ((STRNCMP(acpi_fadt.header.signature, ACPI_FADT_SIGNATURE, ACPI_SIG_LEN) != 0)
- || acpi_slptyp[state] == ACPI_INVALID)
- return -EINVAL;
-
init_waitqueue_head(&ctx.wait);
ctx.state = state;
@@ -166,19 +129,14 @@ acpi_sys_init(void)
printk(KERN_INFO "ACPI: System firmware supports:");
- for (sx = ACPI_S0; sx <= ACPI_S5; sx++) {
- int ca_sx = (sx <= ACPI_S4) ? sx : (sx + 1);
+ for (sx = ACPI_STATE_S0; sx <= ACPI_STATE_S5; sx++) {
if (ACPI_SUCCESS(
- acpi_hw_obtain_sleep_type_register_data(ca_sx,
+ acpi_hw_obtain_sleep_type_register_data(sx,
&type_a,
&type_b))) {
- acpi_slptyp[sx] = ACPI_SLP_TYP(type_a, type_b);
printk(" S%d", sx);
}
- else {
- acpi_slptyp[sx] = ACPI_INVALID;
- }
}
printk("\n");
diff --git a/drivers/acpi/table.c b/drivers/acpi/table.c
index 8379b4204..de0f99a27 100644
--- a/drivers/acpi/table.c
+++ b/drivers/acpi/table.c
@@ -47,21 +47,6 @@ acpi_fetch_fadt(void)
return -ENODEV;
}
- if (acpi_fadt.plvl2_lat
- && acpi_fadt.plvl2_lat <= ACPI_MAX_P_LVL2_LAT) {
- acpi_c2_exit_latency
- = ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl2_lat);
- acpi_c2_enter_latency
- = ACPI_MICROSEC_TO_TMR_TICKS(ACPI_TMR_HZ / 1000);
- }
- if (acpi_fadt.plvl3_lat
- && acpi_fadt.plvl3_lat <= ACPI_MAX_P_LVL3_LAT) {
- acpi_c3_exit_latency
- = ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl3_lat);
- acpi_c3_enter_latency
- = ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl3_lat * 5);
- }
-
return 0;
}
@@ -71,11 +56,7 @@ acpi_fetch_fadt(void)
int
acpi_find_and_load_tables(u64 rsdp)
{
- if (ACPI_SUCCESS(acpi_load_tables(rsdp)))
- {
- printk(KERN_INFO "ACPI: System description tables loaded\n");
- }
- else {
+ if (!ACPI_SUCCESS(acpi_load_tables(rsdp))) {
printk(KERN_INFO "ACPI: System description table load failed\n");
acpi_terminate();
return -1;
diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c
index 624926d27..76d7fff15 100644
--- a/drivers/acpi/tables/tbconvrt.c
+++ b/drivers/acpi/tables/tbconvrt.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: tbconvrt - ACPI Table conversion utilities
- * $Revision: 15 $
+ * $Revision: 18 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -47,7 +47,7 @@
a.register_bit_width = (u8) MUL_8 (b);\
a.register_bit_offset = 0;\
a.reserved = 0;\
- a.address = (UINT64) c;}
+ ACPI_STORE_ADDRESS (a.address,c);}
/* ACPI V1.0 entries -- address space is always I/O */
@@ -126,8 +126,8 @@ acpi_tb_convert_to_xsdt (
new_table->table_offset_entry[i] =
((RSDT_DESCRIPTOR_REV071 *) table_info->pointer)->table_offset_entry[i];
#else
- new_table->table_offset_entry[i] =
- ((RSDT_DESCRIPTOR_REV1 *) table_info->pointer)->table_offset_entry[i];
+ ACPI_STORE_ADDRESS (new_table->table_offset_entry[i],
+ ((RSDT_DESCRIPTOR_REV1 *) table_info->pointer)->table_offset_entry[i]);
#endif
}
else {
@@ -312,11 +312,11 @@ acpi_tb_convert_table_fadt (void)
/* No 0.71 equivalence. Leave pre-zeroed. */
/* FADT2->Flush_stride = 0; */
- /* Processor’s duty cycle index in processor's P_CNT reg*/
+ /* Processor's duty cycle index in processor's P_CNT reg*/
/* No 0.71 equivalence. Leave pre-zeroed. */
/* FADT2->Duty_offset = 0; */
- /* Processor’s duty cycle value bit width in P_CNT register.*/
+ /* Processor's duty cycle value bit width in P_CNT register.*/
/* No 0.71 equivalence. Leave pre-zeroed. */
/* FADT2->Duty_width = 0; */
@@ -384,8 +384,8 @@ acpi_tb_convert_table_fadt (void)
/* Convert table pointers to 64-bit fields */
- FADT2->Xfirmware_ctrl = (UINT64) FADT1->firmware_ctrl;
- FADT2->Xdsdt = (UINT64) FADT1->dsdt;
+ ACPI_STORE_ADDRESS (FADT2->Xfirmware_ctrl, FADT1->firmware_ctrl);
+ ACPI_STORE_ADDRESS (FADT2->Xdsdt, FADT1->dsdt);
/* System Interrupt Model isn't used in ACPI 2.0*/
/* FADT2->Reserved1 = 0; */
@@ -448,6 +448,7 @@ acpi_tb_convert_table_fadt (void)
* Global FADT pointer will point to the common V2.0 FADT
*/
acpi_gbl_FADT = FADT2;
+ acpi_gbl_FADT->header.length = sizeof (FADT_DESCRIPTOR);
/* Free the original table */
@@ -464,8 +465,6 @@ acpi_tb_convert_table_fadt (void)
table_desc->length = sizeof (FADT_DESCRIPTOR_REV2);
- /* Dump the FADT Header */
-
/* Dump the entire FADT */
diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c
index 2cf8eede7..8e05e2c7d 100644
--- a/drivers/acpi/tables/tbget.c
+++ b/drivers/acpi/tables/tbget.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: tbget - ACPI Table get* routines
- * $Revision: 40 $
+ * $Revision: 43 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
@@ -243,7 +243,7 @@ acpi_tb_get_all_tables (
/* Get the table via the XSDT */
status = acpi_tb_get_table ((ACPI_PHYSICAL_ADDRESS)
- acpi_gbl_XSDT->table_offset_entry[index],
+ ACPI_GET_ADDRESS (acpi_gbl_XSDT->table_offset_entry[index]),
table_ptr, &table_info);
/* Ignore a table that failed verification */
@@ -326,7 +326,8 @@ acpi_tb_get_all_tables (
* Get the DSDT (We know that the FADT is valid now)
*/
- status = acpi_tb_get_table (acpi_gbl_FADT->Xdsdt, table_ptr, &table_info);
+ status = acpi_tb_get_table ((ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xdsdt),
+ table_ptr, &table_info);
if (ACPI_FAILURE (status)) {
return (status);
}
@@ -472,13 +473,14 @@ acpi_tb_get_table_rsdt (
/* 0.71 RSDP has 64bit Rsdt address field */
physical_address = ((RSDP_DESCRIPTOR_REV071 *)acpi_gbl_RSDP)->rsdt_physical_address;
#else
- physical_address = acpi_gbl_RSDP->rsdt_physical_address;
+ physical_address = (ACPI_PHYSICAL_ADDRESS) acpi_gbl_RSDP->rsdt_physical_address;
#endif
table_signature = RSDT_SIG;
signature_length = sizeof (RSDT_SIG) -1;
}
else {
- physical_address = (ACPI_PHYSICAL_ADDRESS) acpi_gbl_RSDP->xsdt_physical_address;
+ physical_address = (ACPI_PHYSICAL_ADDRESS)
+ ACPI_GET_ADDRESS (acpi_gbl_RSDP->xsdt_physical_address);
table_signature = XSDT_SIG;
signature_length = sizeof (XSDT_SIG) -1;
}
@@ -586,7 +588,7 @@ acpi_tb_get_table_facs (
else {
/* Just map the physical memory to our address space */
- status = acpi_tb_map_acpi_table (acpi_gbl_FADT->Xfirmware_ctrl,
+ status = acpi_tb_map_acpi_table ((ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xfirmware_ctrl),
&size, &table_ptr);
if (ACPI_FAILURE(status)) {
return (status);
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c
index b3926a0e3..e753917b7 100644
--- a/drivers/acpi/tables/tbinstal.c
+++ b/drivers/acpi/tables/tbinstal.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: tbinstal - ACPI table installation and removal
- * $Revision: 34 $
+ * $Revision: 36 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c
index baae6fb4c..d89b1508c 100644
--- a/drivers/acpi/tables/tbutils.c
+++ b/drivers/acpi/tables/tbutils.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: tbutils - Table manipulation utilities
- * $Revision: 31 $
+ * $Revision: 33 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c
index ee9eba62a..98c99873c 100644
--- a/drivers/acpi/tables/tbxface.c
+++ b/drivers/acpi/tables/tbxface.c
@@ -2,12 +2,12 @@
*
* Module Name: tbxface - Public interfaces to the ACPI subsystem
* ACPI table oriented interfaces
- * $Revision: 32 $
+ * $Revision: 34 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c
index 4c31f1c37..606e8ad10 100644
--- a/drivers/acpi/tables/tbxfroot.c
+++ b/drivers/acpi/tables/tbxfroot.c
@@ -1,12 +1,12 @@
/******************************************************************************
*
* Module Name: tbxfroot - Find the root ACPI table (RSDT)
- * $Revision: 33 $
+ * $Revision: 35 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000 R. Byron Moore
+ * Copyright (C) 2000, 2001 R. Byron Moore
*
* 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
diff --git a/drivers/atm/Makefile b/drivers/atm/Makefile
index 2157f1570..5b602f9ba 100644
--- a/drivers/atm/Makefile
+++ b/drivers/atm/Makefile
@@ -46,7 +46,7 @@ ifeq ($(CONFIG_ATM_FORE200E_SBA),y)
endif
endif
-obj-$(CONFIG_ATM_FORE200E) += fore200e.o $(FORE200E_FW_OBJS)
+obj-$(CONFIG_ATM_FORE200E) += fore_200e.o
EXTRA_CFLAGS=-g
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 5e8dc19f9..d0aac4c7d 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -1820,7 +1820,6 @@ static int DAC960_BackMergeFunction(RequestQueue_T *RequestQueue,
Request->nr_segments < Controller->DriverScatterGatherLimit)
{
Request->nr_segments++;
- RequestQueue->elevator.nr_segments++;
return true;
}
return false;
@@ -1844,7 +1843,6 @@ static int DAC960_FrontMergeFunction(RequestQueue_T *RequestQueue,
Request->nr_segments < Controller->DriverScatterGatherLimit)
{
Request->nr_segments++;
- RequestQueue->elevator.nr_segments++;
return true;
}
return false;
@@ -1864,17 +1862,12 @@ static int DAC960_MergeRequestsFunction(RequestQueue_T *RequestQueue,
DAC960_Controller_T *Controller =
(DAC960_Controller_T *) RequestQueue->queuedata;
int TotalSegments = Request->nr_segments + NextRequest->nr_segments;
- int SameSegment = 0;
if (Request->bhtail->b_data + Request->bhtail->b_size
== NextRequest->bh->b_data)
- {
TotalSegments--;
- SameSegment = 1;
- }
if (TotalSegments > MaxSegments ||
TotalSegments > Controller->DriverScatterGatherLimit)
return false;
- RequestQueue->elevator.nr_segments -= SameSegment;
Request->nr_segments = TotalSegments;
return true;
}
@@ -2834,6 +2827,7 @@ static void DAC960_RequestFunction(RequestQueue_T *RequestQueue)
static inline void DAC960_ProcessCompletedBuffer(BufferHeader_T *BufferHeader,
boolean SuccessfulIO)
{
+ blk_finished_io(BufferHeader->b_size >> 9);
BufferHeader->b_end_io(BufferHeader, SuccessfulIO);
}
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 35afe2a7f..47937edcc 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1086,6 +1086,7 @@ static inline void complete_buffers( struct buffer_head *bh, int status)
{
xbh = bh->b_reqnext;
bh->b_reqnext = NULL;
+ blk_finished_io(bh->b_size >> 9);
bh->b_end_io(bh, status);
bh = xbh;
}
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index afbf60ddc..7016cfff4 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -140,23 +140,7 @@ static int ida_release(struct inode *inode, struct file *filep);
static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg);
static int ida_ctlr_ioctl(int ctlr, int dsk, ida_ioctl_t *io);
-static void do_ida_request(int i);
-/*
- * This is a hack. This driver eats a major number for each controller, and
- * sets blkdev[xxx].request_fn to each one of these so the real request
- * function knows what controller its working with.
- */
-#define DO_IDA_REQUEST(x) { do_ida_request(x); }
-
-static void do_ida_request0(request_queue_t * q) DO_IDA_REQUEST(0);
-static void do_ida_request1(request_queue_t * q) DO_IDA_REQUEST(1);
-static void do_ida_request2(request_queue_t * q) DO_IDA_REQUEST(2);
-static void do_ida_request3(request_queue_t * q) DO_IDA_REQUEST(3);
-static void do_ida_request4(request_queue_t * q) DO_IDA_REQUEST(4);
-static void do_ida_request5(request_queue_t * q) DO_IDA_REQUEST(5);
-static void do_ida_request6(request_queue_t * q) DO_IDA_REQUEST(6);
-static void do_ida_request7(request_queue_t * q) DO_IDA_REQUEST(7);
-
+static void do_ida_request(request_queue_t *q);
static void start_io(ctlr_info_t *h);
static inline void addQ(cmdlist_t **Qptr, cmdlist_t *c);
@@ -362,6 +346,47 @@ void cleanup_module(void)
}
#endif /* MODULE */
+static inline int cpq_new_segment(request_queue_t *q, struct request *rq,
+ int max_segments)
+{
+ if (rq->nr_segments < SG_MAX) {
+ rq->nr_segments++;
+ return 1;
+ }
+ return 0;
+}
+
+static int cpq_back_merge_fn(request_queue_t *q, struct request *rq,
+ struct buffer_head *bh, int max_segments)
+{
+ if (rq->bhtail->b_data + rq->bhtail->b_size == bh->b_data)
+ return 1;
+ return cpq_new_segment(q, rq, max_segments);
+}
+
+static int cpq_front_merge_fn(request_queue_t *q, struct request *rq,
+ struct buffer_head *bh, int max_segments)
+{
+ if (bh->b_data + bh->b_size == rq->bh->b_data)
+ return 1;
+ return cpq_new_segment(q, rq, max_segments);
+}
+
+static int cpq_merge_requests_fn(request_queue_t *q, struct request *rq,
+ struct request *nxt, int max_segments)
+{
+ int total_segments = rq->nr_segments + nxt->nr_segments;
+
+ if (rq->bhtail->b_data + rq->bhtail->b_size == nxt->bh->b_data)
+ total_segments--;
+
+ if (total_segments > SG_MAX)
+ return 0;
+
+ rq->nr_segments = total_segments;
+ return 1;
+}
+
/*
* This is it. Find all the controllers and register them. I really hate
* stealing all these major device numbers.
@@ -369,12 +394,7 @@ void cleanup_module(void)
*/
int __init cpqarray_init(void)
{
- void (*request_fns[MAX_CTLR])(request_queue_t *) = {
- do_ida_request0, do_ida_request1,
- do_ida_request2, do_ida_request3,
- do_ida_request4, do_ida_request5,
- do_ida_request6, do_ida_request7,
- };
+ request_queue_t *q;
int i,j;
int num_cntlrs_reg = 0;
@@ -495,16 +515,20 @@ int __init cpqarray_init(void)
hba[i]->access.set_intr_mask(hba[i], FIFO_NOT_EMPTY);
-
ida_procinit(i);
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR + i),
- request_fns[i]);
- blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR + i), 0);
+ q = BLK_DEFAULT_QUEUE(MAJOR_NR + i);
+ q->queuedata = hba[i];
+ blk_init_queue(q, do_ida_request);
+ blk_queue_headactive(q, 0);
blksize_size[MAJOR_NR+i] = ida_blocksizes + (i*256);
hardsect_size[MAJOR_NR+i] = ida_hardsizes + (i*256);
read_ahead[MAJOR_NR+i] = READ_AHEAD;
+ q->back_merge_fn = cpq_back_merge_fn;
+ q->front_merge_fn = cpq_front_merge_fn;
+ q->merge_requests_fn = cpq_merge_requests_fn;
+
ida_gendisk[i].major = MAJOR_NR + i;
ida_gendisk[i].major_name = "ida";
ida_gendisk[i].minor_shift = NWD_SHIFT;
@@ -872,37 +896,30 @@ static inline cmdlist_t *removeQ(cmdlist_t **Qptr, cmdlist_t *c)
* are in here (either via the dummy do_ida_request functions or by being
* called from the interrupt handler
*/
-static void do_ida_request(int ctlr)
+static void do_ida_request(request_queue_t *q)
{
- ctlr_info_t *h = hba[ctlr];
+ ctlr_info_t *h = q->queuedata;
cmdlist_t *c;
int seg, sect;
char *lastdataend;
- struct list_head * queue_head;
+ struct list_head * queue_head = &q->queue_head;
struct buffer_head *bh;
struct request *creq;
- queue_head = &blk_dev[MAJOR_NR+ctlr].request_queue.queue_head;
-
- if (list_empty(queue_head))
- {
+ if (q->plugged || list_empty(queue_head)) {
start_io(h);
return;
}
creq = blkdev_entry_next_request(queue_head);
- if (creq->rq_status == RQ_INACTIVE)
- {
- start_io(h);
- return;
- }
-
+ if (creq->nr_segments > SG_MAX)
+ BUG();
- if (ctlr != MAJOR(creq->rq_dev)-MAJOR_NR ||
- ctlr > nr_ctlr || h == NULL)
+ if (h->ctlr != MAJOR(creq->rq_dev)-MAJOR_NR || h->ctlr > nr_ctlr)
{
printk(KERN_WARNING "doreq cmd for %d, %x at %p\n",
- ctlr, creq->rq_dev, creq);
+ h->ctlr, creq->rq_dev, creq);
+ blkdev_dequeue_request(creq);
complete_buffers(creq->bh, 0);
start_io(h);
return;
@@ -916,12 +933,12 @@ static void do_ida_request(int ctlr)
bh = creq->bh;
- c->ctlr = ctlr;
+ c->ctlr = h->ctlr;
c->hdr.unit = MINOR(creq->rq_dev) >> NWD_SHIFT;
c->hdr.size = sizeof(rblk_t) >> 2;
c->size += sizeof(rblk_t);
- c->req.hdr.blk = ida[(ctlr<<CTLR_SHIFT) + MINOR(creq->rq_dev)].start_sect + creq->sector;
+ c->req.hdr.blk = ida[(h->ctlr<<CTLR_SHIFT) + MINOR(creq->rq_dev)].start_sect + creq->sector;
c->bh = bh;
DBGPX(
if (bh == NULL)
@@ -933,21 +950,16 @@ DBGPX(
sect = 0;
while(bh) {
sect += bh->b_size/512;
-DBGPX(
- if (bh->b_size % 512) {
- printk("Oh damn. %d+%d, size = %d\n", creq->sector, sect, bh->b_size);
- panic("b_size %% 512 != 0");
- }
-);
if (bh->b_data == lastdataend) {
c->req.sg[seg-1].size += bh->b_size;
lastdataend += bh->b_size;
} else {
+ if (seg == SG_MAX)
+ BUG();
c->req.sg[seg].size = bh->b_size;
c->req.sg[seg].addr = (__u32)virt_to_bus(bh->b_data);
lastdataend = bh->b_data + bh->b_size;
- if (++seg == SG_MAX)
- break;
+ seg++;
}
bh = bh->b_reqnext;
}
@@ -955,30 +967,24 @@ DBGPX( printk("Submitting %d sectors in %d segments\n", sect, seg); );
c->req.hdr.sg_cnt = seg;
c->req.hdr.blk_cnt = sect;
- creq->sector += sect;
- creq->nr_sectors -= sect;
-
- /* Ready the next request:
- * Fix up creq if we still have more buffers in the buffer chain, or
- * mark this request as done and ready the next one.
+ /*
+ * Since we control our own merging, we know that this request
+ * is now fully setup and there's nothing left.
*/
- if (creq->nr_sectors) {
-DBGPX(
- if (bh==NULL) {
- printk("sector=%d, nr_sectors=%d, sect=%d, seg=%d\n",
- creq->sector, creq->nr_sectors, sect, seg);
- panic("mother...");
- }
-);
- creq->bh = bh->b_reqnext;
- bh->b_reqnext = NULL;
-DBGPX( printk("More to do on same request %p\n", creq); );
- } else {
-DBGPX( printk("Done with %p\n", creq); );
- blkdev_dequeue_request(creq);
- end_that_request_last(creq);
+ if (creq->nr_sectors != sect) {
+ printk("ida: %ld != %d sectors\n", creq->nr_sectors, sect);
+ BUG();
}
+ blkdev_dequeue_request(creq);
+
+ /*
+ * ehh, we can't really end the request here since it's not
+ * even started yet. for now it shouldn't hurt though
+ */
+DBGPX( printk("Done with %p\n", creq); );
+ end_that_request_last(creq);
+
c->req.hdr.cmd = (creq->cmd == READ) ? IDA_READ : IDA_WRITE;
c->type = CMD_RWREQ;
@@ -1025,6 +1031,7 @@ static inline void complete_buffers(struct buffer_head *bh, int ok)
xbh = bh->b_reqnext;
bh->b_reqnext = NULL;
+ blk_finished_io(bh->b_size >> 9);
bh->b_end_io(bh, ok);
bh = xbh;
@@ -1072,7 +1079,6 @@ static void do_ida_intr(int irq, void *dev_id, struct pt_regs *regs)
unsigned long flags;
__u32 a,a1;
-
istat = h->access.intr_pending(h);
/* Is this interrupt for us? */
if (istat == 0)
@@ -1116,7 +1122,7 @@ static void do_ida_intr(int irq, void *dev_id, struct pt_regs *regs)
/*
* See if we can queue up some more IO
*/
- do_ida_request(h->ctlr);
+ do_ida_request(BLK_DEFAULT_QUEUE(MAJOR_NR + h->ctlr));
spin_unlock_irqrestore(&io_request_lock, flags);
}
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c
index 1200773c2..9917ad055 100644
--- a/drivers/block/elevator.c
+++ b/drivers/block/elevator.c
@@ -24,125 +24,115 @@
#include <linux/blkdev.h>
#include <linux/elevator.h>
#include <linux/blk.h>
+#include <linux/module.h>
#include <asm/uaccess.h>
-/*
- * Order ascending, but only allow a request to be skipped a certain
- * number of times
- */
-void elevator_linus(struct request *req, elevator_t *elevator,
- struct list_head *real_head,
- struct list_head *head, int orig_latency)
-{
- struct list_head *entry = real_head;
- struct request *tmp;
-
- req->elevator_sequence = orig_latency;
-
- while ((entry = entry->prev) != head) {
- tmp = blkdev_entry_to_request(entry);
- if (IN_ORDER(tmp, req))
- break;
- if (!tmp->elevator_sequence)
- break;
- tmp->elevator_sequence--;
- }
- list_add(&req->queue, entry);
-}
-
int elevator_linus_merge(request_queue_t *q, struct request **req,
+ struct list_head * head,
struct buffer_head *bh, int rw,
- int *max_sectors, int *max_segments)
+ int max_sectors, int max_segments)
{
- struct list_head *entry, *head = &q->queue_head;
+ struct list_head *entry = &q->queue_head;
unsigned int count = bh->b_size >> 9, ret = ELEVATOR_NO_MERGE;
- entry = head;
- if (q->head_active && !q->plugged)
- head = head->next;
-
while ((entry = entry->prev) != head) {
- struct request *__rq = *req = blkdev_entry_to_request(entry);
+ struct request *__rq = blkdev_entry_to_request(entry);
+
+ /*
+ * simply "aging" of requests in queue
+ */
+ if (__rq->elevator_sequence-- <= 0) {
+ *req = __rq;
+ break;
+ }
+
if (__rq->sem)
continue;
if (__rq->cmd != rw)
continue;
- if (__rq->nr_sectors + count > *max_sectors)
- continue;
if (__rq->rq_dev != bh->b_rdev)
continue;
+ if (__rq->nr_sectors + count > max_sectors)
+ continue;
+ if (__rq->elevator_sequence < count)
+ break;
if (__rq->sector + __rq->nr_sectors == bh->b_rsector) {
ret = ELEVATOR_BACK_MERGE;
+ *req = __rq;
break;
- }
- if (!__rq->elevator_sequence)
- break;
- if (__rq->sector - count == bh->b_rsector) {
- __rq->elevator_sequence--;
+ } else if (__rq->sector - count == bh->b_rsector) {
ret = ELEVATOR_FRONT_MERGE;
+ __rq->elevator_sequence -= count;
+ *req = __rq;
break;
- }
+ } else if (!*req && BHRQ_IN_ORDER(bh, __rq))
+ *req = __rq;
}
+ return ret;
+}
+
+void elevator_linus_merge_cleanup(request_queue_t *q, struct request *req, int count)
+{
+ struct list_head *entry = &req->queue, *head = &q->queue_head;
+
/*
* second pass scan of requests that got passed over, if any
*/
- if (ret != ELEVATOR_NO_MERGE && *req) {
- while ((entry = entry->next) != &q->queue_head) {
- struct request *tmp = blkdev_entry_to_request(entry);
- tmp->elevator_sequence--;
- }
+ while ((entry = entry->next) != head) {
+ struct request *tmp = blkdev_entry_to_request(entry);
+ tmp->elevator_sequence -= count;
}
-
- return ret;
}
-/*
- * No request sorting, just add it to the back of the list
- */
-void elevator_noop(struct request *req, elevator_t *elevator,
- struct list_head *real_head, struct list_head *head,
- int orig_latency)
+void elevator_linus_merge_req(struct request *req, struct request *next)
{
- list_add_tail(&req->queue, real_head);
+ if (next->elevator_sequence < req->elevator_sequence)
+ req->elevator_sequence = next->elevator_sequence;
}
/*
- * See if we can find a request that is buffer can be coalesced with.
+ * See if we can find a request that this buffer can be coalesced with.
*/
int elevator_noop_merge(request_queue_t *q, struct request **req,
+ struct list_head * head,
struct buffer_head *bh, int rw,
- int *max_sectors, int *max_segments)
+ int max_sectors, int max_segments)
{
- struct list_head *entry, *head = &q->queue_head;
+ struct list_head *entry;
unsigned int count = bh->b_size >> 9;
- if (q->head_active && !q->plugged)
- head = head->next;
+ if (list_empty(&q->queue_head))
+ return ELEVATOR_NO_MERGE;
- entry = head;
+ entry = &q->queue_head;
while ((entry = entry->prev) != head) {
- struct request *__rq = *req = blkdev_entry_to_request(entry);
- if (__rq->sem)
- continue;
+ struct request *__rq = blkdev_entry_to_request(entry);
+
if (__rq->cmd != rw)
continue;
- if (__rq->nr_sectors + count > *max_sectors)
- continue;
if (__rq->rq_dev != bh->b_rdev)
continue;
- if (__rq->sector + __rq->nr_sectors == bh->b_rsector)
+ if (__rq->nr_sectors + count > max_sectors)
+ continue;
+ if (__rq->sem)
+ continue;
+ if (__rq->sector + __rq->nr_sectors == bh->b_rsector) {
+ *req = __rq;
return ELEVATOR_BACK_MERGE;
- if (__rq->sector - count == bh->b_rsector)
+ } else if (__rq->sector - count == bh->b_rsector) {
+ *req = __rq;
return ELEVATOR_FRONT_MERGE;
+ }
}
+
+ *req = blkdev_entry_to_request(q->queue_head.prev);
return ELEVATOR_NO_MERGE;
}
-/*
- * The noop "elevator" does not do any accounting
- */
-void elevator_noop_dequeue(struct request *req) {}
+void elevator_noop_merge_cleanup(request_queue_t *q, struct request *req, int count) {}
+
+void elevator_noop_merge_req(struct request *req, struct request *next) {}
int blkelvget_ioctl(elevator_t * elevator, blkelv_ioctl_arg_t * arg)
{
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index ef71dddc7..836a89f1e 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -19,6 +19,7 @@
#include <linux/config.h>
#include <linux/locks.h>
#include <linux/mm.h>
+#include <linux/swap.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
@@ -38,8 +39,6 @@
extern int mac_floppy_init(void);
#endif
-extern int lvm_init(void);
-
/*
* For the allocated request tables
*/
@@ -118,6 +117,19 @@ int * max_readahead[MAX_BLKDEV];
*/
int * max_sectors[MAX_BLKDEV];
+/*
+ * queued sectors for all devices, used to make sure we don't fill all
+ * of memory with locked buffers
+ */
+atomic_t queued_sectors;
+
+/*
+ * high and low watermark for above
+ */
+static int high_queued_sectors, low_queued_sectors;
+static int batch_requests, queue_nr_requests;
+static DECLARE_WAIT_QUEUE_HEAD(blk_buffers_wait);
+
static inline int get_max_sectors(kdev_t dev)
{
if (!max_sectors[MAJOR(dev)])
@@ -125,7 +137,7 @@ static inline int get_max_sectors(kdev_t dev)
return max_sectors[MAJOR(dev)][MINOR(dev)];
}
-static inline request_queue_t *__blk_get_queue(kdev_t dev)
+inline request_queue_t *__blk_get_queue(kdev_t dev)
{
struct blk_dev_struct *bdev = blk_dev + MAJOR(dev);
@@ -153,17 +165,14 @@ request_queue_t *blk_get_queue(kdev_t dev)
static int __blk_cleanup_queue(struct list_head *head)
{
- struct list_head *entry;
struct request *rq;
int i = 0;
if (list_empty(head))
return 0;
- entry = head->next;
do {
- rq = list_entry(entry, struct request, table);
- entry = entry->next;
+ rq = list_entry(head->next, struct request, table);
list_del(&rq->table);
kmem_cache_free(request_cachep, rq);
i++;
@@ -188,10 +197,12 @@ static int __blk_cleanup_queue(struct list_head *head)
**/
void blk_cleanup_queue(request_queue_t * q)
{
- int count = QUEUE_NR_REQUESTS;
+ int count = queue_nr_requests;
count -= __blk_cleanup_queue(&q->request_freelist[READ]);
count -= __blk_cleanup_queue(&q->request_freelist[WRITE]);
+ count -= __blk_cleanup_queue(&q->pending_freelist[READ]);
+ count -= __blk_cleanup_queue(&q->pending_freelist[WRITE]);
if (count)
printk("blk_cleanup_queue: leaked requests (%d)\n", count);
@@ -290,7 +301,6 @@ static inline int ll_new_segment(request_queue_t *q, struct request *req, int ma
{
if (req->nr_segments < max_segments) {
req->nr_segments++;
- q->elevator.nr_segments++;
return 1;
}
return 0;
@@ -316,18 +326,13 @@ static int ll_merge_requests_fn(request_queue_t *q, struct request *req,
struct request *next, int max_segments)
{
int total_segments = req->nr_segments + next->nr_segments;
- int same_segment;
- same_segment = 0;
- if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data) {
+ if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data)
total_segments--;
- same_segment = 1;
- }
if (total_segments > max_segments)
return 0;
- q->elevator.nr_segments -= same_segment;
req->nr_segments = total_segments;
return 1;
}
@@ -364,7 +369,7 @@ static inline void __generic_unplug_device(request_queue_t *q)
}
}
-static void generic_unplug_device(void *data)
+void generic_unplug_device(void *data)
{
request_queue_t *q = (request_queue_t *) data;
unsigned long flags;
@@ -379,19 +384,24 @@ static void blk_init_free_list(request_queue_t *q)
struct request *rq;
int i;
+ INIT_LIST_HEAD(&q->request_freelist[READ]);
+ INIT_LIST_HEAD(&q->request_freelist[WRITE]);
+ INIT_LIST_HEAD(&q->pending_freelist[READ]);
+ INIT_LIST_HEAD(&q->pending_freelist[WRITE]);
+ q->pending_free[READ] = q->pending_free[WRITE] = 0;
+
/*
- * Divide requests in half between read and write. This used to
- * be a 2/3 advantage for reads, but now reads can steal from
- * the write free list.
+ * Divide requests in half between read and write
*/
- for (i = 0; i < QUEUE_NR_REQUESTS; i++) {
+ for (i = 0; i < queue_nr_requests; i++) {
rq = kmem_cache_alloc(request_cachep, SLAB_KERNEL);
+ memset(rq, 0, sizeof(struct request));
rq->rq_status = RQ_INACTIVE;
list_add(&rq->table, &q->request_freelist[i & 1]);
}
init_waitqueue_head(&q->wait_for_request);
- spin_lock_init(&q->request_lock);
+ spin_lock_init(&q->queue_lock);
}
static int __make_request(request_queue_t * q, int rw, struct buffer_head * bh);
@@ -426,14 +436,12 @@ static int __make_request(request_queue_t * q, int rw, struct buffer_head * bh);
* blk_queue_headactive().
*
* Note:
- * blk_init_queue() must be paired with a blk_cleanup-queue() call
+ * blk_init_queue() must be paired with a blk_cleanup_queue() call
* when the block device is deactivated (such as at module unload).
**/
void blk_init_queue(request_queue_t * q, request_fn_proc * rfn)
{
INIT_LIST_HEAD(&q->queue_head);
- INIT_LIST_HEAD(&q->request_freelist[READ]);
- INIT_LIST_HEAD(&q->request_freelist[WRITE]);
elevator_init(&q->elevator, ELEVATOR_LINUS);
blk_init_free_list(q);
q->request_fn = rfn;
@@ -455,7 +463,6 @@ void blk_init_queue(request_queue_t * q, request_fn_proc * rfn)
q->head_active = 1;
}
-
#define blkdev_free_rq(list) list_entry((list)->next, struct request, table);
/*
* Get a free request. io_request_lock must be held and interrupts
@@ -463,37 +470,16 @@ void blk_init_queue(request_queue_t * q, request_fn_proc * rfn)
*/
static inline struct request *get_request(request_queue_t *q, int rw)
{
- struct list_head *list = &q->request_freelist[rw];
- struct request *rq;
-
- /*
- * Reads get preferential treatment and are allowed to steal
- * from the write free list if necessary.
- */
- if (!list_empty(list)) {
- rq = blkdev_free_rq(list);
- goto got_rq;
- }
+ struct request *rq = NULL;
- /*
- * if the WRITE list is non-empty, we know that rw is READ
- * and that the READ list is empty. allow reads to 'steal'
- * from the WRITE list.
- */
- if (!list_empty(&q->request_freelist[WRITE])) {
- list = &q->request_freelist[WRITE];
- rq = blkdev_free_rq(list);
- goto got_rq;
+ if (!list_empty(&q->request_freelist[rw])) {
+ rq = blkdev_free_rq(&q->request_freelist[rw]);
+ list_del(&rq->table);
+ rq->rq_status = RQ_ACTIVE;
+ rq->special = NULL;
+ rq->q = q;
}
- return NULL;
-
-got_rq:
- list_del(&rq->table);
- rq->free_list = list;
- rq->rq_status = RQ_ACTIVE;
- rq->special = NULL;
- rq->q = q;
return rq;
}
@@ -581,40 +567,42 @@ inline void drive_stat_acct (kdev_t dev, int rw,
/*
* add-request adds a request to the linked list.
- * It disables interrupts (acquires the request spinlock) so that it can muck
- * with the request-lists in peace. Thus it should be called with no spinlocks
- * held.
+ * io_request_lock is held and interrupts disabled, as we muck with the
+ * request queue list.
*
* By this point, req->cmd is always either READ/WRITE, never READA,
* which is important for drive_stat_acct() above.
*/
-
static inline void add_request(request_queue_t * q, struct request * req,
- struct list_head *head, int lat)
+ struct list_head *insert_here)
{
int major;
drive_stat_acct(req->rq_dev, req->cmd, req->nr_sectors, 1);
+ if (!q->plugged && q->head_active && insert_here == &q->queue_head) {
+ spin_unlock_irq(&io_request_lock);
+ BUG();
+ }
+
/*
- * let selected elevator insert the request
+ * elevator indicated where it wants this request to be
+ * inserted at elevator_merge time
*/
- q->elevator.elevator_fn(req, &q->elevator, &q->queue_head, head, lat);
-
- /*
- * FIXME(eric) I don't understand why there is a need for this
- * special case code. It clearly doesn't fit any more with
- * the new queueing architecture, and it got added in 2.3.10.
- * I am leaving this in here until I hear back from the COMPAQ
- * people.
- */
+ list_add(&req->queue, insert_here);
+
major = MAJOR(req->rq_dev);
- if (major >= COMPAQ_SMART2_MAJOR+0 && major <= COMPAQ_SMART2_MAJOR+7)
- (q->request_fn)(q);
- if (major >= COMPAQ_CISS_MAJOR+0 && major <= COMPAQ_CISS_MAJOR+7)
- (q->request_fn)(q);
if (major >= DAC960_MAJOR+0 && major <= DAC960_MAJOR+7)
- (q->request_fn)(q);
+ q->request_fn(q);
+}
+
+void inline blk_refill_freelist(request_queue_t *q, int rw)
+{
+ if (q->pending_free[rw]) {
+ list_splice(&q->pending_freelist[rw], &q->request_freelist[rw]);
+ INIT_LIST_HEAD(&q->pending_freelist[rw]);
+ q->pending_free[rw] = 0;
+ }
}
/*
@@ -622,15 +610,34 @@ static inline void add_request(request_queue_t * q, struct request * req,
*/
void inline blkdev_release_request(struct request *req)
{
+ request_queue_t *q = req->q;
+ int rw = req->cmd;
+
req->rq_status = RQ_INACTIVE;
+ req->q = NULL;
/*
- * Request may not have originated from ll_rw_blk
+ * Request may not have originated from ll_rw_blk. if not,
+ * asumme it has free buffers and check waiters
*/
- if (req->free_list) {
- list_add(&req->table, req->free_list);
- req->free_list = NULL;
- wake_up(&req->q->wait_for_request);
+ if (q) {
+ /*
+ * we've released enough buffers to start I/O again
+ */
+ if (waitqueue_active(&blk_buffers_wait)
+ && atomic_read(&queued_sectors) < low_queued_sectors)
+ wake_up(&blk_buffers_wait);
+
+ /*
+ * Add to pending free list and batch wakeups
+ */
+ list_add(&req->table, &q->pending_freelist[rw]);
+
+ if (++q->pending_free[rw] >= batch_requests) {
+ int wake_up = q->pending_free[rw];
+ blk_refill_freelist(q, rw);
+ wake_up_nr(&q->wait_for_request, wake_up);
+ }
}
}
@@ -658,9 +665,10 @@ static void attempt_merge(request_queue_t * q,
* will have been updated to the appropriate number,
* and we shouldn't do it here too.
*/
- if(!(q->merge_requests_fn)(q, req, next, max_segments))
+ if (!q->merge_requests_fn(q, req, next, max_segments))
return;
+ q->elevator.elevator_merge_req_fn(req, next);
req->bhtail->b_reqnext = next->bh;
req->bhtail = next->bhtail;
req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors;
@@ -699,7 +707,7 @@ static int __make_request(request_queue_t * q, int rw,
int max_segments = MAX_SEGMENTS;
struct request * req = NULL, *freereq = NULL;
int rw_ahead, max_sectors, el_ret;
- struct list_head *head;
+ struct list_head *head, *insert_here;
int latency;
elevator_t *elevator = &q->elevator;
@@ -713,6 +721,7 @@ static int __make_request(request_queue_t * q, int rw,
rw = READ; /* drop into READ */
case READ:
case WRITE:
+ latency = elevator_request_latency(elevator, rw);
break;
default:
BUG();
@@ -741,38 +750,33 @@ static int __make_request(request_queue_t * q, int rw,
*/
max_sectors = get_max_sectors(bh->b_rdev);
- latency = elevator_request_latency(elevator, rw);
-
+again:
+ head = &q->queue_head;
/*
* Now we acquire the request spinlock, we have to be mega careful
* not to schedule or do something nonatomic
*/
-again:
spin_lock_irq(&io_request_lock);
- /*
- * skip first entry, for devices with active queue head
- */
- head = &q->queue_head;
- if (q->head_active && !q->plugged)
- head = head->next;
-
+ insert_here = head->prev;
if (list_empty(head)) {
q->plug_device_fn(q, bh->b_rdev); /* is atomic */
goto get_rq;
- }
+ } else if (q->head_active && !q->plugged)
+ head = head->next;
- el_ret = elevator->elevator_merge_fn(q, &req, bh, rw,
- &max_sectors, &max_segments);
+ el_ret = elevator->elevator_merge_fn(q, &req, head, bh, rw,
+ max_sectors, max_segments);
switch (el_ret) {
case ELEVATOR_BACK_MERGE:
if (!q->back_merge_fn(q, req, bh, max_segments))
break;
+ elevator->elevator_merge_cleanup_fn(q, req, count);
req->bhtail->b_reqnext = bh;
req->bhtail = bh;
req->nr_sectors = req->hard_nr_sectors += count;
- req->e = elevator;
+ blk_started_io(count);
drive_stat_acct(req->rq_dev, req->cmd, count, 0);
attempt_back_merge(q, req, max_sectors, max_segments);
goto out;
@@ -780,20 +784,29 @@ again:
case ELEVATOR_FRONT_MERGE:
if (!q->front_merge_fn(q, req, bh, max_segments))
break;
+ elevator->elevator_merge_cleanup_fn(q, req, count);
bh->b_reqnext = req->bh;
req->bh = bh;
req->buffer = bh->b_data;
req->current_nr_sectors = count;
req->sector = req->hard_sector = sector;
req->nr_sectors = req->hard_nr_sectors += count;
- req->e = elevator;
+ blk_started_io(count);
drive_stat_acct(req->rq_dev, req->cmd, count, 0);
attempt_front_merge(q, head, req, max_sectors, max_segments);
goto out;
+
/*
* elevator says don't/can't merge. get new request
*/
case ELEVATOR_NO_MERGE:
+ /*
+ * use elevator hints as to where to insert the
+ * request. if no hints, just add it to the back
+ * of the queue
+ */
+ if (req)
+ insert_here = &req->queue;
break;
default:
@@ -802,10 +815,9 @@ again:
}
/*
- * Grab a free request from the freelist. Read first try their
- * own queue - if that is empty, we steal from the write list.
- * Writes must block if the write list is empty, and read aheads
- * are not crucial.
+ * Grab a free request from the freelist - if that is empty, check
+ * if we are doing read ahead and abort instead of blocking for
+ * a free slot.
*/
get_rq:
if (freereq) {
@@ -821,6 +833,7 @@ get_rq:
}
/* fill up the request-info, and add it to the queue */
+ req->elevator_sequence = latency;
req->cmd = rw;
req->errors = 0;
req->hard_sector = req->sector = sector;
@@ -833,13 +846,13 @@ get_rq:
req->bh = bh;
req->bhtail = bh;
req->rq_dev = bh->b_rdev;
- req->e = elevator;
- add_request(q, req, head, latency);
+ blk_started_io(count);
+ add_request(q, req, insert_here);
out:
- if (!q->plugged)
- (q->request_fn)(q);
if (freereq)
blkdev_release_request(freereq);
+ if (!q->plugged)
+ q->request_fn(q);
spin_unlock_irq(&io_request_lock);
return 0;
end_io:
@@ -886,13 +899,13 @@ void generic_make_request (int rw, struct buffer_head * bh)
int major = MAJOR(bh->b_rdev);
request_queue_t *q;
- if (!bh->b_end_io) BUG();
+ if (!bh->b_end_io)
+ BUG();
+
if (blk_size[major]) {
unsigned long maxsector = (blk_size[major][MINOR(bh->b_rdev)] << 1) + 1;
- unsigned int sector, count;
-
- count = bh->b_size >> 9;
- sector = bh->b_rsector;
+ unsigned long sector = bh->b_rsector;
+ unsigned int count = bh->b_size >> 9;
if (maxsector < count || maxsector - count < sector) {
bh->b_state &= (1 << BH_Lock) | (1 << BH_Mapped);
@@ -903,7 +916,7 @@ void generic_make_request (int rw, struct buffer_head * bh)
when mounting a device. */
printk(KERN_INFO
"attempt to access beyond end of device\n");
- printk(KERN_INFO "%s: rw=%d, want=%d, limit=%d\n",
+ printk(KERN_INFO "%s: rw=%d, want=%ld, limit=%d\n",
kdevname(bh->b_rdev), rw,
(sector + count)>>1,
blk_size[major][MINOR(bh->b_rdev)]);
@@ -930,15 +943,13 @@ void generic_make_request (int rw, struct buffer_head * bh)
buffer_IO_error(bh);
break;
}
-
- }
- while (q->make_request_fn(q, rw, bh));
+ } while (q->make_request_fn(q, rw, bh));
}
/**
* submit_bh: submit a buffer_head to the block device later for I/O
- * @rw: whether to %READ or %WRITE, or mayve to %READA (read ahead)
+ * @rw: whether to %READ or %WRITE, or maybe to %READA (read ahead)
* @bh: The &struct buffer_head which describes the I/O
*
* submit_bh() is very similar in purpose to generic_make_request(), and
@@ -961,7 +972,7 @@ void submit_bh(int rw, struct buffer_head * bh)
* further remap this.
*/
bh->b_rdev = bh->b_dev;
- bh->b_rsector = bh->b_blocknr * (bh->b_size>>9);
+ bh->b_rsector = bh->b_blocknr * (bh->b_size >> 9);
generic_make_request(rw, bh);
@@ -1021,6 +1032,9 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bhs[])
int correct_size;
int i;
+ if (!nr)
+ return;
+
major = MAJOR(bhs[0]->b_dev);
/* Determine correct block size for this device. */
@@ -1033,9 +1047,8 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bhs[])
/* Verify requested block sizes. */
for (i = 0; i < nr; i++) {
- struct buffer_head *bh;
- bh = bhs[i];
- if (bh->b_size != correct_size) {
+ struct buffer_head *bh = bhs[i];
+ if (bh->b_size % correct_size) {
printk(KERN_NOTICE "ll_rw_block: device %s: "
"only %d-char blocks implemented (%u)\n",
kdevname(bhs[0]->b_dev),
@@ -1051,8 +1064,17 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bhs[])
}
for (i = 0; i < nr; i++) {
- struct buffer_head *bh;
- bh = bhs[i];
+ struct buffer_head *bh = bhs[i];
+
+ /*
+ * don't lock any more buffers if we are above the high
+ * water mark. instead start I/O on the queued stuff.
+ */
+ if (atomic_read(&queued_sectors) >= high_queued_sectors) {
+ run_task_queue(&tq_disk);
+ wait_event(blk_buffers_wait,
+ atomic_read(&queued_sectors) < low_queued_sectors);
+ }
/* Only one thread can actually submit the I/O. */
if (test_and_set_bit(BH_Lock, &bh->b_state))
@@ -1096,12 +1118,25 @@ sorry:
extern int stram_device_init (void);
#endif
-/*
- * First step of what used to be end_request
+
+/**
+ * end_that_request_first - end I/O on one buffer.
+ * @req: the request being processed
+ * @uptodate: 0 for I/O error
+ * @name: the name printed for an I/O error
*
- * 0 means continue with end_that_request_last,
- * 1 means we are done
- */
+ * Description:
+ * Ends I/O on the first buffer attached to @req, and sets it up
+ * for the next buffer_head (if any) in the cluster.
+ *
+ * Return:
+ * 0 - we are done with this request, call end_that_request_last()
+ * 1 - still buffers pending for this request
+ *
+ * Caveat:
+ * Drivers implementing their own end_request handling must call
+ * blk_finished_io() appropriately.
+ **/
int end_that_request_first (struct request *req, int uptodate, char *name)
{
@@ -1115,6 +1150,7 @@ int end_that_request_first (struct request *req, int uptodate, char *name)
if ((bh = req->bh) != NULL) {
nsect = bh->b_size >> 9;
+ blk_finished_io(nsect);
req->bh = bh->b_reqnext;
bh->b_reqnext = NULL;
bh->b_end_io(bh, uptodate);
@@ -1138,19 +1174,18 @@ int end_that_request_first (struct request *req, int uptodate, char *name)
void end_that_request_last(struct request *req)
{
- if (req->e) {
- printk("end_that_request_last called with non-dequeued req\n");
- BUG();
- }
if (req->sem != NULL)
up(req->sem);
blkdev_release_request(req);
}
+#define MB(kb) ((kb) << 10)
+
int __init blk_dev_init(void)
{
struct blk_dev_struct *dev;
+ int total_ram;
request_cachep = kmem_cache_create("blkdev_requests",
sizeof(struct request),
@@ -1165,6 +1200,44 @@ int __init blk_dev_init(void)
memset(ro_bits,0,sizeof(ro_bits));
memset(max_readahead, 0, sizeof(max_readahead));
memset(max_sectors, 0, sizeof(max_sectors));
+
+ atomic_set(&queued_sectors, 0);
+ total_ram = nr_free_pages() << (PAGE_SHIFT - 10);
+
+ /*
+ * Try to keep 128MB max hysteris. If not possible,
+ * use half of RAM
+ */
+ high_queued_sectors = (total_ram * 2) / 3;
+ low_queued_sectors = high_queued_sectors / 3;
+ if (high_queued_sectors - low_queued_sectors > MB(128))
+ low_queued_sectors = high_queued_sectors - MB(128);
+
+
+ /*
+ * make it sectors (512b)
+ */
+ high_queued_sectors <<= 1;
+ low_queued_sectors <<= 1;
+
+ /*
+ * Scale free request slots per queue too
+ */
+ total_ram = (total_ram + MB(32) - 1) & ~(MB(32) - 1);
+ if ((queue_nr_requests = total_ram >> 9) > QUEUE_NR_REQUESTS)
+ queue_nr_requests = QUEUE_NR_REQUESTS;
+
+ /*
+ * adjust batch frees according to queue length, with upper limit
+ */
+ if ((batch_requests = queue_nr_requests >> 3) > 32)
+ batch_requests = 32;
+
+ printk("block: queued sectors max/low %dkB/%dkB, %d slots per queue\n",
+ high_queued_sectors / 2,
+ low_queued_sectors / 2,
+ queue_nr_requests);
+
#ifdef CONFIG_AMIGA_Z2RAM
z2_init();
#endif
@@ -1268,9 +1341,6 @@ int __init blk_dev_init(void)
#ifdef CONFIG_SUN_JSFLASH
jsfd_init();
#endif
-#ifdef CONFIG_BLK_DEV_LVM
- lvm_init();
-#endif
return 0;
};
@@ -1279,9 +1349,12 @@ EXPORT_SYMBOL(end_that_request_first);
EXPORT_SYMBOL(end_that_request_last);
EXPORT_SYMBOL(blk_init_queue);
EXPORT_SYMBOL(blk_get_queue);
+EXPORT_SYMBOL(__blk_get_queue);
EXPORT_SYMBOL(blk_cleanup_queue);
EXPORT_SYMBOL(blk_queue_headactive);
EXPORT_SYMBOL(blk_queue_pluggable);
EXPORT_SYMBOL(blk_queue_make_request);
EXPORT_SYMBOL(generic_make_request);
EXPORT_SYMBOL(blkdev_release_request);
+EXPORT_SYMBOL(generic_unplug_device);
+EXPORT_SYMBOL(queued_sectors);
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 9b1ff3a32..172acadbe 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -392,7 +392,6 @@ static inline int pd_new_segment(request_queue_t *q, struct request *req, int ma
if (req->nr_segments < max_segments) {
req->nr_segments++;
- q->elevator.nr_segments++;
return 1;
}
return 0;
@@ -432,7 +431,6 @@ static int pd_merge_requests_fn(request_queue_t *q, struct request *req,
if (total_segments > max_segments)
return 0;
- q->elevator.nr_segments -= same_segment;
req->nr_segments = total_segments;
return 1;
}
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index 53f6ca3df..b71703f9b 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -346,7 +346,6 @@ static inline int pf_new_segment(request_queue_t *q, struct request *req, int ma
if (req->nr_segments < max_segments) {
req->nr_segments++;
- q->elevator.nr_segments++;
return 1;
}
return 0;
@@ -386,7 +385,6 @@ static int pf_merge_requests_fn(request_queue_t *q, struct request *req,
if (total_segments > max_segments)
return 0;
- q->elevator.nr_segments -= same_segment;
req->nr_segments = total_segments;
return 1;
}
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 1e555da55..cafe72afd 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -295,11 +295,11 @@ MODULE_PARM(check_media_type, "i");
/* These are used to simplify getting data in from and back to user land */
#define IOCTL_IN(arg, type, in) \
- if (copy_from_user(&in, (type *) arg, sizeof in)) \
+ if (copy_from_user(&(in), (type *) (arg), sizeof (in))) \
return -EFAULT;
#define IOCTL_OUT(arg, type, out) \
- if (copy_to_user((type *) arg, &out, sizeof out)) \
+ if (copy_to_user((type *) (arg), &(out), sizeof (out))) \
return -EFAULT;
/* The (cdo->capability & ~cdi->mask & CDC_XXX) construct was used in
diff --git a/drivers/char/agp/agpgart_be.c b/drivers/char/agp/agpgart_be.c
index 942142832..ccd53dacc 100644
--- a/drivers/char/agp/agpgart_be.c
+++ b/drivers/char/agp/agpgart_be.c
@@ -1384,9 +1384,11 @@ static void via_cleanup(void)
aper_size_info_8 *previous_size;
previous_size = A_SIZE_8(agp_bridge.previous_size);
- pci_write_config_dword(agp_bridge.dev, VIA_ATTBASE, 0);
pci_write_config_byte(agp_bridge.dev, VIA_APSIZE,
previous_size->size_value);
+ /* Do not disable by writing 0 to VIA_ATTBASE, it screws things up
+ * during reinitialization.
+ */
}
static void via_tlbflush(agp_memory * mem)
@@ -2373,9 +2375,10 @@ static int __init agp_find_supported_device(void)
if (i810_dev == NULL) {
printk(KERN_ERR PFX "agpgart: Detected an "
"Intel i815, but could not find the"
- " secondary device.\n");
- agp_bridge.type = NOT_SUPPORTED;
- return -ENODEV;
+ " secondary device.\n"
+ "Assuming user has added an external AGP"
+ " card\n");
+ break;
}
printk(KERN_INFO PFX "agpgart: Detected an Intel i815 "
"Chipset.\n");
diff --git a/drivers/char/drm/Config.in b/drivers/char/drm/Config.in
index c69d37db5..6d7649eb0 100644
--- a/drivers/char/drm/Config.in
+++ b/drivers/char/drm/Config.in
@@ -9,7 +9,8 @@ bool 'Direct Rendering Manager (XFree86 DRI support)' CONFIG_DRM
if [ "$CONFIG_DRM" != "n" ]; then
tristate ' 3dfx Banshee/Voodoo3+' CONFIG_DRM_TDFX
tristate ' 3dlabs GMX 2000' CONFIG_DRM_GAMMA
- tristate ' ATI Rage 128' CONFIG_DRM_R128
+ dep_tristate ' ATI Rage 128' CONFIG_DRM_R128 $CONFIG_AGP
+ dep_tristate ' ATI Radeon' CONFIG_DRM_RADEON $CONFIG_AGP
dep_tristate ' Intel I810' CONFIG_DRM_I810 $CONFIG_AGP
dep_tristate ' Matrox g200/g400' CONFIG_DRM_MGA $CONFIG_AGP
fi
diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile
index d25e33d47..41017340b 100644
--- a/drivers/char/drm/Makefile
+++ b/drivers/char/drm/Makefile
@@ -42,16 +42,18 @@ else
endif
endif
-gamma-objs := gamma_drv.o gamma_dma.o
-tdfx-objs := tdfx_drv.o tdfx_context.o
-r128-objs := r128_drv.o r128_cce.o r128_context.o r128_bufs.o r128_state.o
-ffb-objs := ffb_drv.o ffb_context.o
-mga-objs := mga_drv.o mga_dma.o mga_context.o mga_bufs.o mga_state.o
-i810-objs := i810_drv.o i810_dma.o i810_context.o i810_bufs.o
+gamma-objs := gamma_drv.o gamma_dma.o
+tdfx-objs := tdfx_drv.o tdfx_context.o
+r128-objs := r128_drv.o r128_cce.o r128_context.o r128_bufs.o r128_state.o
+ffb-objs := ffb_drv.o ffb_context.o
+mga-objs := mga_drv.o mga_dma.o mga_context.o mga_bufs.o mga_state.o
+i810-objs := i810_drv.o i810_dma.o i810_context.o i810_bufs.o
+radeon-objs := radeon_drv.o radeon_cp.o radeon_context.o radeon_bufs.o radeon_state.o
obj-$(CONFIG_DRM_GAMMA) += gamma.o
obj-$(CONFIG_DRM_TDFX) += tdfx.o
obj-$(CONFIG_DRM_R128) += r128.o
+obj-$(CONFIG_DRM_RADEON)+= radeon.o
obj-$(CONFIG_DRM_FFB) += ffb.o
obj-$(CONFIG_DRM_MGA) += mga.o
obj-$(CONFIG_DRM_I810) += i810.o
@@ -96,5 +98,8 @@ i810.o: $(i810-objs) $(lib)
r128.o: $(r128-objs) $(lib)
$(LD) -r -o $@ $(r128-objs) $(lib)
+radeon.o: $(radeon-objs) $(lib)
+ $(LD) -r -o $@ $(radeon-objs) $(lib)
+
ffb.o: $(ffb-objs) $(lib)
$(LD) -r -o $@ $(ffb-objs) $(lib)
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
index aeecca77b..101556540 100644
--- a/drivers/char/drm/drm.h
+++ b/drivers/char/drm/drm.h
@@ -83,6 +83,7 @@ typedef struct drm_clip_rect {
#include "mga_drm.h"
#include "i810_drm.h"
#include "r128_drm.h"
+#include "radeon_drm.h"
#ifdef CONFIG_DRM_SIS
#include "sis_drm.h"
#endif
@@ -298,100 +299,116 @@ typedef struct drm_agp_info {
unsigned short id_device;
} drm_agp_info_t;
-#define DRM_IOCTL_BASE 'd'
-#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
-#define DRM_IOR(nr,size) _IOR(DRM_IOCTL_BASE,nr,size)
-#define DRM_IOW(nr,size) _IOW(DRM_IOCTL_BASE,nr,size)
-#define DRM_IOWR(nr,size) _IOWR(DRM_IOCTL_BASE,nr,size)
-
-
-#define DRM_IOCTL_VERSION DRM_IOWR(0x00, drm_version_t)
-#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm_unique_t)
-#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, drm_auth_t)
-#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, drm_irq_busid_t)
-
-#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t)
-#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, drm_auth_t)
-#define DRM_IOCTL_BLOCK DRM_IOWR(0x12, drm_block_t)
-#define DRM_IOCTL_UNBLOCK DRM_IOWR(0x13, drm_block_t)
-#define DRM_IOCTL_CONTROL DRM_IOW( 0x14, drm_control_t)
-#define DRM_IOCTL_ADD_MAP DRM_IOWR(0x15, drm_map_t)
-#define DRM_IOCTL_ADD_BUFS DRM_IOWR(0x16, drm_buf_desc_t)
-#define DRM_IOCTL_MARK_BUFS DRM_IOW( 0x17, drm_buf_desc_t)
-#define DRM_IOCTL_INFO_BUFS DRM_IOWR(0x18, drm_buf_info_t)
-#define DRM_IOCTL_MAP_BUFS DRM_IOWR(0x19, drm_buf_map_t)
-#define DRM_IOCTL_FREE_BUFS DRM_IOW( 0x1a, drm_buf_free_t)
-
-#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, drm_ctx_t)
-#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, drm_ctx_t)
-#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, drm_ctx_t)
-#define DRM_IOCTL_GET_CTX DRM_IOWR(0x23, drm_ctx_t)
-#define DRM_IOCTL_SWITCH_CTX DRM_IOW( 0x24, drm_ctx_t)
-#define DRM_IOCTL_NEW_CTX DRM_IOW( 0x25, drm_ctx_t)
-#define DRM_IOCTL_RES_CTX DRM_IOWR(0x26, drm_ctx_res_t)
-#define DRM_IOCTL_ADD_DRAW DRM_IOWR(0x27, drm_draw_t)
-#define DRM_IOCTL_RM_DRAW DRM_IOWR(0x28, drm_draw_t)
-#define DRM_IOCTL_DMA DRM_IOWR(0x29, drm_dma_t)
-#define DRM_IOCTL_LOCK DRM_IOW( 0x2a, drm_lock_t)
-#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, drm_lock_t)
-#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, drm_lock_t)
-
-#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30)
-#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31)
-#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, drm_agp_mode_t)
-#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, drm_agp_info_t)
-#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, drm_agp_buffer_t)
-#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, drm_agp_buffer_t)
-#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t)
-#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t)
+#define DRM_IOCTL_BASE 'd'
+#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
+#define DRM_IOR(nr,size) _IOR(DRM_IOCTL_BASE,nr,size)
+#define DRM_IOW(nr,size) _IOW(DRM_IOCTL_BASE,nr,size)
+#define DRM_IOWR(nr,size) _IOWR(DRM_IOCTL_BASE,nr,size)
+
+
+#define DRM_IOCTL_VERSION DRM_IOWR(0x00, drm_version_t)
+#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm_unique_t)
+#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, drm_auth_t)
+#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, drm_irq_busid_t)
+
+#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t)
+#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, drm_auth_t)
+#define DRM_IOCTL_BLOCK DRM_IOWR(0x12, drm_block_t)
+#define DRM_IOCTL_UNBLOCK DRM_IOWR(0x13, drm_block_t)
+#define DRM_IOCTL_CONTROL DRM_IOW( 0x14, drm_control_t)
+#define DRM_IOCTL_ADD_MAP DRM_IOWR(0x15, drm_map_t)
+#define DRM_IOCTL_ADD_BUFS DRM_IOWR(0x16, drm_buf_desc_t)
+#define DRM_IOCTL_MARK_BUFS DRM_IOW( 0x17, drm_buf_desc_t)
+#define DRM_IOCTL_INFO_BUFS DRM_IOWR(0x18, drm_buf_info_t)
+#define DRM_IOCTL_MAP_BUFS DRM_IOWR(0x19, drm_buf_map_t)
+#define DRM_IOCTL_FREE_BUFS DRM_IOW( 0x1a, drm_buf_free_t)
+
+#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, drm_ctx_t)
+#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, drm_ctx_t)
+#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, drm_ctx_t)
+#define DRM_IOCTL_GET_CTX DRM_IOWR(0x23, drm_ctx_t)
+#define DRM_IOCTL_SWITCH_CTX DRM_IOW( 0x24, drm_ctx_t)
+#define DRM_IOCTL_NEW_CTX DRM_IOW( 0x25, drm_ctx_t)
+#define DRM_IOCTL_RES_CTX DRM_IOWR(0x26, drm_ctx_res_t)
+#define DRM_IOCTL_ADD_DRAW DRM_IOWR(0x27, drm_draw_t)
+#define DRM_IOCTL_RM_DRAW DRM_IOWR(0x28, drm_draw_t)
+#define DRM_IOCTL_DMA DRM_IOWR(0x29, drm_dma_t)
+#define DRM_IOCTL_LOCK DRM_IOW( 0x2a, drm_lock_t)
+#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, drm_lock_t)
+#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, drm_lock_t)
+
+#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30)
+#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31)
+#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, drm_agp_mode_t)
+#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, drm_agp_info_t)
+#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, drm_agp_buffer_t)
+#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, drm_agp_buffer_t)
+#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t)
+#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t)
/* Mga specific ioctls */
-#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t)
-#define DRM_IOCTL_MGA_SWAP DRM_IOW( 0x41, drm_mga_swap_t)
-#define DRM_IOCTL_MGA_CLEAR DRM_IOW( 0x42, drm_mga_clear_t)
-#define DRM_IOCTL_MGA_ILOAD DRM_IOW( 0x43, drm_mga_iload_t)
-#define DRM_IOCTL_MGA_VERTEX DRM_IOW( 0x44, drm_mga_vertex_t)
-#define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x45, drm_lock_t )
-#define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t)
-#define DRM_IOCTL_MGA_BLIT DRM_IOW( 0x47, drm_mga_blit_t)
+#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t)
+#define DRM_IOCTL_MGA_SWAP DRM_IOW( 0x41, drm_mga_swap_t)
+#define DRM_IOCTL_MGA_CLEAR DRM_IOW( 0x42, drm_mga_clear_t)
+#define DRM_IOCTL_MGA_ILOAD DRM_IOW( 0x43, drm_mga_iload_t)
+#define DRM_IOCTL_MGA_VERTEX DRM_IOW( 0x44, drm_mga_vertex_t)
+#define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x45, drm_lock_t )
+#define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t)
+#define DRM_IOCTL_MGA_BLIT DRM_IOW( 0x47, drm_mga_blit_t)
/* I810 specific ioctls */
-#define DRM_IOCTL_I810_INIT DRM_IOW( 0x40, drm_i810_init_t)
-#define DRM_IOCTL_I810_VERTEX DRM_IOW( 0x41, drm_i810_vertex_t)
-#define DRM_IOCTL_I810_CLEAR DRM_IOW( 0x42, drm_i810_clear_t)
-#define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43)
-#define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44)
-#define DRM_IOCTL_I810_GETBUF DRM_IOWR(0x45, drm_i810_dma_t)
-#define DRM_IOCTL_I810_SWAP DRM_IO ( 0x46)
-#define DRM_IOCTL_I810_COPY DRM_IOW( 0x47, drm_i810_copy_t)
-#define DRM_IOCTL_I810_DOCOPY DRM_IO ( 0x48)
+#define DRM_IOCTL_I810_INIT DRM_IOW( 0x40, drm_i810_init_t)
+#define DRM_IOCTL_I810_VERTEX DRM_IOW( 0x41, drm_i810_vertex_t)
+#define DRM_IOCTL_I810_CLEAR DRM_IOW( 0x42, drm_i810_clear_t)
+#define DRM_IOCTL_I810_FLUSH DRM_IO( 0x43)
+#define DRM_IOCTL_I810_GETAGE DRM_IO( 0x44)
+#define DRM_IOCTL_I810_GETBUF DRM_IOWR(0x45, drm_i810_dma_t)
+#define DRM_IOCTL_I810_SWAP DRM_IO( 0x46)
+#define DRM_IOCTL_I810_COPY DRM_IOW( 0x47, drm_i810_copy_t)
+#define DRM_IOCTL_I810_DOCOPY DRM_IO( 0x48)
/* Rage 128 specific ioctls */
-#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t)
-#define DRM_IOCTL_R128_CCE_START DRM_IO( 0x41)
-#define DRM_IOCTL_R128_CCE_STOP DRM_IOW( 0x42, drm_r128_cce_stop_t)
-#define DRM_IOCTL_R128_CCE_RESET DRM_IO( 0x43)
-#define DRM_IOCTL_R128_CCE_IDLE DRM_IO( 0x44)
-#define DRM_IOCTL_R128_RESET DRM_IO( 0x46)
-#define DRM_IOCTL_R128_SWAP DRM_IO( 0x47)
-#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x48, drm_r128_clear_t)
-#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x49, drm_r128_vertex_t)
-#define DRM_IOCTL_R128_INDICES DRM_IOW( 0x4a, drm_r128_indices_t)
-#define DRM_IOCTL_R128_BLIT DRM_IOW( 0x4b, drm_r128_blit_t)
-#define DRM_IOCTL_R128_DEPTH DRM_IOW( 0x4c, drm_r128_depth_t)
-#define DRM_IOCTL_R128_STIPPLE DRM_IOW( 0x4d, drm_r128_stipple_t)
-#define DRM_IOCTL_R128_PACKET DRM_IOWR(0x4e, drm_r128_packet_t)
+#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t)
+#define DRM_IOCTL_R128_CCE_START DRM_IO( 0x41)
+#define DRM_IOCTL_R128_CCE_STOP DRM_IOW( 0x42, drm_r128_cce_stop_t)
+#define DRM_IOCTL_R128_CCE_RESET DRM_IO( 0x43)
+#define DRM_IOCTL_R128_CCE_IDLE DRM_IO( 0x44)
+#define DRM_IOCTL_R128_RESET DRM_IO( 0x46)
+#define DRM_IOCTL_R128_SWAP DRM_IO( 0x47)
+#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x48, drm_r128_clear_t)
+#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x49, drm_r128_vertex_t)
+#define DRM_IOCTL_R128_INDICES DRM_IOW( 0x4a, drm_r128_indices_t)
+#define DRM_IOCTL_R128_BLIT DRM_IOW( 0x4b, drm_r128_blit_t)
+#define DRM_IOCTL_R128_DEPTH DRM_IOW( 0x4c, drm_r128_depth_t)
+#define DRM_IOCTL_R128_STIPPLE DRM_IOW( 0x4d, drm_r128_stipple_t)
+#define DRM_IOCTL_R128_PACKET DRM_IOWR(0x4e, drm_r128_packet_t)
+
+/* Radeon specific ioctls */
+#define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( 0x40, drm_radeon_init_t)
+#define DRM_IOCTL_RADEON_CP_START DRM_IO( 0x41)
+#define DRM_IOCTL_RADEON_CP_STOP DRM_IOW( 0x42, drm_radeon_cp_stop_t)
+#define DRM_IOCTL_RADEON_CP_RESET DRM_IO( 0x43)
+#define DRM_IOCTL_RADEON_CP_IDLE DRM_IO( 0x44)
+#define DRM_IOCTL_RADEON_RESET DRM_IO( 0x45)
+#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( 0x46, drm_radeon_fullscreen_t)
+#define DRM_IOCTL_RADEON_SWAP DRM_IO( 0x47)
+#define DRM_IOCTL_RADEON_CLEAR DRM_IOW( 0x48, drm_radeon_clear_t)
+#define DRM_IOCTL_RADEON_VERTEX DRM_IOW( 0x49, drm_radeon_vertex_t)
+#define DRM_IOCTL_RADEON_INDICES DRM_IOW( 0x4a, drm_radeon_indices_t)
+#define DRM_IOCTL_RADEON_BLIT DRM_IOW( 0x4b, drm_radeon_blit_t)
+#define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( 0x4c, drm_radeon_stipple_t)
+#define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(0x4d, drm_radeon_indirect_t)
#ifdef CONFIG_DRM_SIS
/* SiS specific ioctls */
-#define SIS_IOCTL_FB_ALLOC DRM_IOWR( 0x44, drm_sis_mem_t)
-#define SIS_IOCTL_FB_FREE DRM_IOW( 0x45, drm_sis_mem_t)
-#define SIS_IOCTL_AGP_INIT DRM_IOWR( 0x53, drm_sis_agp_t)
-#define SIS_IOCTL_AGP_ALLOC DRM_IOWR( 0x54, drm_sis_mem_t)
-#define SIS_IOCTL_AGP_FREE DRM_IOW( 0x55, drm_sis_mem_t)
-#define SIS_IOCTL_FLIP DRM_IOW( 0x48, drm_sis_flip_t)
-#define SIS_IOCTL_FLIP_INIT DRM_IO( 0x49)
-#define SIS_IOCTL_FLIP_FINAL DRM_IO( 0x50)
+#define SIS_IOCTL_FB_ALLOC DRM_IOWR(0x44, drm_sis_mem_t)
+#define SIS_IOCTL_FB_FREE DRM_IOW( 0x45, drm_sis_mem_t)
+#define SIS_IOCTL_AGP_INIT DRM_IOWR(0x53, drm_sis_agp_t)
+#define SIS_IOCTL_AGP_ALLOC DRM_IOWR(0x54, drm_sis_mem_t)
+#define SIS_IOCTL_AGP_FREE DRM_IOW( 0x55, drm_sis_mem_t)
+#define SIS_IOCTL_FLIP DRM_IOW( 0x48, drm_sis_flip_t)
+#define SIS_IOCTL_FLIP_INIT DRM_IO( 0x49)
+#define SIS_IOCTL_FLIP_FINAL DRM_IO( 0x50)
#endif
#endif
diff --git a/drivers/char/drm/radeon_bufs.c b/drivers/char/drm/radeon_bufs.c
new file mode 100644
index 000000000..9a3093eb1
--- /dev/null
+++ b/drivers/char/drm/radeon_bufs.c
@@ -0,0 +1,298 @@
+/* radeon_bufs.c -- IOCTLs to manage buffers -*- linux-c -*-
+ *
+ * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Kevin E. Martin <martin@valinux.com>
+ * Rickard E. (Rik) Faith <faith@valinux.com>
+ * Jeff Hartmann <jhartmann@valinux.com>
+ *
+ */
+
+#define __NO_VERSION__
+#include <linux/config.h>
+#include "drmP.h"
+#include "radeon_drv.h"
+#include "linux/un.h"
+
+
+#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
+int radeon_addbufs_agp(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_desc_t request;
+ drm_buf_entry_t *entry;
+ drm_buf_t *buf;
+ unsigned long offset;
+ unsigned long agp_offset;
+ int count;
+ int order;
+ int size;
+ int alignment;
+ int page_order;
+ int total;
+ int byte_count;
+ int i;
+
+ if (!dma) return -EINVAL;
+
+ if (copy_from_user(&request, (drm_buf_desc_t *)arg, sizeof(request)))
+ return -EFAULT;
+
+ count = request.count;
+ order = drm_order(request.size);
+ size = 1 << order;
+
+ alignment = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size):size;
+ page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+ total = PAGE_SIZE << page_order;
+
+ byte_count = 0;
+ agp_offset = dev->agp->base + request.agp_start;
+
+ DRM_DEBUG("count: %d\n", count);
+ DRM_DEBUG("order: %d\n", order);
+ DRM_DEBUG("size: %d\n", size);
+ DRM_DEBUG("agp_offset: %ld\n", agp_offset);
+ DRM_DEBUG("alignment: %d\n", alignment);
+ DRM_DEBUG("page_order: %d\n", page_order);
+ DRM_DEBUG("total: %d\n", total);
+
+ if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
+ if (dev->queue_count) return -EBUSY; /* Not while in use */
+
+ spin_lock(&dev->count_lock);
+ if (dev->buf_use) {
+ spin_unlock(&dev->count_lock);
+ return -EBUSY;
+ }
+ atomic_inc(&dev->buf_alloc);
+ spin_unlock(&dev->count_lock);
+
+ down(&dev->struct_sem);
+ entry = &dma->bufs[order];
+ if (entry->buf_count) {
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM; /* May only call once for each order */
+ }
+
+ entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
+ DRM_MEM_BUFS);
+ if (!entry->buflist) {
+ up(&dev->struct_sem);
+ atomic_dec(&dev->buf_alloc);
+ return -ENOMEM;
+ }
+ memset(entry->buflist, 0, count * sizeof(*entry->buflist));
+
+ entry->buf_size = size;
+ entry->page_order = page_order;
+ offset = 0;
+
+ for (offset = 0;
+ entry->buf_count < count;
+ offset += alignment, ++entry->buf_count) {
+ buf = &entry->buflist[entry->buf_count];
+ buf->idx = dma->buf_count + entry->buf_count;
+ buf->total = alignment;
+ buf->order = order;
+ buf->used = 0;
+ buf->offset = (dma->byte_count + offset);
+ buf->address = (void *)(agp_offset + offset);
+ buf->next = NULL;
+ buf->waiting = 0;
+ buf->pending = 0;
+ init_waitqueue_head(&buf->dma_wait);
+ buf->pid = 0;
+
+ buf->dev_priv_size = sizeof(drm_radeon_buf_priv_t);
+ buf->dev_private = drm_alloc(sizeof(drm_radeon_buf_priv_t),
+ DRM_MEM_BUFS);
+ memset(buf->dev_private, 0, buf->dev_priv_size);
+
+#if DRM_DMA_HISTOGRAM
+ buf->time_queued = 0;
+ buf->time_dispatched = 0;
+ buf->time_completed = 0;
+ buf->time_freed = 0;
+#endif
+
+ byte_count += PAGE_SIZE << page_order;
+
+ DRM_DEBUG("buffer %d @ %p\n",
+ entry->buf_count, buf->address);
+ }
+
+ DRM_DEBUG("byte_count: %d\n", byte_count);
+
+ dma->buflist = drm_realloc(dma->buflist,
+ dma->buf_count * sizeof(*dma->buflist),
+ (dma->buf_count + entry->buf_count)
+ * sizeof(*dma->buflist),
+ DRM_MEM_BUFS);
+ for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
+ dma->buflist[i] = &entry->buflist[i - dma->buf_count];
+
+ dma->buf_count += entry->buf_count;
+ dma->byte_count += byte_count;
+
+ drm_freelist_create(&entry->freelist, entry->buf_count);
+ for (i = 0; i < entry->buf_count; i++) {
+ drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
+ }
+
+ up(&dev->struct_sem);
+
+ request.count = entry->buf_count;
+ request.size = size;
+
+ if (copy_to_user((drm_buf_desc_t *)arg, &request, sizeof(request)))
+ return -EFAULT;
+
+ dma->flags = _DRM_DMA_USE_AGP;
+
+ atomic_dec(&dev->buf_alloc);
+ return 0;
+}
+#endif
+
+int radeon_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_buf_desc_t request;
+
+ if (!dev_priv || dev_priv->is_pci) return -EINVAL;
+
+ if (copy_from_user(&request, (drm_buf_desc_t *)arg, sizeof(request)))
+ return -EFAULT;
+
+#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
+ if (request.flags & _DRM_AGP_BUFFER)
+ return radeon_addbufs_agp(inode, filp, cmd, arg);
+ else
+#endif
+ return -EINVAL;
+}
+
+int radeon_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ int retcode = 0;
+ const int zero = 0;
+ unsigned long virtual;
+ unsigned long address;
+ drm_buf_map_t request;
+ int i;
+
+ if (!dma || !dev_priv || dev_priv->is_pci) return -EINVAL;
+
+ DRM_DEBUG("\n");
+
+ spin_lock(&dev->count_lock);
+ if (atomic_read(&dev->buf_alloc)) {
+ spin_unlock(&dev->count_lock);
+ return -EBUSY;
+ }
+ ++dev->buf_use; /* Can't allocate more after this call */
+ spin_unlock(&dev->count_lock);
+
+ if (copy_from_user(&request, (drm_buf_map_t *)arg, sizeof(request)))
+ return -EFAULT;
+
+ if (request.count >= dma->buf_count) {
+ if (dma->flags & _DRM_DMA_USE_AGP) {
+ drm_map_t *map;
+
+ map = dev_priv->buffers;
+ if (!map) {
+ retcode = -EINVAL;
+ goto done;
+ }
+
+ down(&current->mm->mmap_sem);
+ virtual = do_mmap(filp, 0, map->size,
+ PROT_READ|PROT_WRITE,
+ MAP_SHARED,
+ (unsigned long)map->offset);
+ up(&current->mm->mmap_sem);
+ } else {
+ down(&current->mm->mmap_sem);
+ virtual = do_mmap(filp, 0, dma->byte_count,
+ PROT_READ|PROT_WRITE, MAP_SHARED, 0);
+ up(&current->mm->mmap_sem);
+ }
+ if (virtual > -1024UL) {
+ /* Real error */
+ retcode = (signed long)virtual;
+ goto done;
+ }
+ request.virtual = (void *)virtual;
+
+ for (i = 0; i < dma->buf_count; i++) {
+ if (copy_to_user(&request.list[i].idx,
+ &dma->buflist[i]->idx,
+ sizeof(request.list[0].idx))) {
+ retcode = -EFAULT;
+ goto done;
+ }
+ if (copy_to_user(&request.list[i].total,
+ &dma->buflist[i]->total,
+ sizeof(request.list[0].total))) {
+ retcode = -EFAULT;
+ goto done;
+ }
+ if (copy_to_user(&request.list[i].used,
+ &zero,
+ sizeof(zero))) {
+ retcode = -EFAULT;
+ goto done;
+ }
+ address = virtual + dma->buflist[i]->offset;
+ if (copy_to_user(&request.list[i].address,
+ &address,
+ sizeof(address))) {
+ retcode = -EFAULT;
+ goto done;
+ }
+ }
+ }
+ done:
+ request.count = dma->buf_count;
+ DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
+
+ if (copy_to_user((drm_buf_map_t *)arg, &request, sizeof(request)))
+ return -EFAULT;
+
+ return retcode;
+}
diff --git a/drivers/char/drm/radeon_context.c b/drivers/char/drm/radeon_context.c
new file mode 100644
index 000000000..e428dc22c
--- /dev/null
+++ b/drivers/char/drm/radeon_context.c
@@ -0,0 +1,215 @@
+/* radeon_context.c -- IOCTLs for Radeon contexts -*- linux-c -*-
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Kevin E. Martin <martin@valinux.com>
+ * Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+#include "radeon_drv.h"
+
+extern drm_ctx_t radeon_res_ctx;
+
+static int radeon_alloc_queue(drm_device_t *dev)
+{
+ return drm_ctxbitmap_next(dev);
+}
+
+int radeon_context_switch(drm_device_t *dev, int old, int new)
+{
+ char buf[64];
+
+ atomic_inc(&dev->total_ctx);
+
+ if (test_and_set_bit(0, &dev->context_flag)) {
+ DRM_ERROR("Reentering -- FIXME\n");
+ return -EBUSY;
+ }
+
+#if DRM_DMA_HISTOGRAM
+ dev->ctx_start = get_cycles();
+#endif
+
+ DRM_DEBUG("Context switch from %d to %d\n", old, new);
+
+ if (new == dev->last_context) {
+ clear_bit(0, &dev->context_flag);
+ return 0;
+ }
+
+ if (drm_flags & DRM_FLAG_NOCTX) {
+ radeon_context_switch_complete(dev, new);
+ } else {
+ sprintf(buf, "C %d %d\n", old, new);
+ drm_write_string(dev, buf);
+ }
+
+ return 0;
+}
+
+int radeon_context_switch_complete(drm_device_t *dev, int new)
+{
+ dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
+ dev->last_switch = jiffies;
+
+ if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ DRM_ERROR("Lock isn't held after context switch\n");
+ }
+
+ /* If a context switch is ever initiated
+ when the kernel holds the lock, release
+ that lock here. */
+#if DRM_DMA_HISTOGRAM
+ atomic_inc(&dev->histo.ctx[drm_histogram_slot(get_cycles()
+ - dev->ctx_start)]);
+
+#endif
+ clear_bit(0, &dev->context_flag);
+ wake_up(&dev->context_wait);
+
+ return 0;
+}
+
+
+int radeon_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_ctx_res_t res;
+ drm_ctx_t ctx;
+ int i;
+
+ DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
+ if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res)))
+ return -EFAULT;
+ if (res.count >= DRM_RESERVED_CONTEXTS) {
+ memset(&ctx, 0, sizeof(ctx));
+ for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
+ ctx.handle = i;
+ if (copy_to_user(&res.contexts[i], &i, sizeof(i)))
+ return -EFAULT;
+ }
+ }
+ res.count = DRM_RESERVED_CONTEXTS;
+ if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res)))
+ return -EFAULT;
+ return 0;
+}
+
+
+int radeon_addctx(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_ctx_t ctx;
+
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
+ if ((ctx.handle = radeon_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) {
+ /* Skip kernel's context and get a new one. */
+ ctx.handle = radeon_alloc_queue(dev);
+ }
+ DRM_DEBUG("%d\n", ctx.handle);
+ if (ctx.handle == -1) {
+ DRM_DEBUG("Not enough free contexts.\n");
+ /* Should this return -EBUSY instead? */
+ return -ENOMEM;
+ }
+
+ if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
+ return -EFAULT;
+ return 0;
+}
+
+int radeon_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_ctx_t ctx;
+
+ if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
+ return -EFAULT;
+ if (ctx.flags==_DRM_CONTEXT_PRESERVED)
+ radeon_res_ctx.handle=ctx.handle;
+ return 0;
+}
+
+int radeon_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_ctx_t ctx;
+
+ if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
+ return -EFAULT;
+ /* This is 0, because we don't hanlde any context flags */
+ ctx.flags = 0;
+ if (copy_to_user((drm_ctx_t*)arg, &ctx, sizeof(ctx)))
+ return -EFAULT;
+ return 0;
+}
+
+int radeon_switchctx(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_ctx_t ctx;
+
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
+ DRM_DEBUG("%d\n", ctx.handle);
+ return radeon_context_switch(dev, dev->last_context, ctx.handle);
+}
+
+int radeon_newctx(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_ctx_t ctx;
+
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
+ DRM_DEBUG("%d\n", ctx.handle);
+ radeon_context_switch_complete(dev, ctx.handle);
+
+ return 0;
+}
+
+int radeon_rmctx(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_ctx_t ctx;
+
+ if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+ return -EFAULT;
+ DRM_DEBUG("%d\n", ctx.handle);
+ drm_ctxbitmap_free(dev, ctx.handle);
+
+ return 0;
+}
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
new file mode 100644
index 000000000..5d662bc08
--- /dev/null
+++ b/drivers/char/drm/radeon_cp.c
@@ -0,0 +1,1314 @@
+/* radeon_cp.c -- CP support for Radeon -*- linux-c -*-
+ *
+ * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+#include "radeon_drv.h"
+
+#include <linux/interrupt.h> /* For task queue support */
+#include <linux/delay.h>
+
+#define RADEON_FIFO_DEBUG 0
+
+
+/* CP microcode (from ATI) */
+static u32 radeon_cp_microcode[][2] = {
+ { 0x21007000, 0000000000 },
+ { 0x20007000, 0000000000 },
+ { 0x000000b4, 0x00000004 },
+ { 0x000000b8, 0x00000004 },
+ { 0x6f5b4d4c, 0000000000 },
+ { 0x4c4c427f, 0000000000 },
+ { 0x5b568a92, 0000000000 },
+ { 0x4ca09c6d, 0000000000 },
+ { 0xad4c4c4c, 0000000000 },
+ { 0x4ce1af3d, 0000000000 },
+ { 0xd8afafaf, 0000000000 },
+ { 0xd64c4cdc, 0000000000 },
+ { 0x4cd10d10, 0000000000 },
+ { 0x000f0000, 0x00000016 },
+ { 0x362f242d, 0000000000 },
+ { 0x00000012, 0x00000004 },
+ { 0x000f0000, 0x00000016 },
+ { 0x362f282d, 0000000000 },
+ { 0x000380e7, 0x00000002 },
+ { 0x04002c97, 0x00000002 },
+ { 0x000f0001, 0x00000016 },
+ { 0x333a3730, 0000000000 },
+ { 0x000077ef, 0x00000002 },
+ { 0x00061000, 0x00000002 },
+ { 0x00000021, 0x0000001a },
+ { 0x00004000, 0x0000001e },
+ { 0x00061000, 0x00000002 },
+ { 0x00000021, 0x0000001a },
+ { 0x00004000, 0x0000001e },
+ { 0x00061000, 0x00000002 },
+ { 0x00000021, 0x0000001a },
+ { 0x00004000, 0x0000001e },
+ { 0x00000017, 0x00000004 },
+ { 0x0003802b, 0x00000002 },
+ { 0x040067e0, 0x00000002 },
+ { 0x00000017, 0x00000004 },
+ { 0x000077e0, 0x00000002 },
+ { 0x00065000, 0x00000002 },
+ { 0x000037e1, 0x00000002 },
+ { 0x040067e1, 0x00000006 },
+ { 0x000077e0, 0x00000002 },
+ { 0x000077e1, 0x00000002 },
+ { 0x000077e1, 0x00000006 },
+ { 0xffffffff, 0000000000 },
+ { 0x10000000, 0000000000 },
+ { 0x0003802b, 0x00000002 },
+ { 0x040067e0, 0x00000006 },
+ { 0x00007675, 0x00000002 },
+ { 0x00007676, 0x00000002 },
+ { 0x00007677, 0x00000002 },
+ { 0x00007678, 0x00000006 },
+ { 0x0003802c, 0x00000002 },
+ { 0x04002676, 0x00000002 },
+ { 0x00007677, 0x00000002 },
+ { 0x00007678, 0x00000006 },
+ { 0x0000002f, 0x00000018 },
+ { 0x0000002f, 0x00000018 },
+ { 0000000000, 0x00000006 },
+ { 0x00000030, 0x00000018 },
+ { 0x00000030, 0x00000018 },
+ { 0000000000, 0x00000006 },
+ { 0x01605000, 0x00000002 },
+ { 0x00065000, 0x00000002 },
+ { 0x00098000, 0x00000002 },
+ { 0x00061000, 0x00000002 },
+ { 0x64c0603e, 0x00000004 },
+ { 0x000380e6, 0x00000002 },
+ { 0x040025c5, 0x00000002 },
+ { 0x00080000, 0x00000016 },
+ { 0000000000, 0000000000 },
+ { 0x0400251d, 0x00000002 },
+ { 0x00007580, 0x00000002 },
+ { 0x00067581, 0x00000002 },
+ { 0x04002580, 0x00000002 },
+ { 0x00067581, 0x00000002 },
+ { 0x00000049, 0x00000004 },
+ { 0x00005000, 0000000000 },
+ { 0x000380e6, 0x00000002 },
+ { 0x040025c5, 0x00000002 },
+ { 0x00061000, 0x00000002 },
+ { 0x0000750e, 0x00000002 },
+ { 0x00019000, 0x00000002 },
+ { 0x00011055, 0x00000014 },
+ { 0x00000055, 0x00000012 },
+ { 0x0400250f, 0x00000002 },
+ { 0x0000504f, 0x00000004 },
+ { 0x000380e6, 0x00000002 },
+ { 0x040025c5, 0x00000002 },
+ { 0x00007565, 0x00000002 },
+ { 0x00007566, 0x00000002 },
+ { 0x00000058, 0x00000004 },
+ { 0x000380e6, 0x00000002 },
+ { 0x040025c5, 0x00000002 },
+ { 0x01e655b4, 0x00000002 },
+ { 0x4401b0e4, 0x00000002 },
+ { 0x01c110e4, 0x00000002 },
+ { 0x26667066, 0x00000018 },
+ { 0x040c2565, 0x00000002 },
+ { 0x00000066, 0x00000018 },
+ { 0x04002564, 0x00000002 },
+ { 0x00007566, 0x00000002 },
+ { 0x0000005d, 0x00000004 },
+ { 0x00401069, 0x00000008 },
+ { 0x00101000, 0x00000002 },
+ { 0x000d80ff, 0x00000002 },
+ { 0x0080006c, 0x00000008 },
+ { 0x000f9000, 0x00000002 },
+ { 0x000e00ff, 0x00000002 },
+ { 0000000000, 0x00000006 },
+ { 0x0000008f, 0x00000018 },
+ { 0x0000005b, 0x00000004 },
+ { 0x000380e6, 0x00000002 },
+ { 0x040025c5, 0x00000002 },
+ { 0x00007576, 0x00000002 },
+ { 0x00065000, 0x00000002 },
+ { 0x00009000, 0x00000002 },
+ { 0x00041000, 0x00000002 },
+ { 0x0c00350e, 0x00000002 },
+ { 0x00049000, 0x00000002 },
+ { 0x00051000, 0x00000002 },
+ { 0x01e785f8, 0x00000002 },
+ { 0x00200000, 0x00000002 },
+ { 0x0060007e, 0x0000000c },
+ { 0x00007563, 0x00000002 },
+ { 0x006075f0, 0x00000021 },
+ { 0x20007073, 0x00000004 },
+ { 0x00005073, 0x00000004 },
+ { 0x000380e6, 0x00000002 },
+ { 0x040025c5, 0x00000002 },
+ { 0x00007576, 0x00000002 },
+ { 0x00007577, 0x00000002 },
+ { 0x0000750e, 0x00000002 },
+ { 0x0000750f, 0x00000002 },
+ { 0x00a05000, 0x00000002 },
+ { 0x00600083, 0x0000000c },
+ { 0x006075f0, 0x00000021 },
+ { 0x000075f8, 0x00000002 },
+ { 0x00000083, 0x00000004 },
+ { 0x000a750e, 0x00000002 },
+ { 0x000380e6, 0x00000002 },
+ { 0x040025c5, 0x00000002 },
+ { 0x0020750f, 0x00000002 },
+ { 0x00600086, 0x00000004 },
+ { 0x00007570, 0x00000002 },
+ { 0x00007571, 0x00000002 },
+ { 0x00007572, 0x00000006 },
+ { 0x000380e6, 0x00000002 },
+ { 0x040025c5, 0x00000002 },
+ { 0x00005000, 0x00000002 },
+ { 0x00a05000, 0x00000002 },
+ { 0x00007568, 0x00000002 },
+ { 0x00061000, 0x00000002 },
+ { 0x00000095, 0x0000000c },
+ { 0x00058000, 0x00000002 },
+ { 0x0c607562, 0x00000002 },
+ { 0x00000097, 0x00000004 },
+ { 0x000380e6, 0x00000002 },
+ { 0x040025c5, 0x00000002 },
+ { 0x00600096, 0x00000004 },
+ { 0x400070e5, 0000000000 },
+ { 0x000380e6, 0x00000002 },
+ { 0x040025c5, 0x00000002 },
+ { 0x000380e5, 0x00000002 },
+ { 0x000000a8, 0x0000001c },
+ { 0x000650aa, 0x00000018 },
+ { 0x040025bb, 0x00000002 },
+ { 0x000610ab, 0x00000018 },
+ { 0x040075bc, 0000000000 },
+ { 0x000075bb, 0x00000002 },
+ { 0x000075bc, 0000000000 },
+ { 0x00090000, 0x00000006 },
+ { 0x00090000, 0x00000002 },
+ { 0x000d8002, 0x00000006 },
+ { 0x00007832, 0x00000002 },
+ { 0x00005000, 0x00000002 },
+ { 0x000380e7, 0x00000002 },
+ { 0x04002c97, 0x00000002 },
+ { 0x00007820, 0x00000002 },
+ { 0x00007821, 0x00000002 },
+ { 0x00007800, 0000000000 },
+ { 0x01200000, 0x00000002 },
+ { 0x20077000, 0x00000002 },
+ { 0x01200000, 0x00000002 },
+ { 0x20007000, 0x00000002 },
+ { 0x00061000, 0x00000002 },
+ { 0x0120751b, 0x00000002 },
+ { 0x8040750a, 0x00000002 },
+ { 0x8040750b, 0x00000002 },
+ { 0x00110000, 0x00000002 },
+ { 0x000380e5, 0x00000002 },
+ { 0x000000c6, 0x0000001c },
+ { 0x000610ab, 0x00000018 },
+ { 0x844075bd, 0x00000002 },
+ { 0x000610aa, 0x00000018 },
+ { 0x840075bb, 0x00000002 },
+ { 0x000610ab, 0x00000018 },
+ { 0x844075bc, 0x00000002 },
+ { 0x000000c9, 0x00000004 },
+ { 0x804075bd, 0x00000002 },
+ { 0x800075bb, 0x00000002 },
+ { 0x804075bc, 0x00000002 },
+ { 0x00108000, 0x00000002 },
+ { 0x01400000, 0x00000002 },
+ { 0x006000cd, 0x0000000c },
+ { 0x20c07000, 0x00000020 },
+ { 0x000000cf, 0x00000012 },
+ { 0x00800000, 0x00000006 },
+ { 0x0080751d, 0x00000006 },
+ { 0000000000, 0000000000 },
+ { 0x0000775c, 0x00000002 },
+ { 0x00a05000, 0x00000002 },
+ { 0x00661000, 0x00000002 },
+ { 0x0460275d, 0x00000020 },
+ { 0x00004000, 0000000000 },
+ { 0x01e00830, 0x00000002 },
+ { 0x21007000, 0000000000 },
+ { 0x6464614d, 0000000000 },
+ { 0x69687420, 0000000000 },
+ { 0x00000073, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0x00005000, 0x00000002 },
+ { 0x000380d0, 0x00000002 },
+ { 0x040025e0, 0x00000002 },
+ { 0x000075e1, 0000000000 },
+ { 0x00000001, 0000000000 },
+ { 0x000380e0, 0x00000002 },
+ { 0x04002394, 0x00000002 },
+ { 0x00005000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0x00000008, 0000000000 },
+ { 0x00000004, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+};
+
+
+#define DO_IOREMAP(_m) (_m)->handle = drm_ioremap((_m)->offset, (_m)->size)
+
+#define DO_IOREMAPFREE(_m) \
+ do { \
+ if ((_m)->handle && (_m)->size) \
+ drm_ioremapfree((_m)->handle, (_m)->size); \
+ } while (0)
+
+#define DO_FIND_MAP(_m, _o) \
+ do { \
+ int _i; \
+ for (_i = 0; _i < dev->map_count; _i++) { \
+ if (dev->maplist[_i]->offset == _o) { \
+ _m = dev->maplist[_i]; \
+ break; \
+ } \
+ } \
+ } while (0)
+
+
+int RADEON_READ_PLL(drm_device_t *dev, int addr)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+ RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f);
+ return RADEON_READ(RADEON_CLOCK_CNTL_DATA);
+}
+
+#if RADEON_FIFO_DEBUG
+static void radeon_status( drm_radeon_private_t *dev_priv )
+{
+ printk( "%s:\n", __FUNCTION__ );
+ printk( "RBBM_STATUS = 0x%08x\n",
+ (unsigned int)RADEON_READ( RADEON_RBBM_STATUS ) );
+ printk( "CP_RB_RTPR = 0x%08x\n",
+ (unsigned int)RADEON_READ( RADEON_CP_RB_RPTR ) );
+ printk( "CP_RB_WTPR = 0x%08x\n",
+ (unsigned int)RADEON_READ( RADEON_CP_RB_WPTR ) );
+}
+#endif
+
+
+/* ================================================================
+ * Engine, FIFO control
+ */
+
+static int radeon_do_pixcache_flush( drm_radeon_private_t *dev_priv )
+{
+ u32 tmp;
+ int i;
+
+ tmp = RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT );
+ tmp |= RADEON_RB2D_DC_FLUSH_ALL;
+ RADEON_WRITE( RADEON_RB2D_DSTCACHE_CTLSTAT, tmp );
+
+ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+ if ( !(RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT )
+ & RADEON_RB2D_DC_BUSY) ) {
+ return 0;
+ }
+ udelay( 1 );
+ }
+
+#if RADEON_FIFO_DEBUG
+ DRM_ERROR( "failed!\n" );
+ radeon_status( dev_priv );
+#endif
+ return -EBUSY;
+}
+
+static int radeon_do_wait_for_fifo( drm_radeon_private_t *dev_priv,
+ int entries )
+{
+ int i;
+
+ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+ int slots = ( RADEON_READ( RADEON_RBBM_STATUS )
+ & RADEON_RBBM_FIFOCNT_MASK );
+ if ( slots >= entries ) return 0;
+ udelay( 1 );
+ }
+
+#if RADEON_FIFO_DEBUG
+ DRM_ERROR( "failed!\n" );
+ radeon_status( dev_priv );
+#endif
+ return -EBUSY;
+}
+
+static int radeon_do_wait_for_idle( drm_radeon_private_t *dev_priv )
+{
+ int i, ret;
+
+ ret = radeon_do_wait_for_fifo( dev_priv, 64 );
+ if ( ret < 0 ) return ret;
+
+ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+ if ( !(RADEON_READ( RADEON_RBBM_STATUS )
+ & RADEON_RBBM_ACTIVE) ) {
+ radeon_do_pixcache_flush( dev_priv );
+ return 0;
+ }
+ udelay( 1 );
+ }
+
+#if RADEON_FIFO_DEBUG
+ DRM_ERROR( "failed!\n" );
+ radeon_status( dev_priv );
+#endif
+ return -EBUSY;
+}
+
+
+/* ================================================================
+ * CP control, initialization
+ */
+
+/* Load the microcode for the CP */
+static void radeon_cp_load_microcode( drm_radeon_private_t *dev_priv )
+{
+ int i;
+
+ radeon_do_wait_for_idle( dev_priv );
+
+ RADEON_WRITE( RADEON_CP_ME_RAM_ADDR, 0 );
+ for ( i = 0 ; i < 256 ; i++ ) {
+ RADEON_WRITE( RADEON_CP_ME_RAM_DATAH,
+ radeon_cp_microcode[i][1] );
+ RADEON_WRITE( RADEON_CP_ME_RAM_DATAL,
+ radeon_cp_microcode[i][0] );
+ }
+}
+
+/* Flush any pending commands to the CP. This should only be used just
+ * prior to a wait for idle, as it informs the engine that the command
+ * stream is ending.
+ */
+static void radeon_do_cp_flush( drm_radeon_private_t *dev_priv )
+{
+#if 0
+ u32 tmp;
+
+ tmp = RADEON_READ( RADEON_CP_RB_WPTR ) | (1 << 31);
+ RADEON_WRITE( RADEON_CP_RB_WPTR, tmp );
+#endif
+}
+
+/* Wait for the CP to go idle.
+ */
+int radeon_do_cp_idle( drm_radeon_private_t *dev_priv )
+{
+ RING_LOCALS;
+
+ BEGIN_RING( 6 );
+
+ RADEON_PURGE_CACHE();
+ RADEON_PURGE_ZCACHE();
+ RADEON_WAIT_UNTIL_IDLE();
+
+ ADVANCE_RING();
+
+ return radeon_do_wait_for_idle( dev_priv );
+}
+
+/* Start the Command Processor.
+ */
+static void radeon_do_cp_start( drm_radeon_private_t *dev_priv )
+{
+ RING_LOCALS;
+
+ radeon_do_wait_for_idle( dev_priv );
+
+ RADEON_WRITE( RADEON_CP_CSQ_CNTL, dev_priv->cp_mode );
+
+ dev_priv->cp_running = 1;
+
+ BEGIN_RING( 6 );
+
+ RADEON_PURGE_CACHE();
+ RADEON_PURGE_ZCACHE();
+ RADEON_WAIT_UNTIL_IDLE();
+
+ ADVANCE_RING();
+}
+
+/* Reset the Command Processor. This will not flush any pending
+ * commands, so you must wait for the CP command stream to complete
+ * before calling this routine.
+ */
+static void radeon_do_cp_reset( drm_radeon_private_t *dev_priv )
+{
+ u32 cur_read_ptr;
+
+ cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
+ RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
+ *dev_priv->ring.head = cur_read_ptr;
+ dev_priv->ring.tail = cur_read_ptr;
+}
+
+/* Stop the Command Processor. This will not flush any pending
+ * commands, so you must flush the command stream and wait for the CP
+ * to go idle before calling this routine.
+ */
+static void radeon_do_cp_stop( drm_radeon_private_t *dev_priv )
+{
+ RADEON_WRITE( RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS );
+
+ dev_priv->cp_running = 0;
+}
+
+/* Reset the engine. This will stop the CP if it is running.
+ */
+static int radeon_do_engine_reset( drm_device_t *dev )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ radeon_do_pixcache_flush( dev_priv );
+
+ clock_cntl_index = RADEON_READ( RADEON_CLOCK_CNTL_INDEX );
+ mclk_cntl = RADEON_READ_PLL( dev, RADEON_MCLK_CNTL );
+
+ /* FIXME: remove magic number here and in radeon ddx driver!!! */
+ RADEON_WRITE_PLL( RADEON_MCLK_CNTL, mclk_cntl | 0x003f00000 );
+
+ rbbm_soft_reset = RADEON_READ( RADEON_RBBM_SOFT_RESET );
+
+ RADEON_WRITE( RADEON_RBBM_SOFT_RESET, ( rbbm_soft_reset |
+ RADEON_SOFT_RESET_CP |
+ RADEON_SOFT_RESET_HI |
+ RADEON_SOFT_RESET_SE |
+ RADEON_SOFT_RESET_RE |
+ RADEON_SOFT_RESET_PP |
+ RADEON_SOFT_RESET_E2 |
+ RADEON_SOFT_RESET_RB |
+ RADEON_SOFT_RESET_HDP ) );
+ RADEON_READ( RADEON_RBBM_SOFT_RESET );
+ RADEON_WRITE( RADEON_RBBM_SOFT_RESET, ( rbbm_soft_reset &
+ ~( RADEON_SOFT_RESET_CP |
+ RADEON_SOFT_RESET_HI |
+ RADEON_SOFT_RESET_SE |
+ RADEON_SOFT_RESET_RE |
+ RADEON_SOFT_RESET_PP |
+ RADEON_SOFT_RESET_E2 |
+ RADEON_SOFT_RESET_RB |
+ RADEON_SOFT_RESET_HDP ) ) );
+ RADEON_READ( RADEON_RBBM_SOFT_RESET );
+
+
+ RADEON_WRITE_PLL( RADEON_MCLK_CNTL, mclk_cntl );
+ RADEON_WRITE( RADEON_CLOCK_CNTL_INDEX, clock_cntl_index );
+ RADEON_WRITE( RADEON_RBBM_SOFT_RESET, rbbm_soft_reset );
+
+ /* Reset the CP ring */
+ radeon_do_cp_reset( dev_priv );
+
+ /* The CP is no longer running after an engine reset */
+ dev_priv->cp_running = 0;
+
+ /* Reset any pending vertex, indirect buffers */
+ radeon_freelist_reset( dev );
+
+ return 0;
+}
+
+static void radeon_cp_init_ring_buffer( drm_device_t *dev )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ u32 ring_start, cur_read_ptr;
+ u32 tmp;
+
+ /* Initialize the memory controller */
+ RADEON_WRITE( RADEON_MC_FB_LOCATION,
+ (dev_priv->agp_vm_start - 1) & 0xffff0000 );
+ RADEON_WRITE( RADEON_MC_AGP_LOCATION,
+ (((dev_priv->agp_vm_start - 1 +
+ dev_priv->agp_size) & 0xffff0000) |
+ (dev_priv->agp_vm_start >> 16)) );
+
+ ring_start = (dev_priv->cp_ring->offset
+ - dev->agp->base
+ + dev_priv->agp_vm_start);
+
+ RADEON_WRITE( RADEON_CP_RB_BASE, ring_start );
+
+ /* Set the write pointer delay */
+ RADEON_WRITE( RADEON_CP_RB_WPTR_DELAY, 0 );
+
+ /* Initialize the ring buffer's read and write pointers */
+ cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
+ RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
+ *dev_priv->ring.head = cur_read_ptr;
+ dev_priv->ring.tail = cur_read_ptr;
+
+ RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, dev_priv->ring_rptr->offset );
+
+ /* Set ring buffer size */
+ RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw );
+
+ radeon_do_wait_for_idle( dev_priv );
+
+ /* Turn off PCI GART */
+ tmp = RADEON_READ( RADEON_AIC_CNTL ) & ~RADEON_PCIGART_TRANSLATE_EN;
+ RADEON_WRITE( RADEON_AIC_CNTL, tmp );
+
+ /* Turn on bus mastering */
+ tmp = RADEON_READ( RADEON_BUS_CNTL ) & ~RADEON_BUS_MASTER_DIS;
+ RADEON_WRITE( RADEON_BUS_CNTL, tmp );
+
+ /* Sync everything up */
+ RADEON_WRITE( RADEON_ISYNC_CNTL,
+ (RADEON_ISYNC_ANY2D_IDLE3D |
+ RADEON_ISYNC_ANY3D_IDLE2D |
+ RADEON_ISYNC_WAIT_IDLEGUI |
+ RADEON_ISYNC_CPSCRATCH_IDLEGUI) );
+}
+
+static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
+{
+ drm_radeon_private_t *dev_priv;
+ int i;
+
+ dev_priv = drm_alloc( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER );
+ if ( dev_priv == NULL )
+ return -ENOMEM;
+ dev->dev_private = (void *)dev_priv;
+
+ memset( dev_priv, 0, sizeof(drm_radeon_private_t) );
+
+ dev_priv->is_pci = init->is_pci;
+
+ /* We don't support PCI cards until PCI GART is implemented.
+ * Fail here so we can remove all checks for PCI cards around
+ * the CP ring code.
+ */
+ if ( dev_priv->is_pci ) {
+ drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
+ dev->dev_private = NULL;
+ return -EINVAL;
+ }
+
+ dev_priv->usec_timeout = init->usec_timeout;
+ if ( dev_priv->usec_timeout < 1 ||
+ dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) {
+ drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
+ dev->dev_private = NULL;
+ return -EINVAL;
+ }
+
+ dev_priv->cp_mode = init->cp_mode;
+
+ /* Simple idle check.
+ */
+ atomic_set( &dev_priv->idle_count, 0 );
+
+ /* We don't support anything other than bus-mastering ring mode,
+ * but the ring can be in either AGP or PCI space for the ring
+ * read pointer.
+ */
+ if ( ( init->cp_mode != RADEON_CSQ_PRIBM_INDDIS ) &&
+ ( init->cp_mode != RADEON_CSQ_PRIBM_INDBM ) ) {
+ drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
+ dev->dev_private = NULL;
+ return -EINVAL;
+ }
+
+ switch ( init->fb_bpp ) {
+ case 16:
+ dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565;
+ break;
+ case 32:
+ default:
+ dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
+ break;
+ }
+ dev_priv->front_offset = init->front_offset;
+ dev_priv->front_pitch = init->front_pitch;
+ dev_priv->back_offset = init->back_offset;
+ dev_priv->back_pitch = init->back_pitch;
+
+ switch ( init->depth_bpp ) {
+ case 16:
+ dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
+ break;
+ case 32:
+ default:
+ dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
+ break;
+ }
+ dev_priv->depth_offset = init->depth_offset;
+ dev_priv->depth_pitch = init->depth_pitch;
+
+ dev_priv->front_pitch_offset = (((dev_priv->front_pitch/64) << 22) |
+ (dev_priv->front_offset >> 10));
+ dev_priv->back_pitch_offset = (((dev_priv->back_pitch/64) << 22) |
+ (dev_priv->back_offset >> 10));
+ dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch/64) << 22) |
+ (dev_priv->depth_offset >> 10));
+
+ /* Hardware state for depth clears. Remove this if/when we no
+ * longer clear the depth buffer with a 3D rectangle. Hard-code
+ * all values to prevent unwanted 3D state from slipping through
+ * and screwing with the clear operation.
+ */
+ dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
+ RADEON_Z_ENABLE |
+ (dev_priv->color_fmt << 10) |
+ RADEON_ZBLOCK16);
+
+ dev_priv->depth_clear.rb3d_zstencilcntl = (dev_priv->depth_fmt |
+ RADEON_Z_TEST_ALWAYS |
+ RADEON_STENCIL_TEST_ALWAYS |
+ RADEON_STENCIL_S_FAIL_KEEP |
+ RADEON_STENCIL_ZPASS_KEEP |
+ RADEON_STENCIL_ZFAIL_KEEP |
+ RADEON_Z_WRITE_ENABLE);
+
+ dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW |
+ RADEON_BFACE_SOLID |
+ RADEON_FFACE_SOLID |
+ RADEON_FLAT_SHADE_VTX_LAST |
+
+ RADEON_DIFFUSE_SHADE_FLAT |
+ RADEON_ALPHA_SHADE_FLAT |
+ RADEON_SPECULAR_SHADE_FLAT |
+ RADEON_FOG_SHADE_FLAT |
+
+ RADEON_VTX_PIX_CENTER_OGL |
+ RADEON_ROUND_MODE_TRUNC |
+ RADEON_ROUND_PREC_8TH_PIX);
+
+ /* FIXME: We want multiple shared areas, including one shared
+ * only by the X Server and kernel module.
+ */
+ for ( i = 0 ; i < dev->map_count ; i++ ) {
+ if ( dev->maplist[i]->type == _DRM_SHM ) {
+ dev_priv->sarea = dev->maplist[i];
+ break;
+ }
+ }
+
+ DO_FIND_MAP( dev_priv->fb, init->fb_offset );
+ DO_FIND_MAP( dev_priv->mmio, init->mmio_offset );
+ DO_FIND_MAP( dev_priv->cp_ring, init->ring_offset );
+ DO_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
+ DO_FIND_MAP( dev_priv->buffers, init->buffers_offset );
+
+ if ( !dev_priv->is_pci ) {
+ DO_FIND_MAP( dev_priv->agp_textures,
+ init->agp_textures_offset );
+ }
+
+ dev_priv->sarea_priv =
+ (drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle +
+ init->sarea_priv_offset);
+
+ DO_IOREMAP( dev_priv->cp_ring );
+ DO_IOREMAP( dev_priv->ring_rptr );
+ DO_IOREMAP( dev_priv->buffers );
+#if 0
+ if ( !dev_priv->is_pci ) {
+ DO_IOREMAP( dev_priv->agp_textures );
+ }
+#endif
+
+ dev_priv->agp_size = init->agp_size;
+ dev_priv->agp_vm_start = RADEON_READ( RADEON_CONFIG_APER_SIZE );
+ dev_priv->agp_buffers_offset = (dev_priv->buffers->offset
+ - dev->agp->base
+ + dev_priv->agp_vm_start);
+
+ dev_priv->ring.head = ((__volatile__ u32 *)
+ dev_priv->ring_rptr->handle);
+
+ dev_priv->ring.start = (u32 *)dev_priv->cp_ring->handle;
+ dev_priv->ring.end = ((u32 *)dev_priv->cp_ring->handle
+ + init->ring_size / sizeof(u32));
+ dev_priv->ring.size = init->ring_size;
+ dev_priv->ring.size_l2qw = drm_order( init->ring_size / 8 );
+
+ dev_priv->ring.tail_mask =
+ (dev_priv->ring.size / sizeof(u32)) - 1;
+
+#if 0
+ /* Initialize the scratch register pointer. This will cause
+ * the scratch register values to be written out to memory
+ * whenever they are updated.
+ * FIXME: This doesn't quite work yet, so we're disabling it
+ * for the release.
+ */
+ RADEON_WRITE( RADEON_SCRATCH_ADDR, (dev_priv->ring_rptr->offset +
+ RADEON_SCRATCH_REG_OFFSET) );
+ RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 );
+#endif
+
+ dev_priv->scratch = ((__volatile__ u32 *)
+ dev_priv->ring_rptr->handle +
+ (RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));
+
+ dev_priv->sarea_priv->last_frame = 0;
+ RADEON_WRITE( RADEON_LAST_FRAME_REG,
+ dev_priv->sarea_priv->last_frame );
+
+ dev_priv->sarea_priv->last_dispatch = 0;
+ RADEON_WRITE( RADEON_LAST_DISPATCH_REG,
+ dev_priv->sarea_priv->last_dispatch );
+
+ dev_priv->sarea_priv->last_clear = 0;
+ RADEON_WRITE( RADEON_LAST_CLEAR_REG,
+ dev_priv->sarea_priv->last_clear );
+
+ radeon_cp_load_microcode( dev_priv );
+ radeon_cp_init_ring_buffer( dev );
+ radeon_do_engine_reset( dev );
+
+#if ROTATE_BUFS
+ dev_priv->last_buf = 0;
+#endif
+
+ return 0;
+}
+
+static int radeon_do_cleanup_cp( drm_device_t *dev )
+{
+ if ( dev->dev_private ) {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+ DO_IOREMAPFREE( dev_priv->cp_ring );
+ DO_IOREMAPFREE( dev_priv->ring_rptr );
+ DO_IOREMAPFREE( dev_priv->buffers );
+#if 0
+ if ( !dev_priv->is_pci ) {
+ DO_IOREMAPFREE( dev_priv->agp_textures );
+ }
+#endif
+
+ drm_free( dev->dev_private, sizeof(drm_radeon_private_t),
+ DRM_MEM_DRIVER );
+ dev->dev_private = NULL;
+ }
+
+ return 0;
+}
+
+int radeon_cp_init( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_radeon_init_t init;
+
+ if ( copy_from_user( &init, (drm_radeon_init_t *)arg, sizeof(init) ) )
+ return -EFAULT;
+
+ switch ( init.func ) {
+ case RADEON_INIT_CP:
+ return radeon_do_init_cp( dev, &init );
+ case RADEON_CLEANUP_CP:
+ return radeon_do_cleanup_cp( dev );
+ }
+
+ return -EINVAL;
+}
+
+int radeon_cp_start( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+ dev->lock.pid != current->pid ) {
+ DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+ if ( dev_priv->cp_running ) {
+ DRM_DEBUG( "%s while CP running\n", __FUNCTION__ );
+ return 0;
+ }
+ if ( dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS ) {
+ DRM_DEBUG( "%s called with bogus CP mode (%d)\n",
+ __FUNCTION__, dev_priv->cp_mode );
+ return 0;
+ }
+
+ radeon_do_cp_start( dev_priv );
+
+ return 0;
+}
+
+/* Stop the CP. The engine must have been idled before calling this
+ * routine.
+ */
+int radeon_cp_stop( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_cp_stop_t stop;
+ int ret;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+ dev->lock.pid != current->pid ) {
+ DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+
+ if ( copy_from_user( &stop, (drm_radeon_init_t *)arg, sizeof(stop) ) )
+ return -EFAULT;
+
+ /* Flush any pending CP commands. This ensures any outstanding
+ * commands are exectuted by the engine before we turn it off.
+ */
+ if ( stop.flush ) {
+ radeon_do_cp_flush( dev_priv );
+ }
+
+ /* If we fail to make the engine go idle, we return an error
+ * code so that the DRM ioctl wrapper can try again.
+ */
+ if ( stop.idle ) {
+ ret = radeon_do_cp_idle( dev_priv );
+ if ( ret < 0 ) return ret;
+ }
+
+ /* Finally, we can turn off the CP. If the engine isn't idle,
+ * we will get some dropped triangles as they won't be fully
+ * rendered before the CP is shut down.
+ */
+ radeon_do_cp_stop( dev_priv );
+
+ /* Reset the engine */
+ radeon_do_engine_reset( dev );
+
+ return 0;
+}
+
+/* Just reset the CP ring. Called as part of an X Server engine reset.
+ */
+int radeon_cp_reset( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+ dev->lock.pid != current->pid ) {
+ DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+ if ( !dev_priv ) {
+ DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+
+ radeon_do_cp_reset( dev_priv );
+
+ /* The CP is no longer running after an engine reset */
+ dev_priv->cp_running = 0;
+
+ return 0;
+}
+
+int radeon_cp_idle( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+ dev->lock.pid != current->pid ) {
+ DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+
+ return radeon_do_cp_idle( dev_priv );
+}
+
+int radeon_engine_reset( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+ dev->lock.pid != current->pid ) {
+ DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+
+ return radeon_do_engine_reset( dev );
+}
+
+
+/* ================================================================
+ * Fullscreen mode
+ */
+
+static int radeon_do_init_pageflip( drm_device_t *dev )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ dev_priv->crtc_offset = RADEON_READ( RADEON_CRTC_OFFSET );
+ dev_priv->crtc_offset_cntl = RADEON_READ( RADEON_CRTC_OFFSET_CNTL );
+
+ RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->front_offset );
+ RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL,
+ dev_priv->crtc_offset_cntl |
+ RADEON_CRTC_OFFSET_FLIP_CNTL );
+
+ dev_priv->page_flipping = 1;
+ dev_priv->current_page = 0;
+
+ return 0;
+}
+
+int radeon_do_cleanup_pageflip( drm_device_t *dev )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->crtc_offset );
+ RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl );
+
+ dev_priv->page_flipping = 0;
+ dev_priv->current_page = 0;
+
+ return 0;
+}
+
+int radeon_fullscreen( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_radeon_fullscreen_t fs;
+
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+ dev->lock.pid != current->pid ) {
+ DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+
+ if ( copy_from_user( &fs, (drm_radeon_fullscreen_t *)arg,
+ sizeof(fs) ) )
+ return -EFAULT;
+
+ switch ( fs.func ) {
+ case RADEON_INIT_FULLSCREEN:
+ return radeon_do_init_pageflip( dev );
+ case RADEON_CLEANUP_FULLSCREEN:
+ return radeon_do_cleanup_pageflip( dev );
+ }
+
+ return -EINVAL;
+}
+
+
+/* ================================================================
+ * Freelist management
+ */
+#define RADEON_BUFFER_USED 0xffffffff
+#define RADEON_BUFFER_FREE 0
+
+#if 0
+static int radeon_freelist_init( drm_device_t *dev )
+{
+ drm_device_dma_t *dma = dev->dma;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_buf_t *buf;
+ drm_radeon_buf_priv_t *buf_priv;
+ drm_radeon_freelist_t *entry;
+ int i;
+
+ dev_priv->head = drm_alloc( sizeof(drm_radeon_freelist_t),
+ DRM_MEM_DRIVER );
+ if ( dev_priv->head == NULL )
+ return -ENOMEM;
+
+ memset( dev_priv->head, 0, sizeof(drm_radeon_freelist_t) );
+ dev_priv->head->age = RADEON_BUFFER_USED;
+
+ for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ buf = dma->buflist[i];
+ buf_priv = buf->dev_private;
+
+ entry = drm_alloc( sizeof(drm_radeon_freelist_t),
+ DRM_MEM_DRIVER );
+ if ( !entry ) return -ENOMEM;
+
+ entry->age = RADEON_BUFFER_FREE;
+ entry->buf = buf;
+ entry->prev = dev_priv->head;
+ entry->next = dev_priv->head->next;
+ if ( !entry->next )
+ dev_priv->tail = entry;
+
+ buf_priv->discard = 0;
+ buf_priv->dispatched = 0;
+ buf_priv->list_entry = entry;
+
+ dev_priv->head->next = entry;
+
+ if ( dev_priv->head->next )
+ dev_priv->head->next->prev = entry;
+ }
+
+ return 0;
+
+}
+#endif
+
+drm_buf_t *radeon_freelist_get( drm_device_t *dev )
+{
+ drm_device_dma_t *dma = dev->dma;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_buf_priv_t *buf_priv;
+ drm_buf_t *buf;
+ int i, t;
+#if ROTATE_BUFS
+ int start;
+#endif
+
+ /* FIXME: Optimize -- use freelist code */
+
+ for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ buf = dma->buflist[i];
+ buf_priv = buf->dev_private;
+ if ( buf->pid == 0 ) {
+ DRM_DEBUG( " ret buf=%d last=%d pid=0\n",
+ buf->idx, dev_priv->last_buf );
+ return buf;
+ }
+ DRM_DEBUG( " skipping buf=%d pid=%d\n",
+ buf->idx, buf->pid );
+ }
+
+#if ROTATE_BUFS
+ if ( ++dev_priv->last_buf >= dma->buf_count )
+ dev_priv->last_buf = 0;
+ start = dev_priv->last_buf;
+#endif
+ for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
+#if 0
+ /* FIXME: Disable this for now */
+ u32 done_age = dev_priv->scratch[RADEON_LAST_DISPATCH];
+#else
+ u32 done_age = RADEON_READ( RADEON_LAST_DISPATCH_REG );
+#endif
+#if ROTATE_BUFS
+ for ( i = start ; i < dma->buf_count ; i++ ) {
+#else
+ for ( i = 0 ; i < dma->buf_count ; i++ ) {
+#endif
+ buf = dma->buflist[i];
+ buf_priv = buf->dev_private;
+ if ( buf->pending && buf_priv->age <= done_age ) {
+ /* The buffer has been processed, so it
+ * can now be used.
+ */
+ buf->pending = 0;
+ DRM_DEBUG( " ret buf=%d last=%d age=%d done=%d\n", buf->idx, dev_priv->last_buf, buf_priv->age, done_age );
+ return buf;
+ }
+ DRM_DEBUG( " skipping buf=%d age=%d done=%d\n",
+ buf->idx, buf_priv->age,
+ done_age );
+#if ROTATE_BUFS
+ start = 0;
+#endif
+ }
+ udelay( 1 );
+ }
+
+ DRM_ERROR( "returning NULL!\n" );
+ return NULL;
+}
+
+void radeon_freelist_reset( drm_device_t *dev )
+{
+ drm_device_dma_t *dma = dev->dma;
+#if ROTATE_BUFS
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+#endif
+ int i;
+
+#if ROTATE_BUFS
+ dev_priv->last_buf = 0;
+#endif
+ for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ drm_buf_t *buf = dma->buflist[i];
+ drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+ buf_priv->age = 0;
+ }
+}
+
+
+/* ================================================================
+ * CP command submission
+ */
+
+int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n )
+{
+ drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
+ int i;
+
+ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+ ring->space = *ring->head - ring->tail;
+ if ( ring->space <= 0 )
+ ring->space += ring->size;
+
+ if ( ring->space >= n )
+ return 0;
+
+ udelay( 1 );
+ }
+
+ /* FIXME: This return value is ignored in the BEGIN_RING macro! */
+ DRM_ERROR( "failed!\n" );
+ return -EBUSY;
+}
+
+void radeon_update_ring_snapshot( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
+
+ ring->space = *ring->head - ring->tail;
+ if ( ring->space == 0 )
+ atomic_inc( &dev_priv->idle_count );
+ if ( ring->space <= 0 )
+ ring->space += ring->size;
+}
+
+static int radeon_cp_get_buffers( drm_device_t *dev, drm_dma_t *d )
+{
+ int i;
+ drm_buf_t *buf;
+
+ for ( i = d->granted_count ; i < d->request_count ; i++ ) {
+ buf = radeon_freelist_get( dev );
+ if ( !buf ) return -EAGAIN;
+
+ buf->pid = current->pid;
+
+ if ( copy_to_user( &d->request_indices[i], &buf->idx,
+ sizeof(buf->idx) ) )
+ return -EFAULT;
+ if ( copy_to_user( &d->request_sizes[i], &buf->total,
+ sizeof(buf->total) ) )
+ return -EFAULT;
+
+ d->granted_count++;
+ }
+ return 0;
+}
+
+int radeon_cp_buffers( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_device_dma_t *dma = dev->dma;
+ int ret = 0;
+ drm_dma_t d;
+
+ if ( copy_from_user( &d, (drm_dma_t *) arg, sizeof(d) ) )
+ return -EFAULT;
+
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+ dev->lock.pid != current->pid ) {
+ DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+
+ /* Please don't send us buffers.
+ */
+ if ( d.send_count != 0 ) {
+ DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
+ current->pid, d.send_count );
+ return -EINVAL;
+ }
+
+ /* We'll send you buffers.
+ */
+ if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
+ DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
+ current->pid, d.request_count, dma->buf_count );
+ return -EINVAL;
+ }
+
+ d.granted_count = 0;
+
+ if ( d.request_count ) {
+ ret = radeon_cp_get_buffers( dev, &d );
+ }
+
+ if ( copy_to_user( (drm_dma_t *) arg, &d, sizeof(d) ) )
+ return -EFAULT;
+
+ return ret;
+}
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
new file mode 100644
index 000000000..c5f9f66d1
--- /dev/null
+++ b/drivers/char/drm/radeon_drm.h
@@ -0,0 +1,325 @@
+/* radeon_drm.h -- Public header for the radeon driver -*- linux-c -*-
+ *
+ * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef __RADEON_DRM_H__
+#define __RADEON_DRM_H__
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the X server file (radeon_sarea.h)
+ */
+#ifndef __RADEON_SAREA_DEFINES__
+#define __RADEON_SAREA_DEFINES__
+
+/* What needs to be changed for the current vertex buffer?
+ */
+#define RADEON_UPLOAD_CONTEXT 0x00000001
+#define RADEON_UPLOAD_VERTFMT 0x00000002
+#define RADEON_UPLOAD_LINE 0x00000004
+#define RADEON_UPLOAD_BUMPMAP 0x00000008
+#define RADEON_UPLOAD_MASKS 0x00000010
+#define RADEON_UPLOAD_VIEWPORT 0x00000020
+#define RADEON_UPLOAD_SETUP 0x00000040
+#define RADEON_UPLOAD_TCL 0x00000080
+#define RADEON_UPLOAD_MISC 0x00000100
+#define RADEON_UPLOAD_TEX0 0x00000200
+#define RADEON_UPLOAD_TEX1 0x00000400
+#define RADEON_UPLOAD_TEX2 0x00000800
+#define RADEON_UPLOAD_TEX0IMAGES 0x00001000
+#define RADEON_UPLOAD_TEX1IMAGES 0x00002000
+#define RADEON_UPLOAD_TEX2IMAGES 0x00004000
+#define RADEON_UPLOAD_CLIPRECTS 0x00008000 /* handled client-side */
+#define RADEON_REQUIRE_QUIESCENCE 0x00010000
+#define RADEON_UPLOAD_ALL 0x0001ffff
+
+#define RADEON_FRONT 0x1
+#define RADEON_BACK 0x2
+#define RADEON_DEPTH 0x4
+
+/* Primitive types
+ */
+#define RADEON_POINTS 0x1
+#define RADEON_LINES 0x2
+#define RADEON_LINE_STRIP 0x3
+#define RADEON_TRIANGLES 0x4
+#define RADEON_TRIANGLE_FAN 0x5
+#define RADEON_TRIANGLE_STRIP 0x6
+
+/* Vertex/indirect buffer size
+ */
+#define RADEON_BUFFER_SIZE 16384
+
+/* Byte offsets for indirect buffer data
+ */
+#define RADEON_INDEX_PRIM_OFFSET 20
+#define RADEON_HOSTDATA_BLIT_OFFSET 32
+
+#define RADEON_SCRATCH_REG_OFFSET 32
+
+/* Keep these small for testing
+ */
+#define RADEON_NR_SAREA_CLIPRECTS 12
+
+/* There are 2 heaps (local/AGP). Each region within a heap is a
+ * minimum of 64k, and there are at most 64 of them per heap.
+ */
+#define RADEON_LOCAL_TEX_HEAP 0
+#define RADEON_AGP_TEX_HEAP 1
+#define RADEON_NR_TEX_HEAPS 2
+#define RADEON_NR_TEX_REGIONS 64
+#define RADEON_LOG_TEX_GRANULARITY 16
+
+#define RADEON_MAX_TEXTURE_LEVELS 11
+#define RADEON_MAX_TEXTURE_UNITS 3
+
+#endif /* __RADEON_SAREA_DEFINES__ */
+
+typedef struct {
+ unsigned int red;
+ unsigned int green;
+ unsigned int blue;
+ unsigned int alpha;
+} radeon_color_regs_t;
+
+typedef struct {
+ /* Context state */
+ unsigned int pp_misc; /* 0x1c14 */
+ unsigned int pp_fog_color;
+ unsigned int re_solid_color;
+ unsigned int rb3d_blendcntl;
+ unsigned int rb3d_depthoffset;
+ unsigned int rb3d_depthpitch;
+ unsigned int rb3d_zstencilcntl;
+
+ unsigned int pp_cntl; /* 0x1c38 */
+ unsigned int rb3d_cntl;
+ unsigned int rb3d_coloroffset;
+ unsigned int re_width_height;
+ unsigned int rb3d_colorpitch;
+ unsigned int se_cntl;
+
+ /* Vertex format state */
+ unsigned int se_coord_fmt; /* 0x1c50 */
+
+ /* Line state */
+ unsigned int re_line_pattern; /* 0x1cd0 */
+ unsigned int re_line_state;
+
+ unsigned int se_line_width; /* 0x1db8 */
+
+ /* Bumpmap state */
+ unsigned int pp_lum_matrix; /* 0x1d00 */
+
+ unsigned int pp_rot_matrix_0; /* 0x1d58 */
+ unsigned int pp_rot_matrix_1;
+
+ /* Mask state */
+ unsigned int rb3d_stencilrefmask; /* 0x1d7c */
+ unsigned int rb3d_ropcntl;
+ unsigned int rb3d_planemask;
+
+ /* Viewport state */
+ unsigned int se_vport_xscale; /* 0x1d98 */
+ unsigned int se_vport_xoffset;
+ unsigned int se_vport_yscale;
+ unsigned int se_vport_yoffset;
+ unsigned int se_vport_zscale;
+ unsigned int se_vport_zoffset;
+
+ /* Setup state */
+ unsigned int se_cntl_status; /* 0x2140 */
+
+#ifdef TCL_ENABLE
+ /* TCL state */
+ radeon_color_regs_t se_tcl_material_emmissive; /* 0x2210 */
+ radeon_color_regs_t se_tcl_material_ambient;
+ radeon_color_regs_t se_tcl_material_diffuse;
+ radeon_color_regs_t se_tcl_material_specular;
+ unsigned int se_tcl_shininess;
+ unsigned int se_tcl_output_vtx_fmt;
+ unsigned int se_tcl_output_vtx_sel;
+ unsigned int se_tcl_matrix_select_0;
+ unsigned int se_tcl_matrix_select_1;
+ unsigned int se_tcl_ucp_vert_blend_ctl;
+ unsigned int se_tcl_texture_proc_ctl;
+ unsigned int se_tcl_light_model_ctl;
+ unsigned int se_tcl_per_light_ctl[4];
+#endif
+
+ /* Misc state */
+ unsigned int re_top_left; /* 0x26c0 */
+ unsigned int re_misc;
+} drm_radeon_context_regs_t;
+
+/* Setup registers for each texture unit
+ */
+typedef struct {
+ unsigned int pp_txfilter;
+ unsigned int pp_txformat;
+ unsigned int pp_txoffset;
+ unsigned int pp_txcblend;
+ unsigned int pp_txablend;
+ unsigned int pp_tfactor;
+
+ unsigned int pp_border_color;
+
+#ifdef CUBIC_ENABLE
+ unsigned int pp_cubic_faces;
+ unsigned int pp_cubic_offset[5];
+#endif
+} drm_radeon_texture_regs_t;
+
+typedef struct {
+ unsigned char next, prev;
+ unsigned char in_use;
+ int age;
+} drm_radeon_tex_region_t;
+
+typedef struct {
+ /* The channel for communication of state information to the kernel
+ * on firing a vertex buffer.
+ */
+ drm_radeon_context_regs_t context_state;
+ drm_radeon_texture_regs_t tex_state[RADEON_MAX_TEXTURE_UNITS];
+ unsigned int dirty;
+ unsigned int vertsize;
+ unsigned int vc_format;
+
+ /* The current cliprects, or a subset thereof.
+ */
+ drm_clip_rect_t boxes[RADEON_NR_SAREA_CLIPRECTS];
+ unsigned int nbox;
+
+ /* Counters for client-side throttling of rendering clients.
+ */
+ unsigned int last_frame;
+ unsigned int last_dispatch;
+ unsigned int last_clear;
+
+ drm_radeon_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1];
+ int tex_age[RADEON_NR_TEX_HEAPS];
+ int ctx_owner;
+} drm_radeon_sarea_t;
+
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the Xserver file (xf86drmRadeon.h)
+ */
+typedef struct drm_radeon_init {
+ enum {
+ RADEON_INIT_CP = 0x01,
+ RADEON_CLEANUP_CP = 0x02
+ } func;
+ int sarea_priv_offset;
+ int is_pci;
+ int cp_mode;
+ int agp_size;
+ int ring_size;
+ int usec_timeout;
+
+ unsigned int fb_bpp;
+ unsigned int front_offset, front_pitch;
+ unsigned int back_offset, back_pitch;
+ unsigned int depth_bpp;
+ unsigned int depth_offset, depth_pitch;
+
+ unsigned int fb_offset;
+ unsigned int mmio_offset;
+ unsigned int ring_offset;
+ unsigned int ring_rptr_offset;
+ unsigned int buffers_offset;
+ unsigned int agp_textures_offset;
+} drm_radeon_init_t;
+
+typedef struct drm_radeon_cp_stop {
+ int flush;
+ int idle;
+} drm_radeon_cp_stop_t;
+
+typedef struct drm_radeon_fullscreen {
+ enum {
+ RADEON_INIT_FULLSCREEN = 0x01,
+ RADEON_CLEANUP_FULLSCREEN = 0x02
+ } func;
+} drm_radeon_fullscreen_t;
+
+#define CLEAR_X1 0
+#define CLEAR_Y1 1
+#define CLEAR_X2 2
+#define CLEAR_Y2 3
+#define CLEAR_DEPTH 4
+
+typedef struct drm_radeon_clear {
+ unsigned int flags;
+ int x, y, w, h;
+ unsigned int clear_color;
+ unsigned int clear_depth;
+ union {
+ float f[5];
+ unsigned int ui[5];
+ } rect;
+} drm_radeon_clear_t;
+
+typedef struct drm_radeon_vertex {
+ int prim;
+ int idx; /* Index of vertex buffer */
+ int count; /* Number of vertices in buffer */
+ int discard; /* Client finished with buffer? */
+} drm_radeon_vertex_t;
+
+typedef struct drm_radeon_indices {
+ int prim;
+ int idx;
+ int start;
+ int end;
+ int discard; /* Client finished with buffer? */
+} drm_radeon_indices_t;
+
+typedef struct drm_radeon_blit {
+ int idx;
+ int pitch;
+ int offset;
+ int format;
+ unsigned short x, y;
+ unsigned short width, height;
+} drm_radeon_blit_t;
+
+typedef struct drm_radeon_stipple {
+ unsigned int *mask;
+} drm_radeon_stipple_t;
+
+typedef struct drm_radeon_indirect {
+ int idx;
+ int start;
+ int end;
+ int discard;
+} drm_radeon_indirect_t;
+
+#endif
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
new file mode 100644
index 000000000..0113ed97c
--- /dev/null
+++ b/drivers/char/drm/radeon_drv.c
@@ -0,0 +1,702 @@
+/* radeon_drv.c -- ATI Radeon driver -*- linux-c -*-
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Kevin E. Martin <martin@valinux.com>
+ * Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ */
+
+#include <linux/config.h>
+#include "drmP.h"
+#include "radeon_drv.h"
+
+#define RADEON_NAME "radeon"
+#define RADEON_DESC "ATI Radeon"
+#define RADEON_DATE "20010105"
+#define RADEON_MAJOR 1
+#define RADEON_MINOR 0
+#define RADEON_PATCHLEVEL 0
+
+static drm_device_t radeon_device;
+drm_ctx_t radeon_res_ctx;
+
+static struct file_operations radeon_fops = {
+#if LINUX_VERSION_CODE >= 0x020400
+ /* This started being used during 2.4.0-test */
+ owner: THIS_MODULE,
+#endif
+ open: radeon_open,
+ flush: drm_flush,
+ release: radeon_release,
+ ioctl: radeon_ioctl,
+ mmap: drm_mmap,
+ read: drm_read,
+ fasync: drm_fasync,
+ poll: drm_poll,
+};
+
+static struct miscdevice radeon_misc = {
+ minor: MISC_DYNAMIC_MINOR,
+ name: RADEON_NAME,
+ fops: &radeon_fops,
+};
+
+static drm_ioctl_desc_t radeon_ioctls[] = {
+ [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { radeon_version, 0, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_busid, 0, 1 },
+
+ [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_block, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_unblock, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { radeon_addbufs, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { radeon_mapbufs, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 },
+
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { radeon_addctx, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { radeon_rmctx, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { radeon_modctx, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { radeon_getctx, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { radeon_switchctx, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { radeon_newctx, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { radeon_resctx, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { radeon_lock, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { radeon_unlock, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 },
+
+#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
+#endif
+
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_INIT)] = { radeon_cp_init, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_START)] = { radeon_cp_start, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_STOP)] = { radeon_cp_stop, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_RESET)] = { radeon_cp_reset, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_IDLE)] = { radeon_cp_idle, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_RESET)] = { radeon_engine_reset, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FULLSCREEN)] = { radeon_fullscreen, 1, 0 },
+
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SWAP)] = { radeon_cp_swap, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CLEAR)] = { radeon_cp_clear, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX)] = { radeon_cp_vertex, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDICES)] = { radeon_cp_indices, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_BLIT)] = { radeon_cp_blit, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_STIPPLE)] = { radeon_cp_stipple, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDIRECT)]= { radeon_cp_indirect,1, 1 },
+};
+#define RADEON_IOCTL_COUNT DRM_ARRAY_SIZE(radeon_ioctls)
+
+#ifdef MODULE
+static char *radeon = NULL;
+#endif
+
+MODULE_AUTHOR("VA Linux Systems, Inc.");
+MODULE_DESCRIPTION("radeon");
+MODULE_PARM(radeon, "s");
+
+#ifndef MODULE
+/* radeon_options is called by the kernel to parse command-line options
+ * passed via the boot-loader (e.g., LILO). It calls the insmod option
+ * routine, drm_parse_drm.
+ */
+
+static int __init radeon_options(char *str)
+{
+ drm_parse_options(str);
+ return 1;
+}
+
+__setup("radeon=", radeon_options);
+#endif
+
+static int radeon_setup(drm_device_t *dev)
+{
+ int i;
+
+ atomic_set(&dev->ioctl_count, 0);
+ atomic_set(&dev->vma_count, 0);
+ dev->buf_use = 0;
+ atomic_set(&dev->buf_alloc, 0);
+
+ drm_dma_setup(dev);
+
+ atomic_set(&dev->total_open, 0);
+ atomic_set(&dev->total_close, 0);
+ atomic_set(&dev->total_ioctl, 0);
+ atomic_set(&dev->total_irq, 0);
+ atomic_set(&dev->total_ctx, 0);
+ atomic_set(&dev->total_locks, 0);
+ atomic_set(&dev->total_unlocks, 0);
+ atomic_set(&dev->total_contends, 0);
+ atomic_set(&dev->total_sleeps, 0);
+
+ for (i = 0; i < DRM_HASH_SIZE; i++) {
+ dev->magiclist[i].head = NULL;
+ dev->magiclist[i].tail = NULL;
+ }
+ dev->maplist = NULL;
+ dev->map_count = 0;
+ dev->vmalist = NULL;
+ dev->lock.hw_lock = NULL;
+ init_waitqueue_head(&dev->lock.lock_queue);
+ dev->queue_count = 0;
+ dev->queue_reserved = 0;
+ dev->queue_slots = 0;
+ dev->queuelist = NULL;
+ dev->irq = 0;
+ dev->context_flag = 0;
+ dev->interrupt_flag = 0;
+ dev->dma_flag = 0;
+ dev->last_context = 0;
+ dev->last_switch = 0;
+ dev->last_checked = 0;
+ init_timer(&dev->timer);
+ init_waitqueue_head(&dev->context_wait);
+
+ dev->ctx_start = 0;
+ dev->lck_start = 0;
+
+ dev->buf_rp = dev->buf;
+ dev->buf_wp = dev->buf;
+ dev->buf_end = dev->buf + DRM_BSZ;
+ dev->buf_async = NULL;
+ init_waitqueue_head(&dev->buf_readers);
+ init_waitqueue_head(&dev->buf_writers);
+
+ radeon_res_ctx.handle = -1;
+
+ DRM_DEBUG("\n");
+
+ /* The kernel's context could be created here, but is now created
+ in drm_dma_enqueue. This is more resource-efficient for
+ hardware that does not do DMA, but may mean that
+ drm_select_queue fails between the time the interrupt is
+ initialized and the time the queues are initialized. */
+
+ return 0;
+}
+
+
+static int radeon_takedown(drm_device_t *dev)
+{
+ int i;
+ drm_magic_entry_t *pt, *next;
+ drm_map_t *map;
+ drm_vma_entry_t *vma, *vma_next;
+
+ DRM_DEBUG("\n");
+
+ down(&dev->struct_sem);
+ del_timer(&dev->timer);
+
+ if (dev->devname) {
+ drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER);
+ dev->devname = NULL;
+ }
+
+ if (dev->unique) {
+ drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER);
+ dev->unique = NULL;
+ dev->unique_len = 0;
+ }
+ /* Clear pid list */
+ for (i = 0; i < DRM_HASH_SIZE; i++) {
+ for (pt = dev->magiclist[i].head; pt; pt = next) {
+ next = pt->next;
+ drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
+ }
+ dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
+ }
+
+#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
+ /* Clear AGP information */
+ if (dev->agp) {
+ drm_agp_mem_t *entry;
+ drm_agp_mem_t *nexte;
+
+ /* Remove AGP resources, but leave dev->agp
+ intact until radeon_cleanup is called. */
+ for (entry = dev->agp->memory; entry; entry = nexte) {
+ nexte = entry->next;
+ if (entry->bound) drm_unbind_agp(entry->memory);
+ drm_free_agp(entry->memory, entry->pages);
+ drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
+ }
+ dev->agp->memory = NULL;
+
+ if (dev->agp->acquired) _drm_agp_release();
+
+ dev->agp->acquired = 0;
+ dev->agp->enabled = 0;
+ }
+#endif
+
+ /* Clear vma list (only built for debugging) */
+ if (dev->vmalist) {
+ for (vma = dev->vmalist; vma; vma = vma_next) {
+ vma_next = vma->next;
+ drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
+ }
+ dev->vmalist = NULL;
+ }
+
+ /* Clear map area and mtrr information */
+ if (dev->maplist) {
+ for (i = 0; i < dev->map_count; i++) {
+ map = dev->maplist[i];
+ switch (map->type) {
+ case _DRM_REGISTERS:
+ case _DRM_FRAME_BUFFER:
+#ifdef CONFIG_MTRR
+ if (map->mtrr >= 0) {
+ int retcode;
+ retcode = mtrr_del(map->mtrr,
+ map->offset,
+ map->size);
+ DRM_DEBUG("mtrr_del = %d\n", retcode);
+ }
+#endif
+ drm_ioremapfree(map->handle, map->size);
+ break;
+ case _DRM_SHM:
+ drm_free_pages((unsigned long)map->handle,
+ drm_order(map->size)
+ - PAGE_SHIFT,
+ DRM_MEM_SAREA);
+ break;
+ case _DRM_AGP:
+ /* Do nothing here, because this is all
+ handled in the AGP/GART driver. */
+ break;
+ }
+ drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+ }
+ drm_free(dev->maplist,
+ dev->map_count * sizeof(*dev->maplist),
+ DRM_MEM_MAPS);
+ dev->maplist = NULL;
+ dev->map_count = 0;
+ }
+
+ drm_dma_takedown(dev);
+
+ dev->queue_count = 0;
+ if (dev->lock.hw_lock) {
+ dev->lock.hw_lock = NULL; /* SHM removed */
+ dev->lock.pid = 0;
+ wake_up_interruptible(&dev->lock.lock_queue);
+ }
+ up(&dev->struct_sem);
+
+ return 0;
+}
+
+/* radeon_init is called via init_module at module load time, or via
+ * linux/init/main.c (this is not currently supported). */
+
+static int __init radeon_init(void)
+{
+ int retcode;
+ drm_device_t *dev = &radeon_device;
+
+ DRM_DEBUG("\n");
+
+ memset((void *)dev, 0, sizeof(*dev));
+ dev->count_lock = SPIN_LOCK_UNLOCKED;
+ sema_init(&dev->struct_sem, 1);
+
+#ifdef MODULE
+ drm_parse_options(radeon);
+#endif
+
+ if ((retcode = misc_register(&radeon_misc))) {
+ DRM_ERROR("Cannot register \"%s\"\n", RADEON_NAME);
+ return retcode;
+ }
+ dev->device = MKDEV(MISC_MAJOR, radeon_misc.minor);
+ dev->name = RADEON_NAME;
+
+ drm_mem_init();
+ drm_proc_init(dev);
+
+#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
+ dev->agp = drm_agp_init();
+ if (dev->agp == NULL) {
+ DRM_ERROR("Cannot initialize agpgart module.\n");
+ drm_proc_cleanup();
+ misc_deregister(&radeon_misc);
+ radeon_takedown(dev);
+ return -ENOMEM;
+ }
+
+#ifdef CONFIG_MTRR
+ dev->agp->agp_mtrr = mtrr_add(dev->agp->agp_info.aper_base,
+ dev->agp->agp_info.aper_size*1024*1024,
+ MTRR_TYPE_WRCOMB,
+ 1);
+#endif
+#endif
+
+ if((retcode = drm_ctxbitmap_init(dev))) {
+ DRM_ERROR("Cannot allocate memory for context bitmap.\n");
+ drm_proc_cleanup();
+ misc_deregister(&radeon_misc);
+ radeon_takedown(dev);
+ return retcode;
+ }
+
+ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
+ RADEON_NAME,
+ RADEON_MAJOR,
+ RADEON_MINOR,
+ RADEON_PATCHLEVEL,
+ RADEON_DATE,
+ radeon_misc.minor);
+
+ return 0;
+}
+
+/* radeon_cleanup is called via cleanup_module at module unload time. */
+
+static void __exit radeon_cleanup(void)
+{
+ drm_device_t *dev = &radeon_device;
+
+ DRM_DEBUG("\n");
+
+ drm_proc_cleanup();
+ if (misc_deregister(&radeon_misc)) {
+ DRM_ERROR("Cannot unload module\n");
+ } else {
+ DRM_INFO("Module unloaded\n");
+ }
+ drm_ctxbitmap_cleanup(dev);
+ radeon_takedown(dev);
+#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
+ if (dev->agp) {
+ drm_agp_uninit();
+ drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
+ dev->agp = NULL;
+ }
+#endif
+}
+
+module_init(radeon_init);
+module_exit(radeon_cleanup);
+
+
+int radeon_version(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_version_t version;
+ int len;
+
+ if (copy_from_user(&version,
+ (drm_version_t *)arg,
+ sizeof(version)))
+ return -EFAULT;
+
+#define DRM_COPY(name,value) \
+ len = strlen(value); \
+ if (len > name##_len) len = name##_len; \
+ name##_len = strlen(value); \
+ if (len && name) { \
+ if (copy_to_user(name, value, len)) \
+ return -EFAULT; \
+ }
+
+ version.version_major = RADEON_MAJOR;
+ version.version_minor = RADEON_MINOR;
+ version.version_patchlevel = RADEON_PATCHLEVEL;
+
+ DRM_COPY(version.name, RADEON_NAME);
+ DRM_COPY(version.date, RADEON_DATE);
+ DRM_COPY(version.desc, RADEON_DESC);
+
+ if (copy_to_user((drm_version_t *)arg,
+ &version,
+ sizeof(version)))
+ return -EFAULT;
+ return 0;
+}
+
+int radeon_open(struct inode *inode, struct file *filp)
+{
+ drm_device_t *dev = &radeon_device;
+ int retcode = 0;
+
+ DRM_DEBUG("open_count = %d\n", dev->open_count);
+ if (!(retcode = drm_open_helper(inode, filp, dev))) {
+#if LINUX_VERSION_CODE < 0x020333
+ MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */
+#endif
+ atomic_inc(&dev->total_open);
+ spin_lock(&dev->count_lock);
+ if (!dev->open_count++) {
+ spin_unlock(&dev->count_lock);
+ return radeon_setup(dev);
+ }
+ spin_unlock(&dev->count_lock);
+ }
+
+ return retcode;
+}
+
+int radeon_release(struct inode *inode, struct file *filp)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev;
+ int retcode = 0;
+
+ lock_kernel();
+ dev = priv->dev;
+
+ DRM_DEBUG("open_count = %d\n", dev->open_count);
+
+ /* Force the cleanup of page flipping when required */
+ if ( dev->dev_private ) {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ if ( dev_priv->page_flipping ) {
+ radeon_do_cleanup_pageflip( dev );
+ }
+ }
+
+ if (!(retcode = drm_release(inode, filp))) {
+#if LINUX_VERSION_CODE < 0x020333
+ MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */
+#endif
+ atomic_inc(&dev->total_close);
+ spin_lock(&dev->count_lock);
+ if (!--dev->open_count) {
+ if (atomic_read(&dev->ioctl_count) || dev->blocked) {
+ DRM_ERROR("Device busy: %d %d\n",
+ atomic_read(&dev->ioctl_count),
+ dev->blocked);
+ spin_unlock(&dev->count_lock);
+ unlock_kernel();
+ return -EBUSY;
+ }
+ spin_unlock(&dev->count_lock);
+ unlock_kernel();
+ return radeon_takedown(dev);
+ }
+ spin_unlock(&dev->count_lock);
+ }
+
+ unlock_kernel();
+ return retcode;
+}
+
+/* radeon_ioctl is called whenever a process performs an ioctl on /dev/drm. */
+
+int radeon_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ int nr = DRM_IOCTL_NR(cmd);
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ int retcode = 0;
+ drm_ioctl_desc_t *ioctl;
+ drm_ioctl_t *func;
+
+ atomic_inc(&dev->ioctl_count);
+ atomic_inc(&dev->total_ioctl);
+ ++priv->ioctl_count;
+
+ DRM_DEBUG("pid = %d, cmd = 0x%02x, nr = 0x%02x, dev 0x%x, auth = %d\n",
+ current->pid, cmd, nr, dev->device, priv->authenticated);
+
+ if (nr >= RADEON_IOCTL_COUNT) {
+ retcode = -EINVAL;
+ } else {
+ ioctl = &radeon_ioctls[nr];
+ func = ioctl->func;
+
+ if (!func) {
+ DRM_DEBUG("no function\n");
+ retcode = -EINVAL;
+ } else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN))
+ || (ioctl->auth_needed && !priv->authenticated)) {
+ retcode = -EACCES;
+ } else {
+ retcode = (func)(inode, filp, cmd, arg);
+ }
+ }
+
+ atomic_dec(&dev->ioctl_count);
+ return retcode;
+}
+
+int radeon_lock(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ DECLARE_WAITQUEUE(entry, current);
+ int ret = 0;
+ drm_lock_t lock;
+#if DRM_DMA_HISTOGRAM
+ cycles_t start;
+
+ dev->lck_start = start = get_cycles();
+#endif
+
+ if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
+ return -EFAULT;
+
+ if (lock.context == DRM_KERNEL_CONTEXT) {
+ DRM_ERROR("Process %d using kernel context %d\n",
+ current->pid, lock.context);
+ return -EINVAL;
+ }
+
+ DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
+ lock.context, current->pid, dev->lock.hw_lock->lock,
+ lock.flags);
+
+ if (lock.context < 0 /* || lock.context >= dev->queue_count */)
+ return -EINVAL;
+
+ if (!ret) {
+ add_wait_queue(&dev->lock.lock_queue, &entry);
+ for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
+ if (!dev->lock.hw_lock) {
+ /* Device has been unregistered */
+ ret = -EINTR;
+ break;
+ }
+ if (drm_lock_take(&dev->lock.hw_lock->lock,
+ lock.context)) {
+ dev->lock.pid = current->pid;
+ dev->lock.lock_time = jiffies;
+ atomic_inc(&dev->total_locks);
+ break; /* Got lock */
+ }
+
+ /* Contention */
+ atomic_inc(&dev->total_sleeps);
+ schedule();
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&dev->lock.lock_queue, &entry);
+ }
+
+ if (!ret) {
+ sigemptyset(&dev->sigmask);
+ sigaddset(&dev->sigmask, SIGSTOP);
+ sigaddset(&dev->sigmask, SIGTSTP);
+ sigaddset(&dev->sigmask, SIGTTIN);
+ sigaddset(&dev->sigmask, SIGTTOU);
+ dev->sigdata.context = lock.context;
+ dev->sigdata.lock = dev->lock.hw_lock;
+ block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
+ if (lock.flags & _DRM_LOCK_READY) {
+ /* Wait for space in DMA/FIFO */
+ }
+ if (lock.flags & _DRM_LOCK_QUIESCENT) {
+ /* Make hardware quiescent */
+ DRM_DEBUG("not quiescent!\n");
+#if 0
+ radeon_quiescent(dev);
+#endif
+ }
+ }
+
+#if LINUX_VERSION_CODE < 0x020400
+ if (lock.context != radeon_res_ctx.handle) {
+ current->counter = 5;
+ current->priority = DEF_PRIORITY/4;
+ }
+#endif
+ DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
+
+#if DRM_DMA_HISTOGRAM
+ atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]);
+#endif
+
+ return ret;
+}
+
+
+int radeon_unlock(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_lock_t lock;
+
+ if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
+ return -EFAULT;
+
+ if (lock.context == DRM_KERNEL_CONTEXT) {
+ DRM_ERROR("Process %d using kernel context %d\n",
+ current->pid, lock.context);
+ return -EINVAL;
+ }
+
+ DRM_DEBUG("%d frees lock (%d holds)\n",
+ lock.context,
+ _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
+ atomic_inc(&dev->total_unlocks);
+ if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock))
+ atomic_inc(&dev->total_contends);
+ drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT);
+ /* FIXME: Try to send data to card here */
+ if (!dev->context_flag) {
+ if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT)) {
+ DRM_ERROR("\n");
+ }
+ }
+
+#if LINUX_VERSION_CODE < 0x020400
+ if (lock.context != radeon_res_ctx.handle) {
+ current->counter = 5;
+ current->priority = DEF_PRIORITY;
+ }
+#endif
+ unblock_all_signals();
+ return 0;
+}
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
new file mode 100644
index 000000000..06b541991
--- /dev/null
+++ b/drivers/char/drm/radeon_drv.h
@@ -0,0 +1,709 @@
+/* radeon_drv.h -- Private header for radeon driver -*- linux-c -*-
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Rickard E. (Rik) Faith <faith@valinux.com>
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef __RADEON_DRV_H__
+#define __RADEON_DRV_H__
+
+typedef struct drm_radeon_freelist {
+ unsigned int age;
+ drm_buf_t *buf;
+ struct drm_radeon_freelist *next;
+ struct drm_radeon_freelist *prev;
+} drm_radeon_freelist_t;
+
+typedef struct drm_radeon_ring_buffer {
+ u32 *start;
+ u32 *end;
+ int size;
+ int size_l2qw;
+
+ volatile u32 *head;
+ u32 tail;
+ u32 tail_mask;
+ int space;
+} drm_radeon_ring_buffer_t;
+
+typedef struct drm_radeon_depth_clear_t {
+ u32 rb3d_cntl;
+ u32 rb3d_zstencilcntl;
+ u32 se_cntl;
+} drm_radeon_depth_clear_t;
+
+typedef struct drm_radeon_private {
+ drm_radeon_ring_buffer_t ring;
+ drm_radeon_sarea_t *sarea_priv;
+
+ int agp_size;
+ u32 agp_vm_start;
+ u32 agp_buffers_offset;
+
+ int cp_mode;
+ int cp_running;
+
+ drm_radeon_freelist_t *head;
+ drm_radeon_freelist_t *tail;
+/* FIXME: ROTATE_BUFS is a hask to cycle through bufs until freelist
+ code is used. Note this hides a problem with the scratch register
+ (used to keep track of last buffer completed) being written to before
+ the last buffer has actually completed rendering. */
+#define ROTATE_BUFS 1
+#if ROTATE_BUFS
+ int last_buf;
+#endif
+ volatile u32 *scratch;
+
+ int usec_timeout;
+ int is_pci;
+
+ atomic_t idle_count;
+
+ int page_flipping;
+ int current_page;
+ u32 crtc_offset;
+ u32 crtc_offset_cntl;
+
+ unsigned int color_fmt;
+ unsigned int front_offset;
+ unsigned int front_pitch;
+ unsigned int back_offset;
+ unsigned int back_pitch;
+
+ unsigned int depth_fmt;
+ unsigned int depth_offset;
+ unsigned int depth_pitch;
+
+ u32 front_pitch_offset;
+ u32 back_pitch_offset;
+ u32 depth_pitch_offset;
+
+ drm_radeon_depth_clear_t depth_clear;
+
+ drm_map_t *sarea;
+ drm_map_t *fb;
+ drm_map_t *mmio;
+ drm_map_t *cp_ring;
+ drm_map_t *ring_rptr;
+ drm_map_t *buffers;
+ drm_map_t *agp_textures;
+} drm_radeon_private_t;
+
+typedef struct drm_radeon_buf_priv {
+ u32 age;
+ int prim;
+ int discard;
+ int dispatched;
+ drm_radeon_freelist_t *list_entry;
+} drm_radeon_buf_priv_t;
+
+ /* radeon_drv.c */
+extern int radeon_version( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int radeon_open( struct inode *inode, struct file *filp );
+extern int radeon_release( struct inode *inode, struct file *filp );
+extern int radeon_ioctl( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int radeon_lock( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int radeon_unlock( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+
+ /* radeon_cp.c */
+extern int radeon_cp_init( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int radeon_cp_start( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int radeon_cp_stop( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int radeon_cp_reset( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int radeon_cp_idle( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int radeon_engine_reset( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int radeon_fullscreen( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int radeon_cp_buffers( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+
+extern void radeon_freelist_reset( drm_device_t *dev );
+extern drm_buf_t *radeon_freelist_get( drm_device_t *dev );
+
+extern int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n );
+extern void radeon_update_ring_snapshot( drm_radeon_private_t *dev_priv );
+
+extern int radeon_do_cp_idle( drm_radeon_private_t *dev_priv );
+extern int radeon_do_cleanup_pageflip( drm_device_t *dev );
+
+ /* radeon_state.c */
+extern int radeon_cp_clear( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int radeon_cp_swap( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int radeon_cp_vertex( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int radeon_cp_indices( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int radeon_cp_blit( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int radeon_cp_stipple( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int radeon_cp_indirect( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+
+ /* radeon_bufs.c */
+extern int radeon_addbufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int radeon_mapbufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+
+ /* radeon_context.c */
+extern int radeon_resctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int radeon_addctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int radeon_modctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int radeon_getctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int radeon_switchctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int radeon_newctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int radeon_rmctx(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+
+extern int radeon_context_switch(drm_device_t *dev, int old, int new);
+extern int radeon_context_switch_complete(drm_device_t *dev, int new);
+
+
+/* Register definitions, register access macros and drmAddMap constants
+ * for Radeon kernel driver.
+ */
+
+#define RADEON_AUX_SCISSOR_CNTL 0x26f0
+# define RADEON_EXCLUSIVE_SCISSOR_0 (1 << 24)
+# define RADEON_EXCLUSIVE_SCISSOR_1 (1 << 25)
+# define RADEON_EXCLUSIVE_SCISSOR_2 (1 << 26)
+# define RADEON_SCISSOR_0_ENABLE (1 << 28)
+# define RADEON_SCISSOR_1_ENABLE (1 << 29)
+# define RADEON_SCISSOR_2_ENABLE (1 << 30)
+
+#define RADEON_BUS_CNTL 0x0030
+# define RADEON_BUS_MASTER_DIS (1 << 6)
+
+#define RADEON_CLOCK_CNTL_DATA 0x000c
+# define RADEON_PLL_WR_EN (1 << 7)
+#define RADEON_CLOCK_CNTL_INDEX 0x0008
+#define RADEON_CONFIG_APER_SIZE 0x0108
+#define RADEON_CRTC_OFFSET 0x0224
+#define RADEON_CRTC_OFFSET_CNTL 0x0228
+# define RADEON_CRTC_TILE_EN (1 << 15)
+# define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16)
+
+#define RADEON_RB3D_COLORPITCH 0x1c48
+#define RADEON_RB3D_DEPTHCLEARVALUE 0x1c30
+#define RADEON_RB3D_DEPTHXY_OFFSET 0x1c60
+
+#define RADEON_DP_GUI_MASTER_CNTL 0x146c
+# define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0)
+# define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1)
+# define RADEON_GMC_BRUSH_SOLID_COLOR (13 << 4)
+# define RADEON_GMC_BRUSH_NONE (15 << 4)
+# define RADEON_GMC_DST_16BPP (4 << 8)
+# define RADEON_GMC_DST_24BPP (5 << 8)
+# define RADEON_GMC_DST_32BPP (6 << 8)
+# define RADEON_GMC_DST_DATATYPE_SHIFT 8
+# define RADEON_GMC_SRC_DATATYPE_COLOR (3 << 12)
+# define RADEON_DP_SRC_SOURCE_MEMORY (2 << 24)
+# define RADEON_DP_SRC_SOURCE_HOST_DATA (3 << 24)
+# define RADEON_GMC_CLR_CMP_CNTL_DIS (1 << 28)
+# define RADEON_GMC_WR_MSK_DIS (1 << 30)
+# define RADEON_ROP3_S 0x00cc0000
+# define RADEON_ROP3_P 0x00f00000
+#define RADEON_DP_WRITE_MASK 0x16cc
+#define RADEON_DST_PITCH_OFFSET 0x142c
+#define RADEON_DST_PITCH_OFFSET_C 0x1c80
+# define RADEON_DST_TILE_LINEAR (0 << 30)
+# define RADEON_DST_TILE_MACRO (1 << 30)
+# define RADEON_DST_TILE_MICRO (2 << 30)
+# define RADEON_DST_TILE_BOTH (3 << 30)
+
+#define RADEON_SCRATCH_REG0 0x15e0
+#define RADEON_SCRATCH_REG1 0x15e4
+#define RADEON_SCRATCH_REG2 0x15e8
+#define RADEON_SCRATCH_REG3 0x15ec
+#define RADEON_SCRATCH_REG4 0x15f0
+#define RADEON_SCRATCH_REG5 0x15f4
+#define RADEON_SCRATCH_UMSK 0x0770
+#define RADEON_SCRATCH_ADDR 0x0774
+
+#define RADEON_HOST_PATH_CNTL 0x0130
+# define RADEON_HDP_SOFT_RESET (1 << 26)
+# define RADEON_HDP_WC_TIMEOUT_MASK (7 << 28)
+# define RADEON_HDP_WC_TIMEOUT_28BCLK (7 << 28)
+
+#define RADEON_ISYNC_CNTL 0x1724
+# define RADEON_ISYNC_ANY2D_IDLE3D (1 << 0)
+# define RADEON_ISYNC_ANY3D_IDLE2D (1 << 1)
+# define RADEON_ISYNC_TRIG2D_IDLE3D (1 << 2)
+# define RADEON_ISYNC_TRIG3D_IDLE2D (1 << 3)
+# define RADEON_ISYNC_WAIT_IDLEGUI (1 << 4)
+# define RADEON_ISYNC_CPSCRATCH_IDLEGUI (1 << 5)
+
+#define RADEON_MC_AGP_LOCATION 0x014c
+#define RADEON_MC_FB_LOCATION 0x0148
+#define RADEON_MCLK_CNTL 0x0012
+
+#define RADEON_PP_BORDER_COLOR_0 0x1d40
+#define RADEON_PP_BORDER_COLOR_1 0x1d44
+#define RADEON_PP_BORDER_COLOR_2 0x1d48
+#define RADEON_PP_CNTL 0x1c38
+# define RADEON_SCISSOR_ENABLE (1 << 1)
+#define RADEON_PP_LUM_MATRIX 0x1d00
+#define RADEON_PP_MISC 0x1c14
+#define RADEON_PP_ROT_MATRIX_0 0x1d58
+#define RADEON_PP_TXFILTER_0 0x1c54
+#define RADEON_PP_TXFILTER_1 0x1c6c
+#define RADEON_PP_TXFILTER_2 0x1c84
+
+#define RADEON_RB2D_DSTCACHE_CTLSTAT 0x342c
+# define RADEON_RB2D_DC_FLUSH (3 << 0)
+# define RADEON_RB2D_DC_FREE (3 << 2)
+# define RADEON_RB2D_DC_FLUSH_ALL 0xf
+# define RADEON_RB2D_DC_BUSY (1 << 31)
+#define RADEON_RB3D_CNTL 0x1c3c
+# define RADEON_ALPHA_BLEND_ENABLE (1 << 0)
+# define RADEON_PLANE_MASK_ENABLE (1 << 1)
+# define RADEON_DITHER_ENABLE (1 << 2)
+# define RADEON_ROUND_ENABLE (1 << 3)
+# define RADEON_SCALE_DITHER_ENABLE (1 << 4)
+# define RADEON_DITHER_INIT (1 << 5)
+# define RADEON_ROP_ENABLE (1 << 6)
+# define RADEON_STENCIL_ENABLE (1 << 7)
+# define RADEON_Z_ENABLE (1 << 8)
+# define RADEON_DEPTH_XZ_OFFEST_ENABLE (1 << 9)
+# define RADEON_ZBLOCK8 (0 << 15)
+# define RADEON_ZBLOCK16 (1 << 15)
+#define RADEON_RB3D_DEPTHOFFSET 0x1c24
+#define RADEON_RB3D_PLANEMASK 0x1d84
+#define RADEON_RB3D_STENCILREFMASK 0x1d7c
+#define RADEON_RB3D_ZCACHE_MODE 0x3250
+#define RADEON_RB3D_ZCACHE_CTLSTAT 0x3254
+# define RADEON_RB3D_ZC_FLUSH (1 << 0)
+# define RADEON_RB3D_ZC_FREE (1 << 2)
+# define RADEON_RB3D_ZC_FLUSH_ALL 0x5
+# define RADEON_RB3D_ZC_BUSY (1 << 31)
+#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c
+# define RADEON_Z_TEST_MASK (7 << 4)
+# define RADEON_Z_TEST_ALWAYS (7 << 4)
+# define RADEON_STENCIL_TEST_ALWAYS (7 << 12)
+# define RADEON_STENCIL_S_FAIL_KEEP (0 << 16)
+# define RADEON_STENCIL_ZPASS_KEEP (0 << 20)
+# define RADEON_STENCIL_ZFAIL_KEEP (0 << 20)
+# define RADEON_Z_WRITE_ENABLE (1 << 30)
+#define RADEON_RBBM_SOFT_RESET 0x00f0
+# define RADEON_SOFT_RESET_CP (1 << 0)
+# define RADEON_SOFT_RESET_HI (1 << 1)
+# define RADEON_SOFT_RESET_SE (1 << 2)
+# define RADEON_SOFT_RESET_RE (1 << 3)
+# define RADEON_SOFT_RESET_PP (1 << 4)
+# define RADEON_SOFT_RESET_E2 (1 << 5)
+# define RADEON_SOFT_RESET_RB (1 << 6)
+# define RADEON_SOFT_RESET_HDP (1 << 7)
+#define RADEON_RBBM_STATUS 0x0e40
+# define RADEON_RBBM_FIFOCNT_MASK 0x007f
+# define RADEON_RBBM_ACTIVE (1 << 31)
+#define RADEON_RE_LINE_PATTERN 0x1cd0
+#define RADEON_RE_MISC 0x26c4
+#define RADEON_RE_TOP_LEFT 0x26c0
+#define RADEON_RE_WIDTH_HEIGHT 0x1c44
+#define RADEON_RE_STIPPLE_ADDR 0x1cc8
+#define RADEON_RE_STIPPLE_DATA 0x1ccc
+
+#define RADEON_SCISSOR_TL_0 0x1cd8
+#define RADEON_SCISSOR_BR_0 0x1cdc
+#define RADEON_SCISSOR_TL_1 0x1ce0
+#define RADEON_SCISSOR_BR_1 0x1ce4
+#define RADEON_SCISSOR_TL_2 0x1ce8
+#define RADEON_SCISSOR_BR_2 0x1cec
+#define RADEON_SE_COORD_FMT 0x1c50
+#define RADEON_SE_CNTL 0x1c4c
+# define RADEON_FFACE_CULL_CW (0 << 0)
+# define RADEON_BFACE_SOLID (3 << 1)
+# define RADEON_FFACE_SOLID (3 << 3)
+# define RADEON_FLAT_SHADE_VTX_LAST (3 << 6)
+# define RADEON_DIFFUSE_SHADE_FLAT (1 << 8)
+# define RADEON_DIFFUSE_SHADE_GOURAUD (2 << 8)
+# define RADEON_ALPHA_SHADE_FLAT (1 << 10)
+# define RADEON_ALPHA_SHADE_GOURAUD (2 << 10)
+# define RADEON_SPECULAR_SHADE_FLAT (1 << 12)
+# define RADEON_SPECULAR_SHADE_GOURAUD (2 << 12)
+# define RADEON_FOG_SHADE_FLAT (1 << 14)
+# define RADEON_FOG_SHADE_GOURAUD (2 << 14)
+# define RADEON_VPORT_XY_XFORM_ENABLE (1 << 24)
+# define RADEON_VPORT_Z_XFORM_ENABLE (1 << 25)
+# define RADEON_VTX_PIX_CENTER_OGL (1 << 27)
+# define RADEON_ROUND_MODE_TRUNC (0 << 28)
+# define RADEON_ROUND_PREC_8TH_PIX (1 << 30)
+#define RADEON_SE_CNTL_STATUS 0x2140
+#define RADEON_SE_LINE_WIDTH 0x1db8
+#define RADEON_SE_VPORT_XSCALE 0x1d98
+#define RADEON_SURFACE_ACCESS_FLAGS 0x0bf8
+#define RADEON_SURFACE_ACCESS_CLR 0x0bfc
+#define RADEON_SURFACE_CNTL 0x0b00
+# define RADEON_SURF_TRANSLATION_DIS (1 << 8)
+# define RADEON_NONSURF_AP0_SWP_MASK (3 << 20)
+# define RADEON_NONSURF_AP0_SWP_LITTLE (0 << 20)
+# define RADEON_NONSURF_AP0_SWP_BIG16 (1 << 20)
+# define RADEON_NONSURF_AP0_SWP_BIG32 (2 << 20)
+# define RADEON_NONSURF_AP1_SWP_MASK (3 << 22)
+# define RADEON_NONSURF_AP1_SWP_LITTLE (0 << 22)
+# define RADEON_NONSURF_AP1_SWP_BIG16 (1 << 22)
+# define RADEON_NONSURF_AP1_SWP_BIG32 (2 << 22)
+#define RADEON_SURFACE0_INFO 0x0b0c
+# define RADEON_SURF_PITCHSEL_MASK (0x1ff << 0)
+# define RADEON_SURF_TILE_MODE_MASK (3 << 16)
+# define RADEON_SURF_TILE_MODE_MACRO (0 << 16)
+# define RADEON_SURF_TILE_MODE_MICRO (1 << 16)
+# define RADEON_SURF_TILE_MODE_32BIT_Z (2 << 16)
+# define RADEON_SURF_TILE_MODE_16BIT_Z (3 << 16)
+#define RADEON_SURFACE0_LOWER_BOUND 0x0b04
+#define RADEON_SURFACE0_UPPER_BOUND 0x0b08
+#define RADEON_SURFACE1_INFO 0x0b1c
+#define RADEON_SURFACE1_LOWER_BOUND 0x0b14
+#define RADEON_SURFACE1_UPPER_BOUND 0x0b18
+#define RADEON_SURFACE2_INFO 0x0b2c
+#define RADEON_SURFACE2_LOWER_BOUND 0x0b24
+#define RADEON_SURFACE2_UPPER_BOUND 0x0b28
+#define RADEON_SURFACE3_INFO 0x0b3c
+#define RADEON_SURFACE3_LOWER_BOUND 0x0b34
+#define RADEON_SURFACE3_UPPER_BOUND 0x0b38
+#define RADEON_SURFACE4_INFO 0x0b4c
+#define RADEON_SURFACE4_LOWER_BOUND 0x0b44
+#define RADEON_SURFACE4_UPPER_BOUND 0x0b48
+#define RADEON_SURFACE5_INFO 0x0b5c
+#define RADEON_SURFACE5_LOWER_BOUND 0x0b54
+#define RADEON_SURFACE5_UPPER_BOUND 0x0b58
+#define RADEON_SURFACE6_INFO 0x0b6c
+#define RADEON_SURFACE6_LOWER_BOUND 0x0b64
+#define RADEON_SURFACE6_UPPER_BOUND 0x0b68
+#define RADEON_SURFACE7_INFO 0x0b7c
+#define RADEON_SURFACE7_LOWER_BOUND 0x0b74
+#define RADEON_SURFACE7_UPPER_BOUND 0x0b78
+#define RADEON_SW_SEMAPHORE 0x013c
+
+#define RADEON_WAIT_UNTIL 0x1720
+# define RADEON_WAIT_CRTC_PFLIP (1 << 0)
+# define RADEON_WAIT_2D_IDLECLEAN (1 << 16)
+# define RADEON_WAIT_3D_IDLECLEAN (1 << 17)
+# define RADEON_WAIT_HOST_IDLECLEAN (1 << 18)
+
+#define RADEON_RB3D_ZMASKOFFSET 0x1c34
+#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c
+# define RADEON_DEPTH_FORMAT_16BIT_INT_Z (0 << 0)
+# define RADEON_DEPTH_FORMAT_24BIT_INT_Z (2 << 0)
+
+
+/* CP registers */
+#define RADEON_CP_ME_RAM_ADDR 0x07d4
+#define RADEON_CP_ME_RAM_RADDR 0x07d8
+#define RADEON_CP_ME_RAM_DATAH 0x07dc
+#define RADEON_CP_ME_RAM_DATAL 0x07e0
+
+#define RADEON_CP_RB_BASE 0x0700
+#define RADEON_CP_RB_CNTL 0x0704
+#define RADEON_CP_RB_RPTR_ADDR 0x070c
+#define RADEON_CP_RB_RPTR 0x0710
+#define RADEON_CP_RB_WPTR 0x0714
+
+#define RADEON_CP_RB_WPTR_DELAY 0x0718
+# define RADEON_PRE_WRITE_TIMER_SHIFT 0
+# define RADEON_PRE_WRITE_LIMIT_SHIFT 23
+
+#define RADEON_CP_IB_BASE 0x0738
+
+#define RADEON_CP_CSQ_CNTL 0x0740
+# define RADEON_CSQ_CNT_PRIMARY_MASK (0xff << 0)
+# define RADEON_CSQ_PRIDIS_INDDIS (0 << 28)
+# define RADEON_CSQ_PRIPIO_INDDIS (1 << 28)
+# define RADEON_CSQ_PRIBM_INDDIS (2 << 28)
+# define RADEON_CSQ_PRIPIO_INDBM (3 << 28)
+# define RADEON_CSQ_PRIBM_INDBM (4 << 28)
+# define RADEON_CSQ_PRIPIO_INDPIO (15 << 28)
+
+#define RADEON_AIC_CNTL 0x01d0
+# define RADEON_PCIGART_TRANSLATE_EN (1 << 0)
+
+/* CP command packets */
+#define RADEON_CP_PACKET0 0x00000000
+# define RADEON_ONE_REG_WR (1 << 15)
+#define RADEON_CP_PACKET1 0x40000000
+#define RADEON_CP_PACKET2 0x80000000
+#define RADEON_CP_PACKET3 0xC0000000
+# define RADEON_3D_RNDR_GEN_INDX_PRIM 0x00002300
+# define RADEON_WAIT_FOR_IDLE 0x00002600
+# define RADEON_3D_DRAW_IMMD 0x00002900
+# define RADEON_3D_CLEAR_ZMASK 0x00003200
+# define RADEON_CNTL_HOSTDATA_BLT 0x00009400
+# define RADEON_CNTL_PAINT_MULTI 0x00009A00
+# define RADEON_CNTL_BITBLT_MULTI 0x00009B00
+
+#define RADEON_CP_PACKET_MASK 0xC0000000
+#define RADEON_CP_PACKET_COUNT_MASK 0x3fff0000
+#define RADEON_CP_PACKET0_REG_MASK 0x000007ff
+#define RADEON_CP_PACKET1_REG0_MASK 0x000007ff
+#define RADEON_CP_PACKET1_REG1_MASK 0x003ff800
+
+#define RADEON_VTX_Z_PRESENT (1 << 31)
+
+#define RADEON_PRIM_TYPE_NONE (0 << 0)
+#define RADEON_PRIM_TYPE_POINT (1 << 0)
+#define RADEON_PRIM_TYPE_LINE (2 << 0)
+#define RADEON_PRIM_TYPE_LINE_STRIP (3 << 0)
+#define RADEON_PRIM_TYPE_TRI_LIST (4 << 0)
+#define RADEON_PRIM_TYPE_TRI_FAN (5 << 0)
+#define RADEON_PRIM_TYPE_TRI_STRIP (6 << 0)
+#define RADEON_PRIM_TYPE_TRI_TYPE2 (7 << 0)
+#define RADEON_PRIM_TYPE_RECT_LIST (8 << 0)
+#define RADEON_PRIM_TYPE_3VRT_POINT_LIST (9 << 0)
+#define RADEON_PRIM_TYPE_3VRT_LINE_LIST (10 << 0)
+#define RADEON_PRIM_WALK_IND (1 << 4)
+#define RADEON_PRIM_WALK_LIST (2 << 4)
+#define RADEON_PRIM_WALK_RING (3 << 4)
+#define RADEON_COLOR_ORDER_BGRA (0 << 6)
+#define RADEON_COLOR_ORDER_RGBA (1 << 6)
+#define RADEON_MAOS_ENABLE (1 << 7)
+#define RADEON_VTX_FMT_R128_MODE (0 << 8)
+#define RADEON_VTX_FMT_RADEON_MODE (1 << 8)
+#define RADEON_NUM_VERTICES_SHIFT 16
+
+#define RADEON_COLOR_FORMAT_CI8 2
+#define RADEON_COLOR_FORMAT_ARGB1555 3
+#define RADEON_COLOR_FORMAT_RGB565 4
+#define RADEON_COLOR_FORMAT_ARGB8888 6
+#define RADEON_COLOR_FORMAT_RGB332 7
+#define RADEON_COLOR_FORMAT_RGB8 9
+#define RADEON_COLOR_FORMAT_ARGB4444 15
+
+#define RADEON_TXF_8BPP_I 0
+#define RADEON_TXF_16BPP_AI88 1
+#define RADEON_TXF_8BPP_RGB332 2
+#define RADEON_TXF_16BPP_ARGB1555 3
+#define RADEON_TXF_16BPP_RGB565 4
+#define RADEON_TXF_16BPP_ARGB4444 5
+#define RADEON_TXF_32BPP_ARGB8888 6
+#define RADEON_TXF_32BPP_RGBA8888 7
+
+/* Constants */
+#define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */
+
+#define RADEON_LAST_FRAME_REG RADEON_SCRATCH_REG0
+#define RADEON_LAST_DISPATCH_REG RADEON_SCRATCH_REG1
+#define RADEON_LAST_CLEAR_REG RADEON_SCRATCH_REG2
+#define RADEON_LAST_DISPATCH 1
+
+#define RADEON_MAX_VB_AGE 0x7fffffff
+#define RADEON_MAX_VB_VERTS (0xffff)
+
+
+#define RADEON_BASE(reg) ((u32)(dev_priv->mmio->handle))
+#define RADEON_ADDR(reg) (RADEON_BASE(reg) + reg)
+
+#define RADEON_DEREF(reg) *(__volatile__ u32 *)RADEON_ADDR(reg)
+#define RADEON_READ(reg) RADEON_DEREF(reg)
+#define RADEON_WRITE(reg,val) do { RADEON_DEREF(reg) = val; } while (0)
+
+#define RADEON_DEREF8(reg) *(__volatile__ u8 *)RADEON_ADDR(reg)
+#define RADEON_READ8(reg) RADEON_DEREF8(reg)
+#define RADEON_WRITE8(reg,val) do { RADEON_DEREF8(reg) = val; } while (0)
+
+#define RADEON_WRITE_PLL(addr,val) \
+do { \
+ RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, \
+ ((addr) & 0x1f) | RADEON_PLL_WR_EN); \
+ RADEON_WRITE(RADEON_CLOCK_CNTL_DATA, (val)); \
+} while (0)
+
+extern int RADEON_READ_PLL(drm_device_t *dev, int addr);
+
+
+
+#define CP_PACKET0( reg, n ) \
+ (RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
+#define CP_PACKET0_TABLE( reg, n ) \
+ (RADEON_CP_PACKET0 | RADEON_ONE_REG_WR | ((n) << 16) | ((reg) >> 2))
+#define CP_PACKET1( reg0, reg1 ) \
+ (RADEON_CP_PACKET1 | (((reg1) >> 2) << 15) | ((reg0) >> 2))
+#define CP_PACKET2() \
+ (RADEON_CP_PACKET2)
+#define CP_PACKET3( pkt, n ) \
+ (RADEON_CP_PACKET3 | (pkt) | ((n) << 16))
+
+
+/* ================================================================
+ * Engine control helper macros
+ */
+
+#define RADEON_WAIT_UNTIL_2D_IDLE() \
+do { \
+ OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \
+ OUT_RING( (RADEON_WAIT_2D_IDLECLEAN | \
+ RADEON_WAIT_HOST_IDLECLEAN) ); \
+} while (0)
+
+#define RADEON_WAIT_UNTIL_3D_IDLE() \
+do { \
+ OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \
+ OUT_RING( (RADEON_WAIT_3D_IDLECLEAN | \
+ RADEON_WAIT_HOST_IDLECLEAN) ); \
+} while (0)
+
+#define RADEON_WAIT_UNTIL_IDLE() \
+do { \
+ OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \
+ OUT_RING( (RADEON_WAIT_2D_IDLECLEAN | \
+ RADEON_WAIT_3D_IDLECLEAN | \
+ RADEON_WAIT_HOST_IDLECLEAN) ); \
+} while (0)
+
+#define RADEON_WAIT_UNTIL_PAGE_FLIPPED() \
+do { \
+ OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \
+ OUT_RING( RADEON_WAIT_CRTC_PFLIP ); \
+} while (0)
+
+#define RADEON_FLUSH_CACHE() \
+do { \
+ OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) ); \
+ OUT_RING( RADEON_RB2D_DC_FLUSH ); \
+} while (0)
+
+#define RADEON_PURGE_CACHE() \
+do { \
+ OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) ); \
+ OUT_RING( RADEON_RB2D_DC_FLUSH_ALL ); \
+} while (0)
+
+#define RADEON_FLUSH_ZCACHE() \
+do { \
+ OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) ); \
+ OUT_RING( RADEON_RB3D_ZC_FLUSH ); \
+} while (0)
+
+#define RADEON_PURGE_ZCACHE() \
+do { \
+ OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) ); \
+ OUT_RING( RADEON_RB3D_ZC_FLUSH_ALL ); \
+} while (0)
+
+
+/* ================================================================
+ * Misc helper macros
+ */
+
+#define VB_AGE_CHECK_WITH_RET( dev_priv ) \
+do { \
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; \
+ if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) { \
+ int __ret = radeon_do_cp_idle( dev_priv ); \
+ if ( __ret < 0 ) return __ret; \
+ sarea_priv->last_dispatch = 0; \
+ radeon_freelist_reset( dev ); \
+ } \
+} while (0)
+
+#define RADEON_DISPATCH_AGE( age ) \
+do { \
+ OUT_RING( CP_PACKET0( RADEON_LAST_DISPATCH_REG, 0 ) ); \
+ OUT_RING( age ); \
+} while (0)
+
+#define RADEON_FRAME_AGE( age ) \
+do { \
+ OUT_RING( CP_PACKET0( RADEON_LAST_FRAME_REG, 0 ) ); \
+ OUT_RING( age ); \
+} while (0)
+
+#define RADEON_CLEAR_AGE( age ) \
+do { \
+ OUT_RING( CP_PACKET0( RADEON_LAST_CLEAR_REG, 0 ) ); \
+ OUT_RING( age ); \
+} while (0)
+
+
+/* ================================================================
+ * Ring control
+ */
+
+#define radeon_flush_write_combine() mb()
+
+
+#define RADEON_VERBOSE 0
+
+#define RING_LOCALS int write; unsigned int mask; volatile u32 *ring;
+
+#define BEGIN_RING( n ) do { \
+ if ( RADEON_VERBOSE ) { \
+ DRM_INFO( "BEGIN_RING( %d ) in %s\n", \
+ n, __FUNCTION__ ); \
+ } \
+ if ( dev_priv->ring.space < (n) * sizeof(u32) ) { \
+ radeon_wait_ring( dev_priv, (n) * sizeof(u32) ); \
+ } \
+ dev_priv->ring.space -= (n) * sizeof(u32); \
+ ring = dev_priv->ring.start; \
+ write = dev_priv->ring.tail; \
+ mask = dev_priv->ring.tail_mask; \
+} while (0)
+
+#define ADVANCE_RING() do { \
+ if ( RADEON_VERBOSE ) { \
+ DRM_INFO( "ADVANCE_RING() tail=0x%06x wr=0x%06x\n", \
+ write, dev_priv->ring.tail ); \
+ } \
+ radeon_flush_write_combine(); \
+ dev_priv->ring.tail = write; \
+ RADEON_WRITE( RADEON_CP_RB_WPTR, write ); \
+} while (0)
+
+#define OUT_RING( x ) do { \
+ if ( RADEON_VERBOSE ) { \
+ DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \
+ (unsigned int)(x), write ); \
+ } \
+ ring[write++] = (x); \
+ write &= mask; \
+} while (0)
+
+#define RADEON_PERFORMANCE_BOXES 0
+
+#endif /* __RADEON_DRV_H__ */
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
new file mode 100644
index 000000000..1a4da8005
--- /dev/null
+++ b/drivers/char/drm/radeon_state.c
@@ -0,0 +1,1447 @@
+/* radeon_state.c -- State support for Radeon -*- linux-c -*-
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+#include "radeon_drv.h"
+#include "drm.h"
+#include <linux/delay.h>
+
+
+/* ================================================================
+ * CP hardware state programming functions
+ */
+
+static inline void radeon_emit_clip_rect( drm_radeon_private_t *dev_priv,
+ drm_clip_rect_t *box )
+{
+ RING_LOCALS;
+
+ DRM_DEBUG( " box: x1=%d y1=%d x2=%d y2=%d\n",
+ box->x1, box->y1, box->x2, box->y2 );
+
+ BEGIN_RING( 4 );
+
+ OUT_RING( CP_PACKET0( RADEON_RE_TOP_LEFT, 0 ) );
+ OUT_RING( (box->y1 << 16) | box->x1 );
+
+ OUT_RING( CP_PACKET0( RADEON_RE_WIDTH_HEIGHT, 0 ) );
+ OUT_RING( ((box->y2 - 1) << 16) | (box->x2 - 1) );
+
+ ADVANCE_RING();
+}
+
+static inline void radeon_emit_context( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 14 );
+
+ OUT_RING( CP_PACKET0( RADEON_PP_MISC, 6 ) );
+ OUT_RING( ctx->pp_misc );
+ OUT_RING( ctx->pp_fog_color );
+ OUT_RING( ctx->re_solid_color );
+ OUT_RING( ctx->rb3d_blendcntl );
+ OUT_RING( ctx->rb3d_depthoffset );
+ OUT_RING( ctx->rb3d_depthpitch );
+ OUT_RING( ctx->rb3d_zstencilcntl );
+
+ OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 2 ) );
+ OUT_RING( ctx->pp_cntl );
+ OUT_RING( ctx->rb3d_cntl );
+ OUT_RING( ctx->rb3d_coloroffset );
+
+ OUT_RING( CP_PACKET0( RADEON_RB3D_COLORPITCH, 0 ) );
+ OUT_RING( ctx->rb3d_colorpitch );
+
+ ADVANCE_RING();
+}
+
+static inline void radeon_emit_vertfmt( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 2 );
+
+ OUT_RING( CP_PACKET0( RADEON_SE_COORD_FMT, 0 ) );
+ OUT_RING( ctx->se_coord_fmt );
+
+ ADVANCE_RING();
+}
+
+static inline void radeon_emit_line( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 5 );
+
+ OUT_RING( CP_PACKET0( RADEON_RE_LINE_PATTERN, 1 ) );
+ OUT_RING( ctx->re_line_pattern );
+ OUT_RING( ctx->re_line_state );
+
+ OUT_RING( CP_PACKET0( RADEON_SE_LINE_WIDTH, 0 ) );
+ OUT_RING( ctx->se_line_width );
+
+ ADVANCE_RING();
+}
+
+static inline void radeon_emit_bumpmap( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 5 );
+
+ OUT_RING( CP_PACKET0( RADEON_PP_LUM_MATRIX, 0 ) );
+ OUT_RING( ctx->pp_lum_matrix );
+
+ OUT_RING( CP_PACKET0( RADEON_PP_ROT_MATRIX_0, 1 ) );
+ OUT_RING( ctx->pp_rot_matrix_0 );
+ OUT_RING( ctx->pp_rot_matrix_1 );
+
+ ADVANCE_RING();
+}
+
+static inline void radeon_emit_masks( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 4 );
+
+ OUT_RING( CP_PACKET0( RADEON_RB3D_STENCILREFMASK, 2 ) );
+ OUT_RING( ctx->rb3d_stencilrefmask );
+ OUT_RING( ctx->rb3d_ropcntl );
+ OUT_RING( ctx->rb3d_planemask );
+
+ ADVANCE_RING();
+}
+
+static inline void radeon_emit_viewport( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 7 );
+
+ OUT_RING( CP_PACKET0( RADEON_SE_VPORT_XSCALE, 5 ) );
+ OUT_RING( ctx->se_vport_xscale );
+ OUT_RING( ctx->se_vport_xoffset );
+ OUT_RING( ctx->se_vport_yscale );
+ OUT_RING( ctx->se_vport_yoffset );
+ OUT_RING( ctx->se_vport_zscale );
+ OUT_RING( ctx->se_vport_zoffset );
+
+ ADVANCE_RING();
+}
+
+static inline void radeon_emit_setup( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 4 );
+
+ OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) );
+ OUT_RING( ctx->se_cntl );
+ OUT_RING( CP_PACKET0( RADEON_SE_CNTL_STATUS, 0 ) );
+ OUT_RING( ctx->se_cntl_status );
+
+ ADVANCE_RING();
+}
+
+static inline void radeon_emit_tcl( drm_radeon_private_t *dev_priv )
+{
+#ifdef TCL_ENABLE
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 29 );
+
+ OUT_RING( CP_PACKET0( RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 27 ) );
+ OUT_RING( ctx->se_tcl_material_emmissive.red );
+ OUT_RING( ctx->se_tcl_material_emmissive.green );
+ OUT_RING( ctx->se_tcl_material_emmissive.blue );
+ OUT_RING( ctx->se_tcl_material_emmissive.alpha );
+ OUT_RING( ctx->se_tcl_material_ambient.red );
+ OUT_RING( ctx->se_tcl_material_ambient.green );
+ OUT_RING( ctx->se_tcl_material_ambient.blue );
+ OUT_RING( ctx->se_tcl_material_ambient.alpha );
+ OUT_RING( ctx->se_tcl_material_diffuse.red );
+ OUT_RING( ctx->se_tcl_material_diffuse.green );
+ OUT_RING( ctx->se_tcl_material_diffuse.blue );
+ OUT_RING( ctx->se_tcl_material_diffuse.alpha );
+ OUT_RING( ctx->se_tcl_material_specular.red );
+ OUT_RING( ctx->se_tcl_material_specular.green );
+ OUT_RING( ctx->se_tcl_material_specular.blue );
+ OUT_RING( ctx->se_tcl_material_specular.alpha );
+ OUT_RING( ctx->se_tcl_shininess );
+ OUT_RING( ctx->se_tcl_output_vtx_fmt );
+ OUT_RING( ctx->se_tcl_output_vtx_sel );
+ OUT_RING( ctx->se_tcl_matrix_select_0 );
+ OUT_RING( ctx->se_tcl_matrix_select_1 );
+ OUT_RING( ctx->se_tcl_ucp_vert_blend_ctl );
+ OUT_RING( ctx->se_tcl_texture_proc_ctl );
+ OUT_RING( ctx->se_tcl_light_model_ctl );
+ for ( i = 0 ; i < 4 ; i++ ) {
+ OUT_RING( ctx->se_tcl_per_light_ctl[i] );
+ }
+
+ ADVANCE_RING();
+#else
+ DRM_ERROR( "TCL not enabled!\n" );
+#endif
+}
+
+static inline void radeon_emit_misc( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 2 );
+
+ OUT_RING( CP_PACKET0( RADEON_RE_MISC, 0 ) );
+ OUT_RING( ctx->re_misc );
+
+ ADVANCE_RING();
+}
+
+static inline void radeon_emit_tex0( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[0];
+ RING_LOCALS;
+ DRM_DEBUG( " %s: offset=0x%x\n", __FUNCTION__, tex->pp_txoffset );
+
+ BEGIN_RING( 9 );
+
+ OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) );
+ OUT_RING( tex->pp_txfilter );
+ OUT_RING( tex->pp_txformat );
+ OUT_RING( tex->pp_txoffset );
+ OUT_RING( tex->pp_txcblend );
+ OUT_RING( tex->pp_txablend );
+ OUT_RING( tex->pp_tfactor );
+
+ OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_0, 0 ) );
+ OUT_RING( tex->pp_border_color );
+
+ ADVANCE_RING();
+}
+
+static inline void radeon_emit_tex1( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[1];
+ RING_LOCALS;
+ DRM_DEBUG( " %s: offset=0x%x\n", __FUNCTION__, tex->pp_txoffset );
+
+ BEGIN_RING( 9 );
+
+ OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) );
+ OUT_RING( tex->pp_txfilter );
+ OUT_RING( tex->pp_txformat );
+ OUT_RING( tex->pp_txoffset );
+ OUT_RING( tex->pp_txcblend );
+ OUT_RING( tex->pp_txablend );
+ OUT_RING( tex->pp_tfactor );
+
+ OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_1, 0 ) );
+ OUT_RING( tex->pp_border_color );
+
+ ADVANCE_RING();
+}
+
+static inline void radeon_emit_tex2( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[2];
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 9 );
+
+ OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) );
+ OUT_RING( tex->pp_txfilter );
+ OUT_RING( tex->pp_txformat );
+ OUT_RING( tex->pp_txoffset );
+ OUT_RING( tex->pp_txcblend );
+ OUT_RING( tex->pp_txablend );
+ OUT_RING( tex->pp_tfactor );
+
+ OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_2, 0 ) );
+ OUT_RING( tex->pp_border_color );
+
+ ADVANCE_RING();
+}
+
+static inline void radeon_emit_state( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int dirty = sarea_priv->dirty;
+
+ DRM_DEBUG( "%s: dirty=0x%08x\n", __FUNCTION__, dirty );
+
+ if ( dirty & RADEON_UPLOAD_CONTEXT ) {
+ radeon_emit_context( dev_priv );
+ sarea_priv->dirty &= ~RADEON_UPLOAD_CONTEXT;
+ }
+
+ if ( dirty & RADEON_UPLOAD_VERTFMT ) {
+ radeon_emit_vertfmt( dev_priv );
+ sarea_priv->dirty &= ~RADEON_UPLOAD_VERTFMT;
+ }
+
+ if ( dirty & RADEON_UPLOAD_LINE ) {
+ radeon_emit_line( dev_priv );
+ sarea_priv->dirty &= ~RADEON_UPLOAD_LINE;
+ }
+
+ if ( dirty & RADEON_UPLOAD_BUMPMAP ) {
+ radeon_emit_bumpmap( dev_priv );
+ sarea_priv->dirty &= ~RADEON_UPLOAD_BUMPMAP;
+ }
+
+ if ( dirty & RADEON_UPLOAD_MASKS ) {
+ radeon_emit_masks( dev_priv );
+ sarea_priv->dirty &= ~RADEON_UPLOAD_MASKS;
+ }
+
+ if ( dirty & RADEON_UPLOAD_VIEWPORT ) {
+ radeon_emit_viewport( dev_priv );
+ sarea_priv->dirty &= ~RADEON_UPLOAD_VIEWPORT;
+ }
+
+ if ( dirty & RADEON_UPLOAD_SETUP ) {
+ radeon_emit_setup( dev_priv );
+ sarea_priv->dirty &= ~RADEON_UPLOAD_SETUP;
+ }
+
+ if ( dirty & RADEON_UPLOAD_TCL ) {
+#ifdef TCL_ENABLE
+ radeon_emit_tcl( dev_priv );
+#endif
+ sarea_priv->dirty &= ~RADEON_UPLOAD_TCL;
+ }
+
+ if ( dirty & RADEON_UPLOAD_MISC ) {
+ radeon_emit_misc( dev_priv );
+ sarea_priv->dirty &= ~RADEON_UPLOAD_MISC;
+ }
+
+ if ( dirty & RADEON_UPLOAD_TEX0 ) {
+ radeon_emit_tex0( dev_priv );
+ sarea_priv->dirty &= ~RADEON_UPLOAD_TEX0;
+ }
+
+ if ( dirty & RADEON_UPLOAD_TEX1 ) {
+ radeon_emit_tex1( dev_priv );
+ sarea_priv->dirty &= ~RADEON_UPLOAD_TEX1;
+ }
+
+ if ( dirty & RADEON_UPLOAD_TEX2 ) {
+#if 0
+ radeon_emit_tex2( dev_priv );
+#endif
+ sarea_priv->dirty &= ~RADEON_UPLOAD_TEX2;
+ }
+
+ sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
+ RADEON_UPLOAD_TEX1IMAGES |
+ RADEON_UPLOAD_TEX2IMAGES |
+ RADEON_REQUIRE_QUIESCENCE);
+}
+
+
+#if RADEON_PERFORMANCE_BOXES
+/* ================================================================
+ * Performance monitoring functions
+ */
+
+static void radeon_clear_box( drm_radeon_private_t *dev_priv,
+ int x, int y, int w, int h,
+ int r, int g, int b )
+{
+ u32 pitch, offset;
+ u32 color;
+ RING_LOCALS;
+
+ switch ( dev_priv->color_fmt ) {
+ case RADEON_COLOR_FORMAT_RGB565:
+ color = (((r & 0xf8) << 8) |
+ ((g & 0xfc) << 3) |
+ ((b & 0xf8) >> 3));
+ break;
+ case RADEON_COLOR_FORMAT_ARGB8888:
+ default:
+ color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
+ break;
+ }
+
+ offset = dev_priv->back_offset;
+ pitch = dev_priv->back_pitch >> 3;
+
+ BEGIN_RING( 6 );
+
+ OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
+ OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+ RADEON_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->color_fmt << 8) |
+ RADEON_GMC_SRC_DATATYPE_COLOR |
+ RADEON_ROP3_P |
+ RADEON_GMC_CLR_CMP_CNTL_DIS );
+
+ OUT_RING( (pitch << 22) | (offset >> 5) );
+ OUT_RING( color );
+
+ OUT_RING( (x << 16) | y );
+ OUT_RING( (w << 16) | h );
+
+ ADVANCE_RING();
+}
+
+static void radeon_cp_performance_boxes( drm_radeon_private_t *dev_priv )
+{
+ if ( atomic_read( &dev_priv->idle_count ) == 0 ) {
+ radeon_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 );
+ } else {
+ atomic_set( &dev_priv->idle_count, 0 );
+ }
+}
+
+#endif
+
+
+/* ================================================================
+ * CP command dispatch functions
+ */
+
+static void radeon_print_dirty( const char *msg, unsigned int flags )
+{
+ DRM_DEBUG( "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+ msg,
+ flags,
+ (flags & RADEON_UPLOAD_CONTEXT) ? "context, " : "",
+ (flags & RADEON_UPLOAD_VERTFMT) ? "vertfmt, " : "",
+ (flags & RADEON_UPLOAD_LINE) ? "line, " : "",
+ (flags & RADEON_UPLOAD_BUMPMAP) ? "bumpmap, " : "",
+ (flags & RADEON_UPLOAD_MASKS) ? "masks, " : "",
+ (flags & RADEON_UPLOAD_VIEWPORT) ? "viewport, " : "",
+ (flags & RADEON_UPLOAD_SETUP) ? "setup, " : "",
+ (flags & RADEON_UPLOAD_TCL) ? "tcl, " : "",
+ (flags & RADEON_UPLOAD_MISC) ? "misc, " : "",
+ (flags & RADEON_UPLOAD_TEX0) ? "tex0, " : "",
+ (flags & RADEON_UPLOAD_TEX1) ? "tex1, " : "",
+ (flags & RADEON_UPLOAD_TEX2) ? "tex2, " : "",
+ (flags & RADEON_UPLOAD_CLIPRECTS) ? "cliprects, " : "",
+ (flags & RADEON_REQUIRE_QUIESCENCE) ? "quiescence, " : "" );
+}
+
+static void radeon_cp_dispatch_clear( drm_device_t *dev,
+ drm_radeon_clear_t *clear )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int nbox = sarea_priv->nbox;
+ drm_clip_rect_t *pbox = sarea_priv->boxes;
+ unsigned int flags = clear->flags;
+ int i;
+ RING_LOCALS;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ radeon_update_ring_snapshot( dev_priv );
+
+ if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
+ unsigned int tmp = flags;
+
+ flags &= ~(RADEON_FRONT | RADEON_BACK);
+ if ( tmp & RADEON_FRONT ) flags |= RADEON_BACK;
+ if ( tmp & RADEON_BACK ) flags |= RADEON_FRONT;
+ }
+
+ for ( i = 0 ; i < nbox ; i++ ) {
+ int x = pbox[i].x1;
+ int y = pbox[i].y1;
+ int w = pbox[i].x2 - x;
+ int h = pbox[i].y2 - y;
+
+ DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n",
+ x, y, w, h, flags );
+
+ if ( flags & (RADEON_FRONT | RADEON_BACK) ) {
+ BEGIN_RING( 4 );
+
+ /* Ensure the 3D stream is idle before doing a
+ * 2D fill to clear the front or back buffer.
+ */
+ RADEON_WAIT_UNTIL_3D_IDLE();
+
+ OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
+ OUT_RING( sarea_priv->context_state.rb3d_planemask );
+
+ ADVANCE_RING();
+
+ /* Make sure we restore the 3D state next time.
+ */
+ dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT |
+ RADEON_UPLOAD_MASKS);
+ }
+
+ if ( flags & RADEON_FRONT ) {
+ BEGIN_RING( 6 );
+
+ OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
+ OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+ RADEON_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->color_fmt << 8) |
+ RADEON_GMC_SRC_DATATYPE_COLOR |
+ RADEON_ROP3_P |
+ RADEON_GMC_CLR_CMP_CNTL_DIS );
+
+ OUT_RING( dev_priv->front_pitch_offset );
+ OUT_RING( clear->clear_color );
+
+ OUT_RING( (x << 16) | y );
+ OUT_RING( (w << 16) | h );
+
+ ADVANCE_RING();
+ }
+
+ if ( flags & RADEON_BACK ) {
+ BEGIN_RING( 6 );
+
+ OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
+ OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+ RADEON_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->color_fmt << 8) |
+ RADEON_GMC_SRC_DATATYPE_COLOR |
+ RADEON_ROP3_P |
+ RADEON_GMC_CLR_CMP_CNTL_DIS );
+
+ OUT_RING( dev_priv->back_pitch_offset );
+ OUT_RING( clear->clear_color );
+
+ OUT_RING( (x << 16) | y );
+ OUT_RING( (w << 16) | h );
+
+ ADVANCE_RING();
+
+ }
+
+ if ( flags & RADEON_DEPTH ) {
+ drm_radeon_depth_clear_t *depth_clear =
+ &dev_priv->depth_clear;
+
+ if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
+ radeon_emit_state( dev_priv );
+ }
+
+ /* FIXME: Render a rectangle to clear the depth
+ * buffer. So much for those "fast Z clears"...
+ */
+ BEGIN_RING( 23 );
+
+ RADEON_WAIT_UNTIL_2D_IDLE();
+
+ OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 1 ) );
+ OUT_RING( 0x00000000 );
+ OUT_RING( depth_clear->rb3d_cntl );
+ OUT_RING( CP_PACKET0( RADEON_RB3D_ZSTENCILCNTL, 0 ) );
+ OUT_RING( depth_clear->rb3d_zstencilcntl );
+ OUT_RING( CP_PACKET0( RADEON_RB3D_PLANEMASK, 0 ) );
+ OUT_RING( 0x00000000 );
+ OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) );
+ OUT_RING( depth_clear->se_cntl );
+
+ OUT_RING( CP_PACKET3( RADEON_3D_DRAW_IMMD, 10 ) );
+ OUT_RING( RADEON_VTX_Z_PRESENT );
+ OUT_RING( (RADEON_PRIM_TYPE_RECT_LIST |
+ RADEON_PRIM_WALK_RING |
+ RADEON_MAOS_ENABLE |
+ RADEON_VTX_FMT_RADEON_MODE |
+ (3 << RADEON_NUM_VERTICES_SHIFT)) );
+
+ OUT_RING( clear->rect.ui[CLEAR_X1] );
+ OUT_RING( clear->rect.ui[CLEAR_Y1] );
+ OUT_RING( clear->rect.ui[CLEAR_DEPTH] );
+
+ OUT_RING( clear->rect.ui[CLEAR_X1] );
+ OUT_RING( clear->rect.ui[CLEAR_Y2] );
+ OUT_RING( clear->rect.ui[CLEAR_DEPTH] );
+
+ OUT_RING( clear->rect.ui[CLEAR_X2] );
+ OUT_RING( clear->rect.ui[CLEAR_Y2] );
+ OUT_RING( clear->rect.ui[CLEAR_DEPTH] );
+
+ ADVANCE_RING();
+
+ /* Make sure we restore the 3D state next time.
+ */
+ dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT |
+ RADEON_UPLOAD_SETUP |
+ RADEON_UPLOAD_MASKS);
+ }
+ }
+
+ /* Increment the clear counter. The client-side 3D driver must
+ * wait on this value before performing the clear ioctl. We
+ * need this because the card's so damned fast...
+ */
+ dev_priv->sarea_priv->last_clear++;
+
+ BEGIN_RING( 4 );
+
+ RADEON_CLEAR_AGE( dev_priv->sarea_priv->last_clear );
+ RADEON_WAIT_UNTIL_IDLE();
+
+ ADVANCE_RING();
+}
+
+static void radeon_cp_dispatch_swap( drm_device_t *dev )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int nbox = sarea_priv->nbox;
+ drm_clip_rect_t *pbox = sarea_priv->boxes;
+ int i;
+ RING_LOCALS;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ radeon_update_ring_snapshot( dev_priv );
+
+#if RADEON_PERFORMANCE_BOXES
+ /* Do some trivial performance monitoring...
+ */
+ radeon_cp_performance_boxes( dev_priv );
+#endif
+
+ /* Wait for the 3D stream to idle before dispatching the bitblt.
+ * This will prevent data corruption between the two streams.
+ */
+ BEGIN_RING( 2 );
+
+ RADEON_WAIT_UNTIL_3D_IDLE();
+
+ ADVANCE_RING();
+
+ for ( i = 0 ; i < nbox ; i++ ) {
+ int x = pbox[i].x1;
+ int y = pbox[i].y1;
+ int w = pbox[i].x2 - x;
+ int h = pbox[i].y2 - y;
+
+ DRM_DEBUG( "dispatch swap %d,%d-%d,%d\n",
+ x, y, w, h );
+
+ BEGIN_RING( 7 );
+
+ OUT_RING( CP_PACKET3( RADEON_CNTL_BITBLT_MULTI, 5 ) );
+ OUT_RING( RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
+ RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+ RADEON_GMC_BRUSH_NONE |
+ (dev_priv->color_fmt << 8) |
+ RADEON_GMC_SRC_DATATYPE_COLOR |
+ RADEON_ROP3_S |
+ RADEON_DP_SRC_SOURCE_MEMORY |
+ RADEON_GMC_CLR_CMP_CNTL_DIS |
+ RADEON_GMC_WR_MSK_DIS );
+
+ OUT_RING( dev_priv->back_pitch_offset );
+ OUT_RING( dev_priv->front_pitch_offset );
+
+ OUT_RING( (x << 16) | y );
+ OUT_RING( (x << 16) | y );
+ OUT_RING( (w << 16) | h );
+
+ ADVANCE_RING();
+ }
+
+ /* Increment the frame counter. The client-side 3D driver must
+ * throttle the framerate by waiting for this value before
+ * performing the swapbuffer ioctl.
+ */
+ dev_priv->sarea_priv->last_frame++;
+
+ BEGIN_RING( 4 );
+
+ RADEON_FRAME_AGE( dev_priv->sarea_priv->last_frame );
+ RADEON_WAIT_UNTIL_2D_IDLE();
+
+ ADVANCE_RING();
+}
+
+static void radeon_cp_dispatch_flip( drm_device_t *dev )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+ DRM_DEBUG( "%s: page=%d\n", __FUNCTION__, dev_priv->current_page );
+
+ radeon_update_ring_snapshot( dev_priv );
+
+#if RADEON_PERFORMANCE_BOXES
+ /* Do some trivial performance monitoring...
+ */
+ radeon_cp_performance_boxes( dev_priv );
+#endif
+
+ BEGIN_RING( 6 );
+
+ RADEON_WAIT_UNTIL_3D_IDLE();
+ RADEON_WAIT_UNTIL_PAGE_FLIPPED();
+
+ OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET, 0 ) );
+
+ if ( dev_priv->current_page == 0 ) {
+ OUT_RING( dev_priv->back_offset );
+ dev_priv->current_page = 1;
+ } else {
+ OUT_RING( dev_priv->front_offset );
+ dev_priv->current_page = 0;
+ }
+
+ ADVANCE_RING();
+
+ /* Increment the frame counter. The client-side 3D driver must
+ * throttle the framerate by waiting for this value before
+ * performing the swapbuffer ioctl.
+ */
+ dev_priv->sarea_priv->last_frame++;
+
+ BEGIN_RING( 2 );
+
+ RADEON_FRAME_AGE( dev_priv->sarea_priv->last_frame );
+
+ ADVANCE_RING();
+}
+
+static void radeon_cp_dispatch_vertex( drm_device_t *dev,
+ drm_buf_t *buf )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int format = sarea_priv->vc_format;
+ int offset = dev_priv->agp_buffers_offset + buf->offset;
+ int size = buf->used;
+ int prim = buf_priv->prim;
+ int i = 0;
+ RING_LOCALS;
+ DRM_DEBUG( "%s: nbox=%d\n", __FUNCTION__, sarea_priv->nbox );
+
+ radeon_update_ring_snapshot( dev_priv );
+
+ if ( 0 )
+ radeon_print_dirty( "dispatch_vertex", sarea_priv->dirty );
+
+ if ( buf->used ) {
+ buf_priv->dispatched = 1;
+
+ if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
+ radeon_emit_state( dev_priv );
+ }
+
+ do {
+ /* Emit the next set of up to three cliprects */
+ if ( i < sarea_priv->nbox ) {
+ radeon_emit_clip_rect( dev_priv,
+ &sarea_priv->boxes[i] );
+ }
+
+ /* Emit the vertex buffer rendering commands */
+ BEGIN_RING( 5 );
+
+ OUT_RING( CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, 3 ) );
+ OUT_RING( offset );
+ OUT_RING( size );
+ OUT_RING( format );
+ OUT_RING( prim | RADEON_PRIM_WALK_LIST |
+ RADEON_COLOR_ORDER_RGBA |
+ RADEON_VTX_FMT_RADEON_MODE |
+ (size << RADEON_NUM_VERTICES_SHIFT) );
+
+ ADVANCE_RING();
+
+ i++;
+ } while ( i < sarea_priv->nbox );
+ }
+
+ if ( buf_priv->discard ) {
+ buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+ /* Emit the vertex buffer age */
+ BEGIN_RING( 2 );
+ RADEON_DISPATCH_AGE( buf_priv->age );
+ ADVANCE_RING();
+
+ buf->pending = 1;
+ buf->used = 0;
+ /* FIXME: Check dispatched field */
+ buf_priv->dispatched = 0;
+ }
+
+ dev_priv->sarea_priv->last_dispatch++;
+
+ sarea_priv->dirty &= ~RADEON_UPLOAD_CLIPRECTS;
+ sarea_priv->nbox = 0;
+}
+
+
+static void radeon_cp_dispatch_indirect( drm_device_t *dev,
+ drm_buf_t *buf,
+ int start, int end )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+ RING_LOCALS;
+ DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
+ buf->idx, start, end );
+
+ radeon_update_ring_snapshot( dev_priv );
+
+ if ( start != end ) {
+ int offset = (dev_priv->agp_buffers_offset
+ + buf->offset + start);
+ int dwords = (end - start + 3) / sizeof(u32);
+
+ /* Indirect buffer data must be an even number of
+ * dwords, so if we've been given an odd number we must
+ * pad the data with a Type-2 CP packet.
+ */
+ if ( dwords & 1 ) {
+ u32 *data = (u32 *)
+ ((char *)dev_priv->buffers->handle
+ + buf->offset + start);
+ data[dwords++] = RADEON_CP_PACKET2;
+ }
+
+ buf_priv->dispatched = 1;
+
+ /* Fire off the indirect buffer */
+ BEGIN_RING( 3 );
+
+ OUT_RING( CP_PACKET0( RADEON_CP_IB_BASE, 1 ) );
+ OUT_RING( offset );
+ OUT_RING( dwords );
+
+ ADVANCE_RING();
+ }
+
+ if ( buf_priv->discard ) {
+ buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+ /* Emit the indirect buffer age */
+ BEGIN_RING( 2 );
+ RADEON_DISPATCH_AGE( buf_priv->age );
+ ADVANCE_RING();
+
+ buf->pending = 1;
+ buf->used = 0;
+ /* FIXME: Check dispatched field */
+ buf_priv->dispatched = 0;
+ }
+
+ dev_priv->sarea_priv->last_dispatch++;
+}
+
+static void radeon_cp_dispatch_indices( drm_device_t *dev,
+ drm_buf_t *buf,
+ int start, int end,
+ int count )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int format = sarea_priv->vc_format;
+ int offset = dev_priv->agp_buffers_offset;
+ int prim = buf_priv->prim;
+ u32 *data;
+ int dwords;
+ int i = 0;
+ RING_LOCALS;
+ DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
+
+ radeon_update_ring_snapshot( dev_priv );
+
+ if ( 0 )
+ radeon_print_dirty( "dispatch_indices", sarea_priv->dirty );
+
+ if ( start != end ) {
+ buf_priv->dispatched = 1;
+
+ if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
+ radeon_emit_state( dev_priv );
+ }
+
+ dwords = (end - start + 3) / sizeof(u32);
+
+ data = (u32 *)((char *)dev_priv->buffers->handle
+ + buf->offset + start);
+
+ data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 );
+
+ data[1] = offset;
+ data[2] = RADEON_MAX_VB_VERTS;
+ data[3] = format;
+ data[4] = (prim | RADEON_PRIM_WALK_IND |
+ RADEON_COLOR_ORDER_RGBA |
+ RADEON_VTX_FMT_RADEON_MODE |
+ (count << RADEON_NUM_VERTICES_SHIFT) );
+
+ if ( count & 0x1 ) {
+ data[dwords-1] &= 0x0000ffff;
+ }
+
+ do {
+ /* Emit the next set of up to three cliprects */
+ if ( i < sarea_priv->nbox ) {
+ radeon_emit_clip_rect( dev_priv,
+ &sarea_priv->boxes[i] );
+ }
+
+ radeon_cp_dispatch_indirect( dev, buf, start, end );
+
+ i++;
+ } while ( i < sarea_priv->nbox );
+ }
+
+ if ( buf_priv->discard ) {
+ buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+ /* Emit the vertex buffer age */
+ BEGIN_RING( 2 );
+ RADEON_DISPATCH_AGE( buf_priv->age );
+ ADVANCE_RING();
+
+ buf->pending = 1;
+ /* FIXME: Check dispatched field */
+ buf_priv->dispatched = 0;
+ }
+
+ dev_priv->sarea_priv->last_dispatch++;
+
+ sarea_priv->dirty &= ~RADEON_UPLOAD_CLIPRECTS;
+ sarea_priv->nbox = 0;
+}
+
+static int radeon_cp_dispatch_blit( drm_device_t *dev,
+ drm_radeon_blit_t *blit )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_radeon_buf_priv_t *buf_priv;
+ u32 format;
+ u32 *data;
+ int dword_shift, dwords;
+ RING_LOCALS;
+ DRM_DEBUG( "blit: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
+ blit->offset >> 10, blit->pitch, blit->format,
+ blit->x, blit->y, blit->width, blit->height );
+
+ radeon_update_ring_snapshot( dev_priv );
+
+ /* The compiler won't optimize away a division by a variable,
+ * even if the only legal values are powers of two. Thus, we'll
+ * use a shift instead.
+ */
+ switch ( blit->format ) {
+ case RADEON_TXF_32BPP_ARGB8888:
+ case RADEON_TXF_32BPP_RGBA8888:
+ format = RADEON_COLOR_FORMAT_ARGB8888;
+ dword_shift = 0;
+ break;
+ case RADEON_TXF_16BPP_AI88:
+ case RADEON_TXF_16BPP_ARGB1555:
+ case RADEON_TXF_16BPP_RGB565:
+ case RADEON_TXF_16BPP_ARGB4444:
+ format = RADEON_COLOR_FORMAT_RGB565;
+ dword_shift = 1;
+ break;
+ case RADEON_TXF_8BPP_I:
+ case RADEON_TXF_8BPP_RGB332:
+ format = RADEON_COLOR_FORMAT_CI8;
+ dword_shift = 2;
+ break;
+ default:
+ DRM_ERROR( "invalid blit format %d\n", blit->format );
+ return -EINVAL;
+ }
+
+ /* Flush the pixel cache. This ensures no pixel data gets mixed
+ * up with the texture data from the host data blit, otherwise
+ * part of the texture image may be corrupted.
+ */
+ BEGIN_RING( 4 );
+
+ RADEON_FLUSH_CACHE();
+ RADEON_WAIT_UNTIL_IDLE();
+
+ ADVANCE_RING();
+
+ /* Dispatch the indirect buffer.
+ */
+ buf = dma->buflist[blit->idx];
+ buf_priv = buf->dev_private;
+
+ if ( buf->pid != current->pid ) {
+ DRM_ERROR( "process %d using buffer owned by %d\n",
+ current->pid, buf->pid );
+ return -EINVAL;
+ }
+ if ( buf->pending ) {
+ DRM_ERROR( "sending pending buffer %d\n", blit->idx );
+ return -EINVAL;
+ }
+
+ buf_priv->discard = 1;
+
+ dwords = (blit->width * blit->height) >> dword_shift;
+ if ( !dwords ) dwords = 1;
+
+ data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
+
+ data[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 );
+ data[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+ RADEON_GMC_BRUSH_NONE |
+ (format << 8) |
+ RADEON_GMC_SRC_DATATYPE_COLOR |
+ RADEON_ROP3_S |
+ RADEON_DP_SRC_SOURCE_HOST_DATA |
+ RADEON_GMC_CLR_CMP_CNTL_DIS |
+ RADEON_GMC_WR_MSK_DIS);
+
+ data[2] = (blit->pitch << 22) | (blit->offset >> 10);
+ data[3] = 0xffffffff;
+ data[4] = 0xffffffff;
+ data[5] = (blit->y << 16) | blit->x;
+ data[6] = (blit->height << 16) | blit->width;
+ data[7] = dwords;
+
+ buf->used = (dwords + 8) * sizeof(u32);
+
+ radeon_cp_dispatch_indirect( dev, buf, 0, buf->used );
+
+ /* Flush the pixel cache after the blit completes. This ensures
+ * the texture data is written out to memory before rendering
+ * continues.
+ */
+ BEGIN_RING( 4 );
+
+ RADEON_FLUSH_CACHE();
+ RADEON_WAIT_UNTIL_2D_IDLE();
+
+ ADVANCE_RING();
+
+ return 0;
+}
+
+static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ int i;
+ RING_LOCALS;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ radeon_update_ring_snapshot( dev_priv );
+
+ BEGIN_RING( 35 );
+
+ OUT_RING( CP_PACKET0( RADEON_RE_STIPPLE_ADDR, 0 ) );
+ OUT_RING( 0x00000000 );
+
+ OUT_RING( CP_PACKET0_TABLE( RADEON_RE_STIPPLE_DATA, 31 ) );
+ for ( i = 0 ; i < 32 ; i++ ) {
+ OUT_RING( stipple[i] );
+ }
+
+ ADVANCE_RING();
+}
+
+
+/* ================================================================
+ * IOCTL functions
+ */
+
+int radeon_cp_clear( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_clear_t clear;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+ dev->lock.pid != current->pid ) {
+ DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+
+ if ( copy_from_user( &clear, (drm_radeon_clear_t *) arg,
+ sizeof(clear) ) )
+ return -EFAULT;
+
+ if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
+ sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
+
+ radeon_cp_dispatch_clear( dev, &clear );
+
+ return 0;
+}
+
+int radeon_cp_swap( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+ dev->lock.pid != current->pid ) {
+ DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+
+ if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
+ sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
+
+ if ( !dev_priv->page_flipping ) {
+ radeon_cp_dispatch_swap( dev );
+ dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT |
+ RADEON_UPLOAD_MASKS);
+ } else {
+ radeon_cp_dispatch_flip( dev );
+ }
+
+ return 0;
+}
+
+int radeon_cp_vertex( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_radeon_buf_priv_t *buf_priv;
+ drm_radeon_vertex_t vertex;
+
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+ dev->lock.pid != current->pid ) {
+ DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+ if ( !dev_priv || dev_priv->is_pci ) {
+ DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+
+ if ( copy_from_user( &vertex, (drm_radeon_vertex_t *)arg,
+ sizeof(vertex) ) )
+ return -EFAULT;
+
+ DRM_DEBUG( "%s: pid=%d index=%d count=%d discard=%d\n",
+ __FUNCTION__, current->pid,
+ vertex.idx, vertex.count, vertex.discard );
+
+ if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
+ DRM_ERROR( "buffer index %d (of %d max)\n",
+ vertex.idx, dma->buf_count - 1 );
+ return -EINVAL;
+ }
+ if ( vertex.prim < 0 ||
+ vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
+ DRM_ERROR( "buffer prim %d\n", vertex.prim );
+ return -EINVAL;
+ }
+
+ VB_AGE_CHECK_WITH_RET( dev_priv );
+
+ buf = dma->buflist[vertex.idx];
+ buf_priv = buf->dev_private;
+
+ if ( buf->pid != current->pid ) {
+ DRM_ERROR( "process %d using buffer owned by %d\n",
+ current->pid, buf->pid );
+ return -EINVAL;
+ }
+ if ( buf->pending ) {
+ DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
+ return -EINVAL;
+ }
+
+ buf->used = vertex.count;
+ buf_priv->prim = vertex.prim;
+ buf_priv->discard = vertex.discard;
+
+ radeon_cp_dispatch_vertex( dev, buf );
+
+ return 0;
+}
+
+int radeon_cp_indices( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_radeon_buf_priv_t *buf_priv;
+ drm_radeon_indices_t elts;
+ int count;
+
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+ dev->lock.pid != current->pid ) {
+ DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+ if ( !dev_priv || dev_priv->is_pci ) {
+ DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+
+ if ( copy_from_user( &elts, (drm_radeon_indices_t *)arg,
+ sizeof(elts) ) )
+ return -EFAULT;
+
+ DRM_DEBUG( "%s: pid=%d index=%d start=%d end=%d discard=%d\n",
+ __FUNCTION__, current->pid,
+ elts.idx, elts.start, elts.end, elts.discard );
+
+ if ( elts.idx < 0 || elts.idx >= dma->buf_count ) {
+ DRM_ERROR( "buffer index %d (of %d max)\n",
+ elts.idx, dma->buf_count - 1 );
+ return -EINVAL;
+ }
+ if ( elts.prim < 0 ||
+ elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
+ DRM_ERROR( "buffer prim %d\n", elts.prim );
+ return -EINVAL;
+ }
+
+ VB_AGE_CHECK_WITH_RET( dev_priv );
+
+ buf = dma->buflist[elts.idx];
+ buf_priv = buf->dev_private;
+
+ if ( buf->pid != current->pid ) {
+ DRM_ERROR( "process %d using buffer owned by %d\n",
+ current->pid, buf->pid );
+ return -EINVAL;
+ }
+ if ( buf->pending ) {
+ DRM_ERROR( "sending pending buffer %d\n", elts.idx );
+ return -EINVAL;
+ }
+
+ count = (elts.end - elts.start) / sizeof(u16);
+ elts.start -= RADEON_INDEX_PRIM_OFFSET;
+
+ if ( elts.start & 0x7 ) {
+ DRM_ERROR( "misaligned buffer 0x%x\n", elts.start );
+ return -EINVAL;
+ }
+ if ( elts.start < buf->used ) {
+ DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used );
+ return -EINVAL;
+ }
+
+ buf->used = elts.end;
+ buf_priv->prim = elts.prim;
+ buf_priv->discard = elts.discard;
+
+ radeon_cp_dispatch_indices( dev, buf, elts.start, elts.end, count );
+
+ return 0;
+}
+
+int radeon_cp_blit( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_radeon_blit_t blit;
+
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+ dev->lock.pid != current->pid ) {
+ DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+
+ if ( copy_from_user( &blit, (drm_radeon_blit_t *)arg,
+ sizeof(blit) ) )
+ return -EFAULT;
+
+ DRM_DEBUG( "%s: pid=%d index=%d\n",
+ __FUNCTION__, current->pid, blit.idx );
+
+ if ( blit.idx < 0 || blit.idx > dma->buf_count ) {
+ DRM_ERROR( "sending %d buffers (of %d max)\n",
+ blit.idx, dma->buf_count );
+ return -EINVAL;
+ }
+
+ VB_AGE_CHECK_WITH_RET( dev_priv );
+
+ return radeon_cp_dispatch_blit( dev, &blit );
+}
+
+int radeon_cp_stipple( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_radeon_stipple_t stipple;
+ u32 mask[32];
+
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+ dev->lock.pid != current->pid ) {
+ DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+
+ if ( copy_from_user( &stipple, (drm_radeon_stipple_t *)arg,
+ sizeof(stipple) ) )
+ return -EFAULT;
+
+ if ( copy_from_user( &mask, stipple.mask,
+ 32 * sizeof(u32) ) )
+ return -EFAULT;
+
+ radeon_cp_dispatch_stipple( dev, mask );
+
+ return 0;
+}
+
+int radeon_cp_indirect( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_radeon_buf_priv_t *buf_priv;
+ drm_radeon_indirect_t indirect;
+ RING_LOCALS;
+
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+ dev->lock.pid != current->pid ) {
+ DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+ if ( !dev_priv || dev_priv->is_pci ) {
+ DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
+ return -EINVAL;
+ }
+
+ if ( copy_from_user( &indirect, (drm_radeon_indirect_t *)arg,
+ sizeof(indirect) ) )
+ return -EFAULT;
+
+ DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
+ indirect.idx, indirect.start,
+ indirect.end, indirect.discard );
+
+ if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
+ DRM_ERROR( "buffer index %d (of %d max)\n",
+ indirect.idx, dma->buf_count - 1 );
+ return -EINVAL;
+ }
+
+ buf = dma->buflist[indirect.idx];
+ buf_priv = buf->dev_private;
+
+ if ( buf->pid != current->pid ) {
+ DRM_ERROR( "process %d using buffer owned by %d\n",
+ current->pid, buf->pid );
+ return -EINVAL;
+ }
+ if ( buf->pending ) {
+ DRM_ERROR( "sending pending buffer %d\n", indirect.idx );
+ return -EINVAL;
+ }
+
+ if ( indirect.start < buf->used ) {
+ DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
+ indirect.start, buf->used );
+ return -EINVAL;
+ }
+
+ VB_AGE_CHECK_WITH_RET( dev_priv );
+
+ buf->used = indirect.end;
+ buf_priv->discard = indirect.discard;
+
+ /* Wait for the 3D stream to idle before the indirect buffer
+ * containing 2D acceleration commands is processed.
+ */
+ BEGIN_RING( 2 );
+
+ RADEON_WAIT_UNTIL_3D_IDLE();
+
+ ADVANCE_RING();
+
+ /* Dispatch the indirect buffer full of commands from the
+ * X server. This is insecure and is thus only available to
+ * privileged clients.
+ */
+ radeon_cp_dispatch_indirect( dev, buf, indirect.start, indirect.end );
+
+ return 0;
+}
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 4c141d668..e4edb9f07 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -70,7 +70,6 @@ extern int psaux_init(void);
extern void gfx_register(void);
#endif
extern void streamable_init(void);
-extern int rtc_sun_init(void); /* Combines MK48T02 and MK48T08 */
extern int rtc_DP8570A_init(void);
extern int rtc_MK48T08_init(void);
extern int ds1286_init(void);
@@ -259,9 +258,6 @@ int __init misc_init(void)
#ifdef CONFIG_BVME6000
rtc_DP8570A_init();
#endif
-#if defined(CONFIG_SUN_MOSTEK_RTC)
- rtc_sun_init();
-#endif
#ifdef CONFIG_SGI_DS1286
ds1286_init();
#endif
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 6f4ebe44c..c2ae319af 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -86,6 +86,15 @@ static inline void free_buf(unsigned char *buf)
free_page((unsigned long) buf);
}
+static inline void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
+{
+ if (tty->read_cnt < N_TTY_BUF_SIZE) {
+ tty->read_buf[tty->read_head] = c;
+ tty->read_head = (tty->read_head + 1) & (N_TTY_BUF_SIZE-1);
+ tty->read_cnt++;
+ }
+}
+
static inline void put_tty_queue(unsigned char c, struct tty_struct *tty)
{
unsigned long flags;
@@ -94,11 +103,7 @@ static inline void put_tty_queue(unsigned char c, struct tty_struct *tty)
* Why didn't anyone see this one comming? --AJK
*/
spin_lock_irqsave(&tty->read_lock, flags);
- if (tty->read_cnt < N_TTY_BUF_SIZE) {
- tty->read_buf[tty->read_head] = c;
- tty->read_head = (tty->read_head + 1) & (N_TTY_BUF_SIZE-1);
- tty->read_cnt++;
- }
+ put_tty_queue_nolock(c, tty);
spin_unlock_irqrestore(&tty->read_lock, flags);
}
@@ -499,6 +504,8 @@ static inline void n_tty_receive_parity_error(struct tty_struct *tty,
static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
{
+ unsigned long flags;
+
if (tty->raw) {
put_tty_queue(c, tty);
return;
@@ -651,10 +658,12 @@ send_signal:
put_tty_queue(c, tty);
handle_newline:
+ spin_lock_irqsave(&tty->read_lock, flags);
set_bit(tty->read_head, &tty->read_flags);
- put_tty_queue(c, tty);
+ put_tty_queue_nolock(c, tty);
tty->canon_head = tty->read_head;
tty->canon_data++;
+ spin_unlock_irqrestore(&tty->read_lock, flags);
kill_fasync(&tty->fasync, SIGIO, POLL_IN);
if (waitqueue_active(&tty->read_wait))
wake_up_interruptible(&tty->read_wait);
@@ -1055,12 +1064,6 @@ do_it_again:
tty->read_tail = ((tty->read_tail+1) &
(N_TTY_BUF_SIZE-1));
tty->read_cnt--;
- spin_unlock_irqrestore(&tty->read_lock, flags);
-
- if (!eol || (c != __DISABLED_CHAR)) {
- put_user(c, b++);
- nr--;
- }
if (eol) {
/* this test should be redundant:
* we shouldn't be reading data if
@@ -1068,8 +1071,15 @@ do_it_again:
*/
if (--tty->canon_data < 0)
tty->canon_data = 0;
- break;
}
+ spin_unlock_irqrestore(&tty->read_lock, flags);
+
+ if (!eol || (c != __DISABLED_CHAR)) {
+ put_user(c, b++);
+ nr--;
+ }
+ if (eol)
+ break;
}
} else {
int uncopied;
diff --git a/drivers/i2o/i2o_block.c b/drivers/i2o/i2o_block.c
index 8389039d6..857b32a7e 100644
--- a/drivers/i2o/i2o_block.c
+++ b/drivers/i2o/i2o_block.c
@@ -392,7 +392,6 @@ static inline int i2ob_new_segment(request_queue_t *q, struct request *req,
if (req->nr_segments < max_segments) {
req->nr_segments++;
- q->elevator.nr_segments++;
return 1;
}
return 0;
@@ -421,22 +420,16 @@ static int i2ob_merge_requests(request_queue_t *q,
{
int max_segments = i2ob_dev[MINOR(req->rq_dev)].max_segments;
int total_segments = req->nr_segments + next->nr_segments;
- int same_segment;
if (__max_segments < max_segments)
max_segments = __max_segments;
- same_segment = 0;
if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data)
- {
total_segments--;
- same_segment = 1;
- }
if (total_segments > max_segments)
return 0;
- q->elevator.nr_segments -= same_segment;
req->nr_segments = total_segments;
return 1;
}
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
index 62e2437e5..38cde0b40 100644
--- a/drivers/ide/hpt366.c
+++ b/drivers/ide/hpt366.c
@@ -55,6 +55,15 @@ const char *bad_ata100_5[] = {
};
const char *bad_ata66_4[] = {
+ "IBM-DTLA-307075",
+ "IBM-DTLA-307060",
+ "IBM-DTLA-307045",
+ "IBM-DTLA-307030",
+ "IBM-DTLA-307020",
+ "IBM-DTLA-307015",
+ "IBM-DTLA-305040",
+ "IBM-DTLA-305030",
+ "IBM-DTLA-305020",
"WDC AC310200R",
NULL
};
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 3a6a9e8d9..433951e95 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -288,6 +288,9 @@
* 4.59 Aug 11, 2000 - Fix changer problem in cdrom_read_toc, we weren't
* correctly sensing a disc change.
* - Rearranged some code
+ * - Use extended sense on drives that support it for
+ * correctly reporting tray status -- from
+ * Michael D Johnson <johnsom@orst.edu>
*
*************************************************************************/
@@ -759,16 +762,13 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
* changed 5 parameters to 3 for dvd-ram
* struct packet_command *pc; now packet_command_t *pc;
*/
-#undef CLASSIC_PACKET_STRUCT
static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
struct packet_command *pc,
ide_handler_t *handler)
{
-#ifdef CLASSIC_PACKET_STRUCT
unsigned char *cmd_buf = pc->c;
int cmd_len = sizeof(pc->c);
unsigned int timeout = pc->timeout;
-#endif
ide_startstop_t startstop;
if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
@@ -786,22 +786,10 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
}
/* Arm the interrupt handler. */
-#ifdef CLASSIC_PACKET_STRUCT
- /* Arm the interrupt handler. */
ide_set_handler (drive, handler, timeout, cdrom_timer_expiry);
/* Send the command to the device. */
atapi_output_bytes (drive, cmd_buf, cmd_len);
-#else /* !CLASSIC_PACKET_STRUCT */
- /* Arm the interrupt handler. */
-// ide_set_handler (drive, handler, (unsigned int) pc->timeout, cdrom_timer_expiry);
- ide_set_handler (drive, handler, pc->timeout, cdrom_timer_expiry);
-
- /* Send the command to the device. */
-// atapi_output_bytes (drive, (void *)pc->c, (unsigned int) sizeof(pc->c));
- atapi_output_bytes (drive, pc->c, sizeof(pc->c));
-#endif /* CLASSIC_PACKET_STRUCT */
-
return ide_started;
}
@@ -1884,9 +1872,6 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
If it is, just return. */
(void) cdrom_check_status(drive, sense);
- if (CDROM_STATE_FLAGS(drive)->toc_valid)
- return 0;
-
/* First read just the header, so we know how long the TOC is. */
stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,
sizeof(struct atapi_toc_header), sense);
@@ -2324,11 +2309,17 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
sense.ascq == 0x04)
return CDS_DISC_OK;
+
+ /*
+ * If not using Mt Fuji extended media tray reports,
+ * just return TRAY_OPEN since ATAPI doesn't provide
+ * any other way to detect this...
+ */
if (sense.sense_key == NOT_READY) {
- /* ATAPI doesn't have anything that can help
- us decide whether the drive is really
- emtpy or the tray is just open. irk. */
- return CDS_TRAY_OPEN;
+ if (sense.asc == 0x3a && (!sense.ascq||sense.ascq == 1))
+ return CDS_NO_DISC;
+ else
+ return CDS_TRAY_OPEN;
}
return CDS_DRIVE_NOT_READY;
@@ -2597,7 +2588,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
if (CDROM_CONFIG_FLAGS (drive)->dvd_r|CDROM_CONFIG_FLAGS (drive)->dvd_ram)
printk (" DVD%s%s",
(CDROM_CONFIG_FLAGS (drive)->dvd_r)? "-R" : "",
- (CDROM_CONFIG_FLAGS (drive)->dvd_ram)? "AM" : "");
+ (CDROM_CONFIG_FLAGS (drive)->dvd_ram)? "-RAM" : "");
if (CDROM_CONFIG_FLAGS (drive)->cd_r|CDROM_CONFIG_FLAGS (drive)->cd_rw)
printk (" CD%s%s",
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 7caafab9b..7158d3461 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -226,6 +226,9 @@ static int ide_build_sglist (ide_hwif_t *hwif, struct request *rq)
unsigned char *virt_addr = bh->b_data;
unsigned int size = bh->b_size;
+ if (nents >= PRD_ENTRIES)
+ return 0;
+
while ((bh = bh->b_reqnext) != NULL) {
if ((virt_addr + size) != (unsigned char *) bh->b_data)
break;
@@ -259,6 +262,9 @@ int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func)
HWIF(drive)->sg_nents = i = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq);
+ if (!i)
+ return 0;
+
sg = HWIF(drive)->sg_table;
while (i && sg_dma_len(sg)) {
u32 cur_addr;
@@ -274,7 +280,7 @@ int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func)
*/
while (cur_len) {
- if (++count >= PRD_ENTRIES) {
+ if (count++ >= PRD_ENTRIES) {
printk("%s: DMA table too small\n", drive->name);
pci_unmap_sg(HWIF(drive)->pci_dev,
HWIF(drive)->sg_table,
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index decbc9f8d..64d9121c8 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -134,7 +134,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
break;
}
#endif
- printk ("CDROM");
+ printk ("CD/DVD-ROM");
break;
case ide_tape:
printk ("TAPE");
@@ -761,9 +761,10 @@ static void init_gendisk (ide_hwif_t *hwif)
for (unit = 0; unit < minors; ++unit) {
*bs++ = BLOCK_SIZE;
#ifdef CONFIG_BLK_DEV_PDC4030
- *max_sect++ = ((hwif->chipset == ide_pdc4030) ? 127 : MAX_SECTORS);
+ *max_sect++ = ((hwif->chipset == ide_pdc4030) ? 127 : 256);
#else
- *max_sect++ = MAX_SECTORS;
+ /* IDE can do up to 128K per request. */
+ *max_sect++ = 256;
#endif
*max_ra++ = MAX_READAHEAD;
}
diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c
index 3ea1e261e..356e7a4cc 100644
--- a/drivers/ide/via82cxxx.c
+++ b/drivers/ide/via82cxxx.c
@@ -602,7 +602,9 @@ void __init ide_init_via82cxxx(ide_hwif_t *hwif)
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base) {
hwif->dmaproc = &via82cxxx_dmaproc;
+#ifdef CONFIG_IDEDMA_AUTO
hwif->autodma = 1;
+#endif
}
#endif /* CONFIG_BLK_DEV_IDEDMA */
}
diff --git a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile
index 66f6b5d4a..72d990134 100644
--- a/drivers/isdn/hisax/Makefile
+++ b/drivers/isdn/hisax/Makefile
@@ -34,8 +34,8 @@ hisax-objs-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_TELEINT) += teleint.o isac.o arcofi.o hfc_2bs0.o
hisax-objs-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o isar.o
-hisax-objs-$(CONFIG_HISAX_SPORTSTER) += sportster.o isac.o arcofi.o hfc_2bs0.o
-hisax-objs-$(CONFIG_HISAX_MIC) += mic.o isac.o arcofi.o hfc_2bs0.o
+hisax-objs-$(CONFIG_HISAX_SPORTSTER) += sportster.o isac.o arcofi.o hscx.o
+hisax-objs-$(CONFIG_HISAX_MIC) += mic.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_NETJET) += nj_s.o netjet.o isac.o arcofi.o
hisax-objs-$(CONFIG_HISAX_NETJET_U) += nj_u.o netjet.o icc.o
hisax-objs-$(CONFIG_HISAX_HFCS) += hfcscard.o hfc_2bds0.o
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index 0b60e89b3..6d0366cf2 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -1708,8 +1708,8 @@ int __devinit hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *
}
static struct pci_device_id hisax_pci_tbl[] __initdata = {
-#ifdef CONFIG_HISAX_FRTIZPCI
- {PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_FRITZ, PCI_ANY_ID, PCI_ANY_ID},
+#ifdef CONFIG_HISAX_FRITZPCI
+ {PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, PCI_ANY_ID, PCI_ANY_ID},
#endif
#ifdef CONFIG_HISAX_DIEHLDIVA
{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20, PCI_ANY_ID, PCI_ANY_ID},
diff --git a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c
index b484635f1..1c2ab1042 100644
--- a/drivers/isdn/hisax/isdnl3.c
+++ b/drivers/isdn/hisax/isdnl3.c
@@ -566,7 +566,7 @@ l3_msg(struct PStack *st, int pr, void *arg)
} else {
struct sk_buff *skb = arg;
- skb_queue_head(&st->l3.squeue, skb);
+ skb_queue_tail(&st->l3.squeue, skb);
FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL);
}
break;
diff --git a/drivers/isdn/hisax/md5sums.asc b/drivers/isdn/hisax/md5sums.asc
index 4cc1f8b83..5ffd61db0 100644
--- a/drivers/isdn/hisax/md5sums.asc
+++ b/drivers/isdn/hisax/md5sums.asc
@@ -10,7 +10,7 @@
ca7bd9bac39203f3074f3f093948cc3c isac.c
a2ad619fd404b3149099a2984de9d23c isdnl1.c
d2a78e407f3d94876deac160c6f9aae6 isdnl2.c
-a109841c2e75b11fc8ef2c8718e24c3e isdnl3.c
+e7932ca7ae39c497c17f13a2e1434fcd isdnl3.c
afb5f2f4ac296d6de45c856993b161e1 tei.c
00023e2a482cb86a26ea870577ade5d6 callc.c
a1834e9b2ec068440cff2e899eff4710 cert.c
@@ -25,9 +25,9 @@ a1834e9b2ec068440cff2e899eff4710 cert.c
Version: 2.6.3i
Charset: noconv
-iQCVAwUBOlMTgDpxHvX/mS9tAQFSbgP/W9y6tnnWHTRLGqyr3EY1OHZiQXERkAAu
-hp+Y8PIoX1GgAh4yZ7xhYwUsk6y0z5USdGuhC9ZHh+oZd57lPsJMnhkEZR5BVsYT
-r7jHwelP527+QCLkVUCHIVIWUW0ANzeZBhDV2vefkFb+gWLiZsBhaHssbcKGsMNG
-Ak4xS1ByqsM=
-=lsIJ
+iQCVAwUBOlxeLTpxHvX/mS9tAQH6RwP8DhyvqAnXFV6WIGi16iQ3vKikkPoqnDQs
+GEn5uCW0dPYKlwthD2Grj/JbMYZhOmCFuDxF7ufJnjTSDe/D8XNe2wngxzAiwcIe
+WjCrT8X95cuP3HZHscbFTEinVV0GAnoI0ZEgs5eBDhVHDqILLYMaTFBQaRH3jgXc
+i5VH88jPfUM=
+=qc+J
-----END PGP SIGNATURE-----
diff --git a/drivers/isdn/isdn_common.c b/drivers/isdn/isdn_common.c
index 7a5074c79..f4c1d429d 100644
--- a/drivers/isdn/isdn_common.c
+++ b/drivers/isdn/isdn_common.c
@@ -1512,7 +1512,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
int i;
if ((ret = verify_area(VERIFY_READ, (void *) arg,
- (ISDN_MODEM_NUMREG + ISDN_MSNLEN)
+ (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN)
* ISDN_MAX_CHANNELS)))
return ret;
@@ -1521,6 +1521,9 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
ISDN_MODEM_NUMREG))
return -EFAULT;
p += ISDN_MODEM_NUMREG;
+ if (copy_from_user(dev->mdm.info[i].emu.plmsn, p, ISDN_LMSNLEN))
+ return -EFAULT;
+ p += ISDN_LMSNLEN;
if (copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
return -EFAULT;
p += ISDN_MSNLEN;
diff --git a/drivers/isdn/isdn_net.c b/drivers/isdn/isdn_net.c
index 757c59ca9..672dd8c5c 100644
--- a/drivers/isdn/isdn_net.c
+++ b/drivers/isdn/isdn_net.c
@@ -2325,6 +2325,7 @@ isdn_net_new(char *name, struct net_device *master)
memset(netdev, 0, sizeof(isdn_net_dev));
if (!(netdev->local = (isdn_net_local *) kmalloc(sizeof(isdn_net_local), GFP_KERNEL))) {
printk(KERN_WARNING "isdn_net: Could not allocate device locals\n");
+ kfree(netdev);
return NULL;
}
memset(netdev->local, 0, sizeof(isdn_net_local));
diff --git a/drivers/isdn/isdn_ppp.c b/drivers/isdn/isdn_ppp.c
index 3bebcdfcf..f1cbb8ab7 100644
--- a/drivers/isdn/isdn_ppp.c
+++ b/drivers/isdn/isdn_ppp.c
@@ -1131,9 +1131,9 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
proto = PPP_IPX; /* untested */
break;
default:
- dev_kfree_skb(skb);
printk(KERN_ERR "isdn_ppp: skipped unsupported protocol: %#x.\n",
skb->protocol);
+ dev_kfree_skb(skb);
return 0;
}
@@ -2310,8 +2310,7 @@ static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struc
rsparm.data = rsdata;
rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
- /* !!!HACK,HACK,HACK!!! 2048 is only assumed */
- skb_out = dev_alloc_skb(2048);
+ skb_out = dev_alloc_skb(is->mru + PPP_HDRLEN);
len = ipc->decompress(stat, skb, skb_out, &rsparm);
kfree_skb(skb);
if (len <= 0) {
@@ -2332,14 +2331,9 @@ static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struc
kfree_skb(skb_out);
return NULL;
}
-
- if (isdn_ppp_skip_ac(ri, skb) < 0) {
- kfree_skb(skb);
- return NULL;
- }
- *proto = isdn_ppp_strip_proto(skb);
+ *proto = isdn_ppp_strip_proto(skb_out);
if (*proto < 0) {
- kfree_skb(skb);
+ kfree_skb(skb_out);
return NULL;
}
return skb_out;
diff --git a/drivers/isdn/isdn_v110.c b/drivers/isdn/isdn_v110.c
index 08c54a866..5dd9f2c58 100644
--- a/drivers/isdn/isdn_v110.c
+++ b/drivers/isdn/isdn_v110.c
@@ -102,7 +102,7 @@ isdn_v110_open(unsigned char key, int hdrlen, int maxsize)
int i;
isdn_v110_stream *v;
- if ((v = kmalloc(sizeof(isdn_v110_stream), GFP_KERNEL)) == NULL)
+ if ((v = kmalloc(sizeof(isdn_v110_stream), GFP_ATOMIC)) == NULL)
return NULL;
memset(v, 0, sizeof(isdn_v110_stream));
v->key = key;
@@ -134,7 +134,7 @@ isdn_v110_open(unsigned char key, int hdrlen, int maxsize)
v->b = 0;
v->skbres = hdrlen;
v->maxsize = maxsize - hdrlen;
- if ((v->encodebuf = kmalloc(maxsize, GFP_KERNEL)) == NULL) {
+ if ((v->encodebuf = kmalloc(maxsize, GFP_ATOMIC)) == NULL) {
kfree(v);
return NULL;
}
diff --git a/drivers/md/Config.in b/drivers/md/Config.in
index 565055a68..30438c77f 100644
--- a/drivers/md/Config.in
+++ b/drivers/md/Config.in
@@ -11,12 +11,7 @@ dep_tristate ' Linear (append) mode' CONFIG_MD_LINEAR $CONFIG_BLK_DEV_MD
dep_tristate ' RAID-0 (striping) mode' CONFIG_MD_RAID0 $CONFIG_BLK_DEV_MD
dep_tristate ' RAID-1 (mirroring) mode' CONFIG_MD_RAID1 $CONFIG_BLK_DEV_MD
dep_tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 $CONFIG_BLK_DEV_MD
-if [ "$CONFIG_MD_LINEAR" = "y" -o "$CONFIG_MD_RAID0" = "y" -o "$CONFIG_MD_RAID1" = "y" -o "$CONFIG_MD_RAID5" = "y" ]; then
- bool ' Boot support' CONFIG_MD_BOOT
- bool ' Auto Detect support' CONFIG_AUTODETECT_RAID
-fi
dep_tristate ' Logical volume manager (LVM) support' CONFIG_BLK_DEV_LVM $CONFIG_MD
-dep_mbool ' LVM information in proc filesystem' CONFIG_LVM_PROC_FS $CONFIG_BLK_DEV_LVM
endmenu
diff --git a/drivers/md/lvm-snap.c b/drivers/md/lvm-snap.c
index 980694ee3..e28ffdbe9 100644
--- a/drivers/md/lvm-snap.c
+++ b/drivers/md/lvm-snap.c
@@ -21,6 +21,14 @@
*
*/
+/*
+ * Changelog
+ *
+ * 05/07/2000 - implemented persistent snapshot support
+ * 23/11/2000 - used cpu_to_le64 rather than my own macro
+ *
+ */
+
#include <linux/kernel.h>
#include <linux/vmalloc.h>
#include <linux/blkdev.h>
@@ -30,7 +38,9 @@
#include <linux/lvm.h>
-static char *lvm_snap_version __attribute__ ((unused)) = "LVM 0.9 snapshot code (13/11/2000)\n";
+#include "lvm-snap.h"
+
+static char *lvm_snap_version __attribute__ ((unused)) = "LVM 0.9.1_beta2 snapshot code (18/01/2001)\n";
extern const char *const lvm_name;
extern int lvm_blocksizes[];
@@ -214,10 +224,10 @@ void lvm_snapshot_fill_COW_page(vg_t * vg, lv_t * lv_snap)
memset(lv_COW_table, 0, blksize_snap);
for ( ; is < lv_snap->lv_remap_ptr; is++, id++) {
/* store new COW_table entry */
- lv_COW_table[id].pv_org_number = LVM_TO_DISK64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_org));
- lv_COW_table[id].pv_org_rsector = LVM_TO_DISK64(lv_snap->lv_block_exception[is].rsector_org);
- lv_COW_table[id].pv_snap_number = LVM_TO_DISK64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_new));
- lv_COW_table[id].pv_snap_rsector = LVM_TO_DISK64(lv_snap->lv_block_exception[is].rsector_new);
+ lv_COW_table[id].pv_org_number = cpu_to_le64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_org));
+ lv_COW_table[id].pv_org_rsector = cpu_to_le64(lv_snap->lv_block_exception[is].rsector_org);
+ lv_COW_table[id].pv_snap_number = cpu_to_le64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_new));
+ lv_COW_table[id].pv_snap_rsector = cpu_to_le64(lv_snap->lv_block_exception[is].rsector_new);
}
}
@@ -227,8 +237,7 @@ void lvm_snapshot_fill_COW_page(vg_t * vg, lv_t * lv_snap)
*
*/
-int lvm_write_COW_table_block(vg_t * vg,
- lv_t * lv_snap)
+int lvm_write_COW_table_block(vg_t * vg, lv_t * lv_snap)
{
int blksize_snap;
int end_of_table;
@@ -268,10 +277,10 @@ int lvm_write_COW_table_block(vg_t * vg,
blocks[0] = (snap_pe_start + COW_table_sector_offset) >> (blksize_snap >> 10);
/* store new COW_table entry */
- lv_COW_table[idx_COW_table].pv_org_number = LVM_TO_DISK64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[idx].rdev_org));
- lv_COW_table[idx_COW_table].pv_org_rsector = LVM_TO_DISK64(lv_snap->lv_block_exception[idx].rsector_org);
- lv_COW_table[idx_COW_table].pv_snap_number = LVM_TO_DISK64(lvm_pv_get_number(vg, snap_phys_dev));
- lv_COW_table[idx_COW_table].pv_snap_rsector = LVM_TO_DISK64(lv_snap->lv_block_exception[idx].rsector_new);
+ lv_COW_table[idx_COW_table].pv_org_number = cpu_to_le64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[idx].rdev_org));
+ lv_COW_table[idx_COW_table].pv_org_rsector = cpu_to_le64(lv_snap->lv_block_exception[idx].rsector_org);
+ lv_COW_table[idx_COW_table].pv_snap_number = cpu_to_le64(lvm_pv_get_number(vg, snap_phys_dev));
+ lv_COW_table[idx_COW_table].pv_snap_rsector = cpu_to_le64(lv_snap->lv_block_exception[idx].rsector_new);
length_tmp = iobuf->length;
iobuf->length = blksize_snap;
@@ -568,6 +577,7 @@ void lvm_snapshot_release(lv_t * lv)
}
if (lv->lv_iobuf)
{
+ kiobuf_wait_for_io(lv->lv_iobuf);
unmap_kiobuf(lv->lv_iobuf);
free_kiovec(1, &lv->lv_iobuf);
lv->lv_iobuf = NULL;
diff --git a/drivers/md/lvm-snap.h b/drivers/md/lvm-snap.h
new file mode 100644
index 000000000..23538a1b7
--- /dev/null
+++ b/drivers/md/lvm-snap.h
@@ -0,0 +1,47 @@
+/*
+ * kernel/lvm-snap.h
+ *
+ * Copyright (C) 2001 Sistina Software
+ *
+ *
+ * LVM driver 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, or (at your option)
+ * any later version.
+ *
+ * LVM driver 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 GNU CC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/*
+ * Changelog
+ *
+ * 05/01/2001:Joe Thornber - Factored this file out of lvm.c
+ *
+ */
+
+#ifndef LVM_SNAP_H
+#define LVM_SNAP_H
+
+/* external snapshot calls */
+extern inline int lvm_get_blksize(kdev_t);
+extern int lvm_snapshot_alloc(lv_t *);
+extern void lvm_snapshot_fill_COW_page(vg_t *, lv_t *);
+extern int lvm_snapshot_COW(kdev_t, ulong, ulong, ulong, lv_t *);
+extern int lvm_snapshot_remap_block(kdev_t *, ulong *, ulong, lv_t *);
+extern void lvm_snapshot_release(lv_t *);
+extern int lvm_write_COW_table_block(vg_t *, lv_t *);
+extern inline void lvm_hash_link(lv_block_exception_t *,
+ kdev_t, ulong, lv_t *);
+extern int lvm_snapshot_alloc_hash_table(lv_t *);
+extern void lvm_drop_snapshot(lv_t *, const char *);
+
+#endif
diff --git a/drivers/md/lvm.c b/drivers/md/lvm.c
index ea276c57c..a4ca05e90 100644
--- a/drivers/md/lvm.c
+++ b/drivers/md/lvm.c
@@ -7,22 +7,23 @@
* April-May,July-August,November 1998
* January-March,May,July,September,October 1999
* January,February,July,September-November 2000
+ * January 2001
*
*
* LVM driver 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, or (at your option)
* any later version.
- *
+ *
* LVM driver 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 GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Boston, MA 02111-1307, USA.
*
*/
@@ -138,13 +139,21 @@
* 01/11/2000 - added memory information on hash tables to
* lvm_proc_get_global_info()
* 02/11/2000 - implemented /proc/lvm/ hierarchy
- * 07/12/2000 - make sure lvm_make_request_fn returns correct value - 0 or 1 - NeilBrown
+ * 22/11/2000 - changed lvm_do_create_proc_entry_of_pv () to work
+ * with devfs
+ * 26/11/2000 - corrected #ifdef locations for PROC_FS
+ * 28/11/2000 - fixed lvm_do_vg_extend() NULL pointer BUG
+ * - fixed lvm_do_create_proc_entry_of_pv() buffer tampering BUG
+ * 08/01/2001 - Removed conditional compiles related to PROC_FS,
+ * procfs is always supported now. (JT)
+ * 12/01/2001 - avoided flushing logical volume in case of shrinking
+ * because of unecessary overhead in case of heavy updates
*
*/
-static char *lvm_version = "LVM version 0.9 by Heinz Mauelshagen (13/11/2000)\n";
-static char *lvm_short_version = "version 0.9 (13/11/2000)";
+static char *lvm_version = "LVM version 0.9.1_beta2 by Heinz Mauelshagen (18/01/2001)\n";
+static char *lvm_short_version = "version 0.9.1_beta2 (18/01/2001)";
#define MAJOR_NR LVM_BLK_MAJOR
#define DEVICE_OFF(device)
@@ -190,6 +199,8 @@ static char *lvm_short_version = "version 0.9 (13/11/2000)";
#include <linux/errno.h>
#include <linux/lvm.h>
+#include "lvm-snap.h"
+
#define LVM_CORRECT_READ_AHEAD( a) \
if ( a < LVM_MIN_READ_AHEAD || \
a > LVM_MAX_READ_AHEAD) a = LVM_MAX_READ_AHEAD;
@@ -198,19 +209,28 @@ static char *lvm_short_version = "version 0.9 (13/11/2000)";
# define WRITEA WRITE
#endif
-/*
- * External function prototypes
- */
-#ifdef MODULE
-int init_module(void);
-void cleanup_module(void);
+/* debug macros */
+#ifdef DEBUG_IOCTL
+#define P_IOCTL(fmt, args...) printk(KERN_DEBUG "lvm ioctl: " fmt, ## args)
#else
-extern int lvm_init(void);
+#define P_IOCTL(fmt, args...)
#endif
-static void lvm_dummy_device_request(request_queue_t *);
-#define DEVICE_REQUEST lvm_dummy_device_request
+#ifdef DEBUG_MAP
+#define P_MAP(fmt, args...) printk(KERN_DEBUG "lvm map: " fmt, ## args)
+#else
+#define P_MAP(fmt, args...)
+#endif
+
+#ifdef DEBUG_KFREE
+#define P_KFREE(fmt, args...) printk(KERN_DEBUG "lvm kfree: " fmt, ## args)
+#else
+#define P_KFREE(fmt, args...)
+#endif
+/*
+ * External function prototypes
+ */
static int lvm_make_request_fn(request_queue_t*, int, struct buffer_head*);
static int lvm_blk_ioctl(struct inode *, struct file *, uint, ulong);
@@ -224,42 +244,29 @@ static int lvm_user_bmap(struct inode *, struct lv_bmap *);
static int lvm_chr_ioctl(struct inode *, struct file *, uint, ulong);
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
int lvm_proc_read_vg_info(char *, char **, off_t, int, int *, void *);
int lvm_proc_read_lv_info(char *, char **, off_t, int, int *, void *);
int lvm_proc_read_pv_info(char *, char **, off_t, int, int *, void *);
static int lvm_proc_get_global_info(char *, char **, off_t, int, int *, void *);
+
+void lvm_do_create_devfs_entry_of_vg ( vg_t *);
+
void lvm_do_create_proc_entry_of_vg ( vg_t *);
-inline void lvm_do_remove_proc_entry_of_vg ( vg_t *);
-inline void lvm_do_create_proc_entry_of_lv ( vg_t *, lv_t *);
-inline void lvm_do_remove_proc_entry_of_lv ( vg_t *, lv_t *);
-inline void lvm_do_create_proc_entry_of_pv ( vg_t *, pv_t *);
-inline void lvm_do_remove_proc_entry_of_pv ( vg_t *, pv_t *);
-#endif
+void lvm_do_remove_proc_entry_of_vg ( vg_t *);
+void lvm_do_create_proc_entry_of_lv ( vg_t *, lv_t *);
+void lvm_do_remove_proc_entry_of_lv ( vg_t *, lv_t *);
+void lvm_do_create_proc_entry_of_pv ( vg_t *, pv_t *);
+void lvm_do_remove_proc_entry_of_pv ( vg_t *, pv_t *);
-#ifdef LVM_HD_NAME
-void lvm_hd_name(char *, int);
-#endif
/* End external function prototypes */
/*
* Internal function prototypes
*/
+static void lvm_cleanup(void);
static void lvm_init_vars(void);
-/* external snapshot calls */
-extern inline int lvm_get_blksize(kdev_t);
-extern int lvm_snapshot_alloc(lv_t *);
-extern void lvm_snapshot_fill_COW_page(vg_t *, lv_t *);
-extern int lvm_snapshot_COW(kdev_t, ulong, ulong, ulong, lv_t *);
-extern int lvm_snapshot_remap_block(kdev_t *, ulong *, ulong, lv_t *);
-extern void lvm_snapshot_release(lv_t *);
-extern int lvm_write_COW_table_block(vg_t *, lv_t *);
-extern inline void lvm_hash_link(lv_block_exception_t *, kdev_t, ulong, lv_t *);
-extern int lvm_snapshot_alloc_hash_table(lv_t *);
-extern void lvm_drop_snapshot(lv_t *, char *);
-
#ifdef LVM_HD_NAME
extern void (*lvm_hd_name_ptr) (char *, int);
#endif
@@ -288,9 +295,9 @@ static int lvm_do_vg_reduce(vg_t *, void *);
static int lvm_do_vg_rename(vg_t *, void *);
static int lvm_do_vg_remove(int);
static void lvm_geninit(struct gendisk *);
-#ifdef LVM_GET_INODE
-static struct inode *lvm_get_inode(int);
-void lvm_clear_inode(struct inode *);
+static char *lvm_show_uuid ( char *);
+#ifdef LVM_HD_NAME
+void lvm_hd_name(char *, int);
#endif
/* END Internal function prototypes */
@@ -298,12 +305,10 @@ void lvm_clear_inode(struct inode *);
/* volume group descriptor area pointers */
static vg_t *vg[ABS_MAX_VG];
-#ifdef CONFIG_DEVFS_FS
static devfs_handle_t lvm_devfs_handle;
static devfs_handle_t vg_devfs_handle[MAX_VG];
static devfs_handle_t ch_devfs_handle[MAX_VG];
static devfs_handle_t lv_devfs_handle[MAX_LV];
-#endif
static pv_t *pvp = NULL;
static lv_t *lvp = NULL;
@@ -340,18 +345,15 @@ static int loadtime = 0;
static uint vg_count = 0;
static long lvm_chr_open_count = 0;
static ushort lvm_iop_version = LVM_DRIVER_IOP_VERSION;
-static DECLARE_WAIT_QUEUE_HEAD(lvm_snapshot_wait);
static DECLARE_WAIT_QUEUE_HEAD(lvm_wait);
static DECLARE_WAIT_QUEUE_HEAD(lvm_map_wait);
static spinlock_t lvm_lock = SPIN_LOCK_UNLOCKED;
static spinlock_t lvm_snapshot_lock = SPIN_LOCK_UNLOCKED;
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
static struct proc_dir_entry *lvm_proc_dir = NULL;
static struct proc_dir_entry *lvm_proc_vg_subdir = NULL;
struct proc_dir_entry *pde = NULL;
-#endif
static struct file_operations lvm_chr_fops =
{
@@ -360,7 +362,7 @@ static struct file_operations lvm_chr_fops =
ioctl: lvm_chr_ioctl,
};
-#define BLOCK_DEVICE_OPERATIONS
+
/* block device operations structure needed for 2.3.38? and above */
static struct block_device_operations lvm_blk_dops =
{
@@ -391,22 +393,10 @@ static struct gendisk lvm_gendisk =
NULL, /* pointer to next gendisk struct (internal) */
};
-
-#ifdef MODULE
-/*
- * Module initialization...
- */
-int init_module(void)
-#else
/*
* Driver initialization...
*/
-#ifdef __initfunc
-__initfunc(int lvm_init(void))
-#else
-int __init lvm_init(void)
-#endif
-#endif /* #ifdef MODULE */
+int lvm_init(void)
{
struct gendisk *gendisk_ptr = NULL;
@@ -414,11 +404,7 @@ int __init lvm_init(void)
printk(KERN_ERR "%s -- register_chrdev failed\n", lvm_name);
return -EIO;
}
-#ifdef BLOCK_DEVICE_OPERATIONS
if (register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_dops) < 0)
-#else
- if (register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_fops) < 0)
-#endif
{
printk("%s -- register_blkdev failed\n", lvm_name);
if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0)
@@ -426,21 +412,17 @@ int __init lvm_init(void)
return -EIO;
}
-#ifdef CONFIG_DEVFS_FS
lvm_devfs_handle = devfs_register(
0 , "lvm", 0, 0, LVM_CHAR_MAJOR,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
&lvm_chr_fops, NULL);
-#endif
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
lvm_proc_dir = create_proc_entry (LVM_DIR, S_IFDIR, &proc_root);
if (lvm_proc_dir != NULL) {
lvm_proc_vg_subdir = create_proc_entry (LVM_VG_SUBDIR, S_IFDIR, lvm_proc_dir);
pde = create_proc_entry(LVM_GLOBAL, S_IFREG, lvm_proc_dir);
if ( pde != NULL) pde->read_proc = &lvm_proc_get_global_info;
}
-#endif
lvm_init_vars();
lvm_geninit(&lvm_gendisk);
@@ -464,9 +446,9 @@ int __init lvm_init(void)
lvm_hd_name_ptr = lvm_hd_name;
#endif
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), lvm_make_request_fn);
+
/* optional read root VGDA */
/*
if ( *rootvg != 0) vg_read_with_pv_and_lv ( rootvg, &vg);
@@ -483,20 +465,17 @@ int __init lvm_init(void)
lvm_version, lvm_name);
return 0;
-} /* init_module() / lvm_init() */
+} /* lvm_init() */
-#ifdef MODULE
/*
- * Module cleanup...
+ * cleanup...
*/
-void cleanup_module(void)
+static void lvm_cleanup(void)
{
struct gendisk *gendisk_ptr = NULL, *gendisk_ptr_prev = NULL;
-#ifdef CONFIG_DEVFS_FS
devfs_unregister (lvm_devfs_handle);
-#endif
if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0) {
printk(KERN_ERR "%s -- unregister_chrdev failed\n", lvm_name);
@@ -504,7 +483,7 @@ void cleanup_module(void)
if (unregister_blkdev(MAJOR_NR, lvm_name) < 0) {
printk(KERN_ERR "%s -- unregister_blkdev failed\n", lvm_name);
}
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+
gendisk_ptr = gendisk_ptr_prev = gendisk_head;
while (gendisk_ptr != NULL) {
@@ -521,11 +500,9 @@ void cleanup_module(void)
blksize_size[MAJOR_NR] = NULL;
hardsect_size[MAJOR_NR] = NULL;
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
remove_proc_entry(LVM_GLOBAL, lvm_proc_dir);
remove_proc_entry(LVM_VG_SUBDIR, lvm_proc_dir);
remove_proc_entry(LVM_DIR, &proc_root);
-#endif
#ifdef LVM_HD_NAME
/* reference from linux/drivers/block/genhd.c */
@@ -535,18 +512,13 @@ void cleanup_module(void)
printk(KERN_INFO "%s -- Module successfully deactivated\n", lvm_name);
return;
-} /* void cleanup_module() */
-#endif /* #ifdef MODULE */
+} /* lvm_cleanup() */
/*
* support function to initialize lvm variables
*/
-#ifdef __initfunc
-__initfunc(void lvm_init_vars(void))
-#else
void __init lvm_init_vars(void)
-#endif
{
int v;
@@ -626,13 +598,9 @@ static int lvm_chr_ioctl(struct inode *inode, struct file *file,
/* otherwise cc will complain about unused variables */
(void) lvm_lock;
-
-#ifdef DEBUG_IOCTL
- printk(KERN_DEBUG
- "%s -- lvm_chr_ioctl: command: 0x%X MINOR: %d "
- "VG#: %d mode: 0x%X\n",
- lvm_name, command, minor, VG_CHR(minor), file->f_mode);
-#endif
+ P_IOCTL("%s -- lvm_chr_ioctl: command: 0x%X MINOR: %d "
+ "VG#: %d mode: 0x%X\n",
+ lvm_name, command, minor, VG_CHR(minor), file->f_mode);
#ifdef LVM_TOTAL_RESET
if (lvm_reset_spindown > 0) return -EACCES;
@@ -890,14 +858,12 @@ static int lvm_blk_open(struct inode *inode, struct file *file)
if (lv_ptr->lv_status & LV_SPINDOWN) return -EPERM;
/* Check inactive LV and open for read/write */
- if (file->f_mode & O_RDWR) {
- if (!(lv_ptr->lv_status & LV_ACTIVE)) return -EPERM;
- if (!(lv_ptr->lv_access & LV_WRITE)) return -EACCES;
- }
+ if (!(lv_ptr->lv_status & LV_ACTIVE))
+ return -EPERM;
+ if (!(lv_ptr->lv_access & LV_WRITE) &&
+ (file->f_mode & FMODE_WRITE))
+ return -EACCES;
-#ifndef BLOCK_DEVICE_OPERATIONS
- file->f_op = &lvm_blk_fops;
-#endif
/* be sure to increment VG counter */
if (lv_ptr->lv_open == 0) vg_ptr->lv_open++;
@@ -930,24 +896,18 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file,
void *arg = (void *) a;
struct hd_geometry *hd = (struct hd_geometry *) a;
-#ifdef DEBUG_IOCTL
- printk(KERN_DEBUG
- "%s -- lvm_blk_ioctl MINOR: %d command: 0x%X arg: %X "
- "VG#: %dl LV#: %d\n",
- lvm_name, minor, command, (ulong) arg,
- VG_BLK(minor), LV_BLK(minor));
-#endif
+ P_IOCTL("%s -- lvm_blk_ioctl MINOR: %d command: 0x%X arg: %X "
+ "VG#: %dl LV#: %d\n",
+ lvm_name, minor, command, (ulong) arg,
+ VG_BLK(minor), LV_BLK(minor));
switch (command) {
case BLKGETSIZE:
/* return device size */
-#ifdef DEBUG_IOCTL
- printk(KERN_DEBUG
- "%s -- lvm_blk_ioctl -- BLKGETSIZE: %u\n",
- lvm_name, lv_ptr->lv_size);
-#endif
+ P_IOCTL("%s -- lvm_blk_ioctl -- BLKGETSIZE: %u\n",
+ lvm_name, lv_ptr->lv_size);
if (put_user(lv_ptr->lv_size, (long *)arg))
- return -EFAULT;
+ return -EFAULT;
break;
@@ -955,10 +915,8 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file,
/* flush buffer cache */
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
-#ifdef DEBUG_IOCTL
- printk(KERN_DEBUG
- "%s -- lvm_blk_ioctl -- BLKFLSBUF\n", lvm_name);
-#endif
+ P_IOCTL("%s -- lvm_blk_ioctl -- BLKFLSBUF\n", lvm_name);
+
fsync_dev(inode->i_rdev);
invalidate_buffers(inode->i_rdev);
break;
@@ -968,11 +926,9 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file,
/* set read ahead for block device */
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
-#ifdef DEBUG_IOCTL
- printk(KERN_DEBUG
- "%s -- lvm_blk_ioctl -- BLKRASET: %d sectors for %02X:%02X\n",
- lvm_name, (long) arg, MAJOR(inode->i_rdev), minor);
-#endif
+ P_IOCTL("%s -- lvm_blk_ioctl -- BLKRASET: %d sectors for %02X:%02X\n",
+ lvm_name, (long) arg, MAJOR(inode->i_rdev), minor);
+
if ((long) arg < LVM_MIN_READ_AHEAD ||
(long) arg > LVM_MAX_READ_AHEAD)
return -EINVAL;
@@ -982,10 +938,7 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file,
case BLKRAGET:
/* get current read ahead setting */
-#ifdef DEBUG_IOCTL
- printk(KERN_DEBUG
- "%s -- lvm_blk_ioctl -- BLKRAGET\n", lvm_name);
-#endif
+ P_IOCTL("%s -- lvm_blk_ioctl -- BLKRAGET\n", lvm_name);
if (put_user(lv_ptr->lv_read_ahead, (long *)arg))
return -EFAULT;
break;
@@ -993,10 +946,7 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file,
case HDIO_GETGEO:
/* get disk geometry */
-#ifdef DEBUG_IOCTL
- printk(KERN_DEBUG
- "%s -- lvm_blk_ioctl -- HDIO_GETGEO\n", lvm_name);
-#endif
+ P_IOCTL("%s -- lvm_blk_ioctl -- HDIO_GETGEO\n", lvm_name);
if (hd == NULL)
return -EINVAL;
{
@@ -1016,11 +966,8 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file,
return -EFAULT;
}
-#ifdef DEBUG_IOCTL
- printk(KERN_DEBUG
- "%s -- lvm_blk_ioctl -- cylinders: %d\n",
- lvm_name, lv_ptr->lv_size / heads / sectors);
-#endif
+ P_IOCTL("%s -- lvm_blk_ioctl -- cylinders: %d\n",
+ lvm_name, lv_ptr->lv_size / heads / sectors);
break;
@@ -1127,22 +1074,22 @@ static int lvm_user_bmap(struct inode *inode, struct lv_bmap *user_result)
struct buffer_head bh;
unsigned long block;
int err;
-
+
if (get_user(block, &user_result->lv_block))
- return -EFAULT;
-
+ return -EFAULT;
+
memset(&bh,0,sizeof bh);
bh.b_rsector = block;
bh.b_dev = bh.b_rdev = inode->i_dev;
bh.b_size = lvm_get_blksize(bh.b_dev);
if ((err=lvm_map(&bh, READ)) < 0) {
- printk("lvm map failed: %d\n", err);
- return -EINVAL;
+ printk("lvm map failed: %d\n", err);
+ return -EINVAL;
}
-
- return put_user( kdev_t_to_nr(bh.b_rdev), &user_result->lv_dev) ||
+
+ return put_user(kdev_t_to_nr(bh.b_rdev), &user_result->lv_dev) ||
put_user(bh.b_rsector, &user_result->lv_block) ? -EFAULT : 0;
-}
+}
/*
@@ -1168,7 +1115,7 @@ int lvm_vg_info(vg_t *vg_ptr, char *buf) {
vg_ptr->pe_total,
vg_ptr->pe_allocated * vg_ptr->pe_size >> 1,
vg_ptr->pe_allocated,
- (vg_ptr->pe_total - vg_ptr->pe_allocated) *
+ (vg_ptr->pe_total - vg_ptr->pe_allocated) *
vg_ptr->pe_size >> 1,
vg_ptr->pe_total - vg_ptr->pe_allocated);
return sz;
@@ -1263,7 +1210,6 @@ int lvm_pv_info(pv_t *pv_ptr, char *buf) {
}
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
/*
* Support functions /proc-Filesystem
*/
@@ -1325,10 +1271,7 @@ static int lvm_proc_get_global_info(char *page, char **start, off_t pos, int cou
lv_block_exception_t_bytes *= sizeof(lv_block_exception_t);
if (buf != NULL) {
-#ifdef DEBUG_KFREE
- printk(KERN_DEBUG
- "%s -- vfree %d\n", lvm_name, __LINE__);
-#endif
+ P_KFREE("%s -- vfree %d\n", lvm_name, __LINE__);
lock_kernel();
vfree(buf);
unlock_kernel();
@@ -1452,7 +1395,6 @@ static int lvm_proc_get_global_info(char *page, char **start, off_t pos, int cou
else
return count;
} /* lvm_proc_get_global_info() */
-#endif /* #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS */
/*
@@ -1478,7 +1420,7 @@ int lvm_proc_read_vg_info(char *page, char **start, off_t off,
sz += sprintf ( page+sz, "PE size: %u\n", vg->pe_size / 2);
sz += sprintf ( page+sz, "PE total: %u\n", vg->pe_total);
sz += sprintf ( page+sz, "PE allocated: %u\n", vg->pe_allocated);
- sz += sprintf ( page+sz, "uuid: %s\n", vg->vg_uuid);
+ sz += sprintf ( page+sz, "uuid: %s\n", lvm_show_uuid(vg->vg_uuid));
return sz;
}
@@ -1525,7 +1467,7 @@ int lvm_proc_read_pv_info(char *page, char **start, off_t off,
sz += sprintf ( page+sz, "PE allocated: %u\n", pv->pe_allocated);
sz += sprintf ( page+sz, "device: %02u:%02u\n",
MAJOR(pv->pv_dev), MINOR(pv->pv_dev));
- sz += sprintf ( page+sz, "uuid: %s\n", pv->pv_uuid);
+ sz += sprintf ( page+sz, "uuid: %s\n", lvm_show_uuid(pv->pv_uuid));
return sz;
@@ -1565,15 +1507,13 @@ static int lvm_map(struct buffer_head *bh, int rw)
lvm_name, lv->lv_name);
return -1;
}
-#ifdef DEBUG_MAP
- printk(KERN_DEBUG
- "%s - lvm_map minor:%d *rdev: %02d:%02d *rsector: %lu "
- "size:%lu\n",
- lvm_name, minor,
- MAJOR(rdev_tmp),
- MINOR(rdev_tmp),
- rsector_tmp, size);
-#endif
+
+ P_MAP("%s - lvm_map minor:%d *rdev: %02d:%02d *rsector: %lu "
+ "size:%lu\n",
+ lvm_name, minor,
+ MAJOR(rdev_tmp),
+ MINOR(rdev_tmp),
+ rsector_tmp, size);
if (rsector_tmp + size > lv->lv_size) {
printk(KERN_ALERT
@@ -1595,15 +1535,13 @@ lvm_second_remap:
(rsector_tmp % vg_this->pe_size);
rdev_tmp = lv->lv_current_pe[index].dev;
-#ifdef DEBUG_MAP
- printk(KERN_DEBUG
- "lv_current_pe[%ld].pe: %ld rdev: %02d:%02d rsector:%ld\n",
+ P_MAP("lv_current_pe[%ld].pe: %ld rdev: %02d:%02d "
+ "rsector:%ld\n",
index,
lv->lv_current_pe[index].pe,
MAJOR(rdev_tmp),
MINOR(rdev_tmp),
rsector_tmp);
-#endif
/* striped mapping */
} else {
@@ -1624,9 +1562,7 @@ lvm_second_remap:
rdev_tmp = lv->lv_current_pe[index].dev;
}
-#ifdef DEBUG_MAP
- printk(KERN_DEBUG
- "lv_current_pe[%ld].pe: %ld rdev: %02d:%02d rsector:%ld\n"
+ P_MAP("lv_current_pe[%ld].pe: %ld rdev: %02d:%02d rsector:%ld\n"
"stripe_length: %ld stripe_index: %ld\n",
index,
lv->lv_current_pe[index].pe,
@@ -1635,7 +1571,6 @@ lvm_second_remap:
rsector_tmp,
stripe_length,
stripe_index);
-#endif
/* handle physical extents on the move */
if (pe_lock_req.lock == LOCK_PE) {
@@ -1659,6 +1594,8 @@ lvm_second_remap:
if (lv->lv_access & (LV_SNAPSHOT|LV_SNAPSHOT_ORG)) {
/* original logical volume */
if (lv->lv_access & LV_SNAPSHOT_ORG) {
+ /* Serializes the access to the lv_snapshot_next list */
+ down(&lv->lv_snapshot_sem);
if (rw == WRITE || rw == WRITEA)
{
lv_t *lv_ptr;
@@ -1669,7 +1606,8 @@ lvm_second_remap:
lv_ptr = lv_ptr->lv_snapshot_next) {
/* Check for inactive snapshot */
if (!(lv_ptr->lv_status & LV_ACTIVE)) continue;
- down(&lv->lv_snapshot_org->lv_snapshot_sem);
+ /* Serializes the COW with the accesses to the snapshot device */
+ down(&lv_ptr->lv_snapshot_sem);
/* do we still have exception storage for this snapshot free? */
if (lv_ptr->lv_block_exception != NULL) {
rdev_sav = rdev_tmp;
@@ -1690,9 +1628,10 @@ lvm_second_remap:
rdev_tmp = rdev_sav;
rsector_tmp = rsector_sav;
}
- up(&lv->lv_snapshot_org->lv_snapshot_sem);
+ up(&lv_ptr->lv_snapshot_sem);
}
}
+ up(&lv->lv_snapshot_sem);
} else {
/* remap snapshot logical volume */
down(&lv->lv_snapshot_sem);
@@ -1733,31 +1672,12 @@ void lvm_hd_name(char *buf, int minor)
/*
- * this one never should be called...
- */
-static void lvm_dummy_device_request(request_queue_t * t)
-{
- printk(KERN_EMERG
- "%s -- oops, got lvm request for %02d:%02d [sector: %lu]\n",
- lvm_name,
- MAJOR(CURRENT->rq_dev),
- MINOR(CURRENT->rq_dev),
- CURRENT->sector);
- return;
-}
-
-
-/*
* make request function
*/
static int lvm_make_request_fn(request_queue_t *q,
int rw,
- struct buffer_head *bh)
-{
- if (lvm_map(bh, rw)<0)
- return 0; /* failure, buffer_IO_error has been called, don't recurse */
- else
- return 1; /* all ok, mapping done, call lower level driver */
+ struct buffer_head *bh) {
+ return (lvm_map(bh, rw) < 0) ? 0 : 1;
}
@@ -1774,10 +1694,8 @@ static int lvm_do_lock_lvm(void)
lock_try_again:
spin_lock(&lvm_lock);
if (lock != 0 && lock != current->pid) {
-#ifdef DEBUG_IOCTL
- printk(KERN_INFO "lvm_do_lock_lvm: %s is locked by pid %d ...\n",
- lvm_name, lock);
-#endif
+ P_IOCTL("lvm_do_lock_lvm: %s is locked by pid %d ...\n",
+ lvm_name, lock);
spin_unlock(&lvm_lock);
interruptible_sleep_on(&lvm_wait);
if (current->sigpending != 0)
@@ -1966,6 +1884,8 @@ int lvm_do_vg_create(int minor, void *arg)
}
}
+ lvm_do_create_devfs_entry_of_vg ( vg_ptr);
+
/* Second path to correct snapshot logical volumes which are not
in place during first path above */
for (l = 0; l < ls; l++) {
@@ -1980,18 +1900,7 @@ int lvm_do_vg_create(int minor, void *arg)
}
}
-#ifdef CONFIG_DEVFS_FS
- vg_devfs_handle[vg_ptr->vg_number] = devfs_mk_dir(0, vg_ptr->vg_name, NULL);
- ch_devfs_handle[vg_ptr->vg_number] = devfs_register(
- vg_devfs_handle[vg_ptr->vg_number] , "group",
- DEVFS_FL_DEFAULT, LVM_CHAR_MAJOR, vg_ptr->vg_number,
- S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
- &lvm_chr_fops, NULL);
-#endif
-
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
lvm_do_create_proc_entry_of_vg ( vg_ptr);
-#endif
vfree(snap_lv_ptr);
@@ -2021,25 +1930,15 @@ static int lvm_do_vg_extend(vg_t *vg_ptr, void *arg)
for (p = 0; p < vg_ptr->pv_max; p++) {
if ( ( pv_ptr = vg_ptr->pv[p]) == NULL) {
ret = lvm_do_pv_create(arg, vg_ptr, p);
- lvm_do_create_proc_entry_of_pv ( vg_ptr, pv_ptr);
if ( ret != 0) return ret;
-
- /* We don't need the PE list
- in kernel space like LVs pe_t list */
- pv_ptr->pe = NULL;
- vg_ptr->pv_cur++;
- vg_ptr->pv_act++;
- vg_ptr->pe_total +=
- pv_ptr->pe_total;
-#ifdef LVM_GET_INODE
- /* insert a dummy inode for fs_may_mount */
- pv_ptr->inode = lvm_get_inode(pv_ptr->pv_dev);
-#endif
+ pv_ptr = vg_ptr->pv[p];
+ vg_ptr->pe_total += pv_ptr->pe_total;
+ lvm_do_create_proc_entry_of_pv(vg_ptr, pv_ptr);
return 0;
}
}
}
-return -EPERM;
+ return -EPERM;
} /* lvm_do_vg_extend() */
@@ -2060,10 +1959,6 @@ static int lvm_do_vg_reduce(vg_t *vg_ptr, void *arg) {
strcmp(pv_ptr->pv_name,
pv_name) == 0) {
if (pv_ptr->lv_cur > 0) return -EPERM;
- vg_ptr->pe_total -=
- pv_ptr->pe_total;
- vg_ptr->pv_cur--;
- vg_ptr->pv_act--;
lvm_do_pv_remove(vg_ptr, p);
/* Make PV pointer array contiguous */
for (; p < vg_ptr->pv_max - 1; p++)
@@ -2091,9 +1986,7 @@ static int lvm_do_vg_rename(vg_t *vg_ptr, void *arg)
if (copy_from_user(vg_name, arg, sizeof(vg_name)) != 0)
return -EFAULT;
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
lvm_do_remove_proc_entry_of_vg ( vg_ptr);
-#endif
strncpy ( vg_ptr->vg_name, vg_name, sizeof ( vg_name)-1);
for ( l = 0; l < vg_ptr->lv_max; l++)
@@ -2115,9 +2008,7 @@ static int lvm_do_vg_rename(vg_t *vg_ptr, void *arg)
strncpy(pv_ptr->vg_name, vg_name, NAME_LEN);
}
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
lvm_do_create_proc_entry_of_vg ( vg_ptr);
-#endif
return 0;
} /* lvm_do_vg_rename */
@@ -2166,27 +2057,17 @@ static int lvm_do_vg_remove(int minor)
/* free PVs */
for (i = 0; i < vg_ptr->pv_max; i++) {
if ((pv_ptr = vg_ptr->pv[i]) != NULL) {
-#ifdef DEBUG_KFREE
- printk(KERN_DEBUG
- "%s -- kfree %d\n", lvm_name, __LINE__);
-#endif
+ P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__);
lvm_do_pv_remove(vg_ptr, i);
}
}
-#ifdef CONFIG_DEVFS_FS
devfs_unregister (ch_devfs_handle[vg_ptr->vg_number]);
devfs_unregister (vg_devfs_handle[vg_ptr->vg_number]);
-#endif
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
lvm_do_remove_proc_entry_of_vg ( vg_ptr);
-#endif
-
-#ifdef DEBUG_KFREE
- printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);
-#endif
+ P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__);
kfree(vg_ptr);
vg[VG_CHR(minor)] = NULL;
@@ -2222,11 +2103,6 @@ static int lvm_do_pv_create(pv_t *pvp, vg_t *vg_ptr, ulong p) {
vg_ptr->pv_act++;
vg_ptr->pv_cur++;
-#ifdef LVM_GET_INODE
- /* insert a dummy inode for fs_may_mount */
- pv_ptr->inode = lvm_get_inode(pv_ptr->pv_dev);
-#endif
-
return 0;
} /* lvm_do_pv_create() */
@@ -2237,11 +2113,8 @@ static int lvm_do_pv_create(pv_t *pvp, vg_t *vg_ptr, ulong p) {
static int lvm_do_pv_remove(vg_t *vg_ptr, ulong p) {
pv_t *pv_ptr = vg_ptr->pv[p];
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
lvm_do_remove_proc_entry_of_pv ( vg_ptr, pv_ptr);
-#endif
- vg_ptr->pe_total -=
- pv_ptr->pe_total;
+ vg_ptr->pe_total -= pv_ptr->pe_total;
vg_ptr->pv_cur--;
vg_ptr->pv_act--;
#ifdef LVM_GET_INODE
@@ -2320,11 +2193,9 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv)
"%s -- LV_CREATE: vmalloc error LV_CURRENT_PE of %d Byte "
"at line %d\n",
lvm_name, size, __LINE__);
-#ifdef DEBUG_KFREE
- printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);
-#endif
+ P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__);
kfree(lv_ptr);
- vg[VG_CHR(minor)]->lv[l] = NULL;
+ vg_ptr->lv[l] = NULL;
return -ENOMEM;
}
if (copy_from_user(lv_ptr->lv_current_pe, pep, size)) {
@@ -2354,9 +2225,8 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv)
"%s -- lvm_do_lv_create: vmalloc error LV_BLOCK_EXCEPTION "
"of %d byte at line %d\n",
lvm_name, size, __LINE__);
-#ifdef DEBUG_KFREE
- printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);
-#endif
+ P_KFREE("%s -- kfree %d\n", lvm_name,
+ __LINE__);
kfree(lv_ptr);
vg_ptr->lv[l] = NULL;
return -ENOMEM;
@@ -2364,7 +2234,7 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv)
if (copy_from_user(lv_ptr->lv_block_exception, lvbe, size)) {
vfree(lv_ptr->lv_block_exception);
kfree(lv_ptr);
- vg[VG_CHR(minor)]->lv[l] = NULL;
+ vg_ptr->lv[l] = NULL;
return -EFAULT;
}
/* point to the original logical volume */
@@ -2372,33 +2242,32 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv)
lv_ptr->lv_snapshot_minor = 0;
lv_ptr->lv_snapshot_org = lv_ptr;
- lv_ptr->lv_snapshot_prev = NULL;
- /* walk thrugh the snapshot list */
- while (lv_ptr->lv_snapshot_next != NULL)
- lv_ptr = lv_ptr->lv_snapshot_next;
- /* now lv_ptr points to the last existing snapshot in the chain */
- vg_ptr->lv[l]->lv_snapshot_prev = lv_ptr;
/* our new one now back points to the previous last in the chain
which can be the original logical volume */
lv_ptr = vg_ptr->lv[l];
/* now lv_ptr points to our new last snapshot logical volume */
- lv_ptr->lv_snapshot_org = lv_ptr->lv_snapshot_prev->lv_snapshot_org;
- lv_ptr->lv_snapshot_next = NULL;
lv_ptr->lv_current_pe = lv_ptr->lv_snapshot_org->lv_current_pe;
+ lv_ptr->lv_allocated_snapshot_le = lv_ptr->lv_allocated_le;
lv_ptr->lv_allocated_le = lv_ptr->lv_snapshot_org->lv_allocated_le;
lv_ptr->lv_current_le = lv_ptr->lv_snapshot_org->lv_current_le;
lv_ptr->lv_size = lv_ptr->lv_snapshot_org->lv_size;
lv_ptr->lv_stripes = lv_ptr->lv_snapshot_org->lv_stripes;
lv_ptr->lv_stripesize = lv_ptr->lv_snapshot_org->lv_stripesize;
+
+ /* Update the VG PE(s) used by snapshot reserve space. */
+ vg_ptr->pe_allocated += lv_ptr->lv_allocated_snapshot_le;
+
if ((ret = lvm_snapshot_alloc(lv_ptr)) != 0)
{
vfree(lv_ptr->lv_block_exception);
kfree(lv_ptr);
- vg[VG_CHR(minor)]->lv[l] = NULL;
+ vg_ptr->lv[l] = NULL;
return ret;
}
for ( e = 0; e < lv_ptr->lv_remap_ptr; e++)
- lvm_hash_link (lv_ptr->lv_block_exception + e, lv_ptr->lv_block_exception[e].rdev_org, lv_ptr->lv_block_exception[e].rsector_org, lv_ptr);
+ lvm_hash_link (lv_ptr->lv_block_exception + e,
+ lv_ptr->lv_block_exception[e].rdev_org,
+ lv_ptr->lv_block_exception[e].rsector_org, lv_ptr);
/* need to fill the COW exception table data
into the page for disk i/o */
lvm_snapshot_fill_COW_page(vg_ptr, lv_ptr);
@@ -2426,9 +2295,8 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv)
vg_ptr->lv_cur++;
lv_ptr->lv_status = lv_status_save;
-#ifdef CONFIG_DEVFS_FS
{
- char *lv_tmp, *lv_buf = NULL;
+ char *lv_tmp, *lv_buf = lv->lv_name;
strtok(lv->lv_name, "/"); /* /dev */
while((lv_tmp = strtok(NULL, "/")) != NULL)
@@ -2440,24 +2308,29 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv)
S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP,
&lvm_blk_dops, NULL);
}
-#endif
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr);
-#endif
/* optionally add our new snapshot LV */
if (lv_ptr->lv_access & LV_SNAPSHOT) {
+ lv_t *org = lv_ptr->lv_snapshot_org, *last;
+
/* sync the original logical volume */
- fsync_dev(lv_ptr->lv_snapshot_org->lv_dev);
+ fsync_dev(org->lv_dev);
#ifdef LVM_VFS_ENHANCEMENT
/* VFS function call to sync and lock the filesystem */
- fsync_dev_lockfs(lv_ptr->lv_snapshot_org->lv_dev);
+ fsync_dev_lockfs(org->lv_dev);
#endif
- lv_ptr->lv_snapshot_org->lv_access |= LV_SNAPSHOT_ORG;
- lv_ptr->lv_access &= ~LV_SNAPSHOT_ORG;
- /* put ourselve into the chain */
- lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr;
+
+ down(&org->lv_snapshot_sem);
+ org->lv_access |= LV_SNAPSHOT_ORG;
+ lv_ptr->lv_access &= ~LV_SNAPSHOT_ORG; /* this can only hide an userspace bug */
+
+ /* Link in the list of snapshot volumes */
+ for (last = org; last->lv_snapshot_next; last = last->lv_snapshot_next);
+ lv_ptr->lv_snapshot_prev = last;
+ last->lv_snapshot_next = lv_ptr;
+ up(&org->lv_snapshot_sem);
}
/* activate the logical volume */
@@ -2513,6 +2386,31 @@ static int lvm_do_lv_remove(int minor, char *lv_name, int l)
lv_ptr->lv_snapshot_next != NULL)
return -EPERM;
+ if (lv_ptr->lv_access & LV_SNAPSHOT) {
+ /*
+ * Atomically make the the snapshot invisible
+ * to the original lv before playing with it.
+ */
+ lv_t * org = lv_ptr->lv_snapshot_org;
+ down(&org->lv_snapshot_sem);
+
+ /* remove this snapshot logical volume from the chain */
+ lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr->lv_snapshot_next;
+ if (lv_ptr->lv_snapshot_next != NULL) {
+ lv_ptr->lv_snapshot_next->lv_snapshot_prev =
+ lv_ptr->lv_snapshot_prev;
+ }
+ up(&org->lv_snapshot_sem);
+
+ /* no more snapshots? */
+ if (!org->lv_snapshot_next)
+ org->lv_access &= ~LV_SNAPSHOT_ORG;
+ lvm_snapshot_release(lv_ptr);
+
+ /* Update the VG PE(s) used by snapshot reserve space. */
+ vg_ptr->pe_allocated -= lv_ptr->lv_allocated_snapshot_le;
+ }
+
lv_ptr->lv_status |= LV_SPINDOWN;
/* sync the buffers */
@@ -2532,7 +2430,8 @@ static int lvm_do_lv_remove(int minor, char *lv_name, int l)
vg_lv_map[MINOR(lv_ptr->lv_dev)].vg_number = ABS_MAX_VG;
vg_lv_map[MINOR(lv_ptr->lv_dev)].lv_number = -1;
- /* correct the PE count in PVs if this is no snapshot logical volume */
+ /* correct the PE count in PVs if this is not a snapshot
+ logical volume */
if (!(lv_ptr->lv_access & LV_SNAPSHOT)) {
/* only if this is no snapshot logical volume because
we share the lv_current_pe[] structs with the
@@ -2546,31 +2445,13 @@ static int lvm_do_lv_remove(int minor, char *lv_name, int l)
}
}
vfree(lv_ptr->lv_current_pe);
- /* LV_SNAPSHOT */
- } else {
- /* remove this snapshot logical volume from the chain */
- lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr->lv_snapshot_next;
- if (lv_ptr->lv_snapshot_next != NULL) {
- lv_ptr->lv_snapshot_next->lv_snapshot_prev =
- lv_ptr->lv_snapshot_prev;
- }
- /* no more snapshots? */
- if (lv_ptr->lv_snapshot_org->lv_snapshot_next == NULL)
- lv_ptr->lv_snapshot_org->lv_access &= ~LV_SNAPSHOT_ORG;
- lvm_snapshot_release(lv_ptr);
}
-#ifdef CONFIG_DEVFS_FS
devfs_unregister(lv_devfs_handle[lv_ptr->lv_number]);
-#endif
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
lvm_do_remove_proc_entry_of_lv ( vg_ptr, lv_ptr);
-#endif
-#ifdef DEBUG_KFREE
- printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);
-#endif
+ P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__);
kfree(lv_ptr);
vg_ptr->lv[l] = NULL;
vg_ptr->lv_cur--;
@@ -2638,21 +2519,24 @@ static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *lv)
}
memcpy(lvbe,
lv_ptr->lv_block_exception,
- (lv->lv_remap_end > lv_ptr->lv_remap_end ? lv_ptr->lv_remap_ptr : lv->lv_remap_end) * sizeof(lv_block_exception_t));
+ (lv->lv_remap_end > lv_ptr->lv_remap_end ?
+ lv_ptr->lv_remap_ptr : lv->lv_remap_end) * sizeof(lv_block_exception_t));
lv_ptr->lv_block_exception = lvbe;
lv_ptr->lv_remap_end = lv->lv_remap_end;
if (lvm_snapshot_alloc_hash_table(lv_ptr) != 0)
{
- lvm_drop_snapshot(lv_ptr, "hash_alloc");
+ lvm_drop_snapshot(lv_ptr, "no memory for hash table");
up(&lv_ptr->lv_snapshot_org->lv_snapshot_sem);
vfree(lvbe_old);
vfree(lvs_hash_table_old);
- return 1;
+ return -ENOMEM;
}
for (e = 0; e < lv_ptr->lv_remap_ptr; e++)
- lvm_hash_link (lv_ptr->lv_block_exception + e, lv_ptr->lv_block_exception[e].rdev_org, lv_ptr->lv_block_exception[e].rsector_org, lv_ptr);
+ lvm_hash_link (lv_ptr->lv_block_exception + e,
+ lv_ptr->lv_block_exception[e].rdev_org,
+ lv_ptr->lv_block_exception[e].rsector_org, lv_ptr);
up(&lv_ptr->lv_snapshot_org->lv_snapshot_sem);
@@ -2677,15 +2561,6 @@ static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *lv)
return -EFAULT;
}
-#ifdef DEBUG
- printk(KERN_DEBUG
- "%s -- fsync_dev and "
- "invalidate_buffers for %s [%s] in %s\n",
- lvm_name, lv_ptr->lv_name,
- kdevname(lv_ptr->lv_dev),
- vg_ptr->vg_name);
-#endif
-
/* reduce allocation counters on PV(s) */
for (le = 0; le < lv_ptr->lv_allocated_le; le++) {
vg_ptr->pe_allocated--;
@@ -2714,9 +2589,6 @@ static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *lv)
/* save # of old allocated logical extents */
old_allocated_le = lv_ptr->lv_allocated_le;
- /* in case of shrinking -> let's flush */
- if ( end > lv->lv_current_le) fsync_dev(lv_ptr->lv_dev);
-
/* copy preloaded LV */
memcpy((char *) lv_ptr, (char *) lv, sizeof(lv_t));
@@ -2914,15 +2786,11 @@ static int lvm_do_lv_rename(vg_t *vg_ptr, lv_req_t *lv_req, lv_t *lv)
if ( (lv_ptr = vg_ptr->lv[l]) == NULL) continue;
if (lv_ptr->lv_dev == lv->lv_dev)
{
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
lvm_do_remove_proc_entry_of_lv ( vg_ptr, lv_ptr);
-#endif
strncpy(lv_ptr->lv_name,
lv_req->lv_name,
NAME_LEN);
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr);
-#endif
break;
}
}
@@ -3004,9 +2872,22 @@ static int lvm_do_pv_status(vg_t *vg_ptr, void *arg)
/*
+ * create a devfs entry for a volume group
+ */
+void lvm_do_create_devfs_entry_of_vg ( vg_t *vg_ptr) {
+ vg_devfs_handle[vg_ptr->vg_number] = devfs_mk_dir(0, vg_ptr->vg_name, NULL);
+ ch_devfs_handle[vg_ptr->vg_number] = devfs_register(
+ vg_devfs_handle[vg_ptr->vg_number] , "group",
+ DEVFS_FL_DEFAULT, LVM_CHAR_MAJOR, vg_ptr->vg_number,
+ S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
+ &lvm_chr_fops, NULL);
+}
+
+
+/*
* create a /proc entry for a logical volume
*/
-inline void lvm_do_create_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) {
+void lvm_do_create_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) {
char *basename;
if ( vg_ptr->lv_subdir_pde != NULL) {
@@ -3026,7 +2907,7 @@ inline void lvm_do_create_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) {
/*
* remove a /proc entry for a logical volume
*/
-inline void lvm_do_remove_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) {
+void lvm_do_remove_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) {
char *basename;
if ( vg_ptr->lv_subdir_pde != NULL) {
@@ -3041,13 +2922,17 @@ inline void lvm_do_remove_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) {
/*
* create a /proc entry for a physical volume
*/
-inline void lvm_do_create_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) {
+void lvm_do_create_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) {
+ int offset = 0;
char *basename;
-
- basename = strrchr(pv_ptr->pv_name, '/');
- if (basename == NULL) basename = pv_ptr->pv_name;
- else basename++;
- pde = create_proc_entry(basename, S_IFREG, vg_ptr->pv_subdir_pde);
+ char buffer[NAME_LEN];
+
+ basename = pv_ptr->pv_name;
+ if (strncmp(basename, "/dev/", 5) == 0) offset = 5;
+ strncpy(buffer, basename + offset, sizeof(buffer));
+ basename = buffer;
+ while ( ( basename = strchr ( basename, '/')) != NULL) *basename = '_';
+ pde = create_proc_entry(buffer, S_IFREG, vg_ptr->pv_subdir_pde);
if ( pde != NULL) {
pde->read_proc = lvm_proc_read_pv_info;
pde->data = pv_ptr;
@@ -3058,7 +2943,7 @@ inline void lvm_do_create_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) {
/*
* remove a /proc entry for a physical volume
*/
-inline void lvm_do_remove_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) {
+void lvm_do_remove_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) {
char *basename;
basename = strrchr(pv_ptr->pv_name, '/');
@@ -3074,7 +2959,6 @@ inline void lvm_do_remove_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) {
/*
* create a /proc entry for a volume group
*/
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
void lvm_do_create_proc_entry_of_vg ( vg_t *vg_ptr) {
int l, p;
pv_t *pv_ptr;
@@ -3090,24 +2974,25 @@ void lvm_do_create_proc_entry_of_vg ( vg_t *vg_ptr) {
pde->read_proc = lvm_proc_read_vg_info;
pde->data = vg_ptr;
}
- vg_ptr->lv_subdir_pde =
- create_proc_entry(LVM_LV_SUBDIR, S_IFDIR,
- vg_ptr->vg_dir_pde);
- vg_ptr->pv_subdir_pde =
- create_proc_entry(LVM_PV_SUBDIR, S_IFDIR,
- vg_ptr->vg_dir_pde);
- }
-
- if ( vg_ptr->pv_subdir_pde != NULL) {
- for ( l = 0; l < vg_ptr->lv_max; l++) {
- if ( ( lv_ptr = vg_ptr->lv[l]) == NULL) continue;
- lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr);
- }
- for ( p = 0; p < vg_ptr->pv_max; p++) {
- if ( ( pv_ptr = vg_ptr->pv[p]) == NULL) continue;
- lvm_do_create_proc_entry_of_pv ( vg_ptr, pv_ptr);
- }
- }
+ pde = create_proc_entry(LVM_LV_SUBDIR, S_IFDIR,
+ vg_ptr->vg_dir_pde);
+ if ( pde != NULL) {
+ vg_ptr->lv_subdir_pde = pde;
+ for ( l = 0; l < vg_ptr->lv_max; l++) {
+ if ( ( lv_ptr = vg_ptr->lv[l]) == NULL) continue;
+ lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr);
+ }
+ }
+ pde = create_proc_entry(LVM_PV_SUBDIR, S_IFDIR,
+ vg_ptr->vg_dir_pde);
+ if ( pde != NULL) {
+ vg_ptr->pv_subdir_pde = pde;
+ for ( p = 0; p < vg_ptr->pv_max; p++) {
+ if ( ( pv_ptr = vg_ptr->pv[p]) == NULL) continue;
+ lvm_do_create_proc_entry_of_pv ( vg_ptr, pv_ptr);
+ }
+ }
+ }
}
/*
@@ -3133,18 +3018,12 @@ void lvm_do_remove_proc_entry_of_vg ( vg_t *vg_ptr) {
remove_proc_entry(vg_ptr->vg_name, lvm_proc_vg_subdir);
}
}
-#endif
/*
* support function initialize gendisk variables
*/
-#ifdef __initfunc
-__initfunc(void lvm_geninit(struct gendisk *lvm_gdisk))
-#else
-void __init
- lvm_geninit(struct gendisk *lvm_gdisk)
-#endif
+void __init lvm_geninit(struct gendisk *lvm_gdisk)
{
int i = 0;
@@ -3166,39 +3045,30 @@ void __init
} /* lvm_gen_init() */
-#ifdef LVM_GET_INODE
/*
- * support function to get an empty inode
- *
- * Gets an empty inode to be inserted into the inode hash,
- * so that a physical volume can't be mounted.
- * This is analog to drivers/block/md.c
- *
- * Is this the real thing?
- *
+ * return a pointer to a '-' padded uuid
*/
-struct inode *lvm_get_inode(int dev)
-{
- struct inode *inode_this = NULL;
+static char *lvm_show_uuid ( char *uuidstr) {
+ int i, j;
+ static char uuid[NAME_LEN] = { 0, };
- /* Lock the device by inserting a dummy inode. */
- inode_this = get_empty_inode();
- inode_this->i_dev = dev;
- insert_inode_hash(inode_this);
- return inode_this;
-}
+ memset ( uuid, 0, NAME_LEN);
+ i = 6;
+ memcpy ( uuid, uuidstr, i);
+ uuidstr += i;
-/*
- * support function to clear an inode
- *
- */
-void lvm_clear_inode(struct inode *inode)
-{
-#ifdef I_FREEING
- inode->i_state |= I_FREEING;
-#endif
- clear_inode(inode);
- return;
+ for ( j = 0; j < 6; j++) {
+ uuid[i++] = '-';
+ memcpy ( &uuid[i], uuidstr, 4);
+ uuidstr += 4;
+ i += 4;
+ }
+
+ memcpy ( &uuid[i], uuidstr, 2 );
+
+ return uuid;
}
-#endif /* #ifdef LVM_GET_INODE */
+
+module_init(lvm_init);
+module_exit(lvm_cleanup);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 8542bc2b0..5d4bab6c9 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2033,68 +2033,65 @@ abort:
struct {
int set;
int noautodetect;
+} raid_setup_args md__initdata;
-} raid_setup_args md__initdata = { 0, 0 };
-
-void md_setup_drive(void) md__init;
+void md_setup_drive (void) md__init;
/*
* Searches all registered partitions for autorun RAID arrays
* at boot time.
*/
-#ifdef CONFIG_AUTODETECT_RAID
-static int detected_devices[128] md__initdata = { 0, };
-static int dev_cnt=0;
+static int detected_devices[128] md__initdata;
+static int dev_cnt;
+
void md_autodetect_dev(kdev_t dev)
{
if (dev_cnt >= 0 && dev_cnt < 127)
detected_devices[dev_cnt++] = dev;
}
-#endif
-int md__init md_run_setup(void)
+
+static void autostart_arrays (void)
{
-#ifdef CONFIG_AUTODETECT_RAID
mdk_rdev_t *rdev;
int i;
- if (raid_setup_args.noautodetect)
- printk(KERN_INFO "skipping autodetection of RAID arrays\n");
- else {
-
- printk(KERN_INFO "autodetecting RAID arrays\n");
+ printk(KERN_INFO "autodetecting RAID arrays\n");
- for (i=0; i<dev_cnt; i++) {
- kdev_t dev = detected_devices[i];
+ for (i=0; i<dev_cnt; i++) {
+ kdev_t dev = detected_devices[i];
- if (md_import_device(dev,1)) {
- printk(KERN_ALERT "could not import %s!\n",
- partition_name(dev));
- continue;
- }
- /*
- * Sanity checks:
- */
- rdev = find_rdev_all(dev);
- if (!rdev) {
- MD_BUG();
- continue;
- }
- if (rdev->faulty) {
- MD_BUG();
- continue;
- }
- md_list_add(&rdev->pending, &pending_raid_disks);
+ if (md_import_device(dev,1)) {
+ printk(KERN_ALERT "could not import %s!\n",
+ partition_name(dev));
+ continue;
}
-
- autorun_devices(-1);
+ /*
+ * Sanity checks:
+ */
+ rdev = find_rdev_all(dev);
+ if (!rdev) {
+ MD_BUG();
+ continue;
+ }
+ if (rdev->faulty) {
+ MD_BUG();
+ continue;
+ }
+ md_list_add(&rdev->pending, &pending_raid_disks);
}
+ autorun_devices(-1);
+}
+
+int md__init md_run_setup(void)
+{
+ if (raid_setup_args.noautodetect)
+ printk(KERN_INFO "skipping autodetection of RAID arrays\n");
+ else
+ autostart_arrays();
dev_cnt = -1; /* make sure further calls to md_autodetect_dev are ignored */
-#endif
-#ifdef CONFIG_MD_BOOT
md_setup_drive();
-#endif
return 0;
}
@@ -2558,6 +2555,11 @@ static int md_ioctl (struct inode *inode, struct file *file,
md_print_devices();
goto done_unlock;
+ case RAID_AUTORUN:
+ err = 0;
+ autostart_arrays();
+ goto done;
+
case BLKGETSIZE: /* Return device size */
if (!arg) {
err = -EINVAL;
@@ -3639,14 +3641,12 @@ int md__init md_init (void)
return (0);
}
-#ifdef CONFIG_MD_BOOT
-#define MAX_MD_BOOT_DEVS 8
-struct {
- unsigned long set;
- int pers[MAX_MD_BOOT_DEVS];
- int chunk[MAX_MD_BOOT_DEVS];
- kdev_t devices[MAX_MD_BOOT_DEVS][MD_SB_DISKS];
-} md_setup_args md__initdata = { 0, };
+static struct {
+ char device_set [MAX_MD_DEVS];
+ int pers[MAX_MD_DEVS];
+ int chunk[MAX_MD_DEVS];
+ kdev_t devices[MAX_MD_DEVS][MD_SB_DISKS];
+} md_setup_args md__initdata;
/*
* Parse the command-line parameters given our kernel, but do not
@@ -3676,10 +3676,10 @@ static int md__init md_setup(char *str)
printk("md: Too few arguments supplied to md=.\n");
return 0;
}
- if (minor >= MAX_MD_BOOT_DEVS) {
+ if (minor >= MAX_MD_DEVS) {
printk ("md: Minor device number too high.\n");
return 0;
- } else if (md_setup_args.set & (1 << minor)) {
+ } else if (md_setup_args.device_set[minor]) {
printk ("md: Warning - md=%d,... has been specified twice;\n"
" will discard the first definition.\n", minor);
}
@@ -3737,7 +3737,7 @@ static int md__init md_setup(char *str)
printk ("md: Will configure md%d (%s) from %s, below.\n",
minor, pername, devnames);
md_setup_args.devices[minor][i] = (kdev_t) 0;
- md_setup_args.set |= (1 << minor);
+ md_setup_args.device_set[minor] = 1;
return 1;
}
@@ -3747,10 +3747,11 @@ void md__init md_setup_drive(void)
kdev_t dev;
mddev_t*mddev;
- for (minor = 0; minor < MAX_MD_BOOT_DEVS; minor++) {
+ for (minor = 0; minor < MAX_MD_DEVS; minor++) {
mdu_disk_info_t dinfo;
- int err=0;
- if (!(md_setup_args.set & (1 << minor)))
+
+ int err = 0;
+ if (!md_setup_args.device_set[minor])
continue;
printk("md: Loading md%d.\n", minor);
if (mddev_map[minor].mddev) {
@@ -3776,7 +3777,7 @@ void md__init md_setup_drive(void)
ainfo.layout = 0;
ainfo.chunk_size = md_setup_args.chunk[minor];
err = set_array_info(mddev, &ainfo);
- for (i=0; !err && (dev = md_setup_args.devices[minor][i]); i++) {
+ for (i = 0; !err && (dev = md_setup_args.devices[minor][i]); i++) {
dinfo.number = i;
dinfo.raid_disk = i;
dinfo.state = (1<<MD_DISK_ACTIVE)|(1<<MD_DISK_SYNC);
@@ -3807,7 +3808,6 @@ void md__init md_setup_drive(void)
}
__setup("md=", md_setup);
-#endif
#ifdef MODULE
int init_module (void)
@@ -3859,9 +3859,7 @@ void cleanup_module (void)
#endif
__initcall(md_init);
-#if defined(CONFIG_AUTODETECT_RAID) || defined(CONFIG_MD_BOOT)
__initcall(md_run_setup);
-#endif
MD_EXPORT_SYMBOL(md_size);
MD_EXPORT_SYMBOL(register_md_personality);
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 7981fe764..3ad3940a9 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -714,6 +714,11 @@ static void compute_parity(struct stripe_head *sh, int method)
break;
}
spin_unlock_irq(&conf->device_lock);
+ if (count>1) {
+ xor_block(count, bh_ptr);
+ count = 1;
+ }
+
for (i = disks; i--;)
if (chosen[i]) {
struct buffer_head *bh = sh->bh_cache[i];
diff --git a/drivers/md/xor.c b/drivers/md/xor.c
index b9b1cefe9..f0b76d466 100644
--- a/drivers/md/xor.c
+++ b/drivers/md/xor.c
@@ -57,8 +57,7 @@ xor_block(unsigned int count, struct buffer_head **bh_ptr)
/* Set of all registered templates. */
static struct xor_block_template *template_list;
-/* The -6*32 shift factor colors the cache. */
-#define BENCH_SIZE (PAGE_SIZE-6*32)
+#define BENCH_SIZE (PAGE_SIZE)
static void
do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2)
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index ae4054d35..02c9204e9 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -118,6 +118,14 @@
LK1.1.11 13 Nov 2000 andrewm
- Dump MOD_INC/DEC_USE_COUNT, use SET_MODULE_OWNER
+ LK1.1.12 1 Jan 2001 andrewm
+ - Call pci_enable_device before we request our IRQ (Tobias Ringstrom)
+ - Add 3c590 PCI latency timer hack to vortex_probe1 (from 0.99Ra)
+ - Added extended wait_for_completion for the 3c905CX.
+ - Look for an MII on PHY index 24 first (3c905CX oddity).
+ - Add HAS_NWAY to 3cSOHO100-TX (Brett Frankenberger)
+ - Don't free skbs we don't own on oom path in vortex_open().
+
- See http://www.uow.edu.au/~andrewm/linux/#3c59x-2.3 for more details.
- Also see Documentation/networking/vortex.txt
*/
@@ -203,7 +211,7 @@ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits;
#include <linux/delay.h>
static char version[] __devinitdata =
-"3c59x.c:LK1.1.11 13 Nov 2000 Donald Becker and others. http://www.scyld.com/network/vortex.html " "$Revision: 1.102.2.46 $\n";
+"3c59x.c:LK1.1.12 06 Jan 2000 Donald Becker and others. http://www.scyld.com/network/vortex.html " "$Revision: 1.102.2.46 $\n";
MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
MODULE_DESCRIPTION("3Com 3c59x/3c90x/3c575 series Vortex/Boomerang/Cyclone driver");
@@ -424,7 +432,7 @@ static struct vortex_chip_info {
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
{"3cSOHO100-TX Hurricane",
- PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, },
{"3c555 Laptop Hurricane",
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|EEPROM_8BIT, 128, },
{"3c556 Laptop Tornado",
@@ -843,10 +851,15 @@ static int __devinit vortex_init_one (struct pci_dev *pdev,
{
int rc;
- rc = vortex_probe1 (pdev, pci_resource_start (pdev, 0), pdev->irq,
- ent->driver_data, vortex_cards_found);
- if (rc == 0)
- vortex_cards_found++;
+ /* wake up and enable device */
+ if (pci_enable_device (pdev)) {
+ rc = -EIO;
+ } else {
+ rc = vortex_probe1 (pdev, pci_resource_start (pdev, 0), pdev->irq,
+ ent->driver_data, vortex_cards_found);
+ if (rc == 0)
+ vortex_cards_found++;
+ }
return rc;
}
@@ -863,7 +876,7 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
struct vortex_private *vp;
int option;
unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */
- int i;
+ int i, step;
struct net_device *dev;
static int printed_version;
int retval;
@@ -889,7 +902,6 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
vci->name,
ioaddr);
- /* private struct aligned and zeroed by init_etherdev */
vp = dev->priv;
dev->base_addr = ioaddr;
dev->irq = irq;
@@ -908,19 +920,29 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
if (pdev) {
/* EISA resources already marked, so only PCI needs to do this here */
/* Ignore return value, because Cardbus drivers already allocate for us */
- if (request_region(ioaddr, vci->io_size, dev->name) != NULL) {
+ if (request_region(ioaddr, vci->io_size, dev->name) != NULL)
vp->must_free_region = 1;
- }
-
- /* wake up and enable device */
- if (pci_enable_device (pdev)) {
- retval = -EIO;
- goto free_region;
- }
/* enable bus-mastering if necessary */
if (vci->flags & PCI_USES_MASTER)
pci_set_master (pdev);
+
+ if (vci->drv_flags & IS_VORTEX) {
+ u8 pci_latency;
+ u8 new_latency = 248;
+
+ /* Check the PCI latency value. On the 3c590 series the latency timer
+ must be set to the maximum value to avoid data corruption that occurs
+ when the timer expires during a transfer. This bug exists the Vortex
+ chip only. */
+ pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
+ if (pci_latency < new_latency) {
+ printk(KERN_INFO "%s: Overriding PCI latency"
+ " timer (CFLT) setting of %d, new value is %d.\n",
+ dev->name, pci_latency, new_latency);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, new_latency);
+ }
+ }
}
spin_lock_init(&vp->lock);
@@ -1025,6 +1047,13 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
dev->irq);
#endif
+ EL3WINDOW(4);
+ step = (inb(ioaddr + Wn4_NetDiag) & 0x1e) >> 1;
+ printk(KERN_INFO " product code '%c%c' rev %02x.%d date %02d-"
+ "%02d-%02d\n", eeprom[6]&0xff, eeprom[6]>>8, eeprom[0x14],
+ step, (eeprom[4]>>5) & 15, eeprom[4] & 31, eeprom[4]>>9);
+
+
if (pdev && vci->drv_flags & HAS_CB_FNS) {
unsigned long fn_st_addr; /* Cardbus function status space */
unsigned short n;
@@ -1089,8 +1118,19 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
mii_preamble_required++;
mii_preamble_required++;
mdio_read(dev, 24, 1);
- for (phy = 1; phy <= 32 && phy_idx < sizeof(vp->phys); phy++) {
- int mii_status, phyx = phy & 0x1f;
+ for (phy = 0; phy < 32 && phy_idx < 1; phy++) {
+ int mii_status, phyx;
+
+ /*
+ * For the 3c905CX we look at index 24 first, because it bogusly
+ * reports an external PHY at all indices
+ */
+ if (phy == 0)
+ phyx = 24;
+ else if (phy <= 24)
+ phyx = phy - 1;
+ else
+ phyx = phy;
mii_status = mdio_read(dev, phyx, 1);
if (mii_status && mii_status != 0xffff) {
vp->phys[phy_idx++] = phyx;
@@ -1135,12 +1175,13 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
dev->set_multicast_list = set_rx_mode;
dev->tx_timeout = vortex_tx_timeout;
dev->watchdog_timeo = (watchdog * HZ) / 1000;
-
+// publish_netdev(dev);
return 0;
free_region:
if (vp->must_free_region)
release_region(ioaddr, vci->io_size);
+// withdraw_netdev(dev);
unregister_netdev(dev);
kfree (dev);
printk(KERN_ERR PFX "vortex_probe1 fails. Returns %d\n", retval);
@@ -1150,13 +1191,23 @@ out:
static void wait_for_completion(struct net_device *dev, int cmd)
{
- int i = 4000;
+ int i;
outw(cmd, dev->base_addr + EL3_CMD);
- while (--i > 0) {
+ for (i = 0; i < 2000; i++) {
if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress))
return;
}
+
+ /* OK, that didn't work. Do it the slow way. One second */
+ for (i = 0; i < 100000; i++) {
+ if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress)) {
+ printk(KERN_INFO "%s: command 0x%04x took %d usecs! Please tell andrewm@uow.edu.au\n",
+ dev->name, cmd, i * 10);
+ return;
+ }
+ udelay(10);
+ }
printk(KERN_ERR "%s: command 0x%04x did not complete! Status=0x%x\n",
dev->name, cmd, inw(dev->base_addr + EL3_STATUS));
}
@@ -1331,6 +1382,7 @@ vortex_up(struct net_device *dev)
set_rx_mode(dev);
outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
+// wait_for_completion(dev, SetTxStart|0x07ff);
outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
/* Allow status bits to be seen. */
@@ -1384,7 +1436,8 @@ vortex_open(struct net_device *dev)
}
if (i != RX_RING_SIZE) {
int j;
- for (j = 0; j < RX_RING_SIZE; j++) {
+ printk(KERN_EMERG "%s: no memory for rx ring\n", dev->name);
+ for (j = 0; j < i; j++) {
if (vp->rx_skbuff[j]) {
dev_kfree_skb(vp->rx_skbuff[j]);
vp->rx_skbuff[j] = 0;
@@ -1532,7 +1585,10 @@ static void vortex_tx_timeout(struct net_device *dev)
printk(KERN_ERR "%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
dev->name, inb(ioaddr + TxStatus),
inw(ioaddr + EL3_STATUS));
-
+ EL3WINDOW(4);
+ printk(KERN_ERR " diagnostics: net %04x media %04x dma %8.8x.\n",
+ inw(ioaddr + Wn4_NetDiag), inw(ioaddr + Wn4_Media),
+ inl(ioaddr + PktStatus));
/* Slight code bloat to be user friendly. */
if ((inb(ioaddr + TxStatus) & 0x88) == 0x88)
printk(KERN_ERR "%s: Transmitter encountered 16 collisions --"
@@ -1663,6 +1719,12 @@ vortex_error(struct net_device *dev, int status)
dev->name, fifo_diag);
/* Adapter failure requires Tx/Rx reset and reinit. */
if (vp->full_bus_master_tx) {
+ int bus_status = inl(ioaddr + PktStatus);
+ /* 0x80000000 PCI master abort. */
+ /* 0x40000000 PCI target abort. */
+ if (vortex_debug)
+ printk(KERN_ERR "%s: PCI bus error, bus status %8.8x\n", dev->name, bus_status);
+
/* In this case, blow the card away */
vortex_down(dev);
wait_for_completion(dev, TotalReset | 0xff);
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 290efb51c..5f9658fa5 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -26,7 +26,7 @@ ifeq ($(CONFIG_ISDN_PPP),y)
obj-$(CONFIG_ISDN) += slhc.o
endif
-subdir-$(CONFIG_PCMCIA) += pcmcia
+subdir-$(CONFIG_NET_PCMCIA) += pcmcia
subdir-$(CONFIG_TULIP) += tulip
subdir-$(CONFIG_IRDA) += irda
subdir-$(CONFIG_TR) += tokenring
diff --git a/drivers/net/depca.c b/drivers/net/depca.c
index 448baa800..d5d3fa19f 100644
--- a/drivers/net/depca.c
+++ b/drivers/net/depca.c
@@ -1817,7 +1817,9 @@ EISA_signature(char *name, s32 eisa_id)
ManCode[5]='\0';
for (i=0;(*signatures[i] != '\0') && (*name == '\0');i++) {
- if (strstr(ManCode, signatures[i]) != NULL) {
+ const char * volatile lhs = ManCode;
+ const char * volatile rhs = signatures[i]; /* egcs-1.1.2 bug */
+ if (strstr(lhs, rhs) != NULL) {
strcpy(name,ManCode);
status = 1;
}
diff --git a/drivers/net/dmfe.c b/drivers/net/dmfe.c
index 481b28700..b160afd78 100644
--- a/drivers/net/dmfe.c
+++ b/drivers/net/dmfe.c
@@ -1596,10 +1596,10 @@ static int __init dmfe_init_module(void)
break;
}
- rc = pci_register_driver(&dmfe_driver);
+ rc = pci_module_init(&dmfe_driver);
if (rc < 0)
return rc;
- if (rc > 0) {
+ if (rc >= 0) {
printk (KERN_INFO "Davicom DM91xx net driver loaded, version "
DMFE_VERSION "\n");
return 0;
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index 298a317e2..2970fac9f 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -29,7 +29,7 @@
static const char *version =
"eepro100.c:v1.09j-t 9/29/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n"
-"eepro100.c: $Revision: 1.35 $ 2000/11/17 Modified by Andrey V. Savochkin <saw@saw.sw.com.sg> and others\n";
+"eepro100.c: $Revision: 1.36 $ 2000/11/17 Modified by Andrey V. Savochkin <saw@saw.sw.com.sg> and others\n";
/* A few user-configurable values that apply to all boards.
First set is undocumented and spelled per Intel recommendations. */
@@ -698,6 +698,7 @@ static int speedo_found1(struct pci_dev *pdev,
This takes less than 10usec and will easily finish before the next
action. */
outl(PortReset, ioaddr + SCBPort);
+ inl(ioaddr + SCBPort);
udelay(10);
if (eeprom[3] & 0x0100)
@@ -785,6 +786,7 @@ static int speedo_found1(struct pci_dev *pdev,
#endif /* kernel_bloat */
outl(PortReset, ioaddr + SCBPort);
+ inl(ioaddr + SCBPort);
udelay(10);
/* Return the chip to its original power state. */
@@ -801,7 +803,7 @@ static int speedo_found1(struct pci_dev *pdev,
sp->tx_ring = tx_ring_space;
sp->tx_ring_dma = tx_ring_dma;
sp->lstats = (struct speedo_stats *)(sp->tx_ring + TX_RING_SIZE);
- sp->lstats_dma = cpu_to_le32(TX_RING_ELEM_DMA(sp, TX_RING_SIZE));
+ sp->lstats_dma = TX_RING_ELEM_DMA(sp, TX_RING_SIZE);
init_timer(&sp->timer); /* used in ioctl() */
sp->full_duplex = option >= 0 && (option & 0x10) ? 1 : 0;
@@ -1002,7 +1004,9 @@ static void speedo_resume(struct net_device *dev)
/* Set the segment registers to '0'. */
wait_for_cmd_done(ioaddr + SCBCmd);
outl(0, ioaddr + SCBPointer);
- inl(ioaddr + SCBPointer); /* XXX */
+ /* impose a delay to avoid a bug */
+ inl(ioaddr + SCBPointer);
+ udelay(10);
outb(RxAddrLoad, ioaddr + SCBCmd);
wait_for_cmd_done(ioaddr + SCBCmd);
outb(CUCmdBase, ioaddr + SCBCmd);
@@ -1010,7 +1014,6 @@ static void speedo_resume(struct net_device *dev)
/* Load the statistics block and rx ring addresses. */
wait_for_cmd_done(ioaddr + SCBCmd);
outl(sp->lstats_dma, ioaddr + SCBPointer);
- inl(ioaddr + SCBPointer); /* XXX */
outb(CUStatsAddr, ioaddr + SCBCmd);
sp->lstats->done_marker = 0;
@@ -1045,7 +1048,7 @@ static void speedo_resume(struct net_device *dev)
/* Start the chip's Tx process and unmask interrupts. */
wait_for_cmd_done(ioaddr + SCBCmd);
- outl(cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->dirty_tx % TX_RING_SIZE)),
+ outl(TX_RING_ELEM_DMA(sp, sp->dirty_tx % TX_RING_SIZE),
ioaddr + SCBPointer);
/* We are not ACK-ing FCP and ER in the interrupt handler yet so they should
remain masked --Dragan */
@@ -1274,7 +1277,7 @@ static void speedo_tx_timeout(struct net_device *dev)
/* Only the command unit has stopped. */
printk(KERN_WARNING "%s: Trying to restart the transmitter...\n",
dev->name);
- outl(cpu_to_le32(TX_RING_ELEM_DMA(sp, dirty_tx % TX_RING_SIZE])),
+ outl(TX_RING_ELEM_DMA(sp, dirty_tx % TX_RING_SIZE]),
ioaddr + SCBPointer);
outw(CUStart, ioaddr + SCBCmd);
reset_mii(dev);
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 7dab437e6..3ec09be5a 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -153,7 +153,7 @@ static int check_crc_flex(unsigned char *cp, int size)
/* Find a free channel, and link in this `tty' line. */
static inline struct ax_disp *ax_alloc(void)
{
- ax25_ctrl_t *axp;
+ ax25_ctrl_t *axp=NULL;
int i;
for (i = 0; i < ax25_maxdev; i++) {
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index d65fddc41..cc31e9e30 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -136,7 +136,7 @@
/* ----------------------------------------------------------------------- */
-#undef SCC_LDELAY 1 /* slow it even a bit more down */
+#undef SCC_LDELAY /* slow it even a bit more down */
#undef SCC_DONT_CHECK /* don't look if the SCCs you specified are available */
#define SCC_MAXCHIPS 4 /* number of max. supported chips */
@@ -1776,7 +1776,7 @@ static int scc_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (hwcfg.vector_latch) {
if (!request_region(Vector_Latch, 1, "scc vector latch"))
- printk(KERN_WARNING "z8530drv: warning, cannot reserve vector latch port 0x%x\n, disabled.", hwcfg.vector_latch);
+ printk(KERN_WARNING "z8530drv: warning, cannot reserve vector latch port 0x%x\n, disabled.", (unsigned int)hwcfg.vector_latch);
else
Vector_Latch = hwcfg.vector_latch;
}
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index ba9c60250..56ca24689 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -892,6 +892,9 @@ static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev,
DET(("myri_ether_init(%p,%p,%d):\n", dev, sdev, num));
dev = init_etherdev(0, sizeof(struct myri_eth));
+ if (!dev)
+ return -ENOMEM;
+
if (version_printed++ == 0)
printk(version);
@@ -982,7 +985,7 @@ static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev,
mp->reg_size, "MyriCOM Regs");
if (!mp->regs) {
printk("MyriCOM: Cannot map MyriCOM registers.\n");
- return -ENODEV;
+ goto err;
}
mp->lanai = (unsigned short *) (mp->regs + (256 * 1024));
mp->lanai3 = (unsigned int *) mp->lanai;
@@ -1059,7 +1062,7 @@ static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev,
if (request_irq(dev->irq, &myri_interrupt,
SA_SHIRQ, "MyriCOM Ethernet", (void *) dev)) {
printk("MyriCOM: Cannot register interrupt handler.\n");
- return -ENODEV;
+ goto err;
}
DET(("ether_setup()\n"));
@@ -1083,6 +1086,9 @@ static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev,
root_myri_dev = mp;
#endif
return 0;
+err: unregister_netdev(dev);
+ kfree(dev);
+ return -ENODEV;
}
static int __init myri_sbus_match(struct sbus_dev *sdev)
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index ccb92e8a5..fa8b951a7 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -695,6 +695,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned char irq_line, int shared, int car
if (a == NULL) {
printk(KERN_ERR "pcnet32: No access methods\n");
+ pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
return -ENODEV;
}
lp->a = *a;
@@ -741,6 +742,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned char irq_line, int shared, int car
printk(", probed IRQ %d.\n", dev->irq);
else {
printk(", failed to detect IRQ line.\n");
+ pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
return -ENODEV;
}
}
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
index d6b2c47f3..c1234c5c8 100644
--- a/drivers/net/ppp_async.c
+++ b/drivers/net/ppp_async.c
@@ -33,13 +33,6 @@
#include <linux/init.h>
#include <asm/uaccess.h>
-#ifndef spin_trylock_bh
-#define spin_trylock_bh(lock) ({ int __r; local_bh_disable(); \
- __r = spin_trylock(lock); \
- if (!__r) local_bh_enable(); \
- __r; })
-#endif
-
#define PPP_VERSION "2.4.1"
#define OBUFSIZE 256
@@ -76,6 +69,7 @@ struct asyncppp {
/* Bit numbers in xmit_flags */
#define XMIT_WAKEUP 0
#define XMIT_FULL 1
+#define XMIT_BUSY 2
/* State bits */
#define SC_TOSS 0x20000000
@@ -181,18 +175,14 @@ ppp_asynctty_close(struct tty_struct *tty)
}
/*
- * Read does nothing.
+ * Read does nothing - no data is ever available this way.
+ * Pppd reads and writes packets via /dev/ppp instead.
*/
static ssize_t
ppp_asynctty_read(struct tty_struct *tty, struct file *file,
unsigned char *buf, size_t count)
{
- /* For now, do the same as the old 2.3.x code useta */
- struct asyncppp *ap = tty->disc_data;
-
- if (ap == 0)
- return -ENXIO;
- return ppp_channel_read(&ap->chan, file, buf, count);
+ return -EAGAIN;
}
/*
@@ -203,12 +193,7 @@ static ssize_t
ppp_asynctty_write(struct tty_struct *tty, struct file *file,
const unsigned char *buf, size_t count)
{
- /* For now, do the same as the old 2.3.x code useta */
- struct asyncppp *ap = tty->disc_data;
-
- if (ap == 0)
- return -ENXIO;
- return ppp_channel_write(&ap->chan, buf, count);
+ return -EAGAIN;
}
static int
@@ -259,25 +244,6 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
err = 0;
break;
-/*
- * For now, do the same as the old 2.3 driver useta
- */
- case PPPIOCGFLAGS:
- case PPPIOCSFLAGS:
- case PPPIOCGASYNCMAP:
- case PPPIOCSASYNCMAP:
- case PPPIOCGRASYNCMAP:
- case PPPIOCSRASYNCMAP:
- case PPPIOCGXASYNCMAP:
- case PPPIOCSXASYNCMAP:
- case PPPIOCGMRU:
- case PPPIOCSMRU:
- err = -EPERM;
- if (!capable(CAP_NET_ADMIN))
- break;
- err = ppp_async_ioctl(&ap->chan, cmd, arg);
- break;
-
case PPPIOCATTACH:
case PPPIOCDETACH:
err = ppp_channel_ioctl(&ap->chan, cmd, arg);
@@ -294,18 +260,7 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
static unsigned int
ppp_asynctty_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
{
- unsigned int mask;
- struct asyncppp *ap = tty->disc_data;
-
- mask = POLLOUT | POLLWRNORM;
-/*
- * For now, do the same as the old 2.3 driver useta
- */
- if (ap != 0)
- mask |= ppp_channel_poll(&ap->chan, file, wait);
- if (test_bit(TTY_OTHER_CLOSED, &tty->flags) || tty_hung_up_p(file))
- mask |= POLLHUP;
- return mask;
+ return 0;
}
static int
@@ -637,8 +592,18 @@ ppp_async_push(struct asyncppp *ap)
int tty_stuffed = 0;
set_bit(XMIT_WAKEUP, &ap->xmit_flags);
- if (!spin_trylock_bh(&ap->xmit_lock))
+ /*
+ * We can get called recursively here if the tty write
+ * function calls our wakeup function. This can happen
+ * for example on a pty with both the master and slave
+ * set to PPP line discipline.
+ * We use the XMIT_BUSY bit to detect this and get out,
+ * leaving the XMIT_WAKEUP bit set to tell the other
+ * instance that it may now be able to write more now.
+ */
+ if (test_and_set_bit(XMIT_BUSY, &ap->xmit_flags))
return 0;
+ spin_lock_bh(&ap->xmit_lock);
for (;;) {
if (test_and_clear_bit(XMIT_WAKEUP, &ap->xmit_flags))
tty_stuffed = 0;
@@ -653,7 +618,7 @@ ppp_async_push(struct asyncppp *ap)
tty_stuffed = 1;
continue;
}
- if (ap->optr == ap->olim && ap->tpkt != 0) {
+ if (ap->optr >= ap->olim && ap->tpkt != 0) {
if (ppp_async_encode(ap)) {
/* finished processing ap->tpkt */
clear_bit(XMIT_FULL, &ap->xmit_flags);
@@ -661,17 +626,29 @@ ppp_async_push(struct asyncppp *ap)
}
continue;
}
- /* haven't made any progress */
- spin_unlock_bh(&ap->xmit_lock);
+ /*
+ * We haven't made any progress this time around.
+ * Clear XMIT_BUSY to let other callers in, but
+ * after doing so we have to check if anyone set
+ * XMIT_WAKEUP since we last checked it. If they
+ * did, we should try again to set XMIT_BUSY and go
+ * around again in case XMIT_BUSY was still set when
+ * the other caller tried.
+ */
+ clear_bit(XMIT_BUSY, &ap->xmit_flags);
+ /* any more work to do? if not, exit the loop */
if (!(test_bit(XMIT_WAKEUP, &ap->xmit_flags)
|| (!tty_stuffed && ap->tpkt != 0)))
break;
- if (!spin_trylock_bh(&ap->xmit_lock))
+ /* more work to do, see if we can do it now */
+ if (test_and_set_bit(XMIT_BUSY, &ap->xmit_flags))
break;
}
+ spin_unlock_bh(&ap->xmit_lock);
return done;
flush:
+ clear_bit(XMIT_BUSY, &ap->xmit_flags);
if (ap->tpkt != 0) {
kfree_skb(ap->tpkt);
ap->tpkt = 0;
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index 8744f6186..7fffdf4f7 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -5,23 +5,24 @@
* PPPoE --- PPP over Ethernet (RFC 2516)
*
*
- * Version: 0.6.4
+ * Version: 0.6.5
*
* 030700 : Fixed connect logic to allow for disconnect.
- * 270700 : Fixed potential SMP problems; we must protect against
- * simultaneous invocation of ppp_input
+ * 270700 : Fixed potential SMP problems; we must protect against
+ * simultaneous invocation of ppp_input
* and ppp_unregister_channel.
* 040800 : Respect reference count mechanisms on net-devices.
* 200800 : fix kfree(skb) in pppoe_rcv (acme)
* Module reference count is decremented in the right spot now,
- * guards against sock_put not actually freeing the sk
+ * guards against sock_put not actually freeing the sk
* in pppoe_release.
* 051000 : Initialization cleanup.
* 111100 : Fix recvmsg.
+ * 050101 : Fix PADT procesing.
*
* Author: Michal Ostrowski <mostrows@styx.uwaterloo.ca>
* Contributors:
- * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ * Arnaldo Carvalho de Melo <acme@xconectiva.com.br>
*
* License:
* This program is free software; you can redistribute it and/or
@@ -110,7 +111,7 @@ static int hash_item(unsigned long sid, unsigned char *addr)
hash ^= sid >> (i*PPPOE_HASH_BITS);
return hash & ( PPPOE_HASH_SIZE - 1 );
-}
+}
static struct pppox_opt *item_hash_table[PPPOE_HASH_SIZE] = { 0, };
@@ -238,7 +239,7 @@ static int pppoe_device_event(struct notifier_block *this,
struct net_device *dev = (struct net_device *) ptr;
struct pppox_opt *po = NULL;
int hash = 0;
-
+
/* Only look at sockets that are using this specific device. */
switch (event) {
case NETDEV_CHANGEMTU:
@@ -255,13 +256,13 @@ static int pppoe_device_event(struct notifier_block *this,
po = item_hash_table[hash];
++hash;
}
-
+
while (po && hash < PPPOE_HASH_SIZE){
if(po->pppoe_dev == dev){
lock_sock(po->sk);
if (po->sk->state & (PPPOX_CONNECTED|PPPOX_BOUND)){
pppox_unbind_sock(po->sk);
-
+
dev_put(po->pppoe_dev);
po->pppoe_dev = NULL;
@@ -308,7 +309,7 @@ int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb){
if (sk->state & PPPOX_BOUND) {
skb_pull(skb, sizeof(struct pppoe_hdr));
-
+
ppp_input(&po->chan, skb);
} else if( sk->state & PPPOX_RELAY ){
@@ -318,7 +319,7 @@ int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb){
!( relay_po->sk->state & PPPOX_CONNECTED ) ){
goto abort;
}
-
+
skb_pull(skb, sizeof(struct pppoe_hdr));
if( !__pppoe_xmit( relay_po->sk , skb) ){
goto abort;
@@ -369,7 +370,7 @@ static int pppoe_rcv(struct sk_buff *skb,
}else{
ret = pppoe_rcv_core(sk, skb);
}
-
+
bh_unlock_sock(sk);
sock_put(sk);
return ret;
@@ -412,13 +413,12 @@ static int pppoe_disc_rcv(struct sk_buff *skb,
po = get_item((unsigned long) ph->sid, skb->mac.ethernet->h_source);
if (!po)
- goto abort_put;
+ goto abort;
sk = po->sk;
pppox_unbind_sock(sk);
- abort_put:
sock_put(sk);
abort:
kfree_skb(skb);
@@ -466,9 +466,9 @@ static int pppoe_create(struct socket *sock)
{
int error = 0;
struct sock *sk;
-
+
MOD_INC_USE_COUNT;
-
+
sk = sk_alloc(PF_PPPOX, GFP_KERNEL, 1);
if (!sk)
return -ENOMEM;
@@ -528,7 +528,7 @@ int pppoe_release(struct socket *sock)
po = sk->protinfo.pppox;
if (po->pppoe_pa.sid)
delete_item(po->pppoe_pa.sid, po->pppoe_pa.remote);
-
+
if (po->pppoe_dev)
dev_put(po->pppoe_dev);
@@ -945,7 +945,7 @@ int pppoe_proc_info(char *buffer, char **start, off_t offset, int length)
off_t begin = 0;
int size;
int i;
-
+
len += sprintf(buffer,
"Id Address Device\n");
pos = len;
@@ -1025,9 +1025,10 @@ int __init pppoe_init(void)
int err = register_pppox_proto(PX_PROTO_OE, &pppoe_proto);
if (err == 0) {
- printk(KERN_INFO "Registered PPPoE v0.6.4\n");
+ printk(KERN_INFO "Registered PPPoE v0.6.5\n");
dev_add_pack(&pppoes_ptype);
+ dev_add_pack(&pppoed_ptype);
register_netdevice_notifier(&pppoe_notifier);
proc_net_create("pppoe", 0, pppoe_proc_info);
}
@@ -1038,6 +1039,7 @@ void __exit pppoe_exit(void)
{
unregister_pppox_proto(PX_PROTO_OE);
dev_remove_pack(&pppoes_ptype);
+ dev_remove_pack(&pppoed_ptype);
unregister_netdevice_notifier(&pppoe_notifier);
proc_net_remove("pppoe");
}
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index 3036684f9..253548599 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -1,12 +1,9 @@
-/* $Id: sunbmac.c,v 1.21 2000/10/22 16:08:38 davem Exp $
+/* $Id: sunbmac.c,v 1.23 2001/01/20 03:36:40 davem Exp $
* sunbmac.c: Driver for Sparc BigMAC 100baseT ethernet adapters.
*
* Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
*/
-static char *version =
- "sunbmac.c:v1.9 11/Sep/99 David S. Miller (davem@redhat.com)\n";
-
#include <linux/module.h>
#include <linux/kernel.h>
@@ -41,6 +38,9 @@ static char *version =
#include "sunbmac.h"
+static char version[] __initdata =
+ "sunbmac.c:v1.9 11/Sep/99 David S. Miller (davem@redhat.com)\n";
+
#undef DEBUG_PROBE
#undef DEBUG_TX
#undef DEBUG_IRQ
@@ -1051,10 +1051,10 @@ static void bigmac_set_multicast(struct net_device *dev)
static int __init bigmac_ether_init(struct net_device *dev, struct sbus_dev *qec_sdev)
{
- static int version_printed = 0;
- struct bigmac *bp = 0;
+ static int version_printed;
+ struct bigmac *bp;
u8 bsizes, bsizes_more;
- int i, res = ENOMEM;
+ int i;
/* Get a new device struct for this interface. */
dev = init_etherdev(0, sizeof(struct bigmac));
@@ -1062,6 +1062,9 @@ static int __init bigmac_ether_init(struct net_device *dev, struct sbus_dev *qec
if (version_printed++ == 0)
printk(KERN_INFO "%s", version);
+ if (!dev)
+ return -ENOMEM;
+
/* Report what we have found to the user. */
printk(KERN_INFO "%s: BigMAC 100baseT Ethernet ", dev->name);
dev->base_addr = (long) qec_sdev;
@@ -1077,9 +1080,6 @@ static int __init bigmac_ether_init(struct net_device *dev, struct sbus_dev *qec
spin_lock_init(&bp->lock);
- /* All further failures we find return this. */
- res = ENODEV;
-
/* Verify the registers we expect, are actually there. */
if ((bp->bigmac_sdev->num_registers != 3) ||
(bp->qec_sdev->num_registers != 2)) {
@@ -1205,28 +1205,25 @@ static int __init bigmac_ether_init(struct net_device *dev, struct sbus_dev *qec
fail_and_cleanup:
/* Something went wrong, undo whatever we did so far. */
- if (bp) {
- /* Free register mappings if any. */
- if (bp->gregs)
- sbus_iounmap(bp->gregs, GLOB_REG_SIZE);
- if (bp->creg)
- sbus_iounmap(bp->creg, CREG_REG_SIZE);
- if (bp->bregs)
- sbus_iounmap(bp->bregs, BMAC_REG_SIZE);
- if (bp->tregs)
- sbus_iounmap(bp->tregs, TCVR_REG_SIZE);
-
- if (bp->bmac_block)
- sbus_free_consistent(bp->bigmac_sdev,
- PAGE_SIZE,
- bp->bmac_block,
- bp->bblock_dvma);
-
- /* Free the BigMAC softc. */
- kfree(bp);
- dev->priv = 0;
- }
- return res; /* Return error code. */
+ /* Free register mappings if any. */
+ if (bp->gregs)
+ sbus_iounmap(bp->gregs, GLOB_REG_SIZE);
+ if (bp->creg)
+ sbus_iounmap(bp->creg, CREG_REG_SIZE);
+ if (bp->bregs)
+ sbus_iounmap(bp->bregs, BMAC_REG_SIZE);
+ if (bp->tregs)
+ sbus_iounmap(bp->tregs, TCVR_REG_SIZE);
+
+ if (bp->bmac_block)
+ sbus_free_consistent(bp->bigmac_sdev,
+ PAGE_SIZE,
+ bp->bmac_block,
+ bp->bblock_dvma);
+
+ unregister_netdev(dev);
+ kfree(dev);
+ return -ENODEV;
}
/* QEC can be the parent of either QuadEthernet or
diff --git a/drivers/net/tulip/ChangeLog b/drivers/net/tulip/ChangeLog
index dfac94349..bb5b70f01 100644
--- a/drivers/net/tulip/ChangeLog
+++ b/drivers/net/tulip/ChangeLog
@@ -1,7 +1,37 @@
-2000-12-17 Alan Cox <alan@redhat.com>
+2001-01-16 Jeff Garzik <jgarzik@mandrakesoft.com>
- * merge support for the Davicom's quirks into the main tulip. Patch
- by Tobias Ringstrom
+ * tulip_core.c: static vars no longer explicitly
+ initialized to zero.
+ * eeprom.c (tulip_read_eeprom): Make sure to delay between
+ EE_ENB and EE_ENB|EE_SHIFT_CLK. Merged from becker tulip.c.
+
+2001-01-05 Peter De Schrijver <p2@mind.be>
+
+ * eeprom.c (tulip_parse_eeprom): Interpret a bit more of 21142
+ extended format type 3 info blocks in a tulip SROM.
+
+2001-01-03 Matti Aarnio <matti.aarnio@zmailer.org>
+
+ * media.c (tulip_select_media): Support media types 5 and 6
+
+2001-??-?? ??
+
+ * tulip_core.c: Add comment about LanMedia needing
+ a different driver.
+ Enable workarounds for early PCI chipsets.
+ Add IA64 csr0 support, update HPPA csr0 support.
+
+2000-12-17 Alan Cox <alan@redhat.com>
+
+ * eeprom.c, timer.c, tulip.h, tulip_core.c: Merge support
+ for the Davicom's quirks into the main tulip.
+ Patch by Tobias Ringstrom
+
+2000-11-08 Jim Studt <jim@federated.com>
+
+ * eeprom.c (tulip_parse_eeprom): Check array bounds for
+ medianame[] and block_name[] arrays to avoid oops due
+ to bad values returned from hardware.
2000-11-02 Jeff Garzik <jgarzik@mandrakesoft.com>
diff --git a/drivers/net/tulip/eeprom.c b/drivers/net/tulip/eeprom.c
index 49e8bf42e..f42baefc2 100644
--- a/drivers/net/tulip/eeprom.c
+++ b/drivers/net/tulip/eeprom.c
@@ -207,8 +207,13 @@ subsequent_board:
p += (p[0] & 0x3f) + 1;
continue;
} else if (p[1] & 1) {
+ int gpr_len, reset_len;
+
mtable->has_mii = 1;
leaf->media = 11;
+ gpr_len=p[3]*2;
+ reset_len=p[4+gpr_len]*2;
+ new_advertise |= get_u16(&p[7+gpr_len+reset_len]);
} else {
mtable->has_nonmii = 1;
leaf->media = p[2] & 0x0f;
@@ -247,9 +252,9 @@ subsequent_board:
}
printk(KERN_INFO "%s: Index #%d - Media %s (#%d) described "
"by a %s (%d) block.\n",
- dev->name, i, medianame[leaf->media], leaf->media,
- leaf->type >= ARRAY_SIZE(block_name) ? "UNKNOWN" :
- block_name[leaf->type], leaf->type);
+ dev->name, i, medianame[leaf->media & 15], leaf->media,
+ leaf->type < ARRAY_SIZE(block_name) ? block_name[leaf->type] : "<unknown>",
+ leaf->type);
}
if (new_advertise)
tp->to_advertise = new_advertise;
@@ -278,6 +283,7 @@ int __devinit tulip_read_eeprom(long ioaddr, int location, int addr_len)
retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
}
outl(EE_ENB, ee_addr);
+ eeprom_delay();
for (i = 16; i > 0; i--) {
outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
diff --git a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c
index b8203f33a..bc8e7bbbc 100644
--- a/drivers/net/tulip/media.c
+++ b/drivers/net/tulip/media.c
@@ -148,7 +148,7 @@ void tulip_select_media(struct net_device *dev, int startup)
long ioaddr = dev->base_addr;
struct tulip_private *tp = (struct tulip_private *)dev->priv;
struct mediatable *mtable = tp->mtable;
- u32 new_csr6;
+ u32 new_csr6=0;
int i;
if (mtable) {
@@ -265,7 +265,9 @@ void tulip_select_media(struct net_device *dev, int startup)
}
case 5: case 6: {
u16 setup[5];
- u32 csr13val, csr14val, csr15dir, csr15val;
+
+ new_csr6 = 0; /* FIXME */
+
for (i = 0; i < 5; i++)
setup[i] = get_u16(&p[i*2 + 1]);
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 765cd6c7c..0517b90af 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -28,7 +28,7 @@
#include <asm/unaligned.h>
static char version[] __devinitdata =
- "Linux Tulip driver version 0.9.13 (January 2, 2001)\n";
+ "Linux Tulip driver version 0.9.13a (January 20, 2001)\n";
/* A few user-configurable values. */
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index eaba0cd34..3f23aec1c 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -45,25 +45,10 @@
#include <linux/lapb.h>
#include <linux/init.h>
-static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
-
-static int lapbeth_rcv(struct sk_buff *, struct net_device *, struct packet_type *);
-static int lapbeth_device_event(struct notifier_block *, unsigned long, void *);
-
-static struct packet_type lapbeth_packet_type = {
- 0, /* ntohs(ETH_P_DEC),*/
- 0, /* copy */
- lapbeth_rcv,
- NULL,
- NULL,
-};
-
-static struct notifier_block lapbeth_dev_notifier = {
- lapbeth_device_event,
- 0
-};
-
+static char bcast_addr[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
+/* If this number is made larger, check that the temporary string buffer
+ * in lapbeth_new_device is large enough to store the probe device name.*/
#define MAXLAPBDEV 100
static struct lapbethdev {
@@ -72,29 +57,14 @@ static struct lapbethdev {
struct net_device *ethdev; /* link to ethernet device */
struct net_device axdev; /* lapbeth device (lapb#) */
struct net_device_stats stats; /* some statistics */
-} *lapbeth_devices = NULL;
-
+} *lapbeth_devices /* = NULL initially */;
/* ------------------------------------------------------------------------ */
-
-/*
- * Get the ethernet device for a LAPB device
- */
-#if 0
-static __inline__ struct net_device *lapbeth_get_ether_dev(struct net_device *dev)
-{
- struct lapbethdev *lapbeth;
-
- lapbeth = (struct lapbethdev *)dev->priv;
-
- return (lapbeth != NULL) ? lapbeth->ethdev : NULL;
-}
-#endif
/*
* Get the LAPB device for the ethernet device
*/
-static __inline__ struct net_device *lapbeth_get_x25_dev(struct net_device *dev)
+static inline struct net_device *lapbeth_get_x25_dev(struct net_device *dev)
{
struct lapbethdev *lapbeth;
@@ -105,7 +75,7 @@ static __inline__ struct net_device *lapbeth_get_x25_dev(struct net_device *dev)
return NULL;
}
-static __inline__ int dev_is_ethdev(struct net_device *dev)
+static inline int dev_is_ethdev(struct net_device *dev)
{
return (
dev->type == ARPHRD_ETHER
@@ -122,7 +92,7 @@ static int lapbeth_check_devices(struct net_device *dev)
struct lapbethdev *lapbeth, *lapbeth_prev;
int result = 0;
unsigned long flags;
-
+
save_flags(flags);
cli();
@@ -134,7 +104,7 @@ static int lapbeth_check_devices(struct net_device *dev)
lapbeth_prev->next = lapbeth->next;
else
lapbeth_devices = lapbeth->next;
-
+
if (&lapbeth->axdev == dev)
result = 1;
@@ -145,16 +115,14 @@ static int lapbeth_check_devices(struct net_device *dev)
lapbeth_prev = lapbeth;
}
-
+
restore_flags(flags);
-
+
return result;
}
-
/* ------------------------------------------------------------------------ */
-
/*
* Receive a LAPB frame via an ethernet interface.
*/
@@ -164,7 +132,7 @@ static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
struct lapbethdev *lapbeth;
skb->sk = NULL; /* Initially we don't know who it's for */
-
+
dev = lapbeth_get_x25_dev(dev);
if (dev == NULL || !netif_running(dev)) {
@@ -172,7 +140,7 @@ static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
return 0;
}
- lapbeth = (struct lapbethdev *)dev->priv;
+ lapbeth = (struct lapbethdev *) dev->priv;
lapbeth->stats.rx_packets++;
@@ -191,7 +159,7 @@ static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
static int lapbeth_data_indication(void *token, struct sk_buff *skb)
{
- struct lapbethdev *lapbeth = (struct lapbethdev *)token;
+ struct lapbethdev *lapbeth = (struct lapbethdev *) token;
unsigned char *ptr;
ptr = skb_push(skb, 1);
@@ -206,14 +174,12 @@ static int lapbeth_data_indication(void *token, struct sk_buff *skb)
}
/*
- * Send a LAPB frame via an ethernet interface
+ * Send a LAPB frame via an ethernet interface
*/
static int lapbeth_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct lapbethdev *lapbeth;
+ struct lapbethdev *lapbeth = (struct lapbethdev *) dev->priv;
int err;
-
- lapbeth = (struct lapbethdev *)dev->priv;
/*
* Just to be *really* sure not to send anything if the interface
@@ -253,10 +219,10 @@ static int lapbeth_xmit(struct sk_buff *skb, struct net_device *dev)
return 0;
}
-
+
static void lapbeth_data_transmit(void *token, struct sk_buff *skb)
{
- struct lapbethdev *lapbeth = (struct lapbethdev *)token;
+ struct lapbethdev *lapbeth = (struct lapbethdev *) token;
unsigned char *ptr;
struct net_device *dev;
int size;
@@ -281,7 +247,7 @@ static void lapbeth_data_transmit(void *token, struct sk_buff *skb)
static void lapbeth_connected(void *token, int reason)
{
- struct lapbethdev *lapbeth = (struct lapbethdev *)token;
+ struct lapbethdev *lapbeth = (struct lapbethdev *) token;
struct sk_buff *skb;
unsigned char *ptr;
@@ -303,7 +269,7 @@ static void lapbeth_connected(void *token, int reason)
static void lapbeth_disconnected(void *token, int reason)
{
- struct lapbethdev *lapbeth = (struct lapbethdev *)token;
+ struct lapbethdev *lapbeth = (struct lapbethdev *) token;
struct sk_buff *skb;
unsigned char *ptr;
@@ -328,10 +294,7 @@ static void lapbeth_disconnected(void *token, int reason)
*/
static struct net_device_stats *lapbeth_get_stats(struct net_device *dev)
{
- struct lapbethdev *lapbeth;
-
- lapbeth = (struct lapbethdev *)dev->priv;
-
+ struct lapbethdev *lapbeth = (struct lapbethdev *) dev->priv;
return &lapbeth->stats;
}
@@ -340,18 +303,11 @@ static struct net_device_stats *lapbeth_get_stats(struct net_device *dev)
*/
static int lapbeth_set_mac_address(struct net_device *dev, void *addr)
{
- struct sockaddr *sa = (struct sockaddr *)addr;
-
+ struct sockaddr *sa = (struct sockaddr *) addr;
memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
-
return 0;
}
-static int lapbeth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
- return -EINVAL;
-}
-
/*
* open/close a device
*/
@@ -363,8 +319,8 @@ static int lapbeth_open(struct net_device *dev)
if (lapbeth_check_devices(dev))
return -ENODEV; /* oops, it's gone */
-
- lapbeth = (struct lapbethdev *)dev->priv;
+
+ lapbeth = (struct lapbethdev *) dev->priv;
lapbeth_callbacks.connect_confirmation = lapbeth_connected;
lapbeth_callbacks.connect_indication = lapbeth_connected;
@@ -378,31 +334,20 @@ static int lapbeth_open(struct net_device *dev)
return -ENODEV;
}
- MOD_INC_USE_COUNT;
netif_start_queue(dev);
-
return 0;
}
static int lapbeth_close(struct net_device *dev)
{
- struct lapbethdev *lapbeth;
+ struct lapbethdev *lapbeth = (struct lapbethdev *) dev->priv;
int err;
netif_stop_queue(dev);
-
- lapbeth = (struct lapbethdev *)dev->priv;
if ((err = lapb_unregister(lapbeth)) != LAPB_OK)
printk(KERN_ERR "lapbeth: lapb_unregister error - %d\n", err);
- MOD_DEC_USE_COUNT;
-
- return 0;
-}
-
-static int lapbeth_dev_init(struct net_device *dev)
-{
return 0;
}
@@ -414,14 +359,14 @@ static int lapbeth_dev_init(struct net_device *dev)
static int lapbeth_new_device(struct net_device *dev)
{
int k;
- unsigned char *buf;
+ unsigned char buf[14];
struct lapbethdev *lapbeth, *lapbeth2;
-
+
if ((lapbeth = kmalloc(sizeof(struct lapbethdev), GFP_KERNEL)) == NULL)
return -ENOMEM;
-
+
memset(lapbeth, 0, sizeof(struct lapbethdev));
-
+
dev_hold(dev);
lapbeth->ethdev = dev;
@@ -429,7 +374,7 @@ static int lapbeth_new_device(struct net_device *dev)
strncpy(lapbeth->ethname, dev->name, sizeof(lapbeth->ethname)-1);
dev = &lapbeth->axdev;
- buf = kmalloc(14, GFP_KERNEL);
+ SET_MODULE_OWNER(dev);
for (k = 0; k < MAXLAPBDEV; k++) {
struct net_device *odev;
@@ -445,10 +390,9 @@ static int lapbeth_new_device(struct net_device *dev)
kfree(lapbeth);
return -ENODEV;
}
-
+
dev->priv = (void *)lapbeth; /* pointer back */
strcpy(dev->name, buf);
- dev->init = lapbeth_dev_init;
if (register_netdev(dev) != 0) {
dev_put(dev);
@@ -463,10 +407,6 @@ static int lapbeth_new_device(struct net_device *dev)
dev->stop = lapbeth_close;
dev->set_mac_address = lapbeth_set_mac_address;
dev->get_stats = lapbeth_get_stats;
- dev->do_ioctl = lapbeth_ioctl;
-
- dev->flags = 0;
-
dev->type = ARPHRD_X25;
dev->hard_header_len = 3;
dev->mtu = 1000;
@@ -480,20 +420,19 @@ static int lapbeth_new_device(struct net_device *dev)
for (lapbeth2 = lapbeth_devices; lapbeth2->next != NULL; lapbeth2 = lapbeth2->next);
lapbeth2->next = lapbeth;
}
-
+
sti();
return 0;
}
-
/*
* Handle device status changes.
*/
-static int lapbeth_device_event(struct notifier_block *this,unsigned long event, void *ptr)
+static int lapbeth_device_event(struct notifier_block *this, unsigned long event, void *ptr)
{
- struct net_device *dev = (struct net_device *)ptr;
-
+ struct net_device *dev = (struct net_device *) ptr;
+
if (!dev_is_ethdev(dev))
return NOTIFY_DONE;
@@ -518,23 +457,28 @@ static int lapbeth_device_event(struct notifier_block *this,unsigned long event,
return NOTIFY_DONE;
}
-
/* ------------------------------------------------------------------------ */
-/*
- * Initialize driver. To be called from af_ax25 if not compiled as a
- * module
- */
-int lapbeth_init(void)
+static struct packet_type lapbeth_packet_type = {
+ type: __constant_htons(ETH_P_DEC),
+ func: lapbeth_rcv,
+};
+
+static struct notifier_block lapbeth_dev_notifier = {
+ notifier_call: lapbeth_device_event,
+};
+
+static const char banner[] __initdata = KERN_INFO "LAPB Ethernet driver version 0.01\n";
+
+static int __init lapbeth_init_driver(void)
{
struct net_device *dev;
- lapbeth_packet_type.type = htons(ETH_P_DEC);
dev_add_pack(&lapbeth_packet_type);
register_netdevice_notifier(&lapbeth_dev_notifier);
- printk(KERN_INFO "LAPB Ethernet driver version 0.01\n");
+ printk(banner);
read_lock_bh(&dev_base_lock);
for (dev = dev_base; dev != NULL; dev = dev->next) {
@@ -548,19 +492,9 @@ int lapbeth_init(void)
return 0;
}
+module_init(lapbeth_init_driver);
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
-MODULE_DESCRIPTION("The unofficial LAPB over Ethernet driver");
-
-int init_module(void)
-{
- return lapbeth_init();
-}
-
-void cleanup_module(void)
+static void __exit lapbeth_cleanup_driver(void)
{
struct lapbethdev *lapbeth;
@@ -571,4 +505,10 @@ void cleanup_module(void)
for (lapbeth = lapbeth_devices; lapbeth != NULL; lapbeth = lapbeth->next)
unregister_netdev(&lapbeth->axdev);
}
-#endif
+module_exit(lapbeth_cleanup_driver);
+
+EXPORT_NO_SYMBOLS;
+
+MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
+MODULE_DESCRIPTION("The unofficial LAPB over Ethernet driver");
+
diff --git a/drivers/net/wan/lmc/lmc.h b/drivers/net/wan/lmc/lmc.h
index 91b9e8f00..882e58c1b 100644
--- a/drivers/net/wan/lmc/lmc.h
+++ b/drivers/net/wan/lmc/lmc.h
@@ -29,4 +29,5 @@ extern lmc_media_t lmc_hssi_media;
static void lmcEventLog( u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3 );
#endif
-#endif \ No newline at end of file
+#endif
+
diff --git a/drivers/net/wan/lmc/lmc_media.h b/drivers/net/wan/lmc/lmc_media.h
index 7cc6c1650..ddcc00403 100644
--- a/drivers/net/wan/lmc/lmc_media.h
+++ b/drivers/net/wan/lmc/lmc_media.h
@@ -61,4 +61,5 @@ lmc_media_t lmc_t1_media = {
};
-#endif \ No newline at end of file
+#endif
+
diff --git a/drivers/net/wan/lmc/lmc_prot.h b/drivers/net/wan/lmc/lmc_prot.h
index 859ef0f00..f3b1df9e2 100644
--- a/drivers/net/wan/lmc/lmc_prot.h
+++ b/drivers/net/wan/lmc/lmc_prot.h
@@ -11,4 +11,5 @@ void lmc_proto_close(lmc_softc_t *sc const)
unsigned short lmc_proto_type(lmc_softc_t *sc const, struct skbuff *skb)
-#endif \ No newline at end of file
+#endif
+
diff --git a/drivers/net/wan/lmc/lmc_proto.h b/drivers/net/wan/lmc/lmc_proto.h
index 6136dfad7..080a55773 100644
--- a/drivers/net/wan/lmc/lmc_proto.h
+++ b/drivers/net/wan/lmc/lmc_proto.h
@@ -12,4 +12,5 @@ unsigned short lmc_proto_type(lmc_softc_t *sc, struct sk_buff *skb);
void lmc_proto_netif(lmc_softc_t *sc, struct sk_buff *skb);
int lmc_skb_rawpackets(char *buf, char **start, off_t offset, int len, int unused);
-#endif \ No newline at end of file
+#endif
+
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index ef489b1a6..1eb66b44e 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -744,7 +744,7 @@ static void sdla_receive(struct net_device *dev)
struct buf_entry *pbuf;
unsigned long flags;
- int i, received, success, addr, buf_base, buf_top;
+ int i=0, received, success, addr, buf_base, buf_top;
short dlci, len, len2, split;
flp = dev->priv;
diff --git a/drivers/pnp/isapnp_proc.c b/drivers/pnp/isapnp_proc.c
index ee4c2aee3..9f3cc0fc3 100644
--- a/drivers/pnp/isapnp_proc.c
+++ b/drivers/pnp/isapnp_proc.c
@@ -783,7 +783,10 @@ static int isapnp_set_card(char *line)
unsigned int id;
char index[16], value[32];
- isapnp_info_card = NULL;
+ if (isapnp_info_card) {
+ isapnp_cfg_end();
+ isapnp_info_card = NULL;
+ }
line = isapnp_get_str(index, line, sizeof(index));
isapnp_get_str(value, line, sizeof(value));
idx = idx1 = simple_strtoul(index, NULL, 0);
@@ -853,10 +856,7 @@ static int isapnp_set_device(char *line)
static int isapnp_autoconfigure(void)
{
- if (isapnp_info_device == NULL) {
- printk("isapnp: device is not set\n");
- return 0;
- }
+ isapnp_cfg_end();
if (isapnp_info_device->active)
isapnp_info_device->deactivate(isapnp_info_device);
if (isapnp_info_device->prepare(isapnp_info_device) < 0) {
@@ -867,6 +867,13 @@ static int isapnp_autoconfigure(void)
printk("isapnp: cannot activate device");
return 0;
}
+ if (isapnp_cfg_begin(isapnp_info_card->number, -1)<0) {
+ printk("isapnp: configuration start sequence for card %d failed\n", isapnp_info_card->number);
+ isapnp_info_card = NULL;
+ isapnp_info_device = NULL;
+ return 1;
+ }
+ isapnp_device(isapnp_info_device->devfn);
return 0;
}
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 55e27c7d8..a48213aea 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -952,7 +952,6 @@ do_dasd_request (request_queue_t *queue)
go = 1;
while (go && !list_empty(&queue->queue_head)) {
req = blkdev_entry_next_request(&queue->queue_head);
- req = blkdev_entry_next_request(&queue->queue_head);
di = DEVICE_NR (req->rq_dev);
dasd_debug ((unsigned long) req); /* req */
dasd_debug (0xc4d90000 + /* DR## */
diff --git a/drivers/sbus/audio/Config.in b/drivers/sbus/audio/Config.in
index a9419f78c..40a431f81 100644
--- a/drivers/sbus/audio/Config.in
+++ b/drivers/sbus/audio/Config.in
@@ -8,9 +8,11 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
comment 'Linux/SPARC audio subsystem (EXPERIMENTAL)'
tristate 'Audio support (EXPERIMENTAL)' CONFIG_SPARCAUDIO
- dep_tristate ' AMD7930 Lowlevel Driver' CONFIG_SPARCAUDIO_AMD7930 $CONFIG_SPARCAUDIO
+ if [ "$CONFIG_SPARC64" != "y" ]; then
+ dep_tristate ' AMD7930 Lowlevel Driver' CONFIG_SPARCAUDIO_AMD7930 $CONFIG_SPARCAUDIO
+ dep_tristate ' DBRI Lowlevel Driver' CONFIG_SPARCAUDIO_DBRI $CONFIG_SPARCAUDIO
+ fi
dep_tristate ' CS4231 Lowlevel Driver' CONFIG_SPARCAUDIO_CS4231 $CONFIG_SPARCAUDIO
- dep_tristate ' DBRI Lowlevel Driver' CONFIG_SPARCAUDIO_DBRI $CONFIG_SPARCAUDIO
dep_tristate ' Dummy Lowlevel Driver' CONFIG_SPARCAUDIO_DUMMY $CONFIG_SPARCAUDIO
endmenu
fi
diff --git a/drivers/sbus/audio/amd7930.c b/drivers/sbus/audio/amd7930.c
index f3f593bce..1ddfb5017 100644
--- a/drivers/sbus/audio/amd7930.c
+++ b/drivers/sbus/audio/amd7930.c
@@ -1,4 +1,4 @@
-/* $Id: amd7930.c,v 1.24 2000/01/22 05:10:27 anton Exp $
+/* $Id: amd7930.c,v 1.25 2001/01/08 04:19:16 davem Exp $
* drivers/sbus/audio/amd7930.c
*
* Copyright (C) 1996,1997 Thomas K. Dyas (tdyas@eden.rutgers.edu)
@@ -107,7 +107,7 @@ static __u8 mulaw2bilinear(__u8 data);
static __u8 linear2mulaw(__u16 data);
static __u16 mulaw2linear(__u8 data);
-#if defined (AMD79C30_ISDN) || defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff
+#if defined (AMD79C30_ISDN) && defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff
#include "../../isdn/hisax/hisax.h"
#include "../../isdn/hisax/isdnl1.h"
#include "../../isdn/hisax/foreign.h"
@@ -1131,7 +1131,7 @@ static int amd7930_ioctl(struct inode * inode, struct file * file,
*
*/
-#if defined (AMD79C30_ISDN) || defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff
+#if defined (AMD79C30_ISDN) && defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff
static int amd7930_get_irqnum(int dev)
{
struct amd7930_info *info;
diff --git a/drivers/sbus/audio/dbri.c b/drivers/sbus/audio/dbri.c
index ad0d879b1..665bb4b31 100644
--- a/drivers/sbus/audio/dbri.c
+++ b/drivers/sbus/audio/dbri.c
@@ -1,4 +1,4 @@
-/* $Id: dbri.c,v 1.22 2000/10/27 07:01:38 uzi Exp $
+/* $Id: dbri.c,v 1.23 2001/01/08 04:19:16 davem Exp $
* drivers/sbus/audio/dbri.c
*
* Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de)
@@ -61,7 +61,7 @@
#include <asm/audioio.h>
#include "dbri.h"
-#if defined(DBRI_ISDN) || defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff
+#if defined(DBRI_ISDN) && defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff
#include "../../isdn/hisax/hisax.h"
#include "../../isdn/hisax/isdnl1.h"
#include "../../isdn/hisax/foreign.h"
@@ -2227,7 +2227,7 @@ void dbri_brecv(int dev, unsigned int chan,
recv_on_pipe(dbri, 8+chan, buffer, size, callback, callback_arg);
}
-#if defined(DBRI_ISDN) || defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff
+#if defined(DBRI_ISDN) && defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff
struct foreign_interface dbri_foreign_interface = {
dbri_get_irqnum,
dbri_get_liu_state,
diff --git a/drivers/sbus/char/Makefile b/drivers/sbus/char/Makefile
index b3a736db5..437f2d28c 100644
--- a/drivers/sbus/char/Makefile
+++ b/drivers/sbus/char/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_PCI) += su.o pcikbd.o
obj-$(CONFIG_SAB82532) += sab82532.o
obj-$(CONFIG_ENVCTRL) += envctrl.o
obj-$(CONFIG_DISPLAY7SEG) += display7seg.o
+obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwatchdog.o
obj-$(CONFIG_OBP_FLASH) += flash.o
obj-$(CONFIG_SUN_OPENPROMIO) += openprom.o
obj-$(CONFIG_SUN_MOSTEK_RTC) += rtc.o
diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c
index c96a141a5..2be051503 100644
--- a/drivers/sbus/char/bpp.c
+++ b/drivers/sbus/char/bpp.c
@@ -17,6 +17,7 @@
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
#include <linux/timer.h>
#include <linux/ioport.h>
#include <linux/major.h>
@@ -432,6 +433,7 @@ static int terminate(unsigned minor)
return 0;
}
+static spinlock_t bpp_open_lock = SPIN_LOCK_UNLOCKED;
/*
* Allow only one process to open the device at a time.
@@ -439,13 +441,25 @@ static int terminate(unsigned minor)
static int bpp_open(struct inode *inode, struct file *f)
{
unsigned minor = MINOR(inode->i_rdev);
- if (minor >= BPP_NO) return -ENODEV;
- if (! instances[minor].present) return -ENODEV;
- if (instances[minor].opened) return -EBUSY;
-
- instances[minor].opened = 1;
+ int ret;
+
+ spin_lock(&bpp_open_lock);
+ ret = 0;
+ if (minor >= BPP_NO) {
+ ret = -ENODEV;
+ } else {
+ if (! instances[minor].present) {
+ ret = -ENODEV;
+ } else {
+ if (instances[minor].opened)
+ ret = -EBUSY;
+ else
+ instances[minor].opened = 1;
+ }
+ }
+ spin_unlock(&bpp_open_lock);
- return 0;
+ return ret;
}
/*
@@ -458,12 +472,14 @@ static int bpp_release(struct inode *inode, struct file *f)
{
unsigned minor = MINOR(inode->i_rdev);
- lock_kernel();
+ spin_lock(&bpp_open_lock);
instances[minor].opened = 0;
if (instances[minor].mode != COMPATIBILITY)
- terminate(minor);
- unlock_kernel();
+ terminate(minor);
+
+ spin_unlock(&bpp_open_lock);
+
return 0;
}
diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c
new file mode 100644
index 000000000..c319b4d33
--- /dev/null
+++ b/drivers/sbus/char/cpwatchdog.c
@@ -0,0 +1,838 @@
+/* cpwatchdog.c - driver implementation for hardware watchdog
+ * timers found on Sun Microsystems CP1400 and CP1500 boards.
+ *
+ * This device supports both the generic Linux watchdog
+ * interface and Solaris-compatible ioctls as best it is
+ * able.
+ *
+ * NOTE: CP1400 systems appear to have a defective intr_mask
+ * register on the PLD, preventing the disabling of
+ * timer interrupts. We use a timer to periodically
+ * reset 'stopped' watchdogs on affected platforms.
+ *
+ * TODO: DevFS support (/dev/watchdogs/0 ... /dev/watchdogs/2)
+ *
+ * Copyright (c) 2000 Eric Brower (ebrower@usa.net)
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/major.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timer.h>
+#include <asm/irq.h>
+#include <asm/ebus.h>
+#include <asm/oplib.h>
+#include <asm/uaccess.h>
+
+#include <asm/watchdog.h>
+
+#define WD_OBPNAME "watchdog"
+#define WD_BADMODEL "SUNW,501-5336"
+#define WD_BTIMEOUT (jiffies + (HZ * 1000))
+#define WD_BLIMIT 0xFFFF
+
+#define WD0_DEVNAME "watchdog0"
+#define WD1_DEVNAME "watchdog1"
+#define WD2_DEVNAME "watchdog2"
+
+#define WD0_MINOR 212
+#define WD1_MINOR 213
+#define WD2_MINOR 214
+
+
+/* Internal driver definitions
+ */
+#define WD0_ID 0 /* Watchdog0 */
+#define WD1_ID 1 /* Watchdog1 */
+#define WD2_ID 2 /* Watchdog2 */
+#define WD_NUMDEVS 3 /* Device contains 3 timers */
+
+#define WD_INTR_OFF 0 /* Interrupt disable value */
+#define WD_INTR_ON 1 /* Interrupt enable value */
+
+#define WD_STAT_INIT 0x01 /* Watchdog timer is initialized */
+#define WD_STAT_BSTOP 0x02 /* Watchdog timer is brokenstopped */
+#define WD_STAT_SVCD 0x04 /* Watchdog interrupt occurred */
+
+/* Register value definitions
+ */
+#define WD0_INTR_MASK 0x01 /* Watchdog device interrupt masks */
+#define WD1_INTR_MASK 0x02
+#define WD2_INTR_MASK 0x04
+
+#define WD_S_RUNNING 0x01 /* Watchdog device status running */
+#define WD_S_EXPIRED 0x02 /* Watchdog device status expired */
+
+/* Sun uses Altera PLD EPF8820ATC144-4
+ * providing three hardware watchdogs:
+ *
+ * 1) RIC - sends an interrupt when triggered
+ * 2) XIR - asserts XIR_B_RESET when triggered, resets CPU
+ * 3) POR - asserts POR_B_RESET when triggered, resets CPU, backplane, board
+ *
+ *** Timer register block definition (struct wd_timer_regblk)
+ *
+ * dcntr and limit registers (halfword access):
+ * -------------------
+ * | 15 | ...| 1 | 0 |
+ * -------------------
+ * |- counter val -|
+ * -------------------
+ * dcntr - Current 16-bit downcounter value.
+ * When downcounter reaches '0' watchdog expires.
+ * Reading this register resets downcounter with 'limit' value.
+ * limit - 16-bit countdown value in 1/10th second increments.
+ * Writing this register begins countdown with input value.
+ * Reading from this register does not affect counter.
+ * NOTES: After watchdog reset, dcntr and limit contain '1'
+ *
+ * status register (byte access):
+ * ---------------------------
+ * | 7 | ... | 2 | 1 | 0 |
+ * --------------+------------
+ * |- UNUSED -| EXP | RUN |
+ * ---------------------------
+ * status- Bit 0 - Watchdog is running
+ * Bit 1 - Watchdog has expired
+ *
+ *** PLD register block definition (struct wd_pld_regblk)
+ *
+ * intr_mask register (byte access):
+ * ---------------------------------
+ * | 7 | ... | 3 | 2 | 1 | 0 |
+ * +-------------+------------------
+ * |- UNUSED -| WD3 | WD2 | WD1 |
+ * ---------------------------------
+ * WD3 - 1 == Interrupt disabled for watchdog 3
+ * WD2 - 1 == Interrupt disabled for watchdog 2
+ * WD1 - 1 == Interrupt disabled for watchdog 1
+ *
+ * pld_status register (byte access):
+ * UNKNOWN, MAGICAL MYSTERY REGISTER
+ *
+ */
+struct wd_timer_regblk {
+ volatile __u16 dcntr; /* down counter - hw */
+ volatile __u16 dcntr_pad;
+ volatile __u16 limit; /* limit register - hw */
+ volatile __u16 limit_pad;
+ volatile __u8 status; /* status register - b */
+ volatile __u8 status_pad;
+ volatile __u16 status_pad2;
+ volatile __u32 pad32; /* yet more padding */
+};
+
+struct wd_pld_regblk {
+ volatile __u8 intr_mask; /* interrupt mask - b */
+ volatile __u8 intr_mask_pad;
+ volatile __u16 intr_mask_pad2;
+ volatile __u8 status; /* device status - b */
+ volatile __u8 status_pad;
+ volatile __u16 status_pad2;
+};
+
+struct wd_regblk {
+ volatile struct wd_timer_regblk wd0_regs;
+ volatile struct wd_timer_regblk wd1_regs;
+ volatile struct wd_timer_regblk wd2_regs;
+ volatile struct wd_pld_regblk pld_regs;
+};
+
+/* Individual timer structure
+ */
+struct wd_timer {
+ __u16 timeout;
+ __u8 intr_mask;
+ unsigned char runstatus;
+ volatile struct wd_timer_regblk* regs;
+};
+
+/* Device structure
+ */
+struct wd_device {
+ int irq;
+ spinlock_t lock;
+ unsigned char isbaddoggie; /* defective PLD */
+ unsigned char opt_enable;
+ unsigned char opt_reboot;
+ unsigned short opt_timeout;
+ unsigned char initialized;
+ struct wd_timer watchdog[WD_NUMDEVS];
+ volatile struct wd_regblk* regs;
+};
+
+static struct wd_device wd_dev = {
+ 0, SPIN_LOCK_UNLOCKED, 0, 0, 0, 0,
+};
+
+struct timer_list wd_timer;
+
+static int wd0_timeout = 0;
+static int wd1_timeout = 0;
+static int wd2_timeout = 0;
+
+#ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
+MODULE_PARM (wd0_timeout, "i");
+MODULE_PARM_DESC(wd0_timeout, "Default watchdog0 timeout in 1/10secs");
+MODULE_PARM (wd1_timeout, "i");
+MODULE_PARM_DESC(wd1_timeout, "Default watchdog1 timeout in 1/10secs");
+MODULE_PARM (wd2_timeout, "i");
+MODULE_PARM_DESC(wd2_timeout, "Default watchdog2 timeout in 1/10secs");
+
+MODULE_AUTHOR
+ ("Eric Brower <ebrower@usa.net>");
+MODULE_DESCRIPTION
+ ("Hardware watchdog driver for Sun Microsystems CP1400/1500");
+MODULE_SUPPORTED_DEVICE
+ ("watchdog");
+#endif /* ifdef MODULE */
+
+/* Forward declarations of internal methods
+ */
+void wd_dumpregs(void);
+void wd_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+void wd_toggleintr(struct wd_timer* pTimer, int enable);
+void wd_pingtimer(struct wd_timer* pTimer);
+void wd_starttimer(struct wd_timer* pTimer);
+void wd_resetbrokentimer(struct wd_timer* pTimer);
+void wd_stoptimer(struct wd_timer* pTimer);
+void wd_brokentimer(unsigned long data);
+int wd_getstatus(struct wd_timer* pTimer);
+
+/* PLD expects words to be written in LSB format,
+ * so we must flip all words prior to writing them to regs
+ */
+inline unsigned short flip_word(unsigned short word)
+{
+ return ((word & 0xff) << 8) | ((word >> 8) & 0xff);
+}
+
+#define wd_writew(val, addr) (writew(flip_word(val), addr))
+#define wd_readw(addr) (flip_word(readw(addr)))
+#define wd_writeb(val, addr) (writeb(val, addr))
+#define wd_readb(addr) (readb(addr))
+
+
+/* CP1400s seem to have broken PLD implementations--
+ * the interrupt_mask register cannot be written, so
+ * no timer interrupts can be masked within the PLD.
+ */
+static inline int wd_isbroken(void)
+{
+ /* we could test this by read/write/read/restore
+ * on the interrupt mask register only if OBP
+ * 'watchdog-enable?' == FALSE, but it seems
+ * ubiquitous on CP1400s
+ */
+ char val[32];
+ prom_getproperty(prom_root_node, "model", val, sizeof(val));
+ return((!strcmp(val, WD_BADMODEL)) ? 1 : 0);
+}
+
+/* Retrieve watchdog-enable? option from OBP
+ * Returns 0 if false, 1 if true
+ */
+static inline int wd_opt_enable(void)
+{
+ int opt_node;
+
+ opt_node = prom_getchild(prom_root_node);
+ opt_node = prom_searchsiblings(opt_node, "options");
+ return((-1 == prom_getint(opt_node, "watchdog-enable?")) ? 0 : 1);
+}
+
+/* Retrieve watchdog-reboot? option from OBP
+ * Returns 0 if false, 1 if true
+ */
+static inline int wd_opt_reboot(void)
+{
+ int opt_node;
+
+ opt_node = prom_getchild(prom_root_node);
+ opt_node = prom_searchsiblings(opt_node, "options");
+ return((-1 == prom_getint(opt_node, "watchdog-reboot?")) ? 0 : 1);
+}
+
+/* Retrieve watchdog-timeout option from OBP
+ * Returns OBP value, or 0 if not located
+ */
+static inline int wd_opt_timeout(void)
+{
+ int opt_node;
+ char value[32];
+ char *p = value;
+
+ opt_node = prom_getchild(prom_root_node);
+ opt_node = prom_searchsiblings(opt_node, "options");
+ opt_node = prom_getproperty(opt_node,
+ "watchdog-timeout",
+ value,
+ sizeof(value));
+ if(-1 != opt_node) {
+ /* atoi implementation */
+ for(opt_node = 0; /* nop */; p++) {
+ if(*p >= '0' && *p <= '9') {
+ opt_node = (10*opt_node)+(*p-'0');
+ }
+ else {
+ break;
+ }
+ }
+ }
+ return((-1 == opt_node) ? (0) : (opt_node));
+}
+
+static int wd_open(struct inode *inode, struct file *f)
+{
+ switch(MINOR(inode->i_rdev))
+ {
+ case WD0_MINOR:
+ f->private_data = &wd_dev.watchdog[WD0_ID];
+ break;
+ case WD1_MINOR:
+ f->private_data = &wd_dev.watchdog[WD1_ID];
+ break;
+ case WD2_MINOR:
+ f->private_data = &wd_dev.watchdog[WD2_ID];
+ break;
+ default:
+ return(-ENODEV);
+ }
+
+ /* Register IRQ on first open of device */
+ if(0 == wd_dev.initialized)
+ {
+ if (request_irq(wd_dev.irq,
+ &wd_interrupt,
+ SA_SHIRQ,
+ WD_OBPNAME,
+ (void *)wd_dev.regs)) {
+ printk("%s: Cannot register IRQ %s\n",
+ WD_OBPNAME, __irq_itoa(wd_dev.irq));
+ return(-EBUSY);
+ }
+ wd_dev.initialized = 1;
+ }
+
+ MOD_INC_USE_COUNT;
+ return(0);
+}
+
+static int wd_release(struct inode *inode, struct file *file)
+{
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+static int wd_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int setopt = 0;
+ struct wd_timer* pTimer = (struct wd_timer*)file->private_data;
+ struct watchdog_info info = {
+ 0,
+ 0,
+ "Altera EPF8820ATC144-4"
+ };
+
+ if(NULL == pTimer) {
+ return(-EINVAL);
+ }
+
+ switch(cmd)
+ {
+ /* Generic Linux IOCTLs */
+ case WDIOC_GETSUPPORT:
+ if(copy_to_user((struct watchdog_info *)arg,
+ (struct watchdog_info *)&info,
+ sizeof(struct watchdog_info *))) {
+ return(-EFAULT);
+ }
+ break;
+ case WDIOC_KEEPALIVE:
+ wd_pingtimer(pTimer);
+ break;
+ case WDIOC_SETOPTIONS:
+ if(copy_from_user(&setopt, (void*) arg, sizeof(unsigned int))) {
+ return -EFAULT;
+ }
+ if(setopt & WDIOS_DISABLECARD) {
+ if(wd_dev.opt_enable) {
+ printk(
+ "%s: cannot disable watchdog in ENABLED mode\n",
+ WD_OBPNAME);
+ return(-EINVAL);
+ }
+ wd_stoptimer(pTimer);
+ }
+ else if(setopt & WDIOS_ENABLECARD) {
+ wd_starttimer(pTimer);
+ }
+ else {
+ return(-EINVAL);
+ }
+ break;
+ /* Solaris-compatible IOCTLs */
+ case WIOCGSTAT:
+ setopt = wd_getstatus(pTimer);
+ if(copy_to_user((void*)arg, &setopt, sizeof(unsigned int))) {
+ return(-EFAULT);
+ }
+ break;
+ case WIOCSTART:
+ wd_starttimer(pTimer);
+ break;
+ case WIOCSTOP:
+ if(wd_dev.opt_enable) {
+ printk("%s: cannot disable watchdog in ENABLED mode\n",
+ WD_OBPNAME);
+ return(-EINVAL);
+ }
+ wd_stoptimer(pTimer);
+ break;
+ default:
+ return(-EINVAL);
+ }
+ return(0);
+}
+
+static ssize_t wd_write( struct file *file,
+ const char *buf,
+ size_t count,
+ loff_t *ppos)
+{
+ struct wd_timer* pTimer = (struct wd_timer*)file->private_data;
+
+ if(NULL == pTimer) {
+ return(-EINVAL);
+ }
+
+ wd_pingtimer(pTimer);
+ return(count);
+}
+
+static ssize_t wd_read(struct file * file, char * buffer,
+ size_t count, loff_t *ppos)
+{
+#ifdef WD_DEBUG
+ wd_dumpregs();
+ return(0);
+#else
+ return(-EINVAL);
+#endif /* ifdef WD_DEBUG */
+}
+
+void wd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ /* Only WD0 will interrupt-- others are NMI and we won't
+ * see them here....
+ */
+ spin_lock_irq(&wd_dev.lock);
+ if((unsigned long)wd_dev.regs == (unsigned long)dev_id)
+ {
+ wd_stoptimer(&wd_dev.watchdog[WD0_ID]);
+ wd_dev.watchdog[WD0_ID].runstatus |= WD_STAT_SVCD;
+ }
+ spin_unlock_irq(&wd_dev.lock);
+ return;
+}
+
+static struct file_operations wd_fops = {
+ owner: THIS_MODULE,
+ ioctl: wd_ioctl,
+ open: wd_open,
+ write: wd_write,
+ read: wd_read,
+ release: wd_release,
+};
+
+static struct miscdevice wd0_miscdev = { WD0_MINOR, WD0_DEVNAME, &wd_fops };
+static struct miscdevice wd1_miscdev = { WD1_MINOR, WD1_DEVNAME, &wd_fops };
+static struct miscdevice wd2_miscdev = { WD2_MINOR, WD2_DEVNAME, &wd_fops };
+
+void wd_dumpregs(void)
+{
+ /* Reading from downcounters initiates watchdog countdown--
+ * Example is included below for illustration purposes.
+ */
+ int i;
+ printk("%s: dumping register values\n", WD_OBPNAME);
+ for(i = WD0_ID; i < WD_NUMDEVS; ++i) {
+ /* printk("\t%s%i: dcntr at 0x%lx: 0x%x\n",
+ * WD_OBPNAME,
+ * i,
+ * (unsigned long)(&wd_dev.watchdog[i].regs->dcntr),
+ * readw(&wd_dev.watchdog[i].regs->dcntr));
+ */
+ printk("\t%s%i: limit at 0x%lx: 0x%x\n",
+ WD_OBPNAME,
+ i,
+ (unsigned long)(&wd_dev.watchdog[i].regs->limit),
+ readw(&wd_dev.watchdog[i].regs->limit));
+ printk("\t%s%i: status at 0x%lx: 0x%x\n",
+ WD_OBPNAME,
+ i,
+ (unsigned long)(&wd_dev.watchdog[i].regs->status),
+ readb(&wd_dev.watchdog[i].regs->status));
+ printk("\t%s%i: driver status: 0x%x\n",
+ WD_OBPNAME,
+ i,
+ wd_getstatus(&wd_dev.watchdog[i]));
+ }
+ printk("\tintr_mask at 0x%lx: 0x%x\n",
+ (unsigned long)(&wd_dev.regs->pld_regs.intr_mask),
+ readb(&wd_dev.regs->pld_regs.intr_mask));
+ printk("\tpld_status at 0x%lx: 0x%x\n",
+ (unsigned long)(&wd_dev.regs->pld_regs.status),
+ readb(&wd_dev.regs->pld_regs.status));
+}
+
+/* Enable or disable watchdog interrupts
+ * Because of the CP1400 defect this should only be
+ * called during initialzation or by wd_[start|stop]timer()
+ *
+ * pTimer - pointer to timer device, or NULL to indicate all timers
+ * enable - non-zero to enable interrupts, zero to disable
+ */
+void wd_toggleintr(struct wd_timer* pTimer, int enable)
+{
+ unsigned char curregs = wd_readb(&wd_dev.regs->pld_regs.intr_mask);
+ unsigned char setregs =
+ (NULL == pTimer) ?
+ (WD0_INTR_MASK | WD1_INTR_MASK | WD2_INTR_MASK) :
+ (pTimer->intr_mask);
+
+ (WD_INTR_ON == enable) ?
+ (curregs &= ~setregs):
+ (curregs |= setregs);
+
+ wd_writeb(curregs, &wd_dev.regs->pld_regs.intr_mask);
+ return;
+}
+
+/* Reset countdown timer with 'limit' value and continue countdown.
+ * This will not start a stopped timer.
+ *
+ * pTimer - pointer to timer device
+ */
+void wd_pingtimer(struct wd_timer* pTimer)
+{
+ if(wd_readb(&pTimer->regs->status) & WD_S_RUNNING) {
+ wd_readb(&pTimer->regs->dcntr);
+ }
+}
+
+/* Stop a running watchdog timer-- the timer actually keeps
+ * running, but the interrupt is masked so that no action is
+ * taken upon expiration.
+ *
+ * pTimer - pointer to timer device
+ */
+void wd_stoptimer(struct wd_timer* pTimer)
+{
+ if(wd_readb(&pTimer->regs->status) & WD_S_RUNNING) {
+ wd_toggleintr(pTimer, WD_INTR_OFF);
+
+ if(wd_dev.isbaddoggie) {
+ pTimer->runstatus |= WD_STAT_BSTOP;
+ wd_brokentimer((unsigned long)&wd_dev);
+ }
+ }
+}
+
+/* Start a watchdog timer with the specified limit value
+ * If the watchdog is running, it will be restarted with
+ * the provided limit value.
+ *
+ * This function will enable interrupts on the specified
+ * watchdog.
+ *
+ * pTimer - pointer to timer device
+ * limit - limit (countdown) value in 1/10th seconds
+ */
+void wd_starttimer(struct wd_timer* pTimer)
+{
+ if(wd_dev.isbaddoggie) {
+ pTimer->runstatus &= ~WD_STAT_BSTOP;
+ }
+ pTimer->runstatus &= ~WD_STAT_SVCD;
+
+ wd_writew(pTimer->timeout, &pTimer->regs->limit);
+ wd_toggleintr(pTimer, WD_INTR_ON);
+}
+
+/* Restarts timer with maximum limit value and
+ * does not unset 'brokenstop' value.
+ */
+void wd_resetbrokentimer(struct wd_timer* pTimer)
+{
+ wd_toggleintr(pTimer, WD_INTR_ON);
+ wd_writew(WD_BLIMIT, &pTimer->regs->limit);
+}
+
+/* Timer device initialization helper.
+ * Returns 0 on success, other on failure
+ */
+int wd_inittimer(int whichdog)
+{
+ struct miscdevice *whichmisc;
+ volatile struct wd_timer_regblk *whichregs;
+ char whichident[8];
+ int whichmask;
+ __u16 whichlimit;
+
+ switch(whichdog)
+ {
+ case WD0_ID:
+ whichmisc = &wd0_miscdev;
+ strcpy(whichident, "RIC");
+ whichregs = &wd_dev.regs->wd0_regs;
+ whichmask = WD0_INTR_MASK;
+ whichlimit= (0 == wd0_timeout) ?
+ (wd_dev.opt_timeout):
+ (wd0_timeout);
+ break;
+ case WD1_ID:
+ whichmisc = &wd1_miscdev;
+ strcpy(whichident, "XIR");
+ whichregs = &wd_dev.regs->wd1_regs;
+ whichmask = WD1_INTR_MASK;
+ whichlimit= (0 == wd1_timeout) ?
+ (wd_dev.opt_timeout):
+ (wd1_timeout);
+ break;
+ case WD2_ID:
+ whichmisc = &wd2_miscdev;
+ strcpy(whichident, "POR");
+ whichregs = &wd_dev.regs->wd2_regs;
+ whichmask = WD2_INTR_MASK;
+ whichlimit= (0 == wd2_timeout) ?
+ (wd_dev.opt_timeout):
+ (wd2_timeout);
+ break;
+ default:
+ printk("%s: %s: invalid watchdog id: %i\n",
+ WD_OBPNAME, __FUNCTION__, whichdog);
+ return(1);
+ }
+ if(0 != misc_register(whichmisc))
+ {
+ return(1);
+ }
+ wd_dev.watchdog[whichdog].regs = whichregs;
+ wd_dev.watchdog[whichdog].timeout = whichlimit;
+ wd_dev.watchdog[whichdog].intr_mask = whichmask;
+ wd_dev.watchdog[whichdog].runstatus &= ~WD_STAT_BSTOP;
+ wd_dev.watchdog[whichdog].runstatus |= WD_STAT_INIT;
+
+ printk("%s%i: %s hardware watchdog [%01i.%i sec] %s\n",
+ WD_OBPNAME,
+ whichdog,
+ whichident,
+ wd_dev.watchdog[whichdog].timeout / 10,
+ wd_dev.watchdog[whichdog].timeout % 10,
+ (0 != wd_dev.opt_enable) ? "in ENABLED mode" : "");
+ return(0);
+}
+
+/* Timer method called to reset stopped watchdogs--
+ * because of the PLD bug on CP1400, we cannot mask
+ * interrupts within the PLD so me must continually
+ * reset the timers ad infinitum.
+ */
+void wd_brokentimer(unsigned long data)
+{
+ struct wd_device* pDev = (struct wd_device*)data;
+ int id, tripped = 0;
+
+ /* kill a running timer instance, in case we
+ * were called directly instead of by kernel timer
+ */
+ if(timer_pending(&wd_timer)) {
+ del_timer(&wd_timer);
+ }
+
+ for(id = WD0_ID; id < WD_NUMDEVS; ++id) {
+ if(pDev->watchdog[id].runstatus & WD_STAT_BSTOP) {
+ ++tripped;
+ wd_resetbrokentimer(&pDev->watchdog[id]);
+ }
+ }
+
+ if(tripped) {
+ /* there is at least one timer brokenstopped-- reschedule */
+ wd_timer.expires = WD_BTIMEOUT;
+ add_timer(&wd_timer);
+ }
+}
+
+int wd_getstatus(struct wd_timer* pTimer)
+{
+ unsigned char stat = wd_readb(&pTimer->regs->status);
+ unsigned char intr = wd_readb(&wd_dev.regs->pld_regs.intr_mask);
+ unsigned char ret = WD_STOPPED;
+
+ /* determine STOPPED */
+ if(0 == stat ) {
+ return(ret);
+ }
+ /* determine EXPIRED vs FREERUN vs RUNNING */
+ else if(WD_S_EXPIRED & stat) {
+ ret = WD_EXPIRED;
+ }
+ else if(WD_S_RUNNING & stat) {
+ if(intr & pTimer->intr_mask) {
+ ret = WD_FREERUN;
+ }
+ else {
+ /* Fudge WD_EXPIRED status for defective CP1400--
+ * IF timer is running
+ * AND brokenstop is set
+ * AND an interrupt has been serviced
+ * we are WD_EXPIRED.
+ *
+ * IF timer is running
+ * AND brokenstop is set
+ * AND no interrupt has been serviced
+ * we are WD_FREERUN.
+ */
+ if(wd_dev.isbaddoggie && (pTimer->runstatus & WD_STAT_BSTOP)) {
+ if(pTimer->runstatus & WD_STAT_SVCD) {
+ ret = WD_EXPIRED;
+ }
+ else {
+ /* we could as well pretend we are expired */
+ ret = WD_FREERUN;
+ }
+ }
+ else {
+ ret = WD_RUNNING;
+ }
+ }
+ }
+
+ /* determine SERVICED */
+ if(pTimer->runstatus & WD_STAT_SVCD) {
+ ret |= WD_SERVICED;
+ }
+
+ return(ret);
+}
+
+static int __init wd_init(void)
+{
+ int id;
+ struct linux_ebus *ebus = NULL;
+ struct linux_ebus_device *edev = NULL;
+
+ for_each_ebus(ebus) {
+ for_each_ebusdev(edev, ebus) {
+ if (!strcmp(edev->prom_name, WD_OBPNAME))
+ goto ebus_done;
+ }
+ }
+
+ebus_done:
+ if(!edev) {
+ printk("%s: unable to locate device\n", WD_OBPNAME);
+ return -ENODEV;
+ }
+
+ wd_dev.regs =
+ ioremap(edev->resource[0].start, sizeof(struct wd_regblk));
+
+ if(NULL == wd_dev.regs) {
+ printk("%s: unable to map registers\n", WD_OBPNAME);
+ return(-ENODEV);
+ }
+
+ /* initialize device structure from OBP parameters */
+ wd_dev.irq = edev->irqs[0];
+ wd_dev.opt_enable = wd_opt_enable();
+ wd_dev.opt_reboot = wd_opt_reboot();
+ wd_dev.opt_timeout = wd_opt_timeout();
+ wd_dev.isbaddoggie = wd_isbroken();
+
+ /* disable all interrupts unless watchdog-enabled? == true */
+ if(! wd_dev.opt_enable) {
+ wd_toggleintr(NULL, WD_INTR_OFF);
+ }
+
+ /* register miscellaneous devices */
+ for(id = WD0_ID; id < WD_NUMDEVS; ++id) {
+ if(0 != wd_inittimer(id)) {
+ printk("%s%i: unable to initialize\n", WD_OBPNAME, id);
+ }
+ }
+
+ /* warn about possible defective PLD */
+ if(wd_dev.isbaddoggie) {
+ init_timer(&wd_timer);
+ wd_timer.function = wd_brokentimer;
+ wd_timer.data = (unsigned long)&wd_dev;
+ wd_timer.expires = WD_BTIMEOUT;
+
+ printk("%s: PLD defect workaround enabled for model %s\n",
+ WD_OBPNAME, WD_BADMODEL);
+ }
+ return(0);
+}
+
+static void __exit wd_cleanup(void)
+{
+ int id;
+
+ /* if 'watchdog-enable?' == TRUE, timers are not stopped
+ * when module is unloaded. All brokenstopped timers will
+ * also now eventually trip.
+ */
+ for(id = WD0_ID; id < WD_NUMDEVS; ++id) {
+ if(WD_S_RUNNING == wd_readb(&wd_dev.watchdog[id].regs->status)) {
+ if(wd_dev.opt_enable) {
+ printk(KERN_WARNING "%s%i: timer not stopped at release\n",
+ WD_OBPNAME, id);
+ }
+ else {
+ wd_stoptimer(&wd_dev.watchdog[id]);
+ if(wd_dev.watchdog[id].runstatus & WD_STAT_BSTOP) {
+ wd_resetbrokentimer(&wd_dev.watchdog[id]);
+ printk(KERN_WARNING
+ "%s%i: defect workaround disabled at release, "\
+ "timer expires in ~%01i sec\n",
+ WD_OBPNAME, id,
+ wd_readw(&wd_dev.watchdog[id].regs->limit) / 10);
+ }
+ }
+ }
+ }
+
+ if(wd_dev.isbaddoggie && timer_pending(&wd_timer)) {
+ del_timer(&wd_timer);
+ }
+ if(0 != (wd_dev.watchdog[WD0_ID].runstatus & WD_STAT_INIT)) {
+ misc_deregister(&wd0_miscdev);
+ }
+ if(0 != (wd_dev.watchdog[WD1_ID].runstatus & WD_STAT_INIT)) {
+ misc_deregister(&wd1_miscdev);
+ }
+ if(0 != (wd_dev.watchdog[WD2_ID].runstatus & WD_STAT_INIT)) {
+ misc_deregister(&wd2_miscdev);
+ }
+ if(0 != wd_dev.initialized) {
+ free_irq(wd_dev.irq, (void *)wd_dev.regs);
+ }
+ iounmap(wd_dev.regs);
+}
+
+module_init(wd_init);
+module_exit(wd_cleanup);
diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c
index 71809b59d..c6c927712 100644
--- a/drivers/sbus/char/flash.c
+++ b/drivers/sbus/char/flash.c
@@ -1,4 +1,4 @@
-/* $Id: flash.c,v 1.20 2000/11/08 04:57:49 davem Exp $
+/* $Id: flash.c,v 1.21 2001/01/11 15:29:36 davem Exp $
* flash.c: Allow mmap access to the OBP Flash, for OBP updates.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -14,6 +14,7 @@
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -22,6 +23,7 @@
#include <asm/sbus.h>
#include <asm/ebus.h>
+static spinlock_t flash_lock = SPIN_LOCK_UNLOCKED;
static struct {
unsigned long read_base; /* Physical read address */
unsigned long write_base; /* Physical write address */
@@ -38,14 +40,14 @@ flash_mmap(struct file *file, struct vm_area_struct *vma)
unsigned long addr;
unsigned long size;
- lock_kernel();
+ spin_lock(&flash_lock);
if (flash.read_base == flash.write_base) {
addr = flash.read_base;
size = flash.read_size;
} else {
if ((vma->vm_flags & VM_READ) &&
(vma->vm_flags & VM_WRITE)) {
- unlock_kernel();
+ spin_unlock(&flash_lock);
return -EINVAL;
}
if (vma->vm_flags & VM_READ) {
@@ -55,11 +57,11 @@ flash_mmap(struct file *file, struct vm_area_struct *vma)
addr = flash.write_base;
size = flash.write_size;
} else {
- unlock_kernel();
+ spin_unlock(&flash_lock);
return -ENXIO;
}
}
- unlock_kernel();
+ spin_unlock(&flash_lock);
if ((vma->vm_pgoff << PAGE_SHIFT) > size)
return -ENXIO;
@@ -127,9 +129,10 @@ flash_open(struct inode *inode, struct file *file)
static int
flash_release(struct inode *inode, struct file *file)
{
- lock_kernel();
+ spin_lock(&flash_lock);
flash.busy = 0;
- unlock_kernel();
+ spin_unlock(&flash_lock);
+
return 0;
}
diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
index f87850b2c..8faec19dd 100644
--- a/drivers/sbus/char/jsflash.c
+++ b/drivers/sbus/char/jsflash.c
@@ -505,9 +505,7 @@ static int jsfd_open(struct inode *inode, struct file *file)
static int jsf_release(struct inode *inode, struct file *file)
{
- lock_kernel();
jsf0.busy = 0;
- unlock_kernel();
return 0;
}
diff --git a/drivers/sbus/char/pcikbd.c b/drivers/sbus/char/pcikbd.c
index 6ddccf114..ea37949fa 100644
--- a/drivers/sbus/char/pcikbd.c
+++ b/drivers/sbus/char/pcikbd.c
@@ -1,4 +1,4 @@
-/* $Id: pcikbd.c,v 1.49 2000/07/13 08:06:40 davem Exp $
+/* $Id: pcikbd.c,v 1.50 2001/01/11 15:29:36 davem Exp $
* pcikbd.c: Ultra/AX PC keyboard support.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -746,13 +746,13 @@ static int aux_release(struct inode * inode, struct file * file)
{
unsigned long flags;
- lock_kernel();
aux_fasync(-1, file, 0);
- if (--aux_count)
- goto out;
spin_lock_irqsave(&pcikbd_lock, flags);
+ if (--aux_count)
+ goto out;
+
/* Disable controller ints */
aux_write_cmd(AUX_INTS_OFF);
poll_aux_status();
@@ -761,9 +761,8 @@ static int aux_release(struct inode * inode, struct file * file)
pcimouse_outb(KBD_CCMD_MOUSE_DISABLE, pcimouse_iobase + KBD_CNTL_REG);
poll_aux_status();
- spin_unlock_irqrestore(&pcikbd_lock, flags);
out:
- unlock_kernel();
+ spin_unlock_irqrestore(&pcikbd_lock, flags);
return 0;
}
@@ -780,11 +779,13 @@ static int aux_open(struct inode * inode, struct file * file)
if (!aux_present)
return -ENODEV;
- if (aux_count++)
- return 0;
-
spin_lock_irqsave(&pcikbd_lock, flags);
+ if (aux_count++) {
+ spin_unlock_irqrestore(&pcikbd_lock, flags);
+ return 0;
+ }
+
if (!poll_aux_status()) {
aux_count--;
spin_unlock_irqrestore(&pcikbd_lock, flags);
diff --git a/drivers/sbus/char/rtc.c b/drivers/sbus/char/rtc.c
index d8454cf25..6105e4229 100644
--- a/drivers/sbus/char/rtc.c
+++ b/drivers/sbus/char/rtc.c
@@ -1,4 +1,4 @@
-/* $Id: rtc.c,v 1.23 2000/08/29 07:01:55 davem Exp $
+/* $Id: rtc.c,v 1.24 2001/01/11 15:07:09 davem Exp $
*
* Linux/SPARC Real Time Clock Driver
* Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
@@ -31,11 +31,9 @@ static int rtc_busy = 0;
void get_rtc_time(struct rtc_time *t)
{
unsigned long regs = mstk48t02_regs;
- unsigned long flags;
u8 tmp;
- save_flags(flags);
- cli();
+ spin_lock_irq(&mostek_lock);
tmp = mostek_read(regs + MOSTEK_CREG);
tmp |= MSTK_CREG_READ;
@@ -52,18 +50,18 @@ void get_rtc_time(struct rtc_time *t)
tmp = mostek_read(regs + MOSTEK_CREG);
tmp &= ~MSTK_CREG_READ;
mostek_write(regs + MOSTEK_CREG, tmp);
- restore_flags(flags);
+
+ spin_unlock_irq(&mostek_lock);
}
/* Set the current date and time inthe real time clock. */
void set_rtc_time(struct rtc_time *t)
{
unsigned long regs = mstk48t02_regs;
- unsigned long flags;
u8 tmp;
- save_flags(flags);
- cli();
+ spin_lock_irq(&mostek_lock);
+
tmp = mostek_read(regs + MOSTEK_CREG);
tmp |= MSTK_CREG_WRITE;
mostek_write(regs + MOSTEK_CREG, tmp);
@@ -79,7 +77,8 @@ void set_rtc_time(struct rtc_time *t)
tmp = mostek_read(regs + MOSTEK_CREG);
tmp &= ~MSTK_CREG_WRITE;
mostek_write(regs + MOSTEK_CREG, tmp);
- restore_flags(flags);
+
+ spin_unlock_irq(&mostek_lock);
}
static long long rtc_lseek(struct file *file, long long offset, int origin)
@@ -121,20 +120,24 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
static int rtc_open(struct inode *inode, struct file *file)
{
+ int ret;
+
+ spin_lock_irq(&mostek_lock);
+ if (rtc_busy) {
+ ret = -EBUSY;
+ } else {
+ rtc_busy = 1;
+ ret = 0;
+ }
+ spin_unlock_irq(&mostek_lock);
- if (rtc_busy)
- return -EBUSY;
-
- rtc_busy = 1;
-
- return 0;
+ return ret;
}
static int rtc_release(struct inode *inode, struct file *file)
{
- lock_kernel();
rtc_busy = 0;
- unlock_kernel();
+
return 0;
}
@@ -150,11 +153,7 @@ static struct miscdevice rtc_dev = { RTC_MINOR, "rtc", &rtc_fops };
EXPORT_NO_SYMBOLS;
-#ifdef MODULE
-int init_module(void)
-#else
-int __init rtc_sun_init(void)
-#endif
+static int __init rtc_sun_init(void)
{
int error;
@@ -173,9 +172,10 @@ int __init rtc_sun_init(void)
return 0;
}
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit rtc_sun_cleanup(void)
{
misc_deregister(&rtc_dev);
}
-#endif
+
+module_init(rtc_sun_init);
+module_exit(rtc_sun_cleanup);
diff --git a/drivers/sbus/char/sunkbd.c b/drivers/sbus/char/sunkbd.c
index f34c12250..467200699 100644
--- a/drivers/sbus/char/sunkbd.c
+++ b/drivers/sbus/char/sunkbd.c
@@ -1521,15 +1521,17 @@ kbd_ioctl (struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
static int
kbd_open (struct inode *i, struct file *f)
{
+ spin_lock_irq(&kbd_queue_lock);
kbd_active++;
if (kbd_opened)
- return 0;
+ goto out;
kbd_opened = fg_console + 1;
- spin_lock_irq(&kbd_queue_lock);
kbd_head = kbd_tail = 0;
+
+ out:
spin_unlock_irq(&kbd_queue_lock);
return 0;
@@ -1538,7 +1540,7 @@ kbd_open (struct inode *i, struct file *f)
static int
kbd_close (struct inode *i, struct file *f)
{
- lock_kernel();
+ spin_lock_irq(&kbd_queue_lock);
if (!--kbd_active) {
if (kbd_redirected)
kbd_table [kbd_redirected-1].kbdmode = VC_XLATE;
@@ -1546,7 +1548,8 @@ kbd_close (struct inode *i, struct file *f)
kbd_opened = 0;
kbd_fasync (-1, f, 0);
}
- unlock_kernel();
+ spin_unlock_irq(&kbd_queue_lock);
+
return 0;
}
diff --git a/drivers/sbus/char/sunmouse.c b/drivers/sbus/char/sunmouse.c
index fd92bc434..8bb45cbde 100644
--- a/drivers/sbus/char/sunmouse.c
+++ b/drivers/sbus/char/sunmouse.c
@@ -391,11 +391,14 @@ sun_mouse_inbyte(unsigned char byte, int is_break)
static int
sun_mouse_open(struct inode * inode, struct file * file)
{
+ spin_lock_irq(&sunmouse.lock);
if (sunmouse.active++)
- return 0;
+ goto out;
sunmouse.delta_x = sunmouse.delta_y = 0;
sunmouse.button_state = 0x80;
sunmouse.vuid_mode = VUID_NATIVE;
+out:
+ spin_unlock_irq(&sunmouse.lock);
return 0;
}
@@ -412,10 +415,12 @@ static int sun_mouse_fasync (int fd, struct file *filp, int on)
static int
sun_mouse_close(struct inode *inode, struct file *file)
{
- lock_kernel();
sun_mouse_fasync (-1, file, 0);
+
+ spin_lock_irq(&sunmouse.lock);
sunmouse.active--;
- unlock_kernel();
+ spin_unlock_irq(&sunmouse.lock);
+
return 0;
}
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c
index 73158f351..a4c0f347e 100644
--- a/drivers/sbus/char/vfc_dev.c
+++ b/drivers/sbus/char/vfc_dev.c
@@ -22,6 +22,7 @@
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
@@ -181,17 +182,26 @@ struct vfc_dev *vfc_get_dev_ptr(int instance)
return vfc_dev_lst[instance];
}
+static spinlock_t vfc_dev_lock = SPIN_LOCK_UNLOCKED;
+
static int vfc_open(struct inode *inode, struct file *file)
{
struct vfc_dev *dev;
+ spin_lock(&vfc_dev_lock);
dev = vfc_get_dev_ptr(MINOR(inode->i_rdev));
- if (dev == NULL)
+ if (dev == NULL) {
+ spin_unlock(&vfc_dev_lock);
return -ENODEV;
- if (dev->busy)
+ }
+ if (dev->busy) {
+ spin_unlock(&vfc_dev_lock);
return -EBUSY;
+ }
dev->busy = 1;
+ spin_unlock(&vfc_dev_lock);
+
vfc_lock_device(dev);
vfc_csr_init(dev);
@@ -209,14 +219,14 @@ static int vfc_release(struct inode *inode,struct file *file)
{
struct vfc_dev *dev;
- lock_kernel();
+ spin_lock(&vfc_dev_lock);
dev = vfc_get_dev_ptr(MINOR(inode->i_rdev));
if (!dev || !dev->busy) {
- unlock_kernel();
+ spin_unlock(&vfc_dev_lock);
return -EINVAL;
}
dev->busy = 0;
- unlock_kernel();
+ spin_unlock(&vfc_dev_lock);
return 0;
}
@@ -611,12 +621,10 @@ static int vfc_mmap(struct inode *inode, struct file *file,
unsigned int map_size, ret, map_offset;
struct vfc_dev *dev;
- lock_kernel();
dev = vfc_get_dev_ptr(MINOR(inode->i_rdev));
- if(dev == NULL) {
- unlock_kernel();
+ if(dev == NULL)
return -ENODEV;
- }
+
map_size = vma->vm_end - vma->vm_start;
if(map_size > sizeof(struct vfc_regs))
map_size = sizeof(struct vfc_regs);
@@ -626,7 +634,7 @@ static int vfc_mmap(struct inode *inode, struct file *file,
map_offset = (unsigned int) (long)dev->phys_regs;
ret = io_remap_page_range(vma->vm_start, map_offset, map_size,
vma->vm_page_prot, dev->which_io);
- unlock_kernel();
+
if(ret)
return -EAGAIN;
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c
index 942a6c59b..032776c70 100644
--- a/drivers/sbus/sbus.c
+++ b/drivers/sbus/sbus.c
@@ -1,4 +1,4 @@
-/* $Id: sbus.c,v 1.91 2000/11/08 05:04:06 davem Exp $
+/* $Id: sbus.c,v 1.92 2001/01/25 17:15:59 davem Exp $
* sbus.c: SBus support routines.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -238,10 +238,14 @@ static void __init __apply_ranges_to_regs(struct linux_prom_ranges *ranges,
break;
}
if (rngnum == num_ranges) {
- prom_printf("sbus_apply_ranges: Cannot find matching "
- "range nregs[%d] nranges[%d].\n",
- num_regs, num_ranges);
- prom_halt();
+ /* We used to flag this as an error. Actually
+ * some devices do not report the regs as we expect.
+ * For example, see SUNW,pln device. In that case
+ * the reg property is in a format internal to that
+ * node, ie. it is not in the SBUS register space
+ * per se. -DaveM
+ */
+ return;
}
regs[regnum].which_io = ranges[rngnum].ot_parent_space;
regs[regnum].phys_addr += ranges[rngnum].ot_parent_base;
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index 5a74bc2df..73bd8029e 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -776,7 +776,7 @@ void print_sense_internal(const char * devclass,
printk("%s%s: sns = %2x %2x\n", devclass,
kdevname(dev), sense_buffer[0], sense_buffer[2]);
- printk("Non-extended sense class %d code 0x%0x ", sense_class, code);
+ printk("Non-extended sense class %d code 0x%0x\n", sense_class, code);
s = 4;
}
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
index f966bf5a7..0e5ee6935 100644
--- a/drivers/scsi/ibmmca.c
+++ b/drivers/scsi/ibmmca.c
@@ -16,6 +16,7 @@
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
#error "This driver works only with kernel 2.4.0 or higher!"
#endif
+#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/ctype.h>
@@ -38,7 +39,7 @@
#include <linux/config.h>
/* current version of this driver-source: */
-#define IBMMCA_SCSI_DRIVER_VERSION "4.0a"
+#define IBMMCA_SCSI_DRIVER_VERSION "4.0b"
#define IBMLOCK spin_lock_irqsave(&io_request_lock, flags);
#define IBMUNLOCK spin_unlock_irqrestore(&io_request_lock, flags);
@@ -443,7 +444,6 @@ static int scsi_id[IM_MAX_HOSTS] = { 7, 7, 7, 7, 7, 7, 7, 7 };
(that is kernel version 2.1.x) */
#if defined(MODULE)
static char *boot_options = NULL;
-#include <linux/module.h>
MODULE_PARM(boot_options, "s");
MODULE_PARM(io_port, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i");
MODULE_PARM(scsi_id, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i");
@@ -2563,9 +2563,6 @@ static int option_setup(char *str)
__setup("ibmmcascsi=", option_setup);
-#ifdef MODULE
-/* Eventually this will go into an include file, but this will be later */
-Scsi_Host_Template driver_template = IBMMCA;
+static Scsi_Host_Template driver_template = IBMMCA;
#include "scsi_module.c"
-#endif
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 264ae2fe0..106e39b8a 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -149,7 +149,6 @@
#include <linux/version.h>
#ifdef MODULE
-#include <linux/modversions.h>
#include <linux/module.h>
char kernel_version[] = UTS_RELEASE;
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
index d82eed0b7..fc0af0cbf 100644
--- a/drivers/scsi/ppa.c
+++ b/drivers/scsi/ppa.c
@@ -222,8 +222,8 @@ int ppa_detect(Scsi_Host_Template * host)
printk(" supported by the imm (ZIP Plus) driver. If the\n");
printk(" cable is marked with \"AutoDetect\", this is what has\n");
printk(" happened.\n");
- return 0;
spin_lock_irq(&io_request_lock);
+ return 0;
}
try_again = 1;
goto retry_entry;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index ace7c7e2c..dcde48437 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -50,6 +50,50 @@
* This entire source file deals with the new queueing code.
*/
+/*
+ * Function: __scsi_insert_special()
+ *
+ * Purpose: worker for scsi_insert_special_*()
+ *
+ * Arguments: q - request queue where request should be inserted
+ * rq - request to be inserted
+ * data - private data
+ * at_head - insert request at head or tail of queue
+ *
+ * Lock status: Assumed that io_request_lock is not held upon entry.
+ *
+ * Returns: Nothing
+ */
+static void __scsi_insert_special(request_queue_t *q, struct request *rq,
+ void *data, int at_head)
+{
+ unsigned long flags;
+
+ ASSERT_LOCK(&io_request_lock, 0);
+
+ rq->cmd = SPECIAL;
+ rq->special = data;
+ rq->q = NULL;
+ rq->nr_segments = 0;
+ rq->elevator_sequence = 0;
+
+ /*
+ * We have the option of inserting the head or the tail of the queue.
+ * Typically we use the tail for new ioctls and so forth. We use the
+ * head of the queue for things like a QUEUE_FULL message from a
+ * device, or a host that is unable to accept a particular command.
+ */
+ spin_lock_irqsave(&io_request_lock, flags);
+
+ if (at_head)
+ list_add(&rq->queue, &q->queue_head);
+ else
+ list_add_tail(&rq->queue, &q->queue_head);
+
+ q->request_fn(q);
+ spin_unlock_irqrestore(&io_request_lock, flags);
+}
+
/*
* Function: scsi_insert_special_cmd()
@@ -73,52 +117,9 @@
*/
int scsi_insert_special_cmd(Scsi_Cmnd * SCpnt, int at_head)
{
- unsigned long flags;
- request_queue_t *q;
-
- ASSERT_LOCK(&io_request_lock, 0);
-
- /*
- * The SCpnt already contains a request structure - we will doctor the
- * thing up with the appropriate values and use that in the actual
- * request queue.
- */
- q = &SCpnt->device->request_queue;
- SCpnt->request.cmd = SPECIAL;
- SCpnt->request.special = (void *) SCpnt;
- SCpnt->request.q = NULL;
- SCpnt->request.free_list = NULL;
- SCpnt->request.nr_segments = 0;
-
- /*
- * We have the option of inserting the head or the tail of the queue.
- * Typically we use the tail for new ioctls and so forth. We use the
- * head of the queue for things like a QUEUE_FULL message from a
- * device, or a host that is unable to accept a particular command.
- */
- spin_lock_irqsave(&io_request_lock, flags);
-
- if (at_head) {
- list_add(&SCpnt->request.queue, &q->queue_head);
- } else {
- /*
- * FIXME(eric) - we always insert at the tail of the
- * list. Otherwise ioctl commands would always take
- * precedence over normal I/O. An ioctl on a busy
- * disk might be delayed indefinitely because the
- * request might not float high enough in the queue
- * to be scheduled.
- */
- list_add_tail(&SCpnt->request.queue, &q->queue_head);
- }
+ request_queue_t *q = &SCpnt->device->request_queue;
- /*
- * Now hit the requeue function for the queue. If the host is
- * already busy, so be it - we have nothing special to do. If
- * the host can queue it, then send it off.
- */
- q->request_fn(q);
- spin_unlock_irqrestore(&io_request_lock, flags);
+ __scsi_insert_special(q, &SCpnt->request, SCpnt, at_head);
return 0;
}
@@ -144,51 +145,9 @@ int scsi_insert_special_cmd(Scsi_Cmnd * SCpnt, int at_head)
*/
int scsi_insert_special_req(Scsi_Request * SRpnt, int at_head)
{
- unsigned long flags;
- request_queue_t *q;
-
- ASSERT_LOCK(&io_request_lock, 0);
-
- /*
- * The SCpnt already contains a request structure - we will doctor the
- * thing up with the appropriate values and use that in the actual
- * request queue.
- */
- q = &SRpnt->sr_device->request_queue;
- SRpnt->sr_request.cmd = SPECIAL;
- SRpnt->sr_request.special = (void *) SRpnt;
- SRpnt->sr_request.q = NULL;
- SRpnt->sr_request.nr_segments = 0;
-
- /*
- * We have the option of inserting the head or the tail of the queue.
- * Typically we use the tail for new ioctls and so forth. We use the
- * head of the queue for things like a QUEUE_FULL message from a
- * device, or a host that is unable to accept a particular command.
- */
- spin_lock_irqsave(&io_request_lock, flags);
+ request_queue_t *q = &SRpnt->sr_device->request_queue;
- if (at_head) {
- list_add(&SRpnt->sr_request.queue, &q->queue_head);
- } else {
- /*
- * FIXME(eric) - we always insert at the tail of the
- * list. Otherwise ioctl commands would always take
- * precedence over normal I/O. An ioctl on a busy
- * disk might be delayed indefinitely because the
- * request might not float high enough in the queue
- * to be scheduled.
- */
- list_add_tail(&SRpnt->sr_request.queue, &q->queue_head);
- }
-
- /*
- * Now hit the requeue function for the queue. If the host is
- * already busy, so be it - we have nothing special to do. If
- * the host can queue it, then send it off.
- */
- q->request_fn(q);
- spin_unlock_irqrestore(&io_request_lock, flags);
+ __scsi_insert_special(q, &SRpnt->sr_request, SRpnt, at_head);
return 0;
}
@@ -403,6 +362,7 @@ static Scsi_Cmnd *__scsi_end_request(Scsi_Cmnd * SCpnt,
struct request *req;
struct buffer_head *bh;
Scsi_Device * SDpnt;
+ int nsect;
ASSERT_LOCK(&io_request_lock, 0);
@@ -414,11 +374,13 @@ static Scsi_Cmnd *__scsi_end_request(Scsi_Cmnd * SCpnt,
}
do {
if ((bh = req->bh) != NULL) {
+ nsect = bh->b_size >> 9;
+ blk_finished_io(nsect);
req->bh = bh->b_reqnext;
- req->nr_sectors -= bh->b_size >> 9;
- req->sector += bh->b_size >> 9;
+ req->nr_sectors -= nsect;
+ req->sector += nsect;
bh->b_reqnext = NULL;
- sectors -= bh->b_size >> 9;
+ sectors -= nsect;
bh->b_end_io(bh, uptodate);
if ((bh = req->bh) != NULL) {
req->current_nr_sectors = bh->b_size >> 9;
@@ -863,17 +825,6 @@ void scsi_request_fn(request_queue_t * q)
SHpnt = SDpnt->host;
/*
- * If the host for this device is in error recovery mode, don't
- * do anything at all here. When the host leaves error recovery
- * mode, it will automatically restart things and start queueing
- * commands again. Same goes if the queue is actually plugged,
- * if the device itself is blocked, or if the host is fully
- * occupied.
- */
- if (SHpnt->in_recovery || q->plugged)
- return;
-
- /*
* To start with, we keep looping until the queue is empty, or until
* the host is no longer able to accept any more requests.
*/
@@ -896,10 +847,11 @@ void scsi_request_fn(request_queue_t * q)
|| (SHpnt->host_blocked)
|| (SHpnt->host_self_blocked)) {
/*
- * If we are unable to process any commands at all for this
- * device, then we consider it to be starved. What this means
- * is that there are no outstanding commands for this device
- * and hence we need a little help getting it started again
+ * If we are unable to process any commands at all for
+ * this device, then we consider it to be starved.
+ * What this means is that there are no outstanding
+ * commands for this device and hence we need a
+ * little help getting it started again
* once the host isn't quite so busy.
*/
if (SDpnt->device_busy == 0) {
@@ -1000,8 +952,8 @@ void scsi_request_fn(request_queue_t * q)
}
/*
* If so, we are ready to do something. Bump the count
- * while the queue is locked and then break out of the loop.
- * Otherwise loop around and try another request.
+ * while the queue is locked and then break out of the
+ * loop. Otherwise loop around and try another request.
*/
if (!SCpnt) {
break;
@@ -1029,8 +981,9 @@ void scsi_request_fn(request_queue_t * q)
memcpy(&SCpnt->request, req, sizeof(struct request));
/*
- * We have copied the data out of the request block - it is now in
- * a field in SCpnt. Release the request block.
+ * We have copied the data out of the request block -
+ * it is now in a field in SCpnt. Release the request
+ * block.
*/
blkdev_release_request(req);
}
@@ -1047,12 +1000,14 @@ void scsi_request_fn(request_queue_t * q)
/*
* This will do a couple of things:
* 1) Fill in the actual SCSI command.
- * 2) Fill in any other upper-level specific fields (timeout).
+ * 2) Fill in any other upper-level specific fields
+ * (timeout).
*
- * If this returns 0, it means that the request failed (reading
- * past end of disk, reading offline device, etc). This won't
- * actually talk to the device, but some kinds of consistency
- * checking may cause the request to be rejected immediately.
+ * If this returns 0, it means that the request failed
+ * (reading past end of disk, reading offline device,
+ * etc). This won't actually talk to the device, but
+ * some kinds of consistency checking may cause the
+ * request to be rejected immediately.
*/
if (STpnt == NULL) {
STpnt = scsi_get_request_dev(req);
@@ -1103,8 +1058,8 @@ void scsi_request_fn(request_queue_t * q)
scsi_dispatch_cmd(SCpnt);
/*
- * Now we need to grab the lock again. We are about to mess with
- * the request queue and try to find another command.
+ * Now we need to grab the lock again. We are about to mess
+ * with the request queue and try to find another command.
*/
spin_lock_irq(&io_request_lock);
}
diff --git a/drivers/scsi/scsi_merge.c b/drivers/scsi/scsi_merge.c
index 7483eb970..4ebadd868 100644
--- a/drivers/scsi/scsi_merge.c
+++ b/drivers/scsi/scsi_merge.c
@@ -324,7 +324,6 @@ static inline int scsi_new_mergeable(request_queue_t * q,
req->nr_segments >= SHpnt->sg_tablesize)
return 0;
req->nr_segments++;
- q->elevator.nr_segments++;
return 1;
}
@@ -341,11 +340,8 @@ static inline int scsi_new_segment(request_queue_t * q,
if (req->nr_hw_segments >= SHpnt->sg_tablesize ||
req->nr_segments >= SHpnt->sg_tablesize)
return 0;
- if (req->nr_segments >= max_segments)
- return 0;
req->nr_hw_segments++;
req->nr_segments++;
- q->elevator.nr_segments++;
return 1;
}
#else
@@ -361,7 +357,6 @@ static inline int scsi_new_segment(request_queue_t * q,
* counter.
*/
req->nr_segments++;
- q->elevator.nr_segments++;
return 1;
} else {
return 0;
@@ -417,8 +412,10 @@ __inline static int __scsi_back_merge_fn(request_queue_t * q,
SDpnt = (Scsi_Device *) q->queuedata;
SHpnt = SDpnt->host;
+#ifdef DMA_CHUNK_SIZE
if (max_segments > 64)
max_segments = 64;
+#endif
if (use_clustering) {
/*
@@ -471,8 +468,10 @@ __inline static int __scsi_front_merge_fn(request_queue_t * q,
SDpnt = (Scsi_Device *) q->queuedata;
SHpnt = SDpnt->host;
+#ifdef DMA_CHUNK_SIZE
if (max_segments > 64)
max_segments = 64;
+#endif
if (use_clustering) {
/*
@@ -601,10 +600,10 @@ __inline static int __scsi_merge_requests_fn(request_queue_t * q,
SDpnt = (Scsi_Device *) q->queuedata;
SHpnt = SDpnt->host;
+#ifdef DMA_CHUNK_SIZE
if (max_segments > 64)
max_segments = 64;
-#ifdef DMA_CHUNK_SIZE
/* If it would not fit into prepared memory space for sg chain,
* then don't allow the merge.
*/
@@ -664,7 +663,6 @@ __inline static int __scsi_merge_requests_fn(request_queue_t * q,
* This one is OK. Let it go.
*/
req->nr_segments += next->nr_segments - 1;
- q->elevator.nr_segments--;
#ifdef DMA_CHUNK_SIZE
req->nr_hw_segments += next->nr_hw_segments - 1;
#endif
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 04e4a6a28..c064dfde4 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -694,6 +694,7 @@ static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
(void *)SRpnt->sr_buffer, hp->dxfer_len,
sg_cmd_done_bh, timeout, SG_DEFAULT_RETRIES);
/* dxfer_len overwrites SRpnt->sr_bufflen, hence need for b_malloc_len */
+ generic_unplug_device(&SRpnt->sr_device->request_queue);
return 0;
}
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 71ec104f4..7a2cde23b 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -671,12 +671,14 @@ void get_capabilities(int i)
cmd[3] = cmd[5] = 0;
rc = sr_do_ioctl(i, cmd, buffer, 128, 1, SCSI_DATA_READ, NULL);
- if (-EINVAL == rc) {
- /* failed, drive has'nt this mode page */
+ if (rc) {
+ /* failed, drive doesn't have capabilities mode page */
scsi_CDs[i].cdi.speed = 1;
- /* disable speed select, drive probably can't do this either */
- scsi_CDs[i].cdi.mask |= CDC_SELECT_SPEED;
+ scsi_CDs[i].cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R |
+ CDC_DVD | CDC_DVD_RAM |
+ CDC_SELECT_DISC | CDC_SELECT_SPEED);
scsi_free(buffer, 512);
+ printk("sr%i: scsi-1 drive\n", i);
return;
}
n = buffer[3] + 4;
diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in
index 9fd35efcb..10235dd2e 100644
--- a/drivers/sound/Config.in
+++ b/drivers/sound/Config.in
@@ -142,9 +142,9 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
dep_tristate ' Yamaha FM synthesizer (YM3812/OPL-3) support' CONFIG_SOUND_YM3812 $CONFIG_SOUND_OSS
dep_tristate ' Yamaha OPL3-SA1 audio controller' CONFIG_SOUND_OPL3SA1 $CONFIG_SOUND_OSS
dep_tristate ' Yamaha OPL3-SA2, SA3, and SAx based PnP cards' CONFIG_SOUND_OPL3SA2 $CONFIG_SOUND_OSS
- dep_tristate ' Yamaha YMF7xx PCI audio (legacy mode)' CONFIG_SOUND_YMPCI $CONFIG_SOUND_OSS $CONFIG_PCI
- if [ "$CONFIG_SOUND_YMPCI" = "n" ]; then
- dep_tristate ' Yamaha YMF7xx PCI audio (native mode) (EXPERIMENTAL)' CONFIG_SOUND_YMFPCI $CONFIG_SOUND_OSS $CONFIG_PCI $CONFIG_EXPERIMENTAL
+ dep_tristate ' Yamaha YMF7xx PCI audio (native mode)' CONFIG_SOUND_YMFPCI $CONFIG_SOUND_OSS $CONFIG_PCI
+ if [ "$CONFIG_SOUND_YMFPCI" != "n" ]; then
+ bool ' Yamaha PCI legacy ports support' CONFIG_SOUND_YMFPCI_LEGACY
fi
dep_tristate ' 6850 UART support' CONFIG_SOUND_UART6850 $CONFIG_SOUND_OSS
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
index e7ee317e6..824f08ec8 100644
--- a/drivers/sound/Makefile
+++ b/drivers/sound/Makefile
@@ -47,8 +47,10 @@ obj-$(CONFIG_SOUND_ACI_MIXER) += aci.o
obj-$(CONFIG_SOUND_AWE32_SYNTH) += awe_wave.o
obj-$(CONFIG_SOUND_VIA82CXXX) += via82cxxx_audio.o ac97_codec.o
-obj-$(CONFIG_SOUND_YMPCI) += ymf_sb.o sb_lib.o uart401.o
obj-$(CONFIG_SOUND_YMFPCI) += ymfpci.o ac97_codec.o
+ifeq ($(CONFIG_SOUND_YMFPCI_LEGACY),y)
+ obj-$(CONFIG_SOUND_YMFPCI) += opl3.o uart401.o
+endif
obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o
obj-$(CONFIG_SOUND_MSNDPIN) += msnd.o msnd_pinnacle.o
obj-$(CONFIG_SOUND_VWSND) += vwsnd.o
diff --git a/drivers/sound/emu10k1/audio.c b/drivers/sound/emu10k1/audio.c
index 9623dcb2e..2280ca236 100644
--- a/drivers/sound/emu10k1/audio.c
+++ b/drivers/sound/emu10k1/audio.c
@@ -375,8 +375,10 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
format = wiinst->format;
format.samplingrate = val;
- if (emu10k1_wavein_setformat(wave_dev, &format) < 0)
+ if (emu10k1_wavein_setformat(wave_dev, &format) < 0) {
+ spin_unlock_irqrestore(&wiinst->lock, flags);
return -EINVAL;
+ }
val = wiinst->format.samplingrate;
@@ -393,8 +395,10 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
format = woinst->format;
format.samplingrate = val;
- if (emu10k1_waveout_setformat(wave_dev, &format) < 0)
+ if (emu10k1_waveout_setformat(wave_dev, &format) < 0) {
+ spin_unlock_irqrestore(&woinst->lock, flags);
return -EINVAL;
+ }
val = woinst->format.samplingrate;
@@ -430,8 +434,10 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
format = wiinst->format;
format.channels = val ? 2 : 1;
- if (emu10k1_wavein_setformat(wave_dev, &format) < 0)
+ if (emu10k1_wavein_setformat(wave_dev, &format) < 0) {
+ spin_unlock_irqrestore(&wiinst->lock, flags);
return -EINVAL;
+ }
val = wiinst->format.channels - 1;
@@ -447,8 +453,10 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
format = woinst->format;
format.channels = val ? 2 : 1;
- if (emu10k1_waveout_setformat(wave_dev, &format) < 0)
+ if (emu10k1_waveout_setformat(wave_dev, &format) < 0) {
+ spin_unlock_irqrestore(&woinst->lock, flags);
return -EINVAL;
+ }
val = woinst->format.channels - 1;
@@ -478,8 +486,10 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
format = wiinst->format;
format.channels = val;
- if (emu10k1_wavein_setformat(wave_dev, &format) < 0)
+ if (emu10k1_wavein_setformat(wave_dev, &format) < 0) {
+ spin_unlock_irqrestore(&wiinst->lock, flags);
return -EINVAL;
+ }
val = wiinst->format.channels;
@@ -495,8 +505,10 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
format = woinst->format;
format.channels = val;
- if (emu10k1_waveout_setformat(wave_dev, &format) < 0)
+ if (emu10k1_waveout_setformat(wave_dev, &format) < 0) {
+ spin_unlock_irqrestore(&woinst->lock, flags);
return -EINVAL;
+ }
val = woinst->format.channels;
@@ -542,8 +554,10 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
format = wiinst->format;
format.bitsperchannel = val;
- if (emu10k1_wavein_setformat(wave_dev, &format) < 0)
+ if (emu10k1_wavein_setformat(wave_dev, &format) < 0) {
+ spin_unlock_irqrestore(&wiinst->lock, flags);
return -EINVAL;
+ }
val = wiinst->format.bitsperchannel;
@@ -559,8 +573,10 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
format = woinst->format;
format.bitsperchannel = val;
- if (emu10k1_waveout_setformat(wave_dev, &format) < 0)
+ if (emu10k1_waveout_setformat(wave_dev, &format) < 0) {
+ spin_unlock_irqrestore(&woinst->lock, flags);
return -EINVAL;
+ }
val = woinst->format.bitsperchannel;
@@ -968,6 +984,7 @@ static int emu10k1_audio_mmap(struct file *file, struct vm_area_struct *vma)
for (i = 0; i < woinst->buffer.pages; i++) {
if (remap_page_range(vma->vm_start + (i * PAGE_SIZE), virt_to_phys(woinst->buffer.addr[i]), PAGE_SIZE, vma->vm_page_prot)) {
spin_unlock_irqrestore(&woinst->lock, flags);
+ unlock_kernel();
return -EAGAIN;
}
}
diff --git a/drivers/sound/trix.c b/drivers/sound/trix.c
index 73c9dcf54..03b4b1999 100644
--- a/drivers/sound/trix.c
+++ b/drivers/sound/trix.c
@@ -17,7 +17,6 @@
* Arnaldo C. de Melo Got rid of attach_uart401
*/
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
diff --git a/drivers/sound/via82cxxx_audio.c b/drivers/sound/via82cxxx_audio.c
index f609d1e2b..fbe02bffd 100644
--- a/drivers/sound/via82cxxx_audio.c
+++ b/drivers/sound/via82cxxx_audio.c
@@ -15,7 +15,7 @@
*/
-#define VIA_VERSION "1.1.14"
+#define VIA_VERSION "1.1.14a"
#include <linux/config.h>
@@ -76,8 +76,16 @@
#define VIA_COUNTER_LIMIT 100000
/* size of DMA buffers */
-#define VIA_DMA_BUFFERS 16
-#define VIA_DMA_BUF_SIZE PAGE_SIZE
+#define VIA_MAX_BUFFER_DMA_PAGES 32
+
+/* buffering default values in ms */
+#define VIA_DEFAULT_FRAG_TIME 20
+#define VIA_DEFAULT_BUFFER_TIME 500
+
+#define VIA_MAX_FRAG_SIZE PAGE_SIZE
+#define VIA_MIN_FRAG_SIZE 64
+
+#define VIA_MIN_FRAG_NUMBER 2
#ifndef AC97_PCM_LR_ADC_RATE
# define AC97_PCM_LR_ADC_RATE AC97_PCM_LR_DAC_RATE
@@ -102,7 +110,6 @@
#define VIA_BASE0_PCM_OUT_CHAN_STATUS 0x00
#define VIA_BASE0_PCM_OUT_CHAN_CTRL 0x01
#define VIA_BASE0_PCM_OUT_CHAN_TYPE 0x02
-#define VIA_BASE0_PCM_OUT_BLOCK_COUNT 0x0C
#define VIA_BASE0_PCM_IN_CHAN 0x10 /* input PCM from user */
#define VIA_BASE0_PCM_IN_CHAN_STATUS 0x10
@@ -114,6 +121,7 @@
#define VIA_PCM_CONTROL 0x01
#define VIA_PCM_TYPE 0x02
#define VIA_PCM_TABLE_ADDR 0x04
+#define VIA_PCM_BLOCK_COUNT 0x0C
/* XXX unused DMA channel for FM PCM data */
#define VIA_BASE0_FM_OUT_CHAN 0x20
@@ -223,14 +231,14 @@ enum via_channel_states {
};
-struct via_sgd_data {
+struct via_buffer_pgtbl {
dma_addr_t handle;
void *cpuaddr;
};
struct via_channel {
- atomic_t n_bufs;
+ atomic_t n_frags;
atomic_t hw_ptr;
wait_queue_head_t wait;
@@ -246,11 +254,14 @@ struct via_channel {
u8 pcm_fmt; /* VIA_PCM_FMT_xxx */
unsigned rate; /* sample rate */
+ unsigned int frag_size;
+ unsigned int frag_number;
volatile struct via_sgd_table *sgtable;
dma_addr_t sgt_handle;
- struct via_sgd_data sgbuf [VIA_DMA_BUFFERS];
+ unsigned int page_number;
+ struct via_buffer_pgtbl pgtbl[VIA_MAX_BUFFER_DMA_PAGES];
long iobase;
@@ -301,17 +312,16 @@ static unsigned int via_dsp_poll(struct file *file, struct poll_table_struct *wa
static int via_dsp_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
static int via_dsp_open (struct inode *inode, struct file *file);
static int via_dsp_release(struct inode *inode, struct file *file);
-#ifdef VIA_SUPPORT_MMAP
static int via_dsp_mmap(struct file *file, struct vm_area_struct *vma);
-#endif
static u16 via_ac97_read_reg (struct ac97_codec *codec, u8 reg);
static void via_ac97_write_reg (struct ac97_codec *codec, u8 reg, u16 value);
static u8 via_ac97_wait_idle (struct via_info *card);
static void via_chan_free (struct via_info *card, struct via_channel *chan);
-static void via_chan_clear (struct via_channel *chan);
+static void via_chan_clear (struct via_info *card, struct via_channel *chan);
static void via_chan_pcm_fmt (struct via_channel *chan, int reset);
+static void via_chan_buffer_free (struct via_info *card, struct via_channel *chan);
#ifdef VIA_PROC_FS
static int via_init_proc (void);
@@ -569,25 +579,53 @@ static void via_chan_init_defaults (struct via_info *card, struct via_channel *c
chan->pcm_fmt = VIA_PCM_FMT_MASK;
chan->is_enabled = 1;
- if (chan->is_record)
- atomic_set (&chan->n_bufs, 0);
- else
- atomic_set (&chan->n_bufs, VIA_DMA_BUFFERS);
+ chan->frag_number = 0;
+ chan->frag_size = 0;
+ atomic_set(&chan->n_frags, 0);
atomic_set (&chan->hw_ptr, 0);
}
+/**
+ * via_chan_init - Initialize PCM channel
+ * @card: Private audio chip info
+ * @chan: Channel to be initialized
+ *
+ * Performs some of the preparations necessary to begin
+ * using a PCM channel.
+ *
+ * Currently the preparations consist in
+ * setting the
+ * PCM channel to a known state.
+ */
+
+
+static void via_chan_init (struct via_info *card, struct via_channel *chan)
+{
+
+ DPRINTK ("ENTER\n");
+
+ /* bzero channel structure, and init members to defaults */
+ via_chan_init_defaults (card, chan);
+
+ /* stop any existing channel output */
+ via_chan_clear (card, chan);
+ via_chan_status_clear (chan->iobase);
+ via_chan_pcm_fmt (chan, 1);
+
+ DPRINTK ("EXIT\n");
+}
/**
- * via_chan_init - Initialize PCM channel
+ * via_chan_buffer_init - Initialize PCM channel buffer
* @card: Private audio chip info
* @chan: Channel to be initialized
*
- * Performs all the preparations necessary to begin
+ * Performs some of the preparations necessary to begin
* using a PCM channel.
*
* Currently the preparations include allocating the
- * scatter-gather DMA table and buffers, setting the
- * PCM channel to a known state, and passing the
+ * scatter-gather DMA table and buffers,
+ * and passing the
* address of the DMA table to the hardware.
*
* Note that special care is taken when passing the
@@ -596,18 +634,21 @@ static void via_chan_init_defaults (struct via_info *card, struct via_channel *c
* always "take" the address.
*/
-static int via_chan_init (struct via_info *card, struct via_channel *chan)
+static int via_chan_buffer_init (struct via_info *card, struct via_channel *chan)
{
+ int page, offset;
int i;
DPRINTK ("ENTER\n");
- /* bzero channel structure, and init members to defaults */
- via_chan_init_defaults (card, chan);
+ if (chan->sgtable != NULL) {
+ DPRINTK ("EXIT\n");
+ return 0;
+ }
/* alloc DMA-able memory for scatter-gather table */
chan->sgtable = pci_alloc_consistent (card->pdev,
- (sizeof (struct via_sgd_table) * VIA_DMA_BUFFERS),
+ (sizeof (struct via_sgd_table) * chan->frag_number),
&chan->sgt_handle);
if (!chan->sgtable) {
printk (KERN_ERR PFX "DMA table alloc fail, aborting\n");
@@ -616,45 +657,54 @@ static int via_chan_init (struct via_info *card, struct via_channel *chan)
}
memset ((void*)chan->sgtable, 0,
- (sizeof (struct via_sgd_table) * VIA_DMA_BUFFERS));
+ (sizeof (struct via_sgd_table) * chan->frag_number));
/* alloc DMA-able memory for scatter-gather buffers */
- for (i = 0; i < VIA_DMA_BUFFERS; i++) {
- chan->sgbuf[i].cpuaddr =
- pci_alloc_consistent (card->pdev, VIA_DMA_BUF_SIZE,
- &chan->sgbuf[i].handle);
- if (!chan->sgbuf[i].cpuaddr)
- goto err_out_nomem;
+ chan->page_number = (chan->frag_number * chan->frag_size) / PAGE_SIZE +
+ (((chan->frag_number * chan->frag_size) % PAGE_SIZE) ? 1 : 0);
+
+ for (i = 0; i < chan->page_number; i++) {
+ chan->pgtbl[i].cpuaddr = pci_alloc_consistent (card->pdev, PAGE_SIZE,
+ &chan->pgtbl[i].handle);
- if (i < (VIA_DMA_BUFFERS - 1))
- chan->sgtable[i].count = cpu_to_le32 (VIA_DMA_BUF_SIZE | VIA_FLAG);
- else
- chan->sgtable[i].count = cpu_to_le32 (VIA_DMA_BUF_SIZE | VIA_EOL);
- chan->sgtable[i].addr = cpu_to_le32 (chan->sgbuf[i].handle);
+ if (!chan->pgtbl[i].cpuaddr) {
+ chan->page_number = i;
+ goto err_out_nomem;
+ }
#ifndef VIA_NDEBUG
- memset (chan->sgbuf[i].cpuaddr, 0xBC, VIA_DMA_BUF_SIZE);
+ memset (chan->pgtbl[i].cpuaddr, 0xBC, chan->frag_size);
#endif
#if 1
- DPRINTK ("dmabuf #%d (h=%lx, 32(h)=%lx, v2p=%lx, a=%p)\n",
- i, (long)chan->sgbuf[i].handle,
- (long)chan->sgtable[i].addr,
- virt_to_phys(chan->sgbuf[i].cpuaddr),
- chan->sgbuf[i].cpuaddr);
+ DPRINTK ("dmabuf_pg #%d (h=%lx, v2p=%lx, a=%p)\n",
+ i, (long)chan->pgtbl[i].handle,
+ virt_to_phys(chan->pgtbl[i].cpuaddr),
+ chan->pgtbl[i].cpuaddr);
#endif
-
- assert ((VIA_DMA_BUF_SIZE % PAGE_SIZE) == 0);
}
- /* stop any existing channel output */
- via_chan_clear (chan);
- via_chan_status_clear (chan->iobase);
- via_chan_pcm_fmt (chan, 1);
+ for (i = 0; i < chan->frag_number; i++) {
+
+ page = i / (PAGE_SIZE / chan->frag_size);
+ offset = (i % (PAGE_SIZE / chan->frag_size)) * chan->frag_size;
+
+ chan->sgtable[i].count = cpu_to_le32 (chan->frag_size | VIA_FLAG);
+ chan->sgtable[i].addr = cpu_to_le32 (chan->pgtbl[page].handle + offset);
+
+#if 1
+ DPRINTK ("dmabuf #%d (32(h)=%lx)\n",
+ i,
+ (long)chan->sgtable[i].addr);
+#endif
+ }
+
+ /* overwrite the last buffer information */
+ chan->sgtable[chan->frag_number - 1].count = cpu_to_le32 (chan->frag_size | VIA_EOL);
/* set location of DMA-able scatter-gather info table */
- DPRINTK("outl (0x%X, 0x%04lX)\n",
+ DPRINTK ("outl (0x%X, 0x%04lX)\n",
cpu_to_le32 (chan->sgt_handle),
chan->iobase + VIA_PCM_TABLE_ADDR);
@@ -664,7 +714,7 @@ static int via_chan_init (struct via_info *card, struct via_channel *chan)
udelay (20);
via_ac97_wait_idle (card);
- DPRINTK("inl (0x%lX) = %x\n",
+ DPRINTK ("inl (0x%lX) = %x\n",
chan->iobase + VIA_PCM_TABLE_ADDR,
inl(chan->iobase + VIA_PCM_TABLE_ADDR));
@@ -673,7 +723,7 @@ static int via_chan_init (struct via_info *card, struct via_channel *chan)
err_out_nomem:
printk (KERN_ERR PFX "DMA buffer alloc fail, aborting\n");
- via_chan_free (card, chan);
+ via_chan_buffer_free (card, chan);
DPRINTK ("EXIT\n");
return -ENOMEM;
}
@@ -695,8 +745,6 @@ err_out_nomem:
static void via_chan_free (struct via_info *card, struct via_channel *chan)
{
- int i;
-
DPRINTK ("ENTER\n");
synchronize_irq();
@@ -710,23 +758,33 @@ static void via_chan_free (struct via_info *card, struct via_channel *chan)
spin_unlock_irq (&card->lock);
+ DPRINTK ("EXIT\n");
+}
+
+static void via_chan_buffer_free (struct via_info *card, struct via_channel *chan)
+{
+ int i;
+
+ DPRINTK ("ENTER\n");
+
/* zero location of DMA-able scatter-gather info table */
via_ac97_wait_idle(card);
outl (0, chan->iobase + VIA_PCM_TABLE_ADDR);
- for (i = 0; i < VIA_DMA_BUFFERS; i++)
- if (chan->sgbuf[i].cpuaddr) {
- assert ((VIA_DMA_BUF_SIZE % PAGE_SIZE) == 0);
- pci_free_consistent (card->pdev, VIA_DMA_BUF_SIZE,
- chan->sgbuf[i].cpuaddr,
- chan->sgbuf[i].handle);
- chan->sgbuf[i].cpuaddr = NULL;
- chan->sgbuf[i].handle = 0;
+ for (i = 0; i < chan->page_number; i++)
+ if (chan->pgtbl[i].cpuaddr) {
+ pci_free_consistent (card->pdev, PAGE_SIZE,
+ chan->pgtbl[i].cpuaddr,
+ chan->pgtbl[i].handle);
+ chan->pgtbl[i].cpuaddr = NULL;
+ chan->pgtbl[i].handle = 0;
}
+ chan->page_number = 0;
+
if (chan->sgtable) {
pci_free_consistent (card->pdev,
- (sizeof (struct via_sgd_table) * VIA_DMA_BUFFERS),
+ (sizeof (struct via_sgd_table) * chan->frag_number),
(void*)chan->sgtable, chan->sgt_handle);
chan->sgtable = NULL;
}
@@ -771,11 +829,11 @@ static void via_chan_pcm_fmt (struct via_channel *chan, int reset)
if (!chan->is_record)
chan->pcm_fmt |= VIA_CHAN_TYPE_INT_SELECT;
- outb (chan->pcm_fmt, chan->iobase + 2);
+ outb (chan->pcm_fmt, chan->iobase + VIA_PCM_TYPE);
DPRINTK ("EXIT, pcm_fmt = 0x%02X, reg = 0x%02X\n",
chan->pcm_fmt,
- inb (chan->iobase + 2));
+ inb (chan->iobase + VIA_PCM_TYPE));
}
@@ -787,10 +845,11 @@ static void via_chan_pcm_fmt (struct via_channel *chan, int reset)
* all software pointers which track DMA operation.
*/
-static void via_chan_clear (struct via_channel *chan)
+static void via_chan_clear (struct via_info *card, struct via_channel *chan)
{
DPRINTK ("ENTER\n");
via_chan_stop (chan->iobase);
+ via_chan_buffer_free(card, chan);
chan->is_active = 0;
chan->is_mapped = 0;
chan->is_enabled = 1;
@@ -798,10 +857,6 @@ static void via_chan_clear (struct via_channel *chan)
chan->sw_ptr = 0;
chan->n_irqs = 0;
atomic_set (&chan->hw_ptr, 0);
- if (chan->is_record)
- atomic_set (&chan->n_bufs, 0);
- else
- atomic_set (&chan->n_bufs, VIA_DMA_BUFFERS);
DPRINTK ("EXIT\n");
}
@@ -826,7 +881,7 @@ static int via_chan_set_speed (struct via_info *card,
{
DPRINTK ("ENTER, requested rate = %d\n", val);
- via_chan_clear (chan);
+ via_chan_clear (card, chan);
val = via_set_rate (&card->ac97, chan, val);
@@ -858,7 +913,7 @@ static int via_chan_set_fmt (struct via_info *card,
val == AFMT_S16_LE ? "AFMT_S16_LE" :
"unknown");
- via_chan_clear (chan);
+ via_chan_clear (card, chan);
assert (val != AFMT_QUERY); /* this case is handled elsewhere */
@@ -907,7 +962,7 @@ static int via_chan_set_stereo (struct via_info *card,
{
DPRINTK ("ENTER, channels = %d\n", val);
- via_chan_clear (chan);
+ via_chan_clear (card, chan);
switch (val) {
@@ -934,6 +989,78 @@ static int via_chan_set_stereo (struct via_info *card,
return val;
}
+static int via_chan_set_buffering (struct via_info *card,
+ struct via_channel *chan, int val)
+{
+ int shift;
+
+ DPRINTK ("ENTER\n");
+
+ /* in both cases the buffer cannot be changed */
+ if (chan->is_active || chan->is_mapped) {
+ DPRINTK ("EXIT\n");
+ return -EINVAL;
+ }
+
+ /* called outside SETFRAGMENT */
+ /* set defaults or do nothing */
+ if (val < 0) {
+
+ if (chan->frag_size && chan->frag_number)
+ goto out;
+
+ DPRINTK ("\n");
+
+ chan->frag_size = (VIA_DEFAULT_FRAG_TIME * chan->rate *
+ ((chan->pcm_fmt & VIA_PCM_FMT_STEREO) ? 2 : 1) *
+ ((chan->pcm_fmt & VIA_PCM_FMT_16BIT) ? 2 : 1)) / 1000 - 1;
+
+ shift = 0;
+ while (chan->frag_size) {
+ chan->frag_size >>= 1;
+ shift++;
+ }
+ chan->frag_size = 1 << shift;
+
+ chan->frag_number = (VIA_DEFAULT_BUFFER_TIME / VIA_DEFAULT_FRAG_TIME);
+
+ DPRINTK ("setting default values %d %d\n", chan->frag_size, chan->frag_number);
+ } else {
+ chan->frag_size = 1 << (val & 0xFFFF);
+ chan->frag_number = (val >> 16) & 0xFFFF;
+
+ DPRINTK ("using user values %d %d\n", chan->frag_size, chan->frag_number);
+ }
+
+ /* quake3 wants frag_number to be a power of two */
+ shift = 0;
+ while (chan->frag_number) {
+ chan->frag_number >>= 1;
+ shift++;
+ }
+ chan->frag_number = 1 << shift;
+
+ if (chan->frag_size > VIA_MAX_FRAG_SIZE)
+ chan->frag_size = VIA_MAX_FRAG_SIZE;
+ else if (chan->frag_size < VIA_MIN_FRAG_SIZE)
+ chan->frag_size = VIA_MIN_FRAG_SIZE;
+
+ if (chan->frag_number < VIA_MIN_FRAG_NUMBER)
+ chan->frag_number = VIA_MIN_FRAG_NUMBER;
+
+ if ((chan->frag_number * chan->frag_size) / PAGE_SIZE > VIA_MAX_BUFFER_DMA_PAGES)
+ chan->frag_number = (VIA_MAX_BUFFER_DMA_PAGES * PAGE_SIZE) / chan->frag_size;
+
+out:
+ if (chan->is_record)
+ atomic_set (&chan->n_frags, 0);
+ else
+ atomic_set (&chan->n_frags, chan->frag_number);
+
+ DPRINTK ("EXIT\n");
+
+ return 0;
+}
#ifdef VIA_CHAN_DUMP_BUFS
/**
@@ -948,7 +1075,7 @@ static void via_chan_dump_bufs (struct via_channel *chan)
{
int i;
- for (i = 0; i < VIA_DMA_BUFFERS; i++) {
+ for (i = 0; i < chan->frag_number; i++) {
DPRINTK ("#%02d: addr=%x, count=%u, flag=%d, eol=%d\n",
i, chan->sgtable[i].addr,
chan->sgtable[i].count & 0x00FFFFFF,
@@ -975,15 +1102,15 @@ static void via_chan_flush_frag (struct via_channel *chan)
assert (chan->slop_len > 0);
- if (chan->sw_ptr == (VIA_DMA_BUFFERS - 1))
+ if (chan->sw_ptr == (chan->frag_number - 1))
chan->sw_ptr = 0;
else
chan->sw_ptr++;
chan->slop_len = 0;
- assert (atomic_read (&chan->n_bufs) > 0);
- atomic_dec (&chan->n_bufs);
+ assert (atomic_read (&chan->n_frags) > 0);
+ atomic_dec (&chan->n_frags);
DPRINTK ("EXIT\n");
}
@@ -1003,7 +1130,7 @@ static inline void via_chan_maybe_start (struct via_channel *chan)
if (!chan->is_active && chan->is_enabled) {
chan->is_active = 1;
sg_begin (chan);
- DPRINTK("starting channel %s\n", chan->name);
+ DPRINTK ("starting channel %s\n", chan->name);
}
}
@@ -1213,7 +1340,7 @@ static loff_t via_llseek(struct file *file, loff_t offset, int origin)
{
DPRINTK ("ENTER\n");
- DPRINTK("EXIT, returning -ESPIPE\n");
+ DPRINTK ("EXIT, returning -ESPIPE\n");
return -ESPIPE;
}
@@ -1245,7 +1372,7 @@ static int __init via_ac97_reset (struct via_info *card)
pci_read_config_byte (card->pdev, 0x43, &r43);
pci_read_config_byte (card->pdev, 0x44, &r44);
pci_read_config_byte (card->pdev, 0x48, &r48);
- DPRINTK("PCI config: %02X %02X %02X %02X %02X %02X\n",
+ DPRINTK ("PCI config: %02X %02X %02X %02X %02X %02X\n",
r40,r41,r42,r43,r44,r48);
spin_lock_irq (&card->lock);
@@ -1334,7 +1461,7 @@ static int __init via_ac97_init (struct via_info *card)
card->ac97.dev_mixer = register_sound_mixer (&via_mixer_fops, -1);
if (card->ac97.dev_mixer < 0) {
printk (KERN_ERR PFX "unable to register AC97 mixer, aborting\n");
- DPRINTK("EXIT, returning -EIO\n");
+ DPRINTK ("EXIT, returning -EIO\n");
return -EIO;
}
@@ -1359,21 +1486,21 @@ static int __init via_ac97_init (struct via_info *card)
err_out:
unregister_sound_mixer (card->ac97.dev_mixer);
- DPRINTK("EXIT, returning %d\n", rc);
+ DPRINTK ("EXIT, returning %d\n", rc);
return rc;
}
static void via_ac97_cleanup (struct via_info *card)
{
- DPRINTK("ENTER\n");
+ DPRINTK ("ENTER\n");
assert (card != NULL);
assert (card->ac97.dev_mixer >= 0);
unregister_sound_mixer (card->ac97.dev_mixer);
- DPRINTK("EXIT\n");
+ DPRINTK ("EXIT\n");
}
@@ -1414,24 +1541,24 @@ static void via_intr_channel (struct via_channel *chan)
/* sanity check: make sure our h/w ptr doesn't have a weird value */
assert (n >= 0);
- assert (n < VIA_DMA_BUFFERS);
+ assert (n < chan->frag_number);
/* reset SGD data structure in memory to reflect a full buffer,
* and advance the h/w ptr, wrapping around to zero if needed
*/
- if (n == (VIA_DMA_BUFFERS - 1)) {
- chan->sgtable[n].count = (VIA_DMA_BUF_SIZE | VIA_EOL);
+ if (n == (chan->frag_number - 1)) {
+ chan->sgtable[n].count = (chan->frag_size | VIA_EOL);
atomic_set (&chan->hw_ptr, 0);
} else {
- chan->sgtable[n].count = (VIA_DMA_BUF_SIZE | VIA_FLAG);
+ chan->sgtable[n].count = (chan->frag_size | VIA_FLAG);
atomic_inc (&chan->hw_ptr);
}
/* accounting crap for SNDCTL_DSP_GETxPTR */
chan->n_irqs++;
- chan->bytes += VIA_DMA_BUF_SIZE;
+ chan->bytes += chan->frag_size;
if (chan->bytes < 0) /* handle overflow of 31-bit value */
- chan->bytes = VIA_DMA_BUF_SIZE;
+ chan->bytes = chan->frag_size;
/* wake up anyone listening to see when interrupts occur */
if (waitqueue_active (&chan->wait))
@@ -1445,25 +1572,25 @@ static void via_intr_channel (struct via_channel *chan)
if (chan->is_mapped)
return;
- /* If we are recording, then n_bufs represents the number
- * of buffers waiting to be handled by userspace.
- * If we are playback, then n_bufs represents the number
- * of buffers remaining to be filled by userspace.
- * We increment here. If we reach max buffers (VIA_DMA_BUFFERS),
+ /* If we are recording, then n_frags represents the number
+ * of fragments waiting to be handled by userspace.
+ * If we are playback, then n_frags represents the number
+ * of fragments remaining to be filled by userspace.
+ * We increment here. If we reach max number of fragments,
* this indicates an underrun/overrun. For this case under OSS,
* we stop the record/playback process.
*/
- if (atomic_read (&chan->n_bufs) < VIA_DMA_BUFFERS)
- atomic_inc (&chan->n_bufs);
- assert (atomic_read (&chan->n_bufs) <= VIA_DMA_BUFFERS);
+ if (atomic_read (&chan->n_frags) < chan->frag_number)
+ atomic_inc (&chan->n_frags);
+ assert (atomic_read (&chan->n_frags) <= chan->frag_number);
- if (atomic_read (&chan->n_bufs) == VIA_DMA_BUFFERS) {
+ if (atomic_read (&chan->n_frags) == chan->frag_number) {
chan->is_active = 0;
via_chan_stop (chan->iobase);
}
- DPRINTK ("%s intr, channel n_bufs == %d\n", chan->name,
- atomic_read (&chan->n_bufs));
+ DPRINTK ("%s intr, channel n_frags == %d\n", chan->name,
+ atomic_read (&chan->n_frags));
}
@@ -1618,9 +1745,7 @@ static struct file_operations via_dsp_fops = {
poll: via_dsp_poll,
llseek: via_llseek,
ioctl: via_dsp_ioctl,
-#ifdef VIA_SUPPORT_MMAP
mmap: via_dsp_mmap,
-#endif
};
@@ -1668,7 +1793,6 @@ static void via_dsp_cleanup (struct via_info *card)
}
-#ifdef VIA_SUPPORT_MMAP
static struct page * via_mm_nopage (struct vm_area_struct * vma,
unsigned long address, int write_access)
{
@@ -1685,8 +1809,6 @@ static struct page * via_mm_nopage (struct vm_area_struct * vma,
address,
write_access);
- assert (VIA_DMA_BUF_SIZE == PAGE_SIZE);
-
if (address > vma->vm_end) {
DPRINTK ("EXIT, returning NOPAGE_SIGBUS\n");
return NOPAGE_SIGBUS; /* Disallow mremap */
@@ -1702,7 +1824,7 @@ static struct page * via_mm_nopage (struct vm_area_struct * vma,
#ifndef VIA_NDEBUG
{
- unsigned long max_bufs = VIA_DMA_BUFFERS;
+ unsigned long max_bufs = chan->frag_number;
if (rd && wr) max_bufs *= 2;
/* via_dsp_mmap() should ensure this */
assert (pgoff < max_bufs);
@@ -1711,17 +1833,17 @@ static struct page * via_mm_nopage (struct vm_area_struct * vma,
/* if full-duplex (read+write) and we have two sets of bufs,
* then the playback buffers come first, sez soundcard.c */
- if (pgoff >= VIA_DMA_BUFFERS) {
- pgoff -= VIA_DMA_BUFFERS;
+ if (pgoff >= chan->page_number) {
+ pgoff -= chan->page_number;
chan = &card->ch_in;
} else if (!wr)
chan = &card->ch_in;
- assert ((((unsigned long)chan->sgbuf[pgoff].cpuaddr) % PAGE_SIZE) == 0);
+ assert ((((unsigned long)chan->pgtbl[pgoff].cpuaddr) % PAGE_SIZE) == 0);
- dmapage = virt_to_page (chan->sgbuf[pgoff].cpuaddr);
+ dmapage = virt_to_page (chan->pgtbl[pgoff].cpuaddr);
DPRINTK ("EXIT, returning page %p for cpuaddr %lXh\n",
- dmapage, (unsigned long) chan->sgbuf[pgoff].cpuaddr);
+ dmapage, (unsigned long) chan->pgtbl[pgoff].cpuaddr);
get_page (dmapage);
return dmapage;
}
@@ -1761,16 +1883,18 @@ static int via_dsp_mmap(struct file *file, struct vm_area_struct *vma)
vma->vm_end - vma->vm_start,
vma->vm_pgoff);
- assert (VIA_DMA_BUF_SIZE == PAGE_SIZE);
-
max_size = 0;
- if (file->f_mode & FMODE_READ) {
+ if (vma->vm_flags & VM_READ) {
rd = 1;
- max_size += (VIA_DMA_BUFFERS * VIA_DMA_BUF_SIZE);
+ via_chan_set_buffering(card, &card->ch_in, -1);
+ via_chan_buffer_init (card, &card->ch_in);
+ max_size += card->ch_in.page_number << PAGE_SHIFT;
}
- if (file->f_mode & FMODE_WRITE) {
+ if (vma->vm_flags & VM_WRITE) {
wr = 1;
- max_size += (VIA_DMA_BUFFERS * VIA_DMA_BUF_SIZE);
+ via_chan_set_buffering(card, &card->ch_out, -1);
+ via_chan_buffer_init (card, &card->ch_out);
+ max_size += card->ch_out.page_number << PAGE_SHIFT;
}
start = vma->vm_start;
@@ -1802,10 +1926,9 @@ static int via_dsp_mmap(struct file *file, struct vm_area_struct *vma)
rc = 0;
out:
- DPRINTK("EXIT, returning %d\n", rc);
+ DPRINTK ("EXIT, returning %d\n", rc);
return rc;
}
-#endif /* VIA_SUPPORT_MMAP */
static ssize_t via_dsp_do_read (struct via_info *card,
@@ -1831,13 +1954,13 @@ handle_one_block:
*/
n = chan->sw_ptr;
- /* n_bufs represents the number of buffers waiting
+ /* n_frags represents the number of fragments waiting
* to be copied to userland. sleep until at least
* one buffer has been read from the audio hardware.
*/
- tmp = atomic_read (&chan->n_bufs);
+ tmp = atomic_read (&chan->n_frags);
assert (tmp >= 0);
- assert (tmp <= VIA_DMA_BUFFERS);
+ assert (tmp <= chan->frag_number);
while (tmp == 0) {
if (nonblock || !chan->is_active)
return -EAGAIN;
@@ -1848,18 +1971,18 @@ handle_one_block:
if (signal_pending (current))
return -ERESTARTSYS;
- tmp = atomic_read (&chan->n_bufs);
+ tmp = atomic_read (&chan->n_frags);
}
/* Now that we have a buffer we can read from, send
* as much as sample data possible to userspace.
*/
- while ((count > 0) && (chan->slop_len < VIA_DMA_BUF_SIZE)) {
- size_t slop_left = VIA_DMA_BUF_SIZE - chan->slop_len;
+ while ((count > 0) && (chan->slop_len < chan->frag_size)) {
+ size_t slop_left = chan->frag_size - chan->slop_len;
size = (count < slop_left) ? count : slop_left;
if (copy_to_user (userbuf,
- chan->sgbuf[n].cpuaddr + chan->slop_len,
+ chan->pgtbl[n / (PAGE_SIZE / chan->frag_size)].cpuaddr + n % (PAGE_SIZE / chan->frag_size) + chan->slop_len,
size))
return -EFAULT;
@@ -1871,7 +1994,7 @@ handle_one_block:
/* If we didn't copy the buffer completely to userspace,
* stop now.
*/
- if (chan->slop_len < VIA_DMA_BUF_SIZE)
+ if (chan->slop_len < chan->frag_size)
goto out;
/*
@@ -1882,20 +2005,20 @@ handle_one_block:
/* advance channel software pointer to point to
* the next buffer from which we will copy
*/
- if (chan->sw_ptr == (VIA_DMA_BUFFERS - 1))
+ if (chan->sw_ptr == (chan->frag_number - 1))
chan->sw_ptr = 0;
else
chan->sw_ptr++;
/* mark one less buffer waiting to be processed */
- assert (atomic_read (&chan->n_bufs) > 0);
- atomic_dec (&chan->n_bufs);
+ assert (atomic_read (&chan->n_frags) > 0);
+ atomic_dec (&chan->n_frags);
/* we are at a block boundary, there is no fragment data */
chan->slop_len = 0;
- DPRINTK("Flushed block %u, sw_ptr now %u, n_bufs now %d\n",
- n, chan->sw_ptr, atomic_read (&chan->n_bufs));
+ DPRINTK ("Flushed block %u, sw_ptr now %u, n_frags now %d\n",
+ n, chan->sw_ptr, atomic_read (&chan->n_frags));
DPRINTK ("regs==%02X %02X %02X %08X %08X %08X %08X\n",
inb (card->baseaddr + 0x00),
@@ -1941,12 +2064,18 @@ static ssize_t via_dsp_read(struct file *file, char *buffer, size_t count, loff_
goto out_up;
}
+ via_chan_set_buffering(card, &card->ch_in, -1);
+ rc = via_chan_buffer_init (card, &card->ch_in);
+
+ if (rc)
+ goto out_up;
+
rc = via_dsp_do_read (card, buffer, count, nonblock);
out_up:
up (&card->syscall_sem);
out:
- DPRINTK("EXIT, returning %ld\n",(long) rc);
+ DPRINTK ("EXIT, returning %ld\n",(long) rc);
return rc;
}
@@ -1966,40 +2095,40 @@ handle_one_block:
if (current->need_resched)
schedule ();
- /* grab current channel software pointer. In the case of
- * playback, this is pointing to the next buffer that
+ /* grab current channel fragment pointer. In the case of
+ * playback, this is pointing to the next fragment that
* should receive data from userland.
*/
n = chan->sw_ptr;
- /* n_bufs represents the number of buffers remaining
+ /* n_frags represents the number of fragments remaining
* to be filled by userspace. Sleep until
- * at least one buffer is available for our use.
+ * at least one fragment is available for our use.
*/
- tmp = atomic_read (&chan->n_bufs);
+ tmp = atomic_read (&chan->n_frags);
assert (tmp >= 0);
- assert (tmp <= VIA_DMA_BUFFERS);
+ assert (tmp <= chan->frag_number);
while (tmp == 0) {
if (nonblock || !chan->is_enabled)
return -EAGAIN;
- DPRINTK ("Sleeping on block %d, tmp==%d, ir==%d\n", n, tmp, chan->is_record);
+ DPRINTK ("Sleeping on page %d, tmp==%d, ir==%d\n", n, tmp, chan->is_record);
interruptible_sleep_on (&chan->wait);
if (signal_pending (current))
return -ERESTARTSYS;
- tmp = atomic_read (&chan->n_bufs);
+ tmp = atomic_read (&chan->n_frags);
}
- /* Now that we have a buffer we can write to, fill it up
+ /* Now that we have at least one fragment we can write to, fill the buffer
* as much as possible with data from userspace.
*/
- while ((count > 0) && (chan->slop_len < VIA_DMA_BUF_SIZE)) {
- size_t slop_left = VIA_DMA_BUF_SIZE - chan->slop_len;
+ while ((count > 0) && (chan->slop_len < chan->frag_size)) {
+ size_t slop_left = chan->frag_size - chan->slop_len;
size = (count < slop_left) ? count : slop_left;
- if (copy_from_user (chan->sgbuf[n].cpuaddr + chan->slop_len,
+ if (copy_from_user (chan->pgtbl[n / (PAGE_SIZE / chan->frag_size)].cpuaddr + (n % (PAGE_SIZE / chan->frag_size)) * chan->frag_size + chan->slop_len,
userbuf, size))
return -EFAULT;
@@ -2009,36 +2138,36 @@ handle_one_block:
}
/* If we didn't fill up the buffer with data, stop now.
- * Put a 'stop' marker in the DMA table too, to tell the
- * audio hardware to stop if it gets here.
- */
- if (chan->slop_len < VIA_DMA_BUF_SIZE) {
+ * Put a 'stop' marker in the DMA table too, to tell the
+ * audio hardware to stop if it gets here.
+ */
+ if (chan->slop_len < chan->frag_size) {
sgtable[n].count = cpu_to_le32 (chan->slop_len | VIA_EOL | VIA_STOP);
goto out;
}
/*
- * If we get to this point, we have filled a buffer with
- * audio data, flush the buffer to audio hardware.
- */
+ * If we get to this point, we have filled a buffer with
+ * audio data, flush the buffer to audio hardware.
+ */
/* Record the true size for the audio hardware to notice */
- if (n == (VIA_DMA_BUFFERS - 1))
- sgtable[n].count = cpu_to_le32 (VIA_DMA_BUF_SIZE | VIA_EOL);
- else
- sgtable[n].count = cpu_to_le32 (VIA_DMA_BUF_SIZE | VIA_FLAG);
+ if (n == (chan->frag_number - 1))
+ sgtable[n].count = cpu_to_le32 (chan->frag_size | VIA_EOL);
+ else
+ sgtable[n].count = cpu_to_le32 (chan->frag_size | VIA_FLAG);
/* advance channel software pointer to point to
* the next buffer we will fill with data
*/
- if (chan->sw_ptr == (VIA_DMA_BUFFERS - 1))
+ if (chan->sw_ptr == (chan->frag_number - 1))
chan->sw_ptr = 0;
else
chan->sw_ptr++;
/* mark one less buffer as being available for userspace consumption */
- assert (atomic_read (&chan->n_bufs) > 0);
- atomic_dec (&chan->n_bufs);
+ assert (atomic_read (&chan->n_frags) > 0);
+ atomic_dec (&chan->n_frags);
/* we are at a block boundary, there is no fragment data */
chan->slop_len = 0;
@@ -2046,8 +2175,8 @@ handle_one_block:
/* if SGD has not yet been started, start it */
via_chan_maybe_start (chan);
- DPRINTK("Flushed block %u, sw_ptr now %u, n_bufs now %d\n",
- n, chan->sw_ptr, atomic_read (&chan->n_bufs));
+ DPRINTK ("Flushed block %u, sw_ptr now %u, n_frags now %d\n",
+ n, chan->sw_ptr, atomic_read (&chan->n_frags));
DPRINTK ("regs==%02X %02X %02X %08X %08X %08X %08X\n",
inb (card->baseaddr + 0x00),
@@ -2093,12 +2222,18 @@ static ssize_t via_dsp_write(struct file *file, const char *buffer, size_t count
goto out_up;
}
+ via_chan_set_buffering(card, &card->ch_out, -1);
+ rc = via_chan_buffer_init (card, &card->ch_out);
+
+ if (rc)
+ goto out_up;
+
rc = via_dsp_do_write (card, buffer, count, nonblock);
out_up:
up (&card->syscall_sem);
out:
- DPRINTK("EXIT, returning %ld\n",(long) rc);
+ DPRINTK ("EXIT, returning %ld\n",(long) rc);
return rc;
}
@@ -2117,23 +2252,27 @@ static unsigned int via_dsp_poll(struct file *file, struct poll_table_struct *wa
rd = (file->f_mode & FMODE_READ);
wr = (file->f_mode & FMODE_WRITE);
- if (wr && (atomic_read (&card->ch_out.n_bufs) == 0)) {
+ if (wr && (atomic_read (&card->ch_out.n_frags) == 0)) {
assert (card->ch_out.is_active);
poll_wait(file, &card->ch_out.wait, wait);
}
if (rd) {
/* XXX is it ok, spec-wise, to start DMA here? */
+ if (!card->ch_in.is_active) {
+ via_chan_set_buffering(card, &card->ch_in, -1);
+ via_chan_buffer_init(card, &card->ch_in);
+ }
via_chan_maybe_start (&card->ch_in);
- if (atomic_read (&card->ch_in.n_bufs) == 0)
+ if (atomic_read (&card->ch_in.n_frags) == 0)
poll_wait(file, &card->ch_in.wait, wait);
}
- if (wr && (atomic_read (&card->ch_out.n_bufs) > 0))
+ if (wr && ((atomic_read (&card->ch_out.n_frags) > 0) || !card->ch_out.is_active))
mask |= POLLOUT | POLLWRNORM;
- if (rd && (atomic_read (&card->ch_in.n_bufs) > 0))
+ if (rd && (atomic_read (&card->ch_in.n_frags) > 0))
mask |= POLLIN | POLLRDNORM;
- DPRINTK("EXIT, returning %u\n", mask);
+ DPRINTK ("EXIT, returning %u\n", mask);
return mask;
}
@@ -2158,12 +2297,12 @@ static int via_dsp_drain_playback (struct via_info *card,
if (chan->slop_len > 0)
via_chan_flush_frag (chan);
- if (atomic_read (&chan->n_bufs) == VIA_DMA_BUFFERS)
+ if (atomic_read (&chan->n_frags) == chan->frag_number)
goto out;
via_chan_maybe_start (chan);
- while (atomic_read (&chan->n_bufs) < VIA_DMA_BUFFERS) {
+ while (atomic_read (&chan->n_frags) < chan->frag_number) {
if (nonblock) {
DPRINTK ("EXIT, returning -EAGAIN\n");
return -EAGAIN;
@@ -2178,7 +2317,7 @@ static int via_dsp_drain_playback (struct via_info *card,
pci_read_config_byte (card->pdev, 0x43, &r43);
pci_read_config_byte (card->pdev, 0x44, &r44);
pci_read_config_byte (card->pdev, 0x48, &r48);
- DPRINTK("PCI config: %02X %02X %02X %02X %02X %02X\n",
+ DPRINTK ("PCI config: %02X %02X %02X %02X %02X %02X\n",
r40,r41,r42,r43,r44,r48);
DPRINTK ("regs==%02X %02X %02X %08X %08X %08X %08X\n",
@@ -2195,7 +2334,7 @@ static int via_dsp_drain_playback (struct via_info *card,
printk (KERN_ERR "sleeping but not active\n");
#endif
- DPRINTK ("sleeping, nbufs=%d\n", atomic_read (&chan->n_bufs));
+ DPRINTK ("sleeping, nbufs=%d\n", atomic_read (&chan->n_frags));
interruptible_sleep_on (&chan->wait);
if (signal_pending (current)) {
@@ -2213,7 +2352,7 @@ static int via_dsp_drain_playback (struct via_info *card,
pci_read_config_byte (card->pdev, 0x43, &r43);
pci_read_config_byte (card->pdev, 0x44, &r44);
pci_read_config_byte (card->pdev, 0x48, &r48);
- DPRINTK("PCI config: %02X %02X %02X %02X %02X %02X\n",
+ DPRINTK ("PCI config: %02X %02X %02X %02X %02X %02X\n",
r40,r41,r42,r43,r44,r48);
DPRINTK ("regs==%02X %02X %02X %08X %08X %08X %08X\n",
@@ -2225,7 +2364,7 @@ static int via_dsp_drain_playback (struct via_info *card,
inl (card->baseaddr + 0x80),
inl (card->baseaddr + 0x84));
- DPRINTK ("final nbufs=%d\n", atomic_read (&chan->n_bufs));
+ DPRINTK ("final nbufs=%d\n", atomic_read (&chan->n_frags));
}
#endif
@@ -2252,21 +2391,23 @@ static int via_dsp_ioctl_space (struct via_info *card,
{
audio_buf_info info;
- info.fragstotal = VIA_DMA_BUFFERS;
- info.fragsize = VIA_DMA_BUF_SIZE;
+ via_chan_set_buffering(card, chan, -1);
+
+ info.fragstotal = chan->frag_number;
+ info.fragsize = chan->frag_size;
/* number of full fragments we can read/write without blocking */
- info.fragments = atomic_read (&chan->n_bufs);
+ info.fragments = atomic_read (&chan->n_frags);
- if ((chan->slop_len > 0) && (info.fragments > 0))
+ if ((chan->slop_len % chan->frag_size > 0) && (info.fragments > 0))
info.fragments--;
/* number of bytes that can be read or written immediately
* without blocking.
*/
- info.bytes = (info.fragments * VIA_DMA_BUF_SIZE);
- if (chan->slop_len > 0)
- info.bytes += VIA_DMA_BUF_SIZE - chan->slop_len;
+ info.bytes = (info.fragments * chan->frag_size);
+ if (chan->slop_len % chan->frag_size > 0)
+ info.bytes += chan->frag_size - (chan->slop_len % chan->frag_size);
DPRINTK ("EXIT, returning fragstotal=%d, fragsize=%d, fragments=%d, bytes=%d\n",
info.fragstotal,
@@ -2305,8 +2446,8 @@ static int via_dsp_ioctl_ptr (struct via_info *card,
if (chan->is_active) {
unsigned long extra;
- info.ptr = atomic_read (&chan->hw_ptr) * VIA_DMA_BUF_SIZE;
- extra = VIA_DMA_BUF_SIZE - inl (chan->iobase + VIA_BASE0_PCM_OUT_BLOCK_COUNT);
+ info.ptr = atomic_read (&chan->hw_ptr) * chan->frag_size;
+ extra = chan->frag_size - inl (chan->iobase + VIA_PCM_BLOCK_COUNT);
info.ptr += extra;
info.bytes += extra;
} else {
@@ -2386,13 +2527,13 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
/* OSS API version. XXX unverified */
case OSS_GETVERSION:
- DPRINTK("ioctl OSS_GETVERSION, EXIT, returning SOUND_VERSION\n");
+ DPRINTK ("ioctl OSS_GETVERSION, EXIT, returning SOUND_VERSION\n");
rc = put_user (SOUND_VERSION, (int *)arg);
break;
/* list of supported PCM data formats */
case SNDCTL_DSP_GETFMTS:
- DPRINTK("DSP_GETFMTS, EXIT, returning AFMT U8|S16_LE\n");
+ DPRINTK ("DSP_GETFMTS, EXIT, returning AFMT U8|S16_LE\n");
rc = put_user (AFMT_U8 | AFMT_S16_LE, (int *)arg);
break;
@@ -2402,20 +2543,19 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
rc = -EFAULT;
break;
}
- DPRINTK("DSP_SETFMT, val==%d\n", val);
+ DPRINTK ("DSP_SETFMT, val==%d\n", val);
if (val != AFMT_QUERY) {
rc = 0;
- if (rc == 0 && rd)
+ if (rd)
rc = via_chan_set_fmt (card, &card->ch_in, val);
- if (rc == 0 && wr)
+
+ if (rc >= 0 && wr)
rc = via_chan_set_fmt (card, &card->ch_out, val);
- if (rc <= 0) {
- if (rc == 0)
- rc = -EINVAL;
+ if (rc < 0)
break;
- }
+
val = rc;
} else {
if ((rd && (card->ch_in.pcm_fmt & VIA_PCM_FMT_16BIT)) ||
@@ -2424,7 +2564,7 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
else
val = AFMT_U8;
}
- DPRINTK("SETFMT EXIT, returning %d\n", val);
+ DPRINTK ("SETFMT EXIT, returning %d\n", val);
rc = put_user (val, (int *)arg);
break;
@@ -2434,18 +2574,19 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
rc = -EFAULT;
break;
}
- DPRINTK("DSP_CHANNELS, val==%d\n", val);
+ DPRINTK ("DSP_CHANNELS, val==%d\n", val);
if (val != 0) {
rc = 0;
- if (rc == 0 && rd)
+
+ if (rd)
rc = via_chan_set_stereo (card, &card->ch_in, val);
- if (rc == 0 && wr)
+
+ if (rc >= 0 && wr)
rc = via_chan_set_stereo (card, &card->ch_out, val);
- if (rc <= 0) {
- if (rc == 0)
- rc = -EINVAL;
+
+ if (rc < 0)
break;
- }
+
val = rc;
} else {
if ((rd && (card->ch_in.pcm_fmt & VIA_PCM_FMT_STEREO)) ||
@@ -2454,7 +2595,7 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
else
val = 1;
}
- DPRINTK("CHANNELS EXIT, returning %d\n", val);
+ DPRINTK ("CHANNELS EXIT, returning %d\n", val);
rc = put_user (val, (int *)arg);
break;
@@ -2464,21 +2605,21 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
rc = -EFAULT;
break;
}
- DPRINTK("DSP_STEREO, val==%d\n", val);
+ DPRINTK ("DSP_STEREO, val==%d\n", val);
rc = 0;
- if (rc == 0 && rd)
+ if (rd)
rc = via_chan_set_stereo (card, &card->ch_in, val ? 2 : 1);
- if (rc == 0 && wr)
+ if (rc >= 0 && wr)
rc = via_chan_set_stereo (card, &card->ch_out, val ? 2 : 1);
- if (rc <= 0) {
- if (rc == 0)
- rc = -EINVAL;
+ if (rc < 0)
break;
- }
- DPRINTK("STEREO EXIT, returning %d\n", val);
- rc = 0;
+
+ val = rc - 1;
+
+ DPRINTK ("STEREO EXIT, returning %d\n", val);
+ rc = put_user(val, (int *) arg);
break;
/* query or set sampling rate */
@@ -2487,7 +2628,7 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
rc = -EFAULT;
break;
}
- DPRINTK("DSP_SPEED, val==%d\n", val);
+ DPRINTK ("DSP_SPEED, val==%d\n", val);
if (val < 0) {
rc = -EINVAL;
break;
@@ -2495,16 +2636,14 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
if (val > 0) {
rc = 0;
- if (rc == 0 && rd)
+ if (rd)
rc = via_chan_set_speed (card, &card->ch_in, val);
- if (rc == 0 && wr)
+ if (rc >= 0 && wr)
rc = via_chan_set_speed (card, &card->ch_out, val);
- if (rc <= 0) {
- if (rc == 0)
- rc = -EINVAL;
+ if (rc < 0)
break;
- }
+
val = rc;
} else {
if (rd)
@@ -2514,7 +2653,7 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
else
val = 0;
}
- DPRINTK("SPEED EXIT, returning %d\n", val);
+ DPRINTK ("SPEED EXIT, returning %d\n", val);
rc = put_user (val, (int *)arg);
break;
@@ -2522,7 +2661,7 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
case SNDCTL_DSP_SYNC:
DPRINTK ("DSP_SYNC\n");
if (wr) {
- DPRINTK("SYNC EXIT (after calling via_dsp_drain_playback)\n");
+ DPRINTK ("SYNC EXIT (after calling via_dsp_drain_playback)\n");
rc = via_dsp_drain_playback (card, &card->ch_out, nonblock);
}
break;
@@ -2531,12 +2670,19 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
case SNDCTL_DSP_RESET:
DPRINTK ("DSP_RESET\n");
if (rd) {
- via_chan_clear (&card->ch_in);
+ via_chan_clear (card, &card->ch_in);
via_chan_pcm_fmt (&card->ch_in, 1);
+ card->ch_in.frag_number = 0;
+ card->ch_in.frag_size = 0;
+ atomic_set(&card->ch_in.n_frags, 0);
}
+
if (wr) {
- via_chan_clear (&card->ch_out);
+ via_chan_clear (card, &card->ch_out);
via_chan_pcm_fmt (&card->ch_out, 1);
+ card->ch_out.frag_number = 0;
+ card->ch_out.frag_size = 0;
+ atomic_set(&card->ch_out.n_frags, 0);
}
rc = 0;
@@ -2544,40 +2690,47 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
/* obtain bitmask of device capabilities, such as mmap, full duplex, etc. */
case SNDCTL_DSP_GETCAPS:
- DPRINTK("DSP_GETCAPS\n");
+ DPRINTK ("DSP_GETCAPS\n");
rc = put_user(VIA_DSP_CAP, (int *)arg);
break;
- /* obtain bitmask of device capabilities, such as mmap, full duplex, etc. */
+ /* obtain buffer fragment size */
case SNDCTL_DSP_GETBLKSIZE:
- DPRINTK("DSP_GETBLKSIZE\n");
- rc = put_user(VIA_DMA_BUF_SIZE, (int *)arg);
+ DPRINTK ("DSP_GETBLKSIZE\n");
+
+ if (rd) {
+ via_chan_set_buffering(card, &card->ch_in, -1);
+ rc = put_user(card->ch_in.frag_size, (int *)arg);
+ } else if (wr) {
+ via_chan_set_buffering(card, &card->ch_out, -1);
+ rc = put_user(card->ch_out.frag_size, (int *)arg);
+ }
break;
/* obtain information about input buffering */
case SNDCTL_DSP_GETISPACE:
- DPRINTK("DSP_GETISPACE\n");
+ DPRINTK ("DSP_GETISPACE\n");
if (rd)
rc = via_dsp_ioctl_space (card, &card->ch_in, (void*) arg);
break;
/* obtain information about output buffering */
case SNDCTL_DSP_GETOSPACE:
- DPRINTK("DSP_GETOSPACE\n");
+ DPRINTK ("DSP_GETOSPACE\n");
if (wr)
rc = via_dsp_ioctl_space (card, &card->ch_out, (void*) arg);
break;
/* obtain information about input hardware pointer */
case SNDCTL_DSP_GETIPTR:
- DPRINTK("DSP_GETIPTR\n");
+ DPRINTK ("DSP_GETIPTR\n");
if (rd)
rc = via_dsp_ioctl_ptr (card, &card->ch_in, (void*) arg);
break;
/* obtain information about output hardware pointer */
case SNDCTL_DSP_GETOPTR:
- DPRINTK("DSP_GETOPTR\n");
+ DPRINTK ("DSP_GETOPTR\n");
if (wr)
rc = via_dsp_ioctl_ptr (card, &card->ch_out, (void*) arg);
break;
@@ -2585,25 +2738,29 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
/* return number of bytes remaining to be played by DMA engine */
case SNDCTL_DSP_GETODELAY:
{
- DPRINTK("DSP_GETODELAY\n");
+ DPRINTK ("DSP_GETODELAY\n");
chan = &card->ch_out;
if (!wr)
break;
- val = VIA_DMA_BUFFERS - atomic_read (&chan->n_bufs);
+ if (chan->is_active) {
- if (val > 0) {
- val *= VIA_DMA_BUF_SIZE;
- val -= VIA_DMA_BUF_SIZE -
- inl (chan->iobase + VIA_BASE0_PCM_OUT_BLOCK_COUNT);
- }
- val += chan->slop_len;
+ val = chan->frag_number - atomic_read (&chan->n_frags);
- assert (val <= (VIA_DMA_BUF_SIZE * VIA_DMA_BUFFERS));
+ if (val > 0) {
+ val *= chan->frag_size;
+ val -= chan->frag_size -
+ inl (chan->iobase + VIA_PCM_BLOCK_COUNT);
+ }
+ val += chan->slop_len % chan->frag_size;
+ } else
+ val = 0;
- DPRINTK("GETODELAY EXIT, val = %d bytes\n", val);
+ assert (val <= (chan->frag_size * chan->frag_number));
+
+ DPRINTK ("GETODELAY EXIT, val = %d bytes\n", val);
rc = put_user (val, (int *)arg);
break;
}
@@ -2617,7 +2774,7 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
rc = -EFAULT;
break;
}
- DPRINTK("DSP_SETTRIGGER, rd=%d, wr=%d, act=%d/%d, en=%d/%d\n",
+ DPRINTK ("DSP_SETTRIGGER, rd=%d, wr=%d, act=%d/%d, en=%d/%d\n",
rd, wr, card->ch_in.is_active, card->ch_out.is_active,
card->ch_in.is_enabled, card->ch_out.is_enabled);
@@ -2625,6 +2782,7 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
if (rd)
rc = via_dsp_ioctl_trigger (&card->ch_in, val);
+
if (!rc && wr)
rc = via_dsp_ioctl_trigger (&card->ch_out, val);
@@ -2634,7 +2792,7 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
* with O_RDWR, this is mainly a no-op that always returns success.
*/
case SNDCTL_DSP_SETDUPLEX:
- DPRINTK("DSP_SETDUPLEX\n");
+ DPRINTK ("DSP_SETDUPLEX\n");
if (!rd || !wr)
break;
rc = 0;
@@ -2646,7 +2804,13 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
rc = -EFAULT;
break;
}
- DPRINTK("DSP_SETFRAGMENT, val==%d\n", val);
+ DPRINTK ("DSP_SETFRAGMENT, val==%d\n", val);
+
+ if (rd)
+ rc = via_chan_set_buffering(card, &card->ch_in, val);
+
+ if (wr)
+ rc = via_chan_set_buffering(card, &card->ch_out, val);
DPRINTK ("SNDCTL_DSP_SETFRAGMENT (fragshift==0x%04X (%d), maxfrags==0x%04X (%d))\n",
val & 0xFFFF,
@@ -2654,13 +2818,12 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
(val >> 16) & 0xFFFF,
(val >> 16) & 0xFFFF);
- /* just to shut up some programs */
rc = 0;
break;
/* inform device of an upcoming pause in input (or output). */
case SNDCTL_DSP_POST:
- DPRINTK("DSP_POST\n");
+ DPRINTK ("DSP_POST\n");
if (wr) {
if (card->ch_out.slop_len > 0)
via_chan_flush_frag (&card->ch_out);
@@ -2678,15 +2841,14 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
}
up (&card->syscall_sem);
- DPRINTK("EXIT, returning %d\n", rc);
+ DPRINTK ("EXIT, returning %d\n", rc);
return rc;
}
static int via_dsp_open (struct inode *inode, struct file *file)
{
- int rc, minor = MINOR(inode->i_rdev);
- int got_read_chan = 0;
+ int minor = MINOR(inode->i_rdev);
struct via_info *card;
struct pci_dev *pdev;
struct via_channel *chan;
@@ -2733,17 +2895,13 @@ match:
}
file->private_data = card;
- DPRINTK("file->f_mode == 0x%x\n", file->f_mode);
+ DPRINTK ("file->f_mode == 0x%x\n", file->f_mode);
/* handle input from analog source */
if (file->f_mode & FMODE_READ) {
chan = &card->ch_in;
- rc = via_chan_init (card, chan);
- if (rc)
- goto err_out;
-
- got_read_chan = 1;
+ via_chan_init (card, chan);
/* why is this forced to 16-bit stereo in all drivers? */
chan->pcm_fmt = VIA_PCM_FMT_16BIT | VIA_PCM_FMT_STEREO;
@@ -2756,30 +2914,28 @@ match:
if (file->f_mode & FMODE_WRITE) {
chan = &card->ch_out;
- rc = via_chan_init (card, chan);
- if (rc)
- goto err_out_read_chan;
+ via_chan_init (card, chan);
- if ((minor & 0xf) == SND_DEV_DSP16) {
- chan->pcm_fmt |= VIA_PCM_FMT_16BIT;
- via_set_rate (&card->ac97, chan, 44100);
+ if (file->f_mode & FMODE_READ) {
+ /* if in duplex mode make the recording and playback channels
+ have the same settings */
+ chan->pcm_fmt = VIA_PCM_FMT_16BIT | VIA_PCM_FMT_STEREO;
+ via_chan_pcm_fmt (chan, 0);
+ via_set_rate (&card->ac97, chan, 44100);
} else {
- via_set_rate (&card->ac97, chan, 8000);
+ if ((minor & 0xf) == SND_DEV_DSP16) {
+ chan->pcm_fmt = VIA_PCM_FMT_16BIT;
+ via_chan_pcm_fmt (chan, 0);
+ via_set_rate (&card->ac97, chan, 44100);
+ } else {
+ via_chan_pcm_fmt (chan, 0);
+ via_set_rate (&card->ac97, chan, 8000);
+ }
}
-
- via_chan_pcm_fmt (chan, 0);
}
DPRINTK ("EXIT, returning 0\n");
return 0;
-
-err_out_read_chan:
- if (got_read_chan)
- via_chan_free (card, &card->ch_in);
-err_out:
- up (&card->open_sem);
- DPRINTK("ERROR EXIT, returning %d\n", rc);
- return rc;
}
@@ -2807,15 +2963,18 @@ static int via_dsp_release(struct inode *inode, struct file *file)
printk (KERN_DEBUG "via_audio: ignoring drain playback error %d\n", rc);
via_chan_free (card, &card->ch_out);
+ via_chan_buffer_free(card, &card->ch_out);
}
- if (file->f_mode & FMODE_READ)
+ if (file->f_mode & FMODE_READ) {
via_chan_free (card, &card->ch_in);
+ via_chan_buffer_free (card, &card->ch_in);
+ }
up (&card->syscall_sem);
up (&card->open_sem);
- DPRINTK("EXIT, returning 0\n");
+ DPRINTK ("EXIT, returning 0\n");
return 0;
}
@@ -2934,9 +3093,9 @@ static int __init via_init_one (struct pci_dev *pdev, const struct pci_device_id
tmp &= 0xF0;
tmp |= pdev->irq;
pci_write_config_byte (pdev, 0x3C, tmp);
- DPRINTK("new 0x3c==0x%02x\n", tmp);
+ DPRINTK ("new 0x3c==0x%02x\n", tmp);
} else {
- DPRINTK("IRQ reg 0x3c==0x%02x, irq==%d\n",
+ DPRINTK ("IRQ reg 0x3c==0x%02x, irq==%d\n",
tmp, tmp & 0x0F);
}
@@ -3036,12 +3195,12 @@ static int __init init_via82cxxx_audio(void)
static void __exit cleanup_via82cxxx_audio(void)
{
- DPRINTK("ENTER\n");
+ DPRINTK ("ENTER\n");
pci_unregister_driver (&via_driver);
via_cleanup_proc ();
- DPRINTK("EXIT\n");
+ DPRINTK ("EXIT\n");
}
@@ -3133,7 +3292,7 @@ static int via_info_read_proc (char *page, char **start, off_t off,
);
- DPRINTK("EXIT, returning %d\n", len);
+ DPRINTK ("EXIT, returning %d\n", len);
return len;
#undef YN
diff --git a/drivers/sound/ymfpci.c b/drivers/sound/ymfpci.c
index a8cdc58f2..9670951f8 100644
--- a/drivers/sound/ymfpci.c
+++ b/drivers/sound/ymfpci.c
@@ -24,19 +24,28 @@
*
* TODO:
* - Use P44Slot for 44.1 playback.
- * - Capture and duplex
* - 96KHz playback for DVD - use pitch of 2.0.
* - uLaw for Sun apps.
+ * : Alan says firmly "no software format conversion in kernel".
* - Retain DMA buffer on close, do not wait the end of frame.
* - Cleanup
- * ? merge ymf_pcm and state
- * ? pcm interrupt no pointer
* ? underused structure members
* - Remove remaining P3 tags (debug messages).
* - Resolve XXX tagged questions.
* - Cannot play 5133Hz.
+ * - 2001/01/07 Consider if we can remove voice_lock, like so:
+ * : Allocate/deallocate voices in open/close under semafore.
+ * : We access voices in interrupt, that only for pcms that open.
+ * voice_lock around playback_prepare closes interrupts for insane duration.
+ * - Revisit the way voice_alloc is done - too confusing, overcomplicated.
+ * Should support various channel types, however.
+ * - Remove prog_dmabuf from read/write, leave it in open.
+ * - 2001/01/07 Replace the OPL3 part of CONFIG_SOUND_YMFPCI_LEGACY code with
+ * native synthesizer through a playback slot.
+ * - Use new 2.3.x cache coherent PCI DMA routines instead of virt_to_bus.
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/ioport.h>
@@ -50,19 +59,19 @@
#include <asm/dma.h>
#include <asm/uaccess.h>
+#ifdef CONFIG_SOUND_YMFPCI_LEGACY
+# include "sound_config.h"
+# include "mpu401.h"
+#endif
#include "ymfpci.h"
-#define snd_magic_cast(t, p, err) ((t *)(p))
-
-/* Channels, such as play and record. I do only play a.t.m. XXX */
-#define NR_HW_CH 1
-
-static int ymf_playback_trigger(ymfpci_t *codec, ymfpci_pcm_t *ypcm, int cmd);
-static int ymfpci_voice_alloc(ymfpci_t *codec, ymfpci_voice_type_t type,
- int pair, ymfpci_voice_t **rvoice);
-static int ymfpci_voice_free(ymfpci_t *codec, ymfpci_voice_t *pvoice);
-static int ymf_playback_prepare(ymfpci_t *codec, struct ymf_state *state);
-static int ymf_state_alloc(ymfpci_t *unit, int nvirt);
+static int ymf_playback_trigger(ymfpci_t *codec, struct ymf_pcm *ypcm, int cmd);
+static void ymf_capture_trigger(ymfpci_t *unit, struct ymf_pcm *ypcm, int cmd);
+static void ymfpci_voice_free(ymfpci_t *codec, ymfpci_voice_t *pvoice);
+static int ymf_capture_alloc(struct ymf_unit *unit, int *pbank);
+static int ymf_playback_prepare(struct ymf_state *state);
+static int ymf_capture_prepare(struct ymf_state *state);
+static struct ymf_state *ymf_state_alloc(ymfpci_t *unit);
static LIST_HEAD(ymf_devs);
@@ -87,7 +96,7 @@ MODULE_DEVICE_TABLE(pci, ymf_id_tbl);
/*
* Mindlessly copied from cs46xx XXX
*/
-extern __inline__ unsigned ld2(unsigned int x)
+static inline unsigned ld2(unsigned int x)
{
unsigned r = 0;
@@ -281,18 +290,13 @@ static void ymf_pcm_update_shift(struct ymf_pcm_format *f)
f->shift++;
}
-/*
- * Whole OSS-style DMA machinery is taken from cs46xx.
- */
-
/* Are you sure 32K is not too much? See if mpg123 skips on loaded systems. */
#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT)
#define DMABUF_MINORDER 1
/* allocate DMA buffer, playback and recording buffer should be allocated seperately */
-static int alloc_dmabuf(struct ymf_state *state)
+static int alloc_dmabuf(struct ymf_dmabuf *dmabuf)
{
- struct ymf_dmabuf *dmabuf = &state->dmabuf;
void *rawbuf = NULL;
int order;
struct page * map, * mapend;
@@ -323,9 +327,8 @@ static int alloc_dmabuf(struct ymf_state *state)
}
/* free DMA buffer */
-static void dealloc_dmabuf(struct ymf_state *state)
+static void dealloc_dmabuf(struct ymf_dmabuf *dmabuf)
{
- struct ymf_dmabuf *dmabuf = &state->dmabuf;
struct page *map, *mapend;
if (dmabuf->rawbuf) {
@@ -339,9 +342,9 @@ static void dealloc_dmabuf(struct ymf_state *state)
dmabuf->mapped = dmabuf->ready = 0;
}
-static int prog_dmabuf(struct ymf_state *state, unsigned rec)
+static int prog_dmabuf(struct ymf_state *state, int rec)
{
- struct ymf_dmabuf *dmabuf = &state->dmabuf;
+ struct ymf_dmabuf *dmabuf;
int w_16;
unsigned bytepersec;
unsigned bufsize;
@@ -350,6 +353,7 @@ static int prog_dmabuf(struct ymf_state *state, unsigned rec)
int ret;
w_16 = ymf_pcm_format_width(state->format.format) == 16;
+ dmabuf = rec ? &state->rpcm.dmabuf : &state->wpcm.dmabuf;
spin_lock_irqsave(&state->unit->reg_lock, flags);
dmabuf->hwptr = dmabuf->swptr = 0;
@@ -359,7 +363,7 @@ static int prog_dmabuf(struct ymf_state *state, unsigned rec)
/* allocate DMA buffer if not allocated yet */
if (!dmabuf->rawbuf)
- if ((ret = alloc_dmabuf(state)))
+ if ((ret = alloc_dmabuf(dmabuf)))
return ret;
bytepersec = state->format.rate << state->format.shift;
@@ -383,7 +387,6 @@ static int prog_dmabuf(struct ymf_state *state, unsigned rec)
dmabuf->numfrag = bufsize >> dmabuf->fragshift;
}
dmabuf->fragsize = 1 << dmabuf->fragshift;
- dmabuf->fragsamples = dmabuf->fragsize >> state->format.shift;
dmabuf->dmasize = dmabuf->numfrag << dmabuf->fragshift;
/*
@@ -414,15 +417,20 @@ static int prog_dmabuf(struct ymf_state *state, unsigned rec)
* Now set up the ring
*/
- spin_lock_irqsave(&state->unit->reg_lock, flags);
+ /* XXX ret = rec? cap_pre(): pbk_pre(); */
+ spin_lock_irqsave(&state->unit->voice_lock, flags);
if (rec) {
- /* ymf_rec_setup(state); */
+ if ((ret = ymf_capture_prepare(state)) != 0) {
+ spin_unlock_irqrestore(&state->unit->voice_lock, flags);
+ return ret;
+ }
} else {
- if ((ret = ymf_playback_prepare(state->unit, state)) != 0) {
+ if ((ret = ymf_playback_prepare(state)) != 0) {
+ spin_unlock_irqrestore(&state->unit->voice_lock, flags);
return ret;
}
}
- spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ spin_unlock_irqrestore(&state->unit->voice_lock, flags);
/* set the ready flag for the dma buffer (this comment is not stupid) */
dmabuf->ready = 1;
@@ -439,9 +447,14 @@ static int prog_dmabuf(struct ymf_state *state, unsigned rec)
static void ymf_start_dac(struct ymf_state *state)
{
- ymf_playback_trigger(state->unit, &state->ypcm, 1);
+ ymf_playback_trigger(state->unit, &state->wpcm, 1);
}
+// static void ymf_start_adc(struct ymf_state *state)
+// {
+// ymf_capture_trigger(state->unit, &state->rpcm, 1);
+// }
+
/*
* Wait until output is drained.
* This does not kill the hardware for the sake of ioctls.
@@ -449,14 +462,14 @@ static void ymf_start_dac(struct ymf_state *state)
static void ymf_wait_dac(struct ymf_state *state)
{
struct ymf_unit *unit = state->unit;
- ymfpci_pcm_t *ypcm = &state->ypcm;
+ struct ymf_pcm *ypcm = &state->wpcm;
DECLARE_WAITQUEUE(waita, current);
unsigned long flags;
- add_wait_queue(&state->dmabuf.wait, &waita);
+ add_wait_queue(&ypcm->dmabuf.wait, &waita);
spin_lock_irqsave(&unit->reg_lock, flags);
- if (state->dmabuf.count != 0 && !state->ypcm.running) {
+ if (ypcm->dmabuf.count != 0 && !ypcm->running) {
ymf_playback_trigger(unit, ypcm, 1);
}
@@ -479,7 +492,7 @@ static void ymf_wait_dac(struct ymf_state *state)
spin_unlock_irqrestore(&unit->reg_lock, flags);
set_current_state(TASK_RUNNING);
- remove_wait_queue(&state->dmabuf.wait, &waita);
+ remove_wait_queue(&ypcm->dmabuf.wait, &waita);
/*
* This function may take up to 4 seconds to reach this point
@@ -487,6 +500,17 @@ static void ymf_wait_dac(struct ymf_state *state)
*/
}
+/* Can just stop, without wait. Or can we? */
+static void ymf_stop_adc(struct ymf_state *state)
+{
+ struct ymf_unit *unit = state->unit;
+ unsigned long flags;
+
+ spin_lock_irqsave(&unit->reg_lock, flags);
+ ymf_capture_trigger(unit, &state->rpcm, 0);
+ spin_unlock_irqrestore(&unit->reg_lock, flags);
+}
+
/*
* Hardware start management
*/
@@ -523,12 +547,11 @@ static void ymfpci_hw_stop(ymfpci_t *codec)
* Playback voice management
*/
-static int voice_alloc(ymfpci_t *codec, ymfpci_voice_type_t type, int pair, ymfpci_voice_t **rvoice)
+static int voice_alloc(ymfpci_t *codec, ymfpci_voice_type_t type, int pair, ymfpci_voice_t *rvoice[])
{
ymfpci_voice_t *voice, *voice2;
int idx;
-
- *rvoice = NULL;
+
for (idx = 0; idx < 64; idx += pair ? 2 : 1) {
voice = &codec->voices[idx];
voice2 = pair ? &codec->voices[idx+1] : NULL;
@@ -551,52 +574,29 @@ static int voice_alloc(ymfpci_t *codec, ymfpci_voice_type_t type, int pair, ymfp
break;
}
ymfpci_hw_start(codec);
- if (voice2)
+ rvoice[0] = voice;
+ if (voice2) {
ymfpci_hw_start(codec);
- *rvoice = voice;
+ rvoice[1] = voice2;
+ }
return 0;
}
- return -ENOMEM;
+ return -EBUSY; /* Your audio channel is open by someone else. */
}
-static int ymfpci_voice_alloc(ymfpci_t *codec, ymfpci_voice_type_t type,
- int pair, ymfpci_voice_t **rvoice)
+static void ymfpci_voice_free(ymfpci_t *unit, ymfpci_voice_t *pvoice)
{
- unsigned long flags;
- int result;
-
- spin_lock_irqsave(&codec->voice_lock, flags);
- for (;;) {
- result = voice_alloc(codec, type, pair, rvoice);
- if (result == 0 || type != YMFPCI_PCM)
- break;
- /* TODO: synth/midi voice deallocation */
- break;
- }
- spin_unlock_irqrestore(&codec->voice_lock, flags);
- return result;
-}
-
-static int ymfpci_voice_free(ymfpci_t *codec, ymfpci_voice_t *pvoice)
-{
- unsigned long flags;
-
- ymfpci_hw_stop(codec);
- spin_lock_irqsave(&codec->voice_lock, flags);
+ ymfpci_hw_stop(unit);
pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0;
pvoice->ypcm = NULL;
- pvoice->interrupt = NULL;
- spin_unlock_irqrestore(&codec->voice_lock, flags);
- return 0;
}
/*
- * PCM part
*/
static void ymf_pcm_interrupt(ymfpci_t *codec, ymfpci_voice_t *voice)
{
- ymfpci_pcm_t *ypcm;
+ struct ymf_pcm *ypcm;
int redzone;
int pos, delta, swptr;
int played, distance;
@@ -611,7 +611,7 @@ static void ymf_pcm_interrupt(ymfpci_t *codec, ymfpci_voice_t *voice)
ypcm->running = 0; // lock it
return;
}
- dmabuf = &state->dmabuf;
+ dmabuf = &ypcm->dmabuf;
spin_lock(&codec->reg_lock);
if (ypcm->running) {
/* P3 */ /** printk("ymfpci: %d, intr bank %d count %d start 0x%x:%x\n",
@@ -627,10 +627,9 @@ static void ymf_pcm_interrupt(ymfpci_t *codec, ymfpci_voice_t *voice)
pos = voice->bank[codec->active_bank].start;
pos <<= state->format.shift;
if (pos < 0 || pos >= dmabuf->dmasize) { /* ucode bug */
- printk(KERN_ERR
- "ymfpci%d: %d: runaway: hwptr %d dmasize %d\n",
+ printk(KERN_ERR "ymfpci%d: runaway voice %d: hwptr %d=>%d dmasize %d\n",
codec->dev_audio, voice->number,
- dmabuf->hwptr, dmabuf->dmasize);
+ dmabuf->hwptr, pos, dmabuf->dmasize);
pos = 0;
}
if (pos < dmabuf->hwptr) {
@@ -706,36 +705,66 @@ static void ymf_pcm_interrupt(ymfpci_t *codec, ymfpci_voice_t *voice)
spin_unlock(&codec->reg_lock);
}
-#if HAVE_RECORD
-static void ymfpci_pcm_capture_interrupt(snd_pcm_subchn_t *substream)
+static void ymf_cap_interrupt(ymfpci_t *unit, struct ymf_capture *cap)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, );
- ymfpci_t *codec = ypcm->codec;
- u32 pos, delta;
-
- spin_lock(&codec->reg_lock);
+ struct ymf_pcm *ypcm;
+ int redzone;
+ struct ymf_state *state;
+ struct ymf_dmabuf *dmabuf;
+ int pos, delta;
+ int cnt;
+
+ if ((ypcm = cap->ypcm) == NULL) {
+ return;
+ }
+ if ((state = ypcm->state) == NULL) {
+ ypcm->running = 0; // lock it
+ return;
+ }
+ dmabuf = &ypcm->dmabuf;
+ spin_lock(&unit->reg_lock);
if (ypcm->running) {
- pos = codec->bank_capture[ypcm->capture_bank_number][codec->active_bank]->start << ypcm->shift_offset;
- if (pos < ypcm->last_pos) // <-- dmabuf->hwptr
- delta = pos + (ypcm->buffer_size - ypcm->last_pos);
- else
- delta = pos - ypcm->last_pos;
- ypcm->frag_pos += delta;
- ypcm->last_pos = pos;
- while (ypcm->frag_pos >= ypcm->frag_size) {
- ypcm->frag_pos -= ypcm->frag_size;
- // printk("done - active_bank = 0x%x, start = 0x%x\n", codec->active_bank, voice->bank[codec->active_bank].start);
- spin_unlock(&codec->reg_lock);
- snd_pcm_transfer_done(substream);
- spin_lock(&codec->reg_lock);
+ redzone = ymf_calc_lend(state->format.rate);
+ redzone <<= (state->format.shift + 1);
+
+ pos = cap->bank[unit->active_bank].start;
+ // pos <<= state->format.shift;
+ if (pos < 0 || pos >= dmabuf->dmasize) { /* ucode bug */
+ printk(KERN_ERR "ymfpci%d: runaway capture %d: hwptr %d=>%d dmasize %d\n",
+ unit->dev_audio, ypcm->capture_bank_number,
+ dmabuf->hwptr, pos, dmabuf->dmasize);
+ pos = 0;
+ }
+ if (pos < dmabuf->hwptr) {
+ delta = dmabuf->dmasize - dmabuf->hwptr;
+ delta += pos;
+ } else {
+ delta = pos - dmabuf->hwptr;
+ }
+ dmabuf->hwptr = pos;
+
+ cnt = dmabuf->count;
+ cnt += delta;
+ if (cnt + redzone > dmabuf->dmasize) {
+ /* Overflow - bump swptr */
+ dmabuf->count = dmabuf->dmasize - redzone;
+ dmabuf->swptr = dmabuf->hwptr + redzone;
+ if (dmabuf->swptr >= dmabuf->dmasize) {
+ dmabuf->swptr -= dmabuf->dmasize;
+ }
+ } else {
+ dmabuf->count = cnt;
+ }
+
+ dmabuf->total_bytes += delta;
+ if (dmabuf->count) { /* && is_sleeping XXX */
+ wake_up(&dmabuf->wait);
}
}
- spin_unlock(&codec->reg_lock);
+ spin_unlock(&unit->reg_lock);
}
-#endif
-static int ymf_playback_trigger(ymfpci_t *codec, ymfpci_pcm_t *ypcm, int cmd)
+static int ymf_playback_trigger(ymfpci_t *codec, struct ymf_pcm *ypcm, int cmd)
{
if (ypcm->voices[0] == NULL) {
@@ -755,40 +784,29 @@ static int ymf_playback_trigger(ymfpci_t *codec, ymfpci_pcm_t *ypcm, int cmd)
return 0;
}
-#if HAVE_RECORD
-static int ymfpci_capture_trigger(void *private_data,
- snd_pcm_subchn_t * substream,
- int cmd)
+static void ymf_capture_trigger(ymfpci_t *codec, struct ymf_pcm *ypcm, int cmd)
{
- unsigned long flags;
- ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO);
- ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, substream->runtime->private_data, -ENXIO);
- int result = 0;
u32 tmp;
- spin_lock_irqsave(&codec->reg_lock, flags);
- if (cmd == SND_PCM_TRIGGER_GO) {
+ if (cmd != 0) {
tmp = ymfpci_readl(codec, YDSXGR_MAPOFREC) | (1 << ypcm->capture_bank_number);
ymfpci_writel(codec, YDSXGR_MAPOFREC, tmp);
ypcm->running = 1;
- } else if (cmd == SND_PCM_TRIGGER_STOP) {
+ } else {
tmp = ymfpci_readl(codec, YDSXGR_MAPOFREC) & ~(1 << ypcm->capture_bank_number);
ymfpci_writel(codec, YDSXGR_MAPOFREC, tmp);
ypcm->running = 0;
- } else {
- result = -EINVAL;
}
- spin_unlock_irqrestore(&codec->reg_lock, flags);
- return result;
}
-#endif
-static int ymfpci_pcm_voice_alloc(ymfpci_pcm_t *ypcm, int voices)
+static int ymfpci_pcm_voice_alloc(struct ymf_pcm *ypcm, int voices)
{
+ struct ymf_unit *unit;
int err;
+ unit = ypcm->state->unit;
if (ypcm->voices[1] != NULL && voices < 2) {
- ymfpci_voice_free(ypcm->codec, ypcm->voices[1]);
+ ymfpci_voice_free(unit, ypcm->voices[1]);
ypcm->voices[1] = NULL;
}
if (voices == 1 && ypcm->voices[0] != NULL)
@@ -797,18 +815,17 @@ static int ymfpci_pcm_voice_alloc(ymfpci_pcm_t *ypcm, int voices)
return 0; /* already allocated */
if (voices > 1) {
if (ypcm->voices[0] != NULL && ypcm->voices[1] == NULL) {
- ymfpci_voice_free(ypcm->codec, ypcm->voices[0]);
+ ymfpci_voice_free(unit, ypcm->voices[0]);
ypcm->voices[0] = NULL;
}
- }
- err = ymfpci_voice_alloc(ypcm->codec, YMFPCI_PCM, voices > 1, &ypcm->voices[0]);
- if (err < 0)
- return err;
- ypcm->voices[0]->ypcm = ypcm;
- ypcm->voices[0]->interrupt = ymf_pcm_interrupt;
- if (voices > 1) {
- ypcm->voices[1] = &ypcm->codec->voices[ypcm->voices[0]->number + 1];
+ if ((err = voice_alloc(unit, YMFPCI_PCM, 1, ypcm->voices)) < 0)
+ return err;
+ ypcm->voices[0]->ypcm = ypcm;
ypcm->voices[1]->ypcm = ypcm;
+ } else {
+ if ((err = voice_alloc(unit, YMFPCI_PCM, 0, ypcm->voices)) < 0)
+ return err;
+ ypcm->voices[0]->ypcm = ypcm;
}
return 0;
}
@@ -901,17 +918,32 @@ static void ymf_pcm_init_voice(ymfpci_voice_t *voice, int stereo,
}
/*
- * XXX Use new cache coherent PCI DMA routines instead of virt_to_bus.
+ * XXX Capture channel allocation is entirely fake at the moment.
+ * We use only one channel and mark it busy as required.
*/
-static int ymf_playback_prepare(ymfpci_t *codec, struct ymf_state *state)
+static int ymf_capture_alloc(struct ymf_unit *unit, int *pbank)
{
- ymfpci_pcm_t *ypcm = &state->ypcm;
+ struct ymf_capture *cap;
+ int cbank;
+
+ cbank = 1; /* Only ADC slot is used for now. */
+ cap = &unit->capture[cbank];
+ if (cap->use)
+ return -EBUSY;
+ cap->use = 1;
+ *pbank = cbank;
+ return 0;
+}
+
+static int ymf_playback_prepare(struct ymf_state *state)
+{
+ struct ymf_pcm *ypcm = &state->wpcm;
int err, nvoice;
if ((err = ymfpci_pcm_voice_alloc(ypcm, state->format.voices)) < 0) {
- /* Cannot be unless we leak voices in ymf_release! */
- printk(KERN_ERR "ymfpci%d: cannot allocate voice!\n",
- codec->dev_audio);
+ /* Somebody started 32 mpg123's in parallel? */
+ /* P3 */ printk("ymfpci%d: cannot allocate voice\n",
+ state->unit->dev_audio);
return err;
}
@@ -919,101 +951,76 @@ static int ymf_playback_prepare(ymfpci_t *codec, struct ymf_state *state)
ymf_pcm_init_voice(ypcm->voices[nvoice],
state->format.voices == 2, state->format.rate,
ymf_pcm_format_width(state->format.format) == 16,
- virt_to_bus(state->dmabuf.rawbuf), state->dmabuf.dmasize,
+ virt_to_bus(ypcm->dmabuf.rawbuf), ypcm->dmabuf.dmasize,
ypcm->spdif);
}
return 0;
}
-#if 0 /* old */
-static int ymfpci_capture_prepare(void *private_data,
- snd_pcm_subchn_t * substream)
+static int ymf_capture_prepare(struct ymf_state *state)
{
- ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, -ENXIO);
+ ymfpci_t *unit = state->unit;
+ struct ymf_pcm *ypcm = &state->rpcm;
ymfpci_capture_bank_t * bank;
- int nbank;
+ /* XXX This is confusing, gotta rename one of them banks... */
+ int nbank; /* flip-flop bank */
+ int cbank; /* input [super-]bank */
+ struct ymf_capture *cap;
u32 rate, format;
- ypcm->frag_size = snd_pcm_lib_transfer_fragment(substream);
- ypcm->buffer_size = snd_pcm_lib_transfer_size(substream);
- ypcm->frag_pos = 0;
- ypcm->last_pos = 0;
- ypcm->shift_offset = 0;
- rate = ((48000 * 4096) / runtime->format.rate) - 1;
+ if (ypcm->capture_bank_number == -1) {
+ if (ymf_capture_alloc(unit, &cbank) != 0)
+ return -EBUSY;
+
+ ypcm->capture_bank_number = cbank;
+
+ cap = &unit->capture[cbank];
+ cap->bank = unit->bank_capture[cbank][0];
+ cap->ypcm = ypcm;
+ ymfpci_hw_start(unit);
+ }
+
+ // ypcm->frag_size = snd_pcm_lib_transfer_fragment(substream);
+ // frag_size is replaced with nonfragged byte-aligned rolling buffer
+ rate = ((48000 * 4096) / state->format.rate) - 1;
format = 0;
- if (runtime->format.voices == 2)
+ if (state->format.voices == 2)
format |= 2;
- if (snd_pcm_format_width(runtime->format.format) == 8)
+ if (ymf_pcm_format_width(state->format.format) == 8)
format |= 1;
switch (ypcm->capture_bank_number) {
case 0:
- ymfpci_writel(codec, YDSXGR_RECFORMAT, format);
- ymfpci_writel(codec, YDSXGR_RECSLOTSR, rate);
+ ymfpci_writel(unit, YDSXGR_RECFORMAT, format);
+ ymfpci_writel(unit, YDSXGR_RECSLOTSR, rate);
break;
case 1:
- ymfpci_writel(codec, YDSXGR_ADCFORMAT, format);
- ymfpci_writel(codec, YDSXGR_ADCSLOTSR, rate);
+ ymfpci_writel(unit, YDSXGR_ADCFORMAT, format);
+ ymfpci_writel(unit, YDSXGR_ADCSLOTSR, rate);
break;
}
for (nbank = 0; nbank < 2; nbank++) {
- bank = codec->bank_capture[ypcm->capture_bank_number][nbank];
- bank->base = virt_to_bus(runtime->dma_area->buf);
- bank->loop_end = ypcm->buffer_size;
+ bank = unit->bank_capture[ypcm->capture_bank_number][nbank];
+ bank->base = virt_to_bus(ypcm->dmabuf.rawbuf);
+ // bank->loop_end = ypcm->dmabuf.dmasize >> state->format.shift;
+ bank->loop_end = ypcm->dmabuf.dmasize;
bank->start = 0;
bank->num_of_loops = 0;
}
- if (runtime->digital.dig_valid)
- /*runtime->digital.type == SND_PCM_DIG_AES_IEC958*/
- ymfpci_writew(codec, YDSXGR_SPDIFOUTSTATUS, runtime->digital.dig_status[0] |
- (runtime->digital.dig_status[1] << 8));
+#if 0 /* s/pdif */
+ if (state->digital.dig_valid)
+ /*state->digital.type == SND_PCM_DIG_AES_IEC958*/
+ ymfpci_writew(codec, YDSXGR_SPDIFOUTSTATUS,
+ state->digital.dig_status[0] | (state->digital.dig_status[1] << 8));
+#endif
return 0;
}
-static unsigned int ymfpci_playback_pointer(void *private_data,
- snd_pcm_subchn_t * substream)
-{
- ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, -ENXIO);
- ymfpci_voice_t *voice = ypcm->voices[0];
- unsigned long flags;
- unsigned int result;
-
- spin_lock_irqsave(&codec->reg_lock, flags);
- if (ypcm->running && voice)
- result = voice->bank[codec->active_bank].start << ypcm->shift_offset;
- else
- result = 0;
- spin_unlock_irqrestore(&codec->reg_lock, flags);
- return result;
-}
-
-static unsigned int ymfpci_capture_pointer(void *private_data,
- snd_pcm_subchn_t * substream)
-{
- ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, -ENXIO);
- unsigned long flags;
- unsigned int result;
-
- spin_lock_irqsave(&codec->reg_lock, flags);
- if (ypcm->running)
- result = codec->bank_capture[ypcm->capture_bank_number][codec->active_bank]->start << ypcm->shift_offset;
- else
- result = 0;
- spin_unlock_irqrestore(&codec->reg_lock, flags);
- return result;
-}
-#endif /* old */
-
void ymf_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
ymfpci_t *codec = dev_id;
u32 status, nvoice, mode;
- ymfpci_voice_t *voice;
+ struct ymf_voice *voice;
+ struct ymf_capture *cap;
status = ymfpci_readl(codec, YDSXGR_STATUS);
if (status & 0x80000000) {
@@ -1026,8 +1033,13 @@ void ymf_interrupt(int irq, void *dev_id, struct pt_regs *regs)
spin_lock(&codec->voice_lock);
for (nvoice = 0; nvoice < 64; nvoice++) {
voice = &codec->voices[nvoice];
- if (voice->interrupt)
- voice->interrupt(codec, voice);
+ if (voice->use)
+ ymf_pcm_interrupt(codec, voice);
+ }
+ for (nvoice = 0; nvoice < 5; nvoice++) {
+ cap = &codec->capture[nvoice];
+ if (cap->use)
+ ymf_cap_interrupt(codec, cap);
}
spin_unlock(&codec->voice_lock);
}
@@ -1039,22 +1051,32 @@ void ymf_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
}
-static void ymf_pcm_free_substream(ymfpci_pcm_t *ypcm)
+static void ymf_pcm_free_substream(struct ymf_pcm *ypcm)
{
- ymfpci_t *codec;
+ unsigned long flags;
+ struct ymf_unit *unit;
+
+ unit = ypcm->state->unit;
- if (ypcm) {
- codec = ypcm->codec;
+ if (ypcm->type == PLAYBACK_VOICE) {
+ spin_lock_irqsave(&unit->voice_lock, flags);
if (ypcm->voices[1])
- ymfpci_voice_free(codec, ypcm->voices[1]);
+ ymfpci_voice_free(unit, ypcm->voices[1]);
if (ypcm->voices[0])
- ymfpci_voice_free(codec, ypcm->voices[0]);
+ ymfpci_voice_free(unit, ypcm->voices[0]);
+ spin_unlock_irqrestore(&unit->voice_lock, flags);
+ } else {
+ if (ypcm->capture_bank_number != -1) {
+ unit->capture[ypcm->capture_bank_number].use = 0;
+ ypcm->capture_bank_number = -1;
+ ymfpci_hw_stop(unit);
+ }
}
}
-static int ymf_state_alloc(ymfpci_t *unit, int nvirt)
+static struct ymf_state *ymf_state_alloc(ymfpci_t *unit)
{
- ymfpci_pcm_t *ypcm;
+ struct ymf_pcm *ypcm;
struct ymf_state *state;
if ((state = kmalloc(sizeof(struct ymf_state), GFP_KERNEL)) == NULL) {
@@ -1062,61 +1084,31 @@ static int ymf_state_alloc(ymfpci_t *unit, int nvirt)
}
memset(state, 0, sizeof(struct ymf_state));
- init_waitqueue_head(&state->dmabuf.wait);
-
- ypcm = &state->ypcm;
+ ypcm = &state->wpcm;
ypcm->state = state;
- ypcm->codec = unit;
ypcm->type = PLAYBACK_VOICE;
+ ypcm->capture_bank_number = -1;
+ init_waitqueue_head(&ypcm->dmabuf.wait);
+
+ ypcm = &state->rpcm;
+ ypcm->state = state;
+ ypcm->type = CAPTURE_AC97;
+ ypcm->capture_bank_number = -1;
+ init_waitqueue_head(&ypcm->dmabuf.wait);
state->unit = unit;
- state->virt = nvirt;
state->format.format = AFMT_U8;
state->format.rate = 8000;
state->format.voices = 1;
ymf_pcm_update_shift(&state->format);
- unit->states[nvirt] = state;
- return 0;
+ return state;
out0:
- return -ENOMEM;
+ return NULL;
}
-#if HAVE_RECORD
-
-static int ymfpci_capture_open(void *private_data,
- snd_pcm_subchn_t * substream,
- u32 capture_bank_number)
-{
- ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ymfpci_pcm_t *ypcm;
- int err;
-
- if ((err = snd_pcm_dma_alloc(substream, !capture_bank_number ? codec->dma2ptr : codec->dma3ptr, "YMFPCI - ADC")) < 0)
- return err;
- ypcm = snd_magic_kcalloc(ymfpci_pcm_t, 0, GFP_KERNEL);
- if (ypcm == NULL) {
- snd_pcm_dma_free(substream);
- return -ENOMEM;
- }
- ypcm->codec = codec;
- ypcm->type = capture_bank_number + CAPTURE_REC;
- ypcm->substream = substream;
- ypcm->capture_bank_number = capture_bank_number;
- codec->capture_substream[capture_bank_number] = substream;
- runtime->hw = &ymfpci_capture;
- snd_pcm_set_mixer(substream, codec->mixer->device, codec->ac97->me_capture);
- runtime->private_data = ypcm;
- runtime->private_free = ymfpci_pcm_free_substream;
- ymfpci_hw_start(codec);
- return 0;
-}
-
-#endif /* old */
-
/* AES/IEC958 channel status bits */
#define SND_PCM_AES0_PROFESSIONAL (1<<0) /* 0 = consumer, 1 = professional */
#define SND_PCM_AES0_NONAUDIO (1<<1) /* 0 = audio, 1 = non-audio */
@@ -1202,24 +1194,6 @@ static int ymfpci_capture_open(void *private_data,
#define SND_PCM_AES3_CON_CLOCK_50PPM (1<<4) /* 50 ppm */
#define SND_PCM_AES3_CON_CLOCK_VARIABLE (2<<4) /* variable pitch */
-#if HAVE_RECORD /* old */
-
-static int ymfpci_capture_close(void *private_data,
- snd_pcm_subchn_t * substream)
-{
- ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, -ENXIO);
-
- if (ypcm != NULL) {
- codec->capture_substream[ypcm->capture_bank_number] = NULL;
- ymfpci_hw_stop(codec);
- }
- snd_pcm_dma_free(substream);
- return 0;
-}
-#endif
-
/*
* User interface
*/
@@ -1229,21 +1203,21 @@ static loff_t ymf_llseek(struct file *file, loff_t offset, int origin)
return -ESPIPE;
}
-/* in this loop, dmabuf.count signifies the amount of data that is waiting to be copied to
- the user's buffer. it is filled by the dma machine and drained by this loop. */
-static ssize_t ymf_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+/*
+ * in this loop, dmabuf.count signifies the amount of data that is
+ * waiting to be copied to the user's buffer. it is filled by the dma
+ * machine and drained by this loop.
+ */
+static ssize_t
+ymf_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
-#if HAVE_RECORD
- struct cs_state *state = (struct cs_state *)file->private_data;
- struct dmabuf *dmabuf = &state->dmabuf;
+ struct ymf_state *state = (struct ymf_state *)file->private_data;
+ struct ymf_dmabuf *dmabuf = &state->rpcm.dmabuf;
+ DECLARE_WAITQUEUE(waita, current);
ssize_t ret;
unsigned long flags;
- unsigned swptr;
- int cnt;
-
-#ifdef DEBUG
- printk("cs461x: cs_read called, count = %d\n", count);
-#endif
+ unsigned int swptr;
+ int cnt; /* This many to go in this revolution */
if (ppos != &file->f_pos)
return -ESPIPE;
@@ -1255,19 +1229,14 @@ static ssize_t ymf_read(struct file *file, char *buffer, size_t count, loff_t *p
return -EFAULT;
ret = 0;
+ add_wait_queue(&dmabuf->wait, &waita);
while (count > 0) {
- spin_lock_irqsave(&state->card->lock, flags);
- if (dmabuf->count > (signed) dmabuf->dmasize) {
- /* buffer overrun, we are recovering from sleep_on_timeout,
- resync hwptr and swptr, make process flush the buffer */
- dmabuf->count = dmabuf->dmasize;
- dmabuf->swptr = dmabuf->hwptr;
- }
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
swptr = dmabuf->swptr;
cnt = dmabuf->dmasize - swptr;
if (dmabuf->count < cnt)
cnt = dmabuf->count;
- spin_unlock_irqrestore(&state->card->lock, flags);
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
if (cnt > count)
cnt = count;
@@ -1275,14 +1244,18 @@ static ssize_t ymf_read(struct file *file, char *buffer, size_t count, loff_t *p
unsigned long tmo;
/* buffer is empty, start the dma machine and wait for data to be
recorded */
- start_adc(state);
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ if (!state->rpcm.running) {
+ ymf_capture_trigger(state->unit, &state->rpcm, 1);
+ }
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
if (file->f_flags & O_NONBLOCK) {
if (!ret) ret = -EAGAIN;
- return ret;
+ break;
}
/* This isnt strictly right for the 810 but it'll do */
- tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
- tmo >>= sample_shift[dmabuf->fmt];
+ tmo = (dmabuf->dmasize * HZ) / (state->format.rate * 2);
+ tmo >>= state->format.shift;
/* There are two situations when sleep_on_timeout returns, one is when
the interrupt is serviced correctly and the process is waked up by
ISR ON TIME. Another is when timeout is expired, which means that
@@ -1290,50 +1263,56 @@ static ssize_t ymf_read(struct file *file, char *buffer, size_t count, loff_t *p
is TOO LATE for the process to be scheduled to run (scheduler latency)
which results in a (potential) buffer overrun. And worse, there is
NOTHING we can do to prevent it. */
- if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) {
-#ifdef DEBUG
- printk(KERN_ERR "cs461x: recording schedule timeout, "
- "dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
- dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
- dmabuf->hwptr, dmabuf->swptr);
-#endif
- /* a buffer overrun, we delay the recovery untill next time the
- while loop begin and we REALLY have space to record */
+ set_current_state(TASK_INTERRUPTIBLE);
+ tmo = schedule_timeout(tmo);
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ if (tmo == 0 && dmabuf->count == 0) {
+ printk(KERN_ERR "ymfpci%d: recording schedule timeout, "
+ "dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
+ state->unit->dev_audio,
+ dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
+ dmabuf->hwptr, dmabuf->swptr);
}
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
if (signal_pending(current)) {
ret = ret ? ret : -ERESTARTSYS;
- return ret;
+ break;
}
continue;
}
if (copy_to_user(buffer, dmabuf->rawbuf + swptr, cnt)) {
if (!ret) ret = -EFAULT;
- return ret;
+ break;
}
swptr = (swptr + cnt) % dmabuf->dmasize;
- spin_lock_irqsave(&state->card->lock, flags);
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
dmabuf->swptr = swptr;
dmabuf->count -= cnt;
- spin_unlock_irqrestore(&state->card->lock, flags);
+ // spin_unlock_irqrestore(&state->unit->reg_lock, flags);
count -= cnt;
buffer += cnt;
ret += cnt;
- start_adc(state);
+ // spin_lock_irqsave(&state->unit->reg_lock, flags);
+ if (!state->rpcm.running) {
+ ymf_capture_trigger(state->unit, &state->rpcm, 1);
+ }
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
}
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&dmabuf->wait, &waita);
+
return ret;
-#else
- return -EINVAL;
-#endif
}
-static ssize_t ymf_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+static ssize_t
+ymf_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
struct ymf_state *state = (struct ymf_state *)file->private_data;
- struct ymf_dmabuf *dmabuf = &state->dmabuf;
+ struct ymf_dmabuf *dmabuf = &state->wpcm.dmabuf;
DECLARE_WAITQUEUE(waita, current);
ssize_t ret;
unsigned long flags;
@@ -1375,7 +1354,7 @@ static ssize_t ymf_write(struct file *file, const char *buffer, size_t count, lo
}
if (dmabuf->count == 0) {
swptr = dmabuf->hwptr;
- if (state->ypcm.running) {
+ if (state->wpcm.running) {
/*
* Add uncertainty reserve.
*/
@@ -1410,8 +1389,8 @@ static ssize_t ymf_write(struct file *file, const char *buffer, size_t count, lo
* wait for data to be played
*/
spin_lock_irqsave(&state->unit->reg_lock, flags);
- if (!state->ypcm.running) {
- ymf_playback_trigger(state->unit, &state->ypcm, 1);
+ if (!state->wpcm.running) {
+ ymf_playback_trigger(state->unit, &state->wpcm, 1);
}
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
if (file->f_flags & O_NONBLOCK) {
@@ -1448,8 +1427,8 @@ static ssize_t ymf_write(struct file *file, const char *buffer, size_t count, lo
*/
delay = state->format.rate / 20; /* 50ms */
delay <<= state->format.shift;
- if (dmabuf->count >= delay && !state->ypcm.running) {
- ymf_playback_trigger(state->unit, &state->ypcm, 1);
+ if (dmabuf->count >= delay && !state->wpcm.running) {
+ ymf_playback_trigger(state->unit, &state->wpcm, 1);
}
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
@@ -1469,19 +1448,23 @@ static ssize_t ymf_write(struct file *file, const char *buffer, size_t count, lo
static unsigned int ymf_poll(struct file *file, struct poll_table_struct *wait)
{
struct ymf_state *state = (struct ymf_state *)file->private_data;
- struct ymf_dmabuf *dmabuf = &state->dmabuf;
+ struct ymf_dmabuf *dmabuf;
unsigned long flags;
unsigned int mask = 0;
- if (file->f_mode & (FMODE_WRITE | FMODE_READ))
- poll_wait(file, &dmabuf->wait, wait);
+ if (file->f_mode & FMODE_WRITE)
+ poll_wait(file, &state->wpcm.dmabuf.wait, wait);
+ // if (file->f_mode & FMODE_READ)
+ // poll_wait(file, &dmabuf->wait, wait);
spin_lock_irqsave(&state->unit->reg_lock, flags);
if (file->f_mode & FMODE_READ) {
+ dmabuf = &state->rpcm.dmabuf;
if (dmabuf->count >= (signed)dmabuf->fragsize)
mask |= POLLIN | POLLRDNORM;
}
if (file->f_mode & FMODE_WRITE) {
+ dmabuf = &state->wpcm.dmabuf;
if (dmabuf->mapped) {
if (dmabuf->count >= (signed)dmabuf->fragsize)
mask |= POLLOUT | POLLWRNORM;
@@ -1498,10 +1481,9 @@ static unsigned int ymf_poll(struct file *file, struct poll_table_struct *wait)
static int ymf_mmap(struct file *file, struct vm_area_struct *vma)
{
struct ymf_state *state = (struct ymf_state *)file->private_data;
- struct ymf_dmabuf *dmabuf = &state->dmabuf;
+ struct ymf_dmabuf *dmabuf = &state->wpcm.dmabuf;
int ret;
unsigned long size;
-
if (vma->vm_flags & VM_WRITE) {
if ((ret = prog_dmabuf(state, 0)) != 0)
@@ -1529,7 +1511,7 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct ymf_state *state = (struct ymf_state *)file->private_data;
- struct ymf_dmabuf *dmabuf = &state->dmabuf;
+ struct ymf_dmabuf *dmabuf;
unsigned long flags;
audio_buf_info abinfo;
count_info cinfo;
@@ -1542,28 +1524,30 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
case SNDCTL_DSP_RESET:
if (file->f_mode & FMODE_WRITE) {
ymf_wait_dac(state);
+ dmabuf = &state->wpcm.dmabuf;
spin_lock_irqsave(&state->unit->reg_lock, flags);
dmabuf->ready = 0;
- dmabuf->swptr = dmabuf->hwptr = 0;
+ dmabuf->swptr = dmabuf->hwptr;
dmabuf->count = dmabuf->total_bytes = 0;
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
}
-#if HAVE_RECORD
if (file->f_mode & FMODE_READ) {
- stop_adc(state);
- synchronize_irq();
+ ymf_stop_adc(state);
+ dmabuf = &state->rpcm.dmabuf;
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
dmabuf->ready = 0;
- dmabuf->swptr = dmabuf->hwptr = 0;
+ dmabuf->swptr = dmabuf->hwptr;
dmabuf->count = dmabuf->total_bytes = 0;
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
}
-#endif
return 0;
case SNDCTL_DSP_SYNC:
if (file->f_mode & FMODE_WRITE) {
+ dmabuf = &state->wpcm.dmabuf;
if (file->f_flags & O_NONBLOCK) {
spin_lock_irqsave(&state->unit->reg_lock, flags);
- if (dmabuf->count != 0 && !state->ypcm.running) {
+ if (dmabuf->count != 0 && !state->wpcm.running) {
ymf_start_dac(state);
}
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
@@ -1571,6 +1555,7 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
ymf_wait_dac(state);
}
}
+ /* XXX What does this do for reading? dmabuf->count=0; ? */
return 0;
case SNDCTL_DSP_SPEED: /* set smaple rate */
@@ -1579,17 +1564,22 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
if (val >= 8000 && val <= 48000) {
if (file->f_mode & FMODE_WRITE) {
ymf_wait_dac(state);
+ dmabuf = &state->wpcm.dmabuf;
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ dmabuf->ready = 0;
+ state->format.rate = val;
+ ymf_pcm_update_shift(&state->format);
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
}
-#if HAVE_RECORD
if (file->f_mode & FMODE_READ) {
- stop_adc(state);
+ ymf_stop_adc(state);
+ dmabuf = &state->rpcm.dmabuf;
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ dmabuf->ready = 0;
+ state->format.rate = val;
+ ymf_pcm_update_shift(&state->format);
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
}
-#endif
- spin_lock_irqsave(&state->unit->reg_lock, flags);
- dmabuf->ready = 0;
- state->format.rate = val;
- ymf_pcm_update_shift(&state->format);
- spin_unlock_irqrestore(&state->unit->reg_lock, flags);
}
return put_user(state->format.rate, (int *)arg);
@@ -1597,41 +1587,41 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
* OSS manual does not mention SNDCTL_DSP_STEREO at all.
* All channels are mono and if you want stereo, you
* play into two channels with SNDCTL_DSP_CHANNELS.
- * However, mpg123 uses it. I wonder, why Michael Hipp uses it.
+ * However, mpg123 calls it. I wonder, why Michael Hipp used it.
*/
case SNDCTL_DSP_STEREO: /* set stereo or mono channel */
if (get_user(val, (int *)arg))
return -EFAULT;
if (file->f_mode & FMODE_WRITE) {
ymf_wait_dac(state);
+ dmabuf = &state->wpcm.dmabuf;
spin_lock_irqsave(&state->unit->reg_lock, flags);
dmabuf->ready = 0;
state->format.voices = val ? 2 : 1;
ymf_pcm_update_shift(&state->format);
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
}
-#if HAVE_RECORD
if (file->f_mode & FMODE_READ) {
- /* stop_adc(state); */
+ ymf_stop_adc(state);
+ dmabuf = &state->rpcm.dmabuf;
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
dmabuf->ready = 0;
- if(val)
- dmabuf->fmt |= CS_FMT_STEREO;
- else
- dmabuf->fmt &= ~CS_FMT_STEREO;
+ state->format.voices = val ? 2 : 1;
+ ymf_pcm_update_shift(&state->format);
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
}
-#endif
return 0;
case SNDCTL_DSP_GETBLKSIZE:
if (file->f_mode & FMODE_WRITE) {
if ((val = prog_dmabuf(state, 0)))
return val;
- return put_user(dmabuf->fragsize, (int *)arg);
+ return put_user(state->wpcm.dmabuf.fragsize, (int *)arg);
}
if (file->f_mode & FMODE_READ) {
if ((val = prog_dmabuf(state, 1)))
return val;
- return put_user(dmabuf->fragsize, (int *)arg);
+ return put_user(state->rpcm.dmabuf.fragsize, (int *)arg);
}
return -EINVAL;
@@ -1644,17 +1634,22 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
if (val == AFMT_S16_LE || val == AFMT_U8) {
if (file->f_mode & FMODE_WRITE) {
ymf_wait_dac(state);
+ dmabuf = &state->wpcm.dmabuf;
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ dmabuf->ready = 0;
+ state->format.format = val;
+ ymf_pcm_update_shift(&state->format);
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
}
-#if HAVE_RECORD
if (file->f_mode & FMODE_READ) {
- stop_adc(state);
+ ymf_stop_adc(state);
+ dmabuf = &state->rpcm.dmabuf;
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ dmabuf->ready = 0;
+ state->format.format = val;
+ ymf_pcm_update_shift(&state->format);
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
}
-#endif
- spin_lock_irqsave(&state->unit->reg_lock, flags);
- dmabuf->ready = 0;
- state->format.format = val;
- ymf_pcm_update_shift(&state->format);
- spin_unlock_irqrestore(&state->unit->reg_lock, flags);
}
return put_user(state->format.format, (int *)arg);
@@ -1667,20 +1662,24 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
ymf_wait_dac(state);
if (val == 1 || val == 2) {
spin_lock_irqsave(&state->unit->reg_lock, flags);
+ dmabuf = &state->wpcm.dmabuf;
dmabuf->ready = 0;
state->format.voices = val;
ymf_pcm_update_shift(&state->format);
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
}
}
-#if HAVE_RECORD
if (file->f_mode & FMODE_READ) {
- spin_lock_irqsave(&state->unit->reg_lock, flags);
- stop_adc(state);
- dmabuf->ready = 0;
- spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ ymf_stop_adc(state);
+ if (val == 1 || val == 2) {
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
+ dmabuf = &state->rpcm.dmabuf;
+ dmabuf->ready = 0;
+ state->format.voices = val;
+ ymf_pcm_update_shift(&state->format);
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ }
}
-#endif
}
return put_user(state->format.voices, (int *)arg);
@@ -1696,15 +1695,16 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
* The paragraph above is a clumsy way to say "flush ioctl".
* This ioctl is used by mpg123.
*/
- /* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_POST\n"); */
spin_lock_irqsave(&state->unit->reg_lock, flags);
- if (dmabuf->count != 0 && !state->ypcm.running) {
+ if (state->wpcm.dmabuf.count != 0 && !state->wpcm.running) {
ymf_start_dac(state);
}
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
return 0;
+#if 0 /* XXX Was dummy implementation anyways. Make sense of this. */
case SNDCTL_DSP_SUBDIVIDE:
+ dmabuf = &state->wpcm.dmabuf;
if (dmabuf->subdivision)
return -EINVAL;
if (get_user(val, (int *)arg))
@@ -1713,6 +1713,7 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
dmabuf->subdivision = val;
return 0;
+#endif
case SNDCTL_DSP_SETFRAGMENT:
if (get_user(val, (int *)arg))
@@ -1720,6 +1721,7 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
/* P3: these frags are for Doom. Amasingly, it sets [2,2**11]. */
/* P3 */ // printk("ymfpci: ioctl SNDCTL_DSP_SETFRAGMENT 0x%x\n", val);
+ dmabuf = &state->wpcm.dmabuf;
dmabuf->ossfragshift = val & 0xffff;
dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
switch (dmabuf->ossmaxfrags) {
@@ -1736,10 +1738,10 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
case SNDCTL_DSP_GETOSPACE:
if (!(file->f_mode & FMODE_WRITE))
return -EINVAL;
+ dmabuf = &state->wpcm.dmabuf;
if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)
return val;
spin_lock_irqsave(&state->unit->reg_lock, flags);
- /* cs_update_ptr(state); */ /* XXX Always up to date? */
abinfo.fragsize = dmabuf->fragsize;
abinfo.bytes = dmabuf->dmasize - dmabuf->count;
abinfo.fragstotal = dmabuf->numfrag;
@@ -1747,21 +1749,19 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
-#if HAVE_RECORD
case SNDCTL_DSP_GETISPACE:
if (!(file->f_mode & FMODE_READ))
return -EINVAL;
+ dmabuf = &state->rpcm.dmabuf;
if (!dmabuf->ready && (val = prog_dmabuf(state, 1)) != 0)
return val;
- spin_lock_irqsave(&state->card->lock, flags);
- cs_update_ptr(state);
+ spin_lock_irqsave(&state->unit->reg_lock, flags);
abinfo.fragsize = dmabuf->fragsize;
abinfo.bytes = dmabuf->count;
abinfo.fragstotal = dmabuf->numfrag;
abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
- spin_unlock_irqrestore(&state->card->lock, flags);
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
-#endif
case SNDCTL_DSP_NONBLOCK:
file->f_flags |= O_NONBLOCK;
@@ -1772,9 +1772,10 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
(int *)arg); */
return put_user(0, (int *)arg);
-#if 0 /* old */
+#if 0 /* not implememnted, yet? */
case SNDCTL_DSP_GETTRIGGER:
val = 0;
+ dmabuf = &state->wpcm.dmabuf;
if (file->f_mode & FMODE_READ && dmabuf->enable)
val |= PCM_ENABLE_INPUT;
if (file->f_mode & FMODE_WRITE && dmabuf->enable)
@@ -1785,6 +1786,7 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
if (get_user(val, (int *)arg))
return -EFAULT;
if (file->f_mode & FMODE_READ) {
+ dmabuf = &state->rpcm.dmabuf;
if (val & PCM_ENABLE_INPUT) {
if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
return ret;
@@ -1793,6 +1795,7 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
stop_adc(state);
}
if (file->f_mode & FMODE_WRITE) {
+ dmabuf = &state->wpcm.dmabuf;
if (val & PCM_ENABLE_OUTPUT) {
if (!dmabuf->ready && (ret = prog_dmabuf(state, 0)))
return ret;
@@ -1801,48 +1804,48 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
stop_dac(state);
}
return 0;
-
#endif
-#if HAVE_RECORD
case SNDCTL_DSP_GETIPTR:
if (!(file->f_mode & FMODE_READ))
return -EINVAL;
+ dmabuf = &state->rpcm.dmabuf;
spin_lock_irqsave(&state->unit->reg_lock, flags);
- cs_update_ptr(state);
cinfo.bytes = dmabuf->total_bytes;
cinfo.blocks = dmabuf->count >> dmabuf->fragshift;
cinfo.ptr = dmabuf->hwptr;
+ /* XXX fishy - breaks invariant count=hwptr-swptr */
if (dmabuf->mapped)
dmabuf->count &= dmabuf->fragsize-1;
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
- return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
-#endif
+ return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
case SNDCTL_DSP_GETOPTR:
if (!(file->f_mode & FMODE_WRITE))
return -EINVAL;
+ dmabuf = &state->wpcm.dmabuf;
spin_lock_irqsave(&state->unit->reg_lock, flags);
- /* cs_update_ptr(state); */ /* Always up to date */
cinfo.bytes = dmabuf->total_bytes;
cinfo.blocks = dmabuf->count >> dmabuf->fragshift;
cinfo.ptr = dmabuf->hwptr;
+ /* XXX fishy - breaks invariant count=swptr-hwptr */
if (dmabuf->mapped)
dmabuf->count &= dmabuf->fragsize-1;
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
- return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+ return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
case SNDCTL_DSP_SETDUPLEX: /* XXX TODO */
return -EINVAL;
-#if 0 /* old */
+#if 0 /* XXX implement when an app found that uses it. */
case SNDCTL_DSP_GETODELAY:
if (!(file->f_mode & FMODE_WRITE))
return -EINVAL;
spin_lock_irqsave(&state->unit->reg_lock, flags);
cs_update_ptr(state);
+ dmabuf = &state->wpcm.dmabuf;
val = dmabuf->count;
- spin_unlock_irqrestore(&state->card->lock, flags);
+ spin_unlock_irqrestore(&state->unit->reg_lock, flags);
return put_user(val, (int *)arg);
#endif
@@ -1850,7 +1853,7 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
return put_user(state->format.rate, (int *)arg);
case SOUND_PCM_READ_CHANNELS:
- return put_user(state->format.voices, (int *)arg);
+ return put_user(state->format.voices, (int *)arg);
case SOUND_PCM_READ_BITS:
return put_user(AFMT_S16_LE, (int *)arg);
@@ -1873,28 +1876,25 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
return -ENOTTY;
}
+/*
+ * open(2)
+ * We use upper part of the minor to distinguish between soundcards.
+ * Channels are opened with a clone open.
+ */
static int ymf_open(struct inode *inode, struct file *file)
{
struct list_head *list;
ymfpci_t *unit;
int minor;
struct ymf_state *state;
- int nvirt;
int err;
- /*
- * This is how we do it currently: only one channel is used
- * in every board, so that we could use several boards in one machine.
- * We waste 63 out of 64 playback slots, but so what.
- * OSS model is constructed for devices with single playback channel.
- */
minor = MINOR(inode->i_rdev);
if ((minor & 0x0F) == 3) { /* /dev/dspN */
;
} else {
return -ENXIO;
}
- nvirt = 0; /* Such is the partitioning of minor */
for (list = ymf_devs.next; list != &ymf_devs; list = list->next) {
unit = list_entry(list, ymfpci_t, ymf_devs);
@@ -1905,34 +1905,36 @@ static int ymf_open(struct inode *inode, struct file *file)
return -ENODEV;
down(&unit->open_sem);
- if (unit->states[nvirt] != NULL) {
- up(&unit->open_sem);
- return -EBUSY;
- }
- if ((err = ymf_state_alloc(unit, nvirt)) != 0) {
+ if ((state = ymf_state_alloc(unit)) == NULL) {
up(&unit->open_sem);
- return err;
+ return -ENOMEM;
}
- state = unit->states[nvirt];
+ list_add_tail(&state->chain, &unit->states);
file->private_data = state;
/*
- * XXX This ymf_playback_prepare is totally unneeded here.
- * The question is if we want to allow write to fail if
- * prog_dmabuf fails... Say, no memory in DMA zone?
+ * ymf_read and ymf_write that we borrowed from cs46xx
+ * allocate buffers with prog_dmabuf(). We call prog_dmabuf
+ * here so that in case of DMA memory exhaustion open
+ * fails rather than write.
+ *
+ * XXX prog_dmabuf allocates voice. Should allocate explicitly, above.
*/
- if ((err = ymf_playback_prepare(unit, state)) != 0) {
- /* XXX This recovery is ugly as hell. */
-
- ymf_pcm_free_substream(&state->ypcm);
-
- unit->states[state->virt] = NULL;
- kfree(state);
-
- up(&unit->open_sem);
- return err;
+ if (file->f_mode & FMODE_WRITE) {
+ if (!state->wpcm.dmabuf.ready) {
+ if ((err = prog_dmabuf(state, 0)) != 0) {
+ goto out_nodma;
+ }
+ }
+ }
+ if (file->f_mode & FMODE_READ) {
+ if (!state->rpcm.dmabuf.ready) {
+ if ((err = prog_dmabuf(state, 1)) != 0) {
+ goto out_nodma;
+ }
+ }
}
#if 0 /* test if interrupts work */
@@ -1941,10 +1943,26 @@ static int ymf_open(struct inode *inode, struct file *file)
(YDSXGR_TIMERCTRL_TEN|YDSXGR_TIMERCTRL_TIEN));
#endif
up(&unit->open_sem);
- /* XXX Is it correct to have MOD_INC_USE_COUNT outside of sem.? */
MOD_INC_USE_COUNT;
return 0;
+
+out_nodma:
+ /*
+ * XXX Broken custom: "goto out_xxx" in other place is
+ * a nestable exception, but here it is not nestable due to semaphore.
+ * XXX Doubtful technique of self-describing objects....
+ */
+ dealloc_dmabuf(&state->wpcm.dmabuf);
+ dealloc_dmabuf(&state->rpcm.dmabuf);
+ ymf_pcm_free_substream(&state->wpcm);
+ ymf_pcm_free_substream(&state->rpcm);
+
+ list_del(&state->chain);
+ kfree(state);
+
+ up(&unit->open_sem);
+ return err;
}
static int ymf_release(struct inode *inode, struct file *file)
@@ -1956,12 +1974,6 @@ static int ymf_release(struct inode *inode, struct file *file)
ymfpci_writeb(codec, YDSXGR_TIMERCTRL, 0);
#endif
- if (state != codec->states[state->virt]) {
- printk(KERN_ERR "ymfpci%d.%d: state mismatch\n",
- state->unit->dev_audio, state->virt);
- return -EIO;
- }
-
down(&codec->open_sem);
/*
@@ -1969,10 +1981,14 @@ static int ymf_release(struct inode *inode, struct file *file)
* Deallocate when unloading the driver and we can wait.
*/
ymf_wait_dac(state);
- dealloc_dmabuf(state);
- ymf_pcm_free_substream(&state->ypcm);
-
- codec->states[state->virt] = NULL;
+ ymf_stop_adc(state); /* fortunately, it's immediate */
+ dealloc_dmabuf(&state->wpcm.dmabuf);
+ dealloc_dmabuf(&state->rpcm.dmabuf);
+ ymf_pcm_free_substream(&state->wpcm);
+ ymf_pcm_free_substream(&state->rpcm);
+
+ list_del(&state->chain);
+ file->private_data = NULL; /* Can you tell I programmed Solaris */
kfree(state);
up(&codec->open_sem);
@@ -2045,6 +2061,83 @@ static /*const*/ struct file_operations ymf_mixer_fops = {
* initialization routines
*/
+#ifdef CONFIG_SOUND_YMFPCI_LEGACY
+
+static int ymfpci_setup_legacy(ymfpci_t *unit, struct pci_dev *pcidev)
+{
+ int v;
+ int mpuio = -1, oplio = -1;
+
+ switch (unit->iomidi) {
+ case 0x330:
+ mpuio = 0;
+ break;
+ case 0x300:
+ mpuio = 1;
+ break;
+ case 0x332:
+ mpuio = 2;
+ break;
+ case 0x334:
+ mpuio = 3;
+ break;
+ default: ;
+ }
+
+ switch (unit->iosynth) {
+ case 0x388:
+ oplio = 0;
+ break;
+ case 0x398:
+ oplio = 1;
+ break;
+ case 0x3a0:
+ oplio = 2;
+ break;
+ case 0x3a8:
+ oplio = 3;
+ break;
+ default: ;
+ }
+
+ if (mpuio >= 0 || oplio >= 0) {
+ v = 0x003e;
+ pci_write_config_word(pcidev, PCIR_LEGCTRL, v);
+
+ switch (pcidev->device) {
+ case PCI_DEVICE_ID_YAMAHA_724:
+ case PCI_DEVICE_ID_YAMAHA_740:
+ case PCI_DEVICE_ID_YAMAHA_724F:
+ case PCI_DEVICE_ID_YAMAHA_740C:
+ v = 0x8800;
+ if (mpuio >= 0) { v |= mpuio<<4; }
+ if (oplio >= 0) { v |= oplio; }
+ pci_write_config_word(pcidev, PCIR_ELEGCTRL, v);
+ break;
+
+ case PCI_DEVICE_ID_YAMAHA_744:
+ case PCI_DEVICE_ID_YAMAHA_754:
+ v = 0x8800;
+ pci_write_config_word(pcidev, PCIR_ELEGCTRL, v);
+ if (oplio >= 0) {
+ pci_write_config_word(pcidev, PCIR_OPLADR, unit->iosynth);
+ }
+ if (mpuio >= 0) {
+ pci_write_config_word(pcidev, PCIR_MPUADR, unit->iomidi);
+ }
+ break;
+
+ default:
+ printk(KERN_ERR "ymfpci: Unknown device ID: 0x%x\n",
+ pcidev->device);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+#endif /* CONFIG_SOUND_YMFPCI_LEGACY */
+
static void ymfpci_aclink_reset(struct pci_dev * pci)
{
u8 cmd;
@@ -2149,6 +2242,12 @@ static int ymfpci_memalloc(ymfpci_t *codec)
ptr += 0x00ff;
(long)ptr &= ~0x00ff;
+ /*
+ * Hardware requires only ptr[playback_ctrl_size] zeroed,
+ * but in our judgement it is a wrong kind of savings, so clear it all.
+ */
+ memset(ptr, 0, size);
+
codec->bank_base_playback = ptr;
codec->ctrl_playback = (u32 *)ptr;
codec->ctrl_playback[0] = YDSXG_PLAYBACK_VOICES;
@@ -2213,7 +2312,7 @@ static void ymfpci_memfree(ymfpci_t *codec)
kfree(codec->work_ptr);
}
-static int ymf_ac97_init(ymfpci_t *card, int num_ac97)
+static int ymf_ac97_init(ymfpci_t *unit, int num_ac97)
{
struct ac97_codec *codec;
u16 eid;
@@ -2224,7 +2323,7 @@ static int ymf_ac97_init(ymfpci_t *card, int num_ac97)
/* initialize some basic codec information, other fields will be filled
in ac97_probe_codec */
- codec->private_data = card;
+ codec->private_data = unit;
codec->id = num_ac97;
codec->codec_read = ymfpci_codec_read;
@@ -2241,14 +2340,14 @@ static int ymf_ac97_init(ymfpci_t *card, int num_ac97)
goto out_kfree;
}
- card->ac97_features = eid;
+ unit->ac97_features = eid;
if ((codec->dev_mixer = register_sound_mixer(&ymf_mixer_fops, -1)) < 0) {
printk(KERN_ERR "ymfpci: couldn't register mixer!\n");
goto out_kfree;
}
- card->ac97_codec[num_ac97] = codec;
+ unit->ac97_codec[num_ac97] = codec;
return 0;
out_kfree:
@@ -2256,6 +2355,19 @@ static int ymf_ac97_init(ymfpci_t *card, int num_ac97)
return -ENODEV;
}
+#ifdef CONFIG_SOUND_YMFPCI_LEGACY
+# ifdef MODULE
+static int mpu_io = 0;
+static int synth_io = 0;
+MODULE_PARM(mpu_io, "i");
+MODULE_PARM(synth_io, "i");
+# else
+static int mpu_io = 0x330;
+static int synth_io = 0x388;
+# endif
+static int assigned;
+#endif /* CONFIG_SOUND_YMFPCI_LEGACY */
+
static int __devinit ymf_probe_one(struct pci_dev *pcidev, const struct pci_device_id *ent)
{
u16 ctrl;
@@ -2277,10 +2389,15 @@ static int __devinit ymf_probe_one(struct pci_dev *pcidev, const struct pci_devi
spin_lock_init(&codec->reg_lock);
spin_lock_init(&codec->voice_lock);
init_MUTEX(&codec->open_sem);
+ INIT_LIST_HEAD(&codec->states);
codec->pci = pcidev;
pci_read_config_byte(pcidev, PCI_REVISION_ID, &codec->rev);
codec->reg_area_virt = ioremap(pci_resource_start(pcidev, 0), 0x8000);
+ if (codec->reg_area_virt == NULL) {
+ printk(KERN_ERR "ymfpci: unable to map registers\n");
+ goto out_free;
+ }
printk(KERN_INFO "ymfpci: %s at 0x%lx IRQ %d\n",
(char *)ent->driver_data, pci_resource_start(pcidev, 0), pcidev->irq);
@@ -2289,6 +2406,16 @@ static int __devinit ymf_probe_one(struct pci_dev *pcidev, const struct pci_devi
if (ymfpci_codec_ready(codec, 0, 1) < 0)
goto out_unmap;
+#ifdef CONFIG_SOUND_YMFPCI_LEGACY
+ if (assigned == 0) {
+ codec->iomidi = mpu_io;
+ codec->iosynth = synth_io;
+ if (ymfpci_setup_legacy(codec, pcidev) < 0)
+ goto out_unmap;
+ assigned = 1;
+ }
+#endif
+
ymfpci_download_image(codec);
udelay(100); /* seems we need some delay after downloading image.. */
@@ -2296,11 +2423,11 @@ static int __devinit ymf_probe_one(struct pci_dev *pcidev, const struct pci_devi
if (ymfpci_memalloc(codec) < 0)
goto out_disable_dsp;
- /* ymfpci_proc_init(card, codec); */
+ /* ymfpci_proc_init(unit, codec); */
if (request_irq(pcidev->irq, ymf_interrupt, SA_SHIRQ, "ymfpci", codec) != 0) {
- printk(KERN_ERR "ymfpci%d: unable to request IRQ %d\n",
- codec->dev_audio, pcidev->irq);
+ printk(KERN_ERR "ymfpci: unable to request IRQ %d\n",
+ pcidev->irq);
goto out_memfree;
}
@@ -2317,6 +2444,23 @@ static int __devinit ymf_probe_one(struct pci_dev *pcidev, const struct pci_devi
if ((err = ymf_ac97_init(codec, 0)) != 0)
goto out_unregister_sound_dsp;
+#ifdef CONFIG_SOUND_YMFPCI_LEGACY
+ codec->opl3_data.name = "ymfpci";
+ codec->mpu_data.name = "ymfpci";
+
+ codec->opl3_data.io_base = codec->iosynth;
+ codec->opl3_data.irq = -1;
+
+ codec->mpu_data.io_base = codec->iomidi;
+ codec->mpu_data.irq = -1; /* XXX Make it ours. */
+
+ if (codec->iomidi) {
+ if (!probe_uart401(&codec->mpu_data, THIS_MODULE)) {
+ codec->iomidi = 0; /* XXX kludge */
+ }
+ }
+#endif /* CONFIG_SOUND_YMFPCI_LEGACY */
+
/* put it into driver list */
list_add_tail(&codec->ymf_devs, &ymf_devs);
pci_set_drvdata(pcidev, codec);
@@ -2336,6 +2480,7 @@ static int __devinit ymf_probe_one(struct pci_dev *pcidev, const struct pci_devi
ymfpci_writel(codec, YDSXGR_STATUS, ~0);
out_unmap:
iounmap(codec->reg_area_virt);
+ out_free:
kfree(codec);
return -ENODEV;
}
@@ -2358,6 +2503,11 @@ static void __devexit ymf_remove_one(struct pci_dev *pcidev)
ctrl = ymfpci_readw(codec, YDSXGR_GLOBALCTRL);
ymfpci_writew(codec, YDSXGR_GLOBALCTRL, ctrl & ~0x0007);
iounmap(codec->reg_area_virt);
+#ifdef CONFIG_SOUND_YMFPCI_LEGACY
+ if (codec->iomidi) {
+ unload_uart401(&codec->mpu_data);
+ }
+#endif /* CONFIG_SOUND_YMFPCI_LEGACY */
kfree(codec);
}
diff --git a/drivers/sound/ymfpci.h b/drivers/sound/ymfpci.h
index 6e1a8d5f3..bd2f4c2a3 100644
--- a/drivers/sound/ymfpci.h
+++ b/drivers/sound/ymfpci.h
@@ -21,6 +21,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
+#include <linux/config.h>
/*
* Direct registers
@@ -131,7 +132,12 @@
#define YDSXG_AC97READCMD 0x8000
#define YDSXG_AC97WRITECMD 0x0000
+#define PCIR_LEGCTRL 0x40
+#define PCIR_ELEGCTRL 0x42
#define PCIR_DSXGCTRL 0x48
+#define PCIR_OPLADR 0x60
+#define PCIR_SBADR 0x62
+#define PCIR_MPUADR 0x64
#define YDSXG_DSPLENGTH 0x0080
#define YDSXG_CTRLLENGTH 0x3000
@@ -185,8 +191,8 @@ typedef struct stru_ymfpci_playback_bank {
} ymfpci_playback_bank_t;
typedef struct stru_ymfpci_capture_bank {
- u32 base; /* 32-bit address */
- u32 loop_end; /* 32-bit offset */
+ u32 base; /* 32-bit address (aligned at 4) */
+ u32 loop_end; /* size in BYTES (aligned at 4) */
u32 start; /* 32-bit offset */
u32 num_of_loops; /* counter */
} ymfpci_capture_bank_t;
@@ -198,8 +204,7 @@ typedef struct stru_ymfpci_effect_bank {
u32 temp;
} ymfpci_effect_bank_t;
-typedef struct stru_ymfpci_voice ymfpci_voice_t;
-typedef struct ymf_pcm ymfpci_pcm_t;
+typedef struct ymf_voice ymfpci_voice_t;
/*
* Throughout the code Yaroslav names YMF unit pointer "codec"
* even though it does not correspond to any codec. Must be historic.
@@ -214,52 +219,35 @@ typedef enum {
YMFPCI_MIDI
} ymfpci_voice_type_t;
-struct stru_ymfpci_voice {
- ymfpci_t *codec;
+struct ymf_voice {
+ // ymfpci_t *codec;
int number;
- int use: 1,
- pcm: 1,
- synth: 1,
- midi: 1;
+ char use, pcm, synth, midi; // bool
ymfpci_playback_bank_t *bank;
- void (*interrupt)(ymfpci_t *codec, ymfpci_voice_t *voice);
- ymfpci_pcm_t *ypcm;
+ struct ymf_pcm *ypcm;
};
-typedef enum {
- PLAYBACK_VOICE,
- CAPTURE_REC,
- CAPTURE_AC97,
- EFFECT_DRY_LEFT,
- EFFECT_DRY_RIGHT,
- EFFECT_EFF1,
- EFFECT_EFF2,
- EFFECT_EFF3
-} ymfpci_pcm_type_t;
-
-struct ymf_pcm {
- ymfpci_t *codec;
- ymfpci_pcm_type_t type;
- struct ymf_state *state;
- ymfpci_voice_t *voices[2]; /* playback only */
- int running; // +
- int spdif;
+struct ymf_capture {
+ // struct ymf_unit *unit;
+ int use;
+ ymfpci_capture_bank_t *bank;
+ struct ymf_pcm *ypcm;
};
struct ymf_unit {
u8 rev; /* PCI revision */
void *reg_area_virt;
- void *work_ptr; // +
+ void *work_ptr;
unsigned int bank_size_playback;
unsigned int bank_size_capture;
unsigned int bank_size_effect;
unsigned int work_size;
- void *bank_base_playback; // +
- void *bank_base_capture; // +
- void *bank_base_effect; // +
- void *work_base; // +
+ void *bank_base_playback;
+ void *bank_base_capture;
+ void *bank_base_effect;
+ void *work_base;
u32 *ctrl_playback;
ymfpci_playback_bank_t *bank_playback[YDSXG_PLAYBACK_VOICES][2];
@@ -269,13 +257,20 @@ struct ymf_unit {
int start_count;
u32 active_bank;
- ymfpci_voice_t voices[64];
+ struct ymf_voice voices[64];
+ struct ymf_capture capture[5];
struct ac97_codec *ac97_codec[NR_AC97];
u16 ac97_features;
struct pci_dev *pci;
+#ifdef CONFIG_SOUND_YMFPCI_LEGACY
+ /* legacy hardware resources */
+ unsigned int iosynth, iomidi;
+ struct address_info opl3_data, mpu_data;
+#endif
+
spinlock_t reg_lock;
spinlock_t voice_lock;
@@ -284,14 +279,11 @@ struct ymf_unit {
struct semaphore open_sem;
struct list_head ymf_devs;
- struct ymf_state *states[1]; // *
- /* ypcm may be the same thing as state, but not for record, effects. */
+ struct list_head states; /* List of states for this unit */
+ /* For the moment we do not traverse list of states so it is
+ * entirely useless. Will be used (PM) or killed. XXX */
};
-/*
- * "Software" or virtual channel, an instance of opened /dev/dsp.
- */
-
struct ymf_dmabuf {
/* OSS buffer management stuff */
@@ -312,7 +304,6 @@ struct ymf_dmabuf {
/* redundant, but makes calculations easier */
unsigned fragsize;
unsigned dmasize; /* Total rawbuf[] size */
- unsigned fragsamples;
/* OSS stuff */
unsigned mapped:1;
@@ -329,15 +320,40 @@ struct ymf_pcm_format {
int shift; /* redundant, computed from the above */
};
-struct ymf_state {
- struct ymf_unit *unit; /* backpointer */
+typedef enum {
+ PLAYBACK_VOICE,
+ CAPTURE_REC,
+ CAPTURE_AC97,
+ EFFECT_DRY_LEFT,
+ EFFECT_DRY_RIGHT,
+ EFFECT_EFF1,
+ EFFECT_EFF2,
+ EFFECT_EFF3
+} ymfpci_pcm_type_t;
- /* virtual channel number */
- int virt; // * unused a.t.m.
+/* This is variant record, but we hate unions. Little waste on pointers []. */
+struct ymf_pcm {
+ ymfpci_pcm_type_t type;
+ struct ymf_state *state;
+
+ ymfpci_voice_t *voices[2];
+ int capture_bank_number;
+
+ struct ymf_dmabuf dmabuf;
+ int running;
+ int spdif;
+};
- struct ymf_pcm ypcm; // *
- struct ymf_dmabuf dmabuf; // *
- struct ymf_pcm_format format; // *
+/*
+ * "Software" or virtual channel, an instance of opened /dev/dsp.
+ * It may have two physical channels (pcms) for duplex operations.
+ */
+
+struct ymf_state {
+ struct list_head chain;
+ struct ymf_unit *unit; /* backpointer */
+ struct ymf_pcm rpcm, wpcm;
+ struct ymf_pcm_format format;
};
#endif /* __YMFPCI_H */
diff --git a/drivers/usb/rio500.c b/drivers/usb/rio500.c
index 6d7b9043d..29b926056 100644
--- a/drivers/usb/rio500.c
+++ b/drivers/usb/rio500.c
@@ -247,6 +247,7 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd,
return 0;
err_out:
+ up(&(rio->lock));
return retval;
}
@@ -389,7 +390,7 @@ read_rio(struct file *file, char *buffer, size_t count, loff_t * ppos)
result, partial, this_read);
return -EIO;
} else {
- unlock_kernel();
+ up(&(rio->lock));
return (0);
}
diff --git a/drivers/usb/serial/Config.in b/drivers/usb/serial/Config.in
index 6d949bc0b..0032f6e15 100644
--- a/drivers/usb/serial/Config.in
+++ b/drivers/usb/serial/Config.in
@@ -22,6 +22,7 @@ if [ "$CONFIG_USB_SERIAL" != "n" ]; then
bool ' USB Keyspan USA-19 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19
bool ' USB Keyspan USA-18X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA18X
bool ' USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W
+ bool ' USB Keyspan USA-49W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA49W
fi
dep_tristate ' USB MCT Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
dep_tristate ' USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
diff --git a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c
index 1a07a03d5..3a3451e49 100644
--- a/drivers/usb/serial/usbserial.c
+++ b/drivers/usb/serial/usbserial.c
@@ -14,8 +14,14 @@
* based on a driver by Brad Keryan)
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
- *
- * (12/29/2000) gkh
+ *
+ * (12/12/2000) gkh
+ * Removed MOD_INC and MOD_DEC from poll and disconnect functions, and
+ * moved them to the serial_open and serial_close functions.
+ * Also fixed bug with there not being a MOD_DEC for the generic driver
+ * (thanks to Gary Brubaker for finding this.)
+ *
+ * (11/29/2000) gkh
* Small NULL pointer initialization cleanup which saves a bit of disk image
*
* (11/01/2000) Adam J. Richter
@@ -471,6 +477,8 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
return -ENODEV;
}
+ MOD_INC_USE_COUNT;
+
/* set up our port structure making the tty driver remember our port object, and us it */
portNumber = MINOR(tty->device) - serial->minor;
port = &serial->port[portNumber];
@@ -508,6 +516,8 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
} else {
generic_close(port, filp);
}
+
+ MOD_DEC_USE_COUNT;
}
@@ -721,12 +731,13 @@ static int generic_open (struct usb_serial_port *port, struct file *filp)
if (port_paranoia_check (port, __FUNCTION__))
return -ENODEV;
+ MOD_INC_USE_COUNT;
+
dbg(__FUNCTION__ " - port %d", port->number);
spin_lock_irqsave (&port->port_lock, flags);
++port->open_count;
- MOD_INC_USE_COUNT;
if (!port->active) {
port->active = 1;
@@ -776,6 +787,7 @@ static void generic_close (struct usb_serial_port *port, struct file * filp)
}
spin_unlock_irqrestore (&port->port_lock, flags);
+ MOD_DEC_USE_COUNT;
}
@@ -1069,7 +1081,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
}
/* found all that we need */
- MOD_INC_USE_COUNT;
info("%s converter detected", type->name);
#ifdef CONFIG_USB_SERIAL_GENERIC
@@ -1077,7 +1088,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
num_ports = num_bulk_out;
if (num_ports == 0) {
err("Generic device with no bulk out, not allowed.");
- MOD_DEC_USE_COUNT;
return NULL;
}
} else
@@ -1087,7 +1097,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
serial = get_free_serial (num_ports, &minor);
if (serial == NULL) {
err("No more free serial devices");
- MOD_DEC_USE_COUNT;
return NULL;
}
@@ -1233,7 +1242,6 @@ probe_error:
/* free up any memory that we allocated */
kfree (serial);
- MOD_DEC_USE_COUNT;
return NULL;
}
@@ -1300,7 +1308,6 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr)
info("device disconnected");
}
- MOD_DEC_USE_COUNT;
}
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index e363916b9..d8a60a2a7 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -10,6 +10,10 @@
* (at your option) any later version.
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
+ *
+ * (12/12/2000) gkh
+ * Moved MOD_DEC to end of visor_close to be nicer, as the final write
+ * message can sleep.
*
* (11/12/2000) gkh
* Fixed bug with data being dropped on the floor by forcing tty->low_latency
@@ -214,7 +218,6 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
spin_lock_irqsave (&port->port_lock, flags);
--port->open_count;
- MOD_DEC_USE_COUNT;
if (port->open_count <= 0) {
transfer_buffer = kmalloc (0x12, GFP_KERNEL);
@@ -237,6 +240,8 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
/* Uncomment the following line if you want to see some statistics in your syslog */
/* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */
+
+ MOD_DEC_USE_COUNT;
}
diff --git a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h
index 5123f85f8..c5477dcaf 100644
--- a/drivers/usb/storage/debug.h
+++ b/drivers/usb/storage/debug.h
@@ -1,7 +1,7 @@
/* Driver for USB Mass Storage compliant devices
* Debugging Functions Header File
*
- * $Id: debug.h,v 1.5 2000/09/04 02:12:47 groovyjava Exp $
+ * $Id: debug.h,v 1.6 2001/01/12 23:51:04 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 241f7d5f6..5c50b578c 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -248,7 +248,7 @@ static int bus_reset( Scsi_Cmnd *srb )
for (i = 0; i < us->pusb_dev->actconfig->bNumInterfaces; i++) {
struct usb_interface *intf =
&us->pusb_dev->actconfig->interface[i];
- const struct usb_device_id *id;
+ struct usb_device_id *id;
/* if this is an unclaimed interface, skip it */
if (!intf->driver) {
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
new file mode 100644
index 000000000..d29307433
--- /dev/null
+++ b/drivers/usb/storage/unusual_devs.h
@@ -0,0 +1,232 @@
+/* Driver for USB Mass Storage compliant devices
+ * Ununsual Devices File
+ *
+ * $Id: unusual_devs.h,v 1.1 2000/12/05 05:38:31 mdharm Exp $
+ *
+ * Current development and maintenance by:
+ * (c) 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
+ *
+ * Initial work by:
+ * (c) 2000 Adam J. Richter (adam@yggdrasil.com), Yggdrasil Computing, Inc.
+ *
+ * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
+ * information about this driver.
+ *
+ * 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, 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* IMPORTANT NOTE: This file must be included in another file which does
+ * the following thing for it to work:
+ * The macro UNUSUAL_DEV() must be defined before this file is included
+ */
+#include <linux/config.h>
+
+/* If you edit this file, please try to keep it sorted first by VendorID,
+ * then by ProductID.
+ */
+
+UNUSUAL_DEV( 0x03ee, 0x0000, 0x0000, 0x0245,
+ "Mitsumi",
+ "CD-R/RW Drive",
+ US_SC_8020, US_PR_CBI, NULL, 0),
+
+UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200,
+ "HP",
+ "CD-Writer+",
+ US_SC_8070, US_PR_CB, NULL, 0),
+
+#ifdef CONFIG_USB_STORAGE_HP8200e
+UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001,
+ "HP",
+ "CD-Writer+ 8200e",
+ US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0),
+#endif
+
+UNUSUAL_DEV( 0x04e6, 0x0001, 0x0200, 0x0200,
+ "Matshita",
+ "LS-120",
+ US_SC_8020, US_PR_CB, NULL, 0),
+
+UNUSUAL_DEV( 0x04e6, 0x0002, 0x0100, 0x0100,
+ "Shuttle",
+ "eUSCSI Bridge",
+ US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
+ US_FL_SCM_MULT_TARG ),
+
+#ifdef CONFIG_USB_STORAGE_SDDR09
+UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999,
+ "Sandisk",
+ "ImageMate SDDR09",
+ US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
+ US_FL_SINGLE_LUN | US_FL_START_STOP ),
+#endif
+
+#ifdef CONFIG_USB_STORAGE_DPCM
+UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100,
+ "Microtech",
+ "CameraMate (DPCM_USB)",
+ US_SC_SCSI, US_PR_DPCM_USB, NULL,
+ US_FL_START_STOP ),
+#endif
+
+UNUSUAL_DEV( 0x04e6, 0x0006, 0x0100, 0x0200,
+ "Shuttle",
+ "eUSB MMC Adapter",
+ US_SC_SCSI, US_PR_CB, NULL,
+ US_FL_SINGLE_LUN),
+
+UNUSUAL_DEV( 0x04e6, 0x0007, 0x0100, 0x0200,
+ "Sony",
+ "Hifd",
+ US_SC_SCSI, US_PR_CB, NULL,
+ US_FL_SINGLE_LUN),
+
+UNUSUAL_DEV( 0x04e6, 0x0009, 0x0200, 0x0200,
+ "Shuttle",
+ "eUSB ATA/ATAPI Adapter",
+ US_SC_8020, US_PR_CB, NULL, 0),
+
+UNUSUAL_DEV( 0x04e6, 0x000a, 0x0200, 0x0200,
+ "Shuttle",
+ "eUSB CompactFlash Adapter",
+ US_SC_8020, US_PR_CB, NULL, 0),
+
+UNUSUAL_DEV( 0x04e6, 0x000B, 0x0100, 0x0100,
+ "Shuttle",
+ "eUSCSI Bridge",
+ US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
+ US_FL_SCM_MULT_TARG ),
+
+UNUSUAL_DEV( 0x04e6, 0x000C, 0x0100, 0x0100,
+ "Shuttle",
+ "eUSCSI Bridge",
+ US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
+ US_FL_SCM_MULT_TARG ),
+
+UNUSUAL_DEV( 0x04e6, 0x0101, 0x0200, 0x0200,
+ "Shuttle",
+ "CD-RW Device",
+ US_SC_8020, US_PR_CB, NULL, 0),
+
+UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0210,
+ "Sony",
+ "DSC-S30/S70/505V/F505",
+ US_SC_SCSI, US_PR_CB, NULL,
+ US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE ),
+
+UNUSUAL_DEV( 0x054c, 0x002d, 0x0100, 0x0100,
+ "Sony",
+ "Memorystick MSAC-US1",
+ US_SC_UFI, US_PR_CB, NULL,
+ US_FL_SINGLE_LUN | US_FL_START_STOP ),
+
+UNUSUAL_DEV( 0x057b, 0x0000, 0x0000, 0x0299,
+ "Y-E Data",
+ "Flashbuster-U",
+ US_SC_UFI, US_PR_CB, NULL,
+ US_FL_SINGLE_LUN),
+
+UNUSUAL_DEV( 0x057b, 0x0000, 0x0300, 0x9999,
+ "Y-E Data",
+ "Flashbuster-U",
+ US_SC_UFI, US_PR_CBI, NULL,
+ US_FL_SINGLE_LUN),
+
+UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200,
+ "LaCie",
+ "USB Hard Disk",
+ US_SC_RBC, US_PR_CB, NULL, 0 ),
+
+UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0100,
+ "In-System",
+ "USB/IDE Bridge (ATAPI ONLY!)",
+ US_SC_8070, US_PR_BULK, NULL, 0 ),
+
+UNUSUAL_DEV( 0x0644, 0x0000, 0x0100, 0x0100,
+ "TEAC",
+ "Floppy Drive",
+ US_SC_UFI, US_PR_CB, NULL, 0 ),
+
+#ifdef CONFIG_USB_STORAGE_SDDR09
+UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100,
+ "Olympus",
+ "Camedia MAUSB-2",
+ US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
+ US_FL_SINGLE_LUN | US_FL_START_STOP ),
+#endif
+
+UNUSUAL_DEV( 0x0693, 0x0002, 0x0100, 0x0100,
+ "Hagiwara",
+ "FlashGate SmartMedia",
+ US_SC_SCSI, US_PR_BULK, NULL, 0 ),
+
+UNUSUAL_DEV( 0x0693, 0x0005, 0x0100, 0x0100,
+ "Hagiwara",
+ "Flashgate",
+ US_SC_SCSI, US_PR_BULK, NULL, 0 ),
+
+UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200,
+ "Sandisk",
+ "ImageMate SDDR-05a",
+ US_SC_SCSI, US_PR_CB, NULL,
+ US_FL_SINGLE_LUN | US_FL_START_STOP),
+
+UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100,
+ "Sandisk",
+ "ImageMate SDDR-12",
+ US_SC_SCSI, US_PR_CB, NULL,
+ US_FL_SINGLE_LUN ),
+
+#ifdef CONFIG_USB_STORAGE_SDDR09
+UNUSUAL_DEV( 0x0781, 0x0200, 0x0100, 0x0100,
+ "Sandisk",
+ "ImageMate SDDR-09",
+ US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
+ US_FL_SINGLE_LUN | US_FL_START_STOP ),
+#endif
+
+UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009,
+ "Sandisk",
+ "ImageMate SDDR-31",
+ US_SC_SCSI, US_PR_BULK, NULL,
+ US_FL_IGNORE_SER),
+
+UNUSUAL_DEV( 0x07af, 0x0004, 0x0100, 0x0100,
+ "Microtech",
+ "USB-SCSI-DB25",
+ US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
+ US_FL_SCM_MULT_TARG ),
+
+#ifdef CONFIG_USB_STORAGE_FREECOM
+UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999,
+ "Freecom",
+ "USB-IDE",
+ US_SC_QIC, US_PR_FREECOM, freecom_init, 0),
+#endif
+
+UNUSUAL_DEV( 0x07af, 0x0005, 0x0100, 0x0100,
+ "Microtech",
+ "USB-SCSI-HD50",
+ US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
+ US_FL_SCM_MULT_TARG ),
+
+#ifdef CONFIG_USB_STORAGE_DPCM
+UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100,
+ "Microtech",
+ "CameraMate (DPCM_USB)",
+ US_SC_SCSI, US_PR_DPCM_USB, NULL,
+ US_FL_START_STOP ),
+#endif
+
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 6c254c701..1e0f40f50 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -1,6 +1,6 @@
/* Driver for USB Mass Storage compliant devices
*
- * $Id: usb.c,v 1.57 2000/11/21 02:56:41 mdharm Exp $
+ * $Id: usb.c,v 1.61 2001/01/13 00:10:59 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -11,6 +11,9 @@
* Initial work by:
* (c) 1999 Michael Gee (michael@linuxspecific.com)
*
+ * usb_device_id support by Adam J. Richter (adam@yggdrasil.com):
+ * (c) 2000 Yggdrasil Computing, Inc.
+ *
* This driver is based on the 'USB Mass Storage Class' document. This
* describes in detail the protocol used to communicate with such
* devices. Clearly, the designers had SCSI and ATAPI commands in
@@ -95,11 +98,133 @@ struct semaphore us_list_semaphore;
static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id);
+
static void storage_disconnect(struct usb_device *dev, void *ptr);
+
+/* The entries in this table, except for final ones here
+ * (USB_MASS_STORAGE_CLASS and the empty entry), correspond,
+ * line for line with the entries of us_unsuaul_dev_list[].
+ * For now, we duplicate idVendor and idProduct in us_unsual_dev_list,
+ * just to avoid alignment bugs.
+ */
+
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+ vendorName, productName,useProtocol, useTransport, \
+ initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax) }
+
+static struct usb_device_id storage_usb_ids [] = {
+
+# include "unusual_devs.h"
+#undef UNUSUAL_DEV
+ /* Control/Bulk transport for all SubClass values */
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CB) },
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CB) },
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CB) },
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CB) },
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CB) },
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CB) },
+
+ /* Control/Bulk/Interrupt transport for all SubClass values */
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CBI) },
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CBI) },
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CBI) },
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CBI) },
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CBI) },
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CBI) },
+
+ /* Bulk-only transport for all SubClass values */
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_BULK) },
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_BULK) },
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_BULK) },
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_BULK) },
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_BULK) },
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
+
+ /* Terminating entry */
+ { }
+};
+
+MODULE_DEVICE_TABLE (usb, storage_usb_ids);
+
+/* This is the list of devices we recognize, along with their flag data */
+
+/* The vendor name should be kept at eight characters or less, and
+ * the product name should be kept at 16 characters or less. If a device
+ * has the US_FL_DUMMY_INQUIRY flag, then the vendor and product names
+ * normally generated by a device thorugh the INQUIRY response will be
+ * taken from this list, and this is the reason for the above size
+ * restriction. However, if the flag is not present, then you
+ * are free to use as many characters as you like.
+ */
+
+#undef UNUSUAL_DEV
+#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
+ vendor_name, product_name, use_protocol, use_transport, \
+ init_function, Flags) \
+{ \
+ vendorName: vendor_name, \
+ productName: product_name, \
+ useProtocol: use_protocol, \
+ useTransport: use_transport, \
+ initFunction : init_function, \
+ flags: Flags, \
+}
+
+static struct us_unusual_dev us_unusual_dev_list[] = {
+# include "unusual_devs.h"
+# undef UNUSUAL_DEV
+ /* Control/Bulk transport for all SubClass values */
+ { useProtocol: US_SC_RBC,
+ useTransport: US_PR_CB},
+ { useProtocol: US_SC_8020,
+ useTransport: US_PR_CB},
+ { useProtocol: US_SC_QIC,
+ useTransport: US_PR_CB},
+ { useProtocol: US_SC_UFI,
+ useTransport: US_PR_CB},
+ { useProtocol: US_SC_8070,
+ useTransport: US_PR_CB},
+ { useProtocol: US_SC_SCSI,
+ useTransport: US_PR_CB},
+
+ /* Control/Bulk/Interrupt transport for all SubClass values */
+ { useProtocol: US_SC_RBC,
+ useTransport: US_PR_CBI},
+ { useProtocol: US_SC_8020,
+ useTransport: US_PR_CBI},
+ { useProtocol: US_SC_QIC,
+ useTransport: US_PR_CBI},
+ { useProtocol: US_SC_UFI,
+ useTransport: US_PR_CBI},
+ { useProtocol: US_SC_8070,
+ useTransport: US_PR_CBI},
+ { useProtocol: US_SC_SCSI,
+ useTransport: US_PR_CBI},
+
+ /* Bulk-only transport for all SubClass values */
+ { useProtocol: US_SC_RBC,
+ useTransport: US_PR_BULK},
+ { useProtocol: US_SC_8020,
+ useTransport: US_PR_BULK},
+ { useProtocol: US_SC_QIC,
+ useTransport: US_PR_BULK},
+ { useProtocol: US_SC_UFI,
+ useTransport: US_PR_BULK},
+ { useProtocol: US_SC_8070,
+ useTransport: US_PR_BULK},
+ { useProtocol: US_SC_SCSI,
+ useTransport: US_PR_BULK},
+
+ /* Terminating entry */
+ { 0 }
+};
+
struct usb_driver usb_storage_driver = {
name: "usb-storage",
probe: storage_probe,
disconnect: storage_disconnect,
+ id_table: storage_usb_ids,
};
/*
@@ -325,246 +450,6 @@ static int usb_stor_control_thread(void * __us)
return 0;
}
-/* This is the list of devices we recognize, along with their flag data */
-
-/* The vendor name should be kept at eight characters or less, and
- * the product name should be kept at 16 characters or less. If a device
- * has the US_FL_DUMMY_INQUIRY flag, then the vendor and product names
- * normally generated by a device thorugh the INQUIRY response will be
- * taken from this list, and this is the reason for the above size
- * restriction. However, if the flag is not present, then you
- * are free to use as many characters as you like.
- */
-static struct us_unusual_dev us_unusual_dev_list[] = {
-
- { 0x03ee, 0x0000, 0x0000, 0x0245,
- "Mitsumi",
- "CD-R/RW Drive",
- US_SC_8020, US_PR_CBI, NULL, 0},
-
- { 0x03f0, 0x0107, 0x0200, 0x0200,
- "HP",
- "CD-Writer+",
- US_SC_8070, US_PR_CB, NULL, 0},
-
-#ifdef CONFIG_USB_STORAGE_HP8200e
- { 0x03f0, 0x0207, 0x0001, 0x0001,
- "HP",
- "CD-Writer+ 8200e",
- US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0},
-#endif
-
- { 0x04e6, 0x0001, 0x0200, 0x0200,
- "Matshita",
- "LS-120",
- US_SC_8020, US_PR_CB, NULL, 0},
-
- { 0x04e6, 0x0002, 0x0100, 0x0100,
- "Shuttle",
- "eUSCSI Bridge",
- US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
- US_FL_SCM_MULT_TARG },
-
-#ifdef CONFIG_USB_STORAGE_SDDR09
- { 0x04e6, 0x0003, 0x0000, 0x9999,
- "Sandisk",
- "ImageMate SDDR09",
- US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
- US_FL_SINGLE_LUN | US_FL_START_STOP },
-#endif
-
-#ifdef CONFIG_USB_STORAGE_DPCM
- { 0x0436, 0x0005, 0x0100, 0x0100,
- "Microtech",
- "CameraMate (DPCM_USB)",
- US_SC_SCSI, US_PR_DPCM_USB, NULL,
- US_FL_START_STOP },
-#endif
-
- { 0x04e6, 0x0006, 0x0100, 0x0200,
- "Shuttle",
- "eUSB MMC Adapter",
- US_SC_SCSI, US_PR_CB, NULL,
- US_FL_SINGLE_LUN},
-
- { 0x04e6, 0x0007, 0x0100, 0x0200,
- "Sony",
- "Hifd",
- US_SC_SCSI, US_PR_CB, NULL,
- US_FL_SINGLE_LUN},
-
- { 0x04e6, 0x0009, 0x0200, 0x0200,
- "Shuttle",
- "eUSB ATA/ATAPI Adapter",
- US_SC_8020, US_PR_CB, NULL, 0},
-
- { 0x04e6, 0x000a, 0x0200, 0x0200,
- "Shuttle",
- "eUSB CompactFlash Adapter",
- US_SC_8020, US_PR_CB, NULL, 0},
-
- { 0x04e6, 0x000B, 0x0100, 0x0100,
- "Shuttle",
- "eUSCSI Bridge",
- US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
- US_FL_SCM_MULT_TARG },
-
- { 0x04e6, 0x000C, 0x0100, 0x0100,
- "Shuttle",
- "eUSCSI Bridge",
- US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
- US_FL_SCM_MULT_TARG },
-
- { 0x04e6, 0x0101, 0x0200, 0x0200,
- "Shuttle",
- "CD-RW Device",
- US_SC_8020, US_PR_CB, NULL, 0},
-
- { 0x054c, 0x0010, 0x0106, 0x0210,
- "Sony",
- "DSC-S30/S70/505V/F505",
- US_SC_SCSI, US_PR_CB, NULL,
- US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE },
-
- { 0x054c, 0x002d, 0x0100, 0x0100,
- "Sony",
- "Memorystick MSAC-US1",
- US_SC_UFI, US_PR_CB, NULL,
- US_FL_SINGLE_LUN | US_FL_START_STOP },
-
- { 0x057b, 0x0000, 0x0000, 0x0299,
- "Y-E Data",
- "Flashbuster-U",
- US_SC_UFI, US_PR_CB, NULL,
- US_FL_SINGLE_LUN},
-
- { 0x057b, 0x0000, 0x0300, 0x9999,
- "Y-E Data",
- "Flashbuster-U",
- US_SC_UFI, US_PR_CBI, NULL,
- US_FL_SINGLE_LUN},
-
- { 0x059f, 0xa601, 0x0200, 0x0200,
- "LaCie",
- "USB Hard Disk",
- US_SC_RBC, US_PR_CB, NULL, 0 },
-
- { 0x05ab, 0x0031, 0x0100, 0x0100,
- "In-System",
- "USB/IDE Bridge (ATAPI ONLY!)",
- US_SC_8070, US_PR_BULK, NULL, 0 },
-
- { 0x0644, 0x0000, 0x0100, 0x0100,
- "TEAC",
- "Floppy Drive",
- US_SC_UFI, US_PR_CB, NULL, 0 },
-
-#ifdef CONFIG_USB_STORAGE_SDDR09
- { 0x066b, 0x0105, 0x0100, 0x0100,
- "Olympus",
- "Camedia MAUSB-2",
- US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
- US_FL_SINGLE_LUN | US_FL_START_STOP },
-#endif
-
- { 0x0693, 0x0002, 0x0100, 0x0100,
- "Hagiwara",
- "FlashGate SmartMedia",
- US_SC_SCSI, US_PR_BULK, NULL, 0 },
-
- { 0x0693, 0x0005, 0x0100, 0x0100,
- "Hagiwara",
- "Flashgate",
- US_SC_SCSI, US_PR_BULK, NULL, 0 },
-
- { 0x0781, 0x0001, 0x0200, 0x0200,
- "Sandisk",
- "ImageMate SDDR-05a",
- US_SC_SCSI, US_PR_CB, NULL,
- US_FL_SINGLE_LUN | US_FL_START_STOP},
-
- { 0x0781, 0x0100, 0x0100, 0x0100,
- "Sandisk",
- "ImageMate SDDR-12",
- US_SC_SCSI, US_PR_CB, NULL,
- US_FL_SINGLE_LUN },
-
-#ifdef CONFIG_USB_STORAGE_SDDR09
- { 0x0781, 0x0200, 0x0100, 0x0208,
- "Sandisk",
- "ImageMate SDDR-09",
- US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
- US_FL_SINGLE_LUN | US_FL_START_STOP },
-#endif
-
- { 0x0781, 0x0002, 0x0009, 0x0009,
- "Sandisk",
- "ImageMate SDDR-31",
- US_SC_SCSI, US_PR_BULK, NULL,
- US_FL_IGNORE_SER},
-
- { 0x07af, 0x0004, 0x0100, 0x0100,
- "Microtech",
- "USB-SCSI-DB25",
- US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
- US_FL_SCM_MULT_TARG },
-
-#ifdef CONFIG_USB_STORAGE_FREECOM
- { 0x07ab, 0xfc01, 0x0000, 0x9999,
- "Freecom",
- "USB-IDE",
- US_SC_QIC, US_PR_FREECOM, freecom_init, 0},
-#endif
-
- { 0x07af, 0x0005, 0x0100, 0x0100,
- "Microtech",
- "USB-SCSI-HD50",
- US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
- US_FL_SCM_MULT_TARG },
-
-#ifdef CONFIG_USB_STORAGE_DPCM
- { 0x07af, 0x0006, 0x0100, 0x0100,
- "Microtech",
- "CameraMate (DPCM_USB)",
- US_SC_SCSI, US_PR_DPCM_USB, NULL,
- US_FL_START_STOP },
-#endif
- { 0 }
-};
-
-/* Search our ususual device list, based on vendor/product combinations
- * to see if we can support this device. Returns a pointer to a structure
- * defining how we should support this device, or NULL if it's not in the
- * list
- */
-static struct us_unusual_dev* us_find_dev(u16 idVendor, u16 idProduct,
- u16 bcdDevice)
-{
- struct us_unusual_dev* ptr;
-
- US_DEBUGP("Searching unusual device list for (0x%x, 0x%x, 0x%x)...\n",
- idVendor, idProduct, bcdDevice);
-
- ptr = us_unusual_dev_list;
- while ((ptr->idVendor != 0x0000) &&
- !((ptr->idVendor == idVendor) &&
- (ptr->idProduct == idProduct) &&
- (ptr->bcdDeviceMin <= bcdDevice) &&
- (ptr->bcdDeviceMax >= bcdDevice)))
- ptr++;
-
- /* if the search ended because we hit the end record, we failed */
- if (ptr->idVendor == 0x0000) {
- US_DEBUGP("-- did not find a matching device\n");
- return NULL;
- }
-
- /* otherwise, we found one! */
- US_DEBUGP("-- found matching device: %s %s\n", ptr->vendorName,
- ptr->productName);
- return ptr;
-}
-
/* Set up the IRQ pipe and handler
* Note that this function assumes that all the data in the us_data
* strucuture is current. This includes the ep_int field, which gives us
@@ -620,6 +505,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id)
{
int i;
+ const int id_index = id - storage_usb_ids;
char mf[USB_STOR_STRING_LEN]; /* manufacturer */
char prod[USB_STOR_STRING_LEN]; /* product */
char serial[USB_STOR_STRING_LEN]; /* serial number */
@@ -640,47 +526,48 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
u8 subclass = 0;
u8 protocol = 0;
- /* the altsettting 0 on the interface we're probing */
- struct usb_interface_descriptor *altsetting =
- &(dev->actconfig->interface[ifnum].altsetting[0]);
+ /* the altsettting on the interface we're probing that matched our
+ * usb_match_id table
+ */
+ struct usb_interface *intf = dev->actconfig->interface;
+ struct usb_interface_descriptor *altsetting =
+ intf[ifnum].altsetting + intf[ifnum].act_altsetting;
+ US_DEBUGP("act_altsettting is %d\n", intf[ifnum].act_altsetting);
/* clear the temporary strings */
memset(mf, 0, sizeof(mf));
memset(prod, 0, sizeof(prod));
memset(serial, 0, sizeof(serial));
- /* search for this device in our unusual device list */
- unusual_dev = us_find_dev(dev->descriptor.idVendor,
- dev->descriptor.idProduct,
- dev->descriptor.bcdDevice);
-
/*
* Can we support this device, either because we know about it
* from our unusual device list, or because it advertises that it's
* compliant to the specification?
+ *
+ * id_index is calculated in the declaration to be the index number
+ * of the match from the usb_device_id table, so we can find the
+ * corresponding entry in the private table.
*/
- if (!unusual_dev &&
- !(dev->descriptor.bDeviceClass == 0 &&
- altsetting->bInterfaceClass == USB_CLASS_MASS_STORAGE &&
- altsetting->bInterfaceSubClass >= US_SC_MIN &&
- altsetting->bInterfaceSubClass <= US_SC_MAX)) {
- /* if it's not a mass storage, we go no further */
+ US_DEBUGP("id_index calculated to be: %d\n", id_index);
+ US_DEBUGP("Array length appears to be: %d\n", sizeof(us_unusual_dev_list) / sizeof(us_unusual_dev_list[0]));
+ if (id_index <
+ sizeof(us_unusual_dev_list) / sizeof(us_unusual_dev_list[0])) {
+ unusual_dev = &us_unusual_dev_list[id_index];
+ if (unusual_dev->vendorName)
+ US_DEBUGP("Vendor: %s\n", unusual_dev->vendorName);
+ if (unusual_dev->productName)
+ US_DEBUGP("Product: %s\n", unusual_dev->productName);
+ } else
+ /* no, we can't support it */
return NULL;
- }
/* At this point, we know we've got a live one */
US_DEBUGP("USB Mass Storage device detected\n");
/* Determine subclass and protocol, or copy from the interface */
- if (unusual_dev) {
- subclass = unusual_dev->useProtocol;
- protocol = unusual_dev->useTransport;
- flags = unusual_dev->flags;
- } else {
- subclass = altsetting->bInterfaceSubClass;
- protocol = altsetting->bInterfaceProtocol;
- flags = 0;
- }
+ subclass = unusual_dev->useProtocol;
+ protocol = unusual_dev->useTransport;
+ flags = unusual_dev->flags;
/*
* Find the endpoints we need
@@ -728,7 +615,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
/* Do some basic sanity checks, and bail if we find a problem */
if (!ep_in || !ep_out || (protocol == US_PR_CBI && !ep_int)) {
- US_DEBUGP("Sanity check failed. Rejecting device.\n");
+ US_DEBUGP("Endpoint sanity check failed! Rejecting dev.\n");
return NULL;
}
@@ -861,7 +748,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
strncpy(ss->product, prod, USB_STOR_STRING_LEN);
strncpy(ss->serial, serial, USB_STOR_STRING_LEN);
if (strlen(ss->vendor) == 0) {
- if (unusual_dev)
+ if (unusual_dev->vendorName)
strncpy(ss->vendor, unusual_dev->vendorName,
USB_STOR_STRING_LEN);
else
@@ -869,7 +756,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
USB_STOR_STRING_LEN);
}
if (strlen(ss->product) == 0) {
- if (unusual_dev)
+ if (unusual_dev->productName)
strncpy(ss->product, unusual_dev->productName,
USB_STOR_STRING_LEN);
else
@@ -1118,6 +1005,8 @@ static void storage_disconnect(struct usb_device *dev, void *ptr)
int __init usb_stor_init(void)
{
+ printk(KERN_INFO "Initializing USB Mass Storage driver...\n");
+
/* initialize internal global data elements */
us_list = NULL;
init_MUTEX(&us_list_semaphore);
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index e0dac568d..9c8076c8d 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -1,7 +1,7 @@
/* Driver for USB Mass Storage compliant devices
* Main Header File
*
- * $Id: usb.h,v 1.11 2000/11/13 22:38:55 mdharm Exp $
+ * $Id: usb.h,v 1.12 2000/12/05 03:33:49 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -84,13 +84,6 @@ struct us_data;
*/
struct us_unusual_dev {
- /* we search the list based on these parameters */
- __u16 idVendor;
- __u16 idProduct;
- __u16 bcdDeviceMin;
- __u16 bcdDeviceMax;
-
- /* the list specifies these parameters */
const char* vendorName;
const char* productName;
__u8 useProtocol;
diff --git a/drivers/video/sbusfb.c b/drivers/video/sbusfb.c
index f9fa0d213..4d5b66386 100644
--- a/drivers/video/sbusfb.c
+++ b/drivers/video/sbusfb.c
@@ -678,7 +678,7 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
int end, count, index;
struct fbcmap *cmap;
- if (!fb->loadcmap)
+ if (!fb->loadcmap || !fb->color_map)
return -EINVAL;
i = verify_area (VERIFY_READ, (void *) arg, sizeof (struct fbcmap));
if (i) return i;
@@ -1110,6 +1110,8 @@ sizechange:
}
if (!p) {
+ if (fb->color_map)
+ kfree(fb->color_map);
kfree(fb);
return;
}
@@ -1147,6 +1149,8 @@ sizechange:
sbusfb_set_var(var, -1, &fb->info);
if (register_framebuffer(&fb->info) < 0) {
+ if (fb->color_map)
+ kfree(fb->color_map);
kfree(fb);
return;
}
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index 8833cbeac..b494e25c6 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -461,7 +461,7 @@ static u_long get_line_length(int xres_virtual, int bpp)
{
u_long length;
- length = (xres_virtual+bpp-1)/bpp;
+ length = xres_virtual*bpp;
length = (length+31)&-32;
length >>= 3;
return(length);