## 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},