## Automatically generated incremental diff
## From: linux-2.6.3-rc3
## To: linux-2.6.3-rc4
## Robot: $Id: make-incremental-diff,v 1.12 2004/01/06 07:19:36 hpa Exp $
diff -urN linux-2.6.3-rc3/Documentation/DocBook/kernel-locking.tmpl linux-2.6.3-rc4/Documentation/DocBook/kernel-locking.tmpl
--- linux-2.6.3-rc3/Documentation/DocBook/kernel-locking.tmpl 2004-02-03 19:43:42.000000000 -0800
+++ linux-2.6.3-rc4/Documentation/DocBook/kernel-locking.tmpl 2004-02-16 19:49:16.000000000 -0800
@@ -1444,27 +1444,6 @@
-
- The Fucked Up Sparc
-
-
- Alan Cox says the irq disable/enable is in the register
- window on a sparc
. Andi Kleen says when you do
- restore_flags in a different function you mess up all the
- register windows
.
-
-
-
- So never pass the flags word set by
- spin_lock_irqsave() and brethren to another
- function (unless it's declared inline). Usually no-one
- does this, but now you've been warned. Dave Miller can never do
- anything in a straightforward manner (I can say that, because I have
- pictures of him and a certain PowerPC maintainer in a compromising
- position).
-
-
-
diff -urN linux-2.6.3-rc3/Makefile linux-2.6.3-rc4/Makefile
--- linux-2.6.3-rc3/Makefile 2004-02-16 19:49:10.000000000 -0800
+++ linux-2.6.3-rc4/Makefile 2004-02-16 19:49:16.000000000 -0800
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 3
-EXTRAVERSION =-rc3
+EXTRAVERSION =-rc4
NAME=Feisty Dunnart
# *DOCUMENTATION*
diff -urN linux-2.6.3-rc3/arch/ppc/8260_io/uart.c linux-2.6.3-rc4/arch/ppc/8260_io/uart.c
--- linux-2.6.3-rc3/arch/ppc/8260_io/uart.c 2004-02-03 19:43:09.000000000 -0800
+++ linux-2.6.3-rc4/arch/ppc/8260_io/uart.c 2004-02-16 19:49:16.000000000 -0800
@@ -5,6 +5,9 @@
* 2.3.99 updates
* Copyright (c) 2002 Allen Curtis, Ones and Zeros, Inc. (acurtis@onz.com)
* 2.5.50 updates
+ * Fix the console driver to be registered with initcalls and some minor fixup
+ * for 2.6.2, by Petter Larsen, moreCom as (petter.larsen@morecom.no) and
+ * Miguel Valero, AxxessIT ASA (miguel.valero@axxessit.no)
*
* I used the 8xx uart.c driver as the framework for this driver.
* The original code was written for the EST8260 board. I tried to make
@@ -75,11 +78,11 @@
static char *serial_version = "0.02";
static struct tty_driver *serial_driver;
-static int serial_console_setup(struct console *co, char *options);
-
+static int __init serial_console_setup( struct console *co, char *options);
static void serial_console_write(struct console *c, const char *s,
unsigned count);
-static kdev_t serial_console_device(struct console *c);
+
+static struct tty_driver *serial_console_device(struct console *c, int *index);
#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
static unsigned long break_pressed; /* break, really ... */
@@ -533,8 +536,6 @@
*(tty->flip.flag_buf_ptr++) = TTY_BREAK;
*(tty->flip.char_buf_ptr++) = 0;
tty->flip.count++;
-
- queue_task(&tty->flip.tqueue, &tq_timer);
}
@@ -1864,8 +1865,8 @@
{
#ifdef DO_THIS_LATER
DECLARE_WAITQUEUE(wait, current);
-#endif
struct serial_state *state = info->state;
+#endif
int retval;
int do_clocal = 0;
@@ -2467,12 +2468,14 @@
/*
* Register console.
*/
-long __init console_8xx_init(long kmem_start, long kmem_end)
+static int __init console_8xx_init(void)
{
register_console(&sercons);
- return kmem_start;
+ return 0;
}
+console_initcall(console_8xx_init);
+
#endif
/* Default console baud rate as determined by the board information
@@ -2879,8 +2882,10 @@
volatile smc_t *sp;
volatile smc_uart_t *up;
#endif
+#ifdef SCC_CONSOLE
volatile scc_t *scp;
volatile scc_uart_t *sup;
+#endif
volatile iop8260_t *io;
bd_t *bd;
diff -urN linux-2.6.3-rc3/arch/ppc/kernel/head.S linux-2.6.3-rc4/arch/ppc/kernel/head.S
--- linux-2.6.3-rc3/arch/ppc/kernel/head.S 2004-02-16 19:49:10.000000000 -0800
+++ linux-2.6.3-rc4/arch/ppc/kernel/head.S 2004-02-16 19:49:16.000000000 -0800
@@ -1657,7 +1657,7 @@
andc r11, r11, r10
mtspr HID0, r11
isync
- li r5, MSR_
+ li r5, MSR_ME|MSR_RI
lis r6,2f@h
addis r6,r6,-KERNELBASE@h
ori r6,r6,2f@l
diff -urN linux-2.6.3-rc3/arch/ppc/platforms/prep_pci.c linux-2.6.3-rc4/arch/ppc/platforms/prep_pci.c
--- linux-2.6.3-rc3/arch/ppc/platforms/prep_pci.c 2004-02-03 19:44:56.000000000 -0800
+++ linux-2.6.3-rc4/arch/ppc/platforms/prep_pci.c 2004-02-16 19:49:16.000000000 -0800
@@ -1171,8 +1171,6 @@
prep_pcibios_fixup(void)
{
struct pci_dev *dev = NULL;
- extern unsigned char *Motherboard_map;
- extern unsigned char *Motherboard_routes;
prep_route_pci_interrupts();
diff -urN linux-2.6.3-rc3/arch/ppc64/kernel/pSeries_lpar.c linux-2.6.3-rc4/arch/ppc64/kernel/pSeries_lpar.c
--- linux-2.6.3-rc3/arch/ppc64/kernel/pSeries_lpar.c 2004-02-16 19:49:10.000000000 -0800
+++ linux-2.6.3-rc4/arch/ppc64/kernel/pSeries_lpar.c 2004-02-16 19:49:16.000000000 -0800
@@ -296,6 +296,8 @@
{
pSeries_lpar_mm_init();
+ tce_init_pSeries();
+
ppc_md.tce_build = tce_build_pSeriesLP;
ppc_md.tce_free_one = tce_free_one_pSeriesLP;
diff -urN linux-2.6.3-rc3/arch/ppc64/kernel/rtasd.c linux-2.6.3-rc4/arch/ppc64/kernel/rtasd.c
--- linux-2.6.3-rc3/arch/ppc64/kernel/rtasd.c 2004-02-03 19:43:38.000000000 -0800
+++ linux-2.6.3-rc4/arch/ppc64/kernel/rtasd.c 2004-02-16 19:49:16.000000000 -0800
@@ -347,6 +347,8 @@
int event_scan = rtas_token("event-scan");
int rc;
+ daemonize("rtasd");
+
if (event_scan == RTAS_UNKNOWN_SERVICE || get_eventscan_parms() == -1)
goto error;
@@ -359,15 +361,9 @@
/* We can use rtas_log_buf now */
no_more_logging = 0;
- DEBUG("will sleep for %d jiffies\n", (HZ*60/rtas_event_scan_rate) / 2);
-
- daemonize("rtasd");
+ printk(KERN_ERR "RTAS daemon started\n");
-#if 0
- /* Rusty unreal time task */
- current->policy = SCHED_FIFO;
- current->nice = sys_sched_get_priority_max(SCHED_FIFO) + 1;
-#endif
+ DEBUG("will sleep for %d jiffies\n", (HZ*60/rtas_event_scan_rate) / 2);
/* See if we have any error stored in NVRAM */
memset(logdata, 0, rtas_error_log_max);
@@ -423,7 +419,9 @@
goto repeat;
error_vfree:
- vfree(rtas_log_buf);
+ if (rtas_log_buf)
+ vfree(rtas_log_buf);
+ rtas_log_buf = NULL;
error:
/* Should delete proc entries */
return -EINVAL;
@@ -451,8 +449,6 @@
if (kernel_thread(rtasd, 0, CLONE_FS) < 0)
printk(KERN_ERR "Failed to start RTAS daemon\n");
- printk(KERN_ERR "RTAS daemon started\n");
-
/* Make room for the sequence number */
rtas_error_log_buffer_max = rtas_error_log_max + sizeof(int);
diff -urN linux-2.6.3-rc3/drivers/ide/arm/icside.c linux-2.6.3-rc4/drivers/ide/arm/icside.c
--- linux-2.6.3-rc3/drivers/ide/arm/icside.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/arm/icside.c 2004-02-16 19:49:17.000000000 -0800
@@ -341,12 +341,6 @@
return icside_dma_host_off(drive);
}
-static int icside_dma_off(ide_drive_t *drive)
-{
- printk("%s: DMA disabled\n", drive->name);
- return icside_dma_off_quietly(drive);
-}
-
static int icside_dma_host_on(ide_drive_t *drive)
{
return 0;
@@ -428,11 +422,6 @@
return 0;
}
-static int icside_dma_count(ide_drive_t *drive)
-{
- return icside_dma_begin(drive);
-}
-
/*
* dma_intr() is the handler for disk read/write DMA interrupts
*/
@@ -648,12 +637,10 @@
hwif->ide_dma_check = icside_dma_check;
hwif->ide_dma_host_off = icside_dma_host_off;
hwif->ide_dma_off_quietly = icside_dma_off_quietly;
- hwif->ide_dma_off = icside_dma_off;
hwif->ide_dma_host_on = icside_dma_host_on;
hwif->ide_dma_on = icside_dma_on;
hwif->ide_dma_read = icside_dma_read;
hwif->ide_dma_write = icside_dma_write;
- hwif->ide_dma_count = icside_dma_count;
hwif->ide_dma_begin = icside_dma_begin;
hwif->ide_dma_end = icside_dma_end;
hwif->ide_dma_test_irq = icside_dma_test_irq;
diff -urN linux-2.6.3-rc3/drivers/ide/ide-cd.c linux-2.6.3-rc4/drivers/ide/ide-cd.c
--- linux-2.6.3-rc3/drivers/ide/ide-cd.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/ide-cd.c 2004-02-16 19:49:17.000000000 -0800
@@ -1101,7 +1101,7 @@
if (dma) {
info->dma = 0;
if ((dma_error = HWIF(drive)->ide_dma_end(drive)))
- HWIF(drive)->ide_dma_off(drive);
+ __ide_dma_off(drive);
}
if (cdrom_decode_status(drive, 0, &stat))
@@ -1720,7 +1720,7 @@
if (dma) {
if (dma_error) {
printk("ide-cd: dma error\n");
- HWIF(drive)->ide_dma_off(drive);
+ __ide_dma_off(drive);
return DRIVER(drive)->error(drive, "dma error", stat);
}
@@ -1847,7 +1847,7 @@
info->dma = 0;
if ((dma_error = HWIF(drive)->ide_dma_end(drive))) {
printk("ide-cd: write dma error\n");
- HWIF(drive)->ide_dma_off(drive);
+ __ide_dma_off(drive);
}
}
diff -urN linux-2.6.3-rc3/drivers/ide/ide-dma.c linux-2.6.3-rc4/drivers/ide/ide-dma.c
--- linux-2.6.3-rc3/drivers/ide/ide-dma.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/ide-dma.c 2004-02-16 19:49:17.000000000 -0800
@@ -413,8 +413,8 @@
if ((id->capability & 1) && hwif->autodma) {
/* Consult the list of known "bad" drives */
- if (hwif->ide_dma_bad_drive(drive))
- return hwif->ide_dma_off(drive);
+ if (__ide_dma_bad_drive(drive))
+ return __ide_dma_off(drive);
/*
* Enable DMA on any drive that has
@@ -432,7 +432,7 @@
return hwif->ide_dma_on(drive);
/* Consult the list of known "good" drives */
- if (hwif->ide_dma_good_drive(drive))
+ if (__ide_dma_good_drive(drive))
return hwif->ide_dma_on(drive);
}
// if (hwif->tuneproc != NULL) hwif->tuneproc(drive, 255);
@@ -520,13 +520,14 @@
}
EXPORT_SYMBOL(__ide_dma_off_quietly);
+#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
/**
- * __ide_dma_host_off - Generic DMA kill
- * @drive: drive to control
+ * __ide_dma_off - disable DMA on a device
+ * @drive: drive to disable DMA on
*
- * Turn off the current DMA on this IDE controller. Inform the
- * user that DMA has been disabled.
+ * Disable IDE DMA for a device on this IDE controller.
+ * Inform the user that DMA has been disabled.
*/
int __ide_dma_off (ide_drive_t *drive)
@@ -537,6 +538,7 @@
EXPORT_SYMBOL(__ide_dma_off);
+#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
/**
* __ide_dma_host_on - Enable DMA on a host
* @drive: drive to enable for DMA
@@ -662,7 +664,7 @@
/* issue cmd to drive */
ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry);
- return HWIF(drive)->ide_dma_count(drive);
+ return hwif->ide_dma_begin(drive);
}
EXPORT_SYMBOL(__ide_dma_read);
@@ -694,7 +696,7 @@
/* issue cmd to drive */
ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry);
- return HWIF(drive)->ide_dma_count(drive);
+ return hwif->ide_dma_begin(drive);
}
EXPORT_SYMBOL(__ide_dma_write);
@@ -791,17 +793,6 @@
EXPORT_SYMBOL(__ide_dma_good_drive);
#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
-/*
- * Used for HOST FIFO counters for VDMA
- * PIO over DMA, effective ATA-Bridge operator.
- */
-int __ide_dma_count (ide_drive_t *drive)
-{
- return HWIF(drive)->ide_dma_begin(drive);
-}
-
-EXPORT_SYMBOL(__ide_dma_count);
-
int __ide_dma_verbose (ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
@@ -1060,8 +1051,6 @@
if (!(hwif->dma_prdtable))
hwif->dma_prdtable = (hwif->dma_base + 4);
- if (!hwif->ide_dma_off)
- hwif->ide_dma_off = &__ide_dma_off;
if (!hwif->ide_dma_off_quietly)
hwif->ide_dma_off_quietly = &__ide_dma_off_quietly;
if (!hwif->ide_dma_host_off)
@@ -1076,18 +1065,12 @@
hwif->ide_dma_read = &__ide_dma_read;
if (!hwif->ide_dma_write)
hwif->ide_dma_write = &__ide_dma_write;
- if (!hwif->ide_dma_count)
- hwif->ide_dma_count = &__ide_dma_count;
if (!hwif->ide_dma_begin)
hwif->ide_dma_begin = &__ide_dma_begin;
if (!hwif->ide_dma_end)
hwif->ide_dma_end = &__ide_dma_end;
if (!hwif->ide_dma_test_irq)
hwif->ide_dma_test_irq = &__ide_dma_test_irq;
- if (!hwif->ide_dma_bad_drive)
- hwif->ide_dma_bad_drive = &__ide_dma_bad_drive;
- if (!hwif->ide_dma_good_drive)
- hwif->ide_dma_good_drive = &__ide_dma_good_drive;
if (!hwif->ide_dma_verbose)
hwif->ide_dma_verbose = &__ide_dma_verbose;
if (!hwif->ide_dma_timeout)
diff -urN linux-2.6.3-rc3/drivers/ide/ide-floppy.c linux-2.6.3-rc4/drivers/ide/ide-floppy.c
--- linux-2.6.3-rc3/drivers/ide/ide-floppy.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/ide-floppy.c 2004-02-16 19:49:17.000000000 -0800
@@ -830,7 +830,7 @@
if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
printk(KERN_ERR "ide-floppy: The floppy wants to issue "
"more interrupts in DMA mode\n");
- (void) HWIF(drive)->ide_dma_off(drive);
+ (void)__ide_dma_off(drive);
return ide_do_reset(drive);
}
@@ -1045,7 +1045,7 @@
bcount.all = min(pc->request_transfer, 63 * 1024);
if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) {
- (void) HWIF(drive)->ide_dma_off(drive);
+ (void)__ide_dma_off(drive);
}
feature.all = 0;
diff -urN linux-2.6.3-rc3/drivers/ide/ide-iops.c linux-2.6.3-rc4/drivers/ide/ide-iops.c
--- linux-2.6.3-rc3/drivers/ide/ide-iops.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/ide-iops.c 2004-02-16 19:49:17.000000000 -0800
@@ -830,7 +830,8 @@
// ide_delay_50ms();
#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI)
- hwif->ide_dma_host_off(drive);
+ if (hwif->ide_dma_check) /* check if host supports DMA */
+ hwif->ide_dma_host_off(drive);
#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */
/*
@@ -906,10 +907,12 @@
drive->id->dma_1word &= ~0x0F00;
#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI)
- if (speed >= XFER_SW_DMA_0)
+ if (speed >= XFER_SW_DMA_0) {
hwif->ide_dma_host_on(drive);
- else
- hwif->ide_dma_off_quietly(drive);
+ } else {
+ if (hwif->ide_dma_check) /* check if host supports DMA */
+ hwif->ide_dma_off_quietly(drive);
+ }
#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */
switch(speed) {
@@ -1130,7 +1133,7 @@
if (drive->current_speed >= XFER_SW_DMA_0)
(void) HWIF(drive)->ide_dma_on(drive);
} else {
- (void) HWIF(drive)->ide_dma_off(drive);
+ (void)__ide_dma_off(drive);
}
}
diff -urN linux-2.6.3-rc3/drivers/ide/ide-tape.c linux-2.6.3-rc4/drivers/ide/ide-tape.c
--- linux-2.6.3-rc3/drivers/ide/ide-tape.c 2004-02-03 19:43:41.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/ide-tape.c 2004-02-16 19:49:17.000000000 -0800
@@ -2198,7 +2198,7 @@
printk(KERN_ERR "ide-tape: The tape wants to issue more "
"interrupts in DMA mode\n");
printk(KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n");
- (void) HWIF(drive)->ide_dma_off(drive);
+ (void)__ide_dma_off(drive);
return ide_do_reset(drive);
}
/* Get the number of bytes to transfer on this interrupt. */
@@ -2411,7 +2411,7 @@
if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) {
printk(KERN_WARNING "ide-tape: DMA disabled, "
"reverting to PIO\n");
- (void) HWIF(drive)->ide_dma_off(drive);
+ (void)__ide_dma_off(drive);
}
if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) {
if (test_bit(PC_WRITING, &pc->flags))
@@ -3212,7 +3212,7 @@
#endif /* IDETAPE_DEBUG_BUGS */
rq->waiting = &wait;
tape->waiting = &wait;
- spin_unlock(&tape->spinlock);
+ spin_unlock_irq(&tape->spinlock);
wait_for_completion(&wait);
/* The stage and its struct request have been deallocated */
tape->waiting = NULL;
@@ -6442,12 +6442,12 @@
goto failed;
}
if (drive->scsi) {
- if (strstr(drive->id->model, "OnStream DI-")) {
- printk("ide-tape: ide-scsi emulation is not supported for %s.\n", drive->id->model);
- } else {
- printk("ide-tape: passing drive %s to ide-scsi emulation.\n", drive->name);
- goto failed;
- }
+ printk("ide-tape: passing drive %s to ide-scsi emulation.\n", drive->name);
+ goto failed;
+ }
+ if (strstr(drive->id->model, "OnStream DI-")) {
+ printk(KERN_WARNING "ide-tape: Use drive %s with ide-scsi emulation and osst.\n", drive->name);
+ printk(KERN_WARNING "ide-tape: OnStream support will be removed soon from ide-tape!\n");
}
tape = (idetape_tape_t *) kmalloc (sizeof (idetape_tape_t), GFP_KERNEL);
if (tape == NULL) {
diff -urN linux-2.6.3-rc3/drivers/ide/ide.c linux-2.6.3-rc4/drivers/ide/ide.c
--- linux-2.6.3-rc3/drivers/ide/ide.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/ide.c 2004-02-16 19:49:17.000000000 -0800
@@ -839,14 +839,10 @@
hwif->ide_dma_end = old_hwif.ide_dma_end;
hwif->ide_dma_check = old_hwif.ide_dma_check;
hwif->ide_dma_on = old_hwif.ide_dma_on;
- hwif->ide_dma_off = old_hwif.ide_dma_off;
hwif->ide_dma_off_quietly = old_hwif.ide_dma_off_quietly;
hwif->ide_dma_test_irq = old_hwif.ide_dma_test_irq;
hwif->ide_dma_host_on = old_hwif.ide_dma_host_on;
hwif->ide_dma_host_off = old_hwif.ide_dma_host_off;
- hwif->ide_dma_bad_drive = old_hwif.ide_dma_bad_drive;
- hwif->ide_dma_good_drive = old_hwif.ide_dma_good_drive;
- hwif->ide_dma_count = old_hwif.ide_dma_count;
hwif->ide_dma_verbose = old_hwif.ide_dma_verbose;
hwif->ide_dma_lostirq = old_hwif.ide_dma_lostirq;
hwif->ide_dma_timeout = old_hwif.ide_dma_timeout;
@@ -1332,7 +1328,8 @@
if (HWIF(drive)->ide_dma_check(drive)) return -EIO;
if (HWIF(drive)->ide_dma_on(drive)) return -EIO;
} else {
- if (HWIF(drive)->ide_dma_off(drive)) return -EIO;
+ if (__ide_dma_off(drive))
+ return -EIO;
}
return 0;
}
diff -urN linux-2.6.3-rc3/drivers/ide/pci/aec62xx.c linux-2.6.3-rc4/drivers/ide/pci/aec62xx.c
--- linux-2.6.3-rc3/drivers/ide/pci/aec62xx.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/pci/aec62xx.c 2004-02-16 19:49:17.000000000 -0800
@@ -330,7 +330,7 @@
if ((id->capability & 1) && drive->autodma) {
/* Consult the list of known "bad" drives */
- if (hwif->ide_dma_bad_drive(drive))
+ if (__ide_dma_bad_drive(drive))
goto fast_ata_pio;
if (id->field_valid & 4) {
if (id->dma_ultra & hwif->ultra_mask) {
@@ -347,7 +347,7 @@
if (!config_chipset_for_dma(drive))
goto no_dma_set;
}
- } else if (hwif->ide_dma_good_drive(drive) &&
+ } else if (__ide_dma_good_drive(drive) &&
(id->eide_dma_time < 150)) {
/* Consult the list of known "good" drives */
if (!config_chipset_for_dma(drive))
diff -urN linux-2.6.3-rc3/drivers/ide/pci/alim15x3.c linux-2.6.3-rc4/drivers/ide/pci/alim15x3.c
--- linux-2.6.3-rc3/drivers/ide/pci/alim15x3.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/pci/alim15x3.c 2004-02-16 19:49:17.000000000 -0800
@@ -516,7 +516,7 @@
if ((id != NULL) && ((id->capability & 1) != 0) && drive->autodma) {
/* Consult the list of known "bad" drives */
- if (hwif->ide_dma_bad_drive(drive))
+ if (__ide_dma_bad_drive(drive))
goto ata_pio;
if ((id->field_valid & 4) && (m5229_revision >= 0xC2)) {
if (id->dma_ultra & hwif->ultra_mask) {
@@ -533,7 +533,7 @@
if (!config_chipset_for_dma(drive))
goto no_dma_set;
}
- } else if (hwif->ide_dma_good_drive(drive) &&
+ } else if (__ide_dma_good_drive(drive) &&
(id->eide_dma_time < 150)) {
/* Consult the list of known "good" drives */
if (!config_chipset_for_dma(drive))
diff -urN linux-2.6.3-rc3/drivers/ide/pci/cmd64x.c linux-2.6.3-rc4/drivers/ide/pci/cmd64x.c
--- linux-2.6.3-rc3/drivers/ide/pci/cmd64x.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/pci/cmd64x.c 2004-02-16 19:49:17.000000000 -0800
@@ -459,7 +459,7 @@
if ((id != NULL) && ((id->capability & 1) != 0) && drive->autodma) {
/* Consult the list of known "bad" drives */
- if (hwif->ide_dma_bad_drive(drive))
+ if (__ide_dma_bad_drive(drive))
goto fast_ata_pio;
if ((id->field_valid & 4) && cmd64x_ratemask(drive)) {
if (id->dma_ultra & hwif->ultra_mask) {
@@ -476,7 +476,7 @@
if (!config_chipset_for_dma(drive))
goto no_dma_set;
}
- } else if (hwif->ide_dma_good_drive(drive) &&
+ } else if (__ide_dma_good_drive(drive) &&
(id->eide_dma_time < 150)) {
/* Consult the list of known "good" drives */
if (!config_chipset_for_dma(drive))
diff -urN linux-2.6.3-rc3/drivers/ide/pci/cs5530.c linux-2.6.3-rc4/drivers/ide/pci/cs5530.c
--- linux-2.6.3-rc3/drivers/ide/pci/cs5530.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/pci/cs5530.c 2004-02-16 19:49:17.000000000 -0800
@@ -180,7 +180,7 @@
if (mate->present) {
struct hd_driveid *mateid = mate->id;
if (mateid && (mateid->capability & 1) &&
- !hwif->ide_dma_bad_drive(mate)) {
+ !__ide_dma_bad_drive(mate)) {
if ((mateid->field_valid & 4) &&
(mateid->dma_ultra & 7))
udma_ok = 1;
@@ -197,7 +197,7 @@
* selecting UDMA only if the mate said it was ok.
*/
if (id && (id->capability & 1) && drive->autodma &&
- !hwif->ide_dma_bad_drive(drive)) {
+ !__ide_dma_bad_drive(drive)) {
if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) {
if (id->dma_ultra & 4)
mode = XFER_UDMA_2;
diff -urN linux-2.6.3-rc3/drivers/ide/pci/hpt34x.c linux-2.6.3-rc4/drivers/ide/pci/hpt34x.c
--- linux-2.6.3-rc3/drivers/ide/pci/hpt34x.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/pci/hpt34x.c 2004-02-16 19:49:17.000000000 -0800
@@ -190,7 +190,7 @@
if (id && (id->capability & 1) && drive->autodma) {
/* Consult the list of known "bad" drives */
- if (hwif->ide_dma_bad_drive(drive))
+ if (__ide_dma_bad_drive(drive))
goto fast_ata_pio;
if (id->field_valid & 4) {
if (id->dma_ultra & hwif->ultra_mask) {
@@ -207,7 +207,7 @@
if (!config_chipset_for_dma(drive))
goto no_dma_set;
}
- } else if (hwif->ide_dma_good_drive(drive) &&
+ } else if (__ide_dma_good_drive(drive) &&
(id->eide_dma_time < 150)) {
/* Consult the list of known "good" drives */
if (!config_chipset_for_dma(drive))
diff -urN linux-2.6.3-rc3/drivers/ide/pci/hpt366.c linux-2.6.3-rc4/drivers/ide/pci/hpt366.c
--- linux-2.6.3-rc3/drivers/ide/pci/hpt366.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/pci/hpt366.c 2004-02-16 19:49:17.000000000 -0800
@@ -514,7 +514,7 @@
if (id && (id->capability & 1) && drive->autodma) {
/* Consult the list of known "bad" drives */
- if (hwif->ide_dma_bad_drive(drive))
+ if (__ide_dma_bad_drive(drive))
goto fast_ata_pio;
if (id->field_valid & 4) {
if (id->dma_ultra & hwif->ultra_mask) {
@@ -530,7 +530,7 @@
if (!config_chipset_for_dma(drive))
goto no_dma_set;
}
- } else if (hwif->ide_dma_good_drive(drive) &&
+ } else if (__ide_dma_good_drive(drive) &&
(id->eide_dma_time < 150)) {
/* Consult the list of known "good" drives */
if (!config_chipset_for_dma(drive))
diff -urN linux-2.6.3-rc3/drivers/ide/pci/it8172.c linux-2.6.3-rc4/drivers/ide/pci/it8172.c
--- linux-2.6.3-rc3/drivers/ide/pci/it8172.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/pci/it8172.c 2004-02-16 19:49:17.000000000 -0800
@@ -202,7 +202,7 @@
if (id && (id->capability & 1) && drive->autodma) {
/* Consult the list of known "bad" drives */
- if (hwif->ide_dma_bad_drive(drive))
+ if (__ide_dma_bad_drive(drive))
goto fast_ata_pio;
if (id->field_valid & 4) {
if (id->dma_ultra & hwif->ultra_mask) {
@@ -219,7 +219,7 @@
if (!it8172_config_chipset_for_dma(drive))
goto no_dma_set;
}
- } else if (hwif->ide_dma_good_drive(drive) &&
+ } else if (__ide_dma_good_drive(drive) &&
(id->eide_dma_time < 150)) {
/* Consult the list of known "good" drives */
if (!it8172_config_chipset_for_dma(drive))
diff -urN linux-2.6.3-rc3/drivers/ide/pci/pdc202xx_new.c linux-2.6.3-rc4/drivers/ide/pci/pdc202xx_new.c
--- linux-2.6.3-rc3/drivers/ide/pci/pdc202xx_new.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/pci/pdc202xx_new.c 2004-02-16 19:49:17.000000000 -0800
@@ -393,7 +393,7 @@
if (id && (id->capability & 1) && drive->autodma) {
/* Consult the list of known "bad" drives */
- if (hwif->ide_dma_bad_drive(drive))
+ if (__ide_dma_bad_drive(drive))
goto fast_ata_pio;
if (id->field_valid & 4) {
if (id->dma_ultra & hwif->ultra_mask) {
@@ -410,7 +410,7 @@
if (!config_chipset_for_dma(drive))
goto no_dma_set;
}
- } else if (hwif->ide_dma_good_drive(drive) &&
+ } else if (__ide_dma_good_drive(drive) &&
(id->eide_dma_time < 150)) {
goto no_dma_set;
/* Consult the list of known "good" drives */
diff -urN linux-2.6.3-rc3/drivers/ide/pci/pdc202xx_old.c linux-2.6.3-rc4/drivers/ide/pci/pdc202xx_old.c
--- linux-2.6.3-rc3/drivers/ide/pci/pdc202xx_old.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/pci/pdc202xx_old.c 2004-02-16 19:49:17.000000000 -0800
@@ -482,7 +482,7 @@
if (id && (id->capability & 1) && drive->autodma) {
/* Consult the list of known "bad" drives */
- if (hwif->ide_dma_bad_drive(drive))
+ if (__ide_dma_bad_drive(drive))
goto fast_ata_pio;
if (id->field_valid & 4) {
if (id->dma_ultra & hwif->ultra_mask) {
@@ -499,7 +499,7 @@
if (!config_chipset_for_dma(drive))
goto no_dma_set;
}
- } else if (hwif->ide_dma_good_drive(drive) &&
+ } else if (__ide_dma_good_drive(drive) &&
(id->eide_dma_time < 150)) {
goto no_dma_set;
/* Consult the list of known "good" drives */
diff -urN linux-2.6.3-rc3/drivers/ide/pci/piix.c linux-2.6.3-rc4/drivers/ide/pci/piix.c
--- linux-2.6.3-rc3/drivers/ide/pci/piix.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/pci/piix.c 2004-02-16 19:49:17.000000000 -0800
@@ -563,7 +563,7 @@
if ((id->capability & 1) && drive->autodma) {
/* Consult the list of known "bad" drives */
- if (hwif->ide_dma_bad_drive(drive))
+ if (__ide_dma_bad_drive(drive))
goto fast_ata_pio;
if (id->field_valid & 4) {
if (id->dma_ultra & hwif->ultra_mask) {
@@ -580,7 +580,7 @@
if (!piix_config_drive_for_dma(drive))
goto no_dma_set;
}
- } else if (hwif->ide_dma_good_drive(drive) &&
+ } else if (__ide_dma_good_drive(drive) &&
(id->eide_dma_time < 150)) {
/* Consult the list of known "good" drives */
if (!piix_config_drive_for_dma(drive))
diff -urN linux-2.6.3-rc3/drivers/ide/pci/sc1200.c linux-2.6.3-rc4/drivers/ide/pci/sc1200.c
--- linux-2.6.3-rc3/drivers/ide/pci/sc1200.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/pci/sc1200.c 2004-02-16 19:49:17.000000000 -0800
@@ -164,7 +164,7 @@
*/
if (mate->present) {
struct hd_driveid *mateid = mate->id;
- if (mateid && (mateid->capability & 1) && !hwif->ide_dma_bad_drive(mate)) {
+ if (mateid && (mateid->capability & 1) && !__ide_dma_bad_drive(mate)) {
if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7))
udma_ok = 1;
else if ((mateid->field_valid & 2) && (mateid->dma_mword & 7))
@@ -177,7 +177,7 @@
* Now see what the current drive is capable of,
* selecting UDMA only if the mate said it was ok.
*/
- if (id && (id->capability & 1) && hwif->autodma && !hwif->ide_dma_bad_drive(drive)) {
+ if (id && (id->capability & 1) && hwif->autodma && !__ide_dma_bad_drive(drive)) {
if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) {
if (id->dma_ultra & 4)
mode = XFER_UDMA_2;
@@ -493,7 +493,7 @@
//
for (d = 0; d < MAX_DRIVES; ++d) {
ide_drive_t *drive = &(hwif->drives[d]);
- if (drive->present && !hwif->ide_dma_bad_drive(drive)) {
+ if (drive->present && !__ide_dma_bad_drive(drive)) {
int was_using_dma = drive->using_dma;
hwif->ide_dma_off_quietly(drive);
sc1200_config_dma(drive);
diff -urN linux-2.6.3-rc3/drivers/ide/pci/serverworks.c linux-2.6.3-rc4/drivers/ide/pci/serverworks.c
--- linux-2.6.3-rc3/drivers/ide/pci/serverworks.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/pci/serverworks.c 2004-02-16 19:49:17.000000000 -0800
@@ -464,7 +464,7 @@
if ((id->capability & 1) && drive->autodma) {
/* Consult the list of known "bad" drives */
- if (hwif->ide_dma_bad_drive(drive))
+ if (__ide_dma_bad_drive(drive))
goto fast_ata_pio;
if (id->field_valid & 4) {
if (id->dma_ultra & hwif->ultra_mask) {
@@ -481,7 +481,7 @@
if (!config_chipset_for_dma(drive))
goto no_dma_set;
}
- } else if (hwif->ide_dma_good_drive(drive) &&
+ } else if (__ide_dma_good_drive(drive) &&
(id->eide_dma_time < 150)) {
/* Consult the list of known "good" drives */
if (!config_chipset_for_dma(drive))
diff -urN linux-2.6.3-rc3/drivers/ide/pci/sgiioc4.c linux-2.6.3-rc4/drivers/ide/pci/sgiioc4.c
--- linux-2.6.3-rc3/drivers/ide/pci/sgiioc4.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/pci/sgiioc4.c 2004-02-16 19:49:17.000000000 -0800
@@ -303,14 +303,6 @@
}
static int
-sgiioc4_ide_dma_off(ide_drive_t * drive)
-{
- printk(KERN_INFO "%s: DMA disabled\n", drive->name);
-
- return HWIF(drive)->ide_dma_off_quietly(drive);
-}
-
-static int
sgiioc4_ide_dma_off_quietly(ide_drive_t * drive)
{
drive->using_dma = 0;
@@ -644,14 +636,10 @@
hwif->ide_dma_end = &sgiioc4_ide_dma_end;
hwif->ide_dma_check = &sgiioc4_ide_dma_check;
hwif->ide_dma_on = &sgiioc4_ide_dma_on;
- hwif->ide_dma_off = &sgiioc4_ide_dma_off;
hwif->ide_dma_off_quietly = &sgiioc4_ide_dma_off_quietly;
hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq;
hwif->ide_dma_host_on = &sgiioc4_ide_dma_host_on;
hwif->ide_dma_host_off = &sgiioc4_ide_dma_host_off;
- hwif->ide_dma_bad_drive = &__ide_dma_bad_drive;
- hwif->ide_dma_good_drive = &__ide_dma_good_drive;
- hwif->ide_dma_count = &__ide_dma_count;
hwif->ide_dma_verbose = &sgiioc4_ide_dma_verbose;
hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq;
hwif->ide_dma_timeout = &__ide_dma_timeout;
diff -urN linux-2.6.3-rc3/drivers/ide/pci/siimage.c linux-2.6.3-rc4/drivers/ide/pci/siimage.c
--- linux-2.6.3-rc3/drivers/ide/pci/siimage.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/pci/siimage.c 2004-02-16 19:49:17.000000000 -0800
@@ -490,7 +490,7 @@
if ((id->capability & 1) != 0 && drive->autodma) {
/* Consult the list of known "bad" drives */
- if (hwif->ide_dma_bad_drive(drive))
+ if (__ide_dma_bad_drive(drive))
goto fast_ata_pio;
if ((id->field_valid & 4) && siimage_ratemask(drive)) {
@@ -508,7 +508,7 @@
if (!config_chipset_for_dma(drive))
goto no_dma_set;
}
- } else if (hwif->ide_dma_good_drive(drive) &&
+ } else if (__ide_dma_good_drive(drive) &&
(id->eide_dma_time < 150)) {
/* Consult the list of known "good" drives */
if (!config_chipset_for_dma(drive))
@@ -545,6 +545,7 @@
return 0;
}
+#if 0
/**
* siimage_mmio_ide_dma_count - DMA bytes done
* @drive
@@ -572,6 +573,7 @@
#endif /* SIIMAGE_VIRTUAL_DMAPIO */
return __ide_dma_count(drive);
}
+#endif
/**
* siimage_mmio_ide_dma_test_irq - check we caused an IRQ
@@ -1133,7 +1135,6 @@
hwif->udma_four = ata66_siimage(hwif);
if (hwif->mmio) {
- hwif->ide_dma_count = &siimage_mmio_ide_dma_count;
hwif->ide_dma_test_irq = &siimage_mmio_ide_dma_test_irq;
hwif->ide_dma_verbose = &siimage_mmio_ide_dma_verbose;
} else {
diff -urN linux-2.6.3-rc3/drivers/ide/pci/sis5513.c linux-2.6.3-rc4/drivers/ide/pci/sis5513.c
--- linux-2.6.3-rc3/drivers/ide/pci/sis5513.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/pci/sis5513.c 2004-02-16 19:49:17.000000000 -0800
@@ -671,7 +671,7 @@
if (id && (id->capability & 1) && drive->autodma) {
/* Consult the list of known "bad" drives */
- if (hwif->ide_dma_bad_drive(drive))
+ if (__ide_dma_bad_drive(drive))
goto fast_ata_pio;
if (id->field_valid & 4) {
if (id->dma_ultra & hwif->ultra_mask) {
@@ -688,7 +688,7 @@
if (!config_chipset_for_dma(drive))
goto no_dma_set;
}
- } else if (hwif->ide_dma_good_drive(drive) &&
+ } else if (__ide_dma_good_drive(drive) &&
(id->eide_dma_time < 150)) {
/* Consult the list of known "good" drives */
if (!config_chipset_for_dma(drive))
diff -urN linux-2.6.3-rc3/drivers/ide/pci/sl82c105.c linux-2.6.3-rc4/drivers/ide/pci/sl82c105.c
--- linux-2.6.3-rc3/drivers/ide/pci/sl82c105.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/pci/sl82c105.c 2004-02-16 19:49:17.000000000 -0800
@@ -158,7 +158,7 @@
break;
/* Consult the list of known "bad" drives */
- if (hwif->ide_dma_bad_drive(drive))
+ if (__ide_dma_bad_drive(drive))
break;
if (id->field_valid & 2) {
@@ -167,7 +167,7 @@
return hwif->ide_dma_on(drive);
}
- if (hwif->ide_dma_good_drive(drive))
+ if (__ide_dma_good_drive(drive))
return hwif->ide_dma_on(drive);
} while (0);
@@ -272,22 +272,6 @@
return __ide_dma_on(drive);
}
-static int sl82c105_ide_dma_off (ide_drive_t *drive)
-{
- u8 speed = XFER_PIO_0;
- int rc;
-
- DBG(("sl82c105_ide_dma_off(drive:%s)\n", drive->name));
-
- rc = __ide_dma_off(drive);
- if (drive->pio_speed)
- speed = drive->pio_speed - XFER_PIO_0;
- config_for_pio(drive, speed, 0, 1);
- drive->current_speed = drive->pio_speed;
-
- return rc;
-}
-
static int sl82c105_ide_dma_off_quietly (ide_drive_t *drive)
{
u8 speed = XFER_PIO_0;
@@ -485,7 +469,6 @@
#ifdef CONFIG_BLK_DEV_IDEDMA
hwif->ide_dma_check = &sl82c105_check_drive;
hwif->ide_dma_on = &sl82c105_ide_dma_on;
- hwif->ide_dma_off = &sl82c105_ide_dma_off;
hwif->ide_dma_off_quietly = &sl82c105_ide_dma_off_quietly;
hwif->ide_dma_lostirq = &sl82c105_ide_dma_lost_irq;
hwif->ide_dma_begin = &sl82c105_ide_dma_begin;
diff -urN linux-2.6.3-rc3/drivers/ide/pci/slc90e66.c linux-2.6.3-rc4/drivers/ide/pci/slc90e66.c
--- linux-2.6.3-rc3/drivers/ide/pci/slc90e66.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/pci/slc90e66.c 2004-02-16 19:49:17.000000000 -0800
@@ -275,7 +275,7 @@
if (id && (id->capability & 1) && drive->autodma) {
/* Consult the list of known "bad" drives */
- if (hwif->ide_dma_bad_drive(drive))
+ if (__ide_dma_bad_drive(drive))
goto fast_ata_pio;
if (id->field_valid & 4) {
@@ -293,7 +293,7 @@
if (!slc90e66_config_drive_for_dma(drive))
goto no_dma_set;
}
- } else if (hwif->ide_dma_good_drive(drive) &&
+ } else if (__ide_dma_good_drive(drive) &&
(id->eide_dma_time < 150)) {
/* Consult the list of known "good" drives */
if (!slc90e66_config_drive_for_dma(drive))
diff -urN linux-2.6.3-rc3/drivers/ide/pci/triflex.c linux-2.6.3-rc4/drivers/ide/pci/triflex.c
--- linux-2.6.3-rc3/drivers/ide/pci/triflex.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/pci/triflex.c 2004-02-16 19:49:17.000000000 -0800
@@ -173,7 +173,7 @@
struct hd_driveid *id = drive->id;
if (id && (id->capability & 1) && drive->autodma) {
- if (hwif->ide_dma_bad_drive(drive))
+ if (__ide_dma_bad_drive(drive))
goto tune_pio;
if (id->field_valid & 2) {
if ((id->dma_mword & hwif->mwdma_mask) ||
diff -urN linux-2.6.3-rc3/drivers/ide/pci/trm290.c linux-2.6.3-rc4/drivers/ide/pci/trm290.c
--- linux-2.6.3-rc3/drivers/ide/pci/trm290.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/pci/trm290.c 2004-02-16 19:49:17.000000000 -0800
@@ -225,7 +225,7 @@
#endif
/* issue cmd to drive */
hwif->OUTB(command, IDE_COMMAND_REG);
- return HWIF(drive)->ide_dma_count(drive);
+ return hwif->ide_dma_begin(drive);
}
static int trm290_ide_dma_read (ide_drive_t *drive /*, struct request *rq */)
@@ -269,7 +269,7 @@
#endif
/* issue cmd to drive */
hwif->OUTB(command, IDE_COMMAND_REG);
- return HWIF(drive)->ide_dma_count(drive);
+ return hwif->ide_dma_begin(drive);
}
static int trm290_ide_dma_begin (ide_drive_t *drive)
diff -urN linux-2.6.3-rc3/drivers/ide/ppc/pmac.c linux-2.6.3-rc4/drivers/ide/ppc/pmac.c
--- linux-2.6.3-rc3/drivers/ide/ppc/pmac.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/ide/ppc/pmac.c 2004-02-16 19:49:17.000000000 -0800
@@ -1988,12 +1988,6 @@
return pmac_ide_dma_begin(drive);
}
-static int __pmac
-pmac_ide_dma_count (ide_drive_t *drive)
-{
- return HWIF(drive)->ide_dma_begin(drive);
-}
-
/*
* Kick the DMA controller into life after the DMA command has been issued
* to the drive.
@@ -2159,20 +2153,16 @@
pmif->dma_table_cpu, pmif->dma_table_dma);
return;
}
- hwif->ide_dma_off = &__ide_dma_off;
hwif->ide_dma_off_quietly = &__ide_dma_off_quietly;
hwif->ide_dma_on = &__ide_dma_on;
hwif->ide_dma_check = &pmac_ide_dma_check;
hwif->ide_dma_read = &pmac_ide_dma_read;
hwif->ide_dma_write = &pmac_ide_dma_write;
- hwif->ide_dma_count = &pmac_ide_dma_count;
hwif->ide_dma_begin = &pmac_ide_dma_begin;
hwif->ide_dma_end = &pmac_ide_dma_end;
hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq;
hwif->ide_dma_host_off = &pmac_ide_dma_host_off;
hwif->ide_dma_host_on = &pmac_ide_dma_host_on;
- hwif->ide_dma_good_drive = &__ide_dma_good_drive;
- hwif->ide_dma_bad_drive = &__ide_dma_bad_drive;
hwif->ide_dma_verbose = &__ide_dma_verbose;
hwif->ide_dma_timeout = &__ide_dma_timeout;
hwif->ide_dma_lostirq = &pmac_ide_dma_lostirq;
diff -urN linux-2.6.3-rc3/drivers/macintosh/via-pmu.c linux-2.6.3-rc4/drivers/macintosh/via-pmu.c
--- linux-2.6.3-rc3/drivers/macintosh/via-pmu.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/macintosh/via-pmu.c 2004-02-16 19:49:17.000000000 -0800
@@ -72,13 +72,6 @@
/* How many iterations between battery polls */
#define BATTERY_POLLING_COUNT 2
-/* Some debugging tools */
-#ifdef CONFIG_XMON
-//#define LIVE_DEBUG(req) ((req) && (req)->data[0] == 0x7d)
-#define LIVE_DEBUG(req) (0)
-static int whacky_debug;
-#endif /* CONFIG_XMON */
-
static volatile unsigned char *via;
/* VIA registers - spaced 0x200 bytes apart */
@@ -1218,12 +1211,6 @@
wait_for_ack();
/* set the shift register to shift out and send a byte */
send_byte(req->data[0]);
-#ifdef CONFIG_XMON
- if (LIVE_DEBUG(req))
- xmon_printf("R");
- else
- whacky_debug = 0;
-#endif /* CONFIG_XMON */
}
void __openfirmware
@@ -1476,29 +1463,17 @@
case sending:
req = current_req;
if (data_len < 0) {
-#ifdef CONFIG_XMON
- if (LIVE_DEBUG(req))
- xmon_printf("s");
-#endif /* CONFIG_XMON */
data_len = req->nbytes - 1;
send_byte(data_len);
break;
}
if (data_index <= data_len) {
-#ifdef CONFIG_XMON
- if (LIVE_DEBUG(req))
- xmon_printf("S");
-#endif /* CONFIG_XMON */
send_byte(req->data[data_index++]);
break;
}
req->sent = 1;
data_len = pmu_data_len[req->data[0]][1];
if (data_len == 0) {
-#ifdef CONFIG_XMON
- if (LIVE_DEBUG(req))
- xmon_printf("D");
-#endif /* CONFIG_XMON */
pmu_state = idle;
current_req = req->next;
if (req->reply_expected)
@@ -1506,10 +1481,6 @@
else
return req;
} else {
-#ifdef CONFIG_XMON
- if (LIVE_DEBUG(req))
- xmon_printf("-");
-#endif /* CONFIG_XMON */
pmu_state = reading;
data_index = 0;
reply_ptr = req->reply + req->reply_len;
@@ -1532,18 +1503,10 @@
case reading:
case reading_intr:
if (data_len == -1) {
-#ifdef CONFIG_XMON
- if (LIVE_DEBUG(current_req))
- xmon_printf("r");
-#endif /* CONFIG_XMON */
data_len = bite;
if (bite > 32)
printk(KERN_ERR "PMU: bad reply len %d\n", bite);
} else if (data_index < 32) {
-#ifdef CONFIG_XMON
- if (LIVE_DEBUG(current_req))
- xmon_printf("R");
-#endif /* CONFIG_XMON */
reply_ptr[data_index++] = bite;
}
if (data_index < data_len) {
@@ -1551,12 +1514,6 @@
break;
}
-#ifdef CONFIG_XMON
- if (LIVE_DEBUG(current_req)) {
- whacky_debug = 1;
- xmon_printf("D");
- }
-#endif /* CONFIG_XMON */
if (pmu_state == reading_intr) {
pmu_state = idle;
int_data_state[int_data_last] = int_data_ready;
@@ -1603,10 +1560,6 @@
intr = in_8(&via[IFR]) & (SR_INT | CB1_INT);
if (intr == 0)
break;
-#ifdef CONFIG_XMON
- if (whacky_debug)
- xmon_printf("|%02x|", intr);
-#endif /* CONFIG_XMON */
handled = 1;
if (++nloop > 1000) {
printk(KERN_DEBUG "PMU: stuck in intr loop, "
@@ -1629,10 +1582,6 @@
recheck:
if (pmu_state == idle) {
if (adb_int_pending) {
-#ifdef CONFIG_XMON
- if (whacky_debug)
- xmon_printf("!A!");
-#endif /* CONFIG_XMON */
if (int_data_state[0] == int_data_empty)
int_data_last = 0;
else if (int_data_state[1] == int_data_empty)
diff -urN linux-2.6.3-rc3/drivers/net/mace.c linux-2.6.3-rc4/drivers/net/mace.c
--- linux-2.6.3-rc3/drivers/net/mace.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/net/mace.c 2004-02-16 19:49:18.000000000 -0800
@@ -20,9 +20,10 @@
#include
#include
#include
+#include
+
#include "mace.h"
-static struct net_device *mace_devs;
static int port_aaui = -1;
#define N_RX_RING 8
@@ -61,8 +62,7 @@
int timeout_active;
int port_aaui;
int chipid;
- struct device_node* of_node;
- struct net_device *next_mace;
+ struct macio_dev *mdev;
spinlock_t lock;
};
@@ -76,8 +76,6 @@
+ (N_RX_RING + NCMDS_TX * N_TX_RING + 3) * sizeof(struct dbdma_cmd))
static int bitrev(int);
-static int mace_probe(void);
-static void mace_probe1(struct device_node *mace);
static int mace_open(struct net_device *dev);
static int mace_close(struct net_device *dev);
static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev);
@@ -110,26 +108,19 @@
return d;
}
-static int __init mace_probe(void)
-{
- struct device_node *mace;
-
- for (mace = find_devices("mace"); mace != NULL; mace = mace->next)
- mace_probe1(mace);
- return mace_devs? 0: -ENODEV;
-}
-static void __init mace_probe1(struct device_node *mace)
+static int __devinit mace_probe(struct macio_dev *mdev, const struct of_match *match)
{
- int j, rev;
+ struct device_node *mace = macio_get_of_node(mdev);
struct net_device *dev;
struct mace_data *mp;
unsigned char *addr;
+ int j, rev, rc = -EBUSY;
- if (mace->n_addrs != 3 || mace->n_intrs != 3) {
+ if (macio_resource_count(mdev) != 3 || macio_irq_count(mdev) != 3) {
printk(KERN_ERR "can't use MACE %s: need 3 addrs and 3 irqs\n",
mace->full_name);
- return;
+ return -ENODEV;
}
addr = get_property(mace, "mac-address", NULL);
@@ -138,48 +129,48 @@
if (addr == NULL) {
printk(KERN_ERR "Can't get mac-address for MACE %s\n",
mace->full_name);
- return;
+ return -ENODEV;
}
}
/*
- * lazy allocation - it's a driver-wide thing and it will live until
- * the unload, but we don't allocate it until it's needed
+ * lazy allocate the driver-wide dummy buffer. (Note that we
+ * never have more than one MACE in the system anyway)
*/
if (dummy_buf == NULL) {
dummy_buf = kmalloc(RX_BUFLEN+2, GFP_KERNEL);
if (dummy_buf == NULL) {
printk(KERN_ERR "MACE: couldn't allocate dummy buffer\n");
- return;
+ return -ENOMEM;
}
}
+ if (macio_request_resources(mdev, "mace")) {
+ printk(KERN_ERR "MACE: can't request IO resources !\n");
+ return -EBUSY;
+ }
+
dev = alloc_etherdev(PRIV_BYTES);
- if (!dev)
- return;
+ if (!dev) {
+ printk(KERN_ERR "MACE: can't allocate ethernet device !\n");
+ rc = -ENOMEM;
+ goto err_release;
+ }
SET_MODULE_OWNER(dev);
+ SET_NETDEV_DEV(dev, &mdev->ofdev.dev);
mp = dev->priv;
- mp->of_node = mace;
-
- if (!request_OF_resource(mace, 0, " (mace)")) {
- printk(KERN_ERR "MACE: can't request IO resource !\n");
- goto out1;
- }
- if (!request_OF_resource(mace, 1, " (mace tx dma)")) {
- printk(KERN_ERR "MACE: can't request TX DMA resource !\n");
- goto out2;
- }
-
- if (!request_OF_resource(mace, 2, " (mace tx dma)")) {
- printk(KERN_ERR "MACE: can't request RX DMA resource !\n");
- goto out3;
- }
-
- dev->base_addr = mace->addrs[0].address;
- mp->mace = (volatile struct mace *)
- ioremap(mace->addrs[0].address, 0x1000);
- dev->irq = mace->intrs[0].line;
+ mp->mdev = mdev;
+ macio_set_drvdata(mdev, dev);
+
+ dev->base_addr = macio_resource_start(mdev, 0);
+ mp->mace = (volatile struct mace *)ioremap(dev->base_addr, 0x1000);
+ if (mp->mace == NULL) {
+ printk(KERN_ERR "MACE: can't map IO resources !\n");
+ rc = -ENOMEM;
+ goto err_free;
+ }
+ dev->irq = macio_irq(mdev, 0);
printk(KERN_INFO "%s: MACE at", dev->name);
rev = addr[0] == 0 && addr[1] == 0xA0;
@@ -194,12 +185,24 @@
mp = (struct mace_data *) dev->priv;
mp->maccc = ENXMT | ENRCV;
+
mp->tx_dma = (volatile struct dbdma_regs *)
- ioremap(mace->addrs[1].address, 0x1000);
- mp->tx_dma_intr = mace->intrs[1].line;
+ ioremap(macio_resource_start(mdev, 1), 0x1000);
+ if (mp->tx_dma == NULL) {
+ printk(KERN_ERR "MACE: can't map TX DMA resources !\n");
+ rc = -ENOMEM;
+ goto err_unmap_io;
+ }
+ mp->tx_dma_intr = macio_irq(mdev, 1);
+
mp->rx_dma = (volatile struct dbdma_regs *)
- ioremap(mace->addrs[2].address, 0x1000);
- mp->rx_dma_intr = mace->intrs[2].line;
+ ioremap(macio_resource_start(mdev, 2), 0x1000);
+ if (mp->rx_dma == NULL) {
+ printk(KERN_ERR "MACE: can't map RX DMA resources !\n");
+ rc = -ENOMEM;
+ goto err_unmap_tx_dma;
+ }
+ mp->rx_dma_intr = macio_irq(mdev, 2);;
mp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(mp + 1);
mp->rx_cmds = mp->tx_cmds + NCMDS_TX * N_TX_RING + 1;
@@ -233,43 +236,81 @@
dev->set_multicast_list = mace_set_multicast;
dev->set_mac_address = mace_set_address;
+ /*
+ * Most of what is below could be moved to mace_open()
+ */
mace_reset(dev);
- if (request_irq(dev->irq, mace_interrupt, 0, "MACE", dev)) {
+ rc = request_irq(dev->irq, mace_interrupt, 0, "MACE", dev);
+ if (rc) {
printk(KERN_ERR "MACE: can't get irq %d\n", dev->irq);
- goto out4;
+ goto err_unmap_rx_dma;
}
- if (request_irq(mace->intrs[1].line, mace_txdma_intr, 0, "MACE-txdma",
- dev)) {
+ rc = request_irq(mp->tx_dma_intr, mace_txdma_intr, 0, "MACE-txdma", dev);
+ if (rc) {
printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[1].line);
- goto out5;
+ goto err_free_irq;
}
- if (request_irq(mace->intrs[2].line, mace_rxdma_intr, 0, "MACE-rxdma",
- dev)) {
+ rc = request_irq(mp->rx_dma_intr, mace_rxdma_intr, 0, "MACE-rxdma", dev);
+ if (rc) {
printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[2].line);
- goto out6;
+ goto err_free_tx_irq;
}
- if (register_netdev(dev) != 0)
- goto out7;
- mp->next_mace = mace_devs;
- mace_devs = dev;
- return;
-
-out7:
- free_irq(mp->rx_dma_intr, dev);
-out6:
- free_irq(mp->tx_dma_intr, dev);
-out5:
+ rc = register_netdev(dev);
+ if (rc) {
+ printk(KERN_ERR "Cannot register net device, aborting.\n");
+ goto err_free_rx_irq;
+ }
+
+ return 0;
+
+ err_free_rx_irq:
+ free_irq(macio_irq(mdev, 2), dev);
+ err_free_tx_irq:
+ free_irq(macio_irq(mdev, 1), dev);
+ err_free_irq:
+ free_irq(macio_irq(mdev, 0), dev);
+ err_unmap_rx_dma:
+ iounmap((void*)mp->rx_dma);
+ err_unmap_tx_dma:
+ iounmap((void*)mp->tx_dma);
+ err_unmap_io:
+ iounmap((void*)mp->mace);
+ err_free:
+ free_netdev(dev);
+ err_release:
+ macio_release_resources(mdev);
+
+ return rc;
+}
+
+static int __devexit mace_remove(struct macio_dev *mdev)
+{
+ struct net_device *dev = macio_get_drvdata(mdev);
+ struct mace_data *mp;
+
+ BUG_ON(dev == NULL);
+
+ macio_set_drvdata(mdev, NULL);
+
+ mp = dev->priv;
+
+ unregister_netdev(dev);
+
free_irq(dev->irq, dev);
-out4:
- release_OF_resource(mp->of_node, 2);
-out3:
- release_OF_resource(mp->of_node, 1);
-out2:
- release_OF_resource(mp->of_node, 0);
-out1:
+ free_irq(mp->tx_dma_intr, dev);
+ free_irq(mp->rx_dma_intr, dev);
+
+ iounmap((void*)mp->rx_dma);
+ iounmap((void*)mp->tx_dma);
+ iounmap((void*)mp->mace);
+
free_netdev(dev);
+
+ macio_release_resources(mdev);
+
+ return 0;
}
static void dbdma_reset(volatile struct dbdma_regs *dma)
@@ -967,37 +1008,45 @@
return IRQ_HANDLED;
}
-MODULE_AUTHOR("Paul Mackerras");
-MODULE_DESCRIPTION("PowerMac MACE driver.");
-MODULE_PARM(port_aaui, "i");
-MODULE_PARM_DESC(port_aaui, "MACE uses AAUI port (0-1)");
-MODULE_LICENSE("GPL");
+static struct of_match mace_match[] =
+{
+ {
+ .name = "mace",
+ .type = OF_ANY_MATCH,
+ .compatible = OF_ANY_MATCH
+ },
+ {},
+};
-static void __exit mace_cleanup (void)
+static struct macio_driver mace_driver =
{
- struct net_device *dev;
- struct mace_data *mp;
+ .name = "mace",
+ .match_table = mace_match,
+ .probe = mace_probe,
+ .remove = mace_remove,
+};
- while ((dev = mace_devs) != 0) {
- mp = (struct mace_data *) mace_devs->priv;
- mace_devs = mp->next_mace;
- unregister_netdev(dev);
- free_irq(dev->irq, dev);
- free_irq(mp->tx_dma_intr, dev);
- free_irq(mp->rx_dma_intr, dev);
+static int __init mace_init(void)
+{
+ return macio_register_driver(&mace_driver);
+}
- release_OF_resource(mp->of_node, 0);
- release_OF_resource(mp->of_node, 1);
- release_OF_resource(mp->of_node, 2);
+static void __exit mace_cleanup(void)
+{
+ macio_unregister_driver(&mace_driver);
- free_netdev(dev);
- }
- if (dummy_buf != NULL) {
+ if (dummy_buf) {
kfree(dummy_buf);
dummy_buf = NULL;
- }
+ }
}
-module_init(mace_probe);
+MODULE_AUTHOR("Paul Mackerras");
+MODULE_DESCRIPTION("PowerMac MACE driver.");
+MODULE_PARM(port_aaui, "i");
+MODULE_PARM_DESC(port_aaui, "MACE uses AAUI port (0-1)");
+MODULE_LICENSE("GPL");
+
+module_init(mace_init);
module_exit(mace_cleanup);
diff -urN linux-2.6.3-rc3/drivers/net/wireless/airport.c linux-2.6.3-rc4/drivers/net/wireless/airport.c
--- linux-2.6.3-rc3/drivers/net/wireless/airport.c 2004-02-16 19:49:11.000000000 -0800
+++ linux-2.6.3-rc4/drivers/net/wireless/airport.c 2004-02-16 19:49:19.000000000 -0800
@@ -40,7 +40,7 @@
#define AIRPORT_IO_LEN (0x1000) /* one page */
struct airport {
- struct device_node *node;
+ struct macio_dev *mdev;
void *vaddr;
int irq_requested;
int ndev_registered;
@@ -51,7 +51,6 @@
{
struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
struct orinoco_private *priv = dev->priv;
- struct airport *card = priv->card;
unsigned long flags;
int err;
@@ -76,7 +75,7 @@
orinoco_unlock(priv, &flags);
disable_irq(dev->irq);
- pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 0);
+ pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 0);
return 0;
}
@@ -86,14 +85,14 @@
{
struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
struct orinoco_private *priv = dev->priv;
- struct airport *card = priv->card;
unsigned long flags;
int err;
printk(KERN_DEBUG "%s: Airport waking up\n", dev->name);
- pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 1);
- mdelay(200);
+ pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HZ/5);
enable_irq(dev->irq);
@@ -142,15 +141,13 @@
iounmap(card->vaddr);
card->vaddr = 0;
- dev->base_addr = 0;
+ macio_release_resource(mdev, 0);
- release_OF_resource(card->node, 0);
-
- pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 0);
- current->state = TASK_UNINTERRUPTIBLE;
+ pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 0);
+ set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ);
- dev_set_drvdata(&mdev->ofdev.dev, NULL);
+ macio_set_drvdata(mdev, NULL);
free_netdev(dev);
return 0;
@@ -173,11 +170,11 @@
* off. */
disable_irq(dev->irq);
- pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 0);
- current->state = TASK_UNINTERRUPTIBLE;
+ pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 0);
+ set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ);
- pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 1);
- current->state = TASK_UNINTERRUPTIBLE;
+ pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 1);
+ set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ);
enable_irq(dev->irq);
@@ -194,10 +191,9 @@
struct net_device *dev;
struct airport *card;
unsigned long phys_addr;
- struct device_node *of_node = mdev->ofdev.node;
hermes_t *hw;
- if (of_node->n_addrs < 1 || of_node->n_intrs < 1) {
+ if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) {
printk(KERN_ERR "airport: wrong interrupt/addresses in OF tree\n");
return -ENODEV;
}
@@ -212,27 +208,26 @@
card = priv->card;
hw = &priv->hw;
- card->node = of_node;
+ card->mdev = mdev;
- if (! request_OF_resource(of_node, 0, " (airport)")) {
+ if (macio_request_resource(mdev, 0, "airport")) {
printk(KERN_ERR "airport: can't request IO resource !\n");
free_netdev(dev);
- return -ENODEV;
+ return -EBUSY;
}
- dev->name[0] = '\0'; /* register_netdev will give us an ethX name */
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &mdev->ofdev.dev);
- dev_set_drvdata(&mdev->ofdev.dev, dev);
+ macio_set_drvdata(mdev, dev);
/* Setup interrupts & base address */
- dev->irq = of_node->intrs[0].line;
- phys_addr = of_node->addrs[0].address; /* Physical address */
+ dev->irq = macio_irq(mdev, 0);
+ phys_addr = macio_resource_start(mdev, 0); /* Physical address */
printk(KERN_DEBUG "Airport at physical address %lx\n", phys_addr);
dev->base_addr = phys_addr;
card->vaddr = ioremap(phys_addr, AIRPORT_IO_LEN);
- if (! card->vaddr) {
+ if (!card->vaddr) {
printk("airport: ioremap() failed\n");
goto failed;
}
@@ -241,8 +236,8 @@
HERMES_MEM, HERMES_16BIT_REGSPACING);
/* Power up card */
- pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 1);
- current->state = TASK_UNINTERRUPTIBLE;
+ pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1);
+ set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ);
/* Reset it before we get the interrupt */
diff -urN linux-2.6.3-rc3/drivers/serial/8250.c linux-2.6.3-rc4/drivers/serial/8250.c
--- linux-2.6.3-rc3/drivers/serial/8250.c 2004-02-16 19:49:12.000000000 -0800
+++ linux-2.6.3-rc4/drivers/serial/8250.c 2004-02-03 19:43:07.000000000 -0800
@@ -1976,8 +1976,6 @@
if (co->index >= UART_NR)
co->index = 0;
port = &serial8250_ports[co->index].port;
- if (port->type == PORT_UNKNOWN)
- return -ENODEV;
/*
* Temporary fix.
@@ -2009,14 +2007,6 @@
}
console_initcall(serial8250_console_init);
-static int __init serial8250_late_console_init(void)
-{
- if (!(serial8250_console.flags & CON_ENABLED))
- register_console(&serial8250_console);
- return 0;
-}
-late_initcall(serial8250_late_console_init);
-
#define SERIAL8250_CONSOLE &serial8250_console
#else
#define SERIAL8250_CONSOLE NULL
diff -urN linux-2.6.3-rc3/drivers/serial/serial_core.c linux-2.6.3-rc4/drivers/serial/serial_core.c
--- linux-2.6.3-rc3/drivers/serial/serial_core.c 2004-02-16 19:49:12.000000000 -0800
+++ linux-2.6.3-rc4/drivers/serial/serial_core.c 2004-02-03 19:43:19.000000000 -0800
@@ -1871,6 +1871,9 @@
if (flow == 'r')
termios.c_cflag |= CRTSCTS;
+ if (!port->ops)
+ return 0; /* "console=" on ia64 */
+
port->ops->set_termios(port, &termios, NULL);
co->cflag = termios.c_cflag;
diff -urN linux-2.6.3-rc3/drivers/video/Kconfig linux-2.6.3-rc4/drivers/video/Kconfig
--- linux-2.6.3-rc3/drivers/video/Kconfig 2004-02-16 19:49:12.000000000 -0800
+++ linux-2.6.3-rc4/drivers/video/Kconfig 2004-02-16 19:49:21.000000000 -0800
@@ -650,6 +650,15 @@
help
Say Y here if you want DDC/I2C support for your Radeon board.
+config FB_RADEON_DEBUG
+ bool "Lots of debug output from Radeon driver"
+ depends on FB_RADEON
+ default n
+ help
+ Say Y here if you want the Radeon driver to output all sorts
+ of debugging informations to provide to the maintainer when
+ something goes wrong.
+
config FB_ATY128
tristate "ATI Rage128 display support"
depends on FB && PCI
diff -urN linux-2.6.3-rc3/drivers/video/aty/aty128fb.c linux-2.6.3-rc4/drivers/video/aty/aty128fb.c
--- linux-2.6.3-rc3/drivers/video/aty/aty128fb.c 2004-02-03 19:43:46.000000000 -0800
+++ linux-2.6.3-rc4/drivers/video/aty/aty128fb.c 2004-02-16 19:49:21.000000000 -0800
@@ -13,6 +13,7 @@
*
* Benjamin Herrenschmidt
* - pmac-specific PM stuff
+ * - various fixes & cleanups
*
* Andreas Hundt
* - FB_ACTIVATE fixes
@@ -24,6 +25,10 @@
* Paul Mundt
* - PCI hotplug
*
+ * Jon Smirl
+ * - PCI ID update
+ * - replace ROM BIOS search
+ *
* Based off of Geert's atyfb.c and vfb.c.
*
* TODO:
@@ -43,6 +48,7 @@
#include
#include
+#include
#include
#include
#include
@@ -57,6 +63,7 @@
#include
#include
#include
+#include
#include
#ifdef CONFIG_PPC_PMAC
@@ -65,11 +72,6 @@
#include "../macmodes.h"
#endif
-#ifdef CONFIG_ADB_PMU
-#include
-#include
-#endif
-
#ifdef CONFIG_PMAC_BACKLIGHT
#include
#endif
@@ -136,8 +138,25 @@
/* Chip generations */
enum {
rage_128,
+ rage_128_pci,
rage_128_pro,
- rage_M3
+ rage_128_pro_pci,
+ rage_M3,
+ rage_M3_pci,
+ rage_M4,
+ rage_128_ultra,
+};
+
+/* Must match above enum */
+static const char *r128_family[] __devinitdata = {
+ "AGP",
+ "PCI",
+ "PRO AGP",
+ "PRO PCI",
+ "M3 AGP",
+ "M3 PCI",
+ "M4 AGP",
+ "Ultra AGP",
};
/*
@@ -146,35 +165,105 @@
static int aty128_probe(struct pci_dev *pdev,
const struct pci_device_id *ent);
static void aty128_remove(struct pci_dev *pdev);
+static int aty128_pci_suspend(struct pci_dev *pdev, u32 state);
+static int aty128_pci_resume(struct pci_dev *pdev);
/* supported Rage128 chipsets */
static struct pci_device_id aty128_pci_tbl[] = {
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RE,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RF,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RI,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RK,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RL,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_Rage128_PD,
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_LE,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M3_pci },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_LF,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M3 },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_MF,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M4 },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_ML,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M4 },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PA,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PB,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PC,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PD,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro_pci },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PE,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PF,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PR,
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PG,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PH,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PI,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PJ,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PK,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PM,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PN,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PP,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro_pci },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PQ,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PR,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro_pci },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PS,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_U3,
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PT,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_U1,
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PU,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_LE,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M3 },
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_LF,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M3 },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PV,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PW,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PX,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RE,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pci },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RF,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RG,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RK,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pci },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SE,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SF,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pci },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SG,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SH,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SK,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SM,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SN,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TF,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TR,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TS,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TT,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TU,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
{ 0, }
};
@@ -185,6 +274,8 @@
.id_table = aty128_pci_tbl,
.probe = aty128_probe,
.remove = __devexit_p(aty128_remove),
+ .suspend = aty128_pci_suspend,
+ .resume = aty128_pci_resume,
};
/* packed BIOS settings */
@@ -250,13 +341,6 @@
.accel = FB_ACCEL_ATI_RAGE128,
};
-#ifdef MODULE
-static char *mode __initdata = NULL;
-#ifdef CONFIG_MTRR
-static int nomtrr __initdata = 0;
-#endif /* CONFIG_MTRR */
-#endif /* MODULE */
-
static char *mode_option __initdata = NULL;
#ifdef CONFIG_PPC_PMAC
@@ -275,7 +359,7 @@
/* PLL constants */
struct aty128_constants {
- u32 dotclock;
+ u32 ref_clk;
u32 ppll_min;
u32 ppll_max;
u32 ref_divider;
@@ -322,26 +406,20 @@
#endif
int blitter_may_be_busy;
int fifo_slots; /* free slots in FIFO (64 max) */
-#ifdef CONFIG_PMAC_PBOOK
- unsigned char *save_framebuffer;
+
int pm_reg;
int crt_on, lcd_on;
struct pci_dev *pdev;
struct fb_info *next;
-#endif
+ int asleep;
+ int lock_blank;
+
u8 red[32]; /* see aty128fb_setcolreg */
u8 green[64];
u8 blue[32];
u32 pseudo_palette[16]; /* used for TRUECOLOR */
};
-#ifdef CONFIG_PMAC_PBOOK
-int aty128_sleep_notify(struct pmu_sleep_notifier *self, int when);
-static struct pmu_sleep_notifier aty128_sleep_notifier = {
- aty128_sleep_notify, SLEEP_LEVEL_VIDEO,
-};
-static struct fb_info *aty128_fb = NULL;
-#endif
#define round_div(n, d) ((n+(d/2))/d)
@@ -349,7 +427,6 @@
* Interface used by the world
*/
int aty128fb_init(void);
-int aty128fb_setup(char *options);
static int aty128fb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info);
@@ -371,10 +448,10 @@
const struct aty128fb_par *par);
static int aty128_decode_var(struct fb_var_screeninfo *var,
struct aty128fb_par *par);
-#if !defined(CONFIG_PPC) && !defined(__sparc__)
+#if 0
static void __init aty128_get_pllinfo(struct aty128fb_par *par,
void *bios);
-static void __init *aty128_map_ROM(struct pci_dev *pdev);
+static void __init *aty128_map_ROM(struct pci_dev *pdev, const struct aty128fb_par *par);
static void __init aty128_unmap_ROM(struct pci_dev *dev, void * rom);
#endif
static void aty128_timings(struct aty128fb_par *par);
@@ -386,6 +463,15 @@
static void wait_for_idle(struct aty128fb_par *par);
static u32 depth_to_dst(u32 depth);
+#define BIOS_IN8(v) (readb(bios + (v)))
+#define BIOS_IN16(v) (readb(bios + (v)) | \
+ (readb(bios + (v) + 1) << 8))
+#define BIOS_IN32(v) (readb(bios + (v)) | \
+ (readb(bios + (v) + 1) << 8) | \
+ (readb(bios + (v) + 2) << 16) | \
+ (readb(bios + (v) + 3) << 24))
+
+
static struct fb_ops aty128fb_ops = {
.owner = THIS_MODULE,
.fb_check_var = aty128fb_check_var,
@@ -395,15 +481,9 @@
.fb_blank = aty128fb_blank,
.fb_ioctl = aty128fb_ioctl,
.fb_sync = aty128fb_sync,
-#if 0
- .fb_fillrect = aty128fb_fillrect,
- .fb_copyarea = aty128fb_copyarea,
- .fb_imageblit = aty128fb_imageblit,
-#else
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
-#endif
.fb_cursor = soft_cursor,
};
@@ -422,40 +502,26 @@
* - endian conversions may possibly be avoided by
* using the other register aperture. TODO.
*/
-static inline u32
-_aty_ld_le32(volatile unsigned int regindex, const struct aty128fb_par *par)
+static inline u32 _aty_ld_le32(volatile unsigned int regindex,
+ const struct aty128fb_par *par)
{
- u32 val;
-
-#if defined(__powerpc__)
- asm("lwbrx %0,%1,%2;eieio" : "=r"(val) : "b"(regindex), "r"(par->regbase));
-#else
- val = readl (par->regbase + regindex);
-#endif
-
- return val;
+ return readl (par->regbase + regindex);
}
-static inline void
-_aty_st_le32(volatile unsigned int regindex, u32 val,
- const struct aty128fb_par *par)
+static inline void _aty_st_le32(volatile unsigned int regindex, u32 val,
+ const struct aty128fb_par *par)
{
-#if defined(__powerpc__)
- asm("stwbrx %0,%1,%2;eieio" : : "r"(val), "b"(regindex),
- "r"(par->regbase) : "memory");
-#else
writel (val, par->regbase + regindex);
-#endif
}
-static inline u8
-_aty_ld_8(unsigned int regindex, const struct aty128fb_par *par)
+static inline u8 _aty_ld_8(unsigned int regindex,
+ const struct aty128fb_par *par)
{
return readb (par->regbase + regindex);
}
-static inline void
-_aty_st_8(unsigned int regindex, u8 val, const struct aty128fb_par *par)
+static inline void _aty_st_8(unsigned int regindex, u8 val,
+ const struct aty128fb_par *par)
{
writeb (val, par->regbase + regindex);
}
@@ -473,17 +539,15 @@
#define aty_st_pll(pll_index, val) _aty_st_pll(pll_index, val, par)
-static u32
-_aty_ld_pll(unsigned int pll_index,
- const struct aty128fb_par *par)
+static u32 _aty_ld_pll(unsigned int pll_index,
+ const struct aty128fb_par *par)
{
aty_st_8(CLOCK_CNTL_INDEX, pll_index & 0x3F);
return aty_ld_le32(CLOCK_CNTL_DATA);
}
-static void
-_aty_st_pll(unsigned int pll_index, u32 val,
+static void _aty_st_pll(unsigned int pll_index, u32 val,
const struct aty128fb_par *par)
{
aty_st_8(CLOCK_CNTL_INDEX, (pll_index & 0x3F) | PLL_WR_EN);
@@ -492,15 +556,13 @@
/* return true when the PLL has completed an atomic update */
-static int
-aty_pll_readupdate(const struct aty128fb_par *par)
+static int aty_pll_readupdate(const struct aty128fb_par *par)
{
return !(aty_ld_pll(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R);
}
-static void
-aty_pll_wait_readupdate(const struct aty128fb_par *par)
+static void aty_pll_wait_readupdate(const struct aty128fb_par *par)
{
unsigned long timeout = jiffies + HZ/100; // should be more than enough
int reset = 1;
@@ -517,8 +579,7 @@
/* tell PLL to update */
-static void
-aty_pll_writeupdate(const struct aty128fb_par *par)
+static void aty_pll_writeupdate(const struct aty128fb_par *par)
{
aty_pll_wait_readupdate(par);
@@ -528,8 +589,7 @@
/* write to the scratch register to test r/w functionality */
-static int __init
-register_test(const struct aty128fb_par *par)
+static int __init register_test(const struct aty128fb_par *par)
{
u32 val;
int flag = 0;
@@ -552,8 +612,7 @@
/*
* Accelerator engine functions
*/
-static void
-do_wait_for_fifo(u16 entries, struct aty128fb_par *par)
+static void do_wait_for_fifo(u16 entries, struct aty128fb_par *par)
{
int i;
@@ -568,8 +627,7 @@
}
-static void
-wait_for_idle(struct aty128fb_par *par)
+static void wait_for_idle(struct aty128fb_par *par)
{
int i;
@@ -588,8 +646,7 @@
}
-static void
-wait_for_fifo(u16 entries, struct aty128fb_par *par)
+static void wait_for_fifo(u16 entries, struct aty128fb_par *par)
{
if (par->fifo_slots < entries)
do_wait_for_fifo(64, par);
@@ -597,8 +654,7 @@
}
-static void
-aty128_flush_pixel_cache(const struct aty128fb_par *par)
+static void aty128_flush_pixel_cache(const struct aty128fb_par *par)
{
int i;
u32 tmp;
@@ -614,8 +670,7 @@
}
-static void
-aty128_reset_engine(const struct aty128fb_par *par)
+static void aty128_reset_engine(const struct aty128fb_par *par)
{
u32 gen_reset_cntl, clock_cntl_index, mclk_cntl;
@@ -643,8 +698,7 @@
}
-static void
-aty128_init_engine(struct aty128fb_par *par)
+static void aty128_init_engine(struct aty128fb_par *par)
{
u32 pitch_value;
@@ -712,8 +766,7 @@
/* convert depth values to their register representation */
-static u32
-depth_to_dst(u32 depth)
+static u32 depth_to_dst(u32 depth)
{
if (depth <= 8)
return DST_8BPP;
@@ -729,15 +782,247 @@
return -EINVAL;
}
+/*
+ * PLL informations retreival
+ */
+
+
+#ifndef __sparc__
+static void __init aty128_unmap_ROM(struct pci_dev *dev, void * rom)
+{
+ struct resource *r = &dev->resource[PCI_ROM_RESOURCE];
+
+ iounmap(rom);
+
+ /* Release the ROM resource if we used it in the first place */
+ if (r->parent && r->flags & PCI_ROM_ADDRESS_ENABLE) {
+ release_resource(r);
+ r->flags &= ~PCI_ROM_ADDRESS_ENABLE;
+ r->end -= r->start;
+ r->start = 0;
+ }
+ /* This will disable and set address to unassigned */
+ pci_write_config_dword(dev, dev->rom_base_reg, 0);
+}
+
+
+static void * __init aty128_map_ROM(const struct aty128fb_par *par, struct pci_dev *dev)
+{
+ struct resource *r;
+ u16 dptr;
+ u8 rom_type;
+ void *bios;
+
+ /* Fix from ATI for problem with Rage128 hardware not leaving ROM enabled */
+ unsigned int temp;
+ temp = aty_ld_le32(RAGE128_MPP_TB_CONFIG);
+ temp &= 0x00ffffffu;
+ temp |= 0x04 << 24;
+ aty_st_le32(RAGE128_MPP_TB_CONFIG, temp);
+ temp = aty_ld_le32(RAGE128_MPP_TB_CONFIG);
+
+ /* no need to search for the ROM, just ask the card where it is. */
+ r = &dev->resource[PCI_ROM_RESOURCE];
+
+ /* assign the ROM an address if it doesn't have one */
+ if (r->parent == NULL)
+ pci_assign_resource(dev, PCI_ROM_RESOURCE);
+
+ /* enable if needed */
+ if (!(r->flags & PCI_ROM_ADDRESS_ENABLE)) {
+ pci_write_config_dword(dev, dev->rom_base_reg,
+ r->start | PCI_ROM_ADDRESS_ENABLE);
+ r->flags |= PCI_ROM_ADDRESS_ENABLE;
+ }
+
+ bios = ioremap(r->start, r->end - r->start + 1);
+ if (!bios) {
+ printk(KERN_ERR "aty128fb: ROM failed to map\n");
+ return NULL;
+ }
+
+ /* Very simple test to make sure it appeared */
+ if (BIOS_IN16(0) != 0xaa55) {
+ printk(KERN_ERR "aty128fb: Invalid ROM signature %x should be 0xaa55\n",
+ BIOS_IN16(0));
+ goto failed;
+ }
+
+ /* Look for the PCI data to check the ROM type */
+ dptr = BIOS_IN16(0x18);
+
+ /* Check the PCI data signature. If it's wrong, we still assume a normal x86 ROM
+ * for now, until I've verified this works everywhere. The goal here is more
+ * to phase out Open Firmware images.
+ *
+ * Currently, we only look at the first PCI data, we could iteratre and deal with
+ * them all, and we should use fb_bios_start relative to start of image and not
+ * relative start of ROM, but so far, I never found a dual-image ATI card
+ *
+ * typedef struct {
+ * u32 signature; + 0x00
+ * u16 vendor; + 0x04
+ * u16 device; + 0x06
+ * u16 reserved_1; + 0x08
+ * u16 dlen; + 0x0a
+ * u8 drevision; + 0x0c
+ * u8 class_hi; + 0x0d
+ * u16 class_lo; + 0x0e
+ * u16 ilen; + 0x10
+ * u16 irevision; + 0x12
+ * u8 type; + 0x14
+ * u8 indicator; + 0x15
+ * u16 reserved_2; + 0x16
+ * } pci_data_t;
+ */
+ if (BIOS_IN32(dptr) != (('R' << 24) | ('I' << 16) | ('C' << 8) | 'P')) {
+ printk(KERN_WARNING "aty128fb: PCI DATA signature in ROM incorrect: %08x\n",
+ BIOS_IN32(dptr));
+ goto anyway;
+ }
+ rom_type = BIOS_IN8(dptr + 0x14);
+ switch(rom_type) {
+ case 0:
+ printk(KERN_INFO "aty128fb: Found Intel x86 BIOS ROM Image\n");
+ break;
+ case 1:
+ printk(KERN_INFO "aty128fb: Found Open Firmware ROM Image\n");
+ goto failed;
+ case 2:
+ printk(KERN_INFO "aty128fb: Found HP PA-RISC ROM Image\n");
+ goto failed;
+ default:
+ printk(KERN_INFO "aty128fb: Found unknown type %d ROM Image\n", rom_type);
+ goto failed;
+ }
+ anyway:
+ return bios;
+
+ failed:
+ aty128_unmap_ROM(dev, bios);
+ return NULL;
+}
+
+static void __init aty128_get_pllinfo(struct aty128fb_par *par, unsigned char *bios)
+{
+ unsigned int bios_hdr;
+ unsigned int bios_pll;
+
+ bios_hdr = BIOS_IN16(0x48);
+ bios_pll = BIOS_IN16(bios_hdr + 0x30);
+
+ par->constants.ppll_max = BIOS_IN32(bios_pll + 0x16);
+ par->constants.ppll_min = BIOS_IN32(bios_pll + 0x12);
+ par->constants.xclk = BIOS_IN16(bios_pll + 0x08);
+ par->constants.ref_divider = BIOS_IN16(bios_pll + 0x10);
+ par->constants.ref_clk = BIOS_IN16(bios_pll + 0x0e);
+
+ DBG("ppll_max %d ppll_min %d xclk %d ref_divider %d ref clock %d\n",
+ par->constants.ppll_max, par->constants.ppll_min,
+ par->constants.xclk, par->constants.ref_divider,
+ par->constants.ref_clk);
+
+}
+
+#ifdef __i386__
+static void * __devinit aty128_find_mem_vbios(struct aty128fb_par *par)
+{
+ /* I simplified this code as we used to miss the signatures in
+ * a lot of case. It's now closer to XFree, we just don't check
+ * for signatures at all... Something better will have to be done
+ * if we end up having conflicts
+ */
+ u32 segstart;
+ unsigned char *rom_base = NULL;
+
+ for (segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
+ rom_base = (char *)ioremap(segstart, 0x10000);
+ if (rom_base == NULL)
+ return NULL;
+ if ((*rom_base == 0x55) && (((*(rom_base + 1)) & 0xff) == 0xaa))
+ break;
+ iounmap(rom_base);
+ rom_base = NULL;
+ }
+ return rom_base;
+}
+#endif /* __i386__ */
+#endif /* ndef(__sparc__) */
+
+/* fill in known card constants if pll_block is not available */
+static void __init aty128_timings(struct aty128fb_par *par)
+{
+#ifdef CONFIG_PPC_OF
+ /* instead of a table lookup, assume OF has properly
+ * setup the PLL registers and use their values
+ * to set the XCLK values and reference divider values */
+
+ u32 x_mpll_ref_fb_div;
+ u32 xclk_cntl;
+ u32 Nx, M;
+ unsigned PostDivSet[] = { 0, 1, 2, 4, 8, 3, 6, 12 };
+#endif
+
+ if (!par->constants.ref_clk)
+ par->constants.ref_clk = 2950;
+
+#ifdef CONFIG_PPC_OF
+ x_mpll_ref_fb_div = aty_ld_pll(X_MPLL_REF_FB_DIV);
+ xclk_cntl = aty_ld_pll(XCLK_CNTL) & 0x7;
+ Nx = (x_mpll_ref_fb_div & 0x00ff00) >> 8;
+ M = x_mpll_ref_fb_div & 0x0000ff;
+
+ par->constants.xclk = round_div((2 * Nx * par->constants.ref_clk),
+ (M * PostDivSet[xclk_cntl]));
+
+ par->constants.ref_divider =
+ aty_ld_pll(PPLL_REF_DIV) & PPLL_REF_DIV_MASK;
+#endif
+
+ if (!par->constants.ref_divider) {
+ par->constants.ref_divider = 0x3b;
+
+ aty_st_pll(X_MPLL_REF_FB_DIV, 0x004c4c1e);
+ aty_pll_writeupdate(par);
+ }
+ aty_st_pll(PPLL_REF_DIV, par->constants.ref_divider);
+ aty_pll_writeupdate(par);
+
+ /* from documentation */
+ if (!par->constants.ppll_min)
+ par->constants.ppll_min = 12500;
+ if (!par->constants.ppll_max)
+ par->constants.ppll_max = 25000; /* 23000 on some cards? */
+ if (!par->constants.xclk)
+ par->constants.xclk = 0x1d4d; /* same as mclk */
+
+ par->constants.fifo_width = 128;
+ par->constants.fifo_depth = 32;
+
+ switch (aty_ld_le32(MEM_CNTL) & 0x3) {
+ case 0:
+ par->mem = &sdr_128;
+ break;
+ case 1:
+ par->mem = &sdr_sgram;
+ break;
+ case 2:
+ par->mem = &ddr_sgram;
+ break;
+ default:
+ par->mem = &sdr_sgram;
+ }
+}
+
+
/*
- * CRTC programming
- */
+ * CRTC programming
+ */
/* Program the CRTC registers */
-static void
-aty128_set_crtc(const struct aty128_crtc *crtc,
- const struct aty128fb_par *par)
+static void aty128_set_crtc(const struct aty128_crtc *crtc,
+ const struct aty128fb_par *par)
{
aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl);
aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_total);
@@ -752,10 +1037,9 @@
}
-static int
-aty128_var_to_crtc(const struct fb_var_screeninfo *var,
- struct aty128_crtc *crtc,
- const struct aty128fb_par *par)
+static int aty128_var_to_crtc(const struct fb_var_screeninfo *var,
+ struct aty128_crtc *crtc,
+ const struct aty128fb_par *par)
{
u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp, dst;
u32 left, right, upper, lower, hslen, vslen, sync, vmode;
@@ -881,8 +1165,7 @@
}
-static int
-aty128_pix_width_to_var(int pix_width, struct fb_var_screeninfo *var)
+static int aty128_pix_width_to_var(int pix_width, struct fb_var_screeninfo *var)
{
/* fill in pixel info */
@@ -945,9 +1228,8 @@
}
-static int
-aty128_crtc_to_var(const struct aty128_crtc *crtc,
- struct fb_var_screeninfo *var)
+static int aty128_crtc_to_var(const struct aty128_crtc *crtc,
+ struct fb_var_screeninfo *var)
{
u32 xres, yres, left, right, upper, lower, hslen, vslen, sync;
u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
@@ -1003,8 +1285,7 @@
}
#ifdef CONFIG_PMAC_PBOOK
-static void
-aty128_set_crt_enable(struct aty128fb_par *par, int on)
+static void aty128_set_crt_enable(struct aty128fb_par *par, int on)
{
if (on) {
aty_st_le32(CRTC_EXT_CNTL, aty_ld_le32(CRTC_EXT_CNTL) | CRT_CRTC_ON);
@@ -1013,8 +1294,7 @@
aty_st_le32(CRTC_EXT_CNTL, aty_ld_le32(CRTC_EXT_CNTL) & ~CRT_CRTC_ON);
}
-static void
-aty128_set_lcd_enable(struct aty128fb_par *par, int on)
+static void aty128_set_lcd_enable(struct aty128fb_par *par, int on)
{
u32 reg;
@@ -1039,10 +1319,9 @@
aty_st_le32(LVDS_GEN_CNTL, reg);
}
}
-#endif
+#endif /* CONFIG_PMAC_PBOOK */
-static void
-aty128_set_pll(struct aty128_pll *pll, const struct aty128fb_par *par)
+static void aty128_set_pll(struct aty128_pll *pll, const struct aty128fb_par *par)
{
u32 div3;
@@ -1081,9 +1360,8 @@
}
-static int
-aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
- const struct aty128fb_par *par)
+static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
+ const struct aty128fb_par *par)
{
const struct aty128_constants c = par->constants;
unsigned char post_dividers[] = {1,2,4,8,3,6,12};
@@ -1109,7 +1387,7 @@
/* calculate feedback divider */
n = c.ref_divider * output_freq;
- d = c.dotclock;
+ d = c.ref_clk;
pll->post_divider = post_dividers[i];
pll->feedback_divider = round_div(n, d);
@@ -1124,8 +1402,7 @@
}
-static int
-aty128_pll_to_var(const struct aty128_pll *pll, struct fb_var_screeninfo *var)
+static int aty128_pll_to_var(const struct aty128_pll *pll, struct fb_var_screeninfo *var)
{
var->pixclock = 100000000 / pll->vclk;
@@ -1133,20 +1410,18 @@
}
-static void
-aty128_set_fifo(const struct aty128_ddafifo *dsp,
- const struct aty128fb_par *par)
+static void aty128_set_fifo(const struct aty128_ddafifo *dsp,
+ const struct aty128fb_par *par)
{
aty_st_le32(DDA_CONFIG, dsp->dda_config);
aty_st_le32(DDA_ON_OFF, dsp->dda_on_off);
}
-static int
-aty128_ddafifo(struct aty128_ddafifo *dsp,
- const struct aty128_pll *pll,
- u32 depth,
- const struct aty128fb_par *par)
+static int aty128_ddafifo(struct aty128_ddafifo *dsp,
+ const struct aty128_pll *pll,
+ u32 depth,
+ const struct aty128fb_par *par)
{
const struct aty128_meminfo *m = par->mem;
u32 xclk = par->constants.xclk;
@@ -1203,8 +1478,7 @@
/*
* This actually sets the video mode.
*/
-static int
-aty128fb_set_par(struct fb_info *info)
+static int aty128fb_set_par(struct fb_info *info)
{
struct aty128fb_par *par = info->par;
u32 config;
@@ -1276,8 +1550,7 @@
* encode/decode the User Defined Part of the Display
*/
-static int
-aty128_decode_var(struct fb_var_screeninfo *var, struct aty128fb_par *par)
+static int aty128_decode_var(struct fb_var_screeninfo *var, struct aty128fb_par *par)
{
int err;
struct aty128_crtc crtc;
@@ -1302,9 +1575,8 @@
}
-static int
-aty128_encode_var(struct fb_var_screeninfo *var,
- const struct aty128fb_par *par)
+static int aty128_encode_var(struct fb_var_screeninfo *var,
+ const struct aty128fb_par *par)
{
int err;
@@ -1325,8 +1597,7 @@
}
-static int
-aty128fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+static int aty128fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct aty128fb_par par;
int err;
@@ -1342,8 +1613,7 @@
/*
* Pan or Wrap the Display
*/
-static int
-aty128fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fb)
+static int aty128fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fb)
{
struct aty128fb_par *par = fb->par;
u32 xoffset, yoffset;
@@ -1376,9 +1646,8 @@
/*
* Helper function to store a single palette register
*/
-static void
-aty128_st_pal(u_int regno, u_int red, u_int green, u_int blue,
- struct aty128fb_par *par)
+static void aty128_st_pal(u_int regno, u_int red, u_int green, u_int blue,
+ struct aty128fb_par *par)
{
if (par->chip_gen == rage_M3) {
#if 0
@@ -1400,8 +1669,7 @@
aty_st_le32(PALETTE_DATA, (red<<16)|(green<<8)|blue);
}
-static int
-aty128fb_sync(struct fb_info *info)
+static int aty128fb_sync(struct fb_info *info)
{
struct aty128fb_par *par = info->par;
@@ -1410,8 +1678,7 @@
return 0;
}
-int __init
-aty128fb_setup(char *options)
+int __init aty128fb_setup(char *options)
{
char *this_opt;
@@ -1470,13 +1737,12 @@
* Initialisation
*/
-static int __init
-aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int __init aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct fb_info *info = pci_get_drvdata(pdev);
struct aty128fb_par *par = info->par;
struct fb_var_screeninfo var;
- char video_card[25];
+ char video_card[DEVICE_NAME_SIZE];
u8 chip_rev;
u32 dac;
@@ -1486,43 +1752,13 @@
/* Get the chip revision */
chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F;
- switch (pdev->device) {
- case PCI_DEVICE_ID_ATI_RAGE128_RE:
- strcpy(video_card, "Rage128 RE (PCI)");
- break;
- case PCI_DEVICE_ID_ATI_RAGE128_RF:
- strcpy(video_card, "Rage128 RF (AGP)");
- break;
- case PCI_DEVICE_ID_ATI_RAGE128_RK:
- strcpy(video_card, "Rage128 RK (PCI)");
- break;
- case PCI_DEVICE_ID_ATI_RAGE128_RL:
- strcpy(video_card, "Rage128 RL (AGP)");
- break;
- case PCI_DEVICE_ID_ATI_Rage128_PD:
- strcpy(video_card, "Rage128 Pro PD (PCI)");
- break;
- case PCI_DEVICE_ID_ATI_RAGE128_PF:
- strcpy(video_card, "Rage128 Pro PF (AGP)");
- break;
- case PCI_DEVICE_ID_ATI_RAGE128_PR:
- strcpy(video_card, "Rage128 Pro PR (PCI)");
- break;
- case PCI_DEVICE_ID_ATI_RAGE128_U3:
- strcpy(video_card, "Rage128 Pro TR (AGP)");
- break;
- case PCI_DEVICE_ID_ATI_RAGE128_U1:
- strcpy(video_card, "Rage128 Pro TF (AGP)");
- break;
- case PCI_DEVICE_ID_ATI_RAGE128_LE:
- strcpy(video_card, "Rage Mobility M3 (PCI)");
- break;
- case PCI_DEVICE_ID_ATI_RAGE128_LF:
- strcpy(video_card, "Rage Mobility M3 (AGP)");
- break;
- default:
- return -ENODEV;
- }
+ strcpy(video_card, "Rage128 XX ");
+ video_card[8] = ent->device >> 8;
+ video_card[9] = ent->device & 0xFF;
+
+ /* range check to make sure */
+ if (ent->driver_data < (sizeof(r128_family)/sizeof(char *)))
+ strncat(video_card, r128_family[ent->driver_data], sizeof(video_card));
printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev);
@@ -1575,8 +1811,12 @@
if (machine_is_compatible("PowerBook3,2"))
default_vmode = VMODE_1152_768_60;
- if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
- default_cmode = CMODE_8;
+ if (default_cmode > 16)
+ default_cmode = CMODE_32;
+ else if (default_cmode > 8)
+ default_cmode = CMODE_16;
+ else
+ default_cmode = CMODE_8;
if (mac_vmode_to_var(default_vmode, default_cmode, &var))
var = default_var;
@@ -1584,9 +1824,10 @@
} else
#endif /* CONFIG_PPC_PMAC */
{
- if (fb_find_mode(&var, info, mode_option, NULL, 0,
- &defaultmode, 8) == 0)
- var = default_var;
+ if (mode_option)
+ if (fb_find_mode(&var, info, mode_option, NULL,
+ 0, &defaultmode, 8) == 0)
+ var = default_var;
}
var.accel_flags &= ~FB_ACCELF_TEXT;
@@ -1623,16 +1864,12 @@
if (par->chip_gen == rage_M3)
register_backlight_controller(&aty128_backlight_controller, par, "ati");
#endif /* CONFIG_PMAC_BACKLIGHT */
-#ifdef CONFIG_PMAC_PBOOK
+
par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM);
- if (aty128_fb == NULL) {
- /* XXX can only put one chip to sleep */
- aty128_fb = info;
- } else
- printk(KERN_WARNING "aty128fb: can only sleep one Rage 128\n");
par->pdev = pdev;
-#endif
-
+ par->asleep = 0;
+ par->lock_blank = 0;
+
printk(KERN_INFO "fb%d: %s frame buffer device on %s\n",
info->node, info->fix.id, video_card);
@@ -1641,14 +1878,13 @@
#ifdef CONFIG_PCI
/* register a card ++ajoshi */
-static int __init
-aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int __init aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
unsigned long fb_addr, reg_addr;
struct aty128fb_par *par;
struct fb_info *info;
- int err, size;
-#if !defined(CONFIG_PPC) && !defined(__sparc__)
+ int err;
+#ifndef __sparc__
void *bios = NULL;
#endif
@@ -1675,17 +1911,14 @@
}
/* We have the resources. Now virtualize them */
- size = sizeof(struct fb_info) + sizeof(struct aty128fb_par);
- if (!(info = kmalloc(size, GFP_ATOMIC))) {
+ info = framebuffer_alloc(sizeof(struct aty128fb_par), &pdev->dev);
+ if (info == NULL) {
printk(KERN_ERR "aty128fb: can't alloc fb_info_aty128\n");
goto err_free_mmio;
}
- memset(info, 0, size);
+ par = info->par;
- par = (struct aty128fb_par *)(info + 1);
info->pseudo_palette = par->pseudo_palette;
-
- info->par = par;
info->fix = aty128fb_fix;
/* Virtualize mmio region */
@@ -1715,16 +1948,21 @@
goto err_out;
}
-#if !defined(CONFIG_PPC) && !defined(__sparc__)
- if (!(bios = aty128_map_ROM(pdev)))
+#ifndef __sparc__
+ bios = aty128_map_ROM(par, pdev);
+#ifdef __i386__
+ if (bios == NULL)
+ bios = aty128_find_mem_vbios(par);
+#endif
+ if (bios == NULL)
printk(KERN_INFO "aty128fb: BIOS not located, guessing timings.\n");
else {
- printk(KERN_INFO "aty128fb: Rage128 BIOS located at %lx\n",
- pdev->resource[PCI_ROM_RESOURCE].start);
+ printk(KERN_INFO "aty128fb: Rage128 BIOS located\n");
aty128_get_pllinfo(par, bios);
aty128_unmap_ROM(pdev, bios);
}
-#endif
+#endif /* __sparc__ */
+
aty128_timings(par);
pci_set_drvdata(pdev, info);
@@ -1747,7 +1985,7 @@
err_unmap_out:
iounmap(par->regbase);
err_free_info:
- kfree(info);
+ framebuffer_release(info);
err_free_mmio:
release_mem_region(pci_resource_start(pdev, 2),
pci_resource_len(pdev, 2));
@@ -1780,170 +2018,23 @@
pci_resource_len(pdev, 1));
release_mem_region(pci_resource_start(pdev, 2),
pci_resource_len(pdev, 2));
-#ifdef CONFIG_PMAC_PBOOK
- if (info == aty128_fb)
- aty128_fb = NULL;
-#endif
- kfree(info);
+ framebuffer_release(info);
}
#endif /* CONFIG_PCI */
-/* PPC and Sparc cannot read video ROM */
-#if !defined(CONFIG_PPC) && !defined(__sparc__)
-static void * __init aty128_map_ROM(struct pci_dev *dev)
-{
- // If this is a primary card, there is a shadow copy of the
- // ROM somewhere in the first meg. We will just ignore the copy
- // and use the ROM directly.
-
- // no need to search for the ROM, just ask the card where it is.
- struct resource *r = &dev->resource[PCI_ROM_RESOURCE];
- unsigned char *addr;
-
- // assign the ROM an address if it doesn't have one
- if (r->start == 0)
- pci_assign_resource(dev, PCI_ROM_RESOURCE);
-
- // enable if needed
- if (!(r->flags & PCI_ROM_ADDRESS_ENABLE))
- pci_write_config_dword(dev, dev->rom_base_reg, r->start | PCI_ROM_ADDRESS_ENABLE);
-
- addr = ioremap(r->start, r->end - r->start + 1);
-
- // Very simple test to make sure it appeared
- if (addr && (*addr != 0x55)) {
- printk("aty128fb: Invalid ROM signature %x\n", *addr);
- iounmap(addr);
- return NULL;
- }
- return (void *)addr;
-}
-
-static void __init aty128_unmap_ROM(struct pci_dev *dev, void * rom)
-{
- // leave it disabled and unassigned
- struct resource *r = &dev->resource[PCI_ROM_RESOURCE];
-
- iounmap(rom);
-
- r->flags &= !PCI_ROM_ADDRESS_ENABLE;
- r->end -= r->start;
- r->start = 0;
- pci_write_config_dword(dev, dev->rom_base_reg, 0);
-}
-
-static void __init
-aty128_get_pllinfo(struct aty128fb_par *par, void *bios)
-{
- void *bios_header;
- void *header_ptr;
- u16 bios_header_offset, pll_info_offset;
- PLL_BLOCK pll;
-
- bios_header = (char *)bios + 0x48L;
- header_ptr = bios_header;
-
- bios_header_offset = readw(header_ptr);
- bios_header = (char *)bios + bios_header_offset;
- bios_header += 0x30;
-
- header_ptr = bios_header;
- pll_info_offset = readw(header_ptr);
- header_ptr = (char *)bios + pll_info_offset;
-
- memcpy_fromio(&pll, header_ptr, 50);
-
- par->constants.ppll_max = pll.PCLK_max_freq;
- par->constants.ppll_min = pll.PCLK_min_freq;
- par->constants.xclk = (u32)pll.XCLK;
- par->constants.ref_divider = (u32)pll.PCLK_ref_divider;
- par->constants.dotclock = (u32)pll.PCLK_ref_freq;
-
- DBG("ppll_max %d ppll_min %d xclk %d ref_divider %d dotclock %d\n",
- par->constants.ppll_max, par->constants.ppll_min,
- par->constants.xclk, par->constants.ref_divider,
- par->constants.dotclock);
-
-}
-#endif /* !CONFIG_PPC */
-
-
-/* fill in known card constants if pll_block is not available */
-static void __init
-aty128_timings(struct aty128fb_par *par)
-{
-#ifdef CONFIG_PPC_OF
- /* instead of a table lookup, assume OF has properly
- * setup the PLL registers and use their values
- * to set the XCLK values and reference divider values */
-
- u32 x_mpll_ref_fb_div;
- u32 xclk_cntl;
- u32 Nx, M;
- unsigned PostDivSet[] = { 0, 1, 2, 4, 8, 3, 6, 12 };
-#endif
-
- if (!par->constants.dotclock)
- par->constants.dotclock = 2950;
-
-#ifdef CONFIG_PPC_OF
- x_mpll_ref_fb_div = aty_ld_pll(X_MPLL_REF_FB_DIV);
- xclk_cntl = aty_ld_pll(XCLK_CNTL) & 0x7;
- Nx = (x_mpll_ref_fb_div & 0x00ff00) >> 8;
- M = x_mpll_ref_fb_div & 0x0000ff;
-
- par->constants.xclk = round_div((2 * Nx * par->constants.dotclock),
- (M * PostDivSet[xclk_cntl]));
-
- par->constants.ref_divider =
- aty_ld_pll(PPLL_REF_DIV) & PPLL_REF_DIV_MASK;
-#endif
-
- if (!par->constants.ref_divider) {
- par->constants.ref_divider = 0x3b;
-
- aty_st_pll(X_MPLL_REF_FB_DIV, 0x004c4c1e);
- aty_pll_writeupdate(par);
- }
- aty_st_pll(PPLL_REF_DIV, par->constants.ref_divider);
- aty_pll_writeupdate(par);
-
- /* from documentation */
- if (!par->constants.ppll_min)
- par->constants.ppll_min = 12500;
- if (!par->constants.ppll_max)
- par->constants.ppll_max = 25000; /* 23000 on some cards? */
- if (!par->constants.xclk)
- par->constants.xclk = 0x1d4d; /* same as mclk */
-
- par->constants.fifo_width = 128;
- par->constants.fifo_depth = 32;
-
- switch (aty_ld_le32(MEM_CNTL) & 0x3) {
- case 0:
- par->mem = &sdr_128;
- break;
- case 1:
- par->mem = &sdr_sgram;
- break;
- case 2:
- par->mem = &ddr_sgram;
- break;
- default:
- par->mem = &sdr_sgram;
- }
-}
/*
* Blank the display.
*/
-static int
-aty128fb_blank(int blank, struct fb_info *fb)
+static int aty128fb_blank(int blank, struct fb_info *fb)
{
struct aty128fb_par *par = fb->par;
u8 state = 0;
+ if (par->lock_blank || par->asleep)
+ return 0;
+
#ifdef CONFIG_PMAC_BACKLIGHT
if ((_machine == _MACH_Pmac) && blank)
set_backlight_enable(0);
@@ -1976,9 +2067,8 @@
* rounded down to the hardware's capabilities (according to the
* entries in the var structure). Return != 0 for invalid regno.
*/
-static int
-aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
- u_int transp, struct fb_info *info)
+static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info)
{
struct aty128fb_par *par = info->par;
@@ -2041,9 +2131,9 @@
#define ATY_MIRROR_CRT_ON 0x00000002
/* out param: u32* backlight value: 0 to 15 */
-#define FBIO_ATY128_GET_MIRROR _IOR('@', 1, __u32*)
+#define FBIO_ATY128_GET_MIRROR _IOR('@', 1, __u32)
/* in param: u32* backlight value: 0 to 15 */
-#define FBIO_ATY128_SET_MIRROR _IOW('@', 2, __u32*)
+#define FBIO_ATY128_SET_MIRROR _IOW('@', 2, __u32)
static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
u_long arg, struct fb_info *info)
@@ -2091,8 +2181,7 @@
/* That one prevents proper CRT output with LCD off */
#undef BACKLIGHT_DAC_OFF
-static int
-aty128_set_backlight_enable(int on, int level, void *data)
+static int aty128_set_backlight_enable(int on, int level, void *data)
{
struct aty128fb_par *par = data;
unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
@@ -2139,8 +2228,7 @@
return 0;
}
-static int
-aty128_set_backlight_level(int level, void* data)
+static int aty128_set_backlight_level(int level, void* data)
{
return aty128_set_backlight_enable(1, level, data);
}
@@ -2151,10 +2239,9 @@
* Accelerated functions
*/
-static inline void
-aty128_rectcopy(int srcx, int srcy, int dstx, int dsty,
- u_int width, u_int height,
- struct fb_info_aty128 *par)
+static inline void aty128_rectcopy(int srcx, int srcy, int dstx, int dsty,
+ u_int width, u_int height,
+ struct fb_info_aty128 *par)
{
u32 save_dp_datatype, save_dp_cntl, dstval;
@@ -2196,8 +2283,7 @@
* Text mode accelerated functions
*/
-static void
-fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy, int dx,
+static void fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
sx *= fontwidth(p);
@@ -2212,9 +2298,7 @@
}
#endif /* 0 */
-#ifdef CONFIG_PMAC_PBOOK
-static void
-aty128_set_suspend(struct aty128fb_par *par, int suspend)
+static void aty128_set_suspend(struct aty128fb_par *par, int suspend)
{
u32 pmgt;
u16 pwr_command;
@@ -2257,95 +2341,122 @@
}
}
-/*
- * Save the contents of the frame buffer when we go to sleep,
- * and restore it when we wake up again.
- */
-int
-aty128_sleep_notify(struct pmu_sleep_notifier *self, int when)
+static int aty128_pci_suspend(struct pci_dev *pdev, u32 state)
{
- int nb;
- struct fb_info *info = aty128_fb;
- struct aty128fb_par *par;
+ struct fb_info *info = pci_get_drvdata(pdev);
+ struct aty128fb_par *par = info->par;
- if (info == NULL)
- return PBOOK_SLEEP_OK;
- par = info->par;
- nb = info->var.yres * info->fix.line_length;
+ /* We don't do anything but D2, for now we return 0, but
+ * we may want to change that. How do we know if the BIOS
+ * can properly take care of D3 ? Also, with swsusp, we
+ * know we'll be rebooted, ...
+ */
+#ifdef CONFIG_PPC_PMAC
+ /* HACK ALERT ! Once I find a proper way to say to each driver
+ * individually what will happen with it's PCI slot, I'll change
+ * that. On laptops, the AGP slot is just unclocked, so D2 is
+ * expected, while on desktops, the card is powered off
+ */
+ if (state >= 3)
+ state = 2;
+#endif /* CONFIG_PPC_PMAC */
+
+ if (state != 2 || state == pdev->dev.power_state)
+ return 0;
- switch (when) {
- case PBOOK_SLEEP_REQUEST:
- par->save_framebuffer = vmalloc(nb);
- if (par->save_framebuffer == NULL)
- return PBOOK_SLEEP_REFUSE;
- break;
- case PBOOK_SLEEP_REJECT:
- if (par->save_framebuffer) {
- vfree(par->save_framebuffer);
- par->save_framebuffer = 0;
- }
- break;
- case PBOOK_SLEEP_NOW:
- wait_for_idle(par);
- aty128_reset_engine(par);
- wait_for_idle(par);
+ printk(KERN_DEBUG "aty128fb: suspending...\n");
+
+ acquire_console_sem();
+
+ fb_set_suspend(info, 1);
+
+ /* Make sure engine is reset */
+ wait_for_idle(par);
+ aty128_reset_engine(par);
+ wait_for_idle(par);
+
+ /* Blank display and LCD */
+ aty128fb_blank(VESA_POWERDOWN, info);
- /* Backup fb content */
- if (par->save_framebuffer)
- memcpy_fromio(par->save_framebuffer,
- info->screen_base, nb);
-
- /* Blank display and LCD */
- aty128fb_blank(VESA_POWERDOWN, info);
-
- /* Sleep the chip */
+ /* Sleep */
+ par->asleep = 1;
+ par->lock_blank = 1;
+
+ /* We need a way to make sure the fbdev layer will _not_ touch the
+ * framebuffer before we put the chip to suspend state. On 2.4, I
+ * used dummy fb ops, 2.5 need proper support for this at the
+ * fbdev level
+ */
+ if (state == 2)
aty128_set_suspend(par, 1);
- break;
- case PBOOK_WAKE:
- /* Wake the chip */
+ release_console_sem();
+
+ pdev->dev.power_state = state;
+
+ return 0;
+}
+
+static int aty128_pci_resume(struct pci_dev *pdev)
+{
+ struct fb_info *info = pci_get_drvdata(pdev);
+ struct aty128fb_par *par = info->par;
+
+ if (pdev->dev.power_state == 0)
+ return 0;
+
+ acquire_console_sem();
+
+ /* Wakeup chip */
+ if (pdev->dev.power_state == 2)
aty128_set_suspend(par, 0);
-
- aty128_reset_engine(par);
- wait_for_idle(par);
+ par->asleep = 0;
- /* Restore fb content */
- if (par->save_framebuffer) {
- memcpy_toio(info->screen_base,
- par->save_framebuffer, nb);
- vfree(par->save_framebuffer);
- par->save_framebuffer = 0;
- }
- aty128fb_blank(0, info);
- break;
- }
- return PBOOK_SLEEP_OK;
+ /* Restore display & engine */
+ aty128_reset_engine(par);
+ wait_for_idle(par);
+ aty128fb_set_par(info);
+ fb_pan_display(info, &info->var);
+ fb_set_cmap(&info->cmap, 1, info);
+
+ /* Refresh */
+ fb_set_suspend(info, 0);
+
+ /* Unblank */
+ par->lock_blank = 0;
+ aty128fb_blank(0, info);
+
+ release_console_sem();
+
+ pdev->dev.power_state = 0;
+
+ printk(KERN_DEBUG "aty128fb: resumed !\n");
+
+ return 0;
}
-#endif /* CONFIG_PMAC_PBOOK */
int __init aty128fb_init(void)
{
-#ifdef CONFIG_PMAC_PBOOK
- pmu_register_sleep_notifier(&aty128_sleep_notifier);
-#endif
return pci_module_init(&aty128fb_driver);
}
static void __exit aty128fb_exit(void)
{
-#ifdef CONFIG_PMAC_PBOOK
- pmu_unregister_sleep_notifier(&aty128_sleep_notifier);
-#endif
pci_unregister_driver(&aty128fb_driver);
}
+#ifdef MODULE
+module_init(aty128fb_init);
+module_exit(aty128fb_exit);
+
MODULE_AUTHOR("(c)1999-2003 Brad Douglas ");
MODULE_DESCRIPTION("FBDev driver for ATI Rage128 / Pro cards");
MODULE_LICENSE("GPL");
-MODULE_PARM(mode, "s");
+module_param(mode_option, charp, 0);
MODULE_PARM_DESC(mode, "Specify resolution as \"x[-][@]\" ");
#ifdef CONFIG_MTRR
-MODULE_PARM(nomtrr, "i");
-MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)");
+module_param_named(nomtrr, mtrr, invbool, 0);
+MODULE_PARM_DESC(mtrr, "bool: Disable MTRR support (0 or 1=disabled) (default=0)");
+#endif
#endif
diff -urN linux-2.6.3-rc3/drivers/video/aty/radeon_accel.c linux-2.6.3-rc4/drivers/video/aty/radeon_accel.c
--- linux-2.6.3-rc3/drivers/video/aty/radeon_accel.c 2004-02-16 19:49:12.000000000 -0800
+++ linux-2.6.3-rc4/drivers/video/aty/radeon_accel.c 2004-02-16 19:49:21.000000000 -0800
@@ -28,7 +28,7 @@
struct fb_fillrect modded;
int vxres, vyres;
- if (rinfo->asleep)
+ if (info->state != FBINFO_STATE_RUNNING)
return;
if (radeon_accel_disabled()) {
cfb_fillrect(info, region);
@@ -81,7 +81,7 @@
modded.width = area->width;
modded.height = area->height;
- if (rinfo->asleep)
+ if (info->state != FBINFO_STATE_RUNNING)
return;
if (radeon_accel_disabled()) {
cfb_copyarea(info, area);
@@ -108,7 +108,7 @@
{
struct radeonfb_info *rinfo = info->par;
- if (rinfo->asleep)
+ if (info->state != FBINFO_STATE_RUNNING)
return;
radeon_engine_idle();
@@ -119,7 +119,7 @@
{
struct radeonfb_info *rinfo = info->par;
- if (rinfo->asleep)
+ if (info->state != FBINFO_STATE_RUNNING)
return 0;
radeon_engine_idle();
diff -urN linux-2.6.3-rc3/drivers/video/aty/radeon_base.c linux-2.6.3-rc4/drivers/video/aty/radeon_base.c
--- linux-2.6.3-rc3/drivers/video/aty/radeon_base.c 2004-02-16 19:49:12.000000000 -0800
+++ linux-2.6.3-rc4/drivers/video/aty/radeon_base.c 2004-02-16 19:49:21.000000000 -0800
@@ -99,6 +99,8 @@
#include "ati_ids.h"
#include "radeonfb.h"
+#define MAX_MAPPED_VRAM (2048*2048*4)
+#define MIN_MAPPED_VRAM (1024*768*1)
#define CHIP_DEF(id, family, flags) \
{ PCI_VENDOR_ID_ATI, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (flags) | (CHIP_FAMILY_##family) }
@@ -210,7 +212,7 @@
/* these common regs are cleared before mode setting so they do not
* interfere with anything
*/
-reg_val common_regs[] = {
+static reg_val common_regs[] = {
{ OVR_CLR, 0 },
{ OVR_WID_LEFT_RIGHT, 0 },
{ OVR_WID_TOP_BOTTOM, 0 },
@@ -222,7 +224,7 @@
{ CAP0_TRIG_CNTL, 0 },
};
-reg_val common_regs_m6[] = {
+static reg_val common_regs_m6[] = {
{ OVR_CLR, 0 },
{ OVR_WID_LEFT_RIGHT, 0 },
{ OVR_WID_TOP_BOTTOM, 0 },
@@ -566,8 +568,9 @@
break;
}
- do_div(vclk, 1000);
- xtal = (xtal * denom) / num;
+ vclk *= denom;
+ do_div(vclk, 1000 * num);
+ xtal = vclk;
if ((xtal > 26900) && (xtal < 27100))
xtal = 2700;
@@ -825,6 +828,9 @@
v.xres_virtual = (pitch << 6) / ((v.bits_per_pixel + 1) / 8);
}
+ if (((v.xres_virtual * v.yres_virtual * nom) / den) > rinfo->mapped_vram)
+ return -EINVAL;
+
if (v.xres_virtual < v.xres)
v.xres = v.xres_virtual;
@@ -941,7 +947,7 @@
static int radeon_screen_blank (struct radeonfb_info *rinfo, int blank)
{
u32 val = INREG(CRTC_EXT_CNTL);
- u32 val2;
+ u32 val2 = 0;
if (rinfo->mon1_type == MT_LCD)
val2 = INREG(LVDS_GEN_CNTL) & ~LVDS_DISPLAY_DIS;
@@ -1022,7 +1028,7 @@
pindex = regno;
if (!rinfo->asleep) {
- u32 dac_cntl2, vclk_cntl;
+ u32 dac_cntl2, vclk_cntl = 0;
if (rinfo->is_mobility) {
vclk_cntl = INPLL(VCLK_ECP_CNTL);
@@ -1316,7 +1322,7 @@
{ 12, 7 },
{ 0, 0 },
};
- int fb_div, pll_output_freq;
+ int fb_div, pll_output_freq = 0;
int uses_dvo = 0;
/* Check if the DVO port is enabled and sourced from the primary CRTC. I'm
@@ -1441,7 +1447,7 @@
nopllcalc = 1;
newmode.ppll_div_3 = rinfo->panel_info.fbk_divider |
(rinfo->panel_info.post_divider << 16);
- newmode.ppll_ref_div = rinfo->pll.ref_div;
+ newmode.ppll_ref_div = rinfo->panel_info.ref_divider;
}
}
dotClock = 1000000000 / pixClock;
@@ -1685,6 +1691,67 @@
+static ssize_t radeonfb_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+ unsigned long p = *ppos;
+ struct inode *inode = file->f_dentry->d_inode;
+ int fbidx = iminor(inode);
+ struct fb_info *info = registered_fb[fbidx];
+ struct radeonfb_info *rinfo = info->par;
+
+ if (p >= rinfo->mapped_vram)
+ return 0;
+ if (count >= rinfo->mapped_vram)
+ count = rinfo->mapped_vram;
+ if (count + p > rinfo->mapped_vram)
+ count = rinfo->mapped_vram - p;
+ radeonfb_sync(info);
+ if (count) {
+ char *base_addr;
+
+ base_addr = info->screen_base;
+ count -= copy_to_user(buf, base_addr+p, count);
+ if (!count)
+ return -EFAULT;
+ *ppos += count;
+ }
+ return count;
+}
+
+static ssize_t radeonfb_write(struct file *file, const char *buf, size_t count,
+ loff_t *ppos)
+{
+ unsigned long p = *ppos;
+ struct inode *inode = file->f_dentry->d_inode;
+ int fbidx = iminor(inode);
+ struct fb_info *info = registered_fb[fbidx];
+ struct radeonfb_info *rinfo = info->par;
+ int err;
+
+ if (p > rinfo->mapped_vram)
+ return -ENOSPC;
+ if (count >= rinfo->mapped_vram)
+ count = rinfo->mapped_vram;
+ err = 0;
+ if (count + p > rinfo->mapped_vram) {
+ count = rinfo->mapped_vram - p;
+ err = -ENOSPC;
+ }
+ radeonfb_sync(info);
+ if (count) {
+ char *base_addr;
+
+ base_addr = info->screen_base;
+ count -= copy_from_user(base_addr+p, buf, count);
+ *ppos += count;
+ err = -EFAULT;
+ }
+ if (count)
+ return count;
+ return err;
+}
+
+
static struct fb_ops radeonfb_ops = {
.owner = THIS_MODULE,
.fb_check_var = radeonfb_check_var,
@@ -1697,6 +1764,8 @@
.fb_fillrect = radeonfb_fillrect,
.fb_copyarea = radeonfb_copyarea,
.fb_imageblit = radeonfb_imageblit,
+ .fb_read = radeonfb_read,
+ .fb_write = radeonfb_write,
.fb_cursor = soft_cursor,
};
@@ -2121,11 +2190,27 @@
RTRACE("radeonfb: probed %s %ldk videoram\n", (rinfo->ram_type), (rinfo->video_ram/1024));
- rinfo->fb_base = (unsigned long) ioremap (rinfo->fb_base_phys, rinfo->video_ram);
+ rinfo->mapped_vram = MAX_MAPPED_VRAM;
+ if (rinfo->video_ram < rinfo->mapped_vram)
+ rinfo->mapped_vram = rinfo->video_ram;
+ for (;;) {
+ rinfo->fb_base = (unsigned long) ioremap (rinfo->fb_base_phys,
+ rinfo->mapped_vram);
+ if (rinfo->fb_base == 0 && rinfo->mapped_vram > MIN_MAPPED_VRAM) {
+ rinfo->mapped_vram /= 2;
+ continue;
+ }
+ break;
+ }
+
if (!rinfo->fb_base) {
printk (KERN_ERR "radeonfb: cannot map FB\n");
goto unmap_rom;
}
+
+ RTRACE("radeonfb: mapped %ldk videoram\n", rinfo->mapped_vram/1024);
+
+
/* Argh. Scary arch !!! */
#ifdef CONFIG_PPC64
rinfo->fb_base = IO_TOKEN_TO_ADDR(rinfo->fb_base);
@@ -2331,7 +2416,7 @@
continue;
if (!strncmp(this_opt, "noaccel", 7)) {
- radeonfb_noaccel = 1;
+ noaccel = radeonfb_noaccel = 1;
} else if (!strncmp(this_opt, "mirror", 6)) {
mirror = 1;
} else if (!strncmp(this_opt, "force_dfp", 9)) {
diff -urN linux-2.6.3-rc3/drivers/video/aty/radeon_i2c.c linux-2.6.3-rc4/drivers/video/aty/radeon_i2c.c
--- linux-2.6.3-rc3/drivers/video/aty/radeon_i2c.c 2004-02-16 19:49:12.000000000 -0800
+++ linux-2.6.3-rc4/drivers/video/aty/radeon_i2c.c 2004-02-16 19:49:21.000000000 -0800
@@ -243,7 +243,8 @@
return MT_NONE;
}
if (edid[0x14] & 0x80) {
- if (rinfo->is_mobility && conn == ddc_dvi &&
+ /* Fix detection using BIOS tables */
+ if (rinfo->is_mobility /*&& conn == ddc_dvi*/ &&
(INREG(LVDS_GEN_CNTL) & LVDS_ON)) {
RTRACE("radeonfb: I2C (port %d) ... found LVDS panel\n", conn);
return MT_LCD;
diff -urN linux-2.6.3-rc3/drivers/video/aty/radeon_monitor.c linux-2.6.3-rc4/drivers/video/aty/radeon_monitor.c
--- linux-2.6.3-rc3/drivers/video/aty/radeon_monitor.c 2004-02-16 19:49:12.000000000 -0800
+++ linux-2.6.3-rc4/drivers/video/aty/radeon_monitor.c 2004-02-16 19:49:21.000000000 -0800
@@ -156,6 +156,7 @@
if (!(tmp = BIOS_IN16(rinfo->fp_bios_start + 0x40))) {
printk(KERN_ERR "radeonfb: Failed to detect DFP panel info using BIOS\n");
+ rinfo->panel_info.pwr_delay = 200;
return 0;
}
@@ -169,7 +170,8 @@
rinfo->panel_info.xres, rinfo->panel_info.yres);
rinfo->panel_info.pwr_delay = BIOS_IN16(tmp + 44);
- if (rinfo->panel_info.pwr_delay > 2000 || rinfo->panel_info.pwr_delay < 0)
+ RTRACE("BIOS provided panel power delay: %d\n", rinfo->panel_info.pwr_delay);
+ if (rinfo->panel_info.pwr_delay > 2000 || rinfo->panel_info.pwr_delay <= 0)
rinfo->panel_info.pwr_delay = 2000;
/*
@@ -182,11 +184,16 @@
rinfo->panel_info.fbk_divider > 3) {
rinfo->panel_info.use_bios_dividers = 1;
printk(KERN_INFO "radeondb: BIOS provided dividers will be used\n");
+ RTRACE("ref_divider = %x\n", rinfo->panel_info.ref_divider);
+ RTRACE("post_divider = %x\n", rinfo->panel_info.post_divider);
+ RTRACE("fbk_divider = %x\n", rinfo->panel_info.fbk_divider);
}
+ RTRACE("Scanning BIOS table ...\n");
for(i=0; i<32; i++) {
tmp0 = BIOS_IN16(tmp+64+i*2);
if (tmp0 == 0)
break;
+ RTRACE(" %d x %d\n", BIOS_IN16(tmp0), BIOS_IN16(tmp0+2));
if ((BIOS_IN16(tmp0) == rinfo->panel_info.xres) &&
(BIOS_IN16(tmp0+2) == rinfo->panel_info.yres)) {
rinfo->panel_info.hblank = (BIOS_IN16(tmp0+17) - BIOS_IN16(tmp0+19)) * 8;
@@ -205,13 +212,68 @@
/* Mark panel infos valid */
rinfo->panel_info.valid = 1;
+ RTRACE("Found panel in BIOS table:\n");
+ RTRACE(" hblank: %d\n", rinfo->panel_info.hblank);
+ RTRACE(" hOver_plus: %d\n", rinfo->panel_info.hOver_plus);
+ RTRACE(" hSync_width: %d\n", rinfo->panel_info.hSync_width);
+ RTRACE(" vblank: %d\n", rinfo->panel_info.vblank);
+ RTRACE(" vOver_plus: %d\n", rinfo->panel_info.vOver_plus);
+ RTRACE(" vSync_width: %d\n", rinfo->panel_info.vSync_width);
+ RTRACE(" clock: %d\n", rinfo->panel_info.clock);
+
return 1;
}
}
+ RTRACE("Didn't find panel in BIOS table !\n");
return 0;
}
+/* Try to extract the connector informations from the BIOS. This
+ * doesn't quite work yet, but it's output is still useful for
+ * debugging
+ */
+static void __devinit radeon_parse_connector_info(struct radeonfb_info *rinfo)
+{
+ int offset, chips, connectors, tmp, i, conn, type;
+
+ static char* __conn_type_table[16] = {
+ "NONE", "Proprietary", "CRT", "DVI-I", "DVI-D", "Unknown", "Unknown",
+ "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown",
+ "Unknown", "Unknown", "Unknown"
+ };
+
+ if (!rinfo->bios_seg)
+ return;
+
+ offset = BIOS_IN16(rinfo->fp_bios_start + 0x50);
+ if (offset == 0) {
+ printk(KERN_WARNING "radeonfb: No connector info table detected\n");
+ return;
+ }
+
+ /* Don't do much more at this point but displaying the data if
+ * DEBUG is enabled
+ */
+ chips = BIOS_IN8(offset++) >> 4;
+ RTRACE("%d chips in connector info\n", chips);
+ for (i = 0; i < chips; i++) {
+ tmp = BIOS_IN8(offset++);
+ connectors = tmp & 0x0f;
+ RTRACE(" - chip %d has %d connectors\n", tmp >> 4, connectors);
+ for (conn = 0; ; conn++) {
+ tmp = BIOS_IN16(offset);
+ if (tmp == 0)
+ break;
+ offset += 2;
+ type = (tmp >> 12) & 0x0f;
+ RTRACE(" * connector %d of type %d (%s) : %04x\n",
+ conn, type, __conn_type_table[type], tmp);
+ }
+ }
+}
+
+
/*
* Probe physical connection of a CRT. This code comes from XFree
* as well and currently is only implemented for the CRT DAC, the
@@ -224,7 +286,7 @@
/* the monitor either wasn't connected or it is a non-DDC CRT.
* try to probe it
*/
- if(is_crt_dac) {
+ if (is_crt_dac) {
unsigned long ulOrigVCLK_ECP_CNTL;
unsigned long ulOrigDAC_CNTL;
unsigned long ulOrigDAC_EXT_CNTL;
@@ -353,10 +415,12 @@
const char *monitor_layout, int ignore_edid)
{
#ifdef CONFIG_FB_RADEON_I2C
- int ddc_crt2_used = 0;
+ int ddc_crt2_used = 0;
#endif
int tmp, i;
+ radeon_parse_connector_info(rinfo);
+
if (radeon_parse_monitor_layout(rinfo, monitor_layout)) {
/*
@@ -392,13 +456,23 @@
rinfo->mon2_EDID = NULL;
}
} else {
-
/*
* Auto-detecting display type (well... trying to ...)
*/
RTRACE("Starting monitor auto detection...\n");
+#if DEBUG && defined(CONFIG_FB_RADEON_I2C)
+ {
+ u8 *EDIDs[4] = { NULL, NULL, NULL, NULL };
+ int mon_types[4] = {MT_NONE, MT_NONE, MT_NONE, MT_NONE};
+ int i;
+
+ for (i = 0; i < 4; i++)
+ mon_types[i] = radeon_probe_i2c_connector(rinfo,
+ i+1, &EDIDs[i]);
+ }
+#endif /* DEBUG */
/*
* Old single head cards
*/
@@ -759,7 +833,7 @@
rinfo->mon1_type = MT_CRT;
goto pickup_default;
}
- printk(KERN_WARNING "radeonfb: Asssuming panel size %dx%d\n",
+ printk(KERN_WARNING "radeonfb: Assuming panel size %dx%d\n",
rinfo->panel_info.xres, rinfo->panel_info.yres);
modedb = rinfo->mon1_modedb;
dbsize = rinfo->mon1_dbsize;
diff -urN linux-2.6.3-rc3/drivers/video/aty/radeonfb.h linux-2.6.3-rc4/drivers/video/aty/radeonfb.h
--- linux-2.6.3-rc3/drivers/video/aty/radeonfb.h 2004-02-16 19:49:12.000000000 -0800
+++ linux-2.6.3-rc4/drivers/video/aty/radeonfb.h 2004-02-16 19:49:21.000000000 -0800
@@ -282,6 +282,7 @@
u8 family;
u8 rev;
unsigned long video_ram;
+ unsigned long mapped_vram;
int pitch, bpp, depth;
@@ -332,7 +333,11 @@
/*
* Debugging stuffs
*/
+#ifdef CONFIG_FB_RADEON_DEBUG
+#define DEBUG 1
+#else
#define DEBUG 0
+#endif
#if DEBUG
#define RTRACE printk
diff -urN linux-2.6.3-rc3/drivers/video/cfbcopyarea.c linux-2.6.3-rc4/drivers/video/cfbcopyarea.c
--- linux-2.6.3-rc3/drivers/video/cfbcopyarea.c 2004-02-03 19:44:34.000000000 -0800
+++ linux-2.6.3-rc4/drivers/video/cfbcopyarea.c 2004-02-16 19:49:21.000000000 -0800
@@ -346,6 +346,9 @@
int dst_idx = 0, src_idx = 0, rev_copy = 0;
unsigned long *dst = NULL, *src = NULL;
+ if (p->state != FBINFO_STATE_RUNNING)
+ return;
+
/* We want rotation but lack hardware to do it for us. */
if (!p->fbops->fb_rotate && p->var.rotate) {
}
diff -urN linux-2.6.3-rc3/drivers/video/cfbfillrect.c linux-2.6.3-rc4/drivers/video/cfbfillrect.c
--- linux-2.6.3-rc3/drivers/video/cfbfillrect.c 2004-02-03 19:43:56.000000000 -0800
+++ linux-2.6.3-rc4/drivers/video/cfbfillrect.c 2004-02-16 19:49:21.000000000 -0800
@@ -367,6 +367,9 @@
unsigned long *dst;
int dst_idx, left;
+ if (p->state != FBINFO_STATE_RUNNING)
+ return;
+
/* We want rotation but lack hardware to do it for us. */
if (!p->fbops->fb_rotate && p->var.rotate) {
}
diff -urN linux-2.6.3-rc3/drivers/video/cfbimgblt.c linux-2.6.3-rc4/drivers/video/cfbimgblt.c
--- linux-2.6.3-rc3/drivers/video/cfbimgblt.c 2004-02-16 19:49:12.000000000 -0800
+++ linux-2.6.3-rc4/drivers/video/cfbimgblt.c 2004-02-16 19:49:21.000000000 -0800
@@ -275,6 +275,9 @@
int x2, y2, vxres, vyres;
u8 *dst1;
+ if (p->state != FBINFO_STATE_RUNNING)
+ return;
+
vxres = p->var.xres_virtual;
vyres = p->var.yres_virtual;
/*
diff -urN linux-2.6.3-rc3/drivers/video/console/fbcon.c linux-2.6.3-rc4/drivers/video/console/fbcon.c
--- linux-2.6.3-rc3/drivers/video/console/fbcon.c 2004-02-16 19:49:12.000000000 -0800
+++ linux-2.6.3-rc4/drivers/video/console/fbcon.c 2004-02-16 19:49:21.000000000 -0800
@@ -195,11 +195,13 @@
{
struct fb_info *info = (struct fb_info *) private;
- /* Test to see if the cursor is erased but still on */
- if (!info || (info->cursor.rop == ROP_COPY))
+ if (!info || info->state != FBINFO_STATE_RUNNING ||
+ info->cursor.rop == ROP_COPY)
return;
+ acquire_console_sem();
info->cursor.enable ^= 1;
info->fbops->fb_cursor(info, &info->cursor);
+ release_console_sem();
}
#if (defined(__arm__) && defined(IRQ_VSYNCPULSE)) || defined(CONFIG_ATARI) || defined(CONFIG_MAC)
@@ -226,8 +228,7 @@
struct fb_info *info = (struct fb_info *) dev_addr;
schedule_work(&info->queue);
- cursor_timer.expires = jiffies + HZ / 5;
- add_timer(&cursor_timer);
+ mod_timer(&cursor_timer, jiffies + HZ/5);
}
int __init fb_console_setup(char *this_opt)
@@ -353,8 +354,6 @@
info->fbops->fb_imageblit(info, image);
image->dx += cnt * vc->vc_font.width;
count -= cnt;
- atomic_dec(&info->pixmap.count);
- smp_mb__after_atomic_dec();
}
}
@@ -393,8 +392,6 @@
info->fbops->fb_imageblit(info, image);
image->dx += cnt * vc->vc_font.width;
count -= cnt;
- atomic_dec(&info->pixmap.count);
- smp_mb__after_atomic_dec();
}
}
@@ -465,8 +462,6 @@
move_buf_aligned(info, dst, src, pitch, width, image.height);
info->fbops->fb_imageblit(info, &image);
- atomic_dec(&info->pixmap.count);
- smp_mb__after_atomic_dec();
}
void accel_putcs(struct vc_data *vc, struct fb_info *info,
@@ -676,7 +671,7 @@
if (!info->queue.func) {
INIT_WORK(&info->queue, fb_flashcursor, info);
- cursor_timer.expires = jiffies + HZ / 50;
+ cursor_timer.expires = jiffies + HZ / 5;
cursor_timer.data = (unsigned long ) info;
add_timer(&cursor_timer);
}
@@ -944,6 +939,8 @@
if (!info->fbops->fb_blank && console_blanked)
return;
+ if (info->state != FBINFO_STATE_RUNNING)
+ return;
if (!height || !width)
return;
@@ -968,6 +965,8 @@
if (!info->fbops->fb_blank && console_blanked)
return;
+ if (info->state != FBINFO_STATE_RUNNING)
+ return;
if (vt_cons[vc->vc_num]->vc_mode != KD_TEXT)
return;
@@ -983,6 +982,8 @@
if (!info->fbops->fb_blank && console_blanked)
return;
+ if (info->state != FBINFO_STATE_RUNNING)
+ return;
if (vt_cons[vc->vc_num]->vc_mode != KD_TEXT)
return;
@@ -2265,6 +2266,39 @@
return 0;
}
+static void fbcon_suspended(struct fb_info *info)
+{
+ /* Clear cursor, restore saved data */
+ info->cursor.enable = 0;
+ info->fbops->fb_cursor(info, &info->cursor);
+}
+
+static void fbcon_resumed(struct fb_info *info)
+{
+ struct vc_data *vc;
+
+ if (info->currcon < 0)
+ return;
+ vc = vc_cons[info->currcon].d;
+
+ update_screen(vc->vc_num);
+}
+static int fbcon_event_notify(struct notifier_block *self,
+ unsigned long action, void *data)
+{
+ struct fb_info *info = (struct fb_info *) data;
+
+ switch(action) {
+ case FB_EVENT_SUSPEND:
+ fbcon_suspended(info);
+ break;
+ case FB_EVENT_RESUME:
+ fbcon_resumed(info);
+ break;
+ }
+ return 0;
+}
+
/*
* The console `switch' structure for the frame buffer based console
*/
@@ -2291,16 +2325,35 @@
.con_resize = fbcon_resize,
};
+static struct notifier_block fbcon_event_notifer = {
+ .notifier_call = fbcon_event_notify,
+};
+
+static int fbcon_event_notifier_registered;
+
int __init fb_console_init(void)
{
if (!num_registered_fb)
return -ENODEV;
take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default);
+ acquire_console_sem();
+ if (!fbcon_event_notifier_registered) {
+ fb_register_client(&fbcon_event_notifer);
+ fbcon_event_notifier_registered = 1;
+ }
+ release_console_sem();
+
return 0;
}
void __exit fb_console_exit(void)
{
+ acquire_console_sem();
+ if (fbcon_event_notifier_registered) {
+ fb_unregister_client(&fbcon_event_notifer);
+ fbcon_event_notifier_registered = 0;
+ }
+ release_console_sem();
give_up_console(&fb_con);
}
diff -urN linux-2.6.3-rc3/drivers/video/fbmem.c linux-2.6.3-rc4/drivers/video/fbmem.c
--- linux-2.6.3-rc3/drivers/video/fbmem.c 2004-02-16 19:49:12.000000000 -0800
+++ linux-2.6.3-rc4/drivers/video/fbmem.c 2004-02-16 19:49:21.000000000 -0800
@@ -27,6 +27,7 @@
#include
#include
#include
+#include
#ifdef CONFIG_KMOD
#include
#endif
@@ -102,6 +103,8 @@
extern int matroxfb_init(void);
extern int matroxfb_setup(char*);
extern int hpfb_init(void);
+extern int platinumfb_init(void);
+extern int platinumfb_setup(char*);
extern int control_init(void);
extern int control_setup(char*);
extern int platinum_init(void);
@@ -135,6 +138,8 @@
extern int tx3912fb_setup(char*);
extern int radeonfb_init(void);
extern int radeonfb_setup(char*);
+extern int radeonfb_old_init(void);
+extern int radeonfb_old_setup(char*);
extern int e1355fb_init(void);
extern int e1355fb_setup(char*);
extern int pvr2fb_init(void);
@@ -222,11 +227,14 @@
#ifdef CONFIG_FB_RADEON
{ "radeonfb", radeonfb_init, radeonfb_setup },
#endif
+#ifdef CONFIG_FB_RADEON_OLD
+ { "radeonfb_old", radeonfb_old_init, radeonfb_old_setup },
+#endif
#ifdef CONFIG_FB_CONTROL
{ "controlfb", control_init, control_setup },
#endif
#ifdef CONFIG_FB_PLATINUM
- { "platinumfb", platinum_init, platinum_setup },
+ { "platinumfb", platinumfb_init, platinumfb_setup },
#endif
#ifdef CONFIG_FB_VALKYRIE
{ "valkyriefb", valkyriefb_init, valkyriefb_setup },
@@ -395,6 +403,7 @@
static initcall_t pref_init_funcs[FB_MAX];
static int num_pref_init_funcs __initdata = 0;
+static struct notifier_block *fb_notifier_list;
struct fb_info *registered_fb[FB_MAX];
int num_registered_fb;
@@ -463,23 +472,32 @@
*/
u32 fb_get_buffer_offset(struct fb_info *info, u32 size)
{
- u32 align = info->pixmap.buf_align - 1;
- u32 offset, count = 1000;
+ struct fb_pixmap *buf = &info->pixmap;
+ u32 align = buf->buf_align - 1, offset;
- spin_lock(&info->pixmap.lock);
- offset = info->pixmap.offset + align;
+ /* If IO mapped, we need to sync before access, no sharing of
+ * the pixmap is done
+ */
+ if (buf->flags & FB_PIXMAP_IO) {
+ if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
+ info->fbops->fb_sync(info);
+ return 0;
+ }
+
+ /* See if we fit in the remaining pixmap space */
+ offset = buf->offset + align;
offset &= ~align;
- if (offset + size > info->pixmap.size) {
- while (atomic_read(&info->pixmap.count) && count--);
- if (info->fbops->fb_sync &&
- info->pixmap.flags & FB_PIXMAP_SYNC)
+ if (offset + size > buf->size) {
+ /* We do not fit. In order to be able to re-use the buffer,
+ * we must ensure no asynchronous DMA'ing or whatever operation
+ * is in progress, we sync for that.
+ */
+ if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
info->fbops->fb_sync(info);
offset = 0;
}
- info->pixmap.offset = offset + size;
- atomic_inc(&info->pixmap.count);
- smp_mb__after_atomic_inc();
- spin_unlock(&info->pixmap.lock);
+ buf->offset = offset + size;
+
return offset;
}
@@ -685,8 +703,8 @@
struct fb_image image;
int x;
- /* Return if the frame buffer is not mapped */
- if (fb_logo.logo == NULL)
+ /* Return if the frame buffer is not mapped or suspended */
+ if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING)
return 0;
image.depth = fb_logo.depth;
@@ -732,8 +750,6 @@
x <= info->var.xres-fb_logo.logo->width; x += (fb_logo.logo->width + 8)) {
image.dx = x;
info->fbops->fb_imageblit(info, &image);
- //atomic_dec(&info->pixmap.count);
- //smp_mb__after_atomic_dec();
}
if (palette != NULL)
@@ -780,6 +796,9 @@
if (!info || ! info->screen_base)
return -ENODEV;
+ if (info->state != FBINFO_STATE_RUNNING)
+ return -EPERM;
+
if (info->fbops->fb_read)
return info->fbops->fb_read(file, buf, count, ppos);
@@ -815,6 +834,9 @@
if (!info || !info->screen_base)
return -ENODEV;
+ if (info->state != FBINFO_STATE_RUNNING)
+ return -EPERM;
+
if (info->fbops->fb_write)
return info->fbops->fb_write(file, buf, count, ppos);
@@ -941,6 +963,8 @@
fb_pan_display(info, &info->var);
fb_set_cmap(&info->cmap, 1, info);
+
+ notifier_call_chain(&fb_notifier_list, FB_EVENT_MODE_CHANGE, info);
}
}
return 0;
@@ -979,7 +1003,7 @@
struct fb_con2fbmap con2fb;
#endif
struct fb_cmap cmap;
- int i;
+ int i, rc;
if (!fb)
return -ENODEV;
@@ -990,7 +1014,9 @@
case FBIOPUT_VSCREENINFO:
if (copy_from_user(&var, (void *) arg, sizeof(var)))
return -EFAULT;
+ acquire_console_sem();
i = fb_set_var(info, &var);
+ release_console_sem();
if (i) return i;
if (copy_to_user((void *) arg, &var, sizeof(var)))
return -EFAULT;
@@ -1009,13 +1035,19 @@
case FBIOPAN_DISPLAY:
if (copy_from_user(&var, (void *) arg, sizeof(var)))
return -EFAULT;
- if ((i = fb_pan_display(info, &var)))
+ acquire_console_sem();
+ i = fb_pan_display(info, &var);
+ release_console_sem();
+ if (i)
return i;
if (copy_to_user((void *) arg, &var, sizeof(var)))
return -EFAULT;
return 0;
case FBIO_CURSOR:
- return (fb_cursor(info, (struct fb_cursor *) arg));
+ acquire_console_sem();
+ rc = fb_cursor(info, (struct fb_cursor *) arg);
+ release_console_sem();
+ return rc;
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
case FBIOGET_CON2FBMAP:
if (copy_from_user(&con2fb, (void *)arg, sizeof(con2fb)))
@@ -1045,7 +1077,10 @@
return 0;
#endif /* CONFIG_FRAMEBUFFER_CONSOLE */
case FBIOBLANK:
- return fb_blank(info, arg);
+ acquire_console_sem();
+ i = fb_blank(info, arg);
+ release_console_sem();
+ return i;
default:
if (fb->fb_ioctl == NULL)
return -EINVAL;
@@ -1242,7 +1277,6 @@
fb_info->pixmap.outbuf = sys_outbuf;
if (fb_info->pixmap.inbuf == NULL)
fb_info->pixmap.inbuf = sys_inbuf;
- spin_lock_init(&fb_info->pixmap.lock);
registered_fb[i] = fb_info;
@@ -1279,8 +1313,42 @@
return 0;
}
+/**
+ * fb_register_client - register a client notifier
+ * @nb: notifier block to callback on events
+ */
+int fb_register_client(struct notifier_block *nb)
+{
+ return notifier_chain_register(&fb_notifier_list, nb);
+}
+
+/**
+ * fb_unregister_client - unregister a client notifier
+ * @nb: notifier block to callback on events
+ */
+int fb_unregister_client(struct notifier_block *nb)
+{
+ return notifier_chain_unregister(&fb_notifier_list, nb);
+}
+
+/**
+ * fb_set_suspend - low level driver signals suspend
+ * @info: framebuffer affected
+ * @state: 0 = resuming, !=0 = suspending
+ *
+ * This is meant to be used by low level drivers to
+ * signal suspend/resume to the core & clients.
+ * It must be called with the console semaphore held
+ */
void fb_set_suspend(struct fb_info *info, int state)
{
+ if (state) {
+ notifier_call_chain(&fb_notifier_list, FB_EVENT_SUSPEND, info);
+ info->state = FBINFO_STATE_SUSPENDED;
+ } else {
+ info->state = FBINFO_STATE_RUNNING;
+ notifier_call_chain(&fb_notifier_list, FB_EVENT_RESUME, info);
+ }
}
/**
@@ -1397,5 +1465,7 @@
EXPORT_SYMBOL(move_buf_unaligned);
EXPORT_SYMBOL(move_buf_aligned);
EXPORT_SYMBOL(fb_set_suspend);
+EXPORT_SYMBOL(fb_register_client);
+EXPORT_SYMBOL(fb_unregister_client);
MODULE_LICENSE("GPL");
diff -urN linux-2.6.3-rc3/drivers/video/platinumfb.c linux-2.6.3-rc4/drivers/video/platinumfb.c
--- linux-2.6.3-rc3/drivers/video/platinumfb.c 2004-02-03 19:43:43.000000000 -0800
+++ linux-2.6.3-rc4/drivers/video/platinumfb.c 2004-02-16 19:49:21.000000000 -0800
@@ -43,16 +43,13 @@
static int default_vmode = VMODE_NVRAM;
static int default_cmode = CMODE_NVRAM;
-struct fb_par_platinum {
- int vmode, cmode;
- int xres, yres;
- int vxres, vyres;
- int xoffset, yoffset;
-};
-
struct fb_info_platinum {
- struct fb_info info;
- struct fb_par_platinum par;
+ struct fb_info *info;
+
+ int vmode, cmode;
+ int xres, yres;
+ int vxres, vyres;
+ int xoffset, yoffset;
struct {
__u8 red, green, blue;
@@ -89,23 +86,19 @@
*/
static inline int platinum_vram_reqd(int video_mode, int color_mode);
-static int read_platinum_sense(struct fb_info_platinum *info);
-static void set_platinum_clock(struct fb_info_platinum *info);
-static void platinum_set_hardware(struct fb_info_platinum *info,
- const struct fb_par_platinum *par);
-static int platinum_par_to_var(struct fb_var_screeninfo *var,
- const struct fb_par_platinum *par,
- const struct fb_info_platinum *info);
-static int platinum_var_to_par(const struct fb_var_screeninfo *var,
- struct fb_par_platinum *par,
- const struct fb_info_platinum *info);
+static int read_platinum_sense(struct fb_info_platinum *pinfo);
+static void set_platinum_clock(struct fb_info_platinum *pinfo);
+static void platinum_set_hardware(struct fb_info_platinum *pinfo);
+static int platinum_var_to_par(struct fb_var_screeninfo *var,
+ struct fb_info_platinum *pinfo,
+ int check_only);
/*
* Interface used by the world
*/
-int platinum_init(void);
-int platinum_setup(char*);
+int platinumfb_init(void);
+int platinumfb_setup(char*);
static struct fb_ops platinumfb_ops = {
.owner = THIS_MODULE,
@@ -124,16 +117,7 @@
*/
static int platinumfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info)
{
- struct fb_info_platinum *p = (struct fb_info_platinum *) info;
- struct fb_par_platinum par;
- int err;
-
- err = platinum_var_to_par(var, &par, p);
- if (err)
- return err;
- platinum_par_to_var(var, &par, p);
-
- return 0;
+ return platinum_var_to_par(var, info->par, 1);
}
/*
@@ -141,27 +125,28 @@
*/
static int platinumfb_set_par (struct fb_info *info)
{
- struct fb_info_platinum *p = (struct fb_info_platinum *) info;
+ struct fb_info_platinum *pinfo = info->par;
struct platinum_regvals *init;
- struct fb_par_platinum par;
- int err;
+ int err, offset = 0x20;
- if((err = platinum_var_to_par(&info->var, &par, p))) {
+ if((err = platinum_var_to_par(&info->var, pinfo, 0))) {
printk (KERN_ERR "platinumfb_set_par: error calling"
" platinum_var_to_par: %d.\n", err);
return err;
}
- platinum_set_hardware(p, &par);
+ platinum_set_hardware(pinfo);
- init = platinum_reg_init[p->par.vmode-1];
+ init = platinum_reg_init[pinfo->vmode-1];
- info->screen_base = (char *) p->frame_buffer + init->fb_offset + 0x20;
- info->fix.smem_start = (p->frame_buffer_phys) + init->fb_offset + 0x20;
- info->fix.visual = (p->par.cmode == CMODE_8) ?
+ if (pinfo->vmode == 13 && pinfo->cmode > 0)
+ offset = 0x10;
+ info->screen_base = (char *) pinfo->frame_buffer + init->fb_offset + offset;
+ info->fix.smem_start = (pinfo->frame_buffer_phys) + init->fb_offset + offset;
+ info->fix.visual = (pinfo->cmode == CMODE_8) ?
FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
- info->fix.line_length = vmode_attrs[p->par.vmode-1].hres * (1<par.cmode) + 0x20;
-
+ info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<cmode) + offset;
+ printk("line_length: %x\n", info->fix.line_length);
return 0;
}
@@ -198,8 +183,8 @@
static int platinumfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
- struct fb_info_platinum *p = (struct fb_info_platinum *) info;
- volatile struct cmap_regs *cmap_regs = p->cmap_regs;
+ struct fb_info_platinum *pinfo = info->par;
+ volatile struct cmap_regs *cmap_regs = pinfo->cmap_regs;
if (regno > 255)
return 1;
@@ -208,9 +193,9 @@
green >>= 8;
blue >>= 8;
- p->palette[regno].red = red;
- p->palette[regno].green = green;
- p->palette[regno].blue = blue;
+ pinfo->palette[regno].red = red;
+ pinfo->palette[regno].green = green;
+ pinfo->palette[regno].blue = blue;
out_8(&cmap_regs->addr, regno); /* tell clut what addr to fill */
out_8(&cmap_regs->lut, red); /* send one color channel at */
@@ -220,7 +205,7 @@
if (regno < 16) {
int i;
u32 *pal = info->pseudo_palette;
- switch (p->par.cmode) {
+ switch (pinfo->cmode) {
case CMODE_16:
pal[regno] = (regno << 10) | (regno << 5) | regno;
break;
@@ -245,23 +230,23 @@
out_8(&cmap_regs->d2, (d)); \
}
-static void set_platinum_clock(struct fb_info_platinum *info)
+static void set_platinum_clock(struct fb_info_platinum *pinfo)
{
- volatile struct cmap_regs *cmap_regs = info->cmap_regs;
+ volatile struct cmap_regs *cmap_regs = pinfo->cmap_regs;
struct platinum_regvals *init;
- init = platinum_reg_init[info->par.vmode-1];
+ init = platinum_reg_init[pinfo->vmode-1];
STORE_D2(6, 0xc6);
out_8(&cmap_regs->addr,3+32);
if (in_8(&cmap_regs->d2) == 2) {
- STORE_D2(7, init->clock_params[info->clktype][0]);
- STORE_D2(8, init->clock_params[info->clktype][1]);
+ STORE_D2(7, init->clock_params[pinfo->clktype][0]);
+ STORE_D2(8, init->clock_params[pinfo->clktype][1]);
STORE_D2(3, 3);
} else {
- STORE_D2(4, init->clock_params[info->clktype][0]);
- STORE_D2(5, init->clock_params[info->clktype][1]);
+ STORE_D2(4, init->clock_params[pinfo->clktype][0]);
+ STORE_D2(5, init->clock_params[pinfo->clktype][1]);
STORE_D2(3, 2);
}
@@ -272,18 +257,16 @@
/* Now how about actually saying, Make it so! */
/* Some things in here probably don't need to be done each time. */
-static void platinum_set_hardware(struct fb_info_platinum *info, const struct fb_par_platinum *par)
+static void platinum_set_hardware(struct fb_info_platinum *pinfo)
{
- volatile struct platinum_regs *platinum_regs = info->platinum_regs;
- volatile struct cmap_regs *cmap_regs = info->cmap_regs;
+ volatile struct platinum_regs *platinum_regs = pinfo->platinum_regs;
+ volatile struct cmap_regs *cmap_regs = pinfo->cmap_regs;
struct platinum_regvals *init;
int i;
int vmode, cmode;
- info->par = *par;
-
- vmode = par->vmode;
- cmode = par->cmode;
+ vmode = pinfo->vmode;
+ cmode = pinfo->cmode;
init = platinum_reg_init[vmode - 1];
@@ -293,15 +276,15 @@
for (i = 0; i < 26; ++i)
out_be32(&platinum_regs->reg[i+32].r, init->regs[i]);
- out_be32(&platinum_regs->reg[26+32].r, (info->total_vram == 0x100000 ?
+ out_be32(&platinum_regs->reg[26+32].r, (pinfo->total_vram == 0x100000 ?
init->offset[cmode] + 4 - cmode :
init->offset[cmode]));
- out_be32(&platinum_regs->reg[16].r, (unsigned) info->frame_buffer_phys+init->fb_offset+0x10);
+ out_be32(&platinum_regs->reg[16].r, (unsigned) pinfo->frame_buffer_phys+init->fb_offset+0x10);
out_be32(&platinum_regs->reg[18].r, init->pitch[cmode]);
- out_be32(&platinum_regs->reg[19].r, (info->total_vram == 0x100000 ?
+ out_be32(&platinum_regs->reg[19].r, (pinfo->total_vram == 0x100000 ?
init->mode[cmode+1] :
init->mode[cmode]));
- out_be32(&platinum_regs->reg[20].r, (info->total_vram == 0x100000 ? 0x11 : 0x1011));
+ out_be32(&platinum_regs->reg[20].r, (pinfo->total_vram == 0x100000 ? 0x11 : 0x1011));
out_be32(&platinum_regs->reg[21].r, 0x100);
out_be32(&platinum_regs->reg[22].r, 1);
out_be32(&platinum_regs->reg[23].r, 1);
@@ -309,13 +292,13 @@
out_be32(&platinum_regs->reg[27].r, 0x235);
/* out_be32(&platinum_regs->reg[27].r, 0x2aa); */
- STORE_D2(0, (info->total_vram == 0x100000 ?
+ STORE_D2(0, (pinfo->total_vram == 0x100000 ?
init->dacula_ctrl[cmode] & 0xf :
init->dacula_ctrl[cmode]));
STORE_D2(1, 4);
STORE_D2(2, 0);
- set_platinum_clock(info);
+ set_platinum_clock(pinfo);
out_be32(&platinum_regs->reg[24].r, 0); /* turn display on */
}
@@ -323,24 +306,23 @@
/*
* Set misc info vars for this driver
*/
-static void __devinit platinum_init_info(struct fb_info *info, struct fb_info_platinum *p)
+static void __devinit platinum_init_info(struct fb_info *info, struct fb_info_platinum *pinfo)
{
/* Fill fb_info */
- info->par = &p->par;
info->fbops = &platinumfb_ops;
- info->pseudo_palette = p->pseudo_palette;
+ info->pseudo_palette = pinfo->pseudo_palette;
info->flags = FBINFO_FLAG_DEFAULT;
- info->screen_base = (char *) p->frame_buffer + 0x20;
+ info->screen_base = (char *) pinfo->frame_buffer + 0x20;
fb_alloc_cmap(&info->cmap, 256, 0);
/* Fill fix common fields */
strcpy(info->fix.id, "platinum");
- info->fix.mmio_start = p->platinum_regs_phys;
+ info->fix.mmio_start = pinfo->platinum_regs_phys;
info->fix.mmio_len = 0x1000;
info->fix.type = FB_TYPE_PACKED_PIXELS;
- info->fix.smem_start = p->frame_buffer_phys + 0x20; /* will be updated later */
- info->fix.smem_len = p->total_vram - 0x20;
+ info->fix.smem_start = pinfo->frame_buffer_phys + 0x20; /* will be updated later */
+ info->fix.smem_len = pinfo->total_vram - 0x20;
info->fix.ywrapstep = 0;
info->fix.xpanstep = 0;
info->fix.ypanstep = 0;
@@ -349,13 +331,14 @@
}
-static int __devinit platinum_init_fb(struct fb_info_platinum *p)
+static int __devinit platinum_init_fb(struct fb_info *info)
{
+ struct fb_info_platinum *pinfo = info->par;
struct fb_var_screeninfo var;
int sense, rc;
- sense = read_platinum_sense(p);
- printk(KERN_INFO "Monitor sense value = 0x%x, ", sense);
+ sense = read_platinum_sense(pinfo);
+ printk(KERN_INFO "platinumfb: Monitor sense value = 0x%x, ", sense);
if (default_vmode == VMODE_NVRAM) {
default_vmode = nvram_read_byte(NV_VMODE);
@@ -375,10 +358,11 @@
/*
* Reduce the pixel size if we don't have enough VRAM.
*/
- while(default_cmode > CMODE_8 && platinum_vram_reqd(default_vmode, default_cmode) > p->total_vram)
+ while(default_cmode > CMODE_8 &&
+ platinum_vram_reqd(default_vmode, default_cmode) > pinfo->total_vram)
default_cmode--;
- printk("using video mode %d and color mode %d.\n", default_vmode, default_cmode);
+ printk("platinumfb: Using video mode %d and color mode %d.\n", default_vmode, default_cmode);
/* Setup default var */
if (mac_vmode_to_var(default_vmode, default_cmode, &var) < 0) {
@@ -394,22 +378,21 @@
}
/* Initialize info structure */
- platinum_init_info(&p->info, p);
+ platinum_init_info(info, pinfo);
/* Apply default var */
- p->info.var = var;
+ info->var = var;
var.activate = FB_ACTIVATE_NOW;
- rc = fb_set_var(&p->info, &var);
+ rc = fb_set_var(info, &var);
if (rc && (default_vmode != VMODE_640_480_60 || default_cmode != CMODE_8))
goto try_again;
/* Register with fbdev layer */
- rc = register_framebuffer(&p->info);
+ rc = register_framebuffer(info);
if (rc < 0)
return rc;
- printk(KERN_INFO "fb%d: platinum frame buffer device\n",
- p->info.node);
+ printk(KERN_INFO "fb%d: Apple Platinum frame buffer device\n", info->node);
return 0;
}
@@ -445,12 +428,17 @@
return sense;
}
-/* This routine takes a user-supplied var, and picks the best vmode/cmode from it. */
-static int platinum_var_to_par(const struct fb_var_screeninfo *var,
- struct fb_par_platinum *par,
- const struct fb_info_platinum *info)
+/*
+ * This routine takes a user-supplied var, and picks the best vmode/cmode from it.
+ * It also updates the var structure to the actual mode data obtained
+ */
+static int platinum_var_to_par(struct fb_var_screeninfo *var,
+ struct fb_info_platinum *pinfo,
+ int check_only)
{
- if(mac_var_to_vmode(var, &par->vmode, &par->cmode) != 0) {
+ int vmode, cmode;
+
+ if (mac_var_to_vmode(var, &vmode, &cmode) != 0) {
printk(KERN_ERR "platinum_var_to_par: mac_var_to_vmode unsuccessful.\n");
printk(KERN_ERR "platinum_var_to_par: var->xres = %d\n", var->xres);
printk(KERN_ERR "platinum_var_to_par: var->yres = %d\n", var->yres);
@@ -462,37 +450,39 @@
return -EINVAL;
}
- if(!platinum_reg_init[par->vmode-1]) {
- printk(KERN_ERR "platinum_var_to_par, vmode %d not valid.\n", par->vmode);
+ if (!platinum_reg_init[vmode-1]) {
+ printk(KERN_ERR "platinum_var_to_par, vmode %d not valid.\n", vmode);
return -EINVAL;
}
- if (platinum_vram_reqd(par->vmode, par->cmode) > info->total_vram) {
- printk(KERN_ERR "platinum_var_to_par, not enough ram for vmode %d, cmode %d.\n", par->vmode, par->cmode);
+ if (platinum_vram_reqd(vmode, cmode) > pinfo->total_vram) {
+ printk(KERN_ERR "platinum_var_to_par, not enough ram for vmode %d, cmode %d.\n", vmode, cmode);
return -EINVAL;
}
- par->xres = vmode_attrs[par->vmode-1].hres;
- par->yres = vmode_attrs[par->vmode-1].vres;
- par->xoffset = 0;
- par->yoffset = 0;
- par->vxres = par->xres;
- par->vyres = par->yres;
+ if (mac_vmode_to_var(vmode, cmode, var))
+ return -EINVAL;
+
+ if (check_only)
+ return 0;
+
+ pinfo->vmode = vmode;
+ pinfo->cmode = cmode;
+ pinfo->xres = vmode_attrs[vmode-1].hres;
+ pinfo->yres = vmode_attrs[vmode-1].vres;
+ pinfo->xoffset = 0;
+ pinfo->yoffset = 0;
+ pinfo->vxres = pinfo->xres;
+ pinfo->vyres = pinfo->yres;
return 0;
}
-static int platinum_par_to_var(struct fb_var_screeninfo *var,
- const struct fb_par_platinum *par,
- const struct fb_info_platinum *info)
-{
- return mac_vmode_to_var(par->vmode, par->cmode, var);
-}
/*
* Parse user speficied options (`video=platinumfb:')
*/
-int __init platinum_setup(char *options)
+int __init platinumfb_setup(char *options)
{
char *this_opt;
@@ -536,7 +526,8 @@
static int __devinit platinumfb_probe(struct of_device* odev, const struct of_match *match)
{
struct device_node *dp = odev->node;
- struct fb_info_platinum *info;
+ struct fb_info *info;
+ struct fb_info_platinum *pinfo;
unsigned long addr, size;
volatile __u8 *fbuffer;
int i, bank0, bank1, bank2, bank3, rc;
@@ -545,11 +536,12 @@
printk(KERN_ERR "expecting 2 address for platinum (got %d)", dp->n_addrs);
return -ENXIO;
}
+ printk(KERN_INFO "platinumfb: Found Apple Platinum video hardware\n");
- info = kmalloc(sizeof(*info), GFP_ATOMIC);
- if (info == 0)
+ info = framebuffer_alloc(sizeof(*pinfo), &odev->dev);
+ if (info == NULL)
return -ENOMEM;
- memset(info, 0, sizeof(*info));
+ pinfo = info->par;
/* Map in frame buffer and registers */
for (i = 0; i < dp->n_addrs; ++i) {
@@ -557,31 +549,31 @@
size = dp->addrs[i].size;
/* Let's assume we can request either all or nothing */
if (!request_mem_region(addr, size, "platinumfb")) {
- kfree(info);
+ framebuffer_release(info);
return -ENXIO;
}
if (size >= 0x400000) {
/* frame buffer - map only 4MB */
- info->frame_buffer_phys = addr;
- info->frame_buffer = __ioremap(addr, 0x400000, _PAGE_WRITETHRU);
- info->base_frame_buffer = info->frame_buffer;
+ pinfo->frame_buffer_phys = addr;
+ pinfo->frame_buffer = __ioremap(addr, 0x400000, _PAGE_WRITETHRU);
+ pinfo->base_frame_buffer = pinfo->frame_buffer;
} else {
/* registers */
- info->platinum_regs_phys = addr;
- info->platinum_regs = ioremap(addr, size);
+ pinfo->platinum_regs_phys = addr;
+ pinfo->platinum_regs = ioremap(addr, size);
}
}
- info->cmap_regs_phys = 0xf301b000; /* XXX not in prom? */
- request_mem_region(info->cmap_regs_phys, 0x1000, "platinumfb cmap");
- info->cmap_regs = ioremap(info->cmap_regs_phys, 0x1000);
+ pinfo->cmap_regs_phys = 0xf301b000; /* XXX not in prom? */
+ request_mem_region(pinfo->cmap_regs_phys, 0x1000, "platinumfb cmap");
+ pinfo->cmap_regs = ioremap(pinfo->cmap_regs_phys, 0x1000);
/* Grok total video ram */
- out_be32(&info->platinum_regs->reg[16].r, (unsigned)info->frame_buffer_phys);
- out_be32(&info->platinum_regs->reg[20].r, 0x1011); /* select max vram */
- out_be32(&info->platinum_regs->reg[24].r, 0); /* switch in vram */
+ out_be32(&pinfo->platinum_regs->reg[16].r, (unsigned)pinfo->frame_buffer_phys);
+ out_be32(&pinfo->platinum_regs->reg[20].r, 0x1011); /* select max vram */
+ out_be32(&pinfo->platinum_regs->reg[24].r, 0); /* switch in vram */
- fbuffer = info->base_frame_buffer;
+ fbuffer = pinfo->base_frame_buffer;
fbuffer[0x100000] = 0x34;
fbuffer[0x100008] = 0x0;
invalidate_cache(&fbuffer[0x100000]);
@@ -595,24 +587,27 @@
bank1 = fbuffer[0x100000] == 0x34;
bank2 = fbuffer[0x200000] == 0x56;
bank3 = fbuffer[0x300000] == 0x78;
- info->total_vram = (bank0 + bank1 + bank2 + bank3) * 0x100000;
- printk(KERN_INFO "Total VRAM = %dMB %d%d%d%d\n", (int) (info->total_vram / 1024 / 1024), bank3, bank2, bank1, bank0);
+ pinfo->total_vram = (bank0 + bank1 + bank2 + bank3) * 0x100000;
+ printk(KERN_INFO "platinumfb: Total VRAM = %dMB (%d%d%d%d)\n", (int) (pinfo->total_vram / 1024 / 1024),
+ bank3, bank2, bank1, bank0);
/*
* Try to determine whether we have an old or a new DACula.
*/
- out_8(&info->cmap_regs->addr, 0x40);
- info->dactype = in_8(&info->cmap_regs->d2);
- switch (info->dactype) {
+ out_8(&pinfo->cmap_regs->addr, 0x40);
+ pinfo->dactype = in_8(&pinfo->cmap_regs->d2);
+ switch (pinfo->dactype) {
case 0x3c:
- info->clktype = 1;
+ pinfo->clktype = 1;
+ printk(KERN_INFO "platinumfb: DACula type 0x3c\n");
break;
case 0x84:
- info->clktype = 0;
+ pinfo->clktype = 0;
+ printk(KERN_INFO "platinumfb: DACula type 0x84\n");
break;
default:
- info->clktype = 0;
- printk(KERN_INFO "Unknown DACula type: %x\n", info->dactype);
+ pinfo->clktype = 0;
+ printk(KERN_INFO "platinumfb: Unknown DACula type: %x\n", pinfo->dactype);
break;
}
dev_set_drvdata(&odev->dev, info);
@@ -620,7 +615,7 @@
rc = platinum_init_fb(info);
if (rc != 0) {
dev_set_drvdata(&odev->dev, NULL);
- kfree(info);
+ framebuffer_release(info);
}
return rc;
@@ -628,15 +623,13 @@
static int __devexit platinumfb_remove(struct of_device* odev)
{
- struct fb_info_platinum *pinfo = dev_get_drvdata(&odev->dev);
+ struct fb_info *info = dev_get_drvdata(&odev->dev);
+ struct fb_info_platinum *pinfo = info->par;
struct device_node *dp = odev->node;
unsigned long addr, size;
int i;
- if (!pinfo)
- return 0;
-
- unregister_framebuffer (&pinfo->info);
+ unregister_framebuffer (info);
/* Unmap frame buffer and registers */
for (i = 0; i < dp->n_addrs; ++i) {
@@ -649,7 +642,7 @@
release_mem_region(pinfo->cmap_regs_phys, 0x1000);
iounmap((void *)pinfo->cmap_regs);
- kfree(pinfo);
+ framebuffer_release(info);
return 0;
}
@@ -672,14 +665,14 @@
.remove = platinumfb_remove,
};
-int __init platinum_init(void)
+int __init platinumfb_init(void)
{
of_register_driver(&platinum_driver);
return 0;
}
-void __exit platinum_exit(void)
+void __exit platinumfb_exit(void)
{
of_unregister_driver(&platinum_driver);
}
@@ -688,6 +681,6 @@
MODULE_DESCRIPTION("framebuffer driver for Apple Platinum video");
#ifdef MODULE
-module_init(platinum_init);
-module_exit(platinum_exit);
+module_init(platinumfb_init);
+module_exit(platinumfb_exit);
#endif
diff -urN linux-2.6.3-rc3/drivers/video/radeonfb.c linux-2.6.3-rc4/drivers/video/radeonfb.c
--- linux-2.6.3-rc3/drivers/video/radeonfb.c 2004-02-16 19:49:12.000000000 -0800
+++ linux-2.6.3-rc4/drivers/video/radeonfb.c 2004-02-16 19:49:21.000000000 -0800
@@ -234,7 +234,7 @@
/* these common regs are cleared before mode setting so they do not
* interfere with anything
*/
-reg_val common_regs[] = {
+static reg_val common_regs[] = {
{ OVR_CLR, 0 },
{ OVR_WID_LEFT_RIGHT, 0 },
{ OVR_WID_TOP_BOTTOM, 0 },
@@ -246,7 +246,7 @@
{ CAP0_TRIG_CNTL, 0 },
};
-reg_val common_regs_m6[] = {
+static reg_val common_regs_m6[] = {
{ OVR_CLR, 0 },
{ OVR_WID_LEFT_RIGHT, 0 },
{ OVR_WID_TOP_BOTTOM, 0 },
@@ -3134,19 +3134,19 @@
};
-int __init radeonfb_init (void)
+int __init radeonfb_old_init (void)
{
return pci_module_init (&radeonfb_driver);
}
-void __exit radeonfb_exit (void)
+void __exit radeonfb_old_exit (void)
{
pci_unregister_driver (&radeonfb_driver);
}
-int __init radeonfb_setup (char *options)
+int __init radeonfb_old_setup (char *options)
{
char *this_opt;
@@ -3174,8 +3174,8 @@
}
#ifdef MODULE
-module_init(radeonfb_init);
-module_exit(radeonfb_exit);
+module_init(radeonfb_old_init);
+module_exit(radeonfb_old_exit);
#endif
diff -urN linux-2.6.3-rc3/drivers/video/riva/fbdev.c linux-2.6.3-rc4/drivers/video/riva/fbdev.c
--- linux-2.6.3-rc3/drivers/video/riva/fbdev.c 2004-02-16 19:49:12.000000000 -0800
+++ linux-2.6.3-rc4/drivers/video/riva/fbdev.c 2004-02-16 19:49:21.000000000 -0800
@@ -1615,8 +1615,9 @@
}
#ifdef CONFIG_PPC_OF
-static int riva_get_EDID_OF(struct riva_par *par, struct pci_dev *pd)
+static int riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
{
+ struct riva_par *par = (struct riva_par *) info->par;
struct device_node *dp;
unsigned char *pedid = NULL;
diff -urN linux-2.6.3-rc3/drivers/video/softcursor.c linux-2.6.3-rc4/drivers/video/softcursor.c
--- linux-2.6.3-rc3/drivers/video/softcursor.c 2004-02-03 19:43:49.000000000 -0800
+++ linux-2.6.3-rc4/drivers/video/softcursor.c 2004-02-16 19:49:21.000000000 -0800
@@ -48,6 +48,9 @@
info->cursor.image.depth = cursor->image.depth;
}
+ if (info->state != FBINFO_STATE_RUNNING)
+ return 0;
+
s_pitch = (info->cursor.image.width + 7) >> 3;
dsize = s_pitch * info->cursor.image.height;
d_pitch = (s_pitch + scan_align) & ~scan_align;
@@ -74,8 +77,6 @@
info->cursor.image.data = dst;
info->fbops->fb_imageblit(info, &info->cursor.image);
- atomic_dec(&info->pixmap.count);
- smp_mb__after_atomic_dec();
return 0;
}
diff -urN linux-2.6.3-rc3/fs/devfs/base.c linux-2.6.3-rc4/fs/devfs/base.c
--- linux-2.6.3-rc3/fs/devfs/base.c 2004-02-03 19:43:15.000000000 -0800
+++ linux-2.6.3-rc4/fs/devfs/base.c 2004-02-16 19:49:21.000000000 -0800
@@ -2840,7 +2840,7 @@
int err;
if ( !(boot_options & OPTION_MOUNT) ) return;
- err = do_mount ("none", "/dev", "devfs", 0, "");
+ err = do_mount ("none", "/dev", "devfs", 0, NULL);
if (err == 0) printk (KERN_INFO "Mounted devfs on /dev\n");
else PRINTK ("(): unable to mount devfs, err: %d\n", err);
} /* End Function mount_devfs_fs */
diff -urN linux-2.6.3-rc3/fs/super.c linux-2.6.3-rc4/fs/super.c
--- linux-2.6.3-rc3/fs/super.c 2004-02-03 19:43:44.000000000 -0800
+++ linux-2.6.3-rc4/fs/super.c 2004-02-16 19:49:21.000000000 -0800
@@ -708,6 +708,7 @@
struct super_block *sb = ERR_PTR(-ENOMEM);
struct vfsmount *mnt;
int error;
+ char *secdata = NULL;
if (!type)
return ERR_PTR(-ENODEV);
@@ -715,11 +716,26 @@
mnt = alloc_vfsmnt(name);
if (!mnt)
goto out;
+
+ if (data) {
+ secdata = alloc_secdata();
+ if (!secdata) {
+ sb = ERR_PTR(-ENOMEM);
+ goto out_mnt;
+ }
+
+ error = security_sb_copy_data(fstype, data, secdata);
+ if (error) {
+ sb = ERR_PTR(error);
+ goto out_free_secdata;
+ }
+ }
+
sb = type->get_sb(type, flags, name, data);
if (IS_ERR(sb))
- goto out_mnt;
- error = security_sb_kern_mount(sb);
- if (error)
+ goto out_free_secdata;
+ error = security_sb_kern_mount(sb, secdata);
+ if (error)
goto out_sb;
mnt->mnt_sb = sb;
mnt->mnt_root = dget(sb->s_root);
@@ -732,6 +748,8 @@
up_write(&sb->s_umount);
deactivate_super(sb);
sb = ERR_PTR(error);
+out_free_secdata:
+ free_secdata(secdata);
out_mnt:
free_vfsmnt(mnt);
out:
diff -urN linux-2.6.3-rc3/include/linux/fb.h linux-2.6.3-rc4/include/linux/fb.h
--- linux-2.6.3-rc3/include/linux/fb.h 2004-02-16 19:49:12.000000000 -0800
+++ linux-2.6.3-rc4/include/linux/fb.h 2004-02-16 19:49:21.000000000 -0800
@@ -340,6 +340,24 @@
struct file;
/*
+ * Register/unregister for framebuffer events
+ */
+
+/* The resolution of the passed in fb_info about to change */
+#define FB_EVENT_MODE_CHANGE 0x01
+/* The display on this fb_info is beeing suspended, no access to the
+ * framebuffer is allowed any more after that call returns
+ */
+#define FB_EVENT_SUSPEND 0x02
+/* The display on this fb_info was resumed, you can restore the display
+ * if you own it
+ */
+#define FB_EVENT_RESUME 0x03
+
+extern int fb_register_client(struct notifier_block *nb);
+extern int fb_unregister_client(struct notifier_block *nb);
+
+/*
* Pixmap structure definition
*
* The purpose of this structure is to translate data
@@ -363,8 +381,6 @@
/* access methods */
void (*outbuf)(u8 *dst, u8 *addr, unsigned int size);
u8 (*inbuf) (u8 *addr);
- spinlock_t lock; /* spinlock */
- atomic_t count;
};
/*
@@ -449,6 +465,9 @@
struct vc_data *display_fg; /* Console visible on this display */
int currcon; /* Current VC. */
void *pseudo_palette; /* Fake palette of 16 colors */
+#define FBINFO_STATE_RUNNING 0
+#define FBINFO_STATE_SUSPENDED 1
+ u32 state; /* Hardware state i.e suspend */
/* From here on everything is device dependent */
void *par;
};
diff -urN linux-2.6.3-rc3/include/linux/fs.h linux-2.6.3-rc4/include/linux/fs.h
--- linux-2.6.3-rc3/include/linux/fs.h 2004-02-03 19:43:20.000000000 -0800
+++ linux-2.6.3-rc4/include/linux/fs.h 2004-02-16 19:49:21.000000000 -0800
@@ -1421,5 +1421,25 @@
/* kernel/fork.c */
extern int unshare_files(void);
+#ifdef CONFIG_SECURITY
+static inline char *alloc_secdata(void)
+{
+ return (char *)get_zeroed_page(GFP_KERNEL);
+}
+
+static inline void free_secdata(void *secdata)
+{
+ free_page((unsigned long)secdata);
+}
+#else
+static inline char *alloc_secdata(void)
+{
+ return (char *)1;
+}
+
+static inline void free_secdata(void *secdata)
+{ }
+#endif /* CONFIG_SECURITY */
+
#endif /* __KERNEL__ */
#endif /* _LINUX_FS_H */
diff -urN linux-2.6.3-rc3/include/linux/ide.h linux-2.6.3-rc4/include/linux/ide.h
--- linux-2.6.3-rc3/include/linux/ide.h 2004-02-16 19:49:12.000000000 -0800
+++ linux-2.6.3-rc4/include/linux/ide.h 2004-02-16 19:49:21.000000000 -0800
@@ -790,14 +790,10 @@
int (*ide_dma_end)(ide_drive_t *drive);
int (*ide_dma_check)(ide_drive_t *drive);
int (*ide_dma_on)(ide_drive_t *drive);
- int (*ide_dma_off)(ide_drive_t *drive);
int (*ide_dma_off_quietly)(ide_drive_t *drive);
int (*ide_dma_test_irq)(ide_drive_t *drive);
int (*ide_dma_host_on)(ide_drive_t *drive);
int (*ide_dma_host_off)(ide_drive_t *drive);
- int (*ide_dma_bad_drive)(ide_drive_t *drive);
- int (*ide_dma_good_drive)(ide_drive_t *drive);
- int (*ide_dma_count)(ide_drive_t *drive);
int (*ide_dma_verbose)(ide_drive_t *drive);
int (*ide_dma_lostirq)(ide_drive_t *drive);
int (*ide_dma_timeout)(ide_drive_t *drive);
@@ -929,14 +925,10 @@
int (*ide_dma_end)(ide_drive_t *drive);
int (*ide_dma_check)(ide_drive_t *drive);
int (*ide_dma_on)(ide_drive_t *drive);
- int (*ide_dma_off)(ide_drive_t *drive);
int (*ide_dma_off_quietly)(ide_drive_t *drive);
int (*ide_dma_test_irq)(ide_drive_t *drive);
int (*ide_dma_host_on)(ide_drive_t *drive);
int (*ide_dma_host_off)(ide_drive_t *drive);
- int (*ide_dma_bad_drive)(ide_drive_t *drive);
- int (*ide_dma_good_drive)(ide_drive_t *drive);
- int (*ide_dma_count)(ide_drive_t *drive);
int (*ide_dma_verbose)(ide_drive_t *drive);
int (*ide_dma_lostirq)(ide_drive_t *drive);
int (*ide_dma_timeout)(ide_drive_t *drive);
@@ -1600,6 +1592,7 @@
#ifdef CONFIG_BLK_DEV_IDEDMA
int __ide_dma_bad_drive(ide_drive_t *);
int __ide_dma_good_drive(ide_drive_t *);
+int __ide_dma_off(ide_drive_t *);
#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
extern int ide_build_sglist(ide_drive_t *, struct request *);
@@ -1613,7 +1606,6 @@
extern int __ide_dma_host_off(ide_drive_t *);
extern int __ide_dma_off_quietly(ide_drive_t *);
-extern int __ide_dma_off(ide_drive_t *);
extern int __ide_dma_host_on(ide_drive_t *);
extern int __ide_dma_on(ide_drive_t *);
extern int __ide_dma_check(ide_drive_t *);
@@ -1622,7 +1614,6 @@
extern int __ide_dma_begin(ide_drive_t *);
extern int __ide_dma_end(ide_drive_t *);
extern int __ide_dma_test_irq(ide_drive_t *);
-extern int __ide_dma_count(ide_drive_t *);
extern int __ide_dma_verbose(ide_drive_t *);
extern int __ide_dma_lostirq(ide_drive_t *);
extern int __ide_dma_timeout(ide_drive_t *);
diff -urN linux-2.6.3-rc3/include/linux/nfs_mount.h linux-2.6.3-rc4/include/linux/nfs_mount.h
--- linux-2.6.3-rc3/include/linux/nfs_mount.h 2004-02-03 19:43:06.000000000 -0800
+++ linux-2.6.3-rc4/include/linux/nfs_mount.h 2004-02-16 19:49:21.000000000 -0800
@@ -20,7 +20,8 @@
* mount-to-kernel version compatibility. Some of these aren't used yet
* but here they are anyway.
*/
-#define NFS_MOUNT_VERSION 5
+#define NFS_MOUNT_VERSION 6
+#define NFS_MAX_CONTEXT_LEN 256
struct nfs_mount_data {
int version; /* 1 */
@@ -41,6 +42,7 @@
unsigned int bsize; /* 3 */
struct nfs3_fh root; /* 4 */
int pseudoflavor; /* 5 */
+ char context[NFS_MAX_CONTEXT_LEN + 1]; /* 6 */
};
/* bits in the flags field */
diff -urN linux-2.6.3-rc3/include/linux/pci_ids.h linux-2.6.3-rc4/include/linux/pci_ids.h
--- linux-2.6.3-rc3/include/linux/pci_ids.h 2004-02-16 19:49:12.000000000 -0800
+++ linux-2.6.3-rc4/include/linux/pci_ids.h 2004-02-16 19:49:21.000000000 -0800
@@ -216,28 +216,37 @@
/* Rage128 GL */
#define PCI_DEVICE_ID_ATI_RAGE128_RE 0x5245
#define PCI_DEVICE_ID_ATI_RAGE128_RF 0x5246
-#define PCI_DEVICE_ID_ATI_RAGE128_RG 0x534b
-#define PCI_DEVICE_ID_ATI_RAGE128_RH 0x534c
-#define PCI_DEVICE_ID_ATI_RAGE128_RI 0x534d
+#define PCI_DEVICE_ID_ATI_RAGE128_RG 0x5247
/* Rage128 VR */
#define PCI_DEVICE_ID_ATI_RAGE128_RK 0x524b
#define PCI_DEVICE_ID_ATI_RAGE128_RL 0x524c
-#define PCI_DEVICE_ID_ATI_RAGE128_RM 0x5345
-#define PCI_DEVICE_ID_ATI_RAGE128_RN 0x5346
-#define PCI_DEVICE_ID_ATI_RAGE128_RO 0x5347
+#define PCI_DEVICE_ID_ATI_RAGE128_SE 0x5345
+#define PCI_DEVICE_ID_ATI_RAGE128_SF 0x5346
+#define PCI_DEVICE_ID_ATI_RAGE128_SG 0x5347
+#define PCI_DEVICE_ID_ATI_RAGE128_SH 0x5348
+#define PCI_DEVICE_ID_ATI_RAGE128_SK 0x534b
+#define PCI_DEVICE_ID_ATI_RAGE128_SL 0x534c
+#define PCI_DEVICE_ID_ATI_RAGE128_SM 0x534d
+#define PCI_DEVICE_ID_ATI_RAGE128_SN 0x534e
+/* Rage128 Ultra */
+#define PCI_DEVICE_ID_ATI_RAGE128_TF 0x5446
+#define PCI_DEVICE_ID_ATI_RAGE128_TL 0x544c
+#define PCI_DEVICE_ID_ATI_RAGE128_TR 0x5452
+#define PCI_DEVICE_ID_ATI_RAGE128_TS 0x5453
+#define PCI_DEVICE_ID_ATI_RAGE128_TT 0x5454
+#define PCI_DEVICE_ID_ATI_RAGE128_TU 0x5455
/* Rage128 M3 */
#define PCI_DEVICE_ID_ATI_RAGE128_LE 0x4c45
#define PCI_DEVICE_ID_ATI_RAGE128_LF 0x4c46
-/* Rage128 Pro Ultra */
-#define PCI_DEVICE_ID_ATI_RAGE128_U1 0x5446
-#define PCI_DEVICE_ID_ATI_RAGE128_U2 0x544C
-#define PCI_DEVICE_ID_ATI_RAGE128_U3 0x5452
+/* Rage128 M4 */
+#define PCI_DEVICE_ID_ATI_RAGE128_MF 0x4d46
+#define PCI_DEVICE_ID_ATI_RAGE128_ML 0x4d4c
/* Rage128 Pro GL */
-#define PCI_DEVICE_ID_ATI_Rage128_PA 0x5041
-#define PCI_DEVICE_ID_ATI_Rage128_PB 0x5042
-#define PCI_DEVICE_ID_ATI_Rage128_PC 0x5043
-#define PCI_DEVICE_ID_ATI_Rage128_PD 0x5044
-#define PCI_DEVICE_ID_ATI_Rage128_PE 0x5045
+#define PCI_DEVICE_ID_ATI_RAGE128_PA 0x5041
+#define PCI_DEVICE_ID_ATI_RAGE128_PB 0x5042
+#define PCI_DEVICE_ID_ATI_RAGE128_PC 0x5043
+#define PCI_DEVICE_ID_ATI_RAGE128_PD 0x5044
+#define PCI_DEVICE_ID_ATI_RAGE128_PE 0x5045
#define PCI_DEVICE_ID_ATI_RAGE128_PF 0x5046
/* Rage128 Pro VR */
#define PCI_DEVICE_ID_ATI_RAGE128_PG 0x5047
diff -urN linux-2.6.3-rc3/include/linux/security.h linux-2.6.3-rc4/include/linux/security.h
--- linux-2.6.3-rc3/include/linux/security.h 2004-02-03 19:44:05.000000000 -0800
+++ linux-2.6.3-rc4/include/linux/security.h 2004-02-16 19:49:21.000000000 -0800
@@ -171,6 +171,16 @@
* @flags contains the mount flags.
* @data contains the filesystem-specific data.
* Return 0 if permission is granted.
+ * @sb_copy_data:
+ * Allow mount option data to be copied prior to parsing by the filesystem,
+ * so that the security module can extract security-specific mount
+ * options cleanly (a filesystem may modify the data e.g. with strsep()).
+ * This also allows the original mount data to be stripped of security-
+ * specific options to avoid having to make filesystems aware of them.
+ * @fstype the type of filesystem being mounted.
+ * @orig the original mount data copied from userspace.
+ * @copy copied data which will be passed to the security module.
+ * Returns 0 if the copy was successful.
* @sb_check_sb:
* Check permission before the device with superblock @mnt->sb is mounted
* on the mount point named by @nd.
@@ -1024,7 +1034,8 @@
int (*sb_alloc_security) (struct super_block * sb);
void (*sb_free_security) (struct super_block * sb);
- int (*sb_kern_mount) (struct super_block *sb);
+ int (*sb_copy_data)(const char *fstype, void *orig, void *copy);
+ int (*sb_kern_mount) (struct super_block *sb, void *data);
int (*sb_statfs) (struct super_block * sb);
int (*sb_mount) (char *dev_name, struct nameidata * nd,
char *type, unsigned long flags, void *data);
@@ -1308,9 +1319,14 @@
security_ops->sb_free_security (sb);
}
-static inline int security_sb_kern_mount (struct super_block *sb)
+static inline int security_sb_copy_data (const char *fstype, void *orig, void *copy)
{
- return security_ops->sb_kern_mount (sb);
+ return security_ops->sb_copy_data (fstype, orig, copy);
+}
+
+static inline int security_sb_kern_mount (struct super_block *sb, void *data)
+{
+ return security_ops->sb_kern_mount (sb, data);
}
static inline int security_sb_statfs (struct super_block *sb)
@@ -1973,7 +1989,12 @@
static inline void security_sb_free (struct super_block *sb)
{ }
-static inline int security_sb_kern_mount (struct super_block *sb)
+static inline int security_sb_copy_data (const char *fstype, void *orig, void *copy)
+{
+ return 0;
+}
+
+static inline int security_sb_kern_mount (struct super_block *sb, void *data)
{
return 0;
}
diff -urN linux-2.6.3-rc3/include/video/aty128.h linux-2.6.3-rc4/include/video/aty128.h
--- linux-2.6.3-rc3/include/video/aty128.h 2004-02-03 19:43:43.000000000 -0800
+++ linux-2.6.3-rc4/include/video/aty128.h 2004-02-16 19:49:21.000000000 -0800
@@ -415,5 +415,8 @@
#define PWR_MGT_SLOWDOWN_MCLK 0x00002000
#define PMI_PMSCR_REG 0x60
+
+/* used by ATI bug fix for hardware ROM */
+#define RAGE128_MPP_TB_CONFIG 0x01c0
#endif /* REG_RAGE128_H */
diff -urN linux-2.6.3-rc3/net/bluetooth/rfcomm/tty.c linux-2.6.3-rc4/net/bluetooth/rfcomm/tty.c
--- linux-2.6.3-rc3/net/bluetooth/rfcomm/tty.c 2004-02-16 19:49:12.000000000 -0800
+++ linux-2.6.3-rc4/net/bluetooth/rfcomm/tty.c 2004-02-16 19:49:22.000000000 -0800
@@ -97,10 +97,16 @@
rfcomm_dlc_unlock(dlc);
rfcomm_dlc_put(dlc);
+
+ /* Refcount should only hit zero when called from rfcomm_dev_del()
+ which will have taken us off the list. Everything else are
+ refcounting bugs. */
+ BUG_ON(!list_empty(&dev->list));
+
kfree(dev);
/* It's safe to call module_put() here because socket still
- holds refference to this module. */
+ holds reference to this module. */
module_put(THIS_MODULE);
}
@@ -111,6 +117,13 @@
static inline void rfcomm_dev_put(struct rfcomm_dev *dev)
{
+ /* The reason this isn't actually a race, as you no
+ doubt have a little voice screaming at you in your
+ head, is that the refcount should never actually
+ reach zero unless the device has already been taken
+ off the list, in rfcomm_dev_del(). And if that's not
+ true, we'll hit the BUG() in rfcomm_dev_destruct()
+ anyway. */
if (atomic_dec_and_test(&dev->refcnt))
rfcomm_dev_destruct(dev);
}
@@ -134,10 +147,13 @@
struct rfcomm_dev *dev;
read_lock(&rfcomm_dev_lock);
+
dev = __rfcomm_dev_get(id);
+ if (dev)
+ rfcomm_dev_hold(dev);
+
read_unlock(&rfcomm_dev_lock);
- if (dev) rfcomm_dev_hold(dev);
return dev;
}
@@ -214,8 +230,9 @@
rfcomm_dlc_unlock(dlc);
/* It's safe to call __module_get() here because socket already
- holds refference to this module. */
+ holds reference to this module. */
__module_get(THIS_MODULE);
+
out:
write_unlock_bh(&rfcomm_dev_lock);
@@ -486,7 +503,8 @@
rfcomm_dev_del(dev);
/* We have to drop DLC lock here, otherwise
- * rfcomm_dev_put() will dead lock if it's the last refference */
+ rfcomm_dev_put() will dead lock if it's
+ the last reference. */
rfcomm_dlc_unlock(dlc);
rfcomm_dev_put(dev);
rfcomm_dlc_lock(dlc);
@@ -541,6 +559,10 @@
BT_DBG("tty %p id %d", tty, id);
+ /* We don't leak this refcount. For reasons which are not entirely
+ clear, the TTY layer will call our ->close() method even if the
+ open fails. We decrease the refcount there, and decreasing it
+ here too would cause breakage. */
dev = rfcomm_dev_get(id);
if (!dev)
return -ENODEV;
@@ -561,10 +583,8 @@
set_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
err = rfcomm_dlc_open(dlc, &dev->src, &dev->dst, dev->channel);
- if (err < 0) {
- rfcomm_dev_put(dev);
+ if (err < 0)
return err;
- }
/* Wait for DLC to connect */
add_wait_queue(&dev->wait, &wait);
@@ -589,9 +609,6 @@
set_current_state(TASK_RUNNING);
remove_wait_queue(&dev->wait, &wait);
- if (err < 0)
- rfcomm_dev_put(dev);
-
return err;
}
diff -urN linux-2.6.3-rc3/security/dummy.c linux-2.6.3-rc4/security/dummy.c
--- linux-2.6.3-rc3/security/dummy.c 2004-02-03 19:43:17.000000000 -0800
+++ linux-2.6.3-rc4/security/dummy.c 2004-02-16 19:49:22.000000000 -0800
@@ -194,7 +194,12 @@
return;
}
-static int dummy_sb_kern_mount (struct super_block *sb)
+static int dummy_sb_copy_data (const char *fstype, void *orig, void *copy)
+{
+ return 0;
+}
+
+static int dummy_sb_kern_mount (struct super_block *sb, void *data)
{
return 0;
}
@@ -877,6 +882,7 @@
set_to_dummy_if_null(ops, bprm_secureexec);
set_to_dummy_if_null(ops, sb_alloc_security);
set_to_dummy_if_null(ops, sb_free_security);
+ set_to_dummy_if_null(ops, sb_copy_data);
set_to_dummy_if_null(ops, sb_kern_mount);
set_to_dummy_if_null(ops, sb_statfs);
set_to_dummy_if_null(ops, sb_mount);
diff -urN linux-2.6.3-rc3/security/selinux/avc.c linux-2.6.3-rc4/security/selinux/avc.c
--- linux-2.6.3-rc3/security/selinux/avc.c 2004-02-03 19:44:14.000000000 -0800
+++ linux-2.6.3-rc4/security/selinux/avc.c 2004-02-16 19:49:22.000000000 -0800
@@ -166,7 +166,7 @@
*
* Initialize the access vector cache.
*/
-void avc_init(void)
+void __init avc_init(void)
{
struct avc_node *new;
int i;
diff -urN linux-2.6.3-rc3/security/selinux/hooks.c linux-2.6.3-rc4/security/selinux/hooks.c
--- linux-2.6.3-rc3/security/selinux/hooks.c 2004-02-03 19:44:44.000000000 -0800
+++ linux-2.6.3-rc4/security/selinux/hooks.c 2004-02-16 19:49:22.000000000 -0800
@@ -56,6 +56,8 @@
#include
#include /* for Unix socket types */
#include /* for Unix socket types */
+#include
+#include
#include "avc.h"
#include "objsec.h"
@@ -223,6 +225,7 @@
sbsec->magic = SELINUX_MAGIC;
sbsec->sb = sb;
sbsec->sid = SECINITSID_UNLABELED;
+ sbsec->def_sid = SECINITSID_FILE;
sb->s_security = sbsec;
return 0;
@@ -283,12 +286,13 @@
/* The file system's label must be initialized prior to use. */
-static char *labeling_behaviors[5] = {
+static char *labeling_behaviors[6] = {
"uses xattr",
"uses transition SIDs",
"uses task SIDs",
"uses genfs_contexts",
- "not configured for labeling"
+ "not configured for labeling",
+ "uses mountpoint labeling",
};
static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
@@ -298,7 +302,200 @@
return inode_doinit_with_dentry(inode, NULL);
}
-static int superblock_doinit(struct super_block *sb)
+enum {
+ Opt_context = 1,
+ Opt_fscontext = 2,
+ Opt_defcontext = 4,
+};
+
+static match_table_t tokens = {
+ {Opt_context, "context=%s"},
+ {Opt_fscontext, "fscontext=%s"},
+ {Opt_defcontext, "defcontext=%s"},
+};
+
+#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
+
+static int try_context_mount(struct super_block *sb, void *data)
+{
+ char *context = NULL, *defcontext = NULL;
+ const char *name;
+ u32 sid;
+ int alloc = 0, rc = 0, seen = 0;
+ struct task_security_struct *tsec = current->security;
+ struct superblock_security_struct *sbsec = sb->s_security;
+
+ if (!data)
+ goto out;
+
+ name = sb->s_type->name;
+
+ /* Ignore these fileystems with binary mount option data. */
+ if (!strcmp(name, "coda") ||
+ !strcmp(name, "afs") || !strcmp(name, "smbfs"))
+ goto out;
+
+ /* NFS we understand. */
+ if (!strcmp(name, "nfs")) {
+ struct nfs_mount_data *d = data;
+
+ if (d->version < NFS_MOUNT_VERSION)
+ goto out;
+
+ if (d->context[0]) {
+ context = d->context;
+ seen |= Opt_context;
+ }
+
+ /* Standard string-based options. */
+ } else {
+ char *p, *options = data;
+
+ while ((p = strsep(&options, ",")) != NULL) {
+ int token;
+ substring_t args[MAX_OPT_ARGS];
+
+ if (!*p)
+ continue;
+
+ token = match_token(p, tokens, args);
+
+ switch (token) {
+ case Opt_context:
+ if (seen) {
+ rc = -EINVAL;
+ printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
+ goto out_free;
+ }
+ context = match_strdup(&args[0]);
+ if (!context) {
+ rc = -ENOMEM;
+ goto out_free;
+ }
+ if (!alloc)
+ alloc = 1;
+ seen |= Opt_context;
+ break;
+
+ case Opt_fscontext:
+ if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
+ rc = -EINVAL;
+ printk(KERN_WARNING "SELinux: "
+ "fscontext option is invalid for"
+ " this filesystem type\n");
+ goto out_free;
+ }
+ if (seen & (Opt_context|Opt_fscontext)) {
+ rc = -EINVAL;
+ printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
+ goto out_free;
+ }
+ context = match_strdup(&args[0]);
+ if (!context) {
+ rc = -ENOMEM;
+ goto out_free;
+ }
+ if (!alloc)
+ alloc = 1;
+ seen |= Opt_fscontext;
+ break;
+
+ case Opt_defcontext:
+ if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
+ rc = -EINVAL;
+ printk(KERN_WARNING "SELinux: "
+ "defcontext option is invalid "
+ "for this filesystem type\n");
+ goto out_free;
+ }
+ if (seen & (Opt_context|Opt_defcontext)) {
+ rc = -EINVAL;
+ printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
+ goto out_free;
+ }
+ defcontext = match_strdup(&args[0]);
+ if (!defcontext) {
+ rc = -ENOMEM;
+ goto out_free;
+ }
+ if (!alloc)
+ alloc = 1;
+ seen |= Opt_defcontext;
+ break;
+
+ default:
+ rc = -EINVAL;
+ printk(KERN_WARNING "SELinux: unknown mount "
+ "option\n");
+ goto out_free;
+
+ }
+ }
+ }
+
+ if (!seen)
+ goto out;
+
+ if (context) {
+ rc = security_context_to_sid(context, strlen(context), &sid);
+ if (rc) {
+ printk(KERN_WARNING "SELinux: security_context_to_sid"
+ "(%s) failed for (dev %s, type %s) errno=%d\n",
+ context, sb->s_id, name, rc);
+ goto out_free;
+ }
+
+ rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
+ FILESYSTEM__RELABELFROM, NULL, NULL);
+ if (rc)
+ goto out_free;
+
+ rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
+ FILESYSTEM__RELABELTO, NULL, NULL);
+ if (rc)
+ goto out_free;
+
+ sbsec->sid = sid;
+
+ if (seen & Opt_context)
+ sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
+ }
+
+ if (defcontext) {
+ rc = security_context_to_sid(defcontext, strlen(defcontext), &sid);
+ if (rc) {
+ printk(KERN_WARNING "SELinux: security_context_to_sid"
+ "(%s) failed for (dev %s, type %s) errno=%d\n",
+ defcontext, sb->s_id, name, rc);
+ goto out_free;
+ }
+
+ if (sid == sbsec->def_sid)
+ goto out_free;
+
+ rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
+ FILESYSTEM__RELABELFROM, NULL, NULL);
+ if (rc)
+ goto out_free;
+
+ rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
+ FILESYSTEM__ASSOCIATE, NULL, NULL);
+ if (rc)
+ goto out_free;
+
+ sbsec->def_sid = sid;
+ }
+
+out_free:
+ if (alloc) {
+ kfree(context);
+ kfree(defcontext);
+ }
+out:
+ return rc;
+}
+
+static int superblock_doinit(struct super_block *sb, void *data)
{
struct superblock_security_struct *sbsec = sb->s_security;
struct dentry *root = sb->s_root;
@@ -328,6 +525,10 @@
goto out;
}
+ rc = try_context_mount(sb, data);
+ if (rc)
+ goto out;
+
if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
/* Make sure that the xattr handler exists and that no
error other than -ENODATA is returned by getxattr on
@@ -530,7 +731,7 @@
switch (sbsec->behavior) {
case SECURITY_FS_USE_XATTR:
if (!inode->i_op->getxattr) {
- isec->sid = SECINITSID_FILE;
+ isec->sid = sbsec->def_sid;
break;
}
@@ -589,7 +790,7 @@
goto out;
}
/* Map ENODATA to the default file SID */
- sid = SECINITSID_FILE;
+ sid = sbsec->def_sid;
rc = 0;
} else {
rc = security_context_to_sid(context, rc, &sid);
@@ -829,6 +1030,7 @@
tsec = current->security;
dsec = dir->i_security;
+ sbsec = dir->i_sb->s_security;
AVC_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.dentry = dentry;
@@ -839,7 +1041,7 @@
if (rc)
return rc;
- if (tsec->create_sid) {
+ if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
newsid = tsec->create_sid;
} else {
rc = security_transition_sid(tsec->sid, dsec->sid, tclass,
@@ -852,8 +1054,6 @@
if (rc)
return rc;
- sbsec = dir->i_sb->s_security;
-
return avc_has_perm(newsid, sbsec->sid,
SECCLASS_FILESYSTEM,
FILESYSTEM__ASSOCIATE, NULL, &ad);
@@ -1061,6 +1261,7 @@
tsec = current->security;
dsec = dir->i_security;
+ sbsec = dir->i_sb->s_security;
inode = dentry->d_inode;
if (!inode) {
@@ -1072,7 +1273,7 @@
return 0;
}
- if (tsec->create_sid) {
+ if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
newsid = tsec->create_sid;
} else {
rc = security_transition_sid(tsec->sid, dsec->sid,
@@ -1095,10 +1296,6 @@
return rc;
}
- sbsec = dir->i_sb->s_security;
- if (!sbsec)
- return 0;
-
if (sbsec->behavior == SECURITY_FS_USE_XATTR &&
inode->i_op->setxattr) {
/* Use extended attributes. */
@@ -1660,12 +1857,83 @@
superblock_free_security(sb);
}
-static int selinux_sb_kern_mount(struct super_block *sb)
+static inline int match_prefix(char *prefix, int plen, char *option, int olen)
+{
+ if (plen > olen)
+ return 0;
+
+ return !memcmp(prefix, option, plen);
+}
+
+static inline int selinux_option(char *option, int len)
+{
+ return (match_prefix("context=", sizeof("context=")-1, option, len) ||
+ match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) ||
+ match_prefix("defcontext=", sizeof("defcontext=")-1, option, len));
+}
+
+static inline void take_option(char **to, char *from, int *first, int len)
+{
+ if (!*first) {
+ **to = ',';
+ *to += 1;
+ }
+ else
+ *first = 0;
+ memcpy(*to, from, len);
+ *to += len;
+}
+
+static int selinux_sb_copy_data(const char *fstype, void *orig, void *copy)
+{
+ int fnosec, fsec, rc = 0;
+ char *in_save, *in_curr, *in_end;
+ char *sec_curr, *nosec_save, *nosec;
+
+ in_curr = orig;
+ sec_curr = copy;
+
+ /* Binary mount data: just copy */
+ if (!strcmp(fstype, "nfs") || !strcmp(fstype, "coda") ||
+ !strcmp(fstype, "smbfs") || !strcmp(fstype, "afs")) {
+ copy_page(sec_curr, in_curr);
+ goto out;
+ }
+
+ nosec = (char *)get_zeroed_page(GFP_KERNEL);
+ if (!nosec) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ nosec_save = nosec;
+ fnosec = fsec = 1;
+ in_save = in_end = orig;
+
+ do {
+ if (*in_end == ',' || *in_end == '\0') {
+ int len = in_end - in_curr;
+
+ if (selinux_option(in_curr, len))
+ take_option(&sec_curr, in_curr, &fsec, len);
+ else
+ take_option(&nosec, in_curr, &fnosec, len);
+
+ in_curr = in_end + 1;
+ }
+ } while (*in_end++);
+
+ copy_page(in_save, nosec_save);
+out:
+ return rc;
+}
+
+static int selinux_sb_kern_mount(struct super_block *sb, void *data)
{
struct avc_audit_data ad;
int rc;
- rc = superblock_doinit(sb);
+ rc = superblock_doinit(sb, data);
if (rc)
return rc;
@@ -1857,6 +2125,10 @@
return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
}
+ sbsec = inode->i_sb->s_security;
+ if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
+ return -ENOTSUPP;
+
AVC_AUDIT_DATA_INIT(&ad,FS);
ad.u.fs.dentry = dentry;
@@ -1875,10 +2147,6 @@
if (rc)
return rc;
- sbsec = inode->i_sb->s_security;
- if (!sbsec)
- return 0;
-
return avc_has_perm(newsid,
sbsec->sid,
SECCLASS_FILESYSTEM,
@@ -1913,6 +2181,12 @@
static int selinux_inode_getxattr (struct dentry *dentry, char *name)
{
+ struct inode *inode = dentry->d_inode;
+ struct superblock_security_struct *sbsec = inode->i_sb->s_security;
+
+ if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
+ return -ENOTSUPP;
+
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
}
@@ -2905,8 +3179,9 @@
/* Fixme: this lookup is inefficient */
iph = skb->nh.iph;
- err = security_node_sid(PF_INET, &iph->daddr, sizeof(iph->daddr), &node_sid);
- if (err)
+ err = security_node_sid(PF_INET, &iph->daddr, sizeof(iph->daddr),
+ &node_sid) ? NF_DROP : NF_ACCEPT;
+ if (err != NF_ACCEPT)
goto out;
err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE,
@@ -3555,6 +3830,7 @@
.sb_alloc_security = selinux_sb_alloc_security,
.sb_free_security = selinux_sb_free_security,
+ .sb_copy_data = selinux_sb_copy_data,
.sb_kern_mount = selinux_sb_kern_mount,
.sb_statfs = selinux_sb_statfs,
.sb_mount = selinux_mount,
@@ -3731,7 +4007,7 @@
spin_unlock(&sb_security_lock);
down_read(&sb->s_umount);
if (sb->s_root)
- superblock_doinit(sb);
+ superblock_doinit(sb, NULL);
drop_super(sb);
spin_lock(&sb_security_lock);
list_del_init(&sbsec->list);
diff -urN linux-2.6.3-rc3/security/selinux/include/avc.h linux-2.6.3-rc4/security/selinux/include/avc.h
--- linux-2.6.3-rc3/security/selinux/include/avc.h 2004-02-03 19:43:17.000000000 -0800
+++ linux-2.6.3-rc4/security/selinux/include/avc.h 2004-02-16 19:49:22.000000000 -0800
@@ -11,6 +11,7 @@
#include
#include
#include
+#include
#include
#include "flask.h"
#include "av_permissions.h"
@@ -121,7 +122,7 @@
* AVC operations
*/
-void avc_init(void);
+void __init avc_init(void);
int avc_lookup(u32 ssid, u32 tsid, u16 tclass,
u32 requested, struct avc_entry_ref *aeref);
diff -urN linux-2.6.3-rc3/security/selinux/include/objsec.h linux-2.6.3-rc4/security/selinux/include/objsec.h
--- linux-2.6.3-rc3/security/selinux/include/objsec.h 2004-02-03 19:43:43.000000000 -0800
+++ linux-2.6.3-rc4/security/selinux/include/objsec.h 2004-02-16 19:49:22.000000000 -0800
@@ -63,6 +63,7 @@
struct super_block *sb; /* back pointer to sb object */
struct list_head list; /* list of superblock_security_struct */
u32 sid; /* SID of file system */
+ u32 def_sid; /* default SID for labeling */
unsigned int behavior; /* labeling behavior */
unsigned char initialized; /* initialization flag */
unsigned char proc; /* proc fs */
diff -urN linux-2.6.3-rc3/security/selinux/include/security.h linux-2.6.3-rc4/security/selinux/include/security.h
--- linux-2.6.3-rc3/security/selinux/include/security.h 2004-02-03 19:43:08.000000000 -0800
+++ linux-2.6.3-rc4/security/selinux/include/security.h 2004-02-16 19:49:22.000000000 -0800
@@ -62,11 +62,13 @@
int security_node_sid(u16 domain, void *addr, u32 addrlen,
u32 *out_sid);
-#define SECURITY_FS_USE_XATTR 1 /* use xattr */
-#define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */
-#define SECURITY_FS_USE_TASK 3 /* use task SIDs, e.g. pipefs/sockfs */
-#define SECURITY_FS_USE_GENFS 4 /* use the genfs support */
-#define SECURITY_FS_USE_NONE 5 /* no labeling support */
+#define SECURITY_FS_USE_XATTR 1 /* use xattr */
+#define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */
+#define SECURITY_FS_USE_TASK 3 /* use task SIDs, e.g. pipefs/sockfs */
+#define SECURITY_FS_USE_GENFS 4 /* use the genfs support */
+#define SECURITY_FS_USE_NONE 5 /* no labeling support */
+#define SECURITY_FS_USE_MNTPOINT 6 /* use mountpoint labeling */
+
int security_fs_use(const char *fstype, unsigned int *behavior,
u32 *sid);
diff -urN linux-2.6.3-rc3/security/selinux/selinuxfs.c linux-2.6.3-rc4/security/selinux/selinuxfs.c
--- linux-2.6.3-rc3/security/selinux/selinuxfs.c 2004-02-03 19:45:09.000000000 -0800
+++ linux-2.6.3-rc4/security/selinux/selinuxfs.c 2004-02-16 19:49:22.000000000 -0800
@@ -603,7 +603,7 @@
{
static struct tree_descr selinux_files[] = {
[SEL_LOAD] = {"load", &sel_load_ops, S_IRUSR|S_IWUSR},
- [SEL_ENFORCE] = {"enforce", &sel_enforce_ops, S_IRUSR|S_IWUSR},
+ [SEL_ENFORCE] = {"enforce", &sel_enforce_ops, S_IRUGO|S_IWUSR},
[SEL_CONTEXT] = {"context", &sel_context_ops, S_IRUGO|S_IWUGO},
[SEL_ACCESS] = {"access", &transaction_ops, S_IRUGO|S_IWUGO},
[SEL_CREATE] = {"create", &transaction_ops, S_IRUGO|S_IWUGO},