diff options
| author | Linus Torvalds <torvalds@home.transmeta.com> | 2002-09-08 18:41:49 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2002-09-08 18:41:49 -0700 |
| commit | d4cddb795d19f1ed3bdaa216f8be4e8b1034843c (patch) | |
| tree | decaab32244e646d049e4663789505fbaad2b8ba | |
| parent | f9506f4d7e4d06ca6f7006d8156ef6ba08ff1f1d (diff) | |
| parent | b32c3a0cc6c27e43c1b6dbbc840bbd569c5f84cc (diff) | |
Merge bk://thebsh.namesys.com/bk/reiser3-linux-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
123 files changed, 3419 insertions, 3242 deletions
diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile index c22b4900075f..5ff98abd62ad 100644 --- a/arch/alpha/Makefile +++ b/arch/alpha/Makefile @@ -128,6 +128,9 @@ archmrproper: vmlinux: arch/alpha/vmlinux.lds.s +arch/$(ARCH)/vmlinux.lds.s: arch/$(ARCH)/vmlinux.lds.S + $(CPP) $(CPPFLAGS) $(CPPFLAGS_$@) -D__ASSEMBLY__ -P -C -U$(ARCH) $< -o $@ + bootpfile: @$(MAKEBOOT) bootpfile diff --git a/arch/alpha/kernel/core_apecs.c b/arch/alpha/kernel/core_apecs.c index 738f2893be31..642153e74964 100644 --- a/arch/alpha/kernel/core_apecs.c +++ b/arch/alpha/kernel/core_apecs.c @@ -90,11 +90,11 @@ */ static int -mk_conf_addr(struct pci_bus *bus_dev, unsigned int device_fn, int where, +mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where, unsigned long *pci_addr, unsigned char *type1) { unsigned long addr; - u8 bus = bus_dev->number; + u8 bus = pbus->number; DBGC(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x," " pci_addr=0x%p, type1=0x%p)\n", @@ -272,8 +272,8 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1) } static int -apecs_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, - u8 *value) +apecs_read_config(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 *value) { unsigned long addr, pci_addr; unsigned char type1; @@ -283,27 +283,16 @@ apecs_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - switch (size) { - case 1: - mask = 0x00; - shift = (where & 3) * 8; - break; - case 2: - mask = 0x08; - shift = (where & 3) * 8; - break; - case 4: - mask = 0x18; - shift = 0; - break; - } + mask = (size - 1) * 8; + shift = (where & 3) * 8; addr = (pci_addr << 5) + mask + APECS_CONF; *value = conf_read(addr, type1) >> (shift); return PCIBIOS_SUCCESSFUL; } static int -apecs_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) +apecs_write_config(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 value) { unsigned long addr, pci_addr; unsigned char type1; @@ -312,17 +301,7 @@ apecs_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - switch (size) { - case 1: - mask = 0x00; - break; - case 2: - mask = 0x08; - break; - case 4: - mask = 0x18; - break; - } + mask = (size - 1) * 8; addr = (pci_addr << 5) + mask + APECS_CONF; conf_write(addr, value << ((where & 3) * 8), type1); return PCIBIOS_SUCCESSFUL; diff --git a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c index 469c1dda51db..b8c7a5e694f3 100644 --- a/arch/alpha/kernel/core_cia.c +++ b/arch/alpha/kernel/core_cia.c @@ -219,22 +219,9 @@ cia_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - switch (size) { - case 1: - mask = 0x00; - shift = (where & 3) * 8; - break; - case 2: - mask = 0x08; - shift = (where & 3) * 8; - break; - case 4: - mase = 0x18; - shift = 0; - break; - } - - addr = (pci_addr << 5) + 0x18 + CIA_CONF; + mask = (size - 1) * 8; + shift = (where & 3) * 8; + addr = (pci_addr << 5) + mask + CIA_CONF; *value = conf_read(addr, type1) >> (shift); return PCIBIOS_SUCCESSFUL; } @@ -250,18 +237,7 @@ cia_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - switch (size) { - case 1: - mask = 0x00; - break; - case 2: - mask = 0x08; - break; - case 4: - mase = 0x18; - break; - } - + mask = (size - 1) * 8; addr = (pci_addr << 5) + mask + CIA_CONF; conf_write(addr, value << ((where & 3) * 8), type1); return PCIBIOS_SUCCESSFUL; diff --git a/arch/alpha/kernel/core_irongate.c b/arch/alpha/kernel/core_irongate.c index 59f91ce4f833..1709838729a6 100644 --- a/arch/alpha/kernel/core_irongate.c +++ b/arch/alpha/kernel/core_irongate.c @@ -83,11 +83,11 @@ */ static int -mk_conf_addr(struct pci_bus *bus_dev, unsigned int device_fn, int where, +mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where, unsigned long *pci_addr, unsigned char *type1) { unsigned long addr; - u8 bus = bus_dev->number; + u8 bus = pbus->number; DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, " "pci_addr=0x%p, type1=0x%p)\n", @@ -113,7 +113,18 @@ irongate_read_config(struct pci_bus *bus, unsigned int devfn, int where, if (mk_conf_addr(bus, devfn, where, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - *value = __kernel_ldbu(*(vucp)addr); + switch (size) { + case 1: + *value = __kernel_ldbu(*(vucp)addr); + break; + case 2: + *value = __kernel_ldwu(*(vusp)addr); + break; + case 4: + *value = *(vuip)addr; + break; + } + return PCIBIOS_SUCCESSFUL; } @@ -127,13 +138,27 @@ irongate_write_config(struct pci_bus *bus, unsigned int devfn, int where, if (mk_conf_addr(bus, devfn, where, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - __kernel_stb(value, *(vucp)addr); - mb(); - __kernel_ldbu(*(vucp)addr); + switch (size) { + case 1: + __kernel_stb(value, *(vucp)addr); + mb(); + __kernel_ldbu(*(vucp)addr); + break; + case 2: + __kernel_stw(value, *(vusp)addr); + mb(); + __kernel_ldwu(*(vusp)addr); + break; + case 4: + *(vuip)addr = value; + mb(); + *(vuip)addr; + break; + } + return PCIBIOS_SUCCESSFUL; } - struct pci_ops irongate_pci_ops = { .read = irongate_read_config, diff --git a/arch/alpha/kernel/core_lca.c b/arch/alpha/kernel/core_lca.c index 0c172677003b..197f03c10ea0 100644 --- a/arch/alpha/kernel/core_lca.c +++ b/arch/alpha/kernel/core_lca.c @@ -99,11 +99,11 @@ */ static int -mk_conf_addr(struct pci_bus *bus_dev, unsigned int device_fn, int where, +mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where, unsigned long *pci_addr) { unsigned long addr; - u8 bus = bus_dev->number; + u8 bus = pbus->number; if (bus == 0) { int device = device_fn >> 3; @@ -204,32 +204,20 @@ lca_read_config(struct pci_bus *bus, unsigned int devfn, int where, { unsigned long addr, pci_addr; long mask; - int shift + int shift; - if (mk_conf_addr(bus, devfn, dev, where, &pci_addr)) + if (mk_conf_addr(bus, devfn, where, &pci_addr)) return PCIBIOS_DEVICE_NOT_FOUND; - switch (size) { - case 1: - shift = (where & 3) * 8; - mask = 0x00; - break; - case 2: - shift = (where & 3) * 8; - mask = 0x08 - break; - case 4: - shift = 0; - mask = 0x18 - break; - } + shift = (where & 3) * 8; + mask = (size - 1) * 8; addr = (pci_addr << 5) + mask + LCA_CONF; *value = conf_read(addr) >> (shift); return PCIBIOS_SUCCESSFUL; } static int -lca_write_config(struct pci_bus *dev, unsigned int devfn, int where, int size, +lca_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) { unsigned long addr, pci_addr; @@ -238,17 +226,7 @@ lca_write_config(struct pci_bus *dev, unsigned int devfn, int where, int size, if (mk_conf_addr(bus, devfn, where, &pci_addr)) return PCIBIOS_DEVICE_NOT_FOUND; - switch (size) { - case 1: - mask = 0x00; - break; - case 2: - mask = 0x08 - break; - case 4: - mask = 0x18 - break; - } + mask = (size - 1) * 8; addr = (pci_addr << 5) + mask + LCA_CONF; conf_write(addr, value << ((where & 3) * 8)); return PCIBIOS_SUCCESSFUL; diff --git a/arch/alpha/kernel/core_mcpcia.c b/arch/alpha/kernel/core_mcpcia.c index 655ed6757535..5b249fde8c0d 100644 --- a/arch/alpha/kernel/core_mcpcia.c +++ b/arch/alpha/kernel/core_mcpcia.c @@ -171,11 +171,11 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1, } static int -mk_conf_addr(struct pci_dev *dev, int where, struct pci_controller *hose, - unsigned long *pci_addr, unsigned char *type1) +mk_conf_addr(struct pci_bus *pbus, unsigned int devfn, int where, + struct pci_controller *hose, unsigned long *pci_addr, + unsigned char *type1) { - u8 bus = dev->bus->number; - u8 devfn = dev->devfn; + u8 bus = pbus->number; unsigned long addr; DBG_CFG(("mk_conf_addr(bus=%d,devfn=0x%x,hose=%d,where=0x%x," @@ -185,7 +185,7 @@ mk_conf_addr(struct pci_dev *dev, int where, struct pci_controller *hose, /* Type 1 configuration cycle for *ALL* busses. */ *type1 = 1; - if (dev->bus->number == hose->first_busno) + if (bus == hose->first_busno) bus = 0; addr = (bus << 16) | (devfn << 8) | (where); addr <<= 5; /* swizzle for SPARSE */ @@ -197,94 +197,53 @@ mk_conf_addr(struct pci_dev *dev, int where, struct pci_controller *hose, } static int -mcpcia_read_config_byte(struct pci_dev *dev, int where, u8 *value) +mcpcia_read_config(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 *value) { - struct pci_controller *hose = dev->sysdata; + struct pci_controller *hose = bus->sysdata; unsigned long addr, w; unsigned char type1; - if (mk_conf_addr(dev, where, hose, &addr, &type1)) + if (mk_conf_addr(bus, devfn, where, hose, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= 0x00; + addr |= (size - 1) * 8; w = conf_read(addr, type1, hose); - *value = __kernel_extbl(w, where & 3); - return PCIBIOS_SUCCESSFUL; -} - -static int -mcpcia_read_config_word(struct pci_dev *dev, int where, u16 *value) -{ - struct pci_controller *hose = dev->sysdata; - unsigned long addr, w; - unsigned char type1; - - if (mk_conf_addr(dev, where, hose, &addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; - - addr |= 0x08; - w = conf_read(addr, type1, hose); - *value = __kernel_extwl(w, where & 3); - return PCIBIOS_SUCCESSFUL; -} - -static int -mcpcia_read_config_dword(struct pci_dev *dev, int where, u32 *value) -{ - struct pci_controller *hose = dev->sysdata; - unsigned long addr; - unsigned char type1; - - if (mk_conf_addr(dev, where, hose, &addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; - - addr |= 0x18; - *value = conf_read(addr, type1, hose); + switch (size) { + case 1: + *value = __kernel_extbl(w, where & 3); + break; + case 2: + *value = __kernel_extwl(w, where & 3); + break; + case 4: + *value = w; + break; + } return PCIBIOS_SUCCESSFUL; } static int -mcpcia_write_config(struct pci_dev *dev, int where, u32 value, long mask) +mcpcia_write_config(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 value) { - struct pci_controller *hose = dev->sysdata; + struct pci_controller *hose = bus->sysdata; unsigned long addr; unsigned char type1; - if (mk_conf_addr(dev, where, hose, &addr, &type1)) + if (mk_conf_addr(bus, devfn, where, hose, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= mask; + addr |= (size - 1) * 8; value = __kernel_insql(value, where & 3); conf_write(addr, value, type1, hose); return PCIBIOS_SUCCESSFUL; } -static int -mcpcia_write_config_byte(struct pci_dev *dev, int where, u8 value) -{ - return mcpcia_write_config(dev, where, value, 0x00); -} - -static int -mcpcia_write_config_word(struct pci_dev *dev, int where, u16 value) -{ - return mcpcia_write_config(dev, where, value, 0x08); -} - -static int -mcpcia_write_config_dword(struct pci_dev *dev, int where, u32 value) -{ - return mcpcia_write_config(dev, where, value, 0x18); -} - struct pci_ops mcpcia_pci_ops = { - read_byte: mcpcia_read_config_byte, - read_word: mcpcia_read_config_word, - read_dword: mcpcia_read_config_dword, - write_byte: mcpcia_write_config_byte, - write_word: mcpcia_write_config_word, - write_dword: mcpcia_write_config_dword + .read = mcpcia_read_config, + .write = mcpcia_write_config, }; void diff --git a/arch/alpha/kernel/core_polaris.c b/arch/alpha/kernel/core_polaris.c index a7b063925d7e..604071eef3c8 100644 --- a/arch/alpha/kernel/core_polaris.c +++ b/arch/alpha/kernel/core_polaris.c @@ -65,10 +65,10 @@ */ static int -mk_conf_addr(struct pci_bus *bus_dev, unsigned int device_fn, int where, +mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where, unsigned long *pci_addr, u8 *type1) { - u8 bus = bus_dev->number; + u8 bus = pbus->number; *type1 = (bus == 0) ? 0 : 1; *pci_addr = (bus << 16) | (device_fn << 8) | (where) | @@ -85,13 +85,24 @@ static int polaris_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) { - unsigned long pci_addr; + unsigned long addr; unsigned char type1; - if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1)) + if (mk_conf_addr(bus, devfn, where, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - *value = __kernel_ldbu(*(vucp)pci_addr); + switch (size) { + case 1: + *value = __kernel_ldbu(*(vucp)addr); + break; + case 2: + *value = __kernel_ldwu(*(vusp)addr); + break; + case 4: + *value = *(vuip)addr; + break; + } + return PCIBIOS_SUCCESSFUL; } @@ -100,15 +111,30 @@ static int polaris_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) { - unsigned long pci_addr; + unsigned long addr; unsigned char type1; - if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1)) + if (mk_conf_addr(bus, devfn, where, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - __kernel_stb(value, *(vucp)pci_addr); - mb(); - __kernel_ldbu(*(vucp)pci_addr); + switch (size) { + case 1: + __kernel_stb(value, *(vucp)addr); + mb(); + __kernel_ldbu(*(vucp)addr); + break; + case 2: + __kernel_stw(value, *(vusp)addr); + mb(); + __kernel_ldwu(*(vusp)addr); + break; + case 4: + *(vuip)addr = value; + mb(); + *(vuip)addr; + break; + } + return PCIBIOS_SUCCESSFUL; } diff --git a/arch/alpha/kernel/core_t2.c b/arch/alpha/kernel/core_t2.c index 6fbd379ae099..801b5b2c2037 100644 --- a/arch/alpha/kernel/core_t2.c +++ b/arch/alpha/kernel/core_t2.c @@ -26,6 +26,18 @@ #include "proto.h" #include "pci_impl.h" +/* + * By default, we direct-map starting at 2GB, in order to allow the + * maximum size direct-map window (2GB) to match the maximum amount of + * memory (2GB) that can be present on SABLEs. But that limits the + * floppy to DMA only via the scatter/gather window set up for 8MB + * ISA DMA, since the maximum ISA DMA address is 2GB-1. + * + * For now, this seems a reasonable trade-off: even though most SABLEs + * have far less than even 1GB of memory, floppy usage/performance will + * not really be affected by forcing it to go via scatter/gather... + */ +#define T2_DIRECTMAP_2G 1 /* * NOTE: Herein lie back-to-back mb instructions. They are magic. @@ -89,11 +101,11 @@ */ static int -mk_conf_addr(struct pci_bus *bus_dev, unsigned int device_fn, int where, +mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where, unsigned long *pci_addr, unsigned char *type1) { unsigned long addr; - u8 bus = bus_dev->number; + u8 bus = pbus->number; DBG(("mk_conf_addr(bus=%d, dfn=0x%x, where=0x%x," " addr=0x%lx, type1=0x%x)\n", @@ -248,20 +260,8 @@ t2_read_config(struct pci_bus *bus, unsigned int devfn, int where, if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - switch (size) { - case 1: - mask = 0x00; - shift = (where & 3) * 8; - break; - case 2: - mask = 0x08; - shift = (where & 3) * 8; - break; - case 4: - mask = 0x18; - shift = 0; - break; - } + mask = (size - 1) * 8; + shift = (where & 3) * 8; addr = (pci_addr << 5) + mask + T2_CONF; *value = conf_read(addr, type1) >> (shift); return PCIBIOS_SUCCESSFUL; @@ -275,20 +275,10 @@ t2_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, unsigned char type1; long mask; - if (mk_conf_addr(dev, where, &pci_addr, &type1)) + if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - switch (size) { - case 1: - mask = 0x00; - break; - case 2: - mask = 0x08; - break; - case 4: - mask = 0x18; - break; - } + mask = (size - 1) * 8; addr = (pci_addr << 5) + mask + T2_CONF; conf_write(addr, value << ((where & 3) * 8), type1); return PCIBIOS_SUCCESSFUL; @@ -304,6 +294,7 @@ void __init t2_init_arch(void) { struct pci_controller *hose; + unsigned long t2_iocsr; unsigned int i; for (i = 0; i < NR_CPUS; i++) { @@ -312,43 +303,80 @@ t2_init_arch(void) } #if 0 - { - /* Set up error reporting. */ - unsigned long t2_err; + /* Set up error reporting. */ + t2_iocsr = *(vulp)T2_IOCSR; + *(vulp)T2_IOCSR = t2_iocsr | (0x1UL << 7); /* TLB error check */ + mb(); + *(vulp)T2_IOCSR; /* read it back to make sure */ +#endif - t2_err = *(vulp)T2_IOCSR; - t2_err |= (0x1 << 7); /* master abort */ - *(vulp)T2_IOCSR = t2_err; - mb(); + /* Enable scatter/gather TLB use. */ + t2_iocsr = *(vulp)T2_IOCSR; + if (!(t2_iocsr & (0x1UL << 26))) { + printk("t2_init_arch: enabling SG TLB, IOCSR was 0x%lx\n", + t2_iocsr); + *(vulp)T2_IOCSR = t2_iocsr | (0x1UL << 26); + mb(); + *(vulp)T2_IOCSR; /* read it back to make sure */ } -#endif - printk("t2_init: HBASE was 0x%lx\n", *(vulp)T2_HBASE); #if 0 - printk("t2_init: WBASE1=0x%lx WMASK1=0x%lx TBASE1=0x%lx\n", - *(vulp)T2_WBASE1, - *(vulp)T2_WMASK1, - *(vulp)T2_TBASE1); - printk("t2_init: WBASE2=0x%lx WMASK2=0x%lx TBASE2=0x%lx\n", - *(vulp)T2_WBASE2, - *(vulp)T2_WMASK2, - *(vulp)T2_TBASE2); + printk("t2_init_arch: HBASE was 0x%lx\n", *(vulp)T2_HBASE); + printk("t2_init_arch: WBASE1=0x%lx WMASK1=0x%lx TBASE1=0x%lx\n", + *(vulp)T2_WBASE1, *(vulp)T2_WMASK1, *(vulp)T2_TBASE1); + printk("t2_init_arch: WBASE2=0x%lx WMASK2=0x%lx TBASE2=0x%lx\n", + *(vulp)T2_WBASE2, *(vulp)T2_WMASK2, *(vulp)T2_TBASE2); #endif /* + * Create our single hose. + */ + + pci_isa_hose = hose = alloc_pci_controller(); + hose->io_space = &ioport_resource; + hose->mem_space = &iomem_resource; + hose->index = 0; + + hose->sparse_mem_base = T2_SPARSE_MEM - IDENT_ADDR; + hose->dense_mem_base = T2_DENSE_MEM - IDENT_ADDR; + hose->sparse_io_base = T2_IO - IDENT_ADDR; + hose->dense_io_base = 0; + + /* Note we can only do 1 SG window, as the other is for direct, so + do an ISA SG area, especially for the floppy. */ + hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0); + hose->sg_pci = NULL; + + /* * Set up the PCI->physical memory translation windows. - * For now, window 2 is disabled. In the future, we may - * want to use it to do scatter/gather DMA. * - * Window 1 goes at 1 GB and is 1 GB large. + * Window 1 goes at ? GB and is ?GB large, direct mapped. + * Window 2 goes at 8 MB and is 8MB large, scatter/gather (for ISA). */ - /* WARNING!! must correspond to the DMA_WIN params!!! */ +#if T2_DIRECTMAP_2G + __direct_map_base = 0x80000000UL; + __direct_map_size = 0x80000000UL; + + /* WARNING!! must correspond to the direct map window params!!! */ + *(vulp)T2_WBASE1 = 0x80080fffU; + *(vulp)T2_WMASK1 = 0x7ff00000U; + *(vulp)T2_TBASE1 = 0; +#else /* T2_DIRECTMAP_2G */ + __direct_map_base = 0x40000000UL; + __direct_map_size = 0x40000000UL; + + /* WARNING!! must correspond to the direct map window params!!! */ *(vulp)T2_WBASE1 = 0x400807ffU; *(vulp)T2_WMASK1 = 0x3ff00000U; *(vulp)T2_TBASE1 = 0; +#endif /* T2_DIRECTMAP_2G */ + + /* WARNING!! must correspond to the SG arena/window params!!! */ + *(vulp)T2_WBASE2 = 0x008c000fU; + *(vulp)T2_WMASK2 = 0x00700000U; + *(vulp)T2_TBASE2 = virt_to_phys(hose->sg_isa->ptes) >> 1; - *(vulp)T2_WBASE2 = 0x0; *(vulp)T2_HBASE = 0x0; /* Zero HAE. */ @@ -356,26 +384,28 @@ t2_init_arch(void) *(vulp)T2_HAE_2 = 0; mb(); *(vulp)T2_HAE_3 = 0; mb(); #if 0 - *(vulp)T2_HAE_4 = 0; mb(); /* do not touch this */ + *(vulp)T2_HAE_4 = 0; mb(); /* DO NOT TOUCH THIS!!! */ #endif - /* - * Create our single hose. - */ + t2_pci_tbi(hose, 0, -1); /* flush TLB all */ +} - pci_isa_hose = hose = alloc_pci_controller(); - hose->io_space = &ioport_resource; - hose->mem_space = &iomem_resource; - hose->index = 0; +void +t2_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end) +{ + unsigned long t2_iocsr; - hose->sparse_mem_base = T2_SPARSE_MEM - IDENT_ADDR; - hose->dense_mem_base = T2_DENSE_MEM - IDENT_ADDR; - hose->sparse_io_base = T2_IO - IDENT_ADDR; - hose->dense_io_base = 0; + t2_iocsr = *(vulp)T2_IOCSR; - hose->sg_isa = hose->sg_pci = NULL; - __direct_map_base = 0x40000000; - __direct_map_size = 0x40000000; + /* set the TLB Clear bit */ + *(vulp)T2_IOCSR = t2_iocsr | (0x1UL << 28); + mb(); + *(vulp)T2_IOCSR; /* read it back to make sure */ + + /* clear the TLB Clear bit */ + *(vulp)T2_IOCSR = t2_iocsr & ~(0x1UL << 28); + mb(); + *(vulp)T2_IOCSR; /* read it back to make sure */ } #define SIC_SEIC (1UL << 33) /* System Event Clear */ diff --git a/arch/alpha/kernel/core_titan.c b/arch/alpha/kernel/core_titan.c index 4b8168f97ca3..eef1c29c7a9b 100644 --- a/arch/alpha/kernel/core_titan.c +++ b/arch/alpha/kernel/core_titan.c @@ -82,19 +82,18 @@ static struct */ static int -mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr, - unsigned char *type1) +mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where, + unsigned long *pci_addr, unsigned char *type1) { - struct pci_controller *hose = dev->sysdata; + struct pci_controller *hose = pbus->sysdata; unsigned long addr; - u8 bus = dev->bus->number; - u8 device_fn = dev->devfn; + u8 bus = pbus->number; DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, " "pci_addr=0x%p, type1=0x%p)\n", bus, device_fn, where, pci_addr, type1)); - if (hose->first_busno == dev->bus->number) + if (hose->first_busno == bus) bus = 0; *type1 = (bus != 0); @@ -106,98 +105,66 @@ mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr, return 0; } -static int -titan_read_config_byte(struct pci_dev *dev, int where, u8 *value) -{ - unsigned long addr; - unsigned char type1; - - if (mk_conf_addr(dev, where, &addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; - - *value = __kernel_ldbu(*(vucp)addr); - return PCIBIOS_SUCCESSFUL; -} - -static int -titan_read_config_word(struct pci_dev *dev, int where, u16 *value) -{ - unsigned long addr; - unsigned char type1; - - if (mk_conf_addr(dev, where, &addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; - - *value = __kernel_ldwu(*(vusp)addr); - return PCIBIOS_SUCCESSFUL; -} - static int -titan_read_config_dword(struct pci_dev *dev, int where, u32 *value) +titan_read_config(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 *value) { unsigned long addr; unsigned char type1; - if (mk_conf_addr(dev, where, &addr, &type1)) + if (mk_conf_addr(bus, devfn, where, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - *value = *(vuip)addr; - return PCIBIOS_SUCCESSFUL; -} - -static int -titan_write_config_byte(struct pci_dev *dev, int where, u8 value) -{ - unsigned long addr; - unsigned char type1; - - if (mk_conf_addr(dev, where, &addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; + switch (size) { + case 1: + *value = __kernel_ldbu(*(vucp)addr); + break; + case 2: + *value = __kernel_ldwu(*(vusp)addr); + break; + case 4: + *value = *(vuip)addr; + break; + } - __kernel_stb(value, *(vucp)addr); - mb(); - __kernel_ldbu(*(vucp)addr); return PCIBIOS_SUCCESSFUL; } static int -titan_write_config_word(struct pci_dev *dev, int where, u16 value) +titan_write_config(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 value) { unsigned long addr; unsigned char type1; - if (mk_conf_addr(dev, where, &addr, &type1)) + if (mk_conf_addr(bus, devfn, where, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - __kernel_stw(value, *(vusp)addr); - mb(); - __kernel_ldwu(*(vusp)addr); - return PCIBIOS_SUCCESSFUL; -} - -static int -titan_write_config_dword(struct pci_dev *dev, int where, u32 value) -{ - unsigned long addr; - unsigned char type1; - - if (mk_conf_addr(dev, where, &addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; + switch (size) { + case 1: + __kernel_stb(value, *(vucp)addr); + mb(); + __kernel_ldbu(*(vucp)addr); + break; + case 2: + __kernel_stw(value, *(vusp)addr); + mb(); + __kernel_ldwu(*(vusp)addr); + break; + case 4: + *(vuip)addr = value; + mb(); + *(vuip)addr; + break; + } - *(vuip)addr = value; - mb(); - *(vuip)addr; return PCIBIOS_SUCCESSFUL; } struct pci_ops titan_pci_ops = { - read_byte: titan_read_config_byte, - read_word: titan_read_config_word, - read_dword: titan_read_config_dword, - write_byte: titan_write_config_byte, - write_word: titan_write_config_word, - write_dword: titan_write_config_dword + .read = titan_read_config, + .write = titan_write_config, }; diff --git a/arch/alpha/kernel/core_tsunami.c b/arch/alpha/kernel/core_tsunami.c index 48908861f4bf..7628bc241085 100644 --- a/arch/alpha/kernel/core_tsunami.c +++ b/arch/alpha/kernel/core_tsunami.c @@ -89,19 +89,18 @@ static struct */ static int -mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr, - unsigned char *type1) +mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where, + unsigned long *pci_addr, unsigned char *type1) { - struct pci_controller *hose = dev->sysdata; + struct pci_controller *hose = pbus->sysdata; unsigned long addr; - u8 bus = dev->bus->number; - u8 device_fn = dev->devfn; + u8 bus = pbus->number; DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, " "pci_addr=0x%p, type1=0x%p)\n", bus, device_fn, where, pci_addr, type1)); - if (hose->first_busno == dev->bus->number) + if (hose->first_busno == bus) bus = 0; *type1 = (bus != 0); @@ -114,97 +113,65 @@ mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr, } static int -tsunami_read_config_byte(struct pci_dev *dev, int where, u8 *value) +tsunami_read_config(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 *value) { unsigned long addr; unsigned char type1; - if (mk_conf_addr(dev, where, &addr, &type1)) + if (mk_conf_addr(bus, devfn, where, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - *value = __kernel_ldbu(*(vucp)addr); - return PCIBIOS_SUCCESSFUL; -} - -static int -tsunami_read_config_word(struct pci_dev *dev, int where, u16 *value) -{ - unsigned long addr; - unsigned char type1; - - if (mk_conf_addr(dev, where, &addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; - - *value = __kernel_ldwu(*(vusp)addr); - return PCIBIOS_SUCCESSFUL; -} - -static int -tsunami_read_config_dword(struct pci_dev *dev, int where, u32 *value) -{ - unsigned long addr; - unsigned char type1; - - if (mk_conf_addr(dev, where, &addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; - - *value = *(vuip)addr; - return PCIBIOS_SUCCESSFUL; -} - -static int -tsunami_write_config_byte(struct pci_dev *dev, int where, u8 value) -{ - unsigned long addr; - unsigned char type1; - - if (mk_conf_addr(dev, where, &addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; + switch (size) { + case 1: + *value = __kernel_ldbu(*(vucp)addr); + break; + case 2: + *value = __kernel_ldwu(*(vusp)addr); + break; + case 4: + *value = *(vuip)addr; + break; + } - __kernel_stb(value, *(vucp)addr); - mb(); - __kernel_ldbu(*(vucp)addr); return PCIBIOS_SUCCESSFUL; } static int -tsunami_write_config_word(struct pci_dev *dev, int where, u16 value) +tsunami_write_config(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 value) { unsigned long addr; unsigned char type1; - if (mk_conf_addr(dev, where, &addr, &type1)) + if (mk_conf_addr(bus, devfn, where, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - __kernel_stw(value, *(vusp)addr); - mb(); - __kernel_ldwu(*(vusp)addr); - return PCIBIOS_SUCCESSFUL; -} - -static int -tsunami_write_config_dword(struct pci_dev *dev, int where, u32 value) -{ - unsigned long addr; - unsigned char type1; - - if (mk_conf_addr(dev, where, &addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; + switch (size) { + case 1: + __kernel_stb(value, *(vucp)addr); + mb(); + __kernel_ldbu(*(vucp)addr); + break; + case 2: + __kernel_stw(value, *(vusp)addr); + mb(); + __kernel_ldwu(*(vusp)addr); + break; + case 4: + *(vuip)addr = value; + mb(); + *(vuip)addr; + break; + } - *(vuip)addr = value; - mb(); - *(vuip)addr; return PCIBIOS_SUCCESSFUL; } struct pci_ops tsunami_pci_ops = { - read_byte: tsunami_read_config_byte, - read_word: tsunami_read_config_word, - read_dword: tsunami_read_config_dword, - write_byte: tsunami_write_config_byte, - write_word: tsunami_write_config_word, - write_dword: tsunami_write_config_dword + .read = tsunami_read_config, + .write = tsunami_write_config, }; void @@ -350,10 +317,17 @@ tsunami_init_one_pchip(tsunami_pchip *pchip, int index) * Window 0 is scatter-gather 8MB at 8MB (for isa) * Window 1 is scatter-gather (up to) 1GB at 1GB * Window 2 is direct access 2GB at 2GB + * + * NOTE: we need the align_entry settings for Acer devices on ES40, + * specifically floppy and IDE when memory is larger than 2GB. */ hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0); + /* Initially set for 4 PTEs, but will be overridden to 64K for ISA. */ + hose->sg_isa->align_entry = 4; + hose->sg_pci = iommu_arena_new(hose, 0x40000000, size_for_memory(0x40000000), 0); + hose->sg_pci->align_entry = 4; /* Tsunami caches 4 PTEs at a time */ __direct_map_base = 0x80000000; __direct_map_size = 0x80000000; diff --git a/arch/alpha/kernel/core_wildfire.c b/arch/alpha/kernel/core_wildfire.c index cf27355f98ef..10b77131e080 100644 --- a/arch/alpha/kernel/core_wildfire.c +++ b/arch/alpha/kernel/core_wildfire.c @@ -357,19 +357,18 @@ wildfire_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end) } static int -mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr, - unsigned char *type1) +mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where, + unsigned long *pci_addr, unsigned char *type1) { - struct pci_controller *hose = dev->sysdata; + struct pci_controller *hose = pbus->sysdata; unsigned long addr; - u8 bus = dev->bus->number; - u8 device_fn = dev->devfn; + u8 bus = pbus->number; DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, " "pci_addr=0x%p, type1=0x%p)\n", bus, device_fn, where, pci_addr, type1)); - if (hose->first_busno == dev->bus->number) + if (hose->first_busno == bus) bus = 0; *type1 = (bus != 0); @@ -382,97 +381,65 @@ mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr, } static int -wildfire_read_config_byte(struct pci_dev *dev, int where, u8 *value) +wildfire_read_config(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 *value) { unsigned long addr; unsigned char type1; - if (mk_conf_addr(dev, where, &addr, &type1)) + if (mk_conf_addr(bus, devfn, where, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - *value = __kernel_ldbu(*(vucp)addr); - return PCIBIOS_SUCCESSFUL; -} - -static int -wildfire_read_config_word(struct pci_dev *dev, int where, u16 *value) -{ - unsigned long addr; - unsigned char type1; - - if (mk_conf_addr(dev, where, &addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; - - *value = __kernel_ldwu(*(vusp)addr); - return PCIBIOS_SUCCESSFUL; -} - -static int -wildfire_read_config_dword(struct pci_dev *dev, int where, u32 *value) -{ - unsigned long addr; - unsigned char type1; - - if (mk_conf_addr(dev, where, &addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; - - *value = *(vuip)addr; - return PCIBIOS_SUCCESSFUL; -} - -static int -wildfire_write_config_byte(struct pci_dev *dev, int where, u8 value) -{ - unsigned long addr; - unsigned char type1; - - if (mk_conf_addr(dev, where, &addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; + switch (size) { + case 1: + *value = __kernel_ldbu(*(vucp)addr); + break; + case 2: + *value = __kernel_ldwu(*(vusp)addr); + break; + case 4: + *value = *(vuip)addr; + break; + } - __kernel_stb(value, *(vucp)addr); - mb(); - __kernel_ldbu(*(vucp)addr); return PCIBIOS_SUCCESSFUL; } static int -wildfire_write_config_word(struct pci_dev *dev, int where, u16 value) +wildfire_write_config(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 value) { unsigned long addr; unsigned char type1; - if (mk_conf_addr(dev, where, &addr, &type1)) + if (mk_conf_addr(bus, devfn, where, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - __kernel_stw(value, *(vusp)addr); - mb(); - __kernel_ldwu(*(vusp)addr); - return PCIBIOS_SUCCESSFUL; -} - -static int -wildfire_write_config_dword(struct pci_dev *dev, int where, u32 value) -{ - unsigned long addr; - unsigned char type1; - - if (mk_conf_addr(dev, where, &addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; + switch (size) { + case 1: + __kernel_stb(value, *(vucp)addr); + mb(); + __kernel_ldbu(*(vucp)addr); + break; + case 2: + __kernel_stw(value, *(vusp)addr); + mb(); + __kernel_ldwu(*(vusp)addr); + break; + case 4: + *(vuip)addr = value; + mb(); + *(vuip)addr; + break; + } - *(vuip)addr = value; - mb(); - *(vuip)addr; return PCIBIOS_SUCCESSFUL; } struct pci_ops wildfire_pci_ops = { - read_byte: wildfire_read_config_byte, - read_word: wildfire_read_config_word, - read_dword: wildfire_read_config_dword, - write_byte: wildfire_write_config_byte, - write_word: wildfire_write_config_word, - write_dword: wildfire_write_config_dword + .read = wildfire_read_config, + .write = wildfire_write_config, }; #if DEBUG_DUMP_REGS diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index 71bff0b02488..ff03ca642089 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -12,11 +12,11 @@ #include <linux/config.h> #include <linux/kernel.h> -#include <linux/ptrace.h> #include <linux/errno.h> #include <linux/kernel_stat.h> #include <linux/signal.h> #include <linux/sched.h> +#include <linux/ptrace.h> #include <linux/interrupt.h> #include <linux/slab.h> #include <linux/random.h> diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index c6cda4e39dae..cb74c9705cad 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c @@ -97,15 +97,22 @@ quirk_cypress(struct pci_dev *dev) way to turn this off. The bridge also supports several extended BIOS ranges (disabled after power-up), and some consoles do turn them on. So if we use a large direct-map window, or a large SG - window, we must avoid entire 0xfff00000-0xffffffff region. */ + window, we must avoid the entire 0xfff00000-0xffffffff region. */ else if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA) { - if (__direct_map_base + __direct_map_size >= 0xfff00000) - __direct_map_size = 0xfff00000 - __direct_map_base; - else { +#define DMAPSZ (max_low_pfn << PAGE_SHIFT) /* memory size, not window size */ + if ((__direct_map_base + DMAPSZ - 1) >= 0xfff00000UL) { + __direct_map_size = 0xfff00000UL - __direct_map_base; + printk("%s: adjusting direct map size to 0x%x\n", + __FUNCTION__, __direct_map_size); + } else { struct pci_controller *hose = dev->sysdata; struct pci_iommu_arena *pci = hose->sg_pci; - if (pci && pci->dma_base + pci->size >= 0xfff00000) - pci->size = 0xfff00000 - pci->dma_base; + if (pci && + (pci->dma_base + pci->size - 1) >= 0xfff00000UL) { + pci->size = 0xfff00000UL - pci->dma_base; + printk("%s: adjusting PCI S/G size to 0x%x\n", + __FUNCTION__, pci->size); + } } } } diff --git a/arch/alpha/kernel/pci_impl.h b/arch/alpha/kernel/pci_impl.h index e850b911789d..7139e6c2da71 100644 --- a/arch/alpha/kernel/pci_impl.h +++ b/arch/alpha/kernel/pci_impl.h @@ -52,15 +52,16 @@ struct pci_iommu_arena; #define APECS_AND_LCA_DEFAULT_MEM_BASE ((16+2)*1024*1024) /* - * Because the MCPCIA core logic supports more bits for physical addresses, - * it should allow an expanded range of SPARSE memory addresses. - * However, we do not use them all, in order to avoid the HAE manipulation - * that would be needed. + * Because MCPCIA and T2 core logic support more bits for + * physical addresses, they should allow an expanded range of SPARSE + * memory addresses. However, we do not use them all, in order to + * avoid the HAE manipulation that would be needed. */ #define MCPCIA_DEFAULT_MEM_BASE ((32+2)*1024*1024) +#define T2_DEFAULT_MEM_BASE ((16+1)*1024*1024) /* - * Because CIA and PYXIS and T2 have more bits for physical addresses, + * Because CIA and PYXIS have more bits for physical addresses, * they support an expanded range of SPARSE memory addresses. */ #define DEFAULT_MEM_BASE ((128+16)*1024*1024) @@ -157,8 +158,6 @@ extern struct resource *alloc_resource(void); extern struct pci_iommu_arena *iommu_arena_new(struct pci_controller *, dma_addr_t, unsigned long, unsigned long); -extern long iommu_arena_alloc(struct pci_iommu_arena *arena, long n); - extern const char *const pci_io_names[]; extern const char *const pci_mem_names[]; extern const char pci_hae0_name[]; diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c index f85e4bfb5f52..72f574168a00 100644 --- a/arch/alpha/kernel/pci_iommu.c +++ b/arch/alpha/kernel/pci_iommu.c @@ -30,6 +30,9 @@ #define DEBUG_NODIRECT 0 #define DEBUG_FORCEDAC 0 +/* Most Alphas support 32-bit ISA DMA. Exceptions are XL, Ruffian, + Nautilus, Sable, and Alcor (see asm-alpha/dma.h for details). */ +#define ISA_DMA_MASK (MAX_DMA_ADDRESS - IDENT_ADDR - 1) static inline unsigned long mk_iommu_pte(unsigned long paddr) @@ -129,8 +132,8 @@ iommu_arena_find_pages(struct pci_iommu_arena *arena, long n, long mask) return p; } -long -iommu_arena_alloc(struct pci_iommu_arena *arena, long n) +static long +iommu_arena_alloc(struct pci_iommu_arena *arena, long n, unsigned int align) { unsigned long flags; unsigned long *ptes; @@ -140,7 +143,7 @@ iommu_arena_alloc(struct pci_iommu_arena *arena, long n) /* Search for N empty ptes */ ptes = arena->ptes; - mask = arena->align_entry - 1; + mask = max(align, arena->align_entry) - 1; p = iommu_arena_find_pages(arena, n, mask); if (p < 0) { spin_unlock_irqrestore(&arena->lock, flags); @@ -181,7 +184,7 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size, int dac_allowed) { struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose; - dma_addr_t max_dma = pdev ? pdev->dma_mask : 0x00ffffff; + dma_addr_t max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK; struct pci_iommu_arena *arena; long npages, dma_ofs, i; unsigned long paddr; @@ -232,7 +235,8 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size, arena = hose->sg_isa; npages = calc_npages((paddr & ~PAGE_MASK) + size); - dma_ofs = iommu_arena_alloc(arena, npages); + /* Force allocation to 64KB boundary for all ISA devices. */ + dma_ofs = iommu_arena_alloc(arena, npages, pdev ? 8 : 0); if (dma_ofs < 0) { printk(KERN_WARNING "pci_map_single failed: " "could not allocate dma page tables\n"); @@ -499,7 +503,7 @@ sg_fill(struct scatterlist *leader, struct scatterlist *end, paddr &= ~PAGE_MASK; npages = calc_npages(paddr + size); - dma_ofs = iommu_arena_alloc(arena, npages); + dma_ofs = iommu_arena_alloc(arena, npages, 0); if (dma_ofs < 0) { /* If we attempted a direct map above but failed, die. */ if (leader->dma_address == 0) @@ -588,7 +592,7 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, /* Second, figure out where we're going to map things. */ if (alpha_mv.mv_pci_tbi) { hose = pdev ? pdev->sysdata : pci_isa_hose; - max_dma = pdev ? pdev->dma_mask : 0x00ffffff; + max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK; arena = hose->sg_pci; if (!arena || arena->dma_base + arena->size - 1 > max_dma) arena = hose->sg_isa; @@ -651,7 +655,7 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, return; hose = pdev ? pdev->sysdata : pci_isa_hose; - max_dma = pdev ? pdev->dma_mask : 0x00ffffff; + max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK; arena = hose->sg_pci; if (!arena || arena->dma_base + arena->size - 1 > max_dma) arena = hose->sg_isa; diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index ae466ff90696..b0cd16ef9493 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -261,11 +261,13 @@ alpha_clone(unsigned long clone_flags, unsigned long usp, struct switch_stack * swstack) { struct task_struct *p; + struct pt_regs *u_regs = (struct pt_regs *) (swstack+1); + int *user_tid = (int *)u_regs->r19; + if (!usp) usp = rdusp(); - p = do_fork(clone_flags & ~CLONE_IDLETASK, - usp, (struct pt_regs *) (swstack+1), 0); + p = do_fork(clone_flags & ~CLONE_IDLETASK, usp, u_regs, 0, user_tid); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } @@ -274,7 +276,7 @@ alpha_vfork(struct switch_stack * swstack) { struct task_struct *p; p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), - (struct pt_regs *) (swstack+1), 0); + (struct pt_regs *) (swstack+1), 0, NULL); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h index 746869cb1145..f27e767155c3 100644 --- a/arch/alpha/kernel/proto.h +++ b/arch/alpha/kernel/proto.h @@ -59,7 +59,7 @@ extern void polaris_machine_check(u64, u64, struct pt_regs *); extern struct pci_ops t2_pci_ops; extern void t2_init_arch(void); extern void t2_machine_check(u64, u64, struct pt_regs *); -#define t2_pci_tbi ((void *)0) +extern void t2_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); /* core_titan.c */ extern struct pci_ops titan_pci_ops; diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index b328c280aa95..160a9ba454ae 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -432,7 +432,7 @@ fork_by_hand(void) /* Don't care about the contents of regs since we'll never reschedule the forked task. */ struct pt_regs regs; - return do_fork(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0); + return do_fork(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL); } /* diff --git a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c index 1b17a6a0e364..fa32465ab44f 100644 --- a/arch/alpha/kernel/sys_alcor.c +++ b/arch/alpha/kernel/sys_alcor.c @@ -251,7 +251,7 @@ struct alpha_machine_vector alcor_mv __initmv = { DO_CIA_IO, DO_CIA_BUS, machine_check: cia_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, + max_dma_address: ALPHA_ALCOR_MAX_DMA_ADDRESS, min_io_address: EISA_DEFAULT_IO_BASE, min_mem_address: CIA_DEFAULT_MEM_BASE, diff --git a/arch/alpha/kernel/sys_rx164.c b/arch/alpha/kernel/sys_rx164.c index 36aa640556e8..48214ff70abc 100644 --- a/arch/alpha/kernel/sys_rx164.c +++ b/arch/alpha/kernel/sys_rx164.c @@ -35,16 +35,15 @@ /* Note mask bit is true for ENABLED irqs. */ static unsigned long cached_irq_mask; -/* Bus 0, Device 0. Nothing else matters, since we invoke the - POLARIS routines directly. */ -static struct pci_dev rx164_system; - static inline void rx164_update_irq_hw(unsigned long mask) { - unsigned int temp; - polaris_write_config_dword(&rx164_system, 0x74, mask); - polaris_read_config_dword(&rx164_system, 0x74, &temp); + volatile unsigned int *irq_mask; + + irq_mask = (void *)(POLARIS_DENSE_CONFIG_BASE + 0x74); + *irq_mask = mask; + mb(); + *irq_mask; } static inline void @@ -86,14 +85,14 @@ static struct hw_interrupt_type rx164_irq_type = { static void rx164_device_interrupt(unsigned long vector, struct pt_regs *regs) { - unsigned int temp; unsigned long pld; + volatile unsigned int *dirr; long i; /* Read the interrupt summary register. On Polaris, this is the DIRR register in PCI config space (offset 0x84). */ - polaris_read_config_dword(&rx164_system, 0x84, &temp); - pld = temp; + dirr = (void *)(POLARIS_DENSE_CONFIG_BASE + 0x84); + pld = *dirr; /* * Now for every possible bit set, work through them and call diff --git a/arch/alpha/kernel/sys_sable.c b/arch/alpha/kernel/sys_sable.c index 6255f9cab307..dc35fe7ea125 100644 --- a/arch/alpha/kernel/sys_sable.c +++ b/arch/alpha/kernel/sys_sable.c @@ -290,9 +290,9 @@ struct alpha_machine_vector sable_mv __initmv = { DO_T2_IO, DO_T2_BUS, machine_check: t2_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, + max_dma_address: ALPHA_SABLE_MAX_DMA_ADDRESS, min_io_address: EISA_DEFAULT_IO_BASE, - min_mem_address: DEFAULT_MEM_BASE, + min_mem_address: T2_DEFAULT_MEM_BASE, nr_irqs: 40, device_interrupt: sable_srm_device_interrupt, @@ -322,9 +322,9 @@ struct alpha_machine_vector sable_gamma_mv __initmv = { DO_T2_IO, DO_T2_BUS, machine_check: t2_machine_check, - max_dma_address: ALPHA_MAX_DMA_ADDRESS, + max_dma_address: ALPHA_SABLE_MAX_DMA_ADDRESS, min_io_address: EISA_DEFAULT_IO_BASE, - min_mem_address: DEFAULT_MEM_BASE, + min_mem_address: T2_DEFAULT_MEM_BASE, nr_irqs: 40, device_interrupt: sable_srm_device_interrupt, diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c index 93a569828d70..00ee0c01b001 100644 --- a/arch/alpha/kernel/time.c +++ b/arch/alpha/kernel/time.c @@ -185,8 +185,8 @@ validate_cc_value(unsigned long cc) unsigned int min, max; } cpu_hz[] __initdata = { [EV3_CPU] = { 50000000, 200000000 }, /* guess */ - [EV4_CPU] = { 150000000, 300000000 }, - [LCA4_CPU] = { 150000000, 300000000 }, /* guess */ + [EV4_CPU] = { 100000000, 300000000 }, + [LCA4_CPU] = { 100000000, 300000000 }, /* guess */ [EV45_CPU] = { 200000000, 300000000 }, [EV5_CPU] = { 250000000, 433000000 }, [EV56_CPU] = { 333000000, 667000000 }, @@ -257,12 +257,12 @@ calibrate_cc_with_pic(void) cc = rpcc(); do { - count++; + count+=100; /* by 1 takes too long to timeout from 0 */ } while ((inb(0x61) & 0x20) == 0 && count > 0); cc = rpcc() - cc; /* Error: ECTCNEVERSET or ECPUTOOFAST. */ - if (count <= 1) + if (count <= 100) return 0; /* Error: ECPUTOOSLOW. */ diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index a7542ecac525..c90a631a8720 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -29,6 +29,7 @@ */ static int opDEC_testing = 0; static int opDEC_fix = 0; +static int opDEC_checked = 0; static unsigned long opDEC_test_pc = 0; static void @@ -36,6 +37,8 @@ opDEC_check(void) { unsigned long test_pc; + if (opDEC_checked) return; + lock_kernel(); opDEC_testing = 1; @@ -48,6 +51,7 @@ opDEC_check(void) : ); opDEC_testing = 0; + opDEC_checked = 1; unlock_kernel(); } diff --git a/arch/i386/kernel/init_task.c b/arch/i386/kernel/init_task.c index f652f279b787..4eb40a9582c7 100644 --- a/arch/i386/kernel/init_task.c +++ b/arch/i386/kernel/init_task.c @@ -10,7 +10,7 @@ static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; -static struct signal_struct init_signals = INIT_SIGNALS; +static struct signal_struct init_signals = INIT_SIGNALS(init_signals); struct mm_struct init_mm = INIT_MM(init_mm); /* diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c index 7165d0fd549f..ca5e8fa1b9eb 100644 --- a/arch/i386/pci/fixup.c +++ b/arch/i386/pci/fixup.c @@ -166,6 +166,22 @@ static void __init pci_fixup_via_northbridge_bug(struct pci_dev *d) } } +/* + * For some reasons Intel decided that certain parts of their + * 815, 845 and some other chipsets must look like PCI-to-PCI bridges + * while they are obviously not. The 82801 family (AA, AB, BAM/CAM, + * BA/CA/DB and E) PCI bridges are actually HUB-to-PCI ones, according + * to Intel terminology. These devices do forward all addresses from + * system to PCI bus no matter what are their window settings, so they are + * "transparent" (or subtractive decoding) from programmers point of view. + */ +static void __init pci_fixup_transparent_bridge(struct pci_dev *dev) +{ + if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && + (dev->device & 0xff00) == 0x2400) + dev->transparent = 1; +} + struct pci_fixup pcibios_fixups[] = { { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx }, @@ -183,5 +199,6 @@ struct pci_fixup pcibios_fixups[] = { { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810 }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixup_transparent_bridge }, { 0 } }; diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c index 1d7c7eb5dcf4..65ed61f1344c 100644 --- a/arch/ppc/mm/fault.c +++ b/arch/ppc/mm/fault.c @@ -102,7 +102,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, #endif /* !CONFIG_4xx */ #endif /* CONFIG_XMON || CONFIG_KGDB */ - if (in_interrupt() || mm == NULL) { + if (in_atomic() || mm == NULL) { bad_page_fault(regs, address, SIGSEGV); return; } diff --git a/arch/sparc/mm/fault.c b/arch/sparc/mm/fault.c index 49eccf61be1d..e07d4d1017a9 100644 --- a/arch/sparc/mm/fault.c +++ b/arch/sparc/mm/fault.c @@ -233,7 +233,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_interrupt() || !mm) + if (in_atomic() || !mm) goto no_context; down_read(&mm->mmap_sem); diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c index d1f952e1643b..55df18f1a484 100644 --- a/drivers/acorn/block/mfmhd.c +++ b/drivers/acorn/block/mfmhd.c @@ -193,8 +193,6 @@ struct mfm_info { #define MFM_DRV_INFO mfm_info[raw_cmd.dev] -static struct hd_struct mfm[MFM_MAXDRIVES << 6]; - /* Stuff from the assembly routines */ extern unsigned int hdc63463_baseaddress; /* Controller base address */ extern unsigned int hdc63463_irqpolladdress; /* Address to read to test for int */ @@ -882,6 +880,20 @@ static void mfm_rerequest(void) mfm_request(); } +static struct gendisk mfm_gendisk[2] = { +{ + .major = MAJOR_NR, + .first_minor = 0, + .major_name = "mfma", + .minor_shift = 6, +}, +{ + .major = MAJOR_NR, + .first_minor = 64, + .major_name = "mfmb", + .minor_shift = 6, +}; + static void mfm_request(void) { DBG("mfm_request CURRENT=%p Busy=%d\n", CURRENT, Busy); @@ -895,7 +907,7 @@ static void mfm_request(void) Busy = 1; while (1) { - unsigned int dev, block, nsect; + unsigned int dev, block, nsect, unit; DBG("mfm_request: loop start\n"); sti(); @@ -912,26 +924,26 @@ static void mfm_request(void) DBG("mfm_request: before arg extraction\n"); dev = minor(CURRENT->rq_dev); + unit = dev>>6; block = CURRENT->sector; nsect = CURRENT->nr_sectors; #ifdef DEBUG - /*if ((dev>>6)==1) */ console_printf("mfm_request: raw vals: dev=%d (block=512 bytes) block=%d nblocks=%d\n", dev, block, nsect); + /*if (unit==1) */ console_printf("mfm_request: raw vals: dev=%d (block=512 bytes) block=%d nblocks=%d\n", dev, block, nsect); #endif - if (dev >= (mfm_drives << 6) || - block >= mfm[dev].nr_sects || ((block+nsect) > mfm[dev].nr_sects)) { - if (dev >= (mfm_drives << 6)) + if (unit >= mfm_drives || + block >= get_capacity(mfm_gendisk + unit) || + ((block+nsect) > get_capacity(mfm_gendisk + unit))) { + if (unit >= mfm_drives) printk("mfm: bad minor number: device=%s\n", kdevname(CURRENT->rq_dev)); else - printk("mfm%c: bad access: block=%d, count=%d, nr_sects=%ld\n", (dev >> 6)+'a', - block, nsect, mfm[dev].nr_sects); + printk("mfm%c: bad access: block=%d, count=%d, nr_sects=%ld\n", unit+'a', + block, nsect, get_capacity(mfm_gendisk+unit)); printk("mfm: continue 1\n"); end_request(CURRENT, 0); Busy = 0; continue; } - block += mfm[dev].start_sect; - /* DAG: Linux doesn't cope with this - even though it has an array telling it the hardware block size - silly */ block <<= 1; /* Now in 256 byte sectors */ @@ -1163,18 +1175,9 @@ static int mfm_initdrives(void) static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg) { struct hd_geometry *geo = (struct hd_geometry *) arg; - kdev_t dev; - int device, minor, err; - - if (!inode || !(dev = inode->i_rdev)) - return -EINVAL; - - minor = minor(dev); - - device = DEVICE_NR(minor(inode->i_rdev)), err; + int device = DEVICE_NR(minor(inode->i_rdev)); if (device >= mfm_drives) return -EINVAL; - if (cmd != HDIO_GETGEO) return -EINVAL; if (!arg) @@ -1185,7 +1188,8 @@ static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long a return -EFAULT; if (put_user (mfm_info[device].cylinders, &geo->cylinders)) return -EFAULT; - if (put_user (mfm[minor].start_sect, &geo->start)) + start = get_start_sect(inode->i_bdev); + if (put_user (get_start_sect(inode->i_bdev), &geo->start)) return -EFAULT; return 0; } @@ -1237,27 +1241,10 @@ void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack, if (raw_cmd.dev == drive) mfm_specify (); mfm_geometry (drive); - mfm[drive << 6].start_sect = 0; - mfm[drive << 6].nr_sects = mfm_info[drive].cylinders * mfm_info[drive].heads * mfm_info[drive].sectors / 2; + set_capacity(&mfm_gendisk[drive], mfm_info[drive].cylinders * mfm_info[drive].heads * mfm_info[drive].sectors / 2); } } -static struct gendisk mfm_gendisk[2] = { -{ - .major = MAJOR_NR, - .first_minor = 0, - .major_name = "mfma", - .minor_shift = 6, - .part = mfm, -}, -{ - .major = MAJOR_NR, - .first_minor = 64, - .major_name = "mfmb", - .minor_shift = 6, - .part = mfm + 64, -}; - static struct block_device_operations mfm_fops = { .owner = THIS_MODULE, @@ -1280,7 +1267,6 @@ static void mfm_geninit (void) outw(0x80, mfm_irqenable); /* Required to enable IRQs from MFM podule */ for (i = 0; i < mfm_drives; i++) { - mfm_gendisk[i].nr_real = 1; add_gendisk(mfm_gendisk + i); mfm_geometry (i); register_disk(mfm_gendisk + i, mk_kdev(MAJOR_NR,i<<6), 1<<6, diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 4256cbb35e78..989f13e46e8f 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -1968,12 +1968,10 @@ static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller) struct gendisk *disk = &Controller->disks[n]; memset(disk, 0, sizeof(struct gendisk)); sprintf(names + 9 * n, "rd/c%dd%d", Controller->ControllerNumber, n); - disk->part = Controller->DiskPartitions + (n<<DAC960_MaxPartitionsBits); disk->major = MajorNumber; disk->first_minor = n << DAC960_MaxPartitionsBits; disk->major_name = names + 9 * n; disk->minor_shift = DAC960_MaxPartitionsBits; - disk->nr_real = 1; disk->fops = &DAC960_BlockDeviceOperations; add_gendisk(disk); } @@ -2034,10 +2032,9 @@ static long disk_size(DAC960_Controller_T *Controller, int disk) static void DAC960_ComputeGenericDiskInfo(DAC960_Controller_T *Controller) { - struct gendisk *disks = Controller->disks; int disk; for (disk = 0; disk < DAC960_MaxLogicalDrives; disk++) - disks->part[0].nr_sects = disk_size(Controller, disk); + set_capacity(Controller->disks + disk, disk_size(Controller, disk)); } static int DAC960_revalidate(kdev_t dev) @@ -2045,7 +2042,7 @@ static int DAC960_revalidate(kdev_t dev) int ctlr = DAC960_ControllerNumber(dev); int disk = DAC960_LogicalDriveNumber(dev); DAC960_Controller_T *p = DAC960_Controllers[ctlr]; - p->disks[disk].part[0].nr_sects = disk_size(p, disk); + set_capacity(&p->disks[disk], disk_size(p, disk)); return 0; } @@ -5277,7 +5274,7 @@ static int DAC960_Open(Inode_T *Inode, File_T *File) DAC960_KernelDevice(Controller->ControllerNumber, LogicalDriveNumber, 0), DAC960_MaxPartitions, &DAC960_BlockDeviceOperations, size); } - if (Controller->disks[LogicalDriveNumber].part[0].nr_sects == 0) + if (!get_capacity(&Controller->disks[LogicalDriveNumber])) return -ENXIO; /* Increment Controller and Logical Drive Usage Counts. diff --git a/drivers/block/DAC960.h b/drivers/block/DAC960.h index 53b4bcb47d5a..33b2822520e3 100644 --- a/drivers/block/DAC960.h +++ b/drivers/block/DAC960.h @@ -2196,7 +2196,6 @@ typedef struct file File_T; typedef struct block_device_operations BlockDeviceOperations_T; typedef struct completion Completion_T; typedef struct hd_geometry DiskGeometry_T; -typedef struct hd_struct DiskPartition_T; typedef struct inode Inode_T; typedef struct inode_operations InodeOperations_T; typedef kdev_t KernelDevice_T; @@ -2472,7 +2471,6 @@ typedef struct DAC960_Controller boolean LogicalDriveFoundDuringScan[DAC960_MaxLogicalDrives]; } V2; } FW; - DiskPartition_T DiskPartitions[DAC960_MinorCount]; unsigned char ProgressBuffer[DAC960_ProgressBufferSize]; unsigned char UserStatusBuffer[DAC960_UserMessageSize]; } diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c index ff0480293480..3313f7cb0a3c 100644 --- a/drivers/block/acsi.c +++ b/drivers/block/acsi.c @@ -245,7 +245,6 @@ char *acsi_buffer; unsigned long phys_acsi_buffer; static int NDevices; -static struct hd_struct acsi_part[MAX_DEV<<4]; static char acsi_names[MAX_DEV*4]; static int access_count[MAX_DEV]; @@ -783,7 +782,7 @@ static void read_intr( void ) status = acsi_getstatus(); if (status != 0) { - int dev = minor(CURRENT->rq_dev); + int dev = DEVICE_NR(CURRENT->rq_dev); printk( KERN_ERR "ad%c: ", dev+'a' ); if (!acsi_reqsense( acsi_buffer, acsi_info[dev].target, acsi_info[dev].lun)) @@ -814,7 +813,7 @@ static void write_intr(void) status = acsi_getstatus(); if (status != 0) { - int dev = minor(CURRENT->rq_dev); + int dev = DEVICE_NR(CURRENT->rq_dev); printk( KERN_ERR "ad%c: ", dev+'a' ); if (!acsi_reqsense( acsi_buffer, acsi_info[dev].target, acsi_info[dev].lun)) @@ -973,15 +972,15 @@ static void redo_acsi_request( void ) panic(DEVICE_NAME ": block not locked"); } - dev = minor(CURRENT->rq_dev); + dev = DEVICE_NR(CURRENT->rq_dev); block = CURRENT->sector; if (dev >= NDevices || - block+CURRENT->nr_sectors >= acsi_part[dev].nr_sects) { + block+CURRENT->nr_sectors >= get_capacity(acsi_gendisk + dev)) { #ifdef DEBUG printk( "ad%c: attempted access for blocks %d...%ld past end of device at block %ld.\n", dev+'a', block, block + CURRENT->nr_sectors - 1, - acsi_part[dev].nr_sects); + get_capacity(acsi_gendisk + dev)); #endif end_request(CURRENT, 0); goto repeat; @@ -1088,11 +1087,7 @@ static void redo_acsi_request( void ) static int acsi_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg ) { - dev_t dev; - - if (!inode) - return -EINVAL; - dev = minor(inode->i_rdev); + int dev = DEVICE_NR(inode->i_rdev); if (dev >= NDevices) return -EINVAL; switch (cmd) { @@ -1140,7 +1135,7 @@ static int acsi_open( struct inode * inode, struct file * filp ) int device; struct acsi_info_struct *aip; - device = minor(inode->i_rdev); + device = DEVICE_NR(inode->i_rdev); if (device >= NDevices) return -ENXIO; aip = &acsi_info[device]; @@ -1176,7 +1171,7 @@ static int acsi_open( struct inode * inode, struct file * filp ) static int acsi_release( struct inode * inode, struct file * file ) { - int device = minor(inode->i_rdev); + int device = DEVICE_NR(inode->i_rdev); if (--access_count[device] == 0 && acsi_info[device].removable) acsi_prevent_removal(device, 0); return( 0 ); @@ -1204,7 +1199,7 @@ static void acsi_prevent_removal(int device, int flag) static int acsi_media_change (kdev_t dev) { - int device = minor(dev); + int device = DEVICE_NR(dev); struct acsi_info_struct *aip; aip = &acsi_info[device]; @@ -1702,9 +1697,7 @@ static void acsi_geninit(void) disk->first_minor = i << 4; disk->major_name = acsi_names + 4*i; disk->minor_shift = (acsi_info[i].type==HARDDISK)?4:0; - disk->part = acsi_part + (i<<4); disk->fops = &acsi_fops; - disk->nr_real = 1; add_gendisk(disk); register_disk(disk, mk_kdev(disk->major, disk->first_minor), 1<<disk->minor_shift, @@ -1808,7 +1801,7 @@ void cleanup_module(void) static int acsi_revalidate(kdev_t dev) { - int unit = DEVICE_NR(minor(dev)); + int unit = DEVICE_NR(dev); struct acsi_info_struct *aip = &acsi_info[unit]; stdma_lock( NULL, NULL ); if (acsi_devinit(aip) != DEV_SUPPORTED) { @@ -1822,6 +1815,6 @@ static int acsi_revalidate(kdev_t dev) ENABLE_IRQ(); stdma_release(); - acsi_part[minor(dev)].nr_sects = aip->size; + set_capacity(acsi_gendisk + unit, aip->size); return 0; } diff --git a/drivers/block/blkpg.c b/drivers/block/blkpg.c index 1d13a84a9919..941d1051d894 100644 --- a/drivers/block/blkpg.c +++ b/drivers/block/blkpg.c @@ -71,7 +71,6 @@ int add_partition(struct block_device *bdev, struct blkpg_partition *p) long pstart, plength; int i; kdev_t dev = to_kdev_t(bdev->bd_dev); - struct hd_struct *part; /* convert bytes to sectors, check for fit in a hd_struct */ ppstart = (p->start >> 9); @@ -86,7 +85,6 @@ int add_partition(struct block_device *bdev, struct blkpg_partition *p) g = get_gendisk(dev); if (!g) return -ENXIO; - part = g->part + minor(dev) - g->first_minor; /* existing drive? */ @@ -97,19 +95,19 @@ int add_partition(struct block_device *bdev, struct blkpg_partition *p) return -EINVAL; /* partition number in use? */ - if (part[p->pno].nr_sects != 0) + if (g->part[p->pno - 1].nr_sects != 0) return -EBUSY; /* overlap? */ - for (i = 1; i < (1<<g->minor_shift); i++) - if (!(pstart+plength <= part[i].start_sect || - pstart >= part[i].start_sect + part[i].nr_sects)) + for (i = 0; i < (1<<g->minor_shift) - 1; i++) + if (!(pstart+plength <= g->part[i].start_sect || + pstart >= g->part[i].start_sect + g->part[i].nr_sects)) return -EBUSY; /* all seems OK */ - part[p->pno].start_sect = pstart; - part[p->pno].nr_sects = plength; - devfs_register_partitions (g, minor(dev), 0); + g->part[p->pno - 1].start_sect = pstart; + g->part[p->pno - 1].nr_sects = plength; + update_partition(g, p->pno); return 0; } @@ -128,22 +126,19 @@ int del_partition(struct block_device *bdev, struct blkpg_partition *p) kdev_t dev = to_kdev_t(bdev->bd_dev); struct gendisk *g; struct block_device *bdevp; - struct hd_struct *part; int holder; /* find the drive major */ g = get_gendisk(dev); if (!g) return -ENXIO; - part = g->part + minor(dev) - g->first_minor; - if (bdev != bdev->bd_contains) return -EINVAL; if (p->pno <= 0 || p->pno >= (1 << g->minor_shift)) return -EINVAL; /* existing drive and partition? */ - if (part[p->pno].nr_sects == 0) + if (g->part[p->pno - 1].nr_sects == 0) return -ENXIO; /* partition in use? Incomplete check for now. */ @@ -159,9 +154,9 @@ int del_partition(struct block_device *bdev, struct blkpg_partition *p) fsync_bdev(bdevp); invalidate_bdev(bdevp, 0); - part[p->pno].start_sect = 0; - part[p->pno].nr_sects = 0; - devfs_register_partitions (g, minor(dev), 0); + g->part[p->pno - 1].start_sect = 0; + g->part[p->pno - 1].nr_sects = 0; + update_partition(g, p->pno); bd_release(bdevp); bdput(bdevp); diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index db3d25ebfd35..0b8fb9a5c7a5 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -407,8 +407,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, driver_geo.sectors = 0x3f; driver_geo.cylinders = hba[ctlr]->drv[dsk].nr_blocks / (0xff*0x3f); } - driver_geo.start= - hba[ctlr]->hd[minor(inode->i_rdev)].start_sect; + driver_geo.start= get_start_sect(inode->i_bdev); if (copy_to_user((void *) arg, &driver_geo, sizeof( struct hd_geometry))) return -EFAULT; @@ -705,7 +704,7 @@ static int cciss_revalidate(kdev_t dev) int ctlr = major(dev) - MAJOR_NR; int target = minor(dev) >> NWD_SHIFT; struct gendisk *disk = &hba[ctlr]->gendisk[target]; - disk->part[0].nr_sects = hba[ctlr]->drv[target].nr_blocks; + set_capacity(disk, hba[ctlr]->drv[target].nr_blocks); return 0; } @@ -742,7 +741,6 @@ static int revalidate_allvol(kdev_t dev) for(i=0; i< NWD; i++) { struct gendisk *disk = &hba[ctlr]->gendisk[i]; if (disk->major_name) { - wipe_partitions(mk_kdev(disk->major, disk->first_minor)); del_gendisk(disk); disk->major_name = NULL; } @@ -752,7 +750,6 @@ static int revalidate_allvol(kdev_t dev) * Set the partition and block size structures for all volumes * on this controller to zero. We will reread all of this data */ - memset(hba[ctlr]->hd, 0, sizeof(struct hd_struct) * 256); memset(hba[ctlr]->drv, 0, sizeof(drive_info_struct) * CISS_MAX_LUN); /* @@ -802,7 +799,6 @@ static int deregister_disk(int ctlr, int logvol) /* invalidate the devices and deregister the disk */ if (disk->major_name) { - wipe_partitions(mk_kdev(disk->major, disk->first_minor)); del_gendisk(disk); disk->major_name = NULL; } @@ -2448,8 +2444,6 @@ static int __init cciss_init_one(struct pci_dev *pdev, disk->first_minor = j << NWD_SHIFT; disk->major_name = NULL; disk->minor_shift = NWD_SHIFT; - disk->part = hba[i]->hd + (j << NWD_SHIFT); - disk->nr_real = 1; if( !(drv->nr_blocks)) continue; (BLK_DEFAULT_QUEUE(MAJOR_NR + i))->hardsect_size = drv->block_size; diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index 7192717a23fe..1baed4acef84 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h @@ -83,9 +83,6 @@ struct ctlr_info // Disk structures we need to pass back struct gendisk gendisk[NWD]; char names[12 * NWD]; - // indexed by minor numbers - struct hd_struct hd[256]; - int sizes[256]; #ifdef CONFIG_CISS_SCSI_TAPE void *scsi_ctlr; /* ptr to structure containing scsi related stuff */ #endif diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index b9dfeb902e3c..aec445236fa0 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -75,7 +75,6 @@ MODULE_LICENSE("GPL"); static int nr_ctlr; static ctlr_info_t *hba[MAX_CTLR]; -static devfs_handle_t de_arr[MAX_CTLR][NWD]; static int eisa[8]; @@ -103,7 +102,6 @@ static struct board_type products[] = { { 0x40580E11, "Smart Array 431", &smart4_access }, }; -static struct hd_struct * ida; static char *ida_names; static struct gendisk ida_gendisk[MAX_CTLR * NWD]; @@ -321,7 +319,6 @@ void cleanup_module(void) } devfs_find_and_unregister(NULL, "ida", 0, 0, 0, 0); remove_proc_entry("cpqarray", proc_root_driver); - kfree(ida); kfree(ida_names); } #endif /* MODULE */ @@ -347,15 +344,12 @@ int __init cpqarray_init(void) printk("Found %d controller(s)\n", nr_ctlr); /* allocate space for disk structs */ - ida = kmalloc(sizeof(struct hd_struct)*nr_ctlr*NWD*16, GFP_KERNEL); ida_names = kmalloc(nr_ctlr*NWD*10, GFP_KERNEL); - if (!ida || !ida_names) { + if (!ida_names) { printk( KERN_ERR "cpqarray: out of memory"); - kfree(ida); kfree(ida_names); return(num_cntlrs_reg); } - memset(ida, 0, sizeof(struct hd_struct)*nr_ctlr*NWD*16); /* * register block devices * Find disks and fill in structs @@ -408,7 +402,6 @@ int __init cpqarray_init(void) if (num_cntlrs_reg == 0) { - kfree(ida); kfree(ida_names); } return(num_cntlrs_reg); @@ -450,9 +443,7 @@ int __init cpqarray_init(void) disk->major = MAJOR_NR + i; disk->first_minor = j<<NWD_SHIFT; disk->minor_shift = NWD_SHIFT; - disk->part = ida + i*256 + (j<<NWD_SHIFT); - disk->nr_real = 1; - disk->de_arr = &de_arr[i][j]; + disk->flags = GENHD_FL_DEVFS; disk->fops = &ida_fops; if (!drv->nr_blks) continue; @@ -1461,11 +1452,9 @@ static int revalidate_allvol(kdev_t dev) struct gendisk *disk = ida_gendisk + ctlr*NWD + i; if (!disk->major_name) continue; - wipe_partitions(mk_kdev(disk->major, disk->first_minor)); del_gendisk(disk); disk->major_name = NULL; } - memset(ida+(ctlr*256), 0, sizeof(struct hd_struct)*NWD*16); memset(hba[ctlr]->drv, 0, sizeof(drv_info_t)*NWD); /* @@ -1500,7 +1489,7 @@ static int ida_revalidate(kdev_t dev) int ctlr = major(dev) - MAJOR_NR; int target = DEVICE_NR(dev); struct gendisk *gdev = &ida_gendisk[ctlr*NWD+target]; - gdev->part[minor(dev)].nr_sects = hba[ctlr]->drv[target].nr_blks; + set_capacity(gdev, hba[ctlr]->drv[target].nr_blks); return 0; } @@ -1667,6 +1656,7 @@ static void getgeometry(int ctlr) (log_index < id_ctlr_buf->nr_drvs) && (log_unit < NWD); log_unit++) { + struct gendisk *disk = ida_gendisk + ctlr * NWD + log_unit; size = sizeof(sense_log_drv_stat_t); @@ -1731,13 +1721,10 @@ static void getgeometry(int ctlr) return; } - if (!de_arr[ctlr][log_unit]) { + if (!disk->de) { char txt[16]; - - sprintf(txt, "ida/c%dd%d", ctlr, - log_unit); - de_arr[ctlr][log_unit] = - devfs_mk_dir(NULL, txt, NULL); + sprintf(txt,"ida/c%dd%d",ctlr,log_unit); + disk->de = devfs_mk_dir(NULL,txt,NULL); } info_p->phys_drives = sense_config_buf->ctlr_phys_drv; diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index e17207282c98..51b77476e95f 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c @@ -23,6 +23,7 @@ #include <linux/init.h> #include <linux/spinlock.h> #include <linux/seq_file.h> +#include <linux/slab.h> static rwlock_t gendisk_lock; @@ -43,6 +44,19 @@ void add_gendisk(struct gendisk *gp) { struct gendisk *sgp; + struct hd_struct *p = NULL; + + if (gp->minor_shift) { + size_t size = sizeof(struct hd_struct)*((1<<gp->minor_shift)-1); + p = kmalloc(size, GFP_KERNEL); + if (!p) { + printk(KERN_ERR "out of memory; no partitions for %s\n", + gp->major_name); + gp->minor_shift = 0; + } else + memset(p, 0, size); + } + gp->part = p; write_lock(&gendisk_lock); @@ -67,32 +81,20 @@ out: } EXPORT_SYMBOL(add_gendisk); +EXPORT_SYMBOL(del_gendisk); - -/** - * del_gendisk - remove partitioning information from kernel list - * @gp: per-device partitioning information - * - * This function unregisters the partitioning information in @gp - * with the kernel. - */ -void -del_gendisk(struct gendisk *gp) +void unlink_gendisk(struct gendisk *disk) { - struct gendisk **gpp; - + struct gendisk **p; write_lock(&gendisk_lock); - for (gpp = &gendisk_head; *gpp; gpp = &((*gpp)->next)) - if (*gpp == gp) + for (p = &gendisk_head; *p; p = &((*p)->next)) + if (*p == disk) break; - if (*gpp) - *gpp = (*gpp)->next; + if (*p) + *p = (*p)->next; write_unlock(&gendisk_lock); } -EXPORT_SYMBOL(del_gendisk); - - /** * get_gendisk - get partitioning information for a given device * @dev: device to get partitioning information for @@ -160,14 +162,17 @@ static int show_partition(struct seq_file *part, void *v) seq_puts(part, "major minor #blocks name\n\n"); /* show the full disk and all non-0 size partitions of it */ - for (n = 0; n < (sgp->nr_real << sgp->minor_shift); n++) { - int minormask = (1<<sgp->minor_shift) - 1; - if ((n & minormask) && sgp->part[n].nr_sects == 0) + seq_printf(part, "%4d %4d %10ld %s\n", + sgp->major, sgp->first_minor, + get_capacity(sgp) >> 1, + disk_name(sgp, 0, buf)); + for (n = 0; n < (1<<sgp->minor_shift) - 1; n++) { + if (sgp->part[n].nr_sects == 0) continue; seq_printf(part, "%4d %4d %10ld %s\n", - sgp->major, n + sgp->first_minor, + sgp->major, n + 1 + sgp->first_minor, sgp->part[n].nr_sects >> 1 , - disk_name(sgp, n + sgp->first_minor, buf)); + disk_name(sgp, n + 1, buf)); } return 0; diff --git a/drivers/block/loop.c b/drivers/block/loop.c index a66f21b8e348..318b1aa0092d 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -210,8 +210,7 @@ do_lo_send(struct loop_device *lo, struct bio_vec *bvec, int bsize, loff_t pos) goto fail; if (aops->prepare_write(file, page, offset, offset+size)) goto unlock; - kaddr = page_address(page); - flush_dcache_page(page); + kaddr = kmap(page); transfer_result = lo_do_transfer(lo, WRITE, kaddr + offset, data, size, IV); if (transfer_result) { /* @@ -221,6 +220,8 @@ do_lo_send(struct loop_device *lo, struct bio_vec *bvec, int bsize, loff_t pos) printk(KERN_ERR "loop: transfer error block %ld\n", index); memset(kaddr + offset, 0, size); } + flush_dcache_page(page); + kunmap(page); if (aops->commit_write(file, page, offset, offset+size)) goto unlock; if (transfer_result) diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c index 25273d4ba1b8..de78fa2198b8 100644 --- a/drivers/block/paride/pcd.c +++ b/drivers/block/paride/pcd.c @@ -111,28 +111,21 @@ */ -static int verbose = 0; -static int major = PCD_MAJOR; -static char *name = PCD_NAME; -static int nice = 0; -static int disable = 0; - -static int drive0[6] = {0,0,0,-1,-1,-1}; -static int drive1[6] = {0,0,0,-1,-1,-1}; -static int drive2[6] = {0,0,0,-1,-1,-1}; -static int drive3[6] = {0,0,0,-1,-1,-1}; - -static int (*drives[4])[6] = {&drive0,&drive1,&drive2,&drive3}; +static int verbose = 0; +static int major = PCD_MAJOR; +static char *name = PCD_NAME; +static int nice = 0; +static int disable = 0; + +static int drive0[6] = { 0, 0, 0, -1, -1, -1 }; +static int drive1[6] = { 0, 0, 0, -1, -1, -1 }; +static int drive2[6] = { 0, 0, 0, -1, -1, -1 }; +static int drive3[6] = { 0, 0, 0, -1, -1, -1 }; + +static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3}; static int pcd_drive_count; -#define D_PRT 0 -#define D_PRO 1 -#define D_UNI 2 -#define D_MOD 3 -#define D_SLV 4 -#define D_DLY 5 - -#define DU (*drives[unit]) +enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY}; /* end of parameters */ @@ -153,28 +146,30 @@ static spinlock_t pcd_lock; #include "setup.h" -static STT pcd_stt[6] = {{"drive0",6,drive0}, - {"drive1",6,drive1}, - {"drive2",6,drive2}, - {"drive3",6,drive3}, - {"disable",1,&disable}, - {"nice",1,&nice}}; - -void pcd_setup( char *str, int *ints) +static STT pcd_stt[6] = { + {"drive0", 6, drive0}, + {"drive1", 6, drive1}, + {"drive2", 6, drive2}, + {"drive3", 6, drive3}, + {"disable", 1, &disable}, + {"nice", 1, &nice} +}; -{ generic_setup(pcd_stt,6,str); +void pcd_setup(char *str, int *ints) +{ + generic_setup(pcd_stt, 6, str); } #endif -MODULE_PARM(verbose,"i"); -MODULE_PARM(major,"i"); -MODULE_PARM(name,"s"); -MODULE_PARM(nice,"i"); -MODULE_PARM(drive0,"1-6i"); -MODULE_PARM(drive1,"1-6i"); -MODULE_PARM(drive2,"1-6i"); -MODULE_PARM(drive3,"1-6i"); +MODULE_PARM(verbose, "i"); +MODULE_PARM(major, "i"); +MODULE_PARM(name, "s"); +MODULE_PARM(nice, "i"); +MODULE_PARM(drive0, "1-6i"); +MODULE_PARM(drive1, "1-6i"); +MODULE_PARM(drive2, "1-6i"); +MODULE_PARM(drive3, "1-6i"); #include "paride.h" @@ -189,10 +184,10 @@ MODULE_PARM(drive3,"1-6i"); #include "pseudo.h" #define PCD_RETRIES 5 -#define PCD_TMO 800 /* timeout in jiffies */ -#define PCD_DELAY 50 /* spin delay in uS */ -#define PCD_READY_TMO 20 /* in seconds */ -#define PCD_RESET_TMO 100 /* in tenths of a second */ +#define PCD_TMO 800 /* timeout in jiffies */ +#define PCD_DELAY 50 /* spin delay in uS */ +#define PCD_READY_TMO 20 /* in seconds */ +#define PCD_RESET_TMO 100 /* in tenths of a second */ #define PCD_SPIN (1000000*PCD_TMO)/(HZ*PCD_DELAY) @@ -208,127 +203,108 @@ static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr); static int pcd_tray_move(struct cdrom_device_info *cdi, int position); static int pcd_lock_door(struct cdrom_device_info *cdi, int lock); static int pcd_drive_reset(struct cdrom_device_info *cdi); -static int pcd_get_mcn (struct cdrom_device_info *cdi, struct cdrom_mcn *mcn); +static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn); static int pcd_audio_ioctl(struct cdrom_device_info *cdi, - unsigned int cmd, void *arg); + unsigned int cmd, void *arg); static int pcd_packet(struct cdrom_device_info *cdi, - struct cdrom_generic_command *cgc); + struct cdrom_generic_command *cgc); -static int pcd_detect(void); -static void pcd_probe_capabilities(void); -static void do_pcd_read_drq(void); -static void do_pcd_request(request_queue_t * q); -static void do_pcd_read(void); +static int pcd_detect(void); +static void pcd_probe_capabilities(void); +static void do_pcd_read_drq(void); +static void do_pcd_request(request_queue_t * q); +static void do_pcd_read(void); struct pcd_unit { - struct pi_adapter pia; /* interface to paride layer */ + struct pi_adapter pia; /* interface to paride layer */ struct pi_adapter *pi; - int drive; /* master/slave */ - int last_sense; /* result of last request sense */ - int changed; /* media change seen */ - int present; /* does this unit exist ? */ - char *name; /* pcd0, pcd1, etc */ + int drive; /* master/slave */ + int last_sense; /* result of last request sense */ + int changed; /* media change seen */ + int present; /* does this unit exist ? */ + char *name; /* pcd0, pcd1, etc */ struct cdrom_device_info info; /* uniform cdrom interface */ - }; +}; struct pcd_unit pcd[PCD_UNITS]; -/* 'unit' must be defined in all functions - either as a local or a param */ - -#define PCD pcd[unit] -#define PI PCD.pi - static char pcd_scratch[64]; -static char pcd_buffer[2048]; /* raw block buffer */ -static int pcd_bufblk = -1; /* block in buffer, in CD units, - -1 for nothing there. See also - pd_unit. - */ +static char pcd_buffer[2048]; /* raw block buffer */ +static int pcd_bufblk = -1; /* block in buffer, in CD units, + -1 for nothing there. See also + pd_unit. + */ /* the variables below are used mainly in the I/O request engine, which processes only one request at a time. */ -static int pcd_unit = -1; /* unit of current request & bufblk */ -static int pcd_retries; /* retries on current request */ -static int pcd_busy = 0; /* request being processed ? */ -static int pcd_sector; /* address of next requested sector */ -static int pcd_count; /* number of blocks still to do */ -static char * pcd_buf; /* buffer for request in progress */ +static struct pcd_unit *pcd_current; /* current request's drive */ +static int pcd_retries; /* retries on current request */ +static int pcd_busy; /* request being processed ? */ +static int pcd_sector; /* address of next requested sector */ +static int pcd_count; /* number of blocks still to do */ +static char *pcd_buf; /* buffer for request in progress */ -static int pcd_warned = 0; /* Have we logged a phase warning ? */ +static int pcd_warned; /* Have we logged a phase warning ? */ /* kernel glue structures */ static struct block_device_operations pcd_bdops = { - owner: THIS_MODULE, - open: cdrom_open, - release: cdrom_release, - ioctl: cdrom_ioctl, - check_media_change: cdrom_media_changed, + .owner = THIS_MODULE, + .open = cdrom_open, + .release = cdrom_release, + .ioctl = cdrom_ioctl, + .check_media_change = cdrom_media_changed, }; static struct cdrom_device_ops pcd_dops = { - pcd_open, - pcd_release, - pcd_drive_status, - pcd_media_changed, - pcd_tray_move, - pcd_lock_door, - 0, /* select speed */ - 0, /* select disk */ - 0, /* get last session */ - pcd_get_mcn, - pcd_drive_reset, - pcd_audio_ioctl, - 0, /* dev_ioctl */ - CDC_CLOSE_TRAY | - CDC_OPEN_TRAY | - CDC_LOCK | - CDC_MCN | - CDC_MEDIA_CHANGED | - CDC_RESET | - CDC_PLAY_AUDIO | - CDC_GENERIC_PACKET | - CDC_CD_R | - CDC_CD_RW, - 0, - pcd_packet, + .open = pcd_open, + .release = pcd_release, + .drive_status = pcd_drive_status, + .media_changed = pcd_media_changed, + .tray_move = pcd_tray_move, + .lock_door = pcd_lock_door, + .get_mcn = pcd_get_mcn, + .reset = pcd_drive_reset, + .audio_ioctl = pcd_audio_ioctl, + .generic_packet = pcd_packet, + .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | + CDC_MCN | CDC_MEDIA_CHANGED | CDC_RESET | + CDC_PLAY_AUDIO | CDC_GENERIC_PACKET | CDC_CD_R | + CDC_CD_RW, }; -static void pcd_init_units( void ) - -{ int unit, j; +static void pcd_init_units(void) +{ + struct pcd_unit *cd; + int unit; - pcd_drive_count = 0; - for (unit=0;unit<PCD_UNITS;unit++) { - PCD.pi = & PCD.pia; - PCD.present = 0; - PCD.last_sense = 0; - PCD.changed = 1; - PCD.drive = DU[D_SLV]; - if (DU[D_PRT]) pcd_drive_count++; - - j = 0; - while ((j < (sizeof(PCD.info.name)-2)) && - (PCD.info.name[j]=name[j])) j++; - PCD.info.name[j++] = '0' + unit; - PCD.info.name[j] = 0; - PCD.name = &PCD.info.name[0]; - - PCD.info.ops = &pcd_dops; - PCD.info.handle = NULL; - PCD.info.dev = mk_kdev(major,unit); - PCD.info.speed = 0; - PCD.info.capacity = 1; - PCD.info.mask = 0; - } + pcd_drive_count = 0; + for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { + cd->pi = &cd->pia; + cd->present = 0; + cd->last_sense = 0; + cd->changed = 1; + cd->drive = (*drives[unit])[D_SLV]; + if ((*drives[unit])[D_PRT]) + pcd_drive_count++; + + cd->name = &cd->info.name[0]; + snprintf(cd->name, sizeof(cd->info.name), "%s%d", name, unit); + cd->info.ops = &pcd_dops; + cd->info.handle = cd; + cd->info.dev = mk_kdev(major, unit); + cd->info.speed = 0; + cd->info.capacity = 1; + cd->info.mask = 0; + } } static int pcd_open(struct cdrom_device_info *cdi, int purpose) { - int unit = DEVICE_NR(cdi->dev); - if ((unit >= PCD_UNITS) || (!PCD.present)) + struct pcd_unit *cd = cdi->handle; + if (!cd->present) return -ENODEV; return 0; } @@ -337,554 +313,598 @@ static void pcd_release(struct cdrom_device_info *cdi) { } -#define WR(c,r,v) pi_write_regr(PI,c,r,v) -#define RR(c,r) (pi_read_regr(PI,c,r)) +static inline int status_reg(struct pcd_unit *cd) +{ + return pi_read_regr(cd->pi, 1, 6); +} + +static inline int read_reg(struct pcd_unit *cd, int reg) +{ + return pi_read_regr(cd->pi, 0, reg); +} -static int pcd_wait( int unit, int go, int stop, char * fun, char * msg ) +static inline void write_reg(struct pcd_unit *cd, int reg, int val) +{ + pi_write_regr(cd->pi, 0, reg, val); +} -{ int j, r, e, s, p; +static int pcd_wait(struct pcd_unit *cd, int go, int stop, char *fun, char *msg) +{ + int j, r, e, s, p; j = 0; - while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(j++<PCD_SPIN)) + while ((((r = status_reg(cd)) & go) || (stop && (!(r & stop)))) + && (j++ < PCD_SPIN)) udelay(PCD_DELAY); - if ((r&(IDE_ERR&stop))||(j>=PCD_SPIN)) { - s = RR(0,7); - e = RR(0,1); - p = RR(0,2); - if (j >= PCD_SPIN) e |= 0x100; - if (fun) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x" - " loop=%d phase=%d\n", - PCD.name,fun,msg,r,s,e,j,p); - return (s<<8)+r; + if ((r & (IDE_ERR & stop)) || (j >= PCD_SPIN)) { + s = read_reg(cd, 7); + e = read_reg(cd, 1); + p = read_reg(cd, 2); + if (j >= PCD_SPIN) + e |= 0x100; + if (fun) + printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x" + " loop=%d phase=%d\n", + cd->name, fun, msg, r, s, e, j, p); + return (s << 8) + r; } return 0; } -static int pcd_command( int unit, char * cmd, int dlen, char * fun ) - -{ pi_connect(PI); +static int pcd_command(struct pcd_unit *cd, char *cmd, int dlen, char *fun) +{ + pi_connect(cd->pi); - WR(0,6,0xa0 + 0x10*PCD.drive); + write_reg(cd, 6, 0xa0 + 0x10 * cd->drive); - if (pcd_wait(unit,IDE_BUSY|IDE_DRQ,0,fun,"before command")) { - pi_disconnect(PI); + if (pcd_wait(cd, IDE_BUSY | IDE_DRQ, 0, fun, "before command")) { + pi_disconnect(cd->pi); return -1; } - WR(0,4,dlen % 256); - WR(0,5,dlen / 256); - WR(0,7,0xa0); /* ATAPI packet command */ + write_reg(cd, 4, dlen % 256); + write_reg(cd, 5, dlen / 256); + write_reg(cd, 7, 0xa0); /* ATAPI packet command */ - if (pcd_wait(unit,IDE_BUSY,IDE_DRQ,fun,"command DRQ")) { - pi_disconnect(PI); + if (pcd_wait(cd, IDE_BUSY, IDE_DRQ, fun, "command DRQ")) { + pi_disconnect(cd->pi); return -1; } - if (RR(0,2) != 1) { - printk("%s: %s: command phase error\n",PCD.name,fun); - pi_disconnect(PI); - return -1; - } + if (read_reg(cd, 2) != 1) { + printk("%s: %s: command phase error\n", cd->name, fun); + pi_disconnect(cd->pi); + return -1; + } - pi_write_block(PI,cmd,12); + pi_write_block(cd->pi, cmd, 12); return 0; } -static int pcd_completion( int unit, char * buf, char * fun ) - -{ int r, d, p, n, k, j; - - r = -1; k = 0; j = 0; - - if (!pcd_wait(unit,IDE_BUSY,IDE_DRQ|IDE_READY|IDE_ERR, - fun,"completion")) { - r = 0; - while (RR(0,7)&IDE_DRQ) { - d = (RR(0,4)+256*RR(0,5)); - n = ((d+3)&0xfffc); - p = RR(0,2)&3; - - if ((p == 2) && (n > 0) && (j == 0)) { - pi_read_block(PI,buf,n); - if (verbose > 1) - printk("%s: %s: Read %d bytes\n",PCD.name,fun,n); - r = 0; j++; - } else { - if (verbose > 1) - printk("%s: %s: Unexpected phase %d, d=%d, k=%d\n", - PCD.name,fun,p,d,k); - if ((verbose < 2) && !pcd_warned) { - pcd_warned = 1; - printk("%s: WARNING: ATAPI phase errors\n",PCD.name); +static int pcd_completion(struct pcd_unit *cd, char *buf, char *fun) +{ + int r, d, p, n, k, j; + + r = -1; + k = 0; + j = 0; + + if (!pcd_wait(cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR, + fun, "completion")) { + r = 0; + while (read_reg(cd, 7) & IDE_DRQ) { + d = read_reg(cd, 4) + 256 * read_reg(cd, 5); + n = (d + 3) & 0xfffc; + p = read_reg(cd, 2) & 3; + + if ((p == 2) && (n > 0) && (j == 0)) { + pi_read_block(cd->pi, buf, n); + if (verbose > 1) + printk("%s: %s: Read %d bytes\n", + cd->name, fun, n); + r = 0; + j++; + } else { + if (verbose > 1) + printk + ("%s: %s: Unexpected phase %d, d=%d, k=%d\n", + cd->name, fun, p, d, k); + if ((verbose < 2) && !pcd_warned) { + pcd_warned = 1; + printk + ("%s: WARNING: ATAPI phase errors\n", + cd->name); + } + mdelay(1); + } + if (k++ > PCD_TMO) { + printk("%s: Stuck DRQ\n", cd->name); + break; + } + if (pcd_wait + (cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR, fun, + "completion")) { + r = -1; + break; } - mdelay(1); - } - if (k++ > PCD_TMO) { - printk("%s: Stuck DRQ\n",PCD.name); - break; - } - if (pcd_wait(unit,IDE_BUSY,IDE_DRQ|IDE_READY|IDE_ERR, - fun,"completion")) { - r = -1; - break; } - } } - - pi_disconnect(PI); + + pi_disconnect(cd->pi); return r; } -static void pcd_req_sense( int unit, char *fun ) - -{ char rs_cmd[12] = { 0x03,0,0,0,16,0,0,0,0,0,0,0 }; - char buf[16]; - int r, c; +static void pcd_req_sense(struct pcd_unit *cd, char *fun) +{ + char rs_cmd[12] = { 0x03, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 }; + char buf[16]; + int r, c; - r = pcd_command(unit,rs_cmd,16,"Request sense"); + r = pcd_command(cd, rs_cmd, 16, "Request sense"); mdelay(1); - if (!r) pcd_completion(unit,buf,"Request sense"); + if (!r) + pcd_completion(cd, buf, "Request sense"); - PCD.last_sense = -1; c = 2; + cd->last_sense = -1; + c = 2; if (!r) { - if (fun) printk("%s: %s: Sense key: %x, ASC: %x, ASQ: %x\n", - PCD.name,fun,buf[2]&0xf,buf[12],buf[13]); - c = buf[2]&0xf; - PCD.last_sense = c | ((buf[12]&0xff)<<8) | ((buf[13]&0xff)<<16); - } - if ((c == 2) || (c == 6)) PCD.changed = 1; + if (fun) + printk("%s: %s: Sense key: %x, ASC: %x, ASQ: %x\n", + cd->name, fun, buf[2] & 0xf, buf[12], buf[13]); + c = buf[2] & 0xf; + cd->last_sense = + c | ((buf[12] & 0xff) << 8) | ((buf[13] & 0xff) << 16); + } + if ((c == 2) || (c == 6)) + cd->changed = 1; } -static int pcd_atapi( int unit, char * cmd, int dlen, char * buf, char * fun ) - -{ int r; +static int pcd_atapi(struct pcd_unit *cd, char *cmd, int dlen, char *buf, char *fun) +{ + int r; - r = pcd_command(unit,cmd,dlen,fun); + r = pcd_command(cd, cmd, dlen, fun); mdelay(1); - if (!r) r = pcd_completion(unit,buf,fun); - if (r) pcd_req_sense(unit,fun); - + if (!r) + r = pcd_completion(cd, buf, fun); + if (r) + pcd_req_sense(cd, fun); + return r; } -static int pcd_packet(struct cdrom_device_info *cdi, - struct cdrom_generic_command *cgc) +static int pcd_packet(struct cdrom_device_info *cdi, struct cdrom_generic_command *cgc) { - char *un_cmd; - int unit = DEVICE_NR(cdi->dev); - - un_cmd = cgc->cmd; - return pcd_atapi(unit,un_cmd,cgc->buflen,cgc->buffer, "generic packet"); + return pcd_atapi(cdi->handle, cgc->cmd, cgc->buflen, cgc->buffer, + "generic packet"); } #define DBMSG(msg) ((verbose>1)?(msg):NULL) static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr) - -{ int r; - int unit = DEVICE_NR(cdi->dev); - - r = PCD.changed; - PCD.changed = 0; - - return r; +{ + struct pcd_unit *cd = cdi->handle; + int res = cd->changed; + if (res) + cd->changed = 0; + return res; } static int pcd_lock_door(struct cdrom_device_info *cdi, int lock) +{ + char un_cmd[12] = { 0x1e, 0, 0, 0, lock, 0, 0, 0, 0, 0, 0, 0 }; -{ char un_cmd[12] = { 0x1e,0,0,0,lock,0,0,0,0,0,0,0 }; - int unit = DEVICE_NR(cdi->dev); - - return pcd_atapi(unit,un_cmd,0,pcd_scratch, - lock?"lock door":"unlock door"); + return pcd_atapi(cdi->handle, un_cmd, 0, pcd_scratch, + lock ? "lock door" : "unlock door"); } static int pcd_tray_move(struct cdrom_device_info *cdi, int position) +{ + char ej_cmd[12] = { 0x1b, 0, 0, 0, 3 - position, 0, 0, 0, 0, 0, 0, 0 }; -{ char ej_cmd[12] = { 0x1b,0,0,0,3-position,0,0,0,0,0,0,0 }; - int unit = DEVICE_NR(cdi->dev); - - return pcd_atapi(unit,ej_cmd,0,pcd_scratch, - position?"eject":"close tray"); + return pcd_atapi(cdi->handle, ej_cmd, 0, pcd_scratch, + position ? "eject" : "close tray"); } -static void pcd_sleep( int cs ) - -{ current->state = TASK_INTERRUPTIBLE; - schedule_timeout(cs); +static void pcd_sleep(int cs) +{ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(cs); } -static int pcd_reset( int unit ) - -{ int i, k, flg; - int expect[5] = {1,1,1,0x14,0xeb}; +static int pcd_reset(struct pcd_unit *cd) +{ + int i, k, flg; + int expect[5] = { 1, 1, 1, 0x14, 0xeb }; - pi_connect(PI); - WR(0,6,0xa0 + 0x10*PCD.drive); - WR(0,7,8); + pi_connect(cd->pi); + write_reg(cd, 6, 0xa0 + 0x10 * cd->drive); + write_reg(cd, 7, 8); - pcd_sleep(20*HZ/1000); /* delay a bit */ + pcd_sleep(20 * HZ / 1000); /* delay a bit */ k = 0; - while ((k++ < PCD_RESET_TMO) && (RR(1,6)&IDE_BUSY)) - pcd_sleep(HZ/10); + while ((k++ < PCD_RESET_TMO) && (status_reg(cd) & IDE_BUSY)) + pcd_sleep(HZ / 10); flg = 1; - for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]); + for (i = 0; i < 5; i++) + flg &= (read_reg(cd, i + 1) == expect[i]); if (verbose) { - printk("%s: Reset (%d) signature = ",PCD.name,k); - for (i=0;i<5;i++) printk("%3x",RR(0,i+1)); - if (!flg) printk(" (incorrect)"); + printk("%s: Reset (%d) signature = ", cd->name, k); + for (i = 0; i < 5; i++) + printk("%3x", read_reg(cd, i + 1)); + if (!flg) + printk(" (incorrect)"); printk("\n"); } - - pi_disconnect(PI); - return flg-1; + + pi_disconnect(cd->pi); + return flg - 1; } static int pcd_drive_reset(struct cdrom_device_info *cdi) - -{ return pcd_reset(DEVICE_NR(cdi->dev)); +{ + return pcd_reset(cdi->handle); } -static int pcd_ready_wait( int unit, int tmo ) - -{ char tr_cmd[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; - int k, p; +static int pcd_ready_wait(struct pcd_unit *cd, int tmo) +{ + char tr_cmd[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + int k, p; - k = 0; - while (k < tmo) { - PCD.last_sense = 0; - pcd_atapi(unit,tr_cmd,0,NULL,DBMSG("test unit ready")); - p = PCD.last_sense; - if (!p) return 0; - if (!(((p & 0xffff) == 0x0402)||((p & 0xff) == 6))) return p; - k++; - pcd_sleep(HZ); - } - return 0x000020; /* timeout */ + k = 0; + while (k < tmo) { + cd->last_sense = 0; + pcd_atapi(cd, tr_cmd, 0, NULL, DBMSG("test unit ready")); + p = cd->last_sense; + if (!p) + return 0; + if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6))) + return p; + k++; + pcd_sleep(HZ); + } + return 0x000020; /* timeout */ } static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr) +{ + char rc_cmd[12] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + struct pcd_unit *cd = cdi->handle; -{ char rc_cmd[12] = { 0x25,0,0,0,0,0,0,0,0,0,0,0}; - int unit = DEVICE_NR(cdi->dev); - - if (pcd_ready_wait(unit,PCD_READY_TMO)) + if (pcd_ready_wait(cd, PCD_READY_TMO)) return CDS_DRIVE_NOT_READY; - if (pcd_atapi(unit,rc_cmd,8,pcd_scratch,DBMSG("check media"))) + if (pcd_atapi(cd, rc_cmd, 8, pcd_scratch, DBMSG("check media"))) return CDS_NO_DISC; return CDS_DISC_OK; } -static int pcd_identify( int unit, char * id ) - -{ int k, s; - char id_cmd[12] = {0x12,0,0,0,36,0,0,0,0,0,0,0}; +static int pcd_identify(struct pcd_unit *cd, char *id) +{ + int k, s; + char id_cmd[12] = { 0x12, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 }; pcd_bufblk = -1; - s = pcd_atapi(unit,id_cmd,36,pcd_buffer,"identify"); + s = pcd_atapi(cd, id_cmd, 36, pcd_buffer, "identify"); - if (s) return -1; + if (s) + return -1; if ((pcd_buffer[0] & 0x1f) != 5) { - if (verbose) printk("%s: %s is not a CD-ROM\n", - PCD.name,PCD.drive?"Slave":"Master"); - return -1; + if (verbose) + printk("%s: %s is not a CD-ROM\n", + cd->name, cd->drive ? "Slave" : "Master"); + return -1; + } + memcpy(id, pcd_buffer + 16, 16); + id[16] = 0; + k = 16; + while ((k >= 0) && (id[k] <= 0x20)) { + id[k] = 0; + k--; } - for (k=0;k<16;k++) id[k] = pcd_buffer[16+k]; id[16] = 0; - k = 16; while ((k >= 0) && (id[k] <= 0x20)) { id[k] = 0; k--; } - printk("%s: %s: %s\n",PCD.name,PCD.drive?"Slave":"Master",id); + printk("%s: %s: %s\n", cd->name, cd->drive ? "Slave" : "Master", id); return 0; } -static int pcd_probe( int unit, int ms, char * id ) - -/* returns 0, with id set if drive is detected - -1, if drive detection failed -*/ - -{ if (ms == -1) { - for (PCD.drive=0;PCD.drive<=1;PCD.drive++) - if (!pcd_reset(unit) && !pcd_identify(unit,id)) - return 0; +/* + * returns 0, with id set if drive is detected + * -1, if drive detection failed + */ +static int pcd_probe(struct pcd_unit *cd, int ms, char *id) +{ + if (ms == -1) { + for (cd->drive = 0; cd->drive <= 1; cd->drive++) + if (!pcd_reset(cd) && !pcd_identify(cd, id)) + return 0; } else { - PCD.drive = ms; - if (!pcd_reset(unit) && !pcd_identify(unit,id)) - return 0; + cd->drive = ms; + if (!pcd_reset(cd) && !pcd_identify(cd, id)) + return 0; } return -1; } -static void pcd_probe_capabilities( void ) - -{ int unit, r; - char buffer[32]; - char cmd[12]={0x5a,1<<3,0x2a,0,0,0,0,18,0,0,0,0}; - - for (unit=0;unit<PCD_UNITS;unit++) { - if (!PCD.present) continue; - r = pcd_atapi(unit,cmd,18, buffer,"mode sense capabilities"); - if (r) continue; +static void pcd_probe_capabilities(void) +{ + int unit, r; + char buffer[32]; + char cmd[12] = { 0x5a, 1 << 3, 0x2a, 0, 0, 0, 0, 18, 0, 0, 0, 0 }; + struct pcd_unit *cd; + + for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { + if (!cd->present) + continue; + r = pcd_atapi(cd, cmd, 18, buffer, "mode sense capabilities"); + if (r) + continue; /* we should now have the cap page */ if ((buffer[11] & 1) == 0) - PCD.info.mask |= CDC_CD_R; + cd->info.mask |= CDC_CD_R; if ((buffer[11] & 2) == 0) - PCD.info.mask |= CDC_CD_RW; + cd->info.mask |= CDC_CD_RW; if ((buffer[12] & 1) == 0) - PCD.info.mask |= CDC_PLAY_AUDIO; + cd->info.mask |= CDC_PLAY_AUDIO; if ((buffer[14] & 1) == 0) - PCD.info.mask |= CDC_LOCK; + cd->info.mask |= CDC_LOCK; if ((buffer[14] & 8) == 0) - PCD.info.mask |= CDC_OPEN_TRAY; + cd->info.mask |= CDC_OPEN_TRAY; if ((buffer[14] >> 6) == 0) - PCD.info.mask |= CDC_CLOSE_TRAY; + cd->info.mask |= CDC_CLOSE_TRAY; } } -static int pcd_detect( void ) - -{ char id[18]; - int k, unit; +static int pcd_detect(void) +{ + char id[18]; + int k, unit; + struct pcd_unit *cd; printk("%s: %s version %s, major %d, nice %d\n", - name,name,PCD_VERSION,major,nice); + name, name, PCD_VERSION, major, nice); k = 0; - if (pcd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */ - unit = 0; - if (pi_init(PI,1,-1,-1,-1,-1,-1,pcd_buffer, - PI_PCD,verbose,PCD.name)) { - if (!pcd_probe(unit,-1,id)) { - PCD.present = 1; - k++; - } else pi_release(PI); - } - - } else for (unit=0;unit<PCD_UNITS;unit++) if (DU[D_PRT]) - if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI], - DU[D_PRO],DU[D_DLY],pcd_buffer,PI_PCD,verbose, - PCD.name)) { - if (!pcd_probe(unit,DU[D_SLV],id)) { - PCD.present = 1; - k++; - } else pi_release(PI); - } - - if (k) return 0; - - printk("%s: No CD-ROM drive found\n",name); + if (pcd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */ + cd = pcd; + if (pi_init(cd->pi, 1, -1, -1, -1, -1, -1, pcd_buffer, + PI_PCD, verbose, cd->name)) { + if (!pcd_probe(cd, -1, id)) { + cd->present = 1; + k++; + } else + pi_release(cd->pi); + } + } else { + for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { + int *conf = *drives[unit]; + if (!conf[D_PRT]) + continue; + if (!pi_init(cd->pi, 0, conf[D_PRT], conf[D_MOD], + conf[D_UNI], conf[D_PRO], conf[D_DLY], + pcd_buffer, PI_PCD, verbose, cd->name)) + continue; + if (!pcd_probe(cd, conf[D_SLV], id)) { + cd->present = 1; + k++; + } else + pi_release(cd->pi); + } + } + if (k) + return 0; + + printk("%s: No CD-ROM drive found\n", name); return -1; } /* I/O request processing */ -static void do_pcd_request (request_queue_t * q) - -{ int unit; - - if (pcd_busy) return; - while (1) { - if (blk_queue_empty(QUEUE)) - return; - - if (rq_data_dir(CURRENT) == READ) { - unit = minor(CURRENT->rq_dev); - if (unit != pcd_unit) { - pcd_bufblk = -1; - pcd_unit = unit; - } - pcd_sector = CURRENT->sector; - pcd_count = CURRENT->current_nr_sectors; - pcd_buf = CURRENT->buffer; - pcd_busy = 1; - ps_set_intr(do_pcd_read,0,0,nice); +static void do_pcd_request(request_queue_t * q) +{ + if (pcd_busy) return; - } - else end_request(CURRENT, 0); + while (1) { + struct request *req; + if (blk_queue_empty(QUEUE)) + return; + req = CURRENT; + if (rq_data_dir(req) == READ) { + struct pcd_unit *cd = pcd + minor(req->rq_dev); + if (cd != pcd_current) + pcd_bufblk = -1; + pcd_current = cd; + pcd_sector = req->sector; + pcd_count = req->current_nr_sectors; + pcd_buf = req->buffer; + pcd_busy = 1; + ps_set_intr(do_pcd_read, 0, 0, nice); + return; + } else + end_request(req, 0); } } -static int pcd_ready( void ) - -{ int unit = pcd_unit; - - return (((RR(1,6)&(IDE_BUSY|IDE_DRQ))==IDE_DRQ)) ; +static int pcd_ready(void) +{ + return (((status_reg(pcd_current) & (IDE_BUSY | IDE_DRQ)) == IDE_DRQ)); } -static void pcd_transfer( void ) - -{ int k, o; +static void pcd_transfer(void) +{ - while (pcd_count && (pcd_sector/4 == pcd_bufblk)) { - o = (pcd_sector % 4) * 512; - for(k=0;k<512;k++) pcd_buf[k] = pcd_buffer[o+k]; + while (pcd_count && (pcd_sector / 4 == pcd_bufblk)) { + int o = (pcd_sector % 4) * 512; + memcpy(pcd_buf, pcd_buffer + o, 512); pcd_count--; pcd_buf += 512; pcd_sector++; } } -static void pcd_start( void ) - -{ int unit = pcd_unit; - int b, i; - char rd_cmd[12] = {0xa8,0,0,0,0,0,0,0,0,1,0,0}; - long saved_flags; +static void pcd_start(void) +{ + int b, i; + char rd_cmd[12] = { 0xa8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }; + long saved_flags; pcd_bufblk = pcd_sector / 4; - b = pcd_bufblk; - for(i=0;i<4;i++) { - rd_cmd[5-i] = b & 0xff; - b = b >> 8; + b = pcd_bufblk; + for (i = 0; i < 4; i++) { + rd_cmd[5 - i] = b & 0xff; + b = b >> 8; } - if (pcd_command(unit,rd_cmd,2048,"read block")) { - pcd_bufblk = -1; - spin_lock_irqsave(&pcd_lock,saved_flags); + if (pcd_command(pcd_current, rd_cmd, 2048, "read block")) { + pcd_bufblk = -1; + spin_lock_irqsave(&pcd_lock, saved_flags); pcd_busy = 0; end_request(CURRENT, 0); do_pcd_request(NULL); - spin_unlock_irqrestore(&pcd_lock,saved_flags); + spin_unlock_irqrestore(&pcd_lock, saved_flags); return; } mdelay(1); - ps_set_intr(do_pcd_read_drq,pcd_ready,PCD_TMO,nice); - + ps_set_intr(do_pcd_read_drq, pcd_ready, PCD_TMO, nice); } -static void do_pcd_read( void ) - - -{ int unit = pcd_unit; - long saved_flags; - +static void do_pcd_read(void) +{ pcd_busy = 1; pcd_retries = 0; pcd_transfer(); if (!pcd_count) { - spin_lock_irqsave(&pcd_lock,saved_flags); + long saved_flags; + spin_lock_irqsave(&pcd_lock, saved_flags); end_request(CURRENT, 1); pcd_busy = 0; do_pcd_request(NULL); - spin_unlock_irqrestore(&pcd_lock,saved_flags); + spin_unlock_irqrestore(&pcd_lock, saved_flags); return; } - pi_do_claimed(PI,pcd_start); + pi_do_claimed(pcd_current->pi, pcd_start); } -static void do_pcd_read_drq( void ) - -{ int unit = pcd_unit; - long saved_flags; - - if (pcd_completion(unit,pcd_buffer,"read block")) { - if (pcd_retries < PCD_RETRIES) { - mdelay(1); - pcd_retries++; - pi_do_claimed(PI,pcd_start); - return; - } - spin_lock_irqsave(&pcd_lock,saved_flags); +static void do_pcd_read_drq(void) +{ + long saved_flags; + + if (pcd_completion(pcd_current, pcd_buffer, "read block")) { + if (pcd_retries < PCD_RETRIES) { + mdelay(1); + pcd_retries++; + pi_do_claimed(pcd_current->pi, pcd_start); + return; + } + spin_lock_irqsave(&pcd_lock, saved_flags); pcd_busy = 0; pcd_bufblk = -1; end_request(CURRENT, 0); do_pcd_request(NULL); - spin_unlock_irqrestore(&pcd_lock,saved_flags); + spin_unlock_irqrestore(&pcd_lock, saved_flags); return; } do_pcd_read(); - spin_lock_irqsave(&pcd_lock,saved_flags); + spin_lock_irqsave(&pcd_lock, saved_flags); do_pcd_request(NULL); - spin_unlock_irqrestore(&pcd_lock,saved_flags); + spin_unlock_irqrestore(&pcd_lock, saved_flags); } /* the audio_ioctl stuff is adapted from sr_ioctl.c */ -static int pcd_audio_ioctl(struct cdrom_device_info *cdi, - unsigned int cmd, void *arg) +static int pcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg) +{ + struct pcd_unit *cd = cdi->handle; -{ int unit = DEVICE_NR(cdi->dev); - - switch (cmd) { - - case CDROMREADTOCHDR: - - { char cmd[12]={GPCMD_READ_TOC_PMA_ATIP,0,0,0,0,0,0,0,12,0,0,0}; - struct cdrom_tochdr* tochdr = (struct cdrom_tochdr*)arg; - char buffer[32]; - int r; - - r = pcd_atapi(unit,cmd,12,buffer,"read toc header"); - - tochdr->cdth_trk0 = buffer[2]; - tochdr->cdth_trk1 = buffer[3]; - - return r * EIO; - } - - case CDROMREADTOCENTRY: - - { char cmd[12]={GPCMD_READ_TOC_PMA_ATIP,0,0,0,0,0,0,0,12,0,0,0}; - - struct cdrom_tocentry* tocentry = (struct cdrom_tocentry*)arg; - unsigned char buffer[32]; - int r; - - cmd[1] = (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0); - cmd[6] = tocentry->cdte_track; - - r = pcd_atapi(unit,cmd,12,buffer,"read toc entry"); - - tocentry->cdte_ctrl = buffer[5] & 0xf; - tocentry->cdte_adr = buffer[5] >> 4; - tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04)?1:0; - if (tocentry->cdte_format == CDROM_MSF) { - tocentry->cdte_addr.msf.minute = buffer[9]; - tocentry->cdte_addr.msf.second = buffer[10]; - tocentry->cdte_addr.msf.frame = buffer[11]; - } else - tocentry->cdte_addr.lba = - (((((buffer[8] << 8) + buffer[9]) << 8) - + buffer[10]) << 8) + buffer[11]; - - return r * EIO; - } - - default: - - return -ENOSYS; - } -} - -static int pcd_get_mcn (struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) - -{ char cmd[12]={GPCMD_READ_SUBCHANNEL,0,0x40,2,0,0,0,0,24,0,0,0}; - char buffer[32]; - int k; - int unit = DEVICE_NR(cdi->dev); - - if (pcd_atapi(unit,cmd,24,buffer,"get mcn")) return -EIO; - - for (k=0;k<13;k++) mcn->medium_catalog_number[k] = buffer[k+9]; + switch (cmd) { + + case CDROMREADTOCHDR: + + { + char cmd[12] = + { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12, + 0, 0, 0 }; + struct cdrom_tochdr *tochdr = + (struct cdrom_tochdr *) arg; + char buffer[32]; + int r; + + r = pcd_atapi(cd, cmd, 12, buffer, "read toc header"); + + tochdr->cdth_trk0 = buffer[2]; + tochdr->cdth_trk1 = buffer[3]; + + return r ? -EIO : 0; + } + + case CDROMREADTOCENTRY: + + { + char cmd[12] = + { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12, + 0, 0, 0 }; + + struct cdrom_tocentry *tocentry = + (struct cdrom_tocentry *) arg; + unsigned char buffer[32]; + int r; + + cmd[1] = + (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0); + cmd[6] = tocentry->cdte_track; + + r = pcd_atapi(cd, cmd, 12, buffer, "read toc entry"); + + tocentry->cdte_ctrl = buffer[5] & 0xf; + tocentry->cdte_adr = buffer[5] >> 4; + tocentry->cdte_datamode = + (tocentry->cdte_ctrl & 0x04) ? 1 : 0; + if (tocentry->cdte_format == CDROM_MSF) { + tocentry->cdte_addr.msf.minute = buffer[9]; + tocentry->cdte_addr.msf.second = buffer[10]; + tocentry->cdte_addr.msf.frame = buffer[11]; + } else + tocentry->cdte_addr.lba = + (((((buffer[8] << 8) + buffer[9]) << 8) + + buffer[10]) << 8) + buffer[11]; + + return r ? -EIO : 0; + } + + default: + + return -ENOSYS; + } +} + +static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) +{ + char cmd[12] = + { GPCMD_READ_SUBCHANNEL, 0, 0x40, 2, 0, 0, 0, 0, 24, 0, 0, 0 }; + char buffer[32]; + + if (pcd_atapi(cdi->handle, cmd, 24, buffer, "get mcn")) + return -EIO; + + memcpy(mcn->medium_catalog_number, buffer + 9, 13); mcn->medium_catalog_number[13] = 0; - + return 0; } - static int __init pcd_init(void) { + struct pcd_unit *cd; int unit; if (disable) @@ -898,15 +918,15 @@ static int __init pcd_init(void) /* get the atapi capabilities page */ pcd_probe_capabilities(); - if (register_blkdev(MAJOR_NR,name,&pcd_bdops)) { - printk("pcd: unable to get major number %d\n",MAJOR_NR); + if (register_blkdev(MAJOR_NR, name, &pcd_bdops)) { + printk("pcd: unable to get major number %d\n", MAJOR_NR); return -1; } - for (unit=0;unit<PCD_UNITS;unit++) { - if (PCD.present) { - register_cdrom(&PCD.info); - devfs_plain_cdrom(&PCD.info, &pcd_bdops); + for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { + if (cd->present) { + register_cdrom(&cd->info); + devfs_plain_cdrom(&cd->info, &pcd_bdops); } } @@ -917,13 +937,16 @@ static int __init pcd_init(void) static void __exit pcd_exit(void) { + struct pcd_unit *cd; int unit; - for (unit=0;unit<PCD_UNITS;unit++) - if (PCD.present) { - pi_release(PI); - unregister_cdrom(&PCD.info); + + for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { + if (cd->present) { + pi_release(cd->pi); + unregister_cdrom(&cd->info); } - unregister_blkdev(MAJOR_NR,name); + } + unregister_blkdev(MAJOR_NR, name); } MODULE_LICENSE("GPL"); diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index 6d6b1ab6a7c4..66e3300028a2 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -271,8 +271,6 @@ static void pd_doorlock(int unit, int func); static int pd_check_media(kdev_t dev); static void pd_eject( int unit); -static struct hd_struct pd_hd[PD_DEVS]; - #define PD_NAMELEN 8 struct pd_unit { @@ -438,9 +436,9 @@ static int pd_revalidate(kdev_t dev) if ((unit >= PD_UNITS) || !PD.present) return -ENODEV; if (pd_identify(unit)) - pd_hd[minor(dev)].nr_sects = PD.capacity; + set_capacity(&PD.gd, PD.capacity); else - pd_hd[minor(dev)].nr_sects = 0; + set_capacity(&PD.gd, 0); return 0; } @@ -687,10 +685,8 @@ static int pd_detect( void ) PD.gd.major_name = PD.name; PD.gd.minor_shift = PD_BITS; PD.gd.fops = &pd_fops; - PD.gd.nr_real = 1; PD.gd.major = major; PD.gd.first_minor = unit << PD_BITS; - PD.gd.part = pd_hd + (unit << PD_BITS); add_gendisk(&PD.gd); register_disk(&PD.gd,mk_kdev(MAJOR_NR,unit<<PD_BITS), PD_PARTNS,&pd_fops, @@ -728,7 +724,7 @@ repeat: pd_count = CURRENT->current_nr_sectors; if ((pd_dev >= PD_DEVS) || - ((pd_block+pd_count) > pd_hd[pd_dev].nr_sects)) { + ((pd_block+pd_count) > get_capacity(&pd[unit].gd))) { end_request(CURRENT, 0); goto repeat; } diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c index c1076b2b65d0..2b4d18cd054d 100644 --- a/drivers/block/ps2esdi.c +++ b/drivers/block/ps2esdi.c @@ -109,7 +109,6 @@ static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int); static int no_int_yet; static int ps2esdi_drives; -static struct hd_struct ps2esdi[MAX_HD << 6]; static u_short io_base; static struct timer_list esdi_timer = { function: ps2esdi_reset_timer }; static int reset_status; @@ -152,17 +151,13 @@ static struct gendisk ps2esdi_gendisk[2] = { major_name: "eda", first_minor: 0, minor_shift: 6, - part: ps2esdi, fops: &ps2esdi_fops, - nr_real: 1 },{ major: MAJOR_NR, first_minor: 64, major_name: "edb", minor_shift: 6, - part: ps2esdi+64, fops: &ps2esdi_fops, - nr_real: 1 } }; @@ -489,6 +484,7 @@ static void __init ps2esdi_get_device_cfg(void) static void do_ps2esdi_request(request_queue_t * q) { u_int block, count; + int unit; /* since, this routine is called with interrupts cleared - they must be before it finishes */ @@ -505,18 +501,19 @@ static void do_ps2esdi_request(request_queue_t * q) if (blk_queue_empty(QUEUE)) return; + unit = DEVICE_NR(CURRENT->rq_dev); if (isa_virt_to_bus(CURRENT->buffer + CURRENT->current_nr_sectors * 512) > 16 * MB) { printk("%s: DMA above 16MB not supported\n", DEVICE_NAME); end_request(CURRENT, FAIL); } /* check for above 16Mb dmas */ - else if ((DEVICE_NR(CURRENT->rq_dev) < ps2esdi_drives) && + else if ((unit < ps2esdi_drives) && (CURRENT->sector + CURRENT->current_nr_sectors <= - ps2esdi[minor(CURRENT->rq_dev)].nr_sects) && + get_capacity(&ps2esdi_gendisk[unit])) && CURRENT->flags & REQ_CMD) { #if 0 printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld\n", DEVICE_NAME, - DEVICE_NR(CURRENT->rq_dev), minor(CURRENT->rq_dev), + unit, minor(CURRENT->rq_dev), CURRENT->cmd, CURRENT->sector, CURRENT->current_nr_sectors); #endif @@ -526,10 +523,10 @@ static void do_ps2esdi_request(request_queue_t * q) switch (rq_data_dir(CURRENT)) { case READ: - ps2esdi_readwrite(READ, DEVICE_NR(CURRENT->rq_dev), block, count); + ps2esdi_readwrite(READ, unit, block, count); break; case WRITE: - ps2esdi_readwrite(WRITE, DEVICE_NR(CURRENT->rq_dev), block, count); + ps2esdi_readwrite(WRITE, unit, block, count); break; default: printk("%s: Unknown command\n", DEVICE_NAME); @@ -540,7 +537,7 @@ static void do_ps2esdi_request(request_queue_t * q) /* is request is valid */ else { printk("Grrr. error. ps2esdi_drives: %d, %lu %lu\n", ps2esdi_drives, - CURRENT->sector, ps2esdi[minor(CURRENT->rq_dev)].nr_sects); + CURRENT->sector, get_capacity(&ps2esdi_gendisk[unit])); end_request(CURRENT, FAIL); } diff --git a/drivers/block/rd.c b/drivers/block/rd.c index 587d432d4ac0..b36f3ccfd81a 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -109,9 +109,11 @@ int rd_blocksize = BLOCK_SIZE; /* blocksize of the RAM disks */ static int ramdisk_readpage(struct file *file, struct page * page) { if (!PageUptodate(page)) { - memset(kmap(page), 0, PAGE_CACHE_SIZE); - kunmap(page); + void *kaddr = kmap_atomic(page, KM_USER0); + + memset(kaddr, 0, PAGE_CACHE_SIZE); flush_dcache_page(page); + kunmap_atomic(kaddr, KM_USER0); SetPageUptodate(page); } unlock_page(page); @@ -121,9 +123,11 @@ static int ramdisk_readpage(struct file *file, struct page * page) static int ramdisk_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) { if (!PageUptodate(page)) { - void *addr = page_address(page); - memset(addr, 0, PAGE_CACHE_SIZE); + void *kaddr = kmap_atomic(page, KM_USER0); + + memset(kaddr, 0, PAGE_CACHE_SIZE); flush_dcache_page(page); + kunmap_atomic(kaddr, KM_USER0); SetPageUptodate(page); } SetPageDirty(page); @@ -178,8 +182,11 @@ static int rd_blkdev_pagecache_IO(int rw, struct bio_vec *vec, err = 0; if (!PageUptodate(page)) { - memset(kmap(page), 0, PAGE_CACHE_SIZE); - kunmap(page); + void *kaddr = kmap_atomic(page, KM_USER0); + + memset(kaddr, 0, PAGE_CACHE_SIZE); + flush_dcache_page(page); + kunmap_atomic(kaddr, KM_USER0); SetPageUptodate(page); } diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 482aa8634984..b714494b67d1 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -159,9 +159,6 @@ static struct cardinfo cards[MM_MAXCARDS]; static struct block_device_operations mm_fops; static struct timer_list battery_timer; - -static struct hd_struct mm_partitions[MM_MAXCARDS << MM_SHIFT]; - static int num_cards = 0; static struct gendisk mm_gendisk[MM_MAXCARDS]; @@ -812,7 +809,7 @@ static void del_battery_timer(void) static int mm_revalidate(kdev_t i_rdev) { int card_number = DEVICE_NR(i_rdev); - mm_partitions[minor(i_rdev)].nr_sects = cards[card_number].mm_size << 1; + set_capacity(mm_gendisk + card_number, cards[card_number].mm_size << 1); return 0; } /* @@ -1192,8 +1189,6 @@ int __init mm_init(void) struct gendisk *disk = mm_gendisk + i; sprintf(mm_names + i*6, "umem%c", 'a'+i); spin_lock_init(&cards[i].lock); - disk->part = mm_partitions + (i << MM_SHIFT); - disk->nr_real = 1; disk->major = major_nr; disk->first_minor = i << MM_SHIFT; disk->major_name = mm_names + i*6; @@ -1222,10 +1217,8 @@ void __exit mm_cleanup(void) del_battery_timer(); - for (i=0; i < num_cards ; i++) { - devfs_register_partitions(mm_gendisk + i, i<<MM_SHIFT, 1); + for (i=0; i < num_cards ; i++) del_gendisk(mm_gendisk + i); - } if (devfs_handle) devfs_unregister(devfs_handle); devfs_handle = NULL; diff --git a/drivers/block/xd.c b/drivers/block/xd.c index 6dc939a7a055..97ec536e4756 100644 --- a/drivers/block/xd.c +++ b/drivers/block/xd.c @@ -121,8 +121,6 @@ static unsigned int xd_bases[] __initdata = 0xE0000 }; -static struct hd_struct xd_struct[XD_MAXDRIVES << 6]; - static spinlock_t xd_lock = SPIN_LOCK_UNLOCKED; extern struct block_device_operations xd_fops; @@ -133,17 +131,13 @@ static struct gendisk xd_gendisk[2] = { .first_minor = 0, .major_name = "xda", .minor_shift = 6, - .part = xd_struct, .fops = &xd_fops, - .nr_real = 1 },{ .major = MAJOR_NR, .first_minor = 64, .major_name = "xdb", .minor_shift = 6, - .part = xd_struct + 64, .fops = &xd_fops, - .nr_real = 1 } }; @@ -281,15 +275,17 @@ static void do_xd_request (request_queue_t * q) return; while (1) { + int unit; code = 0; /* do some checking on the request structure */ if (blk_queue_empty(QUEUE)) return; - if (DEVICE_NR(CURRENT->rq_dev) < xd_drives + unit = DEVICE_NR(CURRENT->rq_dev); + if (unit < xd_drives && (CURRENT->flags & REQ_CMD) && CURRENT->sector + CURRENT->nr_sectors - <= xd_struct[minor(CURRENT->rq_dev)].nr_sects) { + <= get_capacity(xd_gendisk + unit)) { block = CURRENT->sector; count = CURRENT->nr_sectors; @@ -297,7 +293,7 @@ static void do_xd_request (request_queue_t * q) case READ: case WRITE: for (retry = 0; (retry < XD_RETRIES) && !code; retry++) - code = xd_readwrite(rq_data_dir(CURRENT),DEVICE_NR(CURRENT->rq_dev), + code = xd_readwrite(rq_data_dir(CURRENT),unit, CURRENT->buffer,block,count); break; default: diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 3520403e3f1d..6101e17ebe13 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -254,6 +254,7 @@ #include <linux/config.h> #include <linux/module.h> #include <linux/fs.h> +#include <linux/buffer_head.h> #include <linux/major.h> #include <linux/types.h> #include <linux/errno.h> @@ -1608,6 +1609,7 @@ int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, cdinfo(CD_DO_IOCTL, "entering CDROM_RESET\n"); if (!CDROM_CAN(CDC_RESET)) return -ENOSYS; + invalidate_buffers(dev); return cdo->reset(cdi); } diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c index ab5136e92896..b969e36e69b0 100644 --- a/drivers/cdrom/cdu31a.c +++ b/drivers/cdrom/cdu31a.c @@ -331,12 +331,11 @@ static struct timer_list cdu31a_abort_timer; from the abort read. */ static int abort_read_started = 0; - /* - * This routine returns 1 if the disk has been changed since the last - * check or 0 if it hasn't. + * Uniform cdrom interface function + * report back, if disc has changed from time of last request. */ -static int scd_disk_change(kdev_t full_dev) +static int scd_media_changed(struct cdrom_device_info *cdi, int disc_nr) { int retval; @@ -348,15 +347,6 @@ static int scd_disk_change(kdev_t full_dev) /* * Uniform cdrom interface function - * report back, if disc has changed from time of last request. - */ -static int scd_media_changed(struct cdrom_device_info *cdi, int disc_nr) -{ - return scd_disk_change(cdi->dev); -} - -/* - * Uniform cdrom interface function * report back, if drive is ready */ static int scd_drive_status(struct cdrom_device_info *cdi, int slot_nr) diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c index 7567fb2a6dc1..527286c08584 100644 --- a/drivers/cdrom/mcdx.c +++ b/drivers/cdrom/mcdx.c @@ -73,7 +73,6 @@ static const char *mcdx_c_version #include <linux/major.h> #define MAJOR_NR MITSUMI_X_CDROM_MAJOR -#define DEVICE_NR(device) (minor(device)) #include <linux/blk.h> #include <linux/devfs_fs_kernel.h> @@ -197,7 +196,6 @@ struct s_drive_stuff { void *rreg_status; /* r status */ int irq; /* irq used by this drive */ - int minor; /* minor number of this drive */ int present; /* drive present and its capabilities */ unsigned char readcmd; /* read cmd depends on single/double speed */ unsigned char playcmd; /* play should always be single speed */ @@ -207,6 +205,7 @@ struct s_drive_stuff { int lastsector; /* last block accessible */ int status; /* last operation's error / status */ int readerrs; /* # of blocks read w/o error */ + struct cdrom_device_info info; }; @@ -305,21 +304,13 @@ static struct cdrom_device_ops mcdx_dops = { CDC_PLAY_AUDIO | CDC_DRIVE_STATUS, }; -static struct cdrom_device_info mcdx_info = { - ops:&mcdx_dops, - speed:2, - capacity:1, - name:"mcdx", -}; - - /* KERNEL INTERFACE FUNCTIONS **************************************/ static int mcdx_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg) { - struct s_drive_stuff *stuffp = mcdx_stuffp[minor(cdi->dev)]; + struct s_drive_stuff *stuffp = cdi->handle; if (!stuffp->present) return -ENXIO; @@ -627,7 +618,7 @@ static int mcdx_open(struct cdrom_device_info *cdi, int purpose) { struct s_drive_stuff *stuffp; xtrace(OPENCLOSE, "open()\n"); - stuffp = mcdx_stuffp[minor(cdi->dev)]; + stuffp = cdi->handle; if (!stuffp->present) return -ENXIO; @@ -776,7 +767,7 @@ static void mcdx_close(struct cdrom_device_info *cdi) xtrace(OPENCLOSE, "close()\n"); - stuffp = mcdx_stuffp[minor(cdi->dev)]; + stuffp = cdi->handle; --stuffp->users; } @@ -787,10 +778,9 @@ static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr) { struct s_drive_stuff *stuffp; - xinfo("mcdx_media_changed called for device %s\n", - kdevname(cdi->dev)); + xinfo("mcdx_media_changed called for device %s\n", cdi->name); - stuffp = mcdx_stuffp[minor(cdi->dev)]; + stuffp = cdi->handle; mcdx_getstatus(stuffp, 1); if (stuffp->yyy == 0) @@ -1027,14 +1017,13 @@ void __exit mcdx_exit(void) xinfo("cleanup_module called\n"); for (i = 0; i < MCDX_NDRIVES; i++) { - struct s_drive_stuff *stuffp; - if (unregister_cdrom(&mcdx_info)) { + struct s_drive_stuff *stuffp = mcdx_stuffp[i]; + if (!stuffp) + continue; + if (unregister_cdrom(&stuffp->info)) { printk(KERN_WARNING "Can't unregister cdrom mcdx\n"); return; } - stuffp = mcdx_stuffp[i]; - if (!stuffp) - continue; release_region((unsigned long) stuffp->wreg_data, MCDX_IO_SIZE); free_irq(stuffp->irq, NULL); @@ -1208,15 +1197,19 @@ int __init mcdx_init_drive(int drive) xtrace(INIT, "init() set non dma but irq mode\n"); mcdx_config(stuffp, 1); - stuffp->minor = drive; + stuffp->info.ops = &mcdx_dops; + stuffp->info.speed = 2; + stuffp->info.capacity = 1; + stuffp->info.handle = stuffp; + sprintf(stuffp->info.name, "mcdx%d", drive); + stuffp->info.dev = mk_kdev(MAJOR_NR, drive); sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%3p, irq %d." " (Firmware version %c %x)\n", stuffp->wreg_data, stuffp->irq, version.code, version.ver); mcdx_stuffp[drive] = stuffp; xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp); - mcdx_info.dev = mk_kdev(MAJOR_NR, 0); - if (register_cdrom(&mcdx_info) != 0) { + if (register_cdrom(&stuffp->info) != 0) { printk("Cannot register Mitsumi CD-ROM!\n"); release_region((unsigned long) stuffp->wreg_data, MCDX_IO_SIZE); @@ -1227,7 +1220,7 @@ int __init mcdx_init_drive(int drive) blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); return 2; } - devfs_plain_cdrom(&mcdx_info, &mcdx_bdops); + devfs_plain_cdrom(&stuffp->info, &mcdx_bdops); printk(msg); return 0; } @@ -1685,7 +1678,7 @@ mcdx_playtrk(struct s_drive_stuff *stuffp, const struct cdrom_ti *ti) static int mcdx_tray_move(struct cdrom_device_info *cdi, int position) { - struct s_drive_stuff *stuffp = mcdx_stuffp[minor(cdi->dev)]; + struct s_drive_stuff *stuffp = cdi->handle; if (!stuffp->present) return -ENXIO; @@ -1875,7 +1868,7 @@ static int mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tr static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock) { - struct s_drive_stuff *stuffp = mcdx_stuffp[minor(cdi->dev)]; + struct s_drive_stuff *stuffp = cdi->handle; char cmd[2] = { 0xfe }; if (!(stuffp->present & DOOR)) diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c index 2b2625b5ba2f..1dae164fdcee 100644 --- a/drivers/cdrom/sbpcd.c +++ b/drivers/cdrom/sbpcd.c @@ -480,7 +480,6 @@ static void sbp_read_cmd(struct request *req); static int sbp_data(struct request *req); static int cmd_out(void); static int DiskInfo(void); -static int sbpcd_chk_disk_change(kdev_t); /*==========================================================================*/ @@ -623,9 +622,7 @@ static u_char drv_pattern[NR_SBPCD]={speed_auto,speed_auto,speed_auto,speed_auto /* * drive space begins here (needed separate for each unit) */ -static int d; /* DriveStruct index: drive number */ - -static struct { +static struct sbpcd_drive { char drv_id; /* "jumpered" drive ID or -1 */ char drv_sel; /* drive select lines bits */ @@ -728,6 +725,8 @@ static struct { } D_S[NR_SBPCD]; +static struct sbpcd_drive *current_drive = D_S; + /* * drive space ends here (needed separate for each unit) */ @@ -760,7 +759,7 @@ static void msg(int level, const char *fmt, ...) msgnum++; if (msgnum>99) msgnum=0; - sprintf(buf, MSG_LEVEL "%s-%d [%02d]: ", major_name, d, msgnum); + sprintf(buf, MSG_LEVEL "%s-%d [%02d]: ", major_name, current_drive - D_S, msgnum); va_start(args, fmt); vsprintf(&buf[18], fmt, args); va_end(args); @@ -1103,51 +1102,51 @@ static int ResponseInfo(void) /*==========================================================================*/ static void EvaluateStatus(int st) { - D_S[d].status_bits=0; - if (fam1_drive) D_S[d].status_bits=st|p_success; + current_drive->status_bits=0; + if (fam1_drive) current_drive->status_bits=st|p_success; else if (fam0_drive) { - if (st&p_caddin_old) D_S[d].status_bits |= p_door_closed|p_caddy_in; - if (st&p_spinning) D_S[d].status_bits |= p_spinning; - if (st&p_check) D_S[d].status_bits |= p_check; - if (st&p_success_old) D_S[d].status_bits |= p_success; - if (st&p_busy_old) D_S[d].status_bits |= p_busy_new; - if (st&p_disk_ok) D_S[d].status_bits |= p_disk_ok; + if (st&p_caddin_old) current_drive->status_bits |= p_door_closed|p_caddy_in; + if (st&p_spinning) current_drive->status_bits |= p_spinning; + if (st&p_check) current_drive->status_bits |= p_check; + if (st&p_success_old) current_drive->status_bits |= p_success; + if (st&p_busy_old) current_drive->status_bits |= p_busy_new; + if (st&p_disk_ok) current_drive->status_bits |= p_disk_ok; } else if (famLV_drive) { - D_S[d].status_bits |= p_success; - if (st&p_caddin_old) D_S[d].status_bits |= p_disk_ok|p_caddy_in; - if (st&p_spinning) D_S[d].status_bits |= p_spinning; - if (st&p_check) D_S[d].status_bits |= p_check; - if (st&p_busy_old) D_S[d].status_bits |= p_busy_new; - if (st&p_lcs_door_closed) D_S[d].status_bits |= p_door_closed; - if (st&p_lcs_door_locked) D_S[d].status_bits |= p_door_locked; + current_drive->status_bits |= p_success; + if (st&p_caddin_old) current_drive->status_bits |= p_disk_ok|p_caddy_in; + if (st&p_spinning) current_drive->status_bits |= p_spinning; + if (st&p_check) current_drive->status_bits |= p_check; + if (st&p_busy_old) current_drive->status_bits |= p_busy_new; + if (st&p_lcs_door_closed) current_drive->status_bits |= p_door_closed; + if (st&p_lcs_door_locked) current_drive->status_bits |= p_door_locked; } else if (fam2_drive) { - D_S[d].status_bits |= p_success; - if (st&p2_check) D_S[d].status_bits |= p1_check; - if (st&p2_door_closed) D_S[d].status_bits |= p1_door_closed; - if (st&p2_disk_in) D_S[d].status_bits |= p1_disk_in; - if (st&p2_busy1) D_S[d].status_bits |= p1_busy; - if (st&p2_busy2) D_S[d].status_bits |= p1_busy; - if (st&p2_spinning) D_S[d].status_bits |= p1_spinning; - if (st&p2_door_locked) D_S[d].status_bits |= p1_door_locked; - if (st&p2_disk_ok) D_S[d].status_bits |= p1_disk_ok; + current_drive->status_bits |= p_success; + if (st&p2_check) current_drive->status_bits |= p1_check; + if (st&p2_door_closed) current_drive->status_bits |= p1_door_closed; + if (st&p2_disk_in) current_drive->status_bits |= p1_disk_in; + if (st&p2_busy1) current_drive->status_bits |= p1_busy; + if (st&p2_busy2) current_drive->status_bits |= p1_busy; + if (st&p2_spinning) current_drive->status_bits |= p1_spinning; + if (st&p2_door_locked) current_drive->status_bits |= p1_door_locked; + if (st&p2_disk_ok) current_drive->status_bits |= p1_disk_ok; } else if (famT_drive) { return; /* still needs to get coded */ - D_S[d].status_bits |= p_success; - if (st&p2_check) D_S[d].status_bits |= p1_check; - if (st&p2_door_closed) D_S[d].status_bits |= p1_door_closed; - if (st&p2_disk_in) D_S[d].status_bits |= p1_disk_in; - if (st&p2_busy1) D_S[d].status_bits |= p1_busy; - if (st&p2_busy2) D_S[d].status_bits |= p1_busy; - if (st&p2_spinning) D_S[d].status_bits |= p1_spinning; - if (st&p2_door_locked) D_S[d].status_bits |= p1_door_locked; - if (st&p2_disk_ok) D_S[d].status_bits |= p1_disk_ok; + current_drive->status_bits |= p_success; + if (st&p2_check) current_drive->status_bits |= p1_check; + if (st&p2_door_closed) current_drive->status_bits |= p1_door_closed; + if (st&p2_disk_in) current_drive->status_bits |= p1_disk_in; + if (st&p2_busy1) current_drive->status_bits |= p1_busy; + if (st&p2_busy2) current_drive->status_bits |= p1_busy; + if (st&p2_spinning) current_drive->status_bits |= p1_spinning; + if (st&p2_door_locked) current_drive->status_bits |= p1_door_locked; + if (st&p2_disk_ok) current_drive->status_bits |= p1_disk_ok; } return; } @@ -1159,7 +1158,7 @@ static int get_state_T(void) static int cmd_out_T(void); clr_cmdbuf(); - D_S[d].n_bytes=1; + current_drive->n_bytes=1; drvcmd[0]=CMDT_STATUS; i=cmd_out_T(); if (i>=0) i=infobuf[0]; @@ -1170,33 +1169,33 @@ static int get_state_T(void) } if (i>=0) /* 2: closed, disk in */ - D_S[d].status_bits=p1_door_closed|p1_disk_in|p1_spinning|p1_disk_ok; - else if (D_S[d].error_state==6) + current_drive->status_bits=p1_door_closed|p1_disk_in|p1_spinning|p1_disk_ok; + else if (current_drive->error_state==6) { /* 3: closed, disk in, changed ("06 xx xx") */ - D_S[d].status_bits=p1_door_closed|p1_disk_in; - D_S[d].CD_changed=0xFF; - D_S[d].diskstate_flags &= ~toc_bit; + current_drive->status_bits=p1_door_closed|p1_disk_in; + current_drive->CD_changed=0xFF; + current_drive->diskstate_flags &= ~toc_bit; } - else if ((D_S[d].error_state!=2)||(D_S[d].b3!=0x3A)||(D_S[d].b4==0x00)) + else if ((current_drive->error_state!=2)||(current_drive->b3!=0x3A)||(current_drive->b4==0x00)) { /* 1: closed, no disk ("xx yy zz"or "02 3A 00") */ - D_S[d].status_bits=p1_door_closed; - D_S[d].open_count=0; + current_drive->status_bits=p1_door_closed; + current_drive->open_count=0; } - else if (D_S[d].b4==0x01) + else if (current_drive->b4==0x01) { /* 0: open ("02 3A 01") */ - D_S[d].status_bits=0; - D_S[d].open_count=0; + current_drive->status_bits=0; + current_drive->open_count=0; } else { /* 1: closed, no disk ("02 3A xx") */ - D_S[d].status_bits=p1_door_closed; - D_S[d].open_count=0; + current_drive->status_bits=p1_door_closed; + current_drive->open_count=0; } - return (D_S[d].status_bits); + return (current_drive->status_bits); } /*==========================================================================*/ static int ResponseStatus(void) @@ -1226,14 +1225,14 @@ static int ResponseStatus(void) { if ((flags_cmd_out & f_respo3) == 0) msg(DBG_STA,"ResponseStatus: timeout.\n"); - D_S[d].status_bits=0; + current_drive->status_bits=0; return (-401); } i=inb(CDi_info); msg(DBG_STA,"ResponseStatus: response %02X.\n", i); EvaluateStatus(i); - msg(DBG_STA,"status_bits=%02X, i=%02X\n",D_S[d].status_bits,i); - return (D_S[d].status_bits); + msg(DBG_STA,"status_bits=%02X, i=%02X\n",current_drive->status_bits,i); + return (current_drive->status_bits); } /*==========================================================================*/ static void cc_ReadStatus(void) @@ -1283,18 +1282,18 @@ static int cc_ReadError(void) drvcmd[0]=CMDT_READ_ERR; } i=cmd_out(); - D_S[d].error_byte=0; + current_drive->error_byte=0; msg(DBG_ERR,"cc_ReadError: cmd_out(CMDx_READ_ERR) returns %d (%02X)\n",i,i); if (i<0) return (i); if (fam0V_drive) i=1; else i=2; - D_S[d].error_byte=infobuf[i]; - msg(DBG_ERR,"cc_ReadError: infobuf[%d] is %d (%02X)\n",i,D_S[d].error_byte,D_S[d].error_byte); + current_drive->error_byte=infobuf[i]; + msg(DBG_ERR,"cc_ReadError: infobuf[%d] is %d (%02X)\n",i,current_drive->error_byte,current_drive->error_byte); i=sta2err(infobuf[i]); if (i==-ERR_DISKCHANGE) { - D_S[d].CD_changed=0xFF; - D_S[d].diskstate_flags &= ~toc_bit; + current_drive->CD_changed=0xFF; + current_drive->diskstate_flags &= ~toc_bit; } return (i); } @@ -1309,16 +1308,16 @@ static int cmd_out_T(void) int i, j, l=0, m, ntries; unsigned long flags; - D_S[d].error_state=0; - D_S[d].b3=0; - D_S[d].b4=0; - D_S[d].f_drv_error=0; + current_drive->error_state=0; + current_drive->b3=0; + current_drive->b4=0; + current_drive->f_drv_error=0; for (i=0;i<10;i++) sprintf(&msgbuf[i*3]," %02X",drvcmd[i]); msgbuf[i*3]=0; msg(DBG_CMD,"cmd_out_T:%s\n",msgbuf); OUT(CDo_sel_i_d,0); - OUT(CDo_enable,D_S[d].drv_sel); + OUT(CDo_enable,current_drive->drv_sel); i=inb(CDi_status); do_16bit=0; if ((f_16bit)&&(!(i&0x80))) @@ -1435,16 +1434,16 @@ static int cmd_out_T(void) sbp_sleep(1); } while (j<0); - D_S[d].error_state=infobuf[2]; - D_S[d].b3=infobuf[3]; - D_S[d].b4=infobuf[4]; - if (D_S[d].f_drv_error) + current_drive->error_state=infobuf[2]; + current_drive->b3=infobuf[3]; + current_drive->b4=infobuf[4]; + if (current_drive->f_drv_error) { - D_S[d].f_drv_error=0; + current_drive->f_drv_error=0; cc_DriveReset(); - D_S[d].error_state=2; + current_drive->error_state=2; } - return (-D_S[d].error_state-400); + return (-current_drive->error_state-400); } if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */ if ((teac==0)||(ntries<(CMDT_TRIES-5))) sbp_sleep(HZ/10); @@ -1452,9 +1451,9 @@ static int cmd_out_T(void) if (ntries>(CMDT_TRIES-50)) continue; msg(DBG_TEA,"cmd_out_T: next CMDT_TRIES (%02X): %d.\n", drvcmd[0], ntries-1); } - D_S[d].f_drv_error=1; + current_drive->f_drv_error=1; cc_DriveReset(); - D_S[d].error_state=2; + current_drive->error_state=2; return (-99); } /*==========================================================================*/ @@ -1487,7 +1486,7 @@ static int cmd_out(void) else i=ResponseInfo(); if (i<0) return (i); } - if (D_S[d].in_SpinUp) msg(DBG_SPI,"in_SpinUp: to CDi_stat_loop.\n"); + if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to CDi_stat_loop.\n"); if (flags_cmd_out&f_lopsta) { i=CDi_stat_loop(); @@ -1496,13 +1495,13 @@ static int cmd_out(void) if (!(flags_cmd_out&f_getsta)) goto LOC_229; LOC_228: - if (D_S[d].in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadStatus.\n"); + if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadStatus.\n"); cc_ReadStatus(); LOC_229: if (flags_cmd_out&f_ResponseStatus) { - if (D_S[d].in_SpinUp) msg(DBG_SPI,"in_SpinUp: to ResponseStatus.\n"); + if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to ResponseStatus.\n"); i=ResponseStatus(); /* builds status_bits, returns orig. status or p_busy_new */ if (i<0) return (i); @@ -1518,9 +1517,9 @@ static int cmd_out(void) LOC_232: if (!(flags_cmd_out&f_obey_p_check)) return (0); if (!st_check) return (0); - if (D_S[d].in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadError.\n"); + if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadError.\n"); i=cc_ReadError(); - if (D_S[d].in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cmd_out OK.\n"); + if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cmd_out OK.\n"); msg(DBG_000,"cmd_out: cc_ReadError=%d\n", i); return (i); } @@ -1574,7 +1573,7 @@ static int cc_Seek(u_int pos, char f_blk_msf) drvcmd[3]=(pos>>16)&0x00FF; drvcmd[4]=(pos>>8)&0x00FF; drvcmd[5]=pos&0x00FF; - D_S[d].n_bytes=1; + current_drive->n_bytes=1; } response_count=0; i=cmd_out(); @@ -1586,7 +1585,7 @@ static int cc_SpinUp(void) int i; msg(DBG_SPI,"SpinUp.\n"); - D_S[d].in_SpinUp = 1; + current_drive->in_SpinUp = 1; clr_cmdbuf(); if (fam0LV_drive) { @@ -1615,7 +1614,7 @@ static int cc_SpinUp(void) } response_count=0; i=cmd_out(); - D_S[d].in_SpinUp = 0; + current_drive->in_SpinUp = 0; return (i); } /*==========================================================================*/ @@ -1676,15 +1675,15 @@ static int cc_set_mode_T(void) clr_cmdbuf(); response_count=1; drvcmd[0]=CMDT_SETMODE; - drvcmd[1]=D_S[d].speed_byte; - drvcmd[2]=D_S[d].frmsiz>>8; - drvcmd[3]=D_S[d].frmsiz&0x0FF; - drvcmd[4]=D_S[d].f_XA; /* 1: XA */ - drvcmd[5]=D_S[d].type_byte; /* 0, 1, 3 */ - drvcmd[6]=D_S[d].mode_xb_6; - drvcmd[7]=D_S[d].mode_yb_7|D_S[d].volume_control; - drvcmd[8]=D_S[d].mode_xb_8; - drvcmd[9]=D_S[d].delay; + drvcmd[1]=current_drive->speed_byte; + drvcmd[2]=current_drive->frmsiz>>8; + drvcmd[3]=current_drive->frmsiz&0x0FF; + drvcmd[4]=current_drive->f_XA; /* 1: XA */ + drvcmd[5]=current_drive->type_byte; /* 0, 1, 3 */ + drvcmd[6]=current_drive->mode_xb_6; + drvcmd[7]=current_drive->mode_yb_7|current_drive->volume_control; + drvcmd[8]=current_drive->mode_xb_8; + drvcmd[9]=current_drive->delay; i=cmd_out_T(); return (i); } @@ -1699,15 +1698,15 @@ static int cc_prep_mode_T(void) sprintf(&msgbuf[i*3], " %02X", infobuf[i]); msgbuf[i*3]=0; msg(DBG_TEA,"CMDT_GETMODE:%s\n", msgbuf); - D_S[d].speed_byte=0x02; /* 0x02: auto quad, 0x82: quad, 0x81: double, 0x80: single */ - D_S[d].frmsiz=make16(infobuf[2],infobuf[3]); - D_S[d].f_XA=infobuf[4]; - if (D_S[d].f_XA==0) D_S[d].type_byte=0; - else D_S[d].type_byte=1; - D_S[d].mode_xb_6=infobuf[6]; - D_S[d].mode_yb_7=1; - D_S[d].mode_xb_8=infobuf[8]; - D_S[d].delay=0; /* 0, 1, 2, 3 */ + current_drive->speed_byte=0x02; /* 0x02: auto quad, 0x82: quad, 0x81: double, 0x80: single */ + current_drive->frmsiz=make16(infobuf[2],infobuf[3]); + current_drive->f_XA=infobuf[4]; + if (current_drive->f_XA==0) current_drive->type_byte=0; + else current_drive->type_byte=1; + current_drive->mode_xb_6=infobuf[6]; + current_drive->mode_yb_7=1; + current_drive->mode_xb_8=infobuf[8]; + current_drive->delay=0; /* 0, 1, 2, 3 */ j=cc_set_mode_T(); i=cc_get_mode_T(); for (i=0;i<10;i++) @@ -1762,17 +1761,17 @@ static int cc_SetVolume(void) u_char channel0,channel1,volume0,volume1; u_char control0,value0,control1,value1; - D_S[d].diskstate_flags &= ~volume_bit; + current_drive->diskstate_flags &= ~volume_bit; clr_cmdbuf(); - channel0=D_S[d].vol_chan0; - volume0=D_S[d].vol_ctrl0; - channel1=control1=D_S[d].vol_chan1; - volume1=value1=D_S[d].vol_ctrl1; + channel0=current_drive->vol_chan0; + volume0=current_drive->vol_ctrl0; + channel1=control1=current_drive->vol_chan1; + volume1=value1=current_drive->vol_ctrl1; control0=value0=0; if (famV_drive) return (0); - if (((D_S[d].drv_options&audio_mono)!=0)&&(D_S[d].drv_type>=drv_211)) + if (((current_drive->drv_options&audio_mono)!=0)&&(current_drive->drv_type>=drv_211)) { if ((volume0!=0)&&(volume1==0)) { @@ -1841,7 +1840,7 @@ static int cc_SetVolume(void) } else if (fam0_drive) /* different firmware levels */ { - if (D_S[d].drv_type>=drv_300) + if (current_drive->drv_type>=drv_300) { control0=volume0&0xFC; value0=volume1&0xFC; @@ -1853,7 +1852,7 @@ static int cc_SetVolume(void) else { value0=(volume0>volume1)?volume0:volume1; - if (D_S[d].drv_type<drv_211) + if (current_drive->drv_type<drv_211) { if (channel0!=0) { @@ -1886,14 +1885,14 @@ static int cc_SetVolume(void) if (volume0==0xFF) volume1=0xFF; else if (volume1==0xFF) volume0=0xFF; } - else if (D_S[d].drv_type<drv_201) volume0=volume1=value0; + else if (current_drive->drv_type<drv_201) volume0=volume1=value0; - if (D_S[d].drv_type>=drv_201) + if (current_drive->drv_type>=drv_201) { if (volume0==0) control0 |= 0x80; if (volume1==0) control0 |= 0x40; } - if (D_S[d].drv_type>=drv_211) + if (current_drive->drv_type>=drv_211) { if (channel0!=0) control0 |= 0x20; if (channel1!=1) control0 |= 0x10; @@ -1907,9 +1906,9 @@ static int cc_SetVolume(void) } else if (famT_drive) { - D_S[d].volume_control=0; - if (!volume0) D_S[d].volume_control|=0x10; - if (!volume1) D_S[d].volume_control|=0x20; + current_drive->volume_control=0; + if (!volume0) current_drive->volume_control|=0x10; + if (!volume1) current_drive->volume_control|=0x20; i=cc_prep_mode_T(); if (i<0) return (i); } @@ -1919,7 +1918,7 @@ static int cc_SetVolume(void) i=cmd_out(); if (i<0) return (i); } - D_S[d].diskstate_flags |= volume_bit; + current_drive->diskstate_flags |= volume_bit; return (0); } /*==========================================================================*/ @@ -1959,7 +1958,7 @@ static int cc_DriveReset(void) else if (famT_drive) { OUT(CDo_sel_i_d,0); - OUT(CDo_enable,D_S[d].drv_sel); + OUT(CDo_enable,current_drive->drv_sel); OUT(CDo_command,CMDT_RESET); for (i=1;i<10;i++) OUT(CDo_command,0); } @@ -1976,7 +1975,7 @@ static int cc_DriveReset(void) i=GetStatus(); if (i<0) return i; if (!famT_drive) - if (D_S[d].error_byte!=aud_12) return -501; + if (current_drive->error_byte!=aud_12) return -501; return (0); } @@ -1985,27 +1984,26 @@ static int SetSpeed(void) { int i, speed; - if (!(D_S[d].drv_options&(speed_auto|speed_300|speed_150))) return (0); + if (!(current_drive->drv_options&(speed_auto|speed_300|speed_150))) return (0); speed=speed_auto; - if (!(D_S[d].drv_options&speed_auto)) + if (!(current_drive->drv_options&speed_auto)) { speed |= speed_300; - if (!(D_S[d].drv_options&speed_300)) speed=0; + if (!(current_drive->drv_options&speed_300)) speed=0; } i=cc_SetSpeed(speed,0,0); return (i); } -static void switch_drive(int i); +static void switch_drive(struct sbpcd_drive *); static int sbpcd_select_speed(struct cdrom_device_info *cdi, int speed) { - int i = minor(cdi->dev); + struct sbpcd_drive *p = cdi->handle; + if (p != current_drive) + switch_drive(p); - if (i != d) - switch_drive(i); - - return cc_SetSpeed(speed == 2 ? speed_300 : speed_150, 0, 0); + return cc_SetSpeed(speed == 2 ? speed_300 : speed_150, 0, 0); } /*==========================================================================*/ @@ -2026,7 +2024,7 @@ static int DriveReset(void) } while (!st_diskok); #if 000 - D_S[d].CD_changed=1; + current_drive->CD_changed=1; #endif if ((st_door_closed) && (st_caddy_in)) { @@ -2038,12 +2036,10 @@ static int DriveReset(void) static int sbpcd_reset(struct cdrom_device_info *cdi) { - int i = minor(cdi->dev); - - if (i != d) - switch_drive(i); - - return DriveReset(); + struct sbpcd_drive *p = cdi->handle; + if (p != current_drive) + switch_drive(p); + return DriveReset(); } /*==========================================================================*/ @@ -2051,7 +2047,7 @@ static int cc_PlayAudio(int pos_audio_start,int pos_audio_end) { int i, j, n; - if (D_S[d].audio_state==audio_playing) return (-EINVAL); + if (current_drive->audio_state==audio_playing) return (-EINVAL); clr_cmdbuf(); response_count=0; if (famLV_drive) @@ -2141,7 +2137,7 @@ static int cc_Pause_Resume(int pau_res) } else if (famT_drive) { - if (pau_res==3) return (cc_PlayAudio(D_S[d].pos_audio_start,D_S[d].pos_audio_end)); + if (pau_res==3) return (cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end)); else if (pau_res==1) drvcmd[0]=CMDT_PAUSE; else return (-56); } @@ -2154,7 +2150,7 @@ static int cc_LockDoor(char lock) int i; if (fam0_drive) return (0); - msg(DBG_LCK,"cc_LockDoor: %d (drive %d)\n", lock, d); + msg(DBG_LCK,"cc_LockDoor: %d (drive %d)\n", lock, current_drive - D_S); msg(DBG_LCS,"p_door_locked bit %d before\n", st_door_locked); clr_cmdbuf(); response_count=0; @@ -2248,7 +2244,7 @@ static int cc_CloseTray(void) int i; if (fam0_drive) return (0); - msg(DBG_LCK,"cc_CloseTray (drive %d)\n", d); + msg(DBG_LCK,"cc_CloseTray (drive %d)\n", current_drive - D_S); msg(DBG_LCS,"p_door_closed bit %d before\n", st_door_closed); clr_cmdbuf(); @@ -2317,14 +2313,12 @@ static int cc_CloseTray(void) static int sbpcd_tray_move(struct cdrom_device_info *cdi, int position) { - int i; int retval=0; - i = minor(cdi->dev); - switch_drive(i); + switch_drive(cdi->handle); /* DUH! --AJK */ - if(D_S[d].CD_changed != 0xFF) { - D_S[d].CD_changed=0xFF; - D_S[d].diskstate_flags &= ~cd_size_bit; + if(current_drive->CD_changed != 0xFF) { + current_drive->CD_changed=0xFF; + current_drive->diskstate_flags &= ~cd_size_bit; } if (position == 1) { cc_SpinDown(); @@ -2339,7 +2333,7 @@ static int cc_ReadSubQ(void) { int i,j; - D_S[d].diskstate_flags &= ~subq_bit; + current_drive->diskstate_flags &= ~subq_bit; for (j=255;j>0;j--) { clr_cmdbuf(); @@ -2388,26 +2382,26 @@ static int cc_ReadSubQ(void) if (infobuf[0]!=0) break; if ((!st_spinning) || (j==1)) { - D_S[d].SubQ_ctl_adr=D_S[d].SubQ_trk=D_S[d].SubQ_pnt_idx=D_S[d].SubQ_whatisthis=0; - D_S[d].SubQ_run_tot=D_S[d].SubQ_run_trk=0; + current_drive->SubQ_ctl_adr=current_drive->SubQ_trk=current_drive->SubQ_pnt_idx=current_drive->SubQ_whatisthis=0; + current_drive->SubQ_run_tot=current_drive->SubQ_run_trk=0; return (0); } } - if (famT_drive) D_S[d].SubQ_ctl_adr=infobuf[1]; - else D_S[d].SubQ_ctl_adr=swap_nibbles(infobuf[1]); - D_S[d].SubQ_trk=byt2bcd(infobuf[2]); - D_S[d].SubQ_pnt_idx=byt2bcd(infobuf[3]); + if (famT_drive) current_drive->SubQ_ctl_adr=infobuf[1]; + else current_drive->SubQ_ctl_adr=swap_nibbles(infobuf[1]); + current_drive->SubQ_trk=byt2bcd(infobuf[2]); + current_drive->SubQ_pnt_idx=byt2bcd(infobuf[3]); if (fam0LV_drive) i=5; else if (fam12_drive) i=4; else if (famT_drive) i=8; - D_S[d].SubQ_run_tot=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */ + current_drive->SubQ_run_tot=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */ i=7; if (fam0LV_drive) i=9; else if (fam12_drive) i=7; else if (famT_drive) i=4; - D_S[d].SubQ_run_trk=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */ - D_S[d].SubQ_whatisthis=infobuf[i+3]; - D_S[d].diskstate_flags |= subq_bit; + current_drive->SubQ_run_trk=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */ + current_drive->SubQ_whatisthis=infobuf[i+3]; + current_drive->diskstate_flags |= subq_bit; return (0); } /*==========================================================================*/ @@ -2417,7 +2411,7 @@ static int cc_ModeSense(void) if (fam2_drive) return (0); if (famV_drive) return (0); - D_S[d].diskstate_flags &= ~frame_size_bit; + current_drive->diskstate_flags &= ~frame_size_bit; clr_cmdbuf(); if (fam1_drive) { @@ -2441,21 +2435,21 @@ static int cc_ModeSense(void) i=cmd_out(); if (i<0) return (i); i=0; - D_S[d].sense_byte=0; - if (fam1_drive) D_S[d].sense_byte=infobuf[i++]; + current_drive->sense_byte=0; + if (fam1_drive) current_drive->sense_byte=infobuf[i++]; else if (famT_drive) { - if (infobuf[4]==0x01) D_S[d].xa_byte=0x20; - else D_S[d].xa_byte=0; + if (infobuf[4]==0x01) current_drive->xa_byte=0x20; + else current_drive->xa_byte=0; i=2; } - D_S[d].frame_size=make16(infobuf[i],infobuf[i+1]); + current_drive->frame_size=make16(infobuf[i],infobuf[i+1]); for (i=0;i<response_count;i++) sprintf(&msgbuf[i*3], " %02X", infobuf[i]); msgbuf[i*3]=0; msg(DBG_XA1,"cc_ModeSense:%s\n", msgbuf); - D_S[d].diskstate_flags |= frame_size_bit; + current_drive->diskstate_flags |= frame_size_bit; return (0); } /*==========================================================================*/ @@ -2466,30 +2460,30 @@ static int cc_ModeSelect(int framesize) if (fam2_drive) return (0); if (famV_drive) return (0); - D_S[d].diskstate_flags &= ~frame_size_bit; + current_drive->diskstate_flags &= ~frame_size_bit; clr_cmdbuf(); - D_S[d].frame_size=framesize; - if (framesize==CD_FRAMESIZE_RAW) D_S[d].sense_byte=0x82; - else D_S[d].sense_byte=0x00; + current_drive->frame_size=framesize; + if (framesize==CD_FRAMESIZE_RAW) current_drive->sense_byte=0x82; + else current_drive->sense_byte=0x00; msg(DBG_XA1,"cc_ModeSelect: %02X %04X\n", - D_S[d].sense_byte, D_S[d].frame_size); + current_drive->sense_byte, current_drive->frame_size); if (fam1_drive) { drvcmd[0]=CMD1_SETMODE; drvcmd[1]=0x00; - drvcmd[2]=D_S[d].sense_byte; - drvcmd[3]=(D_S[d].frame_size>>8)&0xFF; - drvcmd[4]=D_S[d].frame_size&0xFF; + drvcmd[2]=current_drive->sense_byte; + drvcmd[3]=(current_drive->frame_size>>8)&0xFF; + drvcmd[4]=current_drive->frame_size&0xFF; flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; } else if (fam0L_drive) { drvcmd[0]=CMD0_SETMODE; drvcmd[1]=0x00; - drvcmd[2]=(D_S[d].frame_size>>8)&0xFF; - drvcmd[3]=D_S[d].frame_size&0xFF; + drvcmd[2]=(current_drive->frame_size>>8)&0xFF; + drvcmd[3]=current_drive->frame_size&0xFF; drvcmd[4]=0x00; if(famL_drive) flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check; @@ -2503,7 +2497,7 @@ static int cc_ModeSelect(int framesize) response_count=0; i=cmd_out(); if (i<0) return (i); - D_S[d].diskstate_flags |= frame_size_bit; + current_drive->diskstate_flags |= frame_size_bit; return (0); } /*==========================================================================*/ @@ -2517,7 +2511,7 @@ static int cc_GetVolume(void) u_char vol1=0; if (famV_drive) return (0); - D_S[d].diskstate_flags &= ~volume_bit; + current_drive->diskstate_flags &= ~volume_bit; clr_cmdbuf(); if (fam1_drive) { @@ -2593,14 +2587,14 @@ static int cc_GetVolume(void) chan0=0; chan1=1; vol0=vol1=infobuf[1]; - if (D_S[d].drv_type>=drv_201) + if (current_drive->drv_type>=drv_201) { - if (D_S[d].drv_type<drv_300) + if (current_drive->drv_type<drv_300) { switches=infobuf[0]; if ((switches&0x80)!=0) vol0=0; if ((switches&0x40)!=0) vol1=0; - if (D_S[d].drv_type>=drv_211) + if (current_drive->drv_type>=drv_211) { if ((switches&0x20)!=0) chan0=1; if ((switches&0x10)!=0) chan1=0; @@ -2620,25 +2614,25 @@ static int cc_GetVolume(void) } else if (famT_drive) { - D_S[d].volume_control=infobuf[7]; + current_drive->volume_control=infobuf[7]; chan0=0; chan1=1; - if (D_S[d].volume_control&0x10) vol0=0; + if (current_drive->volume_control&0x10) vol0=0; else vol0=0xff; - if (D_S[d].volume_control&0x20) vol1=0; + if (current_drive->volume_control&0x20) vol1=0; else vol1=0xff; } - D_S[d].vol_chan0=chan0; - D_S[d].vol_ctrl0=vol0; - D_S[d].vol_chan1=chan1; - D_S[d].vol_ctrl1=vol1; + current_drive->vol_chan0=chan0; + current_drive->vol_ctrl0=vol0; + current_drive->vol_chan1=chan1; + current_drive->vol_ctrl1=vol1; #if 000 - D_S[d].vol_chan2=2; - D_S[d].vol_ctrl2=0xFF; - D_S[d].vol_chan3=3; - D_S[d].vol_ctrl3=0xFF; + current_drive->vol_chan2=2; + current_drive->vol_ctrl2=0xFF; + current_drive->vol_chan3=3; + current_drive->vol_ctrl3=0xFF; #endif /* 000 */ - D_S[d].diskstate_flags |= volume_bit; + current_drive->diskstate_flags |= volume_bit; return (0); } /*==========================================================================*/ @@ -2649,7 +2643,7 @@ static int cc_ReadCapacity(void) if (fam2_drive) return (0); /* some firmware lacks this command */ if (famLV_drive) return (0); /* some firmware lacks this command */ if (famT_drive) return (0); /* done with cc_ReadTocDescr() */ - D_S[d].diskstate_flags &= ~cd_size_bit; + current_drive->diskstate_flags &= ~cd_size_bit; for (j=3;j>0;j--) { clr_cmdbuf(); @@ -2679,13 +2673,13 @@ static int cc_ReadCapacity(void) cc_ReadError(); } if (j==0) return (i); - if (fam1_drive) D_S[d].CDsize_frm=msf2blk(make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])))+CD_MSF_OFFSET; - else if (fam0_drive) D_S[d].CDsize_frm=make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])); + if (fam1_drive) current_drive->CDsize_frm=msf2blk(make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])))+CD_MSF_OFFSET; + else if (fam0_drive) current_drive->CDsize_frm=make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])); #if 00 - else if (fam2_drive) D_S[d].CDsize_frm=make32(make16(infobuf[0],infobuf[1]),make16(infobuf[2],infobuf[3])); + else if (fam2_drive) current_drive->CDsize_frm=make32(make16(infobuf[0],infobuf[1]),make16(infobuf[2],infobuf[3])); #endif - D_S[d].diskstate_flags |= cd_size_bit; - msg(DBG_000,"cc_ReadCapacity: %d frames.\n", D_S[d].CDsize_frm); + current_drive->diskstate_flags |= cd_size_bit; + msg(DBG_000,"cc_ReadCapacity: %d frames.\n", current_drive->CDsize_frm); return (0); } /*==========================================================================*/ @@ -2693,7 +2687,7 @@ static int cc_ReadTocDescr(void) { int i; - D_S[d].diskstate_flags &= ~toc_bit; + current_drive->diskstate_flags &= ~toc_bit; clr_cmdbuf(); if (fam1_drive) { @@ -2713,7 +2707,7 @@ static int cc_ReadTocDescr(void) else if (fam2_drive) { /* possibly longer timeout periods necessary */ - D_S[d].f_multisession=0; + current_drive->f_multisession=0; drvcmd[0]=CMD2_DISKINFO; drvcmd[1]=0x02; drvcmd[2]=0xAB; @@ -2723,7 +2717,7 @@ static int cc_ReadTocDescr(void) } else if (famT_drive) { - D_S[d].f_multisession=0; + current_drive->f_multisession=0; response_count=12; drvcmd[0]=CMDT_DISKINFO; drvcmd[1]=0x02; @@ -2735,25 +2729,25 @@ static int cc_ReadTocDescr(void) if (i<0) return (i); if ((famT_drive)&&(i<response_count)) return (-100-i); if ((fam1_drive)||(fam2_drive)||(fam0LV_drive)) - D_S[d].xa_byte=infobuf[0]; + current_drive->xa_byte=infobuf[0]; if (fam2_drive) { - D_S[d].first_session=infobuf[1]; - D_S[d].last_session=infobuf[2]; - D_S[d].n_first_track=infobuf[3]; - D_S[d].n_last_track=infobuf[4]; - if (D_S[d].first_session!=D_S[d].last_session) + current_drive->first_session=infobuf[1]; + current_drive->last_session=infobuf[2]; + current_drive->n_first_track=infobuf[3]; + current_drive->n_last_track=infobuf[4]; + if (current_drive->first_session!=current_drive->last_session) { - D_S[d].f_multisession=1; - D_S[d].lba_multi=msf2blk(make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7]))); + current_drive->f_multisession=1; + current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7]))); } #if 0 - if (D_S[d].first_session!=D_S[d].last_session) + if (current_drive->first_session!=current_drive->last_session) { - if (D_S[d].last_session<=20) - zwanzig=D_S[d].last_session+1; + if (current_drive->last_session<=20) + zwanzig=current_drive->last_session+1; else zwanzig=20; - for (count=D_S[d].first_session;count<zwanzig;count++) + for (count=current_drive->first_session;count<zwanzig;count++) { drvcmd[0]=CMD2_DISKINFO; drvcmd[1]=0x02; @@ -2763,9 +2757,9 @@ static int cc_ReadTocDescr(void) flags_cmd_out=f_putcmd; i=cmd_out(); if (i<0) return (i); - D_S[d].msf_multi_n[count]=make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7])); + current_drive->msf_multi_n[count]=make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7])); } - D_S[d].diskstate_flags |= multisession_bit; + current_drive->diskstate_flags |= multisession_bit; } #endif drvcmd[0]=CMD2_DISKINFO; @@ -2776,34 +2770,34 @@ static int cc_ReadTocDescr(void) flags_cmd_out=f_putcmd; i=cmd_out(); if (i<0) return (i); - D_S[d].size_msf=make32(make16(0,infobuf[2]),make16(infobuf[3],infobuf[4])); - D_S[d].size_blk=msf2blk(D_S[d].size_msf); - D_S[d].CDsize_frm=D_S[d].size_blk+1; + current_drive->size_msf=make32(make16(0,infobuf[2]),make16(infobuf[3],infobuf[4])); + current_drive->size_blk=msf2blk(current_drive->size_msf); + current_drive->CDsize_frm=current_drive->size_blk+1; } else if (famT_drive) { - D_S[d].size_msf=make32(make16(infobuf[8],infobuf[9]),make16(infobuf[10],infobuf[11])); - D_S[d].size_blk=msf2blk(D_S[d].size_msf); - D_S[d].CDsize_frm=D_S[d].size_blk+1; - D_S[d].n_first_track=infobuf[2]; - D_S[d].n_last_track=infobuf[3]; + current_drive->size_msf=make32(make16(infobuf[8],infobuf[9]),make16(infobuf[10],infobuf[11])); + current_drive->size_blk=msf2blk(current_drive->size_msf); + current_drive->CDsize_frm=current_drive->size_blk+1; + current_drive->n_first_track=infobuf[2]; + current_drive->n_last_track=infobuf[3]; } else { - D_S[d].n_first_track=infobuf[1]; - D_S[d].n_last_track=infobuf[2]; - D_S[d].size_msf=make32(make16(0,infobuf[3]),make16(infobuf[4],infobuf[5])); - D_S[d].size_blk=msf2blk(D_S[d].size_msf); - if (famLV_drive) D_S[d].CDsize_frm=D_S[d].size_blk+1; + current_drive->n_first_track=infobuf[1]; + current_drive->n_last_track=infobuf[2]; + current_drive->size_msf=make32(make16(0,infobuf[3]),make16(infobuf[4],infobuf[5])); + current_drive->size_blk=msf2blk(current_drive->size_msf); + if (famLV_drive) current_drive->CDsize_frm=current_drive->size_blk+1; } - D_S[d].diskstate_flags |= toc_bit; + current_drive->diskstate_flags |= toc_bit; msg(DBG_TOC,"TocDesc: xa %02X firstt %02X lastt %02X size %08X firstses %02X lastsess %02X\n", - D_S[d].xa_byte, - D_S[d].n_first_track, - D_S[d].n_last_track, - D_S[d].size_msf, - D_S[d].first_session, - D_S[d].last_session); + current_drive->xa_byte, + current_drive->n_first_track, + current_drive->n_last_track, + current_drive->size_msf, + current_drive->first_session, + current_drive->last_session); return (0); } /*==========================================================================*/ @@ -2853,36 +2847,36 @@ static int cc_ReadTocEntry(int num) if ((famT_drive)&&(i<response_count)) return (-100-i); if ((fam1_drive)||(fam0LV_drive)) { - D_S[d].TocEnt_nixbyte=infobuf[0]; + current_drive->TocEnt_nixbyte=infobuf[0]; i=1; } else if (fam2_drive) i=0; else if (famT_drive) i=5; - D_S[d].TocEnt_ctl_adr=swap_nibbles(infobuf[i++]); + current_drive->TocEnt_ctl_adr=swap_nibbles(infobuf[i++]); if ((fam1_drive)||(fam0L_drive)) { - D_S[d].TocEnt_number=infobuf[i++]; - D_S[d].TocEnt_format=infobuf[i]; + current_drive->TocEnt_number=infobuf[i++]; + current_drive->TocEnt_format=infobuf[i]; } else { - D_S[d].TocEnt_number=num; - D_S[d].TocEnt_format=0; + current_drive->TocEnt_number=num; + current_drive->TocEnt_format=0; } if (fam1_drive) i=4; else if (fam0LV_drive) i=5; else if (fam2_drive) i=2; else if (famT_drive) i=9; - D_S[d].TocEnt_address=make32(make16(0,infobuf[i]), + current_drive->TocEnt_address=make32(make16(0,infobuf[i]), make16(infobuf[i+1],infobuf[i+2])); for (i=0;i<response_count;i++) sprintf(&msgbuf[i*3], " %02X", infobuf[i]); msgbuf[i*3]=0; msg(DBG_ECS,"TocEntry:%s\n", msgbuf); msg(DBG_TOC,"TocEntry: %02X %02X %02X %02X %08X\n", - D_S[d].TocEnt_nixbyte, D_S[d].TocEnt_ctl_adr, - D_S[d].TocEnt_number, D_S[d].TocEnt_format, - D_S[d].TocEnt_address); + current_drive->TocEnt_nixbyte, current_drive->TocEnt_ctl_adr, + current_drive->TocEnt_number, current_drive->TocEnt_format, + current_drive->TocEnt_address); return (0); } /*==========================================================================*/ @@ -2913,11 +2907,11 @@ static int convert_UPC(u_char *p) if (fam0L_drive) p[13]=0; for (i=0;i<7;i++) { - if (fam1_drive) D_S[d].UPC_buf[i]=swap_nibbles(*p++); + if (fam1_drive) current_drive->UPC_buf[i]=swap_nibbles(*p++); else if (fam0L_drive) { - D_S[d].UPC_buf[i]=((*p++)<<4)&0xFF; - D_S[d].UPC_buf[i] |= *p++; + current_drive->UPC_buf[i]=((*p++)<<4)&0xFF; + current_drive->UPC_buf[i] |= *p++; } else if (famT_drive) { @@ -2928,7 +2922,7 @@ static int convert_UPC(u_char *p) return (-1); } } - D_S[d].UPC_buf[6] &= 0xF0; + current_drive->UPC_buf[6] &= 0xF0; return (0); } /*==========================================================================*/ @@ -2946,7 +2940,7 @@ static int cc_ReadUPC(void) if (fam0_drive) return (0); /* but it should work */ #endif - D_S[d].diskstate_flags &= ~upc_bit; + current_drive->diskstate_flags &= ~upc_bit; #if TEST_UPC for (block=CD_MSF_OFFSET+1;block<CD_MSF_OFFSET+200;block++) { @@ -3015,20 +3009,20 @@ static int cc_ReadUPC(void) if ((checksum&0x7F)!=0) break; } #endif /* TEST_UPC */ - D_S[d].UPC_ctl_adr=0; + current_drive->UPC_ctl_adr=0; if (fam1_drive) i=0; else i=2; if ((infobuf[i]&0x80)!=0) { convert_UPC(&infobuf[i]); - D_S[d].UPC_ctl_adr = (D_S[d].TocEnt_ctl_adr & 0xF0) | 0x02; + current_drive->UPC_ctl_adr = (current_drive->TocEnt_ctl_adr & 0xF0) | 0x02; } for (i=0;i<7;i++) - sprintf(&msgbuf[i*3], " %02X", D_S[d].UPC_buf[i]); - sprintf(&msgbuf[i*3], " (%02X)", D_S[d].UPC_ctl_adr); + sprintf(&msgbuf[i*3], " %02X", current_drive->UPC_buf[i]); + sprintf(&msgbuf[i*3], " (%02X)", current_drive->UPC_ctl_adr); msgbuf[i*3+5]=0; msg(DBG_UPC,"UPC code:%s\n", msgbuf); - D_S[d].diskstate_flags |= upc_bit; + current_drive->diskstate_flags |= upc_bit; return (0); } @@ -3038,7 +3032,7 @@ static int sbpcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) unsigned char *mcnp = mcn->medium_catalog_number; unsigned char *resp; - D_S[d].diskstate_flags &= ~upc_bit; + current_drive->diskstate_flags &= ~upc_bit; clr_cmdbuf(); if (fam1_drive) { @@ -3077,7 +3071,7 @@ static int sbpcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) return (i); } } - D_S[d].UPC_ctl_adr=0; + current_drive->UPC_ctl_adr=0; if (fam1_drive) i=0; else i=2; @@ -3100,7 +3094,7 @@ static int sbpcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) } *mcnp = '\0'; - D_S[d].diskstate_flags |= upc_bit; + current_drive->diskstate_flags |= upc_bit; return (0); } @@ -3110,8 +3104,8 @@ static int cc_CheckMultiSession(void) int i; if (fam2_drive) return (0); - D_S[d].f_multisession=0; - D_S[d].lba_multi=0; + current_drive->f_multisession=0; + current_drive->lba_multi=0; if (fam0_drive) return (0); clr_cmdbuf(); if (fam1_drive) @@ -3123,8 +3117,8 @@ static int cc_CheckMultiSession(void) if (i<0) return (i); if ((infobuf[0]&0x80)!=0) { - D_S[d].f_multisession=1; - D_S[d].lba_multi=msf2blk(make32(make16(0,infobuf[1]), + current_drive->f_multisession=1; + current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[1]), make16(infobuf[2],infobuf[3]))); } } @@ -3137,7 +3131,7 @@ static int cc_CheckMultiSession(void) flags_cmd_out=f_putcmd; i=cmd_out(); if (i<0) return (i); - D_S[d].lba_multi=msf2blk(make32(make16(0,infobuf[5]), + current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[5]), make16(infobuf[6],infobuf[7]))); } else if (famT_drive) @@ -3151,23 +3145,23 @@ static int cc_CheckMultiSession(void) i=cmd_out(); if (i<0) return (i); if (i<response_count) return (-100-i); - D_S[d].first_session=infobuf[2]; - D_S[d].last_session=infobuf[3]; - D_S[d].track_of_last_session=infobuf[6]; - if (D_S[d].first_session!=D_S[d].last_session) + current_drive->first_session=infobuf[2]; + current_drive->last_session=infobuf[3]; + current_drive->track_of_last_session=infobuf[6]; + if (current_drive->first_session!=current_drive->last_session) { - D_S[d].f_multisession=1; - D_S[d].lba_multi=msf2blk(make32(make16(0,infobuf[9]),make16(infobuf[10],infobuf[11]))); + current_drive->f_multisession=1; + current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[9]),make16(infobuf[10],infobuf[11]))); } } for (i=0;i<response_count;i++) sprintf(&msgbuf[i*3], " %02X", infobuf[i]); msgbuf[i*3]=0; - msg(DBG_MUL,"MultiSession Info:%s (%d)\n", msgbuf, D_S[d].lba_multi); - if (D_S[d].lba_multi>200) + msg(DBG_MUL,"MultiSession Info:%s (%d)\n", msgbuf, current_drive->lba_multi); + if (current_drive->lba_multi>200) { - D_S[d].f_multisession=1; - msg(DBG_MUL,"MultiSession base: %06X\n", D_S[d].lba_multi); + current_drive->f_multisession=1; + msg(DBG_MUL,"MultiSession base: %06X\n", current_drive->lba_multi); } return (0); } @@ -3184,7 +3178,7 @@ static int cc_SubChanInfo(int frame, int count, u_char *buffer) return (-1); } #if 0 - if (D_S[d].audio_state!=audio_playing) return (-ENODATA); + if (current_drive->audio_state!=audio_playing) return (-ENODATA); #endif clr_cmdbuf(); drvcmd[0]=CMD1_SUBCHANINF; @@ -3195,7 +3189,7 @@ static int cc_SubChanInfo(int frame, int count, u_char *buffer) drvcmd[6]=count&0xFF; flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check; cmd_type=READ_SC; - D_S[d].frame_size=CD_FRAMESIZE_SUB; + current_drive->frame_size=CD_FRAMESIZE_SUB; i=cmd_out(); /* which buffer to use? */ return (i); } @@ -3279,7 +3273,7 @@ static void __init ask_mail(void) msg(DBG_INF, "(don't mail if you are not using the actual kernel):\n"); msg(DBG_INF, "%s\n", VERSION); msg(DBG_INF, "address %03X, type %s, drive %s (ID %d)\n", - CDo_command, type, D_S[d].drive_model, D_S[d].drv_id); + CDo_command, type, current_drive->drive_model, current_drive->drv_id); for (i=0;i<12;i++) sprintf(&msgbuf[i*3], " %02X", infobuf[i]); msgbuf[i*3]=0; @@ -3295,8 +3289,8 @@ static int __init check_version(void) int i, j, l; int teac_possible=0; - msg(DBG_INI,"check_version: id=%d, d=%d.\n", D_S[d].drv_id, d); - D_S[d].drv_type=0; + msg(DBG_INI,"check_version: id=%d, d=%d.\n", current_drive->drv_id, current_drive - D_S); + current_drive->drv_type=0; /* check for CR-52x, CR-56x, LCS-7260 and ECS-AT */ /* clear any pending error state */ @@ -3331,54 +3325,54 @@ static int __init check_version(void) for (i=0;i<4;i++) if (infobuf[i]!=family1[i]) break; if (i==4) { - D_S[d].drive_model[0]='C'; - D_S[d].drive_model[1]='R'; - D_S[d].drive_model[2]='-'; - D_S[d].drive_model[3]='5'; - D_S[d].drive_model[4]=infobuf[i++]; - D_S[d].drive_model[5]=infobuf[i++]; - D_S[d].drive_model[6]=0; - D_S[d].drv_type=drv_fam1; + current_drive->drive_model[0]='C'; + current_drive->drive_model[1]='R'; + current_drive->drive_model[2]='-'; + current_drive->drive_model[3]='5'; + current_drive->drive_model[4]=infobuf[i++]; + current_drive->drive_model[5]=infobuf[i++]; + current_drive->drive_model[6]=0; + current_drive->drv_type=drv_fam1; } - if (!D_S[d].drv_type) + if (!current_drive->drv_type) { for (i=0;i<8;i++) if (infobuf[i]!=family0[i]) break; if (i==8) { - D_S[d].drive_model[0]='C'; - D_S[d].drive_model[1]='R'; - D_S[d].drive_model[2]='-'; - D_S[d].drive_model[3]='5'; - D_S[d].drive_model[4]='2'; - D_S[d].drive_model[5]='x'; - D_S[d].drive_model[6]=0; - D_S[d].drv_type=drv_fam0; + current_drive->drive_model[0]='C'; + current_drive->drive_model[1]='R'; + current_drive->drive_model[2]='-'; + current_drive->drive_model[3]='5'; + current_drive->drive_model[4]='2'; + current_drive->drive_model[5]='x'; + current_drive->drive_model[6]=0; + current_drive->drv_type=drv_fam0; } } - if (!D_S[d].drv_type) + if (!current_drive->drv_type) { for (i=0;i<8;i++) if (infobuf[i]!=familyL[i]) break; if (i==8) { for (j=0;j<8;j++) - D_S[d].drive_model[j]=infobuf[j]; - D_S[d].drive_model[8]=0; - D_S[d].drv_type=drv_famL; + current_drive->drive_model[j]=infobuf[j]; + current_drive->drive_model[8]=0; + current_drive->drv_type=drv_famL; } } - if (!D_S[d].drv_type) + if (!current_drive->drv_type) { for (i=0;i<6;i++) if (infobuf[i]!=familyV[i]) break; if (i==6) { for (j=0;j<6;j++) - D_S[d].drive_model[j]=infobuf[j]; - D_S[d].drive_model[6]=0; - D_S[d].drv_type=drv_famV; + current_drive->drive_model[j]=infobuf[j]; + current_drive->drive_model[6]=0; + current_drive->drv_type=drv_famV; i+=2; /* 2 blanks before version */ } } - if (!D_S[d].drv_type) + if (!current_drive->drv_type) { /* check for CD200 */ clr_cmdbuf(); @@ -3395,7 +3389,7 @@ static int __init check_version(void) #if 0 OUT(CDo_reset,0); sbp_sleep(6*HZ); - OUT(CDo_enable,D_S[d].drv_sel); + OUT(CDo_enable,current_drive->drv_sel); #endif drvcmd[0]=CMD2_READ_VER; response_count=12; @@ -3421,37 +3415,37 @@ static int __init check_version(void) for (i=0;i<5;i++) if (infobuf[i]!=family2[i]) break; if (i==5) { - D_S[d].drive_model[0]='C'; - D_S[d].drive_model[1]='D'; - D_S[d].drive_model[2]='2'; - D_S[d].drive_model[3]='0'; - D_S[d].drive_model[4]='0'; - D_S[d].drive_model[5]=infobuf[i++]; - D_S[d].drive_model[6]=infobuf[i++]; - D_S[d].drive_model[7]=0; - D_S[d].drv_type=drv_fam2; + current_drive->drive_model[0]='C'; + current_drive->drive_model[1]='D'; + current_drive->drive_model[2]='2'; + current_drive->drive_model[3]='0'; + current_drive->drive_model[4]='0'; + current_drive->drive_model[5]=infobuf[i++]; + current_drive->drive_model[6]=infobuf[i++]; + current_drive->drive_model[7]=0; + current_drive->drv_type=drv_fam2; } } } - if (!D_S[d].drv_type) + if (!current_drive->drv_type) { /* check for TEAC CD-55A */ msg(DBG_TEA,"teac_possible: %d\n",teac_possible); - for (j=1;j<=((D_S[d].drv_id==0)?3:1);j++) + for (j=1;j<=((current_drive->drv_id==0)?3:1);j++) { - for (l=1;l<=((D_S[d].drv_id==0)?10:1);l++) + for (l=1;l<=((current_drive->drv_id==0)?10:1);l++) { msg(DBG_TEA,"TEAC reset #%d-%d.\n", j, l); if (sbpro_type==1) OUT(CDo_reset,0); else { - OUT(CDo_enable,D_S[d].drv_sel); + OUT(CDo_enable,current_drive->drv_sel); OUT(CDo_sel_i_d,0); OUT(CDo_command,CMDT_RESET); for (i=0;i<9;i++) OUT(CDo_command,0); } sbp_sleep(5*HZ/10); - OUT(CDo_enable,D_S[d].drv_sel); + OUT(CDo_enable,current_drive->drv_sel); OUT(CDo_sel_i_d,0); i=inb(CDi_status); msg(DBG_TEA,"TEAC CDi_status: %02X.\n",i); @@ -3478,82 +3472,82 @@ static int __init check_version(void) for (i=1;i<6;i++) if (infobuf[i]!=familyT[i-1]) break; if (i==6) { - D_S[d].drive_model[0]='C'; - D_S[d].drive_model[1]='D'; - D_S[d].drive_model[2]='-'; - D_S[d].drive_model[3]='5'; - D_S[d].drive_model[4]='5'; - D_S[d].drive_model[5]=0; - D_S[d].drv_type=drv_famT; + current_drive->drive_model[0]='C'; + current_drive->drive_model[1]='D'; + current_drive->drive_model[2]='-'; + current_drive->drive_model[3]='5'; + current_drive->drive_model[4]='5'; + current_drive->drive_model[5]=0; + current_drive->drv_type=drv_famT; } } } - if (!D_S[d].drv_type) + if (!current_drive->drv_type) { - msg(DBG_TEA,"no drive found at address %03X under ID %d.\n",CDo_command,D_S[d].drv_id); + msg(DBG_TEA,"no drive found at address %03X under ID %d.\n",CDo_command,current_drive->drv_id); return (-522); } - for (j=0;j<4;j++) D_S[d].firmware_version[j]=infobuf[i+j]; + for (j=0;j<4;j++) current_drive->firmware_version[j]=infobuf[i+j]; if (famL_drive) { u_char lcs_firm_e1[]="A E1"; u_char lcs_firm_f4[]="A4F4"; for (j=0;j<4;j++) - if (D_S[d].firmware_version[j]!=lcs_firm_e1[j]) break; - if (j==4) D_S[d].drv_type=drv_e1; + if (current_drive->firmware_version[j]!=lcs_firm_e1[j]) break; + if (j==4) current_drive->drv_type=drv_e1; for (j=0;j<4;j++) - if (D_S[d].firmware_version[j]!=lcs_firm_f4[j]) break; - if (j==4) D_S[d].drv_type=drv_f4; + if (current_drive->firmware_version[j]!=lcs_firm_f4[j]) break; + if (j==4) current_drive->drv_type=drv_f4; - if (D_S[d].drv_type==drv_famL) ask_mail(); + if (current_drive->drv_type==drv_famL) ask_mail(); } else if (famT_drive) { j=infobuf[4]; /* one-byte version??? - here: 0x15 */ if (j=='5') { - D_S[d].firmware_version[0]=infobuf[7]; - D_S[d].firmware_version[1]=infobuf[8]; - D_S[d].firmware_version[2]=infobuf[10]; - D_S[d].firmware_version[3]=infobuf[11]; + current_drive->firmware_version[0]=infobuf[7]; + current_drive->firmware_version[1]=infobuf[8]; + current_drive->firmware_version[2]=infobuf[10]; + current_drive->firmware_version[3]=infobuf[11]; } else { if (j!=0x15) ask_mail(); - D_S[d].firmware_version[0]='0'; - D_S[d].firmware_version[1]='.'; - D_S[d].firmware_version[2]='0'+(j>>4); - D_S[d].firmware_version[3]='0'+(j&0x0f); + current_drive->firmware_version[0]='0'; + current_drive->firmware_version[1]='.'; + current_drive->firmware_version[2]='0'+(j>>4); + current_drive->firmware_version[3]='0'+(j&0x0f); } } else /* CR-52x, CR-56x, CD200, ECS-AT */ { - j = (D_S[d].firmware_version[0] & 0x0F) * 100 + - (D_S[d].firmware_version[2] & 0x0F) *10 + - (D_S[d].firmware_version[3] & 0x0F); + j = (current_drive->firmware_version[0] & 0x0F) * 100 + + (current_drive->firmware_version[2] & 0x0F) *10 + + (current_drive->firmware_version[3] & 0x0F); if (fam0_drive) { - if (j<200) D_S[d].drv_type=drv_199; - else if (j<201) D_S[d].drv_type=drv_200; - else if (j<210) D_S[d].drv_type=drv_201; - else if (j<211) D_S[d].drv_type=drv_210; - else if (j<300) D_S[d].drv_type=drv_211; - else if (j>=300) D_S[d].drv_type=drv_300; + if (j<200) current_drive->drv_type=drv_199; + else if (j<201) current_drive->drv_type=drv_200; + else if (j<210) current_drive->drv_type=drv_201; + else if (j<211) current_drive->drv_type=drv_210; + else if (j<300) current_drive->drv_type=drv_211; + else if (j>=300) current_drive->drv_type=drv_300; } else if (fam1_drive) { - if (j<100) D_S[d].drv_type=drv_099; + if (j<100) current_drive->drv_type=drv_099; else { - D_S[d].drv_type=drv_100; + current_drive->drv_type=drv_100; if ((j!=500)&&(j!=102)) ask_mail(); } } else if (fam2_drive) { - if (D_S[d].drive_model[5]=='F') + if (current_drive->drive_model[5]=='F') { if ((j!=1)&&(j!=35)&&(j!=200)&&(j!=210)) ask_mail(); /* unknown version at time */ @@ -3567,20 +3561,21 @@ static int __init check_version(void) } else if (famV_drive) { - if ((j==100)||(j==150)) D_S[d].drv_type=drv_at; + if ((j==100)||(j==150)) current_drive->drv_type=drv_at; ask_mail(); /* hopefully we get some feedback by this */ } } - msg(DBG_LCS,"drive type %02X\n",D_S[d].drv_type); + msg(DBG_LCS,"drive type %02X\n",current_drive->drv_type); msg(DBG_INI,"check_version done.\n"); return (0); } /*==========================================================================*/ -static void switch_drive(int i) +static void switch_drive(struct sbpcd_drive *p) { - d=i; - OUT(CDo_enable,D_S[d].drv_sel); - msg(DBG_DID,"drive %d (ID=%d) activated.\n", i, D_S[d].drv_id); + current_drive = p; + OUT(CDo_enable,current_drive->drv_sel); + msg(DBG_DID,"drive %d (ID=%d) activated.\n", + current_drive - D_S, current_drive->drv_id); return; } /*==========================================================================*/ @@ -3700,23 +3695,24 @@ static int __init check_drives(void) ndrives=0; for (j=0;j<max_drives;j++) { - D_S[ndrives].drv_id=j; - if (sbpro_type==1) D_S[ndrives].drv_sel=(j&0x01)<<1|(j&0x02)>>1; - else D_S[ndrives].drv_sel=j; - switch_drive(ndrives); + struct sbpcd_drive *p = D_S + ndrives; + p->drv_id=j; + if (sbpro_type==1) p->drv_sel=(j&0x01)<<1|(j&0x02)>>1; + else p->drv_sel=j; + switch_drive(p); msg(DBG_INI,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j); msg(DBG_000,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j); i=check_version(); if (i<0) msg(DBG_INI,"check_version returns %d.\n",i); else { - D_S[d].drv_options=drv_pattern[j]; - if (fam0L_drive) D_S[d].drv_options&=~(speed_auto|speed_300|speed_150); + current_drive->drv_options=drv_pattern[j]; + if (fam0L_drive) current_drive->drv_options&=~(speed_auto|speed_300|speed_150); msg(DBG_INF, "Drive %d (ID=%d): %.9s (%.4s) at 0x%03X (type %d)\n", - d, - D_S[d].drv_id, - D_S[d].drive_model, - D_S[d].firmware_version, + current_drive - D_S, + current_drive->drv_id, + current_drive->drive_model, + current_drive->firmware_version, CDo_command, sbpro_type); ndrives++; @@ -3852,7 +3848,7 @@ static int seek_pos_audio_end(void) { int i; - i=msf2blk(D_S[d].pos_audio_end)-1; + i=msf2blk(current_drive->pos_audio_end)-1; if (i<0) return (-1); i=cc_Seek(i,0); return (i); @@ -3862,24 +3858,24 @@ static int seek_pos_audio_end(void) static int ReadToC(void) { int i, j; - D_S[d].diskstate_flags &= ~toc_bit; - D_S[d].ored_ctl_adr=0; + current_drive->diskstate_flags &= ~toc_bit; + current_drive->ored_ctl_adr=0; /* special handling of CD-I HE */ - if ((D_S[d].n_first_track == 2 && D_S[d].n_last_track == 2) || - D_S[d].xa_byte == 0x10) + if ((current_drive->n_first_track == 2 && current_drive->n_last_track == 2) || + current_drive->xa_byte == 0x10) { - D_S[d].TocBuffer[1].nixbyte=0; - D_S[d].TocBuffer[1].ctl_adr=0x40; - D_S[d].TocBuffer[1].number=1; - D_S[d].TocBuffer[1].format=0; - D_S[d].TocBuffer[1].address=blk2msf(0); - D_S[d].ored_ctl_adr |= 0x40; - D_S[d].n_first_track = 1; - D_S[d].n_last_track = 1; - D_S[d].xa_byte = 0x10; + current_drive->TocBuffer[1].nixbyte=0; + current_drive->TocBuffer[1].ctl_adr=0x40; + current_drive->TocBuffer[1].number=1; + current_drive->TocBuffer[1].format=0; + current_drive->TocBuffer[1].address=blk2msf(0); + current_drive->ored_ctl_adr |= 0x40; + current_drive->n_first_track = 1; + current_drive->n_last_track = 1; + current_drive->xa_byte = 0x10; j = 2; } else - for (j=D_S[d].n_first_track;j<=D_S[d].n_last_track;j++) + for (j=current_drive->n_first_track;j<=current_drive->n_last_track;j++) { i=cc_ReadTocEntry(j); if (i<0) @@ -3887,21 +3883,21 @@ static int ReadToC(void) msg(DBG_INF,"cc_ReadTocEntry(%d) returns %d.\n",j,i); return (i); } - D_S[d].TocBuffer[j].nixbyte=D_S[d].TocEnt_nixbyte; - D_S[d].TocBuffer[j].ctl_adr=D_S[d].TocEnt_ctl_adr; - D_S[d].TocBuffer[j].number=D_S[d].TocEnt_number; - D_S[d].TocBuffer[j].format=D_S[d].TocEnt_format; - D_S[d].TocBuffer[j].address=D_S[d].TocEnt_address; - D_S[d].ored_ctl_adr |= D_S[d].TocEnt_ctl_adr; + current_drive->TocBuffer[j].nixbyte=current_drive->TocEnt_nixbyte; + current_drive->TocBuffer[j].ctl_adr=current_drive->TocEnt_ctl_adr; + current_drive->TocBuffer[j].number=current_drive->TocEnt_number; + current_drive->TocBuffer[j].format=current_drive->TocEnt_format; + current_drive->TocBuffer[j].address=current_drive->TocEnt_address; + current_drive->ored_ctl_adr |= current_drive->TocEnt_ctl_adr; } /* fake entry for LeadOut Track */ - D_S[d].TocBuffer[j].nixbyte=0; - D_S[d].TocBuffer[j].ctl_adr=0; - D_S[d].TocBuffer[j].number=CDROM_LEADOUT; - D_S[d].TocBuffer[j].format=0; - D_S[d].TocBuffer[j].address=D_S[d].size_msf; + current_drive->TocBuffer[j].nixbyte=0; + current_drive->TocBuffer[j].ctl_adr=0; + current_drive->TocBuffer[j].number=CDROM_LEADOUT; + current_drive->TocBuffer[j].format=0; + current_drive->TocBuffer[j].address=current_drive->size_msf; - D_S[d].diskstate_flags |= toc_bit; + current_drive->diskstate_flags |= toc_bit; return (0); } /*==========================================================================*/ @@ -3909,7 +3905,7 @@ static int DiskInfo(void) { int i, j; - D_S[d].mode=READ_M1; + current_drive->mode=READ_M1; #undef LOOP_COUNT #define LOOP_COUNT 10 /* needed for some "old" drives */ @@ -3959,9 +3955,9 @@ static int DiskInfo(void) msg(DBG_INF,"DiskInfo: cc_CheckMultiSession returns %d\n", i); return (i); } - if (D_S[d].f_multisession) D_S[d].sbp_bufsiz=1; /* possibly a weird PhotoCD */ - else D_S[d].sbp_bufsiz=buffers; - i=cc_ReadTocEntry(D_S[d].n_first_track); + if (current_drive->f_multisession) current_drive->sbp_bufsiz=1; /* possibly a weird PhotoCD */ + else current_drive->sbp_bufsiz=buffers; + i=cc_ReadTocEntry(current_drive->n_first_track); if (i<0) { msg(DBG_INF,"DiskInfo: cc_ReadTocEntry(1) returns %d\n", i); @@ -3969,7 +3965,7 @@ static int DiskInfo(void) } i=cc_ReadUPC(); if (i<0) msg(DBG_INF,"DiskInfo: cc_ReadUPC returns %d\n", i); - if ((fam0L_drive) && (D_S[d].xa_byte==0x20 || D_S[d].xa_byte == 0x10)) + if ((fam0L_drive) && (current_drive->xa_byte==0x20 || current_drive->xa_byte == 0x10)) { /* XA disk with old drive */ cc_ModeSelect(CD_FRAMESIZE_RAW1); @@ -3982,6 +3978,7 @@ static int DiskInfo(void) static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr) { + struct sbpcd_drive *p = cdi->handle; int st; if (CDSL_CURRENT != slot_nr) { @@ -4004,13 +4001,13 @@ static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr) msg(DBG_000,"Drive Status: busy =%d.\n", st_busy); #if 0 - if (!(D_S[minor(cdi->dev)].status_bits & p_door_closed)) return CDS_TRAY_OPEN; - if (D_S[minor(cdi->dev)].status_bits & p_disk_ok) return CDS_DISC_OK; - if (D_S[minor(cdi->dev)].status_bits & p_disk_in) return CDS_DRIVE_NOT_READY; + if (!(p->status_bits & p_door_closed)) return CDS_TRAY_OPEN; + if (p->status_bits & p_disk_ok) return CDS_DISC_OK; + if (p->status_bits & p_disk_in) return CDS_DRIVE_NOT_READY; return CDS_NO_DISC; #else - if (D_S[minor(cdi->dev)].status_bits & p_spinning) return CDS_DISC_OK; + if (p->status_bits & p_spinning) return CDS_DISC_OK; /* return CDS_TRAY_OPEN; */ return CDS_NO_DISC; @@ -4037,10 +4034,10 @@ static int prepare(u_char func, u_char subfunc) else if (fam1_drive) GetStatus(); else if (fam2_drive) GetStatus(); else if (famT_drive) GetStatus(); - if (D_S[d].CD_changed==0xFF) + if (current_drive->CD_changed==0xFF) { - D_S[d].diskstate_flags=0; - D_S[d].audio_state=0; + current_drive->diskstate_flags=0; + current_drive->audio_state=0; if (!st_diskok) { i=check_allowed1(func,subfunc); @@ -4051,7 +4048,7 @@ static int prepare(u_char func, u_char subfunc) i=check_allowed3(func,subfunc); if (i<0) { - D_S[d].CD_changed=1; + current_drive->CD_changed=1; return (-15); } } @@ -4060,8 +4057,8 @@ static int prepare(u_char func, u_char subfunc) { if (!st_diskok) { - D_S[d].diskstate_flags=0; - D_S[d].audio_state=0; + current_drive->diskstate_flags=0; + current_drive->audio_state=0; i=check_allowed1(func,subfunc); if (i<0) return (-2); } @@ -4069,7 +4066,7 @@ static int prepare(u_char func, u_char subfunc) { if (st_busy) { - if (D_S[d].audio_state!=audio_pausing) + if (current_drive->audio_state!=audio_pausing) { i=check_allowed2(func,subfunc); if (i<0) return (-2); @@ -4077,16 +4074,16 @@ static int prepare(u_char func, u_char subfunc) } else { - if (D_S[d].audio_state==audio_playing) seek_pos_audio_end(); - D_S[d].audio_state=0; + if (current_drive->audio_state==audio_playing) seek_pos_audio_end(); + current_drive->audio_state=0; } if (!frame_size_valid) { i=DiskInfo(); if (i<0) { - D_S[d].diskstate_flags=0; - D_S[d].audio_state=0; + current_drive->diskstate_flags=0; + current_drive->audio_state=0; i=check_allowed1(func,subfunc); if (i<0) return (-2); } @@ -4145,9 +4142,10 @@ static int sbp_status(void) static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_multisession *ms_infp) { + struct sbpcd_drive *p = cdi->handle; ms_infp->addr_format = CDROM_LBA; - ms_infp->addr.lba = D_S[minor(cdi->dev)].lba_multi; - if (D_S[minor(cdi->dev)].f_multisession) + ms_infp->addr.lba = p->lba_multi; + if (p->f_multisession) ms_infp->xa_flag=1; /* valid redirection address */ else ms_infp->xa_flag=0; /* invalid redirection address */ @@ -4163,20 +4161,19 @@ static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_mu static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, u_long arg) { + struct sbpcd_drive *p = cdi->handle; int i; - msg(DBG_IO2,"ioctl(%d, 0x%08lX, 0x%08lX)\n", - minor(cdi->dev), cmd, arg); - i=minor(cdi->dev); - if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1)) - { - msg(DBG_INF, "ioctl: bad device: %04X\n", cdi->dev); + msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08lX)\n", cdi->name, cmd, arg); + if (p->drv_id==-1) { + msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name); return (-ENXIO); /* no such drive */ } down(&ioctl_read_sem); - if (d!=i) switch_drive(i); + if (p != current_drive) + switch_drive(p); - msg(DBG_IO2,"ioctl: device %d, request %04X\n",i,cmd); + msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd); switch (cmd) /* Sun-compatible */ { case DDIOCSDBG: /* DDI Debug */ @@ -4186,52 +4183,52 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, case CDROMRESET: /* hard reset the drive */ msg(DBG_IOC,"ioctl: CDROMRESET entered.\n"); i=DriveReset(); - D_S[d].audio_state=0; + current_drive->audio_state=0; RETURN_UP(i); case CDROMREADMODE1: msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n"); #if SAFE_MIXED - if (D_S[d].has_data>1) RETURN_UP(-EBUSY); + if (current_drive->has_data>1) RETURN_UP(-EBUSY); #endif /* SAFE_MIXED */ cc_ModeSelect(CD_FRAMESIZE); cc_ModeSense(); - D_S[d].mode=READ_M1; + current_drive->mode=READ_M1; RETURN_UP(0); case CDROMREADMODE2: /* not usable at the moment */ msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n"); #if SAFE_MIXED - if (D_S[d].has_data>1) RETURN_UP(-EBUSY); + if (current_drive->has_data>1) RETURN_UP(-EBUSY); #endif /* SAFE_MIXED */ cc_ModeSelect(CD_FRAMESIZE_RAW1); cc_ModeSense(); - D_S[d].mode=READ_M2; + current_drive->mode=READ_M2; RETURN_UP(0); case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */ msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n"); - if (D_S[d].sbp_audsiz>0) vfree(D_S[d].aud_buf); - D_S[d].aud_buf=NULL; - D_S[d].sbp_audsiz=arg; + if (current_drive->sbp_audsiz>0) vfree(current_drive->aud_buf); + current_drive->aud_buf=NULL; + current_drive->sbp_audsiz=arg; - if (D_S[d].sbp_audsiz>16) + if (current_drive->sbp_audsiz>16) { - D_S[d].sbp_audsiz = 0; - RETURN_UP(D_S[d].sbp_audsiz); + current_drive->sbp_audsiz = 0; + RETURN_UP(current_drive->sbp_audsiz); } - if (D_S[d].sbp_audsiz>0) + if (current_drive->sbp_audsiz>0) { - D_S[d].aud_buf=(u_char *) vmalloc(D_S[d].sbp_audsiz*CD_FRAMESIZE_RAW); - if (D_S[d].aud_buf==NULL) + current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW); + if (current_drive->aud_buf==NULL) { - msg(DBG_INF,"audio buffer (%d frames) not available.\n",D_S[d].sbp_audsiz); - D_S[d].sbp_audsiz=0; + msg(DBG_INF,"audio buffer (%d frames) not available.\n",current_drive->sbp_audsiz); + current_drive->sbp_audsiz=0; } - else msg(DBG_INF,"audio buffer size: %d frames.\n",D_S[d].sbp_audsiz); + else msg(DBG_INF,"audio buffer size: %d frames.\n",current_drive->sbp_audsiz); } - RETURN_UP(D_S[d].sbp_audsiz); + RETURN_UP(current_drive->sbp_audsiz); case CDROMREADAUDIO: { /* start of CDROMREADAUDIO */ @@ -4251,13 +4248,13 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, if (famV_drive) RETURN_UP(-EINVAL); if (famT_drive) RETURN_UP(-EINVAL); #if SAFE_MIXED - if (D_S[d].has_data>1) RETURN_UP(-EBUSY); + if (current_drive->has_data>1) RETURN_UP(-EBUSY); #endif /* SAFE_MIXED */ - if (D_S[d].aud_buf==NULL) RETURN_UP(-EINVAL); + if (current_drive->aud_buf==NULL) RETURN_UP(-EINVAL); if (copy_from_user(&read_audio, (void *)arg, sizeof(struct cdrom_read_audio))) RETURN_UP(-EFAULT); - if (read_audio.nframes < 0 || read_audio.nframes>D_S[d].sbp_audsiz) RETURN_UP(-EINVAL); + if (read_audio.nframes < 0 || read_audio.nframes>current_drive->sbp_audsiz) RETURN_UP(-EINVAL); i=verify_area(VERIFY_WRITE, read_audio.buf, read_audio.nframes*CD_FRAMESIZE_RAW); if (i) RETURN_UP(i); @@ -4282,7 +4279,7 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, for (data_tries=5; data_tries>0; data_tries--) { msg(DBG_AUD,"data_tries=%d ...\n", data_tries); - D_S[d].mode=READ_AU; + current_drive->mode=READ_AU; cc_ModeSelect(CD_FRAMESIZE_RAW); cc_ModeSense(); for (status_tries=3; status_tries > 0; status_tries--) @@ -4372,13 +4369,13 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, } msg(DBG_AUD,"read_audio: before reading data.\n"); error_flag=0; - p = D_S[d].aud_buf; + p = current_drive->aud_buf; if (sbpro_type==1) OUT(CDo_sel_i_d,1); if (do_16bit) { u_short *p2 = (u_short *) p; - for (; (u_char *) p2 < D_S[d].aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;) + for (; (u_char *) p2 < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;) { if ((inb_p(CDi_status)&s_not_data_ready)) continue; @@ -4387,7 +4384,7 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, *p2++ = inw_p(CDi_data); } } else { - for (; p < D_S[d].aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;) + for (; p < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;) { if ((inb_p(CDi_status)&s_not_data_ready)) continue; @@ -4442,7 +4439,7 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */ if (i<0) { msg(DBG_AUD, "read_audio: cc_ReadStatus error after read: %02X\n", - D_S[d].status_bits); + current_drive->status_bits); continue; /* FIXME */ } } @@ -4454,7 +4451,7 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, continue; } if (copy_to_user((u_char *)read_audio.buf, - (u_char *) D_S[d].aud_buf, + (u_char *) current_drive->aud_buf, read_audio.nframes * CD_FRAMESIZE_RAW)) RETURN_UP(-EFAULT); msg(DBG_AUD,"read_audio: copy_to_user done.\n"); @@ -4462,7 +4459,7 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, } cc_ModeSelect(CD_FRAMESIZE); cc_ModeSense(); - D_S[d].mode=READ_M1; + current_drive->mode=READ_M1; #if OLD_BUSY busy_audio=0; #endif /* OLD_BUSY */ @@ -4484,20 +4481,19 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, void * arg) { + struct sbpcd_drive *p = cdi->handle; int i, st, j; - msg(DBG_IO2,"ioctl(%d, 0x%08lX, 0x%08p)\n", - minor(cdi->dev), cmd, arg); - i=minor(cdi->dev); - if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1)) - { - msg(DBG_INF, "ioctl: bad device: %04X\n", cdi->dev); + msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08p)\n", cdi->name, cmd, arg); + if (p->drv_id==-1) { + msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name); return (-ENXIO); /* no such drive */ } down(&ioctl_read_sem); - if (d!=i) switch_drive(i); + if (p != current_drive) + switch_drive(p); - msg(DBG_IO2,"ioctl: device %d, request %04X\n",i,cmd); + msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd); switch (cmd) /* Sun-compatible */ { @@ -4507,7 +4503,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, /* or reset the starting and ending locations when in PAUSED mode. */ /* If applicable, at the next stopping point it reaches */ /* the drive will discontinue playing. */ - switch (D_S[d].audio_state) + switch (current_drive->audio_state) { case audio_playing: if (famL_drive) i=cc_ReadSubQ(); @@ -4516,11 +4512,11 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, if (famL_drive) i=cc_Pause_Resume(1); else i=cc_ReadSubQ(); if (i<0) RETURN_UP(-EIO); - D_S[d].pos_audio_start=D_S[d].SubQ_run_tot; - D_S[d].audio_state=audio_pausing; + current_drive->pos_audio_start=current_drive->SubQ_run_tot; + current_drive->audio_state=audio_pausing; RETURN_UP(0); case audio_pausing: - i=cc_Seek(D_S[d].pos_audio_start,1); + i=cc_Seek(current_drive->pos_audio_start,1); if (i<0) RETURN_UP(-EIO); RETURN_UP(0); default: @@ -4532,56 +4528,56 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, /* resume playing audio tracks when a previous PLAY AUDIO call has */ /* been paused with a PAUSE command. */ /* It will resume playing from the location saved in SubQ_run_tot. */ - if (D_S[d].audio_state!=audio_pausing) RETURN_UP(-EINVAL); + if (current_drive->audio_state!=audio_pausing) RETURN_UP(-EINVAL); if (famL_drive) - i=cc_PlayAudio(D_S[d].pos_audio_start, - D_S[d].pos_audio_end); + i=cc_PlayAudio(current_drive->pos_audio_start, + current_drive->pos_audio_end); else i=cc_Pause_Resume(3); if (i<0) RETURN_UP(-EIO); - D_S[d].audio_state=audio_playing; + current_drive->audio_state=audio_playing; RETURN_UP(0); case CDROMPLAYMSF: msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n"); #if SAFE_MIXED - if (D_S[d].has_data>1) RETURN_UP(-EBUSY); + if (current_drive->has_data>1) RETURN_UP(-EBUSY); #endif /* SAFE_MIXED */ - if (D_S[d].audio_state==audio_playing) + if (current_drive->audio_state==audio_playing) { i=cc_Pause_Resume(1); if (i<0) RETURN_UP(-EIO); i=cc_ReadSubQ(); if (i<0) RETURN_UP(-EIO); - D_S[d].pos_audio_start=D_S[d].SubQ_run_tot; - i=cc_Seek(D_S[d].pos_audio_start,1); + current_drive->pos_audio_start=current_drive->SubQ_run_tot; + i=cc_Seek(current_drive->pos_audio_start,1); } memcpy(&msf, (void *) arg, sizeof(struct cdrom_msf)); /* values come as msf-bin */ - D_S[d].pos_audio_start = (msf.cdmsf_min0<<16) | + current_drive->pos_audio_start = (msf.cdmsf_min0<<16) | (msf.cdmsf_sec0<<8) | msf.cdmsf_frame0; - D_S[d].pos_audio_end = (msf.cdmsf_min1<<16) | + current_drive->pos_audio_end = (msf.cdmsf_min1<<16) | (msf.cdmsf_sec1<<8) | msf.cdmsf_frame1; msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n", - D_S[d].pos_audio_start,D_S[d].pos_audio_end); - i=cc_PlayAudio(D_S[d].pos_audio_start,D_S[d].pos_audio_end); + current_drive->pos_audio_start,current_drive->pos_audio_end); + i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end); if (i<0) { msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i); DriveReset(); - D_S[d].audio_state=0; + current_drive->audio_state=0; RETURN_UP(-EIO); } - D_S[d].audio_state=audio_playing; + current_drive->audio_state=audio_playing; RETURN_UP(0); case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n"); #if SAFE_MIXED - if (D_S[d].has_data>1) RETURN_UP(-EBUSY); + if (current_drive->has_data>1) RETURN_UP(-EBUSY); #endif /* SAFE_MIXED */ - if (D_S[d].audio_state==audio_playing) + if (current_drive->audio_state==audio_playing) { msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n"); #if 1 @@ -4593,27 +4589,27 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, memcpy(&ti,(void *) arg,sizeof(struct cdrom_ti)); msg(DBG_IOX,"ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n", ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1); - if (ti.cdti_trk0<D_S[d].n_first_track) RETURN_UP(-EINVAL); - if (ti.cdti_trk0>D_S[d].n_last_track) RETURN_UP(-EINVAL); + if (ti.cdti_trk0<current_drive->n_first_track) RETURN_UP(-EINVAL); + if (ti.cdti_trk0>current_drive->n_last_track) RETURN_UP(-EINVAL); if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0; - if (ti.cdti_trk1>D_S[d].n_last_track) ti.cdti_trk1=D_S[d].n_last_track; - D_S[d].pos_audio_start=D_S[d].TocBuffer[ti.cdti_trk0].address; - D_S[d].pos_audio_end=D_S[d].TocBuffer[ti.cdti_trk1+1].address; - i=cc_PlayAudio(D_S[d].pos_audio_start,D_S[d].pos_audio_end); + if (ti.cdti_trk1>current_drive->n_last_track) ti.cdti_trk1=current_drive->n_last_track; + current_drive->pos_audio_start=current_drive->TocBuffer[ti.cdti_trk0].address; + current_drive->pos_audio_end=current_drive->TocBuffer[ti.cdti_trk1+1].address; + i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end); if (i<0) { msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i); DriveReset(); - D_S[d].audio_state=0; + current_drive->audio_state=0; RETURN_UP(-EIO); } - D_S[d].audio_state=audio_playing; + current_drive->audio_state=audio_playing; RETURN_UP(0); case CDROMREADTOCHDR: /* Read the table of contents header */ msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n"); - tochdr.cdth_trk0=D_S[d].n_first_track; - tochdr.cdth_trk1=D_S[d].n_last_track; + tochdr.cdth_trk0=current_drive->n_first_track; + tochdr.cdth_trk1=current_drive->n_last_track; memcpy((void *) arg, &tochdr, sizeof(struct cdrom_tochdr)); RETURN_UP(0); @@ -4621,20 +4617,20 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n"); memcpy(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry)); i=tocentry.cdte_track; - if (i==CDROM_LEADOUT) i=D_S[d].n_last_track+1; - else if (i<D_S[d].n_first_track||i>D_S[d].n_last_track) + if (i==CDROM_LEADOUT) i=current_drive->n_last_track+1; + else if (i<current_drive->n_first_track||i>current_drive->n_last_track) RETURN_UP(-EINVAL); - tocentry.cdte_adr=D_S[d].TocBuffer[i].ctl_adr&0x0F; - tocentry.cdte_ctrl=(D_S[d].TocBuffer[i].ctl_adr>>4)&0x0F; - tocentry.cdte_datamode=D_S[d].TocBuffer[i].format; + tocentry.cdte_adr=current_drive->TocBuffer[i].ctl_adr&0x0F; + tocentry.cdte_ctrl=(current_drive->TocBuffer[i].ctl_adr>>4)&0x0F; + tocentry.cdte_datamode=current_drive->TocBuffer[i].format; if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */ { - tocentry.cdte_addr.msf.minute=(D_S[d].TocBuffer[i].address>>16)&0x00FF; - tocentry.cdte_addr.msf.second=(D_S[d].TocBuffer[i].address>>8)&0x00FF; - tocentry.cdte_addr.msf.frame=D_S[d].TocBuffer[i].address&0x00FF; + tocentry.cdte_addr.msf.minute=(current_drive->TocBuffer[i].address>>16)&0x00FF; + tocentry.cdte_addr.msf.second=(current_drive->TocBuffer[i].address>>8)&0x00FF; + tocentry.cdte_addr.msf.frame=current_drive->TocBuffer[i].address&0x00FF; } else if (tocentry.cdte_format==CDROM_LBA) /* blk required */ - tocentry.cdte_addr.lba=msf2blk(D_S[d].TocBuffer[i].address); + tocentry.cdte_addr.lba=msf2blk(current_drive->TocBuffer[i].address); else RETURN_UP(-EINVAL); memcpy((void *) arg, &tocentry, sizeof(struct cdrom_tocentry)); RETURN_UP(0); @@ -4642,10 +4638,10 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, case CDROMSTOP: /* Spin down the drive */ msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n"); #if SAFE_MIXED - if (D_S[d].has_data>1) RETURN_UP(-EBUSY); + if (current_drive->has_data>1) RETURN_UP(-EBUSY); #endif /* SAFE_MIXED */ i=cc_Pause_Resume(1); - D_S[d].audio_state=0; + current_drive->audio_state=0; #if 0 cc_DriveReset(); #endif @@ -4654,16 +4650,16 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, case CDROMSTART: /* Spin up the drive */ msg(DBG_IOC,"ioctl: CDROMSTART entered.\n"); cc_SpinUp(); - D_S[d].audio_state=0; + current_drive->audio_state=0; RETURN_UP(0); case CDROMVOLCTRL: /* Volume control */ msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n"); memcpy(&volctrl,(char *) arg,sizeof(volctrl)); - D_S[d].vol_chan0=0; - D_S[d].vol_ctrl0=volctrl.channel0; - D_S[d].vol_chan1=1; - D_S[d].vol_ctrl1=volctrl.channel1; + current_drive->vol_chan0=0; + current_drive->vol_ctrl0=volctrl.channel0; + current_drive->vol_chan1=1; + current_drive->vol_ctrl1=volctrl.channel1; i=cc_SetVolume(); RETURN_UP(0); @@ -4671,8 +4667,8 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n"); st=cc_GetVolume(); if (st<0) RETURN_UP(st); - volctrl.channel0=D_S[d].vol_ctrl0; - volctrl.channel1=D_S[d].vol_ctrl1; + volctrl.channel0=current_drive->vol_ctrl0; + volctrl.channel1=current_drive->vol_ctrl1; volctrl.channel2=0; volctrl.channel2=0; memcpy((void *)arg,&volctrl,sizeof(volctrl)); @@ -4689,22 +4685,22 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, i=cc_ReadSubQ(); if (i<0) { j=cc_ReadError(); /* clear out error status from drive */ - D_S[d].audio_state=CDROM_AUDIO_NO_STATUS; + current_drive->audio_state=CDROM_AUDIO_NO_STATUS; /* get and set the disk state here, probably not the right place, but who cares! It makes it work properly! --AJK */ - if (D_S[d].CD_changed==0xFF) { + if (current_drive->CD_changed==0xFF) { msg(DBG_000,"Disk changed detect\n"); - D_S[d].diskstate_flags &= ~cd_size_bit; + current_drive->diskstate_flags &= ~cd_size_bit; } RETURN_UP(-EIO); } - if (D_S[d].CD_changed==0xFF) { + if (current_drive->CD_changed==0xFF) { /* reread the TOC because the disk has changed! --AJK */ msg(DBG_000,"Disk changed STILL detected, rereading TOC!\n"); i=DiskInfo(); if(i==0) { - D_S[d].CD_changed=0x00; /* cd has changed, procede, */ + current_drive->CD_changed=0x00; /* cd has changed, procede, */ RETURN_UP(-EIO); /* and get TOC, etc on next try! --AJK */ } else { RETURN_UP(-EIO); /* we weren't ready yet! --AJK */ @@ -4725,12 +4721,12 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning); msg(DBG_000,"Drive Status: busy =%d.\n", st_busy); /* st_busy indicates if it's _ACTUALLY_ playing audio */ - switch (D_S[d].audio_state) + switch (current_drive->audio_state) { case audio_playing: if(st_busy==0) { /* CD has stopped playing audio --AJK */ - D_S[d].audio_state=audio_completed; + current_drive->audio_state=audio_completed; SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED; } else { SC.cdsc_audiostatus=CDROM_AUDIO_PLAY; @@ -4746,23 +4742,23 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS; break; } - SC.cdsc_adr=D_S[d].SubQ_ctl_adr; - SC.cdsc_ctrl=D_S[d].SubQ_ctl_adr>>4; - SC.cdsc_trk=bcd2bin(D_S[d].SubQ_trk); - SC.cdsc_ind=bcd2bin(D_S[d].SubQ_pnt_idx); + SC.cdsc_adr=current_drive->SubQ_ctl_adr; + SC.cdsc_ctrl=current_drive->SubQ_ctl_adr>>4; + SC.cdsc_trk=bcd2bin(current_drive->SubQ_trk); + SC.cdsc_ind=bcd2bin(current_drive->SubQ_pnt_idx); if (SC.cdsc_format==CDROM_LBA) { - SC.cdsc_absaddr.lba=msf2blk(D_S[d].SubQ_run_tot); - SC.cdsc_reladdr.lba=msf2blk(D_S[d].SubQ_run_trk); + SC.cdsc_absaddr.lba=msf2blk(current_drive->SubQ_run_tot); + SC.cdsc_reladdr.lba=msf2blk(current_drive->SubQ_run_trk); } else /* not only if (SC.cdsc_format==CDROM_MSF) */ { - SC.cdsc_absaddr.msf.minute=(D_S[d].SubQ_run_tot>>16)&0x00FF; - SC.cdsc_absaddr.msf.second=(D_S[d].SubQ_run_tot>>8)&0x00FF; - SC.cdsc_absaddr.msf.frame=D_S[d].SubQ_run_tot&0x00FF; - SC.cdsc_reladdr.msf.minute=(D_S[d].SubQ_run_trk>>16)&0x00FF; - SC.cdsc_reladdr.msf.second=(D_S[d].SubQ_run_trk>>8)&0x00FF; - SC.cdsc_reladdr.msf.frame=D_S[d].SubQ_run_trk&0x00FF; + SC.cdsc_absaddr.msf.minute=(current_drive->SubQ_run_tot>>16)&0x00FF; + SC.cdsc_absaddr.msf.second=(current_drive->SubQ_run_tot>>8)&0x00FF; + SC.cdsc_absaddr.msf.frame=current_drive->SubQ_run_tot&0x00FF; + SC.cdsc_reladdr.msf.minute=(current_drive->SubQ_run_trk>>16)&0x00FF; + SC.cdsc_reladdr.msf.second=(current_drive->SubQ_run_trk>>8)&0x00FF; + SC.cdsc_reladdr.msf.frame=current_drive->SubQ_run_trk&0x00FF; } memcpy((void *) arg, &SC, sizeof(struct cdrom_subchnl)); msg(DBG_IOS,"CDROMSUBCHNL: %1X %02X %08X %08X %02X %02X %06X %06X\n", @@ -4786,11 +4782,11 @@ static void sbp_transfer(struct request *req) long offs; while ( (req->nr_sectors > 0) && - (req->sector/4 >= D_S[d].sbp_first_frame) && - (req->sector/4 <= D_S[d].sbp_last_frame) ) + (req->sector/4 >= current_drive->sbp_first_frame) && + (req->sector/4 <= current_drive->sbp_last_frame) ) { - offs = (req->sector - D_S[d].sbp_first_frame * 4) * 512; - memcpy(req->buffer, D_S[d].sbp_buf + offs, 512); + offs = (req->sector - current_drive->sbp_first_frame * 4) * 512; + memcpy(req->buffer, current_drive->sbp_buf + offs, 512); req->nr_sectors--; req->sector++; req->buffer += 512; @@ -4833,8 +4829,9 @@ static void do_sbpcd_request(request_queue_t * q) { u_int block; u_int nsect; - int i, status_tries, data_tries; + int status_tries, data_tries; struct request *req; + struct sbpcd_drive *p; #ifdef DEBUG_GTL static int xx_nr=0; int xnr; @@ -4873,9 +4870,8 @@ static void do_sbpcd_request(request_queue_t * q) msg(DBG_INF, "bad cmd %d\n", req->cmd); goto err_done; } - i = minor(req->rq_dev); - if ( (i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1)) - { + p = D_S + minor(req->rq_dev); + if (p->drv_id==-1) { msg(DBG_INF, "do_request: bad device: %s\n", kdevname(req->rq_dev)); goto err_done; @@ -4885,9 +4881,10 @@ static void do_sbpcd_request(request_queue_t * q) busy_data=1; #endif /* OLD_BUSY */ - if (D_S[i].audio_state==audio_playing) goto err_done; - if (d!=i) switch_drive(i); - + if (p->audio_state==audio_playing) goto err_done; + if (p != current_drive) + switch_drive(p); + block = req->sector; /* always numbered as 512-byte-pieces */ nsect = req->nr_sectors; /* always counted as 512-byte-pieces */ @@ -4939,7 +4936,7 @@ static void do_sbpcd_request(request_queue_t * q) if (sbp_data(req) != 0) { #if SAFE_MIXED - D_S[d].has_data=2; /* is really a data disk */ + current_drive->has_data=2; /* is really a data disk */ #endif /* SAFE_MIXED */ #ifdef DEBUG_GTL printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 3, Time:%li\n", @@ -4977,20 +4974,20 @@ static void sbp_read_cmd(struct request *req) int i; int block; - D_S[d].sbp_first_frame=D_S[d].sbp_last_frame=-1; /* purge buffer */ - D_S[d].sbp_current = 0; + current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */ + current_drive->sbp_current = 0; block=req->sector/4; - if (block+D_S[d].sbp_bufsiz <= D_S[d].CDsize_frm) - D_S[d].sbp_read_frames = D_S[d].sbp_bufsiz; + if (block+current_drive->sbp_bufsiz <= current_drive->CDsize_frm) + current_drive->sbp_read_frames = current_drive->sbp_bufsiz; else { - D_S[d].sbp_read_frames=D_S[d].CDsize_frm-block; + current_drive->sbp_read_frames=current_drive->CDsize_frm-block; /* avoid reading past end of data */ - if (D_S[d].sbp_read_frames < 1) + if (current_drive->sbp_read_frames < 1) { msg(DBG_INF,"requested frame %d, CD size %d ???\n", - block, D_S[d].CDsize_frm); - D_S[d].sbp_read_frames=1; + block, current_drive->CDsize_frm); + current_drive->sbp_read_frames=1; } } @@ -5003,27 +5000,27 @@ static void sbp_read_cmd(struct request *req) bin2bcdx(&drvcmd[1]); bin2bcdx(&drvcmd[2]); bin2bcdx(&drvcmd[3]); - drvcmd[4]=D_S[d].sbp_read_frames>>8; - drvcmd[5]=D_S[d].sbp_read_frames&0xff; + drvcmd[4]=current_drive->sbp_read_frames>>8; + drvcmd[5]=current_drive->sbp_read_frames&0xff; drvcmd[6]=0x02; /* flag "msf-bcd" */ } else if (fam0L_drive) { flags_cmd_out |= f_lopsta | f_getsta | f_bit1; - if (D_S[d].xa_byte==0x20) + if (current_drive->xa_byte==0x20) { cmd_type=READ_M2; drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */ drvcmd[1]=(block>>16)&0x0ff; drvcmd[2]=(block>>8)&0x0ff; drvcmd[3]=block&0x0ff; - drvcmd[4]=(D_S[d].sbp_read_frames>>8)&0x0ff; - drvcmd[5]=D_S[d].sbp_read_frames&0x0ff; + drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; + drvcmd[5]=current_drive->sbp_read_frames&0x0ff; } else { drvcmd[0]=CMD0_READ; /* "read frames", old drives */ - if (D_S[d].drv_type>=drv_201) + if (current_drive->drv_type>=drv_201) { lba2msf(block,&drvcmd[1]); /* msf-bcd format required */ bin2bcdx(&drvcmd[1]); @@ -5036,24 +5033,24 @@ static void sbp_read_cmd(struct request *req) drvcmd[2]=(block>>8)&0x0ff; drvcmd[3]=block&0x0ff; } - drvcmd[4]=(D_S[d].sbp_read_frames>>8)&0x0ff; - drvcmd[5]=D_S[d].sbp_read_frames&0x0ff; - drvcmd[6]=(D_S[d].drv_type<drv_201)?0:2; /* flag "lba or msf-bcd format" */ + drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; + drvcmd[5]=current_drive->sbp_read_frames&0x0ff; + drvcmd[6]=(current_drive->drv_type<drv_201)?0:2; /* flag "lba or msf-bcd format" */ } } else if (fam1_drive) { drvcmd[0]=CMD1_READ; lba2msf(block,&drvcmd[1]); /* msf-bin format required */ - drvcmd[5]=(D_S[d].sbp_read_frames>>8)&0x0ff; - drvcmd[6]=D_S[d].sbp_read_frames&0x0ff; + drvcmd[5]=(current_drive->sbp_read_frames>>8)&0x0ff; + drvcmd[6]=current_drive->sbp_read_frames&0x0ff; } else if (fam2_drive) { drvcmd[0]=CMD2_READ; lba2msf(block,&drvcmd[1]); /* msf-bin format required */ - drvcmd[4]=(D_S[d].sbp_read_frames>>8)&0x0ff; - drvcmd[5]=D_S[d].sbp_read_frames&0x0ff; + drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; + drvcmd[5]=current_drive->sbp_read_frames&0x0ff; drvcmd[6]=0x02; } else if (famT_drive) @@ -5063,8 +5060,8 @@ static void sbp_read_cmd(struct request *req) drvcmd[3]=(block>>16)&0x0ff; drvcmd[4]=(block>>8)&0x0ff; drvcmd[5]=block&0x0ff; - drvcmd[7]=(D_S[d].sbp_read_frames>>8)&0x0ff; - drvcmd[8]=D_S[d].sbp_read_frames&0x0ff; + drvcmd[7]=(current_drive->sbp_read_frames>>8)&0x0ff; + drvcmd[8]=current_drive->sbp_read_frames&0x0ff; } flags_cmd_out=f_putcmd; response_count=0; @@ -5075,7 +5072,7 @@ static void sbp_read_cmd(struct request *req) /*==========================================================================*/ /* * Check the completion of the read-data command. On success, read - * the D_S[d].sbp_bufsiz * 2048 bytes of data from the disk into buffer. + * the current_drive->sbp_bufsiz * 2048 bytes of data from the disk into buffer. */ static int sbp_data(struct request *req) { @@ -5098,11 +5095,11 @@ static int sbp_data(struct request *req) #if LONG_TIMING max_latency=9*HZ; #else - if (D_S[d].f_multisession) max_latency=15*HZ; + if (current_drive->f_multisession) max_latency=15*HZ; else max_latency=5*HZ; #endif duration=jiffies; - for (frame=0;frame<D_S[d].sbp_read_frames&&!error_flag; frame++) + for (frame=0;frame<current_drive->sbp_read_frames&&!error_flag; frame++) { SBPCD_CLI; @@ -5112,7 +5109,7 @@ static int sbp_data(struct request *req) add_timer(&data_timer); while (!timed_out_data) { - if (D_S[d].f_multisession) try=maxtim_data*4; + if (current_drive->f_multisession) try=maxtim_data*4; else try=maxtim_data; msg(DBG_000,"sbp_data: CDi_status loop: try=%d.\n",try); for ( ; try!=0;try--) @@ -5155,7 +5152,7 @@ static int sbp_data(struct request *req) } if (j&s_not_data_ready) { - if ((D_S[d].ored_ctl_adr&0x40)==0) + if ((current_drive->ored_ctl_adr&0x40)==0) msg(DBG_INF, "CD contains no data tracks.\n"); else msg(DBG_INF, "sbp_data: DATA_READY timeout (%02X).\n", j); error_flag++; @@ -5164,7 +5161,7 @@ static int sbp_data(struct request *req) if (error_flag) break; msg(DBG_000, "sbp_data: beginning to read.\n"); - p = D_S[d].sbp_buf + frame * CD_FRAMESIZE; + p = current_drive->sbp_buf + frame * CD_FRAMESIZE; if (sbpro_type==1) OUT(CDo_sel_i_d,1); if (cmd_type==READ_M2) { if (do_16bit) insw(CDi_data, xa_head_buf, CD_XA_HEAD>>1); @@ -5176,7 +5173,7 @@ static int sbp_data(struct request *req) if (do_16bit) insw(CDi_data, xa_tail_buf, CD_XA_TAIL>>1); else insb(CDi_data, xa_tail_buf, CD_XA_TAIL); } - D_S[d].sbp_current++; + current_drive->sbp_current++; if (sbpro_type==1) OUT(CDo_sel_i_d,0); if (cmd_type==READ_M2) { @@ -5255,9 +5252,9 @@ static int sbp_data(struct request *req) sbp_sleep(1); } while (j<0); - D_S[d].error_state=infobuf[2]; - D_S[d].b3=infobuf[3]; - D_S[d].b4=infobuf[4]; + current_drive->error_state=infobuf[2]; + current_drive->b3=infobuf[3]; + current_drive->b4=infobuf[4]; } break; } @@ -5327,7 +5324,7 @@ static int sbp_data(struct request *req) #endif if (i<0) { - msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", D_S[d].status_bits); + msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", current_drive->status_bits); return (0); } } @@ -5341,14 +5338,14 @@ static int sbp_data(struct request *req) if (fatal_err) { fatal_err=0; - D_S[d].sbp_first_frame=D_S[d].sbp_last_frame=-1; /* purge buffer */ - D_S[d].sbp_current = 0; + current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */ + current_drive->sbp_current = 0; msg(DBG_INF,"sbp_data: fatal_err - retrying.\n"); return (0); } - D_S[d].sbp_first_frame = req -> sector / 4; - D_S[d].sbp_last_frame = D_S[d].sbp_first_frame + D_S[d].sbp_read_frames - 1; + current_drive->sbp_first_frame = req -> sector / 4; + current_drive->sbp_last_frame = current_drive->sbp_first_frame + current_drive->sbp_read_frames - 1; sbp_transfer(req); return (1); } @@ -5368,34 +5365,33 @@ static struct block_device_operations sbpcd_bdops = */ static int sbpcd_open(struct cdrom_device_info *cdi, int purpose) { - int i; - - i = minor(cdi->dev); + struct sbpcd_drive *p = cdi->handle; down(&ioctl_read_sem); - switch_drive(i); + switch_drive(p); /* * try to keep an "open" counter here and lock the door if 0->1. */ msg(DBG_LCK,"open_count: %d -> %d\n", - D_S[d].open_count,D_S[d].open_count+1); - if (++D_S[d].open_count<=1) + current_drive->open_count,current_drive->open_count+1); + if (++current_drive->open_count<=1) { + int i; i=LockDoor(); - D_S[d].open_count=1; + current_drive->open_count=1; if (famT_drive) msg(DBG_TEA,"sbpcd_open: before i=DiskInfo();.\n"); i=DiskInfo(); if (famT_drive) msg(DBG_TEA,"sbpcd_open: after i=DiskInfo();.\n"); - if ((D_S[d].ored_ctl_adr&0x40)==0) + if ((current_drive->ored_ctl_adr&0x40)==0) { msg(DBG_INF,"CD contains no data tracks.\n"); #if SAFE_MIXED - D_S[d].has_data=0; + current_drive->has_data=0; #endif /* SAFE_MIXED */ } #if SAFE_MIXED - else if (D_S[d].has_data<1) D_S[d].has_data=1; + else if (current_drive->has_data<1) current_drive->has_data=1; #endif /* SAFE_MIXED */ } if (!st_spinning) cc_SpinUp(); @@ -5407,32 +5403,30 @@ static int sbpcd_open(struct cdrom_device_info *cdi, int purpose) */ static void sbpcd_release(struct cdrom_device_info * cdi) { - int i; + struct sbpcd_drive *p = cdi->handle; - i = minor(cdi->dev); - if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1)) - { - msg(DBG_INF, "release: bad device: %04X\n", cdi->dev); - return ; + if (p->drv_id==-1) { + msg(DBG_INF, "release: bad device: %s\n", cdi->name); + return; } down(&ioctl_read_sem); - switch_drive(i); + switch_drive(p); /* * try to keep an "open" counter here and unlock the door if 1->0. */ msg(DBG_LCK,"open_count: %d -> %d\n", - D_S[d].open_count,D_S[d].open_count-1); - if (D_S[d].open_count>-2) /* CDROMEJECT may have been done */ + p->open_count,p->open_count-1); + if (p->open_count>-2) /* CDROMEJECT may have been done */ { - if (--D_S[d].open_count<=0) + if (--p->open_count<=0) { - D_S[d].sbp_first_frame=D_S[d].sbp_last_frame=-1; - if (D_S[d].audio_state!=audio_playing) - if (D_S[d].f_eject) cc_SpinDown(); - D_S[d].diskstate_flags &= ~cd_size_bit; - D_S[d].open_count=0; + p->sbp_first_frame=p->sbp_last_frame=-1; + if (p->audio_state!=audio_playing) + if (p->f_eject) cc_SpinDown(); + p->diskstate_flags &= ~cd_size_bit; + p->open_count=0; #if SAFE_MIXED - D_S[d].has_data=0; + p->has_data=0; #endif /* SAFE_MIXED */ } } @@ -5463,13 +5457,6 @@ static struct cdrom_device_ops sbpcd_dops = { n_minors: 1, }; -static struct cdrom_device_info sbpcd_info = { - ops: &sbpcd_dops, - speed: 2, - capacity: 1, - name: "sbpcd", -}; - /*==========================================================================*/ /* * accept "kernel command line" parameters @@ -5708,21 +5695,23 @@ int __init sbpcd_init(void) for (j=0;j<NR_SBPCD;j++) { - if (D_S[j].drv_id==-1) continue; - switch_drive(j); + struct sbpcd_drive *p = D_S + j; + if (p->drv_id==-1) + continue; + switch_drive(p); #if 1 if (!famL_drive) cc_DriveReset(); #endif if (!st_spinning) cc_SpinUp(); - D_S[j].sbp_first_frame = -1; /* First frame in buffer */ - D_S[j].sbp_last_frame = -1; /* Last frame in buffer */ - D_S[j].sbp_read_frames = 0; /* Number of frames being read to buffer */ - D_S[j].sbp_current = 0; /* Frame being currently read */ - D_S[j].CD_changed=1; - D_S[j].frame_size=CD_FRAMESIZE; - D_S[j].f_eject=0; + p->sbp_first_frame = -1; /* First frame in buffer */ + p->sbp_last_frame = -1; /* Last frame in buffer */ + p->sbp_read_frames = 0; /* Number of frames being read to buffer */ + p->sbp_current = 0; /* Frame being currently read */ + p->CD_changed=1; + p->frame_size=CD_FRAMESIZE; + p->f_eject=0; #if EJECT - if (!fam0_drive) D_S[j].f_eject=1; + if (!fam0_drive) p->f_eject=1; #endif /* EJECT */ cc_ReadStatus(); i=ResponseStatus(); /* returns orig. status or p_busy_new */ @@ -5742,8 +5731,8 @@ int __init sbpcd_init(void) } msg(DBG_INI,"init: first GetStatus: %d\n",i); msg(DBG_LCS,"init: first GetStatus: error_byte=%d\n", - D_S[j].error_byte); - if (D_S[j].error_byte==aud_12) + p->error_byte); + if (p->error_byte==aud_12) { timeout=jiffies+2*HZ; do @@ -5752,14 +5741,14 @@ int __init sbpcd_init(void) msg(DBG_INI,"init: second GetStatus: %02X\n",i); msg(DBG_LCS, "init: second GetStatus: error_byte=%d\n", - D_S[j].error_byte); + p->error_byte); if (i<0) break; if (!st_caddy_in) break; } while ((!st_diskok)||time_after(jiffies, timeout)); } i=SetSpeed(); - if (i>=0) D_S[j].CD_changed=1; + if (i>=0) p->CD_changed=1; } /* @@ -5788,24 +5777,26 @@ int __init sbpcd_init(void) for (j=0;j<NR_SBPCD;j++) { struct cdrom_device_info * sbpcd_infop; + struct sbpcd_drive *p = D_S + j; - if (D_S[j].drv_id==-1) continue; - switch_drive(j); + if (p->drv_id==-1) continue; + switch_drive(p); #if SAFE_MIXED - D_S[j].has_data=0; + p->has_data=0; #endif /* SAFE_MIXED */ /* * allocate memory for the frame buffers */ - D_S[j].aud_buf=NULL; - D_S[j].sbp_audsiz=0; - D_S[j].sbp_bufsiz=buffers; - if (D_S[j].drv_type&drv_fam1) - if (READ_AUDIO>0) D_S[j].sbp_audsiz=READ_AUDIO; - D_S[j].sbp_buf=(u_char *) vmalloc(D_S[j].sbp_bufsiz*CD_FRAMESIZE); - if (D_S[j].sbp_buf==NULL) - { - msg(DBG_INF,"data buffer (%d frames) not available.\n",D_S[j].sbp_bufsiz); + p->aud_buf=NULL; + p->sbp_audsiz=0; + p->sbp_bufsiz=buffers; + if (p->drv_type&drv_fam1) + if (READ_AUDIO>0) + p->sbp_audsiz = READ_AUDIO; + p->sbp_buf=(u_char *) vmalloc(buffers*CD_FRAMESIZE); + if (!p->sbp_buf) { + msg(DBG_INF,"data buffer (%d frames) not available.\n", + buffers); if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL)) { printk("Can't unregister %s\n", major_name); @@ -5817,11 +5808,11 @@ int __init sbpcd_init(void) #ifdef MODULE msg(DBG_INF,"data buffer size: %d frames.\n",buffers); #endif /* MODULE */ - if (D_S[j].sbp_audsiz>0) + if (p->sbp_audsiz>0) { - D_S[j].aud_buf=(u_char *) vmalloc(D_S[j].sbp_audsiz*CD_FRAMESIZE_RAW); - if (D_S[j].aud_buf==NULL) msg(DBG_INF,"audio buffer (%d frames) not available.\n",D_S[j].sbp_audsiz); - else msg(DBG_INF,"audio buffer size: %d frames.\n",D_S[j].sbp_audsiz); + p->aud_buf=(u_char *) vmalloc(p->sbp_audsiz*CD_FRAMESIZE_RAW); + if (p->aud_buf==NULL) msg(DBG_INF,"audio buffer (%d frames) not available.\n",p->sbp_audsiz); + else msg(DBG_INF,"audio buffer size: %d frames.\n",p->sbp_audsiz); } sbpcd_infop = vmalloc(sizeof (struct cdrom_device_info)); if (sbpcd_infop == NULL) @@ -5830,12 +5821,15 @@ int __init sbpcd_init(void) blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); return -ENOMEM; } - D_S[j].sbpcd_infop = sbpcd_infop; - memcpy (sbpcd_infop, &sbpcd_info, sizeof(struct cdrom_device_info)); + memset(sbpcd_infop, 0, sizeof(struct cdrom_device_info)); + sbpcd_infop->ops = &sbpcd_dops; + sbpcd_infop->speed = 2; + sbpcd_infop->capacity = 1; + sprintf(sbpcd_infop->name, "sbpcd%d", j); sbpcd_infop->dev = mk_kdev(MAJOR_NR, j); - strncpy(sbpcd_infop->name,major_name, sizeof(sbpcd_infop->name)); - - sprintf (nbuff, "c0t%d/cd", D_S[j].drv_id); + sbpcd_infop->handle = p; + p->sbpcd_infop = sbpcd_infop; + sprintf(nbuff, "c0t%d/cd", p->drv_id); sbpcd_infop->de = devfs_register (devfs_handle, nbuff, DEVFS_FL_DEFAULT, MAJOR_NR, j, S_IFBLK | S_IRUGO | S_IWUGO, @@ -5886,28 +5880,21 @@ module_exit(sbpcd_exit); #endif /* MODULE */ -/*==========================================================================*/ -/* - * Check if the media has changed in the CD-ROM drive. - * used externally (isofs/inode.c, fs/buffer.c) - */ -static int sbpcd_chk_disk_change(kdev_t full_dev) +static int sbpcd_media_changed(struct cdrom_device_info *cdi, int disc_nr) { - int i; - - i=minor(full_dev); - msg(DBG_CHK,"media_check (%d) called\n", i); + struct sbpcd_drive *p = cdi->handle; + msg(DBG_CHK,"media_check (%s) called\n", cdi->name); - if (D_S[i].CD_changed==0xFF) + if (p->CD_changed==0xFF) { - D_S[i].CD_changed=0; - msg(DBG_CHK,"medium changed (drive %d)\n", i); + p->CD_changed=0; + msg(DBG_CHK,"medium changed (drive %s)\n", cdi->name); /* BUG! Should invalidate buffers! --AJK */ /* Why should it do the above at all?! --mdcki */ - D_S[d].diskstate_flags &= ~toc_bit; - D_S[d].diskstate_flags &= ~cd_size_bit; + current_drive->diskstate_flags &= ~toc_bit; + current_drive->diskstate_flags &= ~cd_size_bit; #if SAFE_MIXED - D_S[d].has_data=0; + current_drive->has_data=0; #endif /* SAFE_MIXED */ return (1); @@ -5916,11 +5903,6 @@ static int sbpcd_chk_disk_change(kdev_t full_dev) return (0); } -static int sbpcd_media_changed( struct cdrom_device_info *cdi, int disc_nr) -{ - return sbpcd_chk_disk_change(cdi->dev); -} - MODULE_LICENSE("GPL"); /*==========================================================================*/ diff --git a/drivers/cdrom/sbpcd.h b/drivers/cdrom/sbpcd.h index 74255554611d..16a0208a2598 100644 --- a/drivers/cdrom/sbpcd.h +++ b/drivers/cdrom/sbpcd.h @@ -242,12 +242,12 @@ /* * disk states (bits of diskstate_flags): */ -#define upc_valid (D_S[d].diskstate_flags&upc_bit) -#define volume_valid (D_S[d].diskstate_flags&volume_bit) -#define toc_valid (D_S[d].diskstate_flags&toc_bit) -#define cd_size_valid (D_S[d].diskstate_flags&cd_size_bit) -#define subq_valid (D_S[d].diskstate_flags&subq_bit) -#define frame_size_valid (D_S[d].diskstate_flags&frame_size_bit) +#define upc_valid (current_drive->diskstate_flags&upc_bit) +#define volume_valid (current_drive->diskstate_flags&volume_bit) +#define toc_valid (current_drive->diskstate_flags&toc_bit) +#define cd_size_valid (current_drive->diskstate_flags&cd_size_bit) +#define subq_valid (current_drive->diskstate_flags&subq_bit) +#define frame_size_valid (current_drive->diskstate_flags&frame_size_bit) /* * the status_bits variable @@ -324,13 +324,13 @@ /* * used drive states: */ -#define st_door_closed (D_S[d].status_bits&p_door_closed) -#define st_caddy_in (D_S[d].status_bits&p_caddy_in) -#define st_spinning (D_S[d].status_bits&p_spinning) -#define st_check (D_S[d].status_bits&p_check) -#define st_busy (D_S[d].status_bits&p_busy_new) -#define st_door_locked (D_S[d].status_bits&p_door_locked) -#define st_diskok (D_S[d].status_bits&p_disk_ok) +#define st_door_closed (current_drive->status_bits&p_door_closed) +#define st_caddy_in (current_drive->status_bits&p_caddy_in) +#define st_spinning (current_drive->status_bits&p_spinning) +#define st_check (current_drive->status_bits&p_check) +#define st_busy (current_drive->status_bits&p_busy_new) +#define st_door_locked (current_drive->status_bits&p_door_locked) +#define st_diskok (current_drive->status_bits&p_disk_ok) /* * bits of the CDi_status register: @@ -372,22 +372,22 @@ #define drv_famV 0x2000 /* ECS-AT (vertos-100) family */ #define drv_at (drv_famV+0x01) /* ECS-AT, firmware "1.00" */ -#define fam0_drive (D_S[d].drv_type&drv_fam0) -#define famL_drive (D_S[d].drv_type&drv_famL) -#define famV_drive (D_S[d].drv_type&drv_famV) -#define fam1_drive (D_S[d].drv_type&drv_fam1) -#define fam2_drive (D_S[d].drv_type&drv_fam2) -#define famT_drive (D_S[d].drv_type&drv_famT) -#define fam0L_drive (D_S[d].drv_type&(drv_fam0|drv_famL)) -#define fam0V_drive (D_S[d].drv_type&(drv_fam0|drv_famV)) -#define famLV_drive (D_S[d].drv_type&(drv_famL|drv_famV)) -#define fam0LV_drive (D_S[d].drv_type&(drv_fam0|drv_famL|drv_famV)) -#define fam1L_drive (D_S[d].drv_type&(drv_fam1|drv_famL)) -#define fam1V_drive (D_S[d].drv_type&(drv_fam1|drv_famV)) -#define fam1LV_drive (D_S[d].drv_type&(drv_fam1|drv_famL|drv_famV)) -#define fam01_drive (D_S[d].drv_type&(drv_fam0|drv_fam1)) -#define fam12_drive (D_S[d].drv_type&(drv_fam1|drv_fam2)) -#define fam2T_drive (D_S[d].drv_type&(drv_fam2|drv_famT)) +#define fam0_drive (current_drive->drv_type&drv_fam0) +#define famL_drive (current_drive->drv_type&drv_famL) +#define famV_drive (current_drive->drv_type&drv_famV) +#define fam1_drive (current_drive->drv_type&drv_fam1) +#define fam2_drive (current_drive->drv_type&drv_fam2) +#define famT_drive (current_drive->drv_type&drv_famT) +#define fam0L_drive (current_drive->drv_type&(drv_fam0|drv_famL)) +#define fam0V_drive (current_drive->drv_type&(drv_fam0|drv_famV)) +#define famLV_drive (current_drive->drv_type&(drv_famL|drv_famV)) +#define fam0LV_drive (current_drive->drv_type&(drv_fam0|drv_famL|drv_famV)) +#define fam1L_drive (current_drive->drv_type&(drv_fam1|drv_famL)) +#define fam1V_drive (current_drive->drv_type&(drv_fam1|drv_famV)) +#define fam1LV_drive (current_drive->drv_type&(drv_fam1|drv_famL|drv_famV)) +#define fam01_drive (current_drive->drv_type&(drv_fam0|drv_fam1)) +#define fam12_drive (current_drive->drv_type&(drv_fam1|drv_fam2)) +#define fam2T_drive (current_drive->drv_type&(drv_fam2|drv_famT)) /* * audio states: diff --git a/drivers/ide/hd.c b/drivers/ide/hd.c index 81624ccfe02f..714e27ff87b1 100644 --- a/drivers/ide/hd.c +++ b/drivers/ide/hd.c @@ -145,8 +145,6 @@ static struct hd_i_struct hd_info[MAX_HD]; static int NR_HD; #endif -static struct hd_struct hd[MAX_HD<<6]; - static struct timer_list device_timer; #define TIMEOUT_VALUE (6*HZ) @@ -596,22 +594,21 @@ repeat: reset_hd(); return; } - dev = minor(CURRENT->rq_dev); + dev = DEVICE_NR(CURRENT->rq_dev); block = CURRENT->sector; nsect = CURRENT->nr_sectors; - if (dev >= (NR_HD<<6) || (dev & 0x3f) || - block >= hd[dev].nr_sects || ((block+nsect) > hd[dev].nr_sects)) { - if (dev >= (NR_HD<<6) || (dev & 0x3f)) + if (dev >= NR_HD || block >= get_capacity(hd_gendisk+dev) || + ((block+nsect) > get_capacity(hd_gendisk+unit))) { + if (dev >= NR_HD) printk("hd: bad minor number: device=%s\n", kdevname(CURRENT->rq_dev)); else printk("hd%c: bad access: block=%d, count=%d\n", - (minor(CURRENT->rq_dev)>>6)+'a', block, nsect); + dev+'a', block, nsect); end_request(CURRENT, 0); goto repeat; } - dev >>= 6; if (special_op[dev]) { if (do_special_op(dev)) goto repeat; @@ -707,14 +704,12 @@ static struct gendisk hd_gendisk[2] = { .first_minor = 0, .major_name = "hda", .minor_shift = 6, - .part = hd, .fops = &hd_fops, },{ .major = MAJOR_NR, .first_minor = 64, .major_name = "hdb", .minor_shift = 6, - .part = hd + 64, .fops = &hd_fops, } }; @@ -819,10 +814,11 @@ static void __init hd_geninit(void) #endif for (drive=0 ; drive < NR_HD ; drive++) { - hd[drive<<6].nr_sects = hd_info[drive].head * + sector_t size = hd_info[drive].head * hd_info[drive].sect * hd_info[drive].cyl; - printk ("hd%c: %ldMB, CHS=%d/%d/%d\n", drive+'a', - hd[drive<<6].nr_sects / 2048, hd_info[drive].cyl, + set_capacity(hd_gendisk + drive, size); + printk ("%s: %ldMB, CHS=%d/%d/%d\n", hd_gendisk[drive].major_name, + size / 2048, hd_info[drive].cyl, hd_info[drive].head, hd_info[drive].sect); } if (!NR_HD) @@ -849,7 +845,6 @@ static void __init hd_geninit(void) } for(drive=0; drive < NR_HD; drive++) { - hd_gendisk[drive].nr_real = 1; add_gendisk(hd_gendisk + drive); register_disk(hd_gendisk + drive, mk_kdev(MAJOR_NR,drive<<6), 1<<6, diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index d6e7db8b7887..b293f3e92833 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -2138,7 +2138,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) if (stat) toc->capacity = 0x1fffff; - drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME; + set_capacity(drive->disk, toc->capacity * SECTORS_PER_FRAME); /* Remember that we've read this stuff. */ CDROM_STATE_FLAGS (drive)->toc_valid = 1; @@ -2593,9 +2593,8 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots) { struct cdrom_info *info = drive->driver_data; struct cdrom_device_info *devinfo = &info->devinfo; - int minor = (drive->select.b.unit) << PARTN_BITS; - devinfo->dev = mk_kdev(HWIF(drive)->major, minor); + devinfo->dev = mk_kdev(drive->disk->major, drive->disk->first_minor); devinfo->ops = &ide_cdrom_dops; devinfo->mask = 0; *(int *)&devinfo->speed = CDROM_STATE_FLAGS (drive)->current_speed; @@ -2622,7 +2621,8 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots) devinfo->mask |= CDC_CLOSE_TRAY; devinfo->de = devfs_register(drive->de, "cd", DEVFS_FL_DEFAULT, - HWIF(drive)->major, minor, + drive->disk->major, + drive->disk->first_minor, S_IFBLK | S_IRUGO | S_IWUGO, ide_fops, NULL); @@ -2823,13 +2823,12 @@ int ide_cdrom_setup (ide_drive_t *drive) { struct cdrom_info *info = drive->driver_data; struct cdrom_device_info *cdi = &info->devinfo; - int minor = drive->select.b.unit << PARTN_BITS; int nslots; /* * default to read-only always and fix latter at the bottom */ - set_device_ro(mk_kdev(HWIF(drive)->major, minor), 1); + set_device_ro(mk_kdev(drive->disk->major, drive->disk->first_minor), 1); blk_queue_hardsect_size(&drive->queue, CD_FRAMESIZE); blk_queue_prep_rq(&drive->queue, ll_10byte_cmd_build); @@ -2951,7 +2950,7 @@ int ide_cdrom_setup (ide_drive_t *drive) nslots = ide_cdrom_probe_capabilities (drive); if (CDROM_CONFIG_FLAGS(drive)->dvd_ram) - set_device_ro(mk_kdev(HWIF(drive)->major, minor), 0); + set_device_ro(mk_kdev(drive->disk->major, drive->disk->first_minor), 0); if (ide_cdrom_register (drive, nslots)) { printk ("%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name); @@ -2998,8 +2997,8 @@ void ide_cdrom_release (struct inode *inode, struct file *file, static int ide_cdrom_check_media_change (ide_drive_t *drive) { - return cdrom_media_changed(mk_kdev(HWIF (drive)->major, - (drive->select.b.unit) << PARTN_BITS)); + return cdrom_media_changed(mk_kdev(drive->disk->major, + drive->disk->first_minor)); } static @@ -3025,9 +3024,7 @@ int ide_cdrom_cleanup(ide_drive_t *drive) { struct cdrom_info *info = drive->driver_data; struct cdrom_device_info *devinfo = &info->devinfo; - ide_hwif_t *hwif = HWIF(drive); - int unit = drive - hwif->drives; - struct gendisk *g = hwif->gd[unit]; + struct gendisk *g = drive->disk; if (ide_unregister_subdriver (drive)) return 1; @@ -3092,9 +3089,7 @@ MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); static int ide_cdrom_reinit (ide_drive_t *drive) { struct cdrom_info *info; - ide_hwif_t *hwif = HWIF(drive); - int unit = drive - hwif->drives; - struct gendisk *g = hwif->gd[unit]; + struct gendisk *g = drive->disk; struct request_sense sense; if (!strstr("ide-cdrom", drive->driver_req)) @@ -3147,10 +3142,13 @@ static int ide_cdrom_reinit (ide_drive_t *drive) cdrom_read_toc(drive, &sense); g->minor_shift = 0; + /* probably bogus, but that's the old behaviour */ + g->de = NULL; + g->flags = GENHD_FL_DEVFS; add_gendisk(g); register_disk(g, mk_kdev(g->major,g->first_minor), 1<<g->minor_shift, ide_fops, - g->part[0].nr_sects); + get_capacity(g)); return 0; failed: return 1; diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index ce8e1a9e57b9..e8040b7626f7 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -1516,8 +1516,6 @@ static void idedisk_add_settings(ide_drive_t *drive) static void idedisk_setup (ide_drive_t *drive) { - int i; - struct hd_driveid *id = drive->id; unsigned long capacity; @@ -1538,15 +1536,6 @@ static void idedisk_setup (ide_drive_t *drive) drive->doorlocking = 1; } } - for (i = 0; i < MAX_DRIVES; ++i) { - ide_hwif_t *hwif = HWIF(drive); - - if (drive != &hwif->drives[i]) continue; - hwif->gd[i]->de_arr[i] = drive->de; - if (drive->removable) - hwif->gd[i]->flags[i] |= GENHD_FL_REMOVABLE; - break; - } #if 1 (void) probe_lba_addressing(drive, 1); @@ -1629,9 +1618,7 @@ static void idedisk_setup (ide_drive_t *drive) static int idedisk_cleanup (ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - int unit = drive - hwif->drives; - struct gendisk *g = hwif->gd[unit]; + struct gendisk *g = drive->disk; if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) if (do_idedisk_flushcache(drive)) printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", @@ -1683,9 +1670,7 @@ MODULE_DESCRIPTION("ATA DISK Driver"); static int idedisk_reinit(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - int unit = drive - hwif->drives; - struct gendisk *g = hwif->gd[unit]; + struct gendisk *g = drive->disk; /* strstr("foo", "") is non-NULL */ if (!strstr("ide-disk", drive->driver_req)) @@ -1714,6 +1699,9 @@ static int idedisk_reinit(ide_drive_t *drive) } DRIVER(drive)->busy--; g->minor_shift = PARTN_BITS; + g->de = drive->de; + g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0; + g->flags |= GENHD_FL_DEVFS; add_gendisk(g); register_disk(g, mk_kdev(g->major,g->first_minor), 1<<g->minor_shift, ide_fops, diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 4a62a49af582..3c6fbfd9b3f4 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -1500,7 +1500,7 @@ static int idefloppy_get_capacity (ide_drive_t *drive) drive->bios_cyl = 0; drive->bios_head = drive->bios_sect = 0; floppy->blocks = floppy->bs_factor = 0; - drive->part[0].nr_sects = 0; + set_capacity(drive->disk, 0); idefloppy_create_read_capacity_cmd (&pc); if (idefloppy_queue_pc_tail (drive, &pc)) { @@ -1555,7 +1555,7 @@ static int idefloppy_get_capacity (ide_drive_t *drive) (void) idefloppy_get_flexible_disk_page (drive); } - drive->part[0].nr_sects = floppy->blocks * floppy->bs_factor; + set_capacity(drive->disk, floppy->blocks * floppy->bs_factor); return rc; } @@ -2065,7 +2065,6 @@ static void idefloppy_add_settings(ide_drive_t *drive) static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy) { struct idefloppy_id_gcw gcw; - int i; *((unsigned short *) &gcw) = drive->id->config; drive->driver_data = floppy; @@ -2108,23 +2107,12 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy) (void) idefloppy_get_capacity (drive); idefloppy_add_settings(drive); - for (i = 0; i < MAX_DRIVES; ++i) { - ide_hwif_t *hwif = HWIF(drive); - - if (drive != &hwif->drives[i]) continue; - hwif->gd[i]->de_arr[i] = drive->de; - if (drive->removable) - hwif->gd[i]->flags[i] |= GENHD_FL_REMOVABLE; - break; - } } static int idefloppy_cleanup (ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; - ide_hwif_t *hwif = HWIF(drive); - int unit = drive - hwif->drives; - struct gendisk *g = hwif->gd[unit]; + struct gendisk *g = drive->disk; if (ide_unregister_subdriver (drive)) return 1; @@ -2191,9 +2179,7 @@ static ide_driver_t idefloppy_driver = { static int idefloppy_reinit (ide_drive_t *drive) { idefloppy_floppy_t *floppy; - ide_hwif_t *hwif = HWIF(drive); - int unit = drive - hwif->drives; - struct gendisk *g = hwif->gd[unit]; + struct gendisk *g = drive->disk; if (!strstr("ide-floppy", drive->driver_req)) goto failed; if (!drive->present) @@ -2221,10 +2207,13 @@ static int idefloppy_reinit (ide_drive_t *drive) idefloppy_setup (drive, floppy); DRIVER(drive)->busy--; g->minor_shift = PARTN_BITS; + g->de = drive->de; + g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0; + g->flags |= GENHD_FL_DEVFS; add_gendisk(g); register_disk(g, mk_kdev(g->major,g->first_minor), 1<<g->minor_shift, ide_fops, - g->part[0].nr_sects); + get_capacity(g)); return 0; failed: return 1; diff --git a/drivers/ide/ide-geometry.c b/drivers/ide/ide-geometry.c index 5f21651c1785..850419f2a0a7 100644 --- a/drivers/ide/ide-geometry.c +++ b/drivers/ide/ide-geometry.c @@ -214,7 +214,7 @@ int ide_xlate_1024 (kdev_t i_rdev, int xparm, int ptheads, const char *msg) ret = 1; } - drive->part[0].nr_sects = current_capacity(drive); + set_capacity(drive->disk, current_capacity(drive)); if (ret) printk("%s%s [%d/%d/%d]", msg, msg1, diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 1b972998ea2f..f56203db719a 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -807,9 +807,6 @@ static int init_irq (ide_hwif_t *hwif) static void init_gendisk (ide_hwif_t *hwif) { struct gendisk *gd; - struct hd_struct *part; - devfs_handle_t *de_arr; - char *flags; unsigned int unit, units, minors; extern devfs_handle_t ide_devfs_handle; char *names; @@ -830,40 +827,19 @@ static void init_gendisk (ide_hwif_t *hwif) goto err_kmalloc_gd; memset(gd, 0, MAX_DRIVES * sizeof(struct gendisk)); - part = kmalloc(minors * sizeof(struct hd_struct), GFP_KERNEL); - if (!part) - goto err_kmalloc_gd_part; - - memset(part, 0, minors * sizeof(struct hd_struct)); - - de_arr = kmalloc(sizeof(devfs_handle_t) * MAX_DRIVES, GFP_KERNEL); - if (!de_arr) - goto err_kmalloc_gd_de_arr; - memset(de_arr, 0, sizeof(devfs_handle_t) * MAX_DRIVES); - - flags = kmalloc(sizeof(char) * MAX_DRIVES, GFP_KERNEL); - if (!flags) - goto err_kmalloc_gd_flags; - memset(flags, 0, sizeof(char) * MAX_DRIVES); - names = kmalloc (4 * MAX_DRIVES, GFP_KERNEL); if (!names) goto err_kmalloc_gd_names; memset(names, 0, 4 * MAX_DRIVES); for (unit = 0; unit < units; ++unit) { - gd[unit].part = part + (unit << PARTN_BITS); - gd[unit].de_arr = de_arr + unit; - gd[unit].flags = flags + unit; - hwif->drives[unit].part = gd[unit].part; gd[unit].major = hwif->major; gd[unit].first_minor = unit << PARTN_BITS; sprintf(names + 4*unit, "hd%c",'a'+hwif->index*MAX_DRIVES+unit); gd[unit].major_name = names + 4*unit; gd[unit].minor_shift = PARTN_BITS; - gd[unit].nr_real = 1; gd[unit].fops = ide_fops; - hwif->gd[unit] = gd + unit; + hwif->drives[unit].disk = gd + unit; } for (unit = 0; unit < units; ++unit) { @@ -892,12 +868,6 @@ static void init_gendisk (ide_hwif_t *hwif) return; err_kmalloc_gd_names: - kfree(names); -err_kmalloc_gd_flags: - kfree(de_arr); -err_kmalloc_gd_de_arr: - kfree(part); -err_kmalloc_gd_part: kfree(gd); err_kmalloc_gd: printk(KERN_WARNING "(ide::init_gendisk) Out of memory\n"); diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 8ae42efbe71c..e072c15231a1 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -1660,7 +1660,7 @@ ide_drive_t *get_info_ptr (kdev_t i_rdev) if (unit < MAX_DRIVES) { ide_drive_t *drive = &hwif->drives[unit]; #if 0 - if ((drive->present) && (drive->part[minor].nr_sects)) + if (drive->present && get_capacity(drive->disk)) #else if (drive->present) #endif @@ -1747,10 +1747,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio void ide_revalidate_drive (ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - int unit = drive - hwif->drives; - struct gendisk *g = hwif->gd[unit]; - g->part[0].nr_sects = current_capacity(drive); + set_capacity(drive->disk, current_capacity(drive)); } /* @@ -1975,7 +1972,7 @@ void ide_unregister (unsigned int index) continue; minor = drive->select.b.unit << PARTN_BITS; for (p = 0; p < (1<<PARTN_BITS); ++p) { - if (drive->part[p].nr_sects > 0) { + if (get_capacity(drive->disk)) { kdev_t devp = mk_kdev(hwif->major, minor+p); invalidate_device(devp, 0); } @@ -2055,17 +2052,12 @@ void ide_unregister (unsigned int index) blk_dev[hwif->major].data = NULL; blk_dev[hwif->major].queue = NULL; blk_clear(hwif->major); - gd = hwif->gd[0]; + gd = hwif->drives[0].disk; if (gd) { int i; - kfree(gd->part); - if (gd->de_arr) - kfree (gd->de_arr); - if (gd->flags) - kfree (gd->flags); - kfree(gd); for (i = 0; i < MAX_DRIVES; i++) - hwif->gd[i] = NULL; + hwif->drives[i].disk = NULL; + kfree(gd); } old_hwif = *hwif; init_hwif_data (index); /* restore hwif data to pristine status */ @@ -2527,7 +2519,7 @@ static int ide_ioctl (struct inode *inode, struct file *file, if (put_user(drive->bios_head, (byte *) &loc->heads)) return -EFAULT; if (put_user(drive->bios_sect, (byte *) &loc->sectors)) return -EFAULT; if (put_user(bios_cyl, (unsigned short *) &loc->cylinders)) return -EFAULT; - if (put_user((unsigned)drive->part[minor(inode->i_rdev)&PARTN_MASK].start_sect, + if (put_user((unsigned)get_start_sect(inode->i_bdev), (unsigned long *) &loc->start)) return -EFAULT; return 0; } @@ -2539,7 +2531,7 @@ static int ide_ioctl (struct inode *inode, struct file *file, if (put_user(drive->head, (byte *) &loc->heads)) return -EFAULT; if (put_user(drive->sect, (byte *) &loc->sectors)) return -EFAULT; if (put_user(drive->cyl, (unsigned int *) &loc->cylinders)) return -EFAULT; - if (put_user((unsigned)drive->part[minor(inode->i_rdev)&PARTN_MASK].start_sect, + if (put_user((unsigned)get_start_sect(inode->i_bdev), (unsigned long *) &loc->start)) return -EFAULT; return 0; } diff --git a/drivers/md/md.c b/drivers/md/md.c index 16496cc15d77..2686038c5a9e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -103,11 +103,6 @@ static ctl_table raid_root_table[] = { {0} }; -/* - * these have to be allocated separately because external - * subsystems want to have a pre-defined structure - */ -struct hd_struct md_hd_struct[MAX_MD_DEVS]; static void md_recover_arrays(void); static mdk_thread_t *md_recovery_thread; @@ -276,7 +271,7 @@ char * partition_name(kdev_t dev) hd = get_gendisk (dev); dname->name = NULL; if (hd) - dname->name = disk_name (hd, minor(dev), dname->namebuf); + dname->name = disk_name(hd, minor(dev)-hd->first_minor, dname->namebuf); if (!dname->name) { sprintf (dname->namebuf, "[dev %s]", kdevname(dev)); dname->name = dname->namebuf; @@ -618,7 +613,7 @@ static void free_mddev(mddev_t *mddev) export_array(mddev); md_size[mdidx(mddev)] = 0; - md_hd_struct[mdidx(mddev)].nr_sects = 0; + set_capacity(disks[mdidx(mddev)], 0); } #undef BAD_CSUM @@ -1458,8 +1453,6 @@ static int do_md_run(mddev_t * mddev) disk->minor_shift = 0; sprintf(major_name, "md%d", mdidx(mddev)); disk->major_name = major_name; - disk->part = md_hd_struct + mdidx(mddev); - disk->nr_real = 1; disk->fops = &md_fops; mddev->pers = pers[pnum]; @@ -2344,7 +2337,7 @@ static int md_ioctl(struct inode *inode, struct file *file, err = put_user (4, (char *) &loc->sectors); if (err) goto abort_unlock; - err = put_user (md_hd_struct[mdidx(mddev)].nr_sects/8, + err = put_user(get_capacity(disks[mdidx(mddev)])/8, (short *) &loc->cylinders); if (err) goto abort_unlock; @@ -3178,11 +3171,10 @@ int __init md_init(void) return (-1); } devfs_handle = devfs_mk_dir (NULL, "md", NULL); - /* we don't use devfs_register_series because we want to fill md_hd_struct */ for (minor=0; minor < MAX_MD_DEVS; ++minor) { char devname[128]; sprintf (devname, "%u", minor); - md_hd_struct[minor].de = devfs_register (devfs_handle, + devfs_register (devfs_handle, devname, DEVFS_FL_DEFAULT, MAJOR_NR, minor, S_IFBLK | S_IRUSR | S_IWUSR, &md_fops, NULL); } diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index 0dba96c0d6af..ae7befdf574b 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -186,7 +186,6 @@ static struct i2ob_request *i2ob_backlog_tail[MAX_I2O_CONTROLLERS]; static struct i2ob_device i2ob_dev[MAX_I2OB<<4]; static int i2ob_dev_count = 0; -static struct hd_struct i2ob[MAX_I2OB<<4]; static struct gendisk i2o_disk[MAX_I2OB]; static char i2o_names[MAX_I2OB * 8]; @@ -248,7 +247,7 @@ static u32 i2ob_get(struct i2ob_device *dev) * Turn a Linux block request into an I2O block read/write. */ -static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq, u32 base, int unit) +static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq, int unit) { struct i2o_controller *c = dev->controller; int tid = dev->tid; @@ -279,7 +278,7 @@ static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq, /* This can be optimised later - just want to be sure its right for starters */ - offset = ((u64)(req->sector+base)) << 9; + offset = ((u64)req->sector) << 9; __raw_writel( offset & 0xFFFFFFFF, msg+24); __raw_writel(offset>>32, msg+28); mptr=msg+32; @@ -724,7 +723,7 @@ static int i2ob_evt(void *dummy) register_disk(p, mk_kdev(p->major, p->first_minor), 1<<p->minor_shift, p->fops, - i2ob[unit].nr_sects); + get_capacity(p)); break; } @@ -737,7 +736,6 @@ static int i2ob_evt(void *dummy) case I2O_EVT_IND_BSA_VOLUME_UNLOAD: { struct gendisk *p = &i2o_disk[unit>>4]; - wipe_partitions(mk_kdev(MAJOR_NR, unit)); del_gendisk(p); for(i = unit; i <= unit+15; i++) blk_queue_max_sectors(i2ob_dev[i].req_queue, 0); @@ -769,7 +767,7 @@ static int i2ob_evt(void *dummy) i2ob_query_device(&i2ob_dev[unit], 0x0000, 4, &size, 8); spin_lock_irqsave(I2O_LOCK(unit), flags); - i2ob[unit].nr_sects = size>>9; + set_capacity(&i2o_disk[unit>>4], size>>9); spin_unlock_irqrestore(I2O_LOCK(unit), flags); break; } @@ -870,7 +868,7 @@ static int i2ob_backlog_request(struct i2o_controller *c, struct i2ob_device *de i2ob_backlog_tail[c->unit] = NULL; unit = minor(ireq->req->rq_dev); - i2ob_send(m, dev, ireq, i2ob[unit].start_sect, unit); + i2ob_send(m, dev, ireq, unit); } if(i2ob_backlog[c->unit]) return 1; @@ -970,7 +968,7 @@ static void i2ob_request(request_queue_t *q) i2ob_queues[dev->unit]->i2ob_qhead = ireq->next; ireq->req = req; - i2ob_send(m, dev, ireq, i2ob[unit].start_sect, (unit&0xF0)); + i2ob_send(m, dev, ireq, (unit&0xF0)); } } @@ -1039,7 +1037,7 @@ static int i2ob_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct hd_geometry g; - int u = minor(inode->i_rdev) & 0xF0; + int u = minor(inode->i_rdev) >> 4; /* Anyone capable of this syscall can do *real bad* things */ if (!capable(CAP_SYS_ADMIN)) @@ -1047,7 +1045,7 @@ static int i2ob_ioctl(struct inode *inode, struct file *file, if (cmd != HDIO_GETGEO) return -EINVAL; - i2o_block_biosparam(i2ob[u].nr_sects, + i2o_block_biosparam(get_capacity(&i2o_disk[u]), &g.cylinders, &g.heads, &g.sectors); g.start = get_start_sect(inode->i_bdev); return copy_to_user((void *)arg, &g, sizeof(g)) ? -EFAULT : 0; @@ -1223,7 +1221,7 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i i2ob_query_device(dev, 0x0000, 5, &flags, 4); i2ob_query_device(dev, 0x0000, 6, &status, 4); - i2ob[unit].nr_sects = size>>9; + set_capacity(&i2o_disk[unit>>4], size>>9); /* Set limit based on inbound frame size */ limit = (d->controller->status_block->inbound_frame_size - 8)/2; @@ -1327,7 +1325,7 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i i2o_event_register(c, d->lct_data.tid, i2ob_context, unit, (I2OB_EVENT_MASK & d->lct_data.event_capabilities)); - i2ob[unit].nr_sects = size>>9; + set_capacity(i2o_disk[unit>>4], size>>9); return 0; } @@ -1472,7 +1470,7 @@ static void i2ob_scan(int bios) register_disk(p, mk_kdev(p->major, p->first_minor), 1<<p->minor_shift, p->fops, - i2ob[scan_unit].nr_sects); + get_capacity(p)); scan_unit+=16; i2ob_dev_count++; @@ -1565,7 +1563,7 @@ void i2ob_new_device(struct i2o_controller *c, struct i2o_device *d) register_disk(p, mk_kdev(p->major, p->first_minor), 1<<p->minor_shift, p->fops, - i2ob[unit].nr_sects); + get_capacity(p)); i2ob_dev_count++; i2o_device_notify_on(d, &i2o_block_handler); } @@ -1616,7 +1614,6 @@ void i2ob_del_device(struct i2o_controller *c, struct i2o_device *d) * This will force errors when i2ob_get_queue() is called * by the kenrel. */ - wipe_partitions(mk_kdev(MAJOR_NR, unit)); del_gendisk(&i2o_disk[unit>>4]); i2ob_dev[unit].req_queue = NULL; for(i = unit; i <= unit+15; i++) @@ -1773,9 +1770,7 @@ int i2o_block_init(void) disk->major = MAJOR_NR; disk->first_minor = i<<4; disk->minor_shift = 4; - disk->part = i2ob + (i<<4); disk->fops = &i2ob_fops; - disk->nr_real = 1; disk->major_name = i2o_names + i*8; sprintf(disk->major_name, "i2o/hd%c", 'a' + i); } diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c index 83e5ba3c3f7f..4ddc0d9337ec 100644 --- a/drivers/mtd/ftl.c +++ b/drivers/mtd/ftl.c @@ -175,8 +175,6 @@ static struct mtd_notifier ftl_notifier = { #define XFER_PREPARED 0x03 #define XFER_FAILED 0x04 -static struct hd_struct ftl_hd[MINOR_NR(MAX_DEV, 0, 0)]; - /*====================================================================*/ static int ftl_ioctl(struct inode *inode, struct file *file, @@ -846,7 +844,7 @@ static int ftl_open(struct inode *inode, struct file *file) if (partition->state != FTL_FORMATTED) return -ENXIO; - if (partition->disk->part[0].nr_sects == 0) + if (get_capacity(partition->disk) == 0) return -ENXIO; if (!get_mtd_device(partition->mtd, -1)) @@ -1132,8 +1130,8 @@ static int ftl_revalidate(kdev_t dev) int unit = minor(dev) >> 4; partition_t *part = myparts[unit]; scan_header(part); - part->disk->part[0].nr_sects = - le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE); + set_capacity(part->disk, + le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE)); return 0; } @@ -1252,9 +1250,7 @@ static void ftl_notify_add(struct mtd_info *mtd) disk->first_minor = device << 4; disk->major_name = name; disk->minor_shift = PART_BITS; - disk->part = ftl_hd + (device << 4); disk->fops = &ftl_blk_fops; - disk->nr_real = 1; partition->mtd = mtd; partition->disk = disk; @@ -1298,7 +1294,6 @@ static void ftl_notify_remove(struct mtd_info *mtd) ftl_freepart(myparts[i]); myparts[i]->state = 0; - wipe_partitions(mk_kdev(MAJOR_NR, i<<4)); del_gendisk(myparts[i]->disk); kfree(myparts[i]->disk->name); kfree(myparts[i]->disk); diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index 2de5c0783fde..c6fa25aeabf6 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c @@ -49,16 +49,6 @@ /* Linux-specific block device functions */ -/* I _HATE_ the Linux block device setup more than anything else I've ever - * encountered, except ... - */ - -/* .. for the Linux partition table handling. */ -/* So why didn't you fucking go and clean it up? -- AV */ -struct hd_struct part_table[256]; - -static struct block_device_operations nftl_fops; - struct NFTLrecord *NFTLs[MAX_NFTLS]; static void NFTL_setup(struct mtd_info *mtd) @@ -150,9 +140,7 @@ static void NFTL_setup(struct mtd_info *mtd) gd->major = MAJOR_NR; gd->first_minor = firstfree << NFTL_PARTN_BITS; gd->minor_shift = NFTL_PARTN_BITS; - gd->part = part_table + (firstfree << NFTL_PARTN_BITS); gd->major_name = name; - gd->nr_real = 1; nftl->disk = gd; add_gendisk(gd); register_disk(gd, mk_kdev(MAJOR_NR,firstfree<<NFTL_PARTN_BITS), @@ -847,10 +835,10 @@ void nftl_request(RQFUNC_ARG) down(&nftl->mutex); DEBUG(MTD_DEBUG_LEVEL3, "Got mutex\n"); - if (block + nsect > part_table[dev].nr_sects) { + if (block + nsect > get_capacity(nftl->disk)) { /* access past the end of device */ printk("nftl%c%d: bad access: block = %d, count = %d\n", - (minor(req->rq_dev)>>6)+'a', dev & 0xf, block, nsect); + unit+'a', dev & 0xf, block, nsect); up(&nftl->mutex); res = 0; /* fail */ goto repeat; diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 060b94008a15..6460e5f08eda 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -128,6 +128,13 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) if (!dev) /* It's a host bus, nothing to read */ return; + if (dev->transparent) { + printk("Transparent bridge - %s\n", dev->name); + for(i = 0; i < PCI_BUS_NUM_RESOURCES; i++) + child->resource[i] = child->parent->resource[i]; + return; + } + for(i=0; i<3; i++) child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i]; @@ -149,13 +156,6 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO; res->start = base; res->end = limit + 0xfff; - } else { - /* - * Ugh. We don't know enough about this bridge. Just assume - * that it's entirely transparent. - */ - printk(KERN_ERR "Unknown bridge resource %d: assuming transparent\n", 0); - child->resource[0] = child->parent->resource[0]; } res = child->resource[1]; @@ -167,10 +167,6 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM; res->start = base; res->end = limit + 0xfffff; - } else { - /* See comment above. Same thing */ - printk(KERN_ERR "Unknown bridge resource %d: assuming transparent\n", 1); - child->resource[1] = child->parent->resource[1]; } res = child->resource[2]; @@ -197,10 +193,6 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH; res->start = base; res->end = limit + 0xfffff; - } else { - /* See comments above */ - printk(KERN_ERR "Unknown bridge resource %d: assuming transparent\n", 2); - child->resource[2] = child->parent->resource[2]; } } @@ -389,6 +381,10 @@ int pci_setup_device(struct pci_dev * dev) case PCI_HEADER_TYPE_BRIDGE: /* bridge header */ if (class != PCI_CLASS_BRIDGE_PCI) goto bad; + /* The PCI-to-PCI bridge spec requires that subtractive + decoding (i.e. transparent) bridge must have programming + interface code of 0x01. */ + dev->transparent = ((class & 0xff) == 1); pci_read_bases(dev, 2, PCI_ROM_ADDRESS1); break; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index e66a3237f252..43aea3183d77 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -471,6 +471,11 @@ static void __init quirk_dunord ( struct pci_dev * dev ) r -> end = 0xffffff; } +static void __init quirk_transparent_bridge(struct pci_dev *dev) +{ + dev->transparent = 1; +} + /* * The main table of quirks. */ @@ -525,6 +530,13 @@ static struct pci_fixup pci_fixups[] __initdata = { { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering }, + /* + * i82380FB mobile docking controller: its PCI-to-PCI bridge + * is subtractive decoding (transparent), and does indicate this + * in the ProgIf. Unfortunately, the ProgIf value is wrong - 0x80 + * instead of 0x01. + */ + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82380FB, quirk_transparent_bridge }, { 0 } }; diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 33efcd5717e9..da3eb2e5f5cc 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -73,7 +73,7 @@ static int pci_assign_bus_resource(const struct pci_bus *bus, int i; type_mask |= IORESOURCE_IO | IORESOURCE_MEM; - for (i = 0 ; i < 4; i++) { + for (i = 0 ; i < PCI_BUS_NUM_RESOURCES; i++) { struct resource *r = bus->resource[i]; if (!r) continue; diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 8f7670f944ed..422e6e6e9d3c 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -302,7 +302,7 @@ dasd_state_new_to_known(dasd_device_t *device) /* Add a proc directory and the dasd device entry to devfs. */ sprintf(buffer, "%04x", device->devinfo.devno); dir = devfs_mk_dir(dasd_devfs_handle, buffer, device); - gdp->de_arr[0] = dir; + gdp->de = dir; if (devmap->features & DASD_FEATURE_READONLY) devfs_perm = S_IFBLK | S_IRUSR; else @@ -328,7 +328,7 @@ dasd_state_known_to_new(dasd_device_t * device) return; /* Remove device entry and devfs directory. */ devfs_unregister(device->devfs_entry); - devfs_unregister(gdp->de_arr[0]); + devfs_unregister(gdp->de); /* Forget the discipline information. */ device->discipline = NULL; diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c index 5733d3f466f5..6df129445724 100644 --- a/drivers/s390/block/dasd_genhd.c +++ b/drivers/s390/block/dasd_genhd.c @@ -34,10 +34,7 @@ struct major_info { struct list_head list; int major; struct gendisk disks[DASD_PER_MAJOR]; - devfs_handle_t de_arr[DASD_PER_MAJOR]; - char flags[DASD_PER_MAJOR]; char names[DASD_PER_MAJOR * 8]; - struct hd_struct part[1<<MINORBITS]; }; /* @@ -106,11 +103,8 @@ dasd_register_major(int major) disk->major = new_major; disk->first_minor = i << DASD_PARTN_BITS; disk->minor_shift = DASD_PARTN_BITS; - disk->nr_real = 1; disk->fops = &dasd_device_operations; - disk->de_arr = mi->de_arr + i; - disk->flags = mi->flags + i; - disk->part = mi->part + (i << DASD_PARTN_BITS); + disk->flags = GENHD_FL_DEVFS; } /* Setup block device pointers for the new major. */ @@ -284,14 +278,6 @@ dasd_destroy_partitions(dasd_device_t * device) if (disk == NULL) return; - wipe_partitions(device->kdev); - - /* - * This is confusing. The funcions is devfs_register_partitions - * but the 1 as third parameter makes it do an unregister... - * FIXME: there must be a better way to get rid of the devfs entries - */ - devfs_register_partitions(disk, minor(device->kdev), 1); del_gendisk(disk); } diff --git a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c index 6ae15e45a619..f5900895fc93 100644 --- a/drivers/scsi/qlogicfc.c +++ b/drivers/scsi/qlogicfc.c @@ -1342,18 +1342,11 @@ int isp2x00_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *)) num_free = QLOGICFC_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr); num_free = (num_free > 2) ? num_free - 2 : 0; - host->can_queue = hostdata->queued + num_free; + host->can_queue = host->host_busy + num_free; if (host->can_queue > QLOGICFC_REQ_QUEUE_LEN) host->can_queue = QLOGICFC_REQ_QUEUE_LEN; host->sg_tablesize = QLOGICFC_MAX_SG(num_free); - /* this is really gross */ - if (host->can_queue <= host->host_busy){ - if (host->can_queue+2 < host->host_busy) - DEBUG(printk("qlogicfc%d.c crosses its fingers.\n", hostdata->host_id)); - host->can_queue = host->host_busy + 1; - } - LEAVE("isp2x00_queuecommand"); return 0; @@ -1623,17 +1616,11 @@ void isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs) num_free = QLOGICFC_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr); num_free = (num_free > 2) ? num_free - 2 : 0; - host->can_queue = hostdata->queued + num_free; + host->can_queue = host->host_busy + num_free; if (host->can_queue > QLOGICFC_REQ_QUEUE_LEN) host->can_queue = QLOGICFC_REQ_QUEUE_LEN; host->sg_tablesize = QLOGICFC_MAX_SG(num_free); - if (host->can_queue <= host->host_busy){ - if (host->can_queue+2 < host->host_busy) - DEBUG(printk("qlogicfc%d : crosses its fingers.\n", hostdata->host_id)); - host->can_queue = host->host_busy + 1; - } - outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR); LEAVE_INTR("isp2x00_intr_handler"); } diff --git a/drivers/scsi/qlogicfc.h b/drivers/scsi/qlogicfc.h index e67e9f5af274..a2b54f43256c 100644 --- a/drivers/scsi/qlogicfc.h +++ b/drivers/scsi/qlogicfc.h @@ -65,7 +65,7 @@ #define DATASEGS_PER_COMMAND 2 #define DATASEGS_PER_CONT 5 -#define QLOGICFC_REQ_QUEUE_LEN 127 /* must be power of two - 1 */ +#define QLOGICFC_REQ_QUEUE_LEN 255 /* must be power of two - 1 */ #define QLOGICFC_MAX_SG(ql) (DATASEGS_PER_COMMAND + (((ql) > 0) ? DATASEGS_PER_CONT*((ql) - 1) : 0)) #define QLOGICFC_CMD_PER_LUN 8 diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 9cdfbbe27d0e..96d8d8c1c017 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -84,9 +84,6 @@ #define SD_DSK_ARR_LUMP 6 /* amount to over allocate sd_dsk_arr by */ - -struct hd_struct *sd; - static Scsi_Disk ** sd_dsk_arr; static rwlock_t sd_dsk_arr_lock = RW_LOCK_UNLOCKED; @@ -126,8 +123,6 @@ static void sd_rw_intr(Scsi_Cmnd * SCpnt); static Scsi_Disk * sd_get_sdisk(int index); -extern void driverfs_remove_partitions(struct gendisk *hd, int minor); - #if defined(CONFIG_PPC32) /** * sd_find_target - find kdev_t of first scsi disk that matches @@ -288,6 +283,8 @@ static request_queue_t *sd_find_queue(kdev_t dev) return NULL; /* No such device */ } +static struct gendisk **sd_disks; + /** * sd_init_command - build a scsi (read or write) command from * information in the request structure. @@ -323,7 +320,7 @@ static int sd_init_command(Scsi_Cmnd * SCpnt) /* >>>>> this change is not in the lk 2.5 series */ if (part_nr >= (sd_template.dev_max << 4) || (part_nr & 0xf) || !sdp || !sdp->online || - block + SCpnt->request->nr_sectors > sd[part_nr].nr_sects) { + block + SCpnt->request->nr_sectors > get_capacity(sd_disks[dsk_nr])) { SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", SCpnt->request->nr_sectors)); SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt)); @@ -590,8 +587,6 @@ static struct block_device_operations sd_fops = revalidate: sd_revalidate }; -static struct gendisk **sd_disks; - /** * sd_rw_intr - bottom half handler: called when the lower level * driver has completed (successfully or otherwise) a scsi command. @@ -1207,12 +1202,10 @@ static int sd_init() init_mem_lth(sd_disks, sd_template.dev_max); if (sd_disks) zero_mem_lth(sd_disks, sd_template.dev_max); - init_mem_lth(sd, maxparts); - if (!sd_dsk_arr || !sd || !sd_disks) + if (!sd_dsk_arr || !sd_disks) goto cleanup_mem; - zero_mem_lth(sd, maxparts); return 0; #undef init_mem_lth @@ -1221,8 +1214,6 @@ static int sd_init() cleanup_mem: vfree(sd_disks); sd_disks = NULL; - vfree(sd); - sd = NULL; if (sd_dsk_arr) { for (k = 0; k < sd_template.dev_max; ++k) vfree(sd_dsk_arr[k]); @@ -1312,9 +1303,6 @@ static int sd_attach(Scsi_Device * sdp) unsigned long iflags; struct { struct gendisk disk; - devfs_handle_t de; - struct device *dev; - char flags; char name[5]; } *p; struct gendisk *gd; @@ -1327,9 +1315,6 @@ static int sd_attach(Scsi_Device * sdp) if (!p) return 1; gd = &p->disk; - gd->de_arr = &p->de; - gd->flags = &p->flags; - gd->driverfs_dev_arr = &p->dev; SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun)); @@ -1361,21 +1346,19 @@ static int sd_attach(Scsi_Device * sdp) } sd_template.nr_dev++; - gd->nr_real = 1; - gd->de_arr[0] = sdp->de; - gd->driverfs_dev_arr[0] = &sdp->sdev_driverfs_dev; + gd->de = sdp->de; gd->major = SD_MAJOR(dsk_nr>>4); gd->first_minor = (dsk_nr & 15)<<4; gd->minor_shift = 4; - gd->part = sd + (dsk_nr << 4); gd->fops = &sd_fops; if (dsk_nr > 26) sprintf(p->name, "sd%c%c", 'a'+dsk_nr/26-1, 'a'+dsk_nr%26); else sprintf(p->name, "sd%c", 'a'+dsk_nr%26); gd->major_name = p->name; - if (sdp->removable) - gd->flags[0] |= GENHD_FL_REMOVABLE; + gd->flags = sdp->removable ? GENHD_FL_REMOVABLE : 0; + gd->driverfs_dev = &sdp->sdev_driverfs_dev; + gd->flags |= GENHD_FL_DRIVERFS | GENHD_FL_DEVFS; sd_disks[dsk_nr] = gd; sd_dskname(dsk_nr, diskname); printk(KERN_NOTICE "Attached scsi %sdisk %s at scsi%d, channel %d, " @@ -1393,7 +1376,7 @@ static int sd_revalidate(kdev_t dev) return -ENODEV; sd_init_onedisk(sdkp, dsk_nr); - sd_disks[dsk_nr]->part[0].nr_sects = sdkp->capacity; + set_capacity(sd_disks[dsk_nr], sdkp->capacity); return 0; } @@ -1435,10 +1418,6 @@ static void sd_detach(Scsi_Device * sdp) if (sdkp->has_been_registered) { sdkp->has_been_registered = 0; dev = MKDEV_SD(dsk_nr); - driverfs_remove_partitions(sd_disks[dsk_nr], minor(dev)); - wipe_partitions(dev); - devfs_register_partitions (sd_disks[dsk_nr], minor(dev), 1); - /* unregister_disk() */ del_gendisk(sd_disks[dsk_nr]); } sdp->attached--; @@ -1488,7 +1467,6 @@ static void __exit exit_sd(void) vfree(sd_dsk_arr[k]); vfree(sd_dsk_arr); } - vfree((char *) sd); for (k = 0; k < N_USED_SD_MAJORS; k++) { blk_dev[SD_MAJOR(k)].queue = NULL; blk_clear(SD_MAJOR(k)); diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index e3eb4be41a26..5ba16cfec18c 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -20,8 +20,6 @@ #include <linux/genhd.h> #endif -extern struct hd_struct *sd; - typedef struct scsi_disk { unsigned capacity; /* size in 512-byte sectors */ Scsi_Device *device; diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 6be5cdac0797..4e68f16b14e7 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -87,25 +87,24 @@ static struct Scsi_Device_Template sr_template = init_command:sr_init_command }; -Scsi_CD *scsi_CDs; -static int *sr_sizes; +static Scsi_CD *scsi_CDs; static int sr_open(struct cdrom_device_info *, int); -void get_sectorsize(int); -void get_capabilities(int); +static void get_sectorsize(Scsi_CD *); +static void get_capabilities(Scsi_CD *); static int sr_media_change(struct cdrom_device_info *, int); static int sr_packet(struct cdrom_device_info *, struct cdrom_generic_command *); static void sr_release(struct cdrom_device_info *cdi) { - Scsi_CD *SCp = cdi->handle; + Scsi_CD *cd = cdi->handle; - if (SCp->device->sector_size > 2048) - sr_set_blocklength(minor(cdi->dev), 2048); - SCp->device->access_count--; - if (SCp->device->host->hostt->module) - __MOD_DEC_USE_COUNT(SCp->device->host->hostt->module); + if (cd->device->sector_size > 2048) + sr_set_blocklength(cd, 2048); + cd->device->access_count--; + if (cd->device->host->hostt->module) + __MOD_DEC_USE_COUNT(cd->device->host->hostt->module); if (sr_template.module) __MOD_DEC_USE_COUNT(sr_template.module); } @@ -146,7 +145,7 @@ static struct cdrom_device_ops sr_dops = int sr_media_change(struct cdrom_device_info *cdi, int slot) { - Scsi_CD *SCp = cdi->handle; + Scsi_CD *cd = cdi->handle; int retval; if (CDSL_CURRENT != slot) { @@ -154,19 +153,19 @@ int sr_media_change(struct cdrom_device_info *cdi, int slot) return -EINVAL; } - retval = scsi_ioctl(SCp->device, SCSI_IOCTL_TEST_UNIT_READY, 0); + retval = scsi_ioctl(cd->device, SCSI_IOCTL_TEST_UNIT_READY, 0); if (retval) { /* Unable to test, unit probably not ready. This usually * means there is no disc in the drive. Mark as changed, * and we will figure it out later once the drive is * available again. */ - SCp->device->changed = 1; + cd->device->changed = 1; return 1; /* This will force a flush, if called from * check_disk_change */ }; - retval = SCp->device->changed; - SCp->device->changed = 0; + retval = cd->device->changed; + cd->device->changed = 0; /* If the disk changed, the capacity will now be different, * so we force a re-read of this information */ if (retval) { @@ -180,8 +179,8 @@ int sr_media_change(struct cdrom_device_info *cdi, int slot) * be trying to use something that is too small if the disc * has changed. */ - SCp->needs_sector_size = 1; - SCp->device->sector_size = 2048; + cd->needs_sector_size = 1; + cd->device->sector_size = 2048; } return retval; } @@ -198,7 +197,7 @@ static void rw_intr(Scsi_Cmnd * SCpnt) int good_sectors = (result == 0 ? this_count : 0); int block_sectors = 0; int device_nr = DEVICE_NR(SCpnt->request->rq_dev); - Scsi_CD *SCp = &scsi_CDs[device_nr]; + Scsi_CD *cd = &scsi_CDs[device_nr]; #ifdef DEBUG printk("sr.c done: %x %p\n", result, SCpnt->request->bh->b_data); @@ -223,7 +222,7 @@ static void rw_intr(Scsi_Cmnd * SCpnt) block_sectors = bio_sectors(SCpnt->request->bio); if (block_sectors < 4) block_sectors = 4; - if (SCp->device->sector_size == 2048) + if (cd->device->sector_size == 2048) error_sector <<= 2; error_sector &= ~(block_sectors - 1); good_sectors = error_sector - SCpnt->request->sector; @@ -235,9 +234,9 @@ static void rw_intr(Scsi_Cmnd * SCpnt) * block. Therefore, if we hit a medium error within the last * 75 2K sectors, we decrease the saved size value. */ - if ((error_sector >> 1) < sr_sizes[device_nr] && - SCp->capacity - error_sector < 4 * 75) - sr_sizes[device_nr] = error_sector >> 1; + if (error_sector < get_capacity(cd->disk) && + cd->capacity - error_sector < 4 * 75) + set_capacity(cd->disk, error_sector); } /* @@ -251,34 +250,34 @@ static void rw_intr(Scsi_Cmnd * SCpnt) static request_queue_t *sr_find_queue(kdev_t dev) { - Scsi_CD *SCp; + Scsi_CD *cd; if (minor(dev) >= sr_template.dev_max) return NULL; - SCp = &scsi_CDs[minor(dev)]; - if (!SCp->device) + cd = &scsi_CDs[minor(dev)]; + if (!cd->device) return NULL; - return &SCp->device->request_queue; + return &cd->device->request_queue; } static int sr_init_command(Scsi_Cmnd * SCpnt) { int dev, devm, block=0, this_count, s_size; - Scsi_CD *SCp; + Scsi_CD *cd; devm = minor(SCpnt->request->rq_dev); dev = DEVICE_NR(SCpnt->request->rq_dev); - SCp = &scsi_CDs[dev]; + cd = &scsi_CDs[dev]; SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %d, block = %d\n", devm, block)); - if (dev >= sr_template.nr_dev || !SCp->device || !SCp->device->online) { + if (dev >= sr_template.nr_dev || !cd->device || !cd->device->online) { SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", SCpnt->request->nr_sectors)); SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt)); return 0; } - if (SCp->device->changed) { + if (cd->device->changed) { /* * quietly refuse to do anything to a changed disc until the * changed bit has been reset @@ -295,10 +294,10 @@ static int sr_init_command(Scsi_Cmnd * SCpnt) * we do lazy blocksize switching (when reading XA sectors, * see CDROMREADMODE2 ioctl) */ - s_size = SCp->device->sector_size; + s_size = cd->device->sector_size; if (s_size > 2048) { if (!in_interrupt()) - sr_set_blocklength(DEVICE_NR(CURRENT->rq_dev), 2048); + sr_set_blocklength(cd, 2048); else printk("sr: can't switch blocksize: in interrupt\n"); } @@ -309,7 +308,7 @@ static int sr_init_command(Scsi_Cmnd * SCpnt) } if (rq_data_dir(SCpnt->request) == WRITE) { - if (!SCp->device->writeable) + if (!cd->device->writeable) return 0; SCpnt->cmnd[0] = WRITE_10; SCpnt->sc_data_direction = SCSI_DATA_WRITE; @@ -332,8 +331,8 @@ static int sr_init_command(Scsi_Cmnd * SCpnt) this_count = (SCpnt->request_bufflen >> 9) / (s_size >> 9); - SCSI_LOG_HLQUEUE(2, printk("sr%d : %s %d/%ld 512 byte blocks.\n", - devm, + SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n", + cd->cdi.name, (rq_data_dir(SCpnt->request) == WRITE) ? "writing" : "reading", this_count, SCpnt->request->nr_sectors)); @@ -358,7 +357,7 @@ static int sr_init_command(Scsi_Cmnd * SCpnt) * host adapter, it's safe to assume that we can at least transfer * this many bytes between each connect / disconnect. */ - SCpnt->transfersize = SCp->device->sector_size; + SCpnt->transfersize = cd->device->sector_size; SCpnt->underflow = this_count << 9; SCpnt->allowed = MAX_RETRIES; @@ -400,21 +399,20 @@ struct block_device_operations sr_bdops = static int sr_open(struct cdrom_device_info *cdi, int purpose) { - Scsi_CD *SCp = cdi->handle; + Scsi_CD *cd = cdi->handle; - if (minor(cdi->dev) >= sr_template.dev_max || !SCp->device) { + if (!cd->device) return -ENXIO; /* No such device */ - } /* * If the device is in error recovery, wait until it is done. * If the device is offline, then disallow any access to it. */ - if (!scsi_block_when_processing_errors(SCp->device)) { + if (!scsi_block_when_processing_errors(cd->device)) { return -ENXIO; } - SCp->device->access_count++; - if (SCp->device->host->hostt->module) - __MOD_INC_USE_COUNT(SCp->device->host->hostt->module); + cd->device->access_count++; + if (cd->device->host->hostt->module) + __MOD_INC_USE_COUNT(cd->device->host->hostt->module); if (sr_template.module) __MOD_INC_USE_COUNT(sr_template.module); @@ -423,8 +421,8 @@ static int sr_open(struct cdrom_device_info *cdi, int purpose) * this is the case, and try again. */ - if (SCp->needs_sector_size) - get_sectorsize(minor(cdi->dev)); + if (cd->needs_sector_size) + get_sectorsize(cd); return 0; } @@ -464,35 +462,32 @@ static int sr_attach(Scsi_Device * SDp) if (sr_template.nr_dev > sr_template.dev_max) panic("scsi_devices corrupt (sr)"); - printk("Attached scsi CD-ROM sr%d at scsi%d, channel %d, id %d, lun %d\n", - i, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun); + printk("Attached scsi CD-ROM %s at scsi%d, channel %d, id %d, lun %d\n", + scsi_CDs[i].cdi.name, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun); return 0; } -void get_sectorsize(int i) +static void get_sectorsize(Scsi_CD *cd) { unsigned char cmd[10]; unsigned char *buffer; int the_result, retries = 3; int sector_size; Scsi_Request *SRpnt = NULL; - Scsi_CD *SCp; request_queue_t *queue; - SCp = &scsi_CDs[i]; - buffer = kmalloc(512, GFP_DMA); if (!buffer) goto Enomem; - SRpnt = scsi_allocate_request(SCp->device); + SRpnt = scsi_allocate_request(cd->device); if (!SRpnt) goto Enomem; do { cmd[0] = READ_CAPACITY; - cmd[1] = (SCp->device->scsi_level <= SCSI_2) ? - ((SCp->device->lun << 5) & 0xe0) : 0; + cmd[1] = (cd->device->scsi_level <= SCSI_2) ? + ((cd->device->lun << 5) & 0xe0) : 0; memset((void *) &cmd[2], 0, 8); SRpnt->sr_request->rq_status = RQ_SCSI_BUSY; /* Mark as really busy */ SRpnt->sr_cmd_len = 0; @@ -515,15 +510,15 @@ void get_sectorsize(int i) SRpnt = NULL; if (the_result) { - SCp->capacity = 0x1fffff; + cd->capacity = 0x1fffff; sector_size = 2048; /* A guess, just in case */ - SCp->needs_sector_size = 1; + cd->needs_sector_size = 1; } else { #if 0 - if (cdrom_get_last_written(&SCp->cdi, - &SCp->capacity)) + if (cdrom_get_last_written(&cd->cdi, + &cd->capacity)) #endif - SCp->capacity = 1 + ((buffer[0] << 24) | + cd->capacity = 1 + ((buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]); @@ -542,45 +537,44 @@ void get_sectorsize(int i) sector_size = 2048; /* fall through */ case 2048: - SCp->capacity *= 4; + cd->capacity *= 4; /* fall through */ case 512: break; default: - printk("sr%d: unsupported sector size %d.\n", - i, sector_size); - SCp->capacity = 0; - SCp->needs_sector_size = 1; + printk("%s: unsupported sector size %d.\n", + cd->cdi.name, sector_size); + cd->capacity = 0; + cd->needs_sector_size = 1; } - SCp->device->sector_size = sector_size; + cd->device->sector_size = sector_size; /* * Add this so that we have the ability to correctly gauge * what the device is capable of. */ - SCp->needs_sector_size = 0; - sr_sizes[i] = SCp->capacity >> (BLOCK_SIZE_BITS - 9); + cd->needs_sector_size = 0; + set_capacity(cd->disk, cd->capacity); } - queue = &SCp->device->request_queue; + queue = &cd->device->request_queue; blk_queue_hardsect_size(queue, sector_size); out: kfree(buffer); return; Enomem: - SCp->capacity = 0x1fffff; + cd->capacity = 0x1fffff; sector_size = 2048; /* A guess, just in case */ - SCp->needs_sector_size = 1; + cd->needs_sector_size = 1; if (SRpnt) scsi_release_request(SRpnt); goto out; } -void get_capabilities(int i) +void get_capabilities(Scsi_CD *cd) { - Scsi_CD *SCp; unsigned char cmd[6]; unsigned char *buffer; int rc, n; @@ -597,7 +591,6 @@ void get_capabilities(int i) "" }; - SCp = &scsi_CDs[i]; buffer = kmalloc(512, GFP_DMA); if (!buffer) { @@ -605,31 +598,31 @@ void get_capabilities(int i) return; } cmd[0] = MODE_SENSE; - cmd[1] = (SCp->device->scsi_level <= SCSI_2) ? - ((SCp->device->lun << 5) & 0xe0) : 0; + cmd[1] = (cd->device->scsi_level <= SCSI_2) ? + ((cd->device->lun << 5) & 0xe0) : 0; cmd[2] = 0x2a; cmd[4] = 128; cmd[3] = cmd[5] = 0; - rc = sr_do_ioctl(i, cmd, buffer, 128, 1, SCSI_DATA_READ, NULL); + rc = sr_do_ioctl(cd, cmd, buffer, 128, 1, SCSI_DATA_READ, NULL); if (rc) { /* failed, drive doesn't have capabilities mode page */ - SCp->cdi.speed = 1; - SCp->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R | + cd->cdi.speed = 1; + cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R | CDC_DVD | CDC_DVD_RAM | CDC_SELECT_DISC | CDC_SELECT_SPEED); kfree(buffer); - printk("sr%i: scsi-1 drive\n", i); + printk("%s: scsi-1 drive\n", cd->cdi.name); return; } n = buffer[3] + 4; - SCp->cdi.speed = ((buffer[n + 8] << 8) + buffer[n + 9]) / 176; - SCp->readcd_known = 1; - SCp->readcd_cdda = buffer[n + 5] & 0x01; + cd->cdi.speed = ((buffer[n + 8] << 8) + buffer[n + 9]) / 176; + cd->readcd_known = 1; + cd->readcd_cdda = buffer[n + 5] & 0x01; /* print some capability bits */ - printk("sr%i: scsi3-mmc drive: %dx/%dx %s%s%s%s%s%s\n", i, + printk("%s: scsi3-mmc drive: %dx/%dx %s%s%s%s%s%s\n", cd->cdi.name, ((buffer[n + 14] << 8) + buffer[n + 15]) / 176, - SCp->cdi.speed, + cd->cdi.speed, buffer[n + 3] & 0x01 ? "writer " : "", /* CD Writer */ buffer[n + 3] & 0x20 ? "dvd-ram " : "", buffer[n + 2] & 0x02 ? "cd/rw " : "", /* can read rewriteable */ @@ -638,38 +631,38 @@ void get_capabilities(int i) loadmech[buffer[n + 6] >> 5]); if ((buffer[n + 6] >> 5) == 0) /* caddy drives can't close tray... */ - SCp->cdi.mask |= CDC_CLOSE_TRAY; + cd->cdi.mask |= CDC_CLOSE_TRAY; if ((buffer[n + 2] & 0x8) == 0) /* not a DVD drive */ - SCp->cdi.mask |= CDC_DVD; + cd->cdi.mask |= CDC_DVD; if ((buffer[n + 3] & 0x20) == 0) { /* can't write DVD-RAM media */ - SCp->cdi.mask |= CDC_DVD_RAM; + cd->cdi.mask |= CDC_DVD_RAM; } else { - SCp->device->writeable = 1; + cd->device->writeable = 1; } if ((buffer[n + 3] & 0x10) == 0) /* can't write DVD-R media */ - SCp->cdi.mask |= CDC_DVD_R; + cd->cdi.mask |= CDC_DVD_R; if ((buffer[n + 3] & 0x2) == 0) /* can't write CD-RW media */ - SCp->cdi.mask |= CDC_CD_RW; + cd->cdi.mask |= CDC_CD_RW; if ((buffer[n + 3] & 0x1) == 0) /* can't write CD-R media */ - SCp->cdi.mask |= CDC_CD_R; + cd->cdi.mask |= CDC_CD_R; if ((buffer[n + 6] & 0x8) == 0) /* can't eject */ - SCp->cdi.mask |= CDC_OPEN_TRAY; + cd->cdi.mask |= CDC_OPEN_TRAY; if ((buffer[n + 6] >> 5) == mechtype_individual_changer || (buffer[n + 6] >> 5) == mechtype_cartridge_changer) - SCp->cdi.capacity = - cdrom_number_of_slots(&SCp->cdi); - if (SCp->cdi.capacity <= 1) + cd->cdi.capacity = + cdrom_number_of_slots(&cd->cdi); + if (cd->cdi.capacity <= 1) /* not a changer */ - SCp->cdi.mask |= CDC_SELECT_DISC; + cd->cdi.mask |= CDC_SELECT_DISC; /*else I don't think it can close its tray - SCp->cdi.mask |= CDC_CLOSE_TRAY; */ + cd->cdi.mask |= CDC_CLOSE_TRAY; */ kfree(buffer); } @@ -680,14 +673,14 @@ void get_capabilities(int i) */ static int sr_packet(struct cdrom_device_info *cdi, struct cdrom_generic_command *cgc) { - Scsi_CD *SCp = cdi->handle; - Scsi_Device *device = SCp->device; + Scsi_CD *cd = cdi->handle; + Scsi_Device *device = cd->device; /* set the LUN */ if (device->scsi_level <= SCSI_2) cgc->cmd[1] |= device->lun << 5; - cgc->stat = sr_do_ioctl(minor(cdi->dev), cgc->cmd, cgc->buffer, cgc->buflen, cgc->quiet, cgc->data_direction, cgc->sense); + cgc->stat = sr_do_ioctl(cdi->handle, cgc->cmd, cgc->buffer, cgc->buflen, cgc->quiet, cgc->data_direction, cgc->sense); return cgc->stat; } @@ -696,6 +689,7 @@ static int sr_registered; static int sr_init() { + int i; if (sr_template.dev_noticed == 0) return 0; @@ -714,15 +708,10 @@ static int sr_init() if (!scsi_CDs) goto cleanup_dev; memset(scsi_CDs, 0, sr_template.dev_max * sizeof(Scsi_CD)); - - sr_sizes = kmalloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC); - if (!sr_sizes) - goto cleanup_cds; - memset(sr_sizes, 0, sr_template.dev_max * sizeof(int)); + for (i = 0; i < sr_template.dev_max; i++) + sprintf(scsi_CDs[i].cdi.name, "sr%d", i); return 0; -cleanup_cds: - kfree(scsi_CDs); cleanup_dev: unregister_blkdev(MAJOR_NR, "sr"); sr_registered--; @@ -750,67 +739,80 @@ static DEVICE_ATTR(type,S_IRUGO,sr_device_type_read,NULL); void sr_finish() { int i; - char name[6]; blk_dev[MAJOR_NR].queue = sr_find_queue; - blk_size[MAJOR_NR] = sr_sizes; for (i = 0; i < sr_template.nr_dev; ++i) { - Scsi_CD *SCp = &scsi_CDs[i]; + struct gendisk *disk; + Scsi_CD *cd = &scsi_CDs[i]; /* If we have already seen this, then skip it. Comes up * with loadable modules. */ - if (SCp->capacity) + if (cd->disk) + continue; + disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL); + if (!disk) continue; - SCp->capacity = 0x1fffff; - SCp->device->sector_size = 2048;/* A guess, just in case */ - SCp->needs_sector_size = 1; - SCp->device->changed = 1; /* force recheck CD type */ + if (cd->disk) { + kfree(disk); + continue; + } + memset(disk, 0, sizeof(struct gendisk)); + disk->major = MAJOR_NR; + disk->first_minor = i; + disk->minor_shift = 0; + disk->major_name = cd->cdi.name; + disk->fops = &sr_bdops; + cd->disk = disk; + cd->capacity = 0x1fffff; + cd->device->sector_size = 2048;/* A guess, just in case */ + cd->needs_sector_size = 1; + cd->device->changed = 1; /* force recheck CD type */ #if 0 /* seems better to leave this for later */ - get_sectorsize(i); - printk("Scd sectorsize = %d bytes.\n", SCp->sector_size); + get_sectorsize(cd); + printk("Scd sectorsize = %d bytes.\n", cd->sector_size); #endif - SCp->use = 1; - - SCp->device->ten = 1; - SCp->device->remap = 1; - SCp->readcd_known = 0; - SCp->readcd_cdda = 0; - sr_sizes[i] = SCp->capacity >> (BLOCK_SIZE_BITS - 9); - - SCp->cdi.ops = &sr_dops; - SCp->cdi.handle = SCp; - SCp->cdi.dev = mk_kdev(MAJOR_NR, i); - SCp->cdi.mask = 0; - SCp->cdi.capacity = 1; + cd->use = 1; + + cd->device->ten = 1; + cd->device->remap = 1; + cd->readcd_known = 0; + cd->readcd_cdda = 0; + + cd->cdi.ops = &sr_dops; + cd->cdi.handle = cd; + cd->cdi.dev = mk_kdev(MAJOR_NR, i); + cd->cdi.mask = 0; + cd->cdi.capacity = 1; /* * FIXME: someone needs to handle a get_capabilities * failure properly ?? */ - get_capabilities(i); - sr_vendor_init(SCp); - - sprintf(name, "sr%d", i); - strcpy(SCp->cdi.name, name); - sprintf(SCp->cdi.cdrom_driverfs_dev.bus_id, "%s:cd", - SCp->device->sdev_driverfs_dev.bus_id); - sprintf(SCp->cdi.cdrom_driverfs_dev.name, "%scdrom", - SCp->device->sdev_driverfs_dev.name); - SCp->cdi.cdrom_driverfs_dev.parent = - &SCp->device->sdev_driverfs_dev; - SCp->cdi.cdrom_driverfs_dev.bus = &scsi_driverfs_bus_type; - SCp->cdi.cdrom_driverfs_dev.driver_data = + get_capabilities(cd); + sr_vendor_init(cd); + + sprintf(cd->cdi.cdrom_driverfs_dev.bus_id, "%s:cd", + cd->device->sdev_driverfs_dev.bus_id); + sprintf(cd->cdi.cdrom_driverfs_dev.name, "%scdrom", + cd->device->sdev_driverfs_dev.name); + cd->cdi.cdrom_driverfs_dev.parent = + &cd->device->sdev_driverfs_dev; + cd->cdi.cdrom_driverfs_dev.bus = &scsi_driverfs_bus_type; + cd->cdi.cdrom_driverfs_dev.driver_data = (void *)(long)__mkdev(MAJOR_NR, i); - device_register(&SCp->cdi.cdrom_driverfs_dev); - device_create_file(&SCp->cdi.cdrom_driverfs_dev, + device_register(&cd->cdi.cdrom_driverfs_dev); + device_create_file(&cd->cdi.cdrom_driverfs_dev, &dev_attr_type); - device_create_file(&SCp->cdi.cdrom_driverfs_dev, + device_create_file(&cd->cdi.cdrom_driverfs_dev, &dev_attr_kdev); - SCp->cdi.de = devfs_register(SCp->device->de, "cd", + cd->cdi.de = devfs_register(cd->device->de, "cd", DEVFS_FL_DEFAULT, MAJOR_NR, i, S_IFBLK | S_IRUGO | S_IWUGO, &sr_bdops, NULL); - register_cdrom(&SCp->cdi); + register_cdrom(&cd->cdi); + add_gendisk(disk); + register_disk(disk, mk_kdev(disk->major, disk->first_minor), + 1<<disk->minor_shift, disk->fops, cd->capacity); } } @@ -826,7 +828,9 @@ static void sr_detach(Scsi_Device * SDp) * the device. * We should be kind to our buffer cache, however. */ - invalidate_device(mk_kdev(MAJOR_NR, i), 0); + del_gendisk(cpnt->disk); + kfree(cpnt->disk); + cpnt->disk = NULL; /* * Reset things back to a sane state so that one can @@ -838,7 +842,6 @@ static void sr_detach(Scsi_Device * SDp) SDp->attached--; sr_template.nr_dev--; sr_template.dev_noticed--; - sr_sizes[i] = 0; return; } } @@ -861,12 +864,8 @@ static void __exit exit_sr(void) scsi_unregister_device(&sr_template); unregister_blkdev(MAJOR_NR, "sr"); sr_registered--; - if (scsi_CDs != NULL) { + if (scsi_CDs != NULL) kfree(scsi_CDs); - - kfree(sr_sizes); - sr_sizes = NULL; - } blk_clear(MAJOR_NR); sr_template.dev_max = 0; diff --git a/drivers/scsi/sr.h b/drivers/scsi/sr.h index e4ac7cb2265d..3c3ec7165690 100644 --- a/drivers/scsi/sr.h +++ b/drivers/scsi/sr.h @@ -18,6 +18,7 @@ #define _SR_H #include "scsi.h" +#include <linux/genhd.h> typedef struct { unsigned capacity; /* size in blocks */ @@ -30,11 +31,10 @@ typedef struct { unsigned readcd_known:1; /* drive supports READ_CD (0xbe) */ unsigned readcd_cdda:1; /* reading audio data using READ_CD */ struct cdrom_device_info cdi; + struct gendisk *disk; } Scsi_CD; -extern Scsi_CD *scsi_CDs; - -int sr_do_ioctl(int, unsigned char *, void *, unsigned, int, int, struct request_sense *); +int sr_do_ioctl(Scsi_CD *, unsigned char *, void *, unsigned, int, int, struct request_sense *); int sr_lock_door(struct cdrom_device_info *, int); int sr_tray_move(struct cdrom_device_info *, int); @@ -47,12 +47,11 @@ int sr_select_speed(struct cdrom_device_info *cdi, int speed); int sr_audio_ioctl(struct cdrom_device_info *, unsigned int, void *); int sr_dev_ioctl(struct cdrom_device_info *, unsigned int, unsigned long); -int sr_read_sector(int minor, int lba, int blksize, unsigned char *dest); -int sr_is_xa(int minor); +int sr_is_xa(Scsi_CD *); /* sr_vendor.c */ void sr_vendor_init(Scsi_CD *); int sr_cd_check(struct cdrom_device_info *); -int sr_set_blocklength(int minor, int blocklength); +int sr_set_blocklength(Scsi_CD *, int blocklength); #endif diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c index 85ba7a66a237..f6a54e77bc66 100644 --- a/drivers/scsi/sr_ioctl.c +++ b/drivers/scsi/sr_ioctl.c @@ -24,8 +24,6 @@ * It is off by default and can be turned on with this module parameter */ static int xa_test = 0; -extern void get_sectorsize(int); - #define IOCTL_RETRIES 3 /* The CDROM is fairly slow, so we need a little extra time */ /* In fact, it is very slow if it has to spin up first */ @@ -69,14 +67,14 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti sr_cmd[6] = trk1_te.cdte_addr.msf.minute; sr_cmd[7] = trk1_te.cdte_addr.msf.second; sr_cmd[8] = trk1_te.cdte_addr.msf.frame; - return sr_do_ioctl(minor(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL); + return sr_do_ioctl(cdi->handle, sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL); } /* We do our own retries because we want to know what the specific error code is. Normally the UNIT_ATTENTION code will automatically clear after one error */ -int sr_do_ioctl(int target, unsigned char *sr_cmd, void *buffer, unsigned buflength, int quiet, int readwrite, struct request_sense *sense) +int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned buflength, int quiet, int readwrite, struct request_sense *sense) { Scsi_Request *SRpnt; Scsi_Device *SDev; @@ -84,7 +82,7 @@ int sr_do_ioctl(int target, unsigned char *sr_cmd, void *buffer, unsigned buflen int result, err = 0, retries = 0; char *bounce_buffer; - SDev = scsi_CDs[target].device; + SDev = cd->device; SRpnt = scsi_allocate_request(SDev); if (!SRpnt) { printk("Unable to allocate SCSI request in sr_do_ioctl"); @@ -127,7 +125,7 @@ int sr_do_ioctl(int target, unsigned char *sr_cmd, void *buffer, unsigned buflen case UNIT_ATTENTION: SDev->changed = 1; if (!quiet) - printk(KERN_INFO "sr%d: disc change detected.\n", target); + printk(KERN_INFO "%s: disc change detected.\n", cd->cdi.name); if (retries++ < 10) goto retry; err = -ENOMEDIUM; @@ -137,7 +135,7 @@ int sr_do_ioctl(int target, unsigned char *sr_cmd, void *buffer, unsigned buflen SRpnt->sr_sense_buffer[13] == 0x01) { /* sense: Logical unit is in process of becoming ready */ if (!quiet) - printk(KERN_INFO "sr%d: CDROM not ready yet.\n", target); + printk(KERN_INFO "%s: CDROM not ready yet.\n", cd->cdi.name); if (retries++ < 10) { /* sleep 2 sec and try again */ scsi_sleep(2 * HZ); @@ -149,7 +147,7 @@ int sr_do_ioctl(int target, unsigned char *sr_cmd, void *buffer, unsigned buflen } } if (!quiet) - printk(KERN_INFO "sr%d: CDROM not ready. Make sure there is a disc in the drive.\n", target); + printk(KERN_INFO "%s: CDROM not ready. Make sure there is a disc in the drive.\n", cd->cdi.name); #ifdef DEBUG print_req_sense("sr", SRpnt); #endif @@ -157,8 +155,8 @@ int sr_do_ioctl(int target, unsigned char *sr_cmd, void *buffer, unsigned buflen break; case ILLEGAL_REQUEST: if (!quiet) - printk(KERN_ERR "sr%d: CDROM (ioctl) reports ILLEGAL " - "REQUEST.\n", target); + printk(KERN_ERR "%s: CDROM (ioctl) reports ILLEGAL " + "REQUEST.\n", cd->cdi.name); if (SRpnt->sr_sense_buffer[12] == 0x20 && SRpnt->sr_sense_buffer[13] == 0x00) { /* sense: Invalid command operation code */ @@ -172,7 +170,7 @@ int sr_do_ioctl(int target, unsigned char *sr_cmd, void *buffer, unsigned buflen #endif break; default: - printk(KERN_ERR "sr%d: CDROM (ioctl) error, command: ", target); + printk(KERN_ERR "%s: CDROM (ioctl) error, command: ", cd->cdi.name); print_command(sr_cmd); print_req_sense("sr", SRpnt); err = -EIO; @@ -191,38 +189,36 @@ int sr_do_ioctl(int target, unsigned char *sr_cmd, void *buffer, unsigned buflen /* ---------------------------------------------------------------------- */ /* interface to cdrom.c */ -static int test_unit_ready(int minor) +static int test_unit_ready(Scsi_CD *cd) { - Scsi_CD *SCp; u_char sr_cmd[10]; - SCp = &scsi_CDs[minor]; sr_cmd[0] = GPCMD_TEST_UNIT_READY; - sr_cmd[1] = (SCp->device->scsi_level <= SCSI_2) ? - ((SCp->device->lun) << 5) : 0; + sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ? + ((cd->device->lun) << 5) : 0; sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0; - return sr_do_ioctl(minor, sr_cmd, NULL, 0, 1, SCSI_DATA_NONE, NULL); + return sr_do_ioctl(cd, sr_cmd, NULL, 0, 1, SCSI_DATA_NONE, NULL); } int sr_tray_move(struct cdrom_device_info *cdi, int pos) { - Scsi_CD *SCp = cdi->handle; + Scsi_CD *cd = cdi->handle; u_char sr_cmd[10]; sr_cmd[0] = GPCMD_START_STOP_UNIT; - sr_cmd[1] = (SCp->device->scsi_level <= SCSI_2) ? - ((SCp->device->lun) << 5) : 0; + sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ? + ((cd->device->lun) << 5) : 0; sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; sr_cmd[4] = (pos == 0) ? 0x03 /* close */ : 0x02 /* eject */ ; - return sr_do_ioctl(minor(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL); + return sr_do_ioctl(cd, sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL); } int sr_lock_door(struct cdrom_device_info *cdi, int lock) { - Scsi_CD *SCp = cdi->handle; + Scsi_CD *cd = cdi->handle; - return scsi_ioctl(SCp->device, lock ? SCSI_IOCTL_DOORLOCK : + return scsi_ioctl(cd->device, lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK, 0); } @@ -232,7 +228,7 @@ int sr_drive_status(struct cdrom_device_info *cdi, int slot) /* we have no changer support */ return -EINVAL; } - if (0 == test_unit_ready(minor(cdi->dev))) + if (0 == test_unit_ready(cdi->handle)) return CDS_DISC_OK; return CDS_TRAY_OPEN; @@ -240,7 +236,7 @@ int sr_drive_status(struct cdrom_device_info *cdi, int slot) int sr_disk_status(struct cdrom_device_info *cdi) { - Scsi_CD *SCp = cdi->handle; + Scsi_CD *cd = cdi->handle; struct cdrom_tochdr toc_h; struct cdrom_tocentry toc_e; int i, rc, have_datatracks = 0; @@ -262,7 +258,7 @@ int sr_disk_status(struct cdrom_device_info *cdi) if (!have_datatracks) return CDS_AUDIO; - if (SCp->xa_flag) + if (cd->xa_flag) return CDS_XA_2_1; else return CDS_DATA_1; @@ -271,24 +267,24 @@ int sr_disk_status(struct cdrom_device_info *cdi) int sr_get_last_session(struct cdrom_device_info *cdi, struct cdrom_multisession *ms_info) { - Scsi_CD *SCp = cdi->handle; + Scsi_CD *cd = cdi->handle; - ms_info->addr.lba = SCp->ms_offset; - ms_info->xa_flag = SCp->xa_flag || SCp->ms_offset > 0; + ms_info->addr.lba = cd->ms_offset; + ms_info->xa_flag = cd->xa_flag || cd->ms_offset > 0; return 0; } int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) { - Scsi_CD *SCp = cdi->handle; + Scsi_CD *cd = cdi->handle; u_char sr_cmd[10]; char buffer[32]; int result; sr_cmd[0] = GPCMD_READ_SUBCHANNEL; - sr_cmd[1] = (SCp->device->scsi_level <= SCSI_2) ? - ((SCp->device->lun) << 5) : 0; + sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ? + ((cd->device->lun) << 5) : 0; sr_cmd[2] = 0x40; /* I do want the subchannel info */ sr_cmd[3] = 0x02; /* Give me medium catalog number info */ sr_cmd[4] = sr_cmd[5] = 0; @@ -297,7 +293,7 @@ int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) sr_cmd[8] = 24; sr_cmd[9] = 0; - result = sr_do_ioctl(minor(cdi->dev), sr_cmd, buffer, 24, 0, SCSI_DATA_READ, NULL); + result = sr_do_ioctl(cd, sr_cmd, buffer, 24, 0, SCSI_DATA_READ, NULL); memcpy(mcn->medium_catalog_number, buffer + 9, 13); mcn->medium_catalog_number[13] = 0; @@ -307,13 +303,12 @@ int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) int sr_reset(struct cdrom_device_info *cdi) { - invalidate_buffers(cdi->dev); return 0; } int sr_select_speed(struct cdrom_device_info *cdi, int speed) { - Scsi_CD *SCp = cdi->handle; + Scsi_CD *cd = cdi->handle; u_char sr_cmd[MAX_COMMAND_SIZE]; if (speed == 0) @@ -323,12 +318,12 @@ int sr_select_speed(struct cdrom_device_info *cdi, int speed) memset(sr_cmd, 0, MAX_COMMAND_SIZE); sr_cmd[0] = GPCMD_SET_SPEED; /* SET CD SPEED */ - sr_cmd[1] = (SCp->device->scsi_level <= SCSI_2) ? - ((SCp->device->lun) << 5) : 0; + sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ? + ((cd->device->lun) << 5) : 0; sr_cmd[2] = (speed >> 8) & 0xff; /* MSB for speed (in kbytes/sec) */ sr_cmd[3] = speed & 0xff; /* LSB */ - if (sr_do_ioctl(minor(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL)) + if (sr_do_ioctl(cd, sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL)) return -EIO; return 0; } @@ -341,9 +336,9 @@ int sr_select_speed(struct cdrom_device_info *cdi, int speed) int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg) { - Scsi_CD *SCp = cdi->handle; + Scsi_CD *cd = cdi->handle; u_char sr_cmd[10]; - int result, target = minor(cdi->dev); + int result; unsigned char buffer[32]; memset(sr_cmd, 0, sizeof(sr_cmd)); @@ -354,12 +349,12 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg) struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg; sr_cmd[0] = GPCMD_READ_TOC_PMA_ATIP; - sr_cmd[1] = (SCp->device->scsi_level <= SCSI_2) ? - ((SCp->device->lun) << 5) : 0; + sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ? + ((cd->device->lun) << 5) : 0; sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0; sr_cmd[8] = 12; /* LSB of length */ - result = sr_do_ioctl(target, sr_cmd, buffer, 12, 1, SCSI_DATA_READ, NULL); + result = sr_do_ioctl(cd, sr_cmd, buffer, 12, 1, SCSI_DATA_READ, NULL); tochdr->cdth_trk0 = buffer[2]; tochdr->cdth_trk1 = buffer[3]; @@ -372,14 +367,14 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg) struct cdrom_tocentry *tocentry = (struct cdrom_tocentry *) arg; sr_cmd[0] = GPCMD_READ_TOC_PMA_ATIP; - sr_cmd[1] = (SCp->device->scsi_level <= SCSI_2) ? - ((SCp->device->lun) << 5) : 0; + sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ? + ((cd->device->lun) << 5) : 0; sr_cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0; sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0; sr_cmd[6] = tocentry->cdte_track; sr_cmd[8] = 12; /* LSB of length */ - result = sr_do_ioctl(target, sr_cmd, buffer, 12, 0, SCSI_DATA_READ, NULL); + result = sr_do_ioctl(cd, sr_cmd, buffer, 12, 0, SCSI_DATA_READ, NULL); tocentry->cdte_ctrl = buffer[5] & 0xf; tocentry->cdte_adr = buffer[5] >> 4; @@ -399,14 +394,14 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg) struct cdrom_ti* ti = (struct cdrom_ti*)arg; sr_cmd[0] = GPCMD_PLAYAUDIO_TI; - sr_cmd[1] = (SCp->device->scsi_level <= SCSI_2) ? - (SCp->device->lun << 5) : 0; + sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ? + (cd->device->lun << 5) : 0; sr_cmd[4] = ti->cdti_trk0; sr_cmd[5] = ti->cdti_ind0; sr_cmd[7] = ti->cdti_trk1; sr_cmd[8] = ti->cdti_ind1; - result = sr_do_ioctl(target, sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL); + result = sr_do_ioctl(cd, sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL); if (result == -EDRIVE_CANT_DO_THIS) result = sr_fake_playtrkind(cdi, ti); @@ -439,20 +434,19 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg) * blksize: 2048 | 2336 | 2340 | 2352 */ -int sr_read_cd(int minor, unsigned char *dest, int lba, int format, int blksize) +static int sr_read_cd(Scsi_CD *cd, unsigned char *dest, int lba, int format, int blksize) { unsigned char cmd[MAX_COMMAND_SIZE]; - Scsi_CD *SCp = &scsi_CDs[minor]; #ifdef DEBUG - printk("sr%d: sr_read_cd lba=%d format=%d blksize=%d\n", - minor, lba, format, blksize); + printk("%s: sr_read_cd lba=%d format=%d blksize=%d\n", + cd->cdi.name, lba, format, blksize); #endif memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = GPCMD_READ_CD; /* READ_CD */ - cmd[1] = (SCp->device->scsi_level <= SCSI_2) ? - (SCp->device->lun << 5) : 0; + cmd[1] = (cd->device->scsi_level <= SCSI_2) ? + (cd->device->lun << 5) : 0; cmd[1] |= ((format & 7) << 2); cmd[2] = (unsigned char) (lba >> 24) & 0xff; cmd[3] = (unsigned char) (lba >> 16) & 0xff; @@ -473,47 +467,46 @@ int sr_read_cd(int minor, unsigned char *dest, int lba, int format, int blksize) cmd[9] = 0x10; break; } - return sr_do_ioctl(minor, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL); + return sr_do_ioctl(cd, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL); } /* * read sectors with blocksizes other than 2048 */ -int sr_read_sector(int minor, int lba, int blksize, unsigned char *dest) +static int sr_read_sector(Scsi_CD *cd, int lba, int blksize, unsigned char *dest) { unsigned char cmd[MAX_COMMAND_SIZE]; /* the scsi-command */ - Scsi_CD *SCp = &scsi_CDs[minor]; int rc; /* we try the READ CD command first... */ - if (SCp->readcd_known) { - rc = sr_read_cd(minor, dest, lba, 0, blksize); + if (cd->readcd_known) { + rc = sr_read_cd(cd, dest, lba, 0, blksize); if (-EDRIVE_CANT_DO_THIS != rc) return rc; - SCp->readcd_known = 0; + cd->readcd_known = 0; printk("CDROM does'nt support READ CD (0xbe) command\n"); /* fall & retry the other way */ } /* ... if this fails, we switch the blocksize using MODE SELECT */ - if (blksize != SCp->device->sector_size) { - if (0 != (rc = sr_set_blocklength(minor, blksize))) + if (blksize != cd->device->sector_size) { + if (0 != (rc = sr_set_blocklength(cd, blksize))) return rc; } #ifdef DEBUG - printk("sr%d: sr_read_sector lba=%d blksize=%d\n", minor, lba, blksize); + printk("%s: sr_read_sector lba=%d blksize=%d\n", cd->cdi.name, lba, blksize); #endif memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = GPCMD_READ_10; - cmd[1] = (SCp->device->scsi_level <= SCSI_2) ? - (SCp->device->lun << 5) : 0; + cmd[1] = (cd->device->scsi_level <= SCSI_2) ? + (cd->device->lun << 5) : 0; cmd[2] = (unsigned char) (lba >> 24) & 0xff; cmd[3] = (unsigned char) (lba >> 16) & 0xff; cmd[4] = (unsigned char) (lba >> 8) & 0xff; cmd[5] = (unsigned char) lba & 0xff; cmd[8] = 1; - rc = sr_do_ioctl(minor, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL); + rc = sr_do_ioctl(cd, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL); return rc; } @@ -523,10 +516,9 @@ int sr_read_sector(int minor, int lba, int blksize, unsigned char *dest) * ret: 1 == mode2 (XA), 0 == mode1, <0 == error */ -int sr_is_xa(int minor) +int sr_is_xa(Scsi_CD *cd) { unsigned char *raw_sector; - Scsi_CD *SCp = &scsi_CDs[minor]; int is_xa; if (!xa_test) @@ -535,7 +527,7 @@ int sr_is_xa(int minor) raw_sector = (unsigned char *) kmalloc(2048, GFP_DMA | GFP_KERNEL); if (!raw_sector) return -ENOMEM; - if (0 == sr_read_sector(minor, SCp->ms_offset + 16, + if (0 == sr_read_sector(cd, cd->ms_offset + 16, CD_FRAMESIZE_RAW1, raw_sector)) { is_xa = (raw_sector[3] == 0x02) ? 1 : 0; } else { @@ -544,7 +536,7 @@ int sr_is_xa(int minor) } kfree(raw_sector); #ifdef DEBUG - printk("sr%d: sr_is_xa: %d\n", minor, is_xa); + printk("%s: sr_is_xa: %d\n", cd->cdi.name, is_xa); #endif return is_xa; } @@ -552,16 +544,16 @@ int sr_is_xa(int minor) int sr_dev_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, unsigned long arg) { - Scsi_CD *SCp = cdi->handle; + Scsi_CD *cd = cdi->handle; switch (cmd) { case BLKGETSIZE: - return put_user(SCp->capacity, (unsigned long *) arg); + return put_user(cd->capacity, (unsigned long *) arg); case BLKGETSIZE64: - return put_user((u64)SCp->capacity << 9, (u64 *)arg); + return put_user((u64)cd->capacity << 9, (u64 *)arg); default: - return scsi_ioctl(SCp->device, cmd, (void *)arg); + return scsi_ioctl(cd->device, cmd, (void *)arg); } } diff --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c index 9733ae387f65..b7000df8b520 100644 --- a/drivers/scsi/sr_vendor.c +++ b/drivers/scsi/sr_vendor.c @@ -58,25 +58,25 @@ #define VENDOR_TOSHIBA 3 #define VENDOR_WRITER 4 /* pre-scsi3 writers */ -void sr_vendor_init(Scsi_CD *SCp) +void sr_vendor_init(Scsi_CD *cd) { #ifndef CONFIG_BLK_DEV_SR_VENDOR - SCp->vendor = VENDOR_SCSI3; + cd->vendor = VENDOR_SCSI3; #else - char *vendor = SCp->device->vendor; - char *model = SCp->device->model; + char *vendor = cd->device->vendor; + char *model = cd->device->model; /* default */ - SCp->vendor = VENDOR_SCSI3; - if (SCp->readcd_known) + cd->vendor = VENDOR_SCSI3; + if (cd->readcd_known) /* this is true for scsi3/mmc drives - no more checks */ return; - if (SCp->device->type == TYPE_WORM) { - SCp->vendor = VENDOR_WRITER; + if (cd->device->type == TYPE_WORM) { + cd->vendor = VENDOR_WRITER; } else if (!strncmp(vendor, "NEC", 3)) { - SCp->vendor = VENDOR_NEC; + cd->vendor = VENDOR_NEC; if (!strncmp(model, "CD-ROM DRIVE:25", 15) || !strncmp(model, "CD-ROM DRIVE:36", 15) || !strncmp(model, "CD-ROM DRIVE:83", 15) || @@ -88,10 +88,10 @@ void sr_vendor_init(Scsi_CD *SCp) #endif ) /* these can't handle multisession, may hang */ - SCp->cdi.mask |= CDC_MULTI_SESSION; + cd->cdi.mask |= CDC_MULTI_SESSION; } else if (!strncmp(vendor, "TOSHIBA", 7)) { - SCp->vendor = VENDOR_TOSHIBA; + cd->vendor = VENDOR_TOSHIBA; } #endif @@ -101,16 +101,15 @@ void sr_vendor_init(Scsi_CD *SCp) /* small handy function for switching block length using MODE SELECT, * used by sr_read_sector() */ -int sr_set_blocklength(int minor, int blocklength) +int sr_set_blocklength(Scsi_CD *cd, int blocklength) { unsigned char *buffer; /* the buffer for the ioctl */ unsigned char cmd[MAX_COMMAND_SIZE]; /* the scsi-command */ struct ccs_modesel_head *modesel; - Scsi_CD *SCp = &scsi_CDs[minor]; int rc, density = 0; #ifdef CONFIG_BLK_DEV_SR_VENDOR - if (SCp->vendor == VENDOR_TOSHIBA) + if (cd->vendor == VENDOR_TOSHIBA) density = (blocklength > 2048) ? 0x81 : 0x83; #endif @@ -119,12 +118,12 @@ int sr_set_blocklength(int minor, int blocklength) return -ENOMEM; #ifdef DEBUG - printk("sr%d: MODE SELECT 0x%x/%d\n", minor, density, blocklength); + printk("%s: MODE SELECT 0x%x/%d\n", cd->cdi.name, density, blocklength); #endif memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = MODE_SELECT; - cmd[1] = (SCp->device->scsi_level <= SCSI_2) ? - (SCp->device->lun << 5) : 0; + cmd[1] = (cd->device->scsi_level <= SCSI_2) ? + (cd->device->lun << 5) : 0; cmd[1] |= (1 << 4); cmd[4] = 12; modesel = (struct ccs_modesel_head *) buffer; @@ -133,13 +132,13 @@ int sr_set_blocklength(int minor, int blocklength) modesel->density = density; modesel->block_length_med = (blocklength >> 8) & 0xff; modesel->block_length_lo = blocklength & 0xff; - if (0 == (rc = sr_do_ioctl(minor, cmd, buffer, sizeof(*modesel), 0, SCSI_DATA_WRITE, NULL))) { - SCp->device->sector_size = blocklength; + if (0 == (rc = sr_do_ioctl(cd, cmd, buffer, sizeof(*modesel), 0, SCSI_DATA_WRITE, NULL))) { + cd->device->sector_size = blocklength; } #ifdef DEBUG else - printk("sr%d: switching blocklength to %d bytes failed\n", - minor, blocklength); + printk("%s: switching blocklength to %d bytes failed\n", + cd->cdi.name, blocklength); #endif kfree(buffer); return rc; @@ -152,14 +151,13 @@ int sr_set_blocklength(int minor, int blocklength) int sr_cd_check(struct cdrom_device_info *cdi) { - Scsi_CD *SCp = cdi->handle; + Scsi_CD *cd = cdi->handle; unsigned long sector; unsigned char *buffer; /* the buffer for the ioctl */ unsigned char cmd[MAX_COMMAND_SIZE]; /* the scsi-command */ - int rc, no_multi, minor; + int rc, no_multi; - minor = minor(cdi->dev); - if (SCp->cdi.mask & CDC_MULTI_SESSION) + if (cd->cdi.mask & CDC_MULTI_SESSION) return 0; buffer = (unsigned char *) kmalloc(512, GFP_KERNEL | GFP_DMA); @@ -170,21 +168,21 @@ int sr_cd_check(struct cdrom_device_info *cdi) no_multi = 0; /* flag: the drive can't handle multisession */ rc = 0; - switch (SCp->vendor) { + switch (cd->vendor) { case VENDOR_SCSI3: memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = READ_TOC; - cmd[1] = (SCp->device->scsi_level <= SCSI_2) ? - (SCp->device->lun << 5) : 0; + cmd[1] = (cd->device->scsi_level <= SCSI_2) ? + (cd->device->lun << 5) : 0; cmd[8] = 12; cmd[9] = 0x40; - rc = sr_do_ioctl(minor, cmd, buffer, 12, 1, SCSI_DATA_READ, NULL); + rc = sr_do_ioctl(cd, cmd, buffer, 12, 1, SCSI_DATA_READ, NULL); if (rc != 0) break; if ((buffer[0] << 8) + buffer[1] < 0x0a) { - printk(KERN_INFO "sr%d: Hmm, seems the drive " - "doesn't support multisession CD's\n", minor); + printk(KERN_INFO "%s: Hmm, seems the drive " + "doesn't support multisession CD's\n", cd->cdi.name); no_multi = 1; break; } @@ -201,16 +199,17 @@ int sr_cd_check(struct cdrom_device_info *cdi) unsigned long min, sec, frame; memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = 0xde; - cmd[1] = (SCp->device->scsi_level <= SCSI_2) ? - (SCp->device->lun << 5) : 0; + cmd[1] = (cd->device->scsi_level <= SCSI_2) ? + (cd->device->lun << 5) : 0; cmd[1] |= 0x03; cmd[2] = 0xb0; - rc = sr_do_ioctl(minor, cmd, buffer, 0x16, 1, SCSI_DATA_READ, NULL); + rc = sr_do_ioctl(cd, cmd, buffer, 0x16, 1, SCSI_DATA_READ, NULL); if (rc != 0) break; if (buffer[14] != 0 && buffer[14] != 0xb0) { - printk(KERN_INFO "sr%d: Hmm, seems the cdrom " - "doesn't support multisession CD's\n", minor); + printk(KERN_INFO "%s: Hmm, seems the cdrom " + "doesn't support multisession CD's\n", + cd->cdi.name); no_multi = 1; break; } @@ -228,13 +227,14 @@ int sr_cd_check(struct cdrom_device_info *cdi) * where starts the last session ?) */ memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = 0xc7; - cmd[1] = (SCp->device->scsi_level <= SCSI_2) ? - (SCp->device->lun << 5) : 0; + cmd[1] = (cd->device->scsi_level <= SCSI_2) ? + (cd->device->lun << 5) : 0; cmd[1] |= 0x03; - rc = sr_do_ioctl(minor, cmd, buffer, 4, 1, SCSI_DATA_READ, NULL); + rc = sr_do_ioctl(cd, cmd, buffer, 4, 1, SCSI_DATA_READ, NULL); if (rc == -EINVAL) { - printk(KERN_INFO "sr%d: Hmm, seems the drive " - "doesn't support multisession CD's\n", minor); + printk(KERN_INFO "%s: Hmm, seems the drive " + "doesn't support multisession CD's\n", + cd->cdi.name); no_multi = 1; break; } @@ -246,33 +246,33 @@ int sr_cd_check(struct cdrom_device_info *cdi) sector = min * CD_SECS * CD_FRAMES + sec * CD_FRAMES + frame; if (sector) sector -= CD_MSF_OFFSET; - sr_set_blocklength(minor, 2048); + sr_set_blocklength(cd, 2048); break; } case VENDOR_WRITER: memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = READ_TOC; - cmd[1] = (SCp->device->scsi_level <= SCSI_2) ? - (SCp->device->lun << 5) : 0; + cmd[1] = (cd->device->scsi_level <= SCSI_2) ? + (cd->device->lun << 5) : 0; cmd[8] = 0x04; cmd[9] = 0x40; - rc = sr_do_ioctl(minor, cmd, buffer, 0x04, 1, SCSI_DATA_READ, NULL); + rc = sr_do_ioctl(cd, cmd, buffer, 0x04, 1, SCSI_DATA_READ, NULL); if (rc != 0) { break; } if ((rc = buffer[2]) == 0) { printk(KERN_WARNING - "sr%d: No finished session\n", minor); + "%s: No finished session\n", cd->cdi.name); break; } cmd[0] = READ_TOC; /* Read TOC */ - cmd[1] = (SCp->device->scsi_level <= SCSI_2) ? - (SCp->device->lun << 5) : 0; + cmd[1] = (cd->device->scsi_level <= SCSI_2) ? + (cd->device->lun << 5) : 0; cmd[6] = rc & 0x7f; /* number of last session */ cmd[8] = 0x0c; cmd[9] = 0x40; - rc = sr_do_ioctl(minor, cmd, buffer, 12, 1, SCSI_DATA_READ, NULL); + rc = sr_do_ioctl(cd, cmd, buffer, 12, 1, SCSI_DATA_READ, NULL); if (rc != 0) { break; } @@ -284,27 +284,27 @@ int sr_cd_check(struct cdrom_device_info *cdi) default: /* should not happen */ printk(KERN_WARNING - "sr%d: unknown vendor code (%i), not initialized ?\n", - minor, SCp->vendor); + "%s: unknown vendor code (%i), not initialized ?\n", + cd->cdi.name, cd->vendor); sector = 0; no_multi = 1; break; } - SCp->ms_offset = sector; - SCp->xa_flag = 0; - if (CDS_AUDIO != sr_disk_status(cdi) && 1 == sr_is_xa(minor)) - SCp->xa_flag = 1; + cd->ms_offset = sector; + cd->xa_flag = 0; + if (CDS_AUDIO != sr_disk_status(cdi) && 1 == sr_is_xa(cd)) + cd->xa_flag = 1; - if (2048 != SCp->device->sector_size) { - sr_set_blocklength(minor, 2048); + if (2048 != cd->device->sector_size) { + sr_set_blocklength(cd, 2048); } if (no_multi) cdi->mask |= CDC_MULTI_SESSION; #ifdef DEBUG if (sector) - printk(KERN_DEBUG "sr%d: multisession offset=%lu\n", - minor, sector); + printk(KERN_DEBUG "%s: multisession offset=%lu\n", + cd->cdi.name, sector); #endif kfree(buffer); return rc; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index ffb781e46792..074e657bee0b 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -184,7 +184,7 @@ static struct Scsi_Device_Template st_template = { static int st_compression(Scsi_Tape *, int); static int find_partition(Scsi_Tape *); -static int update_partition(Scsi_Tape *); +static int switch_partition(Scsi_Tape *); static int st_int_ioctl(Scsi_Tape *, unsigned int, unsigned long); @@ -1028,9 +1028,9 @@ static int st_flush(struct file *filp) } if (STp->can_partitions && - (result2 = update_partition(STp)) < 0) { + (result2 = switch_partition(STp)) < 0) { DEBC(printk(ST_DEB_MSG - "st%d: update_partition at close failed.\n", dev)); + "st%d: switch_partition at close failed.\n", dev)); if (result == 0) result = result2; goto out; @@ -1206,7 +1206,7 @@ static ssize_t rw_checks(Scsi_Tape *STp, struct file *filp, size_t count, loff_t } ) /* end DEB */ if (STp->can_partitions && - (retval = update_partition(STp)) < 0) + (retval = switch_partition(STp)) < 0) goto out; if (STp->block_size == 0 && STp->max_block > 0 && @@ -2904,7 +2904,7 @@ static int find_partition(Scsi_Tape *STp) /* Change the partition if necessary */ -static int update_partition(Scsi_Tape *STp) +static int switch_partition(Scsi_Tape *STp) { ST_partstat *STps; @@ -3239,7 +3239,7 @@ static int st_ioctl(struct inode *inode, struct file *file, } if (STp->can_partitions && STp->ready == ST_READY && - (i = update_partition(STp)) < 0) { + (i = switch_partition(STp)) < 0) { retval = i; goto out; } @@ -3260,7 +3260,7 @@ static int st_ioctl(struct inode *inode, struct file *file, goto out; } if (STp->can_partitions && - (i = update_partition(STp)) < 0) { + (i = switch_partition(STp)) < 0) { retval = i; goto out; } diff --git a/fs/affs/file.c b/fs/affs/file.c index 6568b35895e9..af200dd36b29 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -27,6 +27,7 @@ #include <linux/fs.h> #include <linux/amigaffs.h> #include <linux/mm.h> +#include <linux/highmem.h> #include <linux/pagemap.h> #include <linux/buffer_head.h> @@ -518,6 +519,7 @@ affs_do_readpage_ofs(struct file *file, struct page *page, unsigned from, unsign pr_debug("AFFS: read_page(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to); if (from > to || to > PAGE_CACHE_SIZE) BUG(); + kmap(page); data = page_address(page); bsize = AFFS_SB(sb)->s_data_blksize; tmp = (page->index << PAGE_CACHE_SHIFT) + from; @@ -537,6 +539,8 @@ affs_do_readpage_ofs(struct file *file, struct page *page, unsigned from, unsign from += tmp; boff = 0; } + flush_dcache_page(page); + kunmap(page); return 0; } @@ -656,7 +660,11 @@ static int affs_prepare_write_ofs(struct file *file, struct page *page, unsigned return err; } if (to < PAGE_CACHE_SIZE) { - memset(page_address(page) + to, 0, PAGE_CACHE_SIZE - to); + char *kaddr = kmap_atomic(page, KM_USER0); + + memset(kaddr + to, 0, PAGE_CACHE_SIZE - to); + flush_dcache_page(page); + kunmap_atomic(kaddr, KM_USER0); if (size > offset + to) { if (size < offset + PAGE_CACHE_SIZE) tmp = size & ~PAGE_CACHE_MASK; diff --git a/fs/block_dev.c b/fs/block_dev.c index 56fec1317128..7d8a089a9d0a 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -503,21 +503,16 @@ int check_disk_change(struct block_device *bdev) struct block_device_operations * bdops = bdev->bd_op; kdev_t dev = to_kdev_t(bdev->bd_dev); struct gendisk *disk; - struct hd_struct *part; if (bdops->check_media_change == NULL) return 0; if (!bdops->check_media_change(dev)) return 0; - printk(KERN_DEBUG "VFS: Disk change detected on device %s\n", - bdevname(bdev)); - if (invalidate_device(dev, 0)) printk("VFS: busy inodes on changed media.\n"); disk = get_gendisk(dev); - part = disk->part + minor(dev) - disk->first_minor; if (bdops->revalidate) bdops->revalidate(dev); if (disk && disk->minor_shift) @@ -527,17 +522,13 @@ int check_disk_change(struct block_device *bdev) int full_check_disk_change(struct block_device *bdev) { - int res; + int res = 0; + if (bdev->bd_contains != bdev) + BUG(); down(&bdev->bd_sem); - res = check_disk_change(bdev); - if (bdev->bd_invalidated && !bdev->bd_part_count) { - struct gendisk *g = get_gendisk(to_kdev_t(bdev->bd_dev)); - struct hd_struct *part; - part = g->part + MINOR(bdev->bd_dev) - g->first_minor; - bdev->bd_invalidated = 0; - wipe_partitions(to_kdev_t(bdev->bd_dev)); - if (part[0].nr_sects) - check_partition(g, bdev); + if (check_disk_change(bdev)) { + rescan_partitions(get_gendisk(to_kdev_t(bdev->bd_dev)), bdev); + res = 1; } up(&bdev->bd_sem); return res; @@ -602,8 +593,7 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file * struct gendisk *g = get_gendisk(dev); bdev->bd_contains = bdev; if (g) { - int shift = g->minor_shift; - unsigned minor0 = (minor >> shift) << shift; + unsigned minor0 = g->first_minor; if (minor != minor0) { struct block_device *disk; disk = bdget(MKDEV(major(dev), minor0)); @@ -637,11 +627,9 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file * sector_t sect = 0; bdev->bd_offset = 0; - if (g) { - struct hd_struct *p; - p = g->part + minor(dev) - g->first_minor; - sect = p->nr_sects; - } else if (blk_size[major(dev)]) + if (g) + sect = get_capacity(g); + else if (blk_size[major(dev)]) sect = blk_size[major(dev)][minor(dev)] << 1; bd_set_size(bdev, (loff_t)sect << 9); bdi = blk_get_backing_dev_info(bdev); @@ -650,21 +638,15 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file * inode->i_data.backing_dev_info = bdi; bdev->bd_inode->i_data.backing_dev_info = bdi; } - if (bdev->bd_invalidated && !bdev->bd_part_count) { - struct hd_struct *part; - part = g->part + minor(dev) - g->first_minor; - bdev->bd_invalidated = 0; - wipe_partitions(dev); - if (part[0].nr_sects) - check_partition(g, bdev); - } + if (bdev->bd_invalidated) + rescan_partitions(g, bdev); } else { down(&bdev->bd_contains->bd_sem); bdev->bd_contains->bd_part_count++; if (!bdev->bd_openers) { struct gendisk *g = get_gendisk(dev); struct hd_struct *p; - p = g->part + minor(dev) - g->first_minor; + p = g->part + minor(dev) - g->first_minor - 1; inode->i_data.backing_dev_info = bdev->bd_inode->i_data.backing_dev_info = bdev->bd_contains->bd_inode->i_data.backing_dev_info; @@ -792,27 +774,15 @@ static int blkdev_reread_part(struct block_device *bdev) { kdev_t dev = to_kdev_t(bdev->bd_dev); struct gendisk *disk = get_gendisk(dev); - struct hd_struct *part; - int res; + int res = 0; - if (!disk || !disk->minor_shift) + if (!disk || !disk->minor_shift || bdev != bdev->bd_contains) return -EINVAL; - part = disk->part + minor(dev) - disk->first_minor; if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (down_trylock(&bdev->bd_sem)) return -EBUSY; - if (bdev->bd_part_count) { - up(&bdev->bd_sem); - return -EBUSY; - } - res = wipe_partitions(dev); - if (!res) { - if (bdev->bd_op->revalidate) - bdev->bd_op->revalidate(dev); - if (part[0].nr_sects) - check_partition(disk, bdev); - } + res = rescan_partitions(disk, bdev); up(&bdev->bd_sem); return res; } diff --git a/fs/buffer.c b/fs/buffer.c index 30dec7003327..20b2874fd6d8 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1784,6 +1784,7 @@ done: if (err == 0) return ret; return err; + recover: /* * ENOSPC, or some other error. We may already have added some @@ -1795,7 +1796,8 @@ recover: bh = head; /* Recovery: lock and submit the mapped buffers */ do { - if (buffer_mapped(bh)) { + get_bh(bh); + if (buffer_mapped(bh) && buffer_dirty(bh)) { lock_buffer(bh); mark_buffer_async_write(bh); } else { @@ -1805,21 +1807,21 @@ recover: */ clear_buffer_dirty(bh); } - bh = bh->b_this_page; - } while (bh != head); + } while ((bh = bh->b_this_page) != head); + SetPageError(page); + BUG_ON(PageWriteback(page)); + SetPageWriteback(page); + unlock_page(page); do { struct buffer_head *next = bh->b_this_page; if (buffer_async_write(bh)) { - set_buffer_uptodate(bh); clear_buffer_dirty(bh); submit_bh(WRITE, bh); nr_underway++; } + put_bh(bh); bh = next; } while (bh != head); - BUG_ON(PageWriteback(page)); - SetPageWriteback(page); - unlock_page(page); goto done; } @@ -1831,7 +1833,6 @@ static int __block_prepare_write(struct inode *inode, struct page *page, int err = 0; unsigned blocksize, bbits; struct buffer_head *bh, *head, *wait[2], **wait_bh=wait; - char *kaddr = kmap(page); BUG_ON(!PageLocked(page)); BUG_ON(from > PAGE_CACHE_SIZE); @@ -1872,13 +1873,19 @@ static int __block_prepare_write(struct inode *inode, struct page *page, set_buffer_uptodate(bh); continue; } - if (block_end > to) - memset(kaddr+to, 0, block_end-to); - if (block_start < from) - memset(kaddr+block_start, - 0, from-block_start); - if (block_end > to || block_start < from) + if (block_end > to || block_start < from) { + void *kaddr; + + kaddr = kmap_atomic(page, KM_USER0); + if (block_end > to) + memset(kaddr+to, 0, + block_end-to); + if (block_start < from) + memset(kaddr+block_start, + 0, from-block_start); flush_dcache_page(page); + kunmap_atomic(kaddr, KM_USER0); + } continue; } } @@ -1917,10 +1924,14 @@ out: if (block_start >= to) break; if (buffer_new(bh)) { + void *kaddr; + clear_buffer_new(bh); if (buffer_uptodate(bh)) buffer_error(); + kaddr = kmap_atomic(page, KM_USER0); memset(kaddr+block_start, 0, bh->b_size); + kunmap_atomic(kaddr, KM_USER0); set_buffer_uptodate(bh); mark_buffer_dirty(bh); } @@ -2006,9 +2017,10 @@ int block_read_full_page(struct page *page, get_block_t *get_block) SetPageError(page); } if (!buffer_mapped(bh)) { - memset(kmap(page) + i*blocksize, 0, blocksize); + void *kaddr = kmap_atomic(page, KM_USER0); + memset(kaddr + i * blocksize, 0, blocksize); flush_dcache_page(page); - kunmap(page); + kunmap_atomic(kaddr, KM_USER0); set_buffer_uptodate(bh); continue; } @@ -2116,7 +2128,7 @@ int cont_prepare_write(struct page *page, unsigned offset, long status; unsigned zerofrom; unsigned blocksize = 1 << inode->i_blkbits; - char *kaddr; + void *kaddr; while(page->index > (pgpos = *bytes>>PAGE_CACHE_SHIFT)) { status = -ENOMEM; @@ -2138,12 +2150,12 @@ int cont_prepare_write(struct page *page, unsigned offset, PAGE_CACHE_SIZE, get_block); if (status) goto out_unmap; - kaddr = page_address(new_page); + kaddr = kmap_atomic(new_page, KM_USER0); memset(kaddr+zerofrom, 0, PAGE_CACHE_SIZE-zerofrom); flush_dcache_page(new_page); + kunmap_atomic(kaddr, KM_USER0); __block_commit_write(inode, new_page, zerofrom, PAGE_CACHE_SIZE); - kunmap(new_page); unlock_page(new_page); page_cache_release(new_page); } @@ -2168,21 +2180,20 @@ int cont_prepare_write(struct page *page, unsigned offset, status = __block_prepare_write(inode, page, zerofrom, to, get_block); if (status) goto out1; - kaddr = page_address(page); if (zerofrom < offset) { + kaddr = kmap_atomic(page, KM_USER0); memset(kaddr+zerofrom, 0, offset-zerofrom); flush_dcache_page(page); + kunmap_atomic(kaddr, KM_USER0); __block_commit_write(inode, page, zerofrom, offset); } return 0; out1: ClearPageUptodate(page); - kunmap(page); return status; out_unmap: ClearPageUptodate(new_page); - kunmap(new_page); unlock_page(new_page); page_cache_release(new_page); out: @@ -2194,10 +2205,8 @@ int block_prepare_write(struct page *page, unsigned from, unsigned to, { struct inode *inode = page->mapping->host; int err = __block_prepare_write(inode, page, from, to, get_block); - if (err) { + if (err) ClearPageUptodate(page); - kunmap(page); - } return err; } @@ -2205,7 +2214,6 @@ int block_commit_write(struct page *page, unsigned from, unsigned to) { struct inode *inode = page->mapping->host; __block_commit_write(inode,page,from,to); - kunmap(page); return 0; } @@ -2215,7 +2223,6 @@ int generic_commit_write(struct file *file, struct page *page, struct inode *inode = page->mapping->host; loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; __block_commit_write(inode,page,from,to); - kunmap(page); if (pos > inode->i_size) { inode->i_size = pos; mark_inode_dirty(inode); @@ -2232,6 +2239,7 @@ int block_truncate_page(struct address_space *mapping, struct inode *inode = mapping->host; struct page *page; struct buffer_head *bh; + void *kaddr; int err; blocksize = 1 << inode->i_blkbits; @@ -2284,9 +2292,10 @@ int block_truncate_page(struct address_space *mapping, goto unlock; } - memset(kmap(page) + offset, 0, length); + kaddr = kmap_atomic(page, KM_USER0); + memset(kaddr + offset, 0, length); flush_dcache_page(page); - kunmap(page); + kunmap_atomic(kaddr, KM_USER0); mark_buffer_dirty(bh); err = 0; @@ -2306,7 +2315,7 @@ int block_write_full_page(struct page *page, get_block_t *get_block) struct inode * const inode = page->mapping->host; const unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT; unsigned offset; - char *kaddr; + void *kaddr; /* Is the page fully inside i_size? */ if (page->index < end_index) @@ -2326,10 +2335,10 @@ int block_write_full_page(struct page *page, get_block_t *get_block) * the page size, the remaining memory is zeroed when mapped, and * writes to that region are not written out to the file." */ - kaddr = kmap(page); + kaddr = kmap_atomic(page, KM_USER0); memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset); flush_dcache_page(page); - kunmap(page); + kunmap_atomic(kaddr, KM_USER0); return __block_write_full_page(inode, page, get_block); } diff --git a/fs/driverfs/inode.c b/fs/driverfs/inode.c index af41d842ef96..e91db32c1cbd 100644 --- a/fs/driverfs/inode.c +++ b/fs/driverfs/inode.c @@ -59,9 +59,11 @@ static int mount_count = 0; static int driverfs_readpage(struct file *file, struct page * page) { if (!PageUptodate(page)) { - memset(kmap(page), 0, PAGE_CACHE_SIZE); - kunmap(page); + void *kaddr = kmap_atomic(page, KM_USER0); + + memset(kaddr, 0, PAGE_CACHE_SIZE); flush_dcache_page(page); + kunmap_atomic(kaddr, KM_USER0); SetPageUptodate(page); } unlock_page(page); @@ -70,10 +72,12 @@ static int driverfs_readpage(struct file *file, struct page * page) static int driverfs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) { - void *addr = kmap(page); if (!PageUptodate(page)) { - memset(addr, 0, PAGE_CACHE_SIZE); + void *kaddr = kmap_atomic(page, KM_USER0); + + memset(kaddr, 0, PAGE_CACHE_SIZE); flush_dcache_page(page); + kunmap_atomic(kaddr, KM_USER0); SetPageUptodate(page); } return 0; @@ -85,7 +89,6 @@ static int driverfs_commit_write(struct file *file, struct page *page, unsigned loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; set_page_dirty(page); - kunmap(page); if (pos > inode->i_size) inode->i_size = pos; return 0; diff --git a/fs/exec.c b/fs/exec.c index 769380e3899a..9344e1ec3894 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -504,6 +504,8 @@ static inline int make_private_signals(void) { struct signal_struct * newsig; + remove_thread_group(current, current->sig); + if (atomic_read(¤t->sig->count) <= 1) return 0; newsig = kmem_cache_alloc(sigact_cachep, GFP_KERNEL); @@ -512,6 +514,8 @@ static inline int make_private_signals(void) spin_lock_init(&newsig->siglock); atomic_set(&newsig->count, 1); memcpy(newsig->action, current->sig->action, sizeof(newsig->action)); + init_sigpending(&newsig->shared_pending); + spin_lock_irq(¤t->sigmask_lock); current->sig = newsig; spin_unlock_irq(¤t->sigmask_lock); @@ -575,42 +579,10 @@ static inline void flush_old_files(struct files_struct * files) */ static void de_thread(struct task_struct *tsk) { - struct task_struct *sub; - struct list_head *head, *ptr; - struct siginfo info; - int pause; - - write_lock_irq(&tasklist_lock); - - if (tsk->tgid != tsk->pid) { - /* subsidiary thread - just escapes the group */ - list_del_init(&tsk->thread_group); - tsk->tgid = tsk->pid; - pause = 0; - } - else { - /* master thread - kill all subsidiary threads */ - info.si_signo = SIGKILL; - info.si_errno = 0; - info.si_code = SI_DETHREAD; - info.si_pid = current->pid; - info.si_uid = current->uid; - - head = tsk->thread_group.next; - list_del_init(&tsk->thread_group); - - list_for_each(ptr,head) { - sub = list_entry(ptr,struct task_struct,thread_group); - send_sig_info(SIGKILL,&info,sub); - } - - pause = 1; - } - - write_unlock_irq(&tasklist_lock); - - /* give the subsidiary threads a chance to clean themselves up */ - if (pause) yield(); + if (!list_empty(&tsk->thread_group)) + BUG(); + /* An exec() starts a new thread group: */ + tsk->tgid = tsk->pid; } int flush_old_exec(struct linux_binprm * bprm) @@ -633,6 +605,8 @@ int flush_old_exec(struct linux_binprm * bprm) if (retval) goto mmap_failed; /* This is the point of no return */ + de_thread(current); + release_old_signals(oldsig); current->sas_ss_sp = current->sas_ss_size = 0; @@ -651,9 +625,6 @@ int flush_old_exec(struct linux_binprm * bprm) flush_thread(); - if (!list_empty(¤t->thread_group)) - de_thread(current); - if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || permission(bprm->file->f_dentry->d_inode,MAY_READ)) current->mm->dumpable = 0; diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 1260a599e83a..b0a69d186471 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c @@ -571,8 +571,8 @@ int ext2_make_empty(struct inode *inode, struct inode *parent) struct page *page = grab_cache_page(mapping, 0); unsigned chunk_size = ext2_chunk_size(inode); struct ext2_dir_entry_2 * de; - char *base; int err; + void *kaddr; if (!page) return -ENOMEM; @@ -581,22 +581,21 @@ int ext2_make_empty(struct inode *inode, struct inode *parent) unlock_page(page); goto fail; } - base = page_address(page); - - de = (struct ext2_dir_entry_2 *) base; + kaddr = kmap_atomic(page, KM_USER0); + de = (struct ext2_dir_entry_2 *)kaddr; de->name_len = 1; de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(1)); memcpy (de->name, ".\0\0", 4); de->inode = cpu_to_le32(inode->i_ino); ext2_set_de_type (de, inode); - de = (struct ext2_dir_entry_2 *) (base + EXT2_DIR_REC_LEN(1)); + de = (struct ext2_dir_entry_2 *)(kaddr + EXT2_DIR_REC_LEN(1)); de->name_len = 2; de->rec_len = cpu_to_le16(chunk_size - EXT2_DIR_REC_LEN(1)); de->inode = cpu_to_le32(parent->i_ino); memcpy (de->name, "..\0", 4); ext2_set_de_type (de, inode); - + kunmap_atomic(kaddr, KM_USER0); err = ext2_commit_chunk(page, 0, chunk_size); fail: page_cache_release(page); diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index d7c0b7030a6e..38e3decdae39 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -1082,16 +1082,6 @@ static int ext3_prepare_write(struct file *file, struct page *page, if (ext3_should_journal_data(inode)) { ret = walk_page_buffers(handle, page_buffers(page), from, to, NULL, do_journal_get_write_access); - if (ret) { - /* - * We're going to fail this prepare_write(), - * so commit_write() will not be called. - * We need to undo block_prepare_write()'s kmap(). - * AKPM: Do we need to clear PageUptodate? I don't - * think so. - */ - kunmap(page); - } } prepare_write_failed: if (ret) @@ -1151,7 +1141,6 @@ static int ext3_commit_write(struct file *file, struct page *page, from, to, &partial, commit_write_fn); if (!partial) SetPageUptodate(page); - kunmap(page); if (pos > inode->i_size) inode->i_size = pos; EXT3_I(inode)->i_state |= EXT3_STATE_JDATA; @@ -1162,17 +1151,8 @@ static int ext3_commit_write(struct file *file, struct page *page, } /* Be careful here if generic_commit_write becomes a * required invocation after block_prepare_write. */ - if (ret == 0) { + if (ret == 0) ret = generic_commit_write(file, page, from, to); - } else { - /* - * block_prepare_write() was called, but we're not - * going to call generic_commit_write(). So we - * need to perform generic_commit_write()'s kunmap - * by hand. - */ - kunmap(page); - } } if (inode->i_size > EXT3_I(inode)->i_disksize) { EXT3_I(inode)->i_disksize = inode->i_size; @@ -1535,6 +1515,7 @@ static int ext3_block_truncate_page(handle_t *handle, struct page *page; struct buffer_head *bh; int err; + void *kaddr; blocksize = inode->i_sb->s_blocksize; length = offset & (blocksize - 1); @@ -1590,10 +1571,11 @@ static int ext3_block_truncate_page(handle_t *handle, if (err) goto unlock; } - - memset(kmap(page) + offset, 0, length); + + kaddr = kmap_atomic(page, KM_USER0); + memset(kaddr + offset, 0, length); flush_dcache_page(page); - kunmap(page); + kunmap_atomic(kaddr, KM_USER0); BUFFER_TRACE(bh, "zeroed end of block"); diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 898cf3e1d940..79a5576740c5 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -982,11 +982,24 @@ static int fat_readpage(struct file *file, struct page *page) { return block_read_full_page(page,fat_get_block); } -static int fat_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) + +static int +fat_prepare_write(struct file *file, struct page *page, + unsigned from, unsigned to) { + kmap(page); return cont_prepare_write(page,from,to,fat_get_block, &MSDOS_I(page->mapping->host)->mmu_private); } + +static int +fat_commit_write(struct file *file, struct page *page, + unsigned from, unsigned to) +{ + kunmap(page); + return generic_commit_write(file, page, from, to); +} + static int _fat_bmap(struct address_space *mapping, long block) { return generic_block_bmap(mapping,block,fat_get_block); @@ -996,7 +1009,7 @@ static struct address_space_operations fat_aops = { writepage: fat_writepage, sync_page: block_sync_page, prepare_write: fat_prepare_write, - commit_write: generic_commit_write, + commit_write: fat_commit_write, bmap: _fat_bmap }; diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index aca27e701f64..a9711a7fefae 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c @@ -47,6 +47,7 @@ #include <linux/stat.h> #include <linux/blkdev.h> #include <linux/quotaops.h> +#include <linux/highmem.h> #include <linux/smp_lock.h> #include <asm/semaphore.h> #include <asm/byteorder.h> @@ -751,7 +752,6 @@ jffs_do_readpage_nolock(struct file *file, struct page *page) get_page(page); /* Don't SetPageLocked(page), should be locked already */ - buf = page_address(page); ClearPageUptodate(page); ClearPageError(page); @@ -760,8 +760,10 @@ jffs_do_readpage_nolock(struct file *file, struct page *page) read_len = 0; result = 0; - offset = page->index << PAGE_CACHE_SHIFT; + + kmap(page); + buf = page_address(page); if (offset < inode->i_size) { read_len = min_t(long, inode->i_size - offset, PAGE_SIZE); r = jffs_read_data(f, buf, offset, read_len); @@ -779,6 +781,8 @@ jffs_do_readpage_nolock(struct file *file, struct page *page) /* This handles the case of partial or no read in above */ if(read_len < PAGE_SIZE) memset(buf + read_len, 0, PAGE_SIZE - read_len); + flush_dcache_page(page); + kunmap(page); D3(printk (KERN_NOTICE "readpage(): up biglock\n")); up(&c->fmc->biglock); @@ -788,9 +792,8 @@ jffs_do_readpage_nolock(struct file *file, struct page *page) }else { SetPageUptodate(page); } - flush_dcache_page(page); - put_page(page); + page_cache_release(page); D3(printk("jffs_readpage(): Leaving...\n")); diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index a8cf25f2c141..1d75079a5fb1 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -17,6 +17,7 @@ #include <linux/fs.h> #include <linux/time.h> #include <linux/pagemap.h> +#include <linux/highmem.h> #include <linux/crc32.h> #include <linux/jffs2.h> #include "nodelist.h" @@ -381,9 +382,10 @@ int jffs2_commit_write (struct file *filp, struct page *pg, unsigned start, unsi ri->isize = (uint32_t)inode->i_size; ri->atime = ri->ctime = ri->mtime = CURRENT_TIME; - /* We rely on the fact that generic_file_write() currently kmaps the page for us. */ + kmap(pg); ret = jffs2_write_inode_range(c, f, ri, page_address(pg) + start, (pg->index << PAGE_CACHE_SHIFT) + start, end - start, &writtenlen); + kunmap(pg); if (ret) { /* There was an error writing. */ diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index eb4be0b97533..6c21109b9a94 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -403,7 +403,6 @@ static void __write_metapage(metapage_t * mp) if (rc) { jERROR(1, ("prepare_write return %d!\n", rc)); ClearPageUptodate(mp->page); - kunmap(mp->page); unlock_page(mp->page); clear_bit(META_dirty, &mp->flag); return; diff --git a/fs/minix/dir.c b/fs/minix/dir.c index 6df43a92d213..d8339f3f401f 100644 --- a/fs/minix/dir.c +++ b/fs/minix/dir.c @@ -7,6 +7,7 @@ */ #include "minix.h" +#include <linux/highmem.h> #include <linux/smp_lock.h> typedef struct minix_dir_entry minix_dirent; @@ -261,7 +262,7 @@ int minix_delete_entry(struct minix_dir_entry *de, struct page *page) { struct address_space *mapping = page->mapping; struct inode *inode = (struct inode*)mapping->host; - char *kaddr = (char*)page_address(page); + char *kaddr = page_address(page); unsigned from = (char*)de - kaddr; unsigned to = from + minix_sb(inode->i_sb)->s_dirsize; int err; @@ -286,7 +287,7 @@ int minix_make_empty(struct inode *inode, struct inode *dir) struct page *page = grab_cache_page(mapping, 0); struct minix_sb_info * sbi = minix_sb(inode->i_sb); struct minix_dir_entry * de; - char *base; + char *kaddr; int err; if (!page) @@ -297,15 +298,16 @@ int minix_make_empty(struct inode *inode, struct inode *dir) goto fail; } - base = (char*)page_address(page); - memset(base, 0, PAGE_CACHE_SIZE); + kaddr = kmap_atomic(page, KM_USER0); + memset(kaddr, 0, PAGE_CACHE_SIZE); - de = (struct minix_dir_entry *) base; + de = (struct minix_dir_entry *)kaddr; de->inode = inode->i_ino; strcpy(de->name,"."); de = minix_next_entry(de, sbi); de->inode = dir->i_ino; strcpy(de->name,".."); + kunmap_atomic(kaddr, KM_USER0); err = dir_commit_chunk(page, 0, 2 * sbi->s_dirsize); fail: diff --git a/fs/namei.c b/fs/namei.c index ade1cb87562c..59b7bc8f86ba 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2200,8 +2200,9 @@ int page_symlink(struct inode *inode, const char *symname, int len) err = mapping->a_ops->prepare_write(NULL, page, 0, len-1); if (err) goto fail_map; - kaddr = page_address(page); + kaddr = kmap_atomic(page, KM_USER0); memcpy(kaddr, symname, len-1); + kunmap_atomic(kaddr, KM_USER0); mapping->a_ops->commit_write(NULL, page, 0, len-1); /* * Notice that we are _not_ going to block here - end of page is diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 907cb1faf056..8a12dbe5d523 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -35,7 +35,7 @@ #include "efi.h" #if CONFIG_BLK_DEV_MD -extern void md_autodetect_dev(kdev_t dev); +extern void md_autodetect_dev(dev_t dev); #endif int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/ @@ -87,46 +87,27 @@ static int (*check_part[])(struct parsed_partitions *, struct block_device *) = * a pointer to that same buffer (for convenience). */ -char *disk_name (struct gendisk *hd, int minor, char *buf) +char *disk_name(struct gendisk *hd, int part, char *buf) { - unsigned int unit = (minor >> hd->minor_shift); - unsigned int part = (minor & ((1 << hd->minor_shift) -1 )); - struct hd_struct *p = hd->part + minor - hd->first_minor; - char s[40]; - const char *maj; - - if ((((minor - hd->first_minor) >> hd->minor_shift) < hd->nr_real) && - p->de) { - int pos; - - pos = devfs_generate_path(p->de, buf, 64); - if (pos >= 0) - return buf + pos; - } - - /* - * Yes, I know, ... in cases is gccism and not a pretty one. - * However, the first variant will eventually consume _all_ cases - * and switch will disappear. - */ - switch (hd->major) { - default: - maj = hd->major_name; - break; - case MD_MAJOR: - sprintf(s, "%s%d", "md", unit); - maj = s; - break; - case I2O_MAJOR: - sprintf(s, "%s%c", hd->major_name, unit + 'a'); - maj = s; + int pos; + if (!part) { + if (hd->disk_de) { + pos = devfs_generate_path(hd->disk_de, buf, 64); + if (pos >= 0) + return buf + pos; + } + sprintf(buf, "%s", hd->major_name); + } else { + if (hd->part[part-1].de) { + pos = devfs_generate_path(hd->part[part-1].de, buf, 64); + if (pos >= 0) + return buf + pos; + } + if (isdigit(hd->major_name[strlen(hd->major_name)-1])) + sprintf(buf, "%sp%d", hd->major_name, part); + else + sprintf(buf, "%s%d", hd->major_name, part); } - if (!part) - sprintf(buf, "%s", maj); - else if (isdigit(maj[strlen(maj)-1])) - sprintf(buf, "%sp%d", maj, part); - else - sprintf(buf, "%s%d", maj, part); return buf; } @@ -147,118 +128,91 @@ static ssize_t partition_device_type_read(struct device *driverfs_dev, } static DEVICE_ATTR(type,S_IRUGO,partition_device_type_read,NULL); -void driverfs_create_partitions(struct gendisk *hd, int minor) +static void driverfs_create_partitions(struct gendisk *hd) { - int pos = -1; - int devnum = (minor - hd->first_minor) >> hd->minor_shift; - char dirname[256]; - struct device *parent = 0; - int max_p; + int max_p = 1<<hd->minor_shift; + struct hd_struct *p = hd->part; + char name[DEVICE_NAME_SIZE]; + char bus_id[BUS_ID_SIZE]; + struct device *dev, *parent; int part; - devfs_handle_t dir = 0; - struct hd_struct *p = hd->part + minor - hd->first_minor; - - /* get parent driverfs device structure */ - if (hd->driverfs_dev_arr) - parent = hd->driverfs_dev_arr[devnum]; - else /* if driverfs not supported by subsystem, skip partitions */ + + /* if driverfs not supported by subsystem, skip partitions */ + if (!(hd->flags & GENHD_FL_DRIVERFS)) return; - - /* get parent device node directory name */ - if (hd->de_arr) { - dir = hd->de_arr[devnum]; - if (dir) - pos = devfs_generate_path (dir, dirname, - sizeof dirname); + + parent = hd->driverfs_dev; + + if (parent) { + sprintf(name, "%s", parent->name); + sprintf(bus_id, "%s:", parent->bus_id); + } else { + *name = *bus_id = '\0'; } - - if (pos < 0) { - disk_name(hd, minor, dirname); - pos = 0; + + dev = &hd->disk_dev; + dev->driver_data = (void *)(long)__mkdev(hd->major, hd->first_minor); + sprintf(dev->name, "%sdisc", name); + sprintf(dev->bus_id, "%sdisc", bus_id); + for (part=1; part < max_p; part++) { + dev = &p[part-1].hd_driverfs_dev; + sprintf(dev->name, "%spart%d", name, part); + sprintf(dev->bus_id, "%s:p%d", bus_id, part); + if (!p[part-1].nr_sects) + continue; + dev->driver_data = + (void *)(long)__mkdev(hd->major, hd->first_minor+part); } - - max_p = (1 << hd->minor_shift); - - /* for all partitions setup parents and device node names */ - for(part=0; part < max_p; part++) { - if ((part == 0) || (p[part].nr_sects >= 1)) { - struct device * current_driverfs_dev = - &p[part].hd_driverfs_dev; - current_driverfs_dev->parent = parent; - /* handle disc case */ - current_driverfs_dev->driver_data = - (void *)(long)__mkdev(hd->major, minor+part); - if (part == 0) { - if (parent) { - sprintf(current_driverfs_dev->name, - "%sdisc", parent->name); - sprintf(current_driverfs_dev->bus_id, - "%s:disc", parent->bus_id); - } else { - sprintf(current_driverfs_dev->name, - "disc"); - sprintf(current_driverfs_dev->bus_id, - "disc"); - } - } else { /* this is a partition */ - if (parent) { - sprintf(current_driverfs_dev->name, - "%spart%d", parent->name, part); - sprintf(current_driverfs_dev->bus_id, - "%s:p%d", parent->bus_id, part); - } else { - sprintf(current_driverfs_dev->name, - "part%d", part); - sprintf(current_driverfs_dev->bus_id, - "p%d" ,part); - } - } - if (parent) current_driverfs_dev->bus = parent->bus; - device_register(current_driverfs_dev); - device_create_file(current_driverfs_dev, - &dev_attr_type); - device_create_file(current_driverfs_dev, - &dev_attr_kdev); - } + + dev = &hd->disk_dev; + dev->parent = parent; + if (parent) + dev->bus = parent->bus; + device_register(dev); + device_create_file(dev, &dev_attr_type); + device_create_file(dev, &dev_attr_kdev); + + for (part=0; part < max_p-1; part++) { + dev = &p[part].hd_driverfs_dev; + dev->parent = parent; + if (parent) + dev->bus = parent->bus; + if (!dev->driver_data) + continue; + device_register(dev); + device_create_file(dev, &dev_attr_type); + device_create_file(dev, &dev_attr_kdev); } } -void driverfs_remove_partitions(struct gendisk *hd, int minor) +static void driverfs_remove_partitions(struct gendisk *hd) { - int max_p; + int max_p = 1<<hd->minor_shift; + struct device *dev; + struct hd_struct *p; int part; - struct device * current_driverfs_dev; - struct hd_struct *p = hd->part + minor - hd->first_minor; - - max_p=(1 << hd->minor_shift); - - /* for all parts setup parent relationships and device node names */ - for(part=1; part < max_p; part++) { - if ((p[part].nr_sects >= 1)) { - current_driverfs_dev = &p[part].hd_driverfs_dev; - device_remove_file(current_driverfs_dev, - &dev_attr_type); - device_remove_file(current_driverfs_dev, - &dev_attr_kdev); - put_device(current_driverfs_dev); + + for (part=1, p = hd->part; part < max_p; part++, p++) { + dev = &p->hd_driverfs_dev; + if (dev->driver_data) { + device_remove_file(dev, &dev_attr_type); + device_remove_file(dev, &dev_attr_kdev); + put_device(dev); + dev->driver_data = NULL; } } - current_driverfs_dev = &p->hd_driverfs_dev; - device_remove_file(current_driverfs_dev, - &dev_attr_type); - device_remove_file(current_driverfs_dev, - &dev_attr_kdev); - put_device(current_driverfs_dev); - return; + dev = &hd->disk_dev; + if (dev->driver_data) { + device_remove_file(dev, &dev_attr_type); + device_remove_file(dev, &dev_attr_kdev); + put_device(dev); + dev->driver_data = NULL; + } } -/* - * DON'T EXPORT - */ -void check_partition(struct gendisk *hd, struct block_device *bdev) +static void check_partition(struct gendisk *hd, struct block_device *bdev) { devfs_handle_t de = NULL; - kdev_t dev = to_kdev_t(bdev->bd_dev); char buf[64]; struct parsed_partitions *state; int i; @@ -267,17 +221,16 @@ void check_partition(struct gendisk *hd, struct block_device *bdev) if (!state) return; - if (hd->de_arr) - de = hd->de_arr[(minor(dev)-hd->first_minor)>>hd->minor_shift]; + if (hd->flags & GENHD_FL_DEVFS) + de = hd->de; i = devfs_generate_path (de, buf, sizeof buf); if (i >= 0) { printk(KERN_INFO " /dev/%s:", buf + i); sprintf(state->name, "p"); } else { - unsigned n = hd->major; - disk_name(hd, minor(dev), state->name); + disk_name(hd, 0, state->name); printk(KERN_INFO " %s:", state->name); - if (n - COMPAQ_SMART2_MAJOR <= 7 || n - COMPAQ_CISS_MAJOR <= 7) + if (isdigit(state->name[strlen(state->name)-1])) sprintf(state->name, "p"); } state->limit = 1<<hd->minor_shift; @@ -291,68 +244,65 @@ void check_partition(struct gendisk *hd, struct block_device *bdev) if (res < 0) { if (warn_no_part) printk(" unable to read partition table\n"); - goto out; + return; } - p = hd->part + minor(dev) - hd->first_minor; + p = hd->part; for (j = 1; j < state->limit; j++) { - p[j].start_sect = state->parts[j].from; - p[j].nr_sects = state->parts[j].size; + p[j-1].start_sect = state->parts[j].from; + p[j-1].nr_sects = state->parts[j].size; #if CONFIG_BLK_DEV_MD - if (!state->parts[j].flags) + if (!state->parts[j-1].flags) continue; - md_autodetect_dev(mk_kdev(major(dev),minor(dev)+j)); + md_autodetect_dev(bdev->bd_dev+j); #endif } - goto out; + return; } - printk(" unknown partition table\n"); -out: - driverfs_create_partitions(hd, minor(dev)); - devfs_register_partitions (hd, minor(dev), 0); } -#ifdef CONFIG_DEVFS_FS -static void devfs_register_partition (struct gendisk *dev, int minor, int part) +static void devfs_register_partition(struct gendisk *dev, int part) { - int devnum = (minor - dev->first_minor) >> dev->minor_shift; +#ifdef CONFIG_DEVFS_FS devfs_handle_t dir; unsigned int devfs_flags = DEVFS_FL_DEFAULT; - struct hd_struct *p = dev->part + minor - dev->first_minor; + struct hd_struct *p = dev->part; char devname[16]; - if (p[part].de) + if (p[part-1].de) return; - dir = devfs_get_parent(p[0].de); + dir = devfs_get_parent(dev->disk_de); if (!dir) return; - if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) ) + if (dev->flags & GENHD_FL_REMOVABLE) devfs_flags |= DEVFS_FL_REMOVABLE; - sprintf (devname, "part%d", part); - p[part].de = devfs_register (dir, devname, devfs_flags, - dev->major, minor + part, + sprintf(devname, "part%d", part); + p[part-1].de = devfs_register (dir, devname, devfs_flags, + dev->major, dev->first_minor + part, S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL); +#endif } +#ifdef CONFIG_DEVFS_FS static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER; +#endif -static void devfs_register_disc (struct gendisk *dev, int minor) +static void devfs_create_partitions(struct gendisk *dev) { +#ifdef CONFIG_DEVFS_FS int pos = 0; - int devnum = (minor - dev->first_minor) >> dev->minor_shift; devfs_handle_t dir, slave; unsigned int devfs_flags = DEVFS_FL_DEFAULT; char dirname[64], symlink[16]; static devfs_handle_t devfs_handle; - struct hd_struct *p = dev->part + minor - dev->first_minor; + int part, max_p = 1<<dev->minor_shift; + struct hd_struct *p = dev->part; - if (p[0].de) - return; - if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) ) + if (dev->flags & GENHD_FL_REMOVABLE) devfs_flags |= DEVFS_FL_REMOVABLE; - if (dev->de_arr) { - dir = dev->de_arr[devnum]; + if (dev->flags & GENHD_FL_DEVFS) { + dir = dev->de; if (!dir) /* Aware driver wants to block disc management */ return; pos = devfs_generate_path(dir, dirname + 3, sizeof dirname-3); @@ -362,46 +312,39 @@ static void devfs_register_disc (struct gendisk *dev, int minor) } else { /* Unaware driver: construct "real" directory */ sprintf(dirname, "../%s/disc%d", dev->major_name, - (dev->first_minor >> dev->minor_shift) + devnum); + dev->first_minor >> dev->minor_shift); dir = devfs_mk_dir(NULL, dirname + 3, NULL); } if (!devfs_handle) devfs_handle = devfs_mk_dir(NULL, "discs", NULL); - p[0].number = devfs_alloc_unique_number (&disc_numspace); - sprintf(symlink, "disc%d", p[0].number); + dev->number = devfs_alloc_unique_number (&disc_numspace); + sprintf(symlink, "disc%d", dev->number); devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT, dirname + pos, &slave, NULL); - p[0].de = devfs_register (dir, "disc", devfs_flags, dev->major, minor, + dev->disk_de = devfs_register(dir, "disc", devfs_flags, + dev->major, dev->first_minor, S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL); - devfs_auto_unregister(p[0].de, slave); - if (!dev->de_arr) + devfs_auto_unregister(dev->disk_de, slave); + if (!(dev->flags & GENHD_FL_DEVFS)) devfs_auto_unregister (slave, dir); + for (part = 1, p++; part < max_p; part++, p++) + if (p->nr_sects) + devfs_register_partition(dev, part); +#endif } -#endif /* CONFIG_DEVFS_FS */ -void devfs_register_partitions (struct gendisk *dev, int minor, int unregister) +static void devfs_remove_partitions(struct gendisk *dev) { #ifdef CONFIG_DEVFS_FS - int part, max_p; - struct hd_struct *p = dev->part + minor - dev->first_minor; - - if (!unregister) - devfs_register_disc (dev, minor); - max_p = (1 << dev->minor_shift); - for (part = 1; part < max_p; part++) { - if ( unregister || (p[part].nr_sects < 1) ) { - devfs_unregister(p[part].de); - p[part].de = NULL; - continue; - } - devfs_register_partition (dev, minor, part); - } - if (unregister) { - devfs_unregister(p[0].de); - p[0].de = NULL; - devfs_dealloc_unique_number(&disc_numspace, p[0].number); + int part; + for (part = (1<<dev->minor_shift)-1; part--; ) { + devfs_unregister(dev->part[part].de); + dev->part[part].de = NULL; } -#endif /* CONFIG_DEVFS_FS */ + devfs_unregister(dev->disk_de); + dev->disk_de = NULL; + devfs_dealloc_unique_number(&disc_numspace, dev->number); +#endif } /* @@ -414,28 +357,18 @@ void devfs_register_partitions (struct gendisk *dev, int minor, int unregister) * done */ -void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors, +void register_disk(struct gendisk *disk, kdev_t dev, unsigned minors, struct block_device_operations *ops, long size) { - if (!gdev) - return; - grok_partitions(dev, size); -} - -void grok_partitions(kdev_t dev, long size) -{ struct block_device *bdev; - struct gendisk *g = get_gendisk(dev); - struct hd_struct *p; - if (!g) + if (!disk) return; - p = g->part + minor(dev) - g->first_minor; - p[0].nr_sects = size; + set_capacity(disk, size); /* No minors to use for partitions */ - if (!g->minor_shift) + if (!disk->minor_shift) return; /* No such device (e.g., media were just removed) */ @@ -445,10 +378,66 @@ void grok_partitions(kdev_t dev, long size) bdev = bdget(kdev_t_to_nr(dev)); if (blkdev_get(bdev, FMODE_READ, 0, BDEV_RAW) < 0) return; - check_partition(g, bdev); + check_partition(disk, bdev); + driverfs_create_partitions(disk); + devfs_create_partitions(disk); blkdev_put(bdev, BDEV_RAW); } +void update_partition(struct gendisk *disk, int part) +{ + struct hd_struct *p = disk->part + part - 1; + struct device *dev = &p->hd_driverfs_dev; + + if (!p->nr_sects) { + if (p->de) { + devfs_unregister(p->de); + p->de = NULL; + } + if (dev->driver_data) { + device_remove_file(dev, &dev_attr_type); + device_remove_file(dev, &dev_attr_kdev); + put_device(dev); + dev->driver_data = NULL; + } + return; + } + if (!p->de) + devfs_register_partition(disk, part); + if (dev->driver_data || !(disk->flags & GENHD_FL_DRIVERFS)) + return; + dev->driver_data = + (void *)(long)__mkdev(disk->major, disk->first_minor+part); + device_register(dev); + device_create_file(dev, &dev_attr_type); + device_create_file(dev, &dev_attr_kdev); +} + +int rescan_partitions(struct gendisk *disk, struct block_device *bdev) +{ + kdev_t dev = to_kdev_t(bdev->bd_dev); + int p, res; + if (!bdev->bd_invalidated) + return 0; + if (bdev->bd_part_count) + return -EBUSY; + res = invalidate_device(dev, 1); + if (res) + return res; + bdev->bd_invalidated = 0; + for (p = 0; p < (1<<disk->minor_shift) - 1; p++) { + disk->part[p].start_sect = 0; + disk->part[p].nr_sects = 0; + } + if (bdev->bd_op->revalidate) + bdev->bd_op->revalidate(dev); + if (get_capacity(disk)) + check_partition(disk, bdev); + for (p = 1; p < (1<<disk->minor_shift); p++) + update_partition(disk, p); + return res; +} + unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Sector *p) { struct address_space *mapping = bdev->bd_inode->i_mapping; @@ -472,38 +461,46 @@ fail: return NULL; } -int wipe_partitions(kdev_t dev) +static int wipe_partitions(struct gendisk *disk) { - struct gendisk *g; + int max_p = 1 << disk->minor_shift; kdev_t devp; - int p, major, minor, minor0, max_p, res; - struct hd_struct *part; - - g = get_gendisk(dev); - if (g == NULL) - return -EINVAL; + int res; + int p; - max_p = 1 << g->minor_shift; - major = major(dev); - minor = minor(dev); - minor0 = minor & ~(max_p - 1); - if (minor0 != minor) /* for now only whole-disk reread */ - return -EINVAL; /* %%% later.. */ - - part = g->part + minor - g->first_minor; /* invalidate stuff */ - for (p = max_p - 1; p >= 0; p--) { - minor = minor0 + p; - devp = mk_kdev(major,minor); + for (p = max_p - 1; p > 0; p--) { + devp = mk_kdev(disk->major,disk->first_minor + p); #if 0 /* %%% superfluous? */ - if (part[p].nr_sects == 0) + if (disk->part[p-1].nr_sects == 0) continue; #endif res = invalidate_device(devp, 1); if (res) return res; - part[p].start_sect = 0; - part[p].nr_sects = 0; + disk->part[p-1].start_sect = 0; + disk->part[p-1].nr_sects = 0; } + devp = mk_kdev(disk->major,disk->first_minor); +#if 0 /* %%% superfluous? */ + if (disk->part[p].nr_sects == 0) + continue; +#endif + res = invalidate_device(devp, 1); + if (res) + return res; + disk->capacity = 0; return 0; } + +void del_gendisk(struct gendisk *disk) +{ + driverfs_remove_partitions(disk); + wipe_partitions(disk); + unlink_gendisk(disk); + devfs_remove_partitions(disk); + if (disk->part) { + kfree(disk->part); + disk->part = NULL; + } +} diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index 1beb8ecb05f8..d1af58486615 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c @@ -26,6 +26,7 @@ #include <linux/module.h> #include <linux/fs.h> #include <linux/pagemap.h> +#include <linux/highmem.h> #include <linux/init.h> #include <linux/string.h> #include <linux/smp_lock.h> @@ -47,8 +48,10 @@ static struct inode_operations ramfs_dir_inode_operations; static int ramfs_readpage(struct file *file, struct page * page) { if (!PageUptodate(page)) { - memset(kmap(page), 0, PAGE_CACHE_SIZE); - kunmap(page); + char *kaddr = kmap_atomic(page, KM_USER0); + + memset(kaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(kaddr, KM_USER0); flush_dcache_page(page); SetPageUptodate(page); } @@ -58,10 +61,12 @@ static int ramfs_readpage(struct file *file, struct page * page) static int ramfs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) { - void *addr = kmap(page); if (!PageUptodate(page)) { - memset(addr, 0, PAGE_CACHE_SIZE); + char *kaddr = kmap_atomic(page, KM_USER0); + + memset(kaddr, 0, PAGE_CACHE_SIZE); flush_dcache_page(page); + kunmap_atomic(kaddr, KM_USER0); SetPageUptodate(page); } SetPageDirty(page); @@ -73,7 +78,6 @@ static int ramfs_commit_write(struct file *file, struct page *page, unsigned off struct inode *inode = page->mapping->host; loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; - kunmap(page); if (pos > inode->i_size) inode->i_size = pos; return 0; diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 5b2862949193..3344121f15d6 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -7,6 +7,7 @@ #include <linux/reiserfs_fs.h> #include <linux/smp_lock.h> #include <linux/pagemap.h> +#include <linux/highmem.h> #include <asm/uaccess.h> #include <asm/unaligned.h> #include <linux/buffer_head.h> @@ -1672,8 +1673,6 @@ static int grab_tail_page(struct inode *p_s_inode, if (error) goto unlock ; - kunmap(page) ; /* mapped by block_prepare_write */ - head = page_buffers(page) ; bh = head; do { @@ -1768,10 +1767,13 @@ void reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps) { length = offset & (blocksize - 1) ; /* if we are not on a block boundary */ if (length) { + char *kaddr; + length = blocksize - length ; - memset((char *)kmap(page) + offset, 0, length) ; + kaddr = kmap_atomic(page, KM_USER0) ; + memset(kaddr + offset, 0, length) ; flush_dcache_page(page) ; - kunmap(page) ; + kunmap_atomic(kaddr, KM_USER0) ; if (buffer_mapped(bh) && bh->b_blocknr != 0) { mark_buffer_dirty(bh) ; } @@ -1921,23 +1923,25 @@ static int reiserfs_write_full_page(struct page *page) { struct buffer_head *arr[PAGE_CACHE_SIZE/512] ; int nr = 0 ; - if (!page_has_buffers(page)) { + if (!page_has_buffers(page)) block_prepare_write(page, 0, 0, NULL) ; - kunmap(page) ; - } + /* last page in the file, zero out any contents past the ** last byte in the file */ if (page->index >= end_index) { + char *kaddr; + last_offset = inode->i_size & (PAGE_CACHE_SIZE - 1) ; /* no file contents in this page */ if (page->index >= end_index + 1 || !last_offset) { error = -EIO ; goto fail ; } - memset((char *)kmap(page)+last_offset, 0, PAGE_CACHE_SIZE-last_offset) ; + kaddr = kmap_atomic(page, KM_USER0); + memset(kaddr + last_offset, 0, PAGE_CACHE_SIZE-last_offset) ; flush_dcache_page(page) ; - kunmap(page) ; + kunmap_atomic(kaddr, KM_USER0) ; } head = page_buffers(page) ; bh = head ; diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index 560f1f336111..8d6dfeec1e06 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c @@ -1286,15 +1286,15 @@ int reiserfs_delete_item (struct reiserfs_transaction_handle *th, ** ** p_s_un_bh is from the page cache (all unformatted nodes are ** from the page cache) and might be a highmem page. So, we - ** can't use p_s_un_bh->b_data. But, the page has already been - ** kmapped, so we can use page_address() + ** can't use p_s_un_bh->b_data. ** -clm */ - data = page_address(p_s_un_bh->b_page) ; + data = kmap_atomic(p_s_un_bh->b_page, KM_USER0); off = ((le_ih_k_offset (&s_ih) - 1) & (PAGE_CACHE_SIZE - 1)); memcpy(data + off, B_I_PITEM(PATH_PLAST_BUFFER(p_s_path), &s_ih), n_ret_value); + kunmap_atomic(data, KM_USER0); } /* Perform balancing after all resources have been collected at once. */ diff --git a/fs/reiserfs/tail_conversion.c b/fs/reiserfs/tail_conversion.c index ed235b1adeb4..9be2d624b989 100644 --- a/fs/reiserfs/tail_conversion.c +++ b/fs/reiserfs/tail_conversion.c @@ -122,11 +122,12 @@ int direct2indirect (struct reiserfs_transaction_handle *th, struct inode * inod } /* if we've copied bytes from disk into the page, we need to zero ** out the unused part of the block (it was not up to date before) - ** the page is still kmapped (by whoever called reiserfs_get_block) */ if (up_to_date_bh) { unsigned pgoff = (tail_offset + total_tail - 1) & (PAGE_CACHE_SIZE - 1); - memset(page_address(unbh->b_page) + pgoff, 0, n_blk_size - total_tail) ; + char *kaddr=kmap_atomic(up_to_date_bh->b_page, KM_USER0); + memset(kaddr + pgoff, 0, n_blk_size - total_tail) ; + kunmap_atomic(kaddr, KM_USER0); } REISERFS_I(inode)->i_first_direct_byte = U32_MAX; diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c index c7ae7625f15f..e56c14bec653 100644 --- a/fs/sysv/dir.c +++ b/fs/sysv/dir.c @@ -14,6 +14,7 @@ */ #include <linux/pagemap.h> +#include <linux/highmem.h> #include <linux/smp_lock.h> #include "sysv.h" @@ -273,6 +274,7 @@ int sysv_make_empty(struct inode *inode, struct inode *dir) if (!page) return -ENOMEM; + kmap(page); err = mapping->a_ops->prepare_write(NULL, page, 0, 2 * SYSV_DIRSIZE); if (err) { unlock_page(page); @@ -291,6 +293,7 @@ int sysv_make_empty(struct inode *inode, struct inode *dir) err = dir_commit_chunk(page, 0, 2 * SYSV_DIRSIZE); fail: + kunmap(page); page_cache_release(page); return err; } diff --git a/include/asm-alpha/core_t2.h b/include/asm-alpha/core_t2.h index 007cf43baf10..fdaa57aa2c14 100644 --- a/include/asm-alpha/core_t2.h +++ b/include/asm-alpha/core_t2.h @@ -19,7 +19,7 @@ * */ -#define T2_MEM_R1_MASK 0x03ffffff /* Mem sparse region 1 mask is 26 bits */ +#define T2_MEM_R1_MASK 0x07ffffff /* Mem sparse region 1 mask is 26 bits */ /* GAMMA-SABLE is a SABLE with EV5-based CPUs */ #define _GAMMA_BIAS 0x8000000000UL @@ -402,13 +402,17 @@ __EXTERN_INLINE void t2_outl(u32 b, unsigned long addr) * */ +#define t2_set_hae { \ + msb = addr >> 27; \ + addr &= T2_MEM_R1_MASK; \ + set_hae(msb); \ +} + __EXTERN_INLINE u8 t2_readb(unsigned long addr) { unsigned long result, msb; - msb = addr & 0xE0000000; - addr &= T2_MEM_R1_MASK; - set_hae(msb); + t2_set_hae; result = *(vip) ((addr << 5) + T2_SPARSE_MEM + 0x00); return __kernel_extbl(result, addr & 3); @@ -418,9 +422,7 @@ __EXTERN_INLINE u16 t2_readw(unsigned long addr) { unsigned long result, msb; - msb = addr & 0xE0000000; - addr &= T2_MEM_R1_MASK; - set_hae(msb); + t2_set_hae; result = *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08); return __kernel_extwl(result, addr & 3); @@ -431,9 +433,7 @@ __EXTERN_INLINE u32 t2_readl(unsigned long addr) { unsigned long msb; - msb = addr & 0xE0000000; - addr &= T2_MEM_R1_MASK; - set_hae(msb); + t2_set_hae; return *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18); } @@ -442,9 +442,7 @@ __EXTERN_INLINE u64 t2_readq(unsigned long addr) { unsigned long r0, r1, work, msb; - msb = addr & 0xE0000000; - addr &= T2_MEM_R1_MASK; - set_hae(msb); + t2_set_hae; work = (addr << 5) + T2_SPARSE_MEM + 0x18; r0 = *(vuip)(work); @@ -456,9 +454,7 @@ __EXTERN_INLINE void t2_writeb(u8 b, unsigned long addr) { unsigned long msb, w; - msb = addr & 0xE0000000; - addr &= T2_MEM_R1_MASK; - set_hae(msb); + t2_set_hae; w = __kernel_insbl(b, addr & 3); *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x00) = w; @@ -468,9 +464,7 @@ __EXTERN_INLINE void t2_writew(u16 b, unsigned long addr) { unsigned long msb, w; - msb = addr & 0xE0000000; - addr &= T2_MEM_R1_MASK; - set_hae(msb); + t2_set_hae; w = __kernel_inswl(b, addr & 3); *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08) = w; @@ -481,9 +475,7 @@ __EXTERN_INLINE void t2_writel(u32 b, unsigned long addr) { unsigned long msb; - msb = addr & 0xE0000000; - addr &= T2_MEM_R1_MASK; - set_hae(msb); + t2_set_hae; *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18) = b; } @@ -492,9 +484,7 @@ __EXTERN_INLINE void t2_writeq(u64 b, unsigned long addr) { unsigned long msb, work; - msb = addr & 0xE0000000; - addr &= T2_MEM_R1_MASK; - set_hae(msb); + t2_set_hae; work = (addr << 5) + T2_SPARSE_MEM + 0x18; *(vuip)work = b; diff --git a/include/asm-alpha/dma.h b/include/asm-alpha/dma.h index e6d667144b50..97daf7d786aa 100644 --- a/include/asm-alpha/dma.h +++ b/include/asm-alpha/dma.h @@ -75,34 +75,49 @@ #define MAX_DMA_CHANNELS 8 -/* The maximum address that we can perform a DMA transfer to on Alpha XL, - due to a hardware SIO (PCI<->ISA bus bridge) chip limitation, is 64MB. - See <asm/apecs.h> for more info. +/* + ISA DMA limitations on Alpha platforms, + + These may be due to SIO (PCI<->ISA bridge) chipset limitation, or + just a wiring limit. */ -/* The maximum address that we can perform a DMA transfer to on RUFFIAN, - due to a hardware SIO (PCI<->ISA bus bridge) chip limitation, is 16MB. - See <asm/pyxis.h> for more info. + +/* The maximum address for ISA DMA transfer on Alpha XL, due to an + hardware SIO limitation, is 64MB. +*/ +#define ALPHA_XL_MAX_DMA_ADDRESS (IDENT_ADDR+0x04000000UL) + +/* The maximum address for ISA DMA transfer on RUFFIAN and NAUTILUS, + due to an hardware SIO limitation, is 16MB. */ -/* NOTE: we must define the maximum as something less than 64Mb, to prevent - virt_to_bus() from returning an address in the first window, for a - data area that goes beyond the 64Mb first DMA window. Sigh... - We MUST coordinate the maximum with <asm/apecs.h> for consistency. - For now, this limit is set to 48Mb... +#define ALPHA_RUFFIAN_MAX_DMA_ADDRESS (IDENT_ADDR+0x01000000UL) +#define ALPHA_NAUTILUS_MAX_DMA_ADDRESS (IDENT_ADDR+0x01000000UL) + +/* The maximum address for ISA DMA transfer on SABLE, and some ALCORs, + due to an hardware SIO chip limitation, is 2GB. +*/ +#define ALPHA_SABLE_MAX_DMA_ADDRESS (IDENT_ADDR+0x80000000UL) +#define ALPHA_ALCOR_MAX_DMA_ADDRESS (IDENT_ADDR+0x80000000UL) + +/* + Maximum address for all the others is the complete 32-bit bus + address space. */ -#define ALPHA_XL_MAX_DMA_ADDRESS (IDENT_ADDR+0x3000000UL) -#define ALPHA_RUFFIAN_MAX_DMA_ADDRESS (IDENT_ADDR+0x1000000UL) -#define ALPHA_NAUTILUS_MAX_DMA_ADDRESS (IDENT_ADDR+0x1000000UL) -#define ALPHA_MAX_DMA_ADDRESS (~0UL) +#define ALPHA_MAX_DMA_ADDRESS (IDENT_ADDR+0x100000000UL) #ifdef CONFIG_ALPHA_GENERIC # define MAX_DMA_ADDRESS (alpha_mv.max_dma_address) #else -# ifdef CONFIG_ALPHA_XL +# if defined(CONFIG_ALPHA_XL) # define MAX_DMA_ADDRESS ALPHA_XL_MAX_DMA_ADDRESS # elif defined(CONFIG_ALPHA_RUFFIAN) # define MAX_DMA_ADDRESS ALPHA_RUFFIAN_MAX_DMA_ADDRESS # elif defined(CONFIG_ALPHA_NAUTILUS) # define MAX_DMA_ADDRESS ALPHA_NAUTILUS_MAX_DMA_ADDRESS +# elif defined(CONFIG_ALPHA_SABLE) +# define MAX_DMA_ADDRESS ALPHA_SABLE_MAX_DMA_ADDRESS +# elif defined(CONFIG_ALPHA_ALCOR) +# define MAX_DMA_ADDRESS ALPHA_ALCOR_MAX_DMA_ADDRESS # else # define MAX_DMA_ADDRESS ALPHA_MAX_DMA_ADDRESS # endif diff --git a/include/asm-alpha/floppy.h b/include/asm-alpha/floppy.h index 58d053db1a7f..88049a927ddd 100644 --- a/include/asm-alpha/floppy.h +++ b/include/asm-alpha/floppy.h @@ -97,25 +97,22 @@ static int FDC2 = -1; /* * Most Alphas have no problems with floppy DMA crossing 64k borders, - * except for XL and RUFFIAN. They are also the only one with DMA - * limits, so we use that to test in the generic kernel. + * except for certain ones, like XL and RUFFIAN. + * + * However, the test is simple and fast, and this *is* floppy, after all, + * so we do it for all platforms, just to make sure. + * + * This is advantageous in other circumstances as well, as in moving + * about the PCI DMA windows and forcing the floppy to start doing + * scatter-gather when it never had before, and there *is* a problem + * on that platform... ;-} */ -#define __CROSS_64KB(a,s) \ +#define CROSS_64KB(a,s) \ ({ unsigned long __s64 = (unsigned long)(a); \ unsigned long __e64 = __s64 + (unsigned long)(s) - 1; \ (__s64 ^ __e64) & ~0xfffful; }) -#ifdef CONFIG_ALPHA_GENERIC -# define CROSS_64KB(a,s) (__CROSS_64KB(a,s) && ~alpha_mv.max_dma_address) -#else -# if defined(CONFIG_ALPHA_XL) || defined(CONFIG_ALPHA_RUFFIAN) || defined(CONFIG_ALPHA_NAUTILUS) -# define CROSS_64KB(a,s) __CROSS_64KB(a,s) -# else -# define CROSS_64KB(a,s) (0) -# endif -#endif - #define EXTRA_FLOPPY_PARAMS #endif /* __ASM_ALPHA_FLOPPY_H */ diff --git a/include/asm-alpha/ide.h b/include/asm-alpha/ide.h index 63bb9f785498..0ca863142cf5 100644 --- a/include/asm-alpha/ide.h +++ b/include/asm-alpha/ide.h @@ -80,6 +80,17 @@ static __inline__ void ide_init_default_hwifs(void) #endif } +#define ide_request_irq(irq,hand,flg,dev,id) request_irq((irq),(hand),(flg),(dev),(id)) +#define ide_free_irq(irq,dev_id) free_irq((irq), (dev_id)) +#define ide_check_region(from,extent) check_region((from), (extent)) +#define ide_request_region(from,extent,name) request_region((from), (extent), (name)) +#define ide_release_region(from,extent) release_region((from), (extent)) + +#define ide_ack_intr(hwif) (1) +#define ide_fix_driveid(id) do {} while (0) +#define ide_release_lock(lock) do {} while (0) +#define ide_get_lock(lock, hdlr, data) do {} while (0) + #endif /* __KERNEL__ */ #endif /* __ASMalpha_IDE_H */ diff --git a/include/asm-alpha/kmap_types.h b/include/asm-alpha/kmap_types.h new file mode 100644 index 000000000000..3e755b973e65 --- /dev/null +++ b/include/asm-alpha/kmap_types.h @@ -0,0 +1,31 @@ +#ifndef _ASM_KMAP_TYPES_H +#define _ASM_KMAP_TYPES_H + +/* Dummy header just to define km_type. */ + +#include <linux/config.h> + +#if CONFIG_DEBUG_HIGHMEM +# define D(n) __KM_FENCE_##n , +#else +# define D(n) +#endif + +enum km_type { +D(0) KM_BOUNCE_READ, +D(1) KM_SKB_SUNRPC_DATA, +D(2) KM_SKB_DATA_SOFTIRQ, +D(3) KM_USER0, +D(4) KM_USER1, +D(5) KM_BIO_SRC_IRQ, +D(6) KM_BIO_DST_IRQ, +D(7) KM_PTE0, +D(8) KM_PTE1, +D(9) KM_IRQ0, +D(10) KM_IRQ1, +D(11) KM_TYPE_NR +}; + +#undef D + +#endif diff --git a/include/asm-alpha/user.h b/include/asm-alpha/user.h index c5519bf162d7..7e417fc9d491 100644 --- a/include/asm-alpha/user.h +++ b/include/asm-alpha/user.h @@ -1,6 +1,7 @@ #ifndef _ALPHA_USER_H #define _ALPHA_USER_H +#include <linux/sched.h> #include <linux/ptrace.h> #include <asm/page.h> diff --git a/include/asm-i386/highmem.h b/include/asm-i386/highmem.h index 1cba7fc45882..0316b53f868f 100644 --- a/include/asm-i386/highmem.h +++ b/include/asm-i386/highmem.h @@ -81,7 +81,7 @@ static inline void *kmap_atomic(struct page *page, enum km_type type) enum fixed_addresses idx; unsigned long vaddr; - preempt_disable(); + inc_preempt_count(); if (page < highmem_start_page) return page_address(page); @@ -104,7 +104,7 @@ static inline void kunmap_atomic(void *kvaddr, enum km_type type) enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); if (vaddr < FIXADDR_START) { // FIXME - preempt_enable(); + dec_preempt_count(); return; } @@ -119,7 +119,7 @@ static inline void kunmap_atomic(void *kvaddr, enum km_type type) __flush_tlb_one(vaddr); #endif - preempt_enable(); + dec_preempt_count(); } #endif /* __KERNEL__ */ diff --git a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h index d565c78c2d81..d26bf652d894 100644 --- a/include/asm-i386/spinlock.h +++ b/include/asm-i386/spinlock.h @@ -158,6 +158,8 @@ typedef struct { #define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0) +#define rwlock_is_locked(x) ((x)->lock != RW_LOCK_BIAS) + /* * On x86, we implement read-write locks as a 32-bit counter * with the high bit (sign) being the "contended" bit. diff --git a/include/asm-i386/tlbflush.h b/include/asm-i386/tlbflush.h index c0c0388c9387..8b2e98c1425e 100644 --- a/include/asm-i386/tlbflush.h +++ b/include/asm-i386/tlbflush.h @@ -45,11 +45,21 @@ extern unsigned long pgkern_mask; __flush_tlb(); \ } while (0) -#ifndef CONFIG_X86_INVLPG -#define __flush_tlb_one(addr) __flush_tlb() +#define cpu_has_invlpg (boot_cpu_data.x86 > 3) + +#define __flush_tlb_single(addr) \ + __asm__ __volatile__("invlpg %0": :"m" (*(char *) addr)) + +#ifdef CONFIG_X86_INVLPG +# define __flush_tlb_one(addr) __flush_tlb_single(addr) #else -#define __flush_tlb_one(addr) \ -__asm__ __volatile__("invlpg %0": :"m" (*(char *) addr)) +# define __flush_tlb_one(addr) \ + do { \ + if (cpu_has_invlpg) \ + __flush_tlb_single(addr); \ + else \ + __flush_tlb(); \ + } while (0) #endif /* diff --git a/include/asm-ppc/hardirq.h b/include/asm-ppc/hardirq.h index d56152a03ccc..547f2491000f 100644 --- a/include/asm-ppc/hardirq.h +++ b/include/asm-ppc/hardirq.h @@ -85,8 +85,10 @@ typedef struct { #define irq_enter() (preempt_count() += HARDIRQ_OFFSET) #if CONFIG_PREEMPT +# define in_atomic() (preempt_count() != kernel_locked()) # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1) #else +# define in_atomic() (preempt_count() != 0) # define IRQ_EXIT_OFFSET HARDIRQ_OFFSET #endif #define irq_exit() \ diff --git a/include/asm-ppc/highmem.h b/include/asm-ppc/highmem.h index 5a630083d014..472482ca3f36 100644 --- a/include/asm-ppc/highmem.h +++ b/include/asm-ppc/highmem.h @@ -88,6 +88,7 @@ static inline void *kmap_atomic(struct page *page, enum km_type type) unsigned int idx; unsigned long vaddr; + inc_preempt_count(); if (page < highmem_start_page) return page_address(page); @@ -109,8 +110,10 @@ static inline void kunmap_atomic(void *kvaddr, enum km_type type) unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; unsigned int idx = type + KM_TYPE_NR*smp_processor_id(); - if (vaddr < KMAP_FIX_BEGIN) // FIXME + if (vaddr < KMAP_FIX_BEGIN) { // FIXME + dec_preempt_count(); return; + } if (vaddr != KMAP_FIX_BEGIN + idx * PAGE_SIZE) BUG(); @@ -122,6 +125,7 @@ static inline void kunmap_atomic(void *kvaddr, enum km_type type) pte_clear(kmap_pte+idx); flush_tlb_page(0, vaddr); #endif + dec_preempt_count(); } #endif /* __KERNEL__ */ diff --git a/include/asm-sparc/hardirq.h b/include/asm-sparc/hardirq.h index a80212dc3a2a..f77ee7e415cf 100644 --- a/include/asm-sparc/hardirq.h +++ b/include/asm-sparc/hardirq.h @@ -113,6 +113,12 @@ do { \ #define irq_exit() br_read_unlock(BR_GLOBALIRQ_LOCK) #endif +#if CONFIG_PREEMPT +# define in_atomic() (preempt_count() != kernel_locked()) +#else +# define in_atomic() (preempt_count() != 0) +#endif + #ifndef CONFIG_SMP #define synchronize_irq() barrier() diff --git a/include/asm-sparc/highmem.h b/include/asm-sparc/highmem.h index bb2fc2331b5b..2ba438ea6111 100644 --- a/include/asm-sparc/highmem.h +++ b/include/asm-sparc/highmem.h @@ -83,6 +83,7 @@ static inline void *kmap_atomic(struct page *page, enum km_type type) unsigned long idx; unsigned long vaddr; + inc_preempt_count(); if (page < highmem_start_page) return page_address(page); @@ -116,8 +117,10 @@ static inline void kunmap_atomic(void *kvaddr, enum km_type type) unsigned long vaddr = (unsigned long) kvaddr; unsigned long idx = type + KM_TYPE_NR*smp_processor_id(); - if (vaddr < FIX_KMAP_BEGIN) // FIXME + if (vaddr < FIX_KMAP_BEGIN) { // FIXME + dec_preempt_count(); return; + } if (vaddr != FIX_KMAP_BEGIN + idx * PAGE_SIZE) BUG(); @@ -142,6 +145,7 @@ static inline void kunmap_atomic(void *kvaddr, enum km_type type) flush_tlb_all(); #endif #endif + dec_preempt_count(); } #endif /* __KERNEL__ */ diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 9f1ac6d07fe8..a11b6181c76f 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -281,10 +281,7 @@ struct sec_size { extern struct sec_size * blk_sec[MAX_BLKDEV]; extern struct blk_dev_struct blk_dev[MAX_BLKDEV]; -extern void grok_partitions(kdev_t dev, long size); -extern int wipe_partitions(kdev_t dev); extern void register_disk(struct gendisk *dev, kdev_t first, unsigned minors, struct block_device_operations *ops, long size); -extern void check_partition(struct gendisk *disk, struct block_device *bdev); extern void generic_make_request(struct bio *bio); extern inline request_queue_t *bdev_get_queue(struct block_device *bdev); extern void blk_put_request(struct request *); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index fd9f5a8d7c06..ecd747fbe569 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -62,11 +62,12 @@ struct hd_struct { unsigned long start_sect; unsigned long nr_sects; devfs_handle_t de; /* primary (master) devfs entry */ - int number; /* stupid old code wastes space */ struct device hd_driverfs_dev; /* support driverfs hiearchy */ }; #define GENHD_FL_REMOVABLE 1 +#define GENHD_FL_DRIVERFS 2 +#define GENHD_FL_DEVFS 4 struct gendisk { int major; /* major number of driver */ @@ -76,24 +77,35 @@ struct gendisk { get real minor */ struct hd_struct *part; /* [indexed by minor] */ - int nr_real; /* number of real devices */ - struct gendisk *next; struct block_device_operations *fops; - - devfs_handle_t *de_arr; /* one per physical disc */ - struct device **driverfs_dev_arr;/* support driverfs hierarchy */ - char *flags; /* one per physical disc */ + sector_t capacity; + + int flags; + int number; /* devfs crap */ + devfs_handle_t de; /* more of the same */ + devfs_handle_t disk_de; /* piled higher and deeper */ + struct device *driverfs_dev; + struct device disk_dev; }; /* drivers/block/genhd.c */ extern void add_gendisk(struct gendisk *gp); extern void del_gendisk(struct gendisk *gp); +extern void unlink_gendisk(struct gendisk *gp); extern struct gendisk *get_gendisk(kdev_t dev); static inline unsigned long get_start_sect(struct block_device *bdev) { return bdev->bd_offset; } +static inline sector_t get_capacity(struct gendisk *disk) +{ + return disk->capacity; +} +static inline void set_capacity(struct gendisk *disk, sector_t size) +{ + disk->capacity = size; +} #endif /* __KERNEL__ */ @@ -242,11 +254,10 @@ struct unixware_disklabel { #ifdef __KERNEL__ -char *disk_name (struct gendisk *hd, int minor, char *buf); +char *disk_name (struct gendisk *hd, int part, char *buf); -extern void devfs_register_partitions (struct gendisk *dev, int minor, - int unregister); -extern void driverfs_remove_partitions (struct gendisk *hd, int minor); +extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); +extern void update_partition(struct gendisk *disk, int part); static inline unsigned int disk_index (kdev_t dev) { diff --git a/include/linux/highmem.h b/include/linux/highmem.h index b389a75be5d7..370177037315 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -24,8 +24,8 @@ static inline void *kmap(struct page *page) { return page_address(page); } #define kunmap(page) do { (void) (page); } while (0) -#define kmap_atomic(page,idx) kmap(page) -#define kunmap_atomic(page,idx) kunmap(page) +#define kmap_atomic(page, idx) page_address(page) +#define kunmap_atomic(addr, idx) do { } while (0) #endif /* CONFIG_HIGHMEM */ diff --git a/include/linux/ide.h b/include/linux/ide.h index 98a2db1db397..1843237adf4a 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -506,7 +506,6 @@ typedef struct ide_drive_s { unsigned int drive_data; /* for use by tuneproc/selectproc as needed */ struct hwif_s *hwif; /* actually (ide_hwif_t *) */ struct hd_driveid *id; /* drive model identification info */ - struct hd_struct *part; /* drive partition table */ char name[4]; /* drive name, such as "hda" */ struct ide_driver_s *driver; /* (ide_driver_t *) */ void *driver_data; /* extra driver data */ @@ -528,6 +527,7 @@ typedef struct ide_drive_s { unsigned int failures; /* current failure count */ unsigned int max_failures; /* maximum allowed failure count */ struct list_head list; + struct gendisk *disk; } ide_drive_t; /* @@ -714,7 +714,6 @@ typedef struct hwif_s { */ hw_regs_t hw; /* Hardware info */ ide_drive_t drives[MAX_DRIVES]; /* drive info */ - struct gendisk *gd[MAX_DRIVES];/* gendisk structure */ int addressing; /* hosts addressing */ void (*tuneproc)(ide_drive_t *, byte); /* routine to tune PIO mode for drives */ int (*speedproc)(ide_drive_t *, byte); /* routine to retune DMA modes for drives */ diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 80a57914bccc..bdf03241a009 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -29,10 +29,11 @@ .mmlist = LIST_HEAD_INIT(name.mmlist), \ } -#define INIT_SIGNALS { \ +#define INIT_SIGNALS(sig) { \ .count = ATOMIC_INIT(1), \ .action = { {{0,}}, }, \ - .siglock = SPIN_LOCK_UNLOCKED \ + .siglock = SPIN_LOCK_UNLOCKED, \ + .shared_pending = { NULL, &sig.shared_pending.head, {{0}}}, \ } /* diff --git a/include/linux/pci.h b/include/linux/pci.h index 3c76341f02bf..b82ec8e41174 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -386,6 +386,9 @@ struct pci_dev { int ro; /* ISAPnP: read only */ unsigned short regs; /* ISAPnP: supported registers */ + /* These fields are used by common fixups */ + unsigned short transparent:1; /* Transparent PCI bridge */ + int (*prepare)(struct pci_dev *dev); /* ISAPnP hooks */ int (*activate)(struct pci_dev *dev); int (*deactivate)(struct pci_dev *dev); @@ -406,6 +409,10 @@ struct pci_dev { #define PCI_ROM_RESOURCE 6 #define PCI_BRIDGE_RESOURCES 7 #define PCI_NUM_RESOURCES 11 + +#ifndef PCI_BUS_NUM_RESOURCES +#define PCI_BUS_NUM_RESOURCES 4 +#endif #define PCI_REGION_FLAG_MASK 0x0fU /* These bits of resource flags tell us the PCI region flags */ @@ -415,7 +422,8 @@ struct pci_bus { struct list_head children; /* list of child buses */ struct list_head devices; /* list of devices on this bus */ struct pci_dev *self; /* bridge device as seen by parent */ - struct resource *resource[4]; /* address space routed to this bus */ + struct resource *resource[PCI_BUS_NUM_RESOURCES]; + /* address space routed to this bus */ struct pci_ops *ops; /* configuration access functions */ void *sysdata; /* hook for sys-specific extension */ diff --git a/include/linux/preempt.h b/include/linux/preempt.h index b4ff1a7c881c..1b227b3c8ccb 100644 --- a/include/linux/preempt.h +++ b/include/linux/preempt.h @@ -48,9 +48,6 @@ do { \ preempt_check_resched(); \ } while (0) -#define inc_preempt_count_non_preempt() do { } while (0) -#define dec_preempt_count_non_preempt() do { } while (0) - #else #define preempt_disable() do { } while (0) @@ -58,13 +55,6 @@ do { \ #define preempt_enable() do { } while (0) #define preempt_check_resched() do { } while (0) -/* - * Sometimes we want to increment the preempt count, but we know that it's - * already incremented if the kernel is compiled for preemptibility. - */ -#define inc_preempt_count_non_preempt() inc_preempt_count() -#define dec_preempt_count_non_preempt() dec_preempt_count() - #endif #endif /* __LINUX_PREEMPT_H */ diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h index a9cca6e4da8f..f95cdf658a39 100644 --- a/include/linux/raid/md.h +++ b/include/linux/raid/md.h @@ -61,7 +61,6 @@ #define MD_PATCHLEVEL_VERSION 0 extern int md_size[MAX_MD_DEVS]; -extern struct hd_struct md_hd_struct[MAX_MD_DEVS]; extern char * partition_name (kdev_t dev); extern inline char * bdev_partition_name (struct block_device *bdev) diff --git a/include/linux/sched.h b/include/linux/sched.h index 896b7f59941c..bd7073fdefaf 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -211,6 +211,11 @@ struct signal_struct { atomic_t count; struct k_sigaction action[_NSIG]; spinlock_t siglock; + + /* current thread group signal load-balancing target: */ + task_t *curr_target; + + struct sigpending shared_pending; }; /* @@ -356,7 +361,7 @@ struct task_struct { spinlock_t sigmask_lock; /* Protects signal and blocked */ struct signal_struct *sig; - sigset_t blocked; + sigset_t blocked, real_blocked, shared_unblocked; struct sigpending pending; unsigned long sas_ss_sp; @@ -431,6 +436,7 @@ extern void set_cpus_allowed(task_t *p, unsigned long new_mask); extern void set_user_nice(task_t *p, long nice); extern int task_prio(task_t *p); extern int task_nice(task_t *p); +extern int task_curr(task_t *p); extern int idle_cpu(int cpu); void yield(void); @@ -535,7 +541,7 @@ extern void proc_caches_init(void); extern void flush_signals(struct task_struct *); extern void flush_signal_handlers(struct task_struct *); extern void sig_exit(int, int, struct siginfo *); -extern int dequeue_signal(sigset_t *, siginfo_t *); +extern int dequeue_signal(struct sigpending *pending, sigset_t *mask, siginfo_t *info); extern void block_all_signals(int (*notifier)(void *priv), void *priv, sigset_t *mask); extern void unblock_all_signals(void); @@ -654,6 +660,7 @@ extern void exit_thread(void); extern void exit_mm(struct task_struct *); extern void exit_files(struct task_struct *); extern void exit_sighand(struct task_struct *); +extern void remove_thread_group(struct task_struct *tsk, struct signal_struct *sig); extern void reparent_to_init(void); extern void daemonize(void); @@ -786,8 +793,29 @@ static inline struct task_struct *younger_sibling(struct task_struct *p) #define for_each_thread(task) \ for (task = next_thread(current) ; task != current ; task = next_thread(task)) -#define next_thread(p) \ - list_entry((p)->thread_group.next, struct task_struct, thread_group) +static inline task_t *next_thread(task_t *p) +{ + if (!p->sig) + BUG(); +#if CONFIG_SMP + if (!spin_is_locked(&p->sig->siglock) && + !rwlock_is_locked(&tasklist_lock)) + BUG(); +#endif + return list_entry((p)->thread_group.next, task_t, thread_group); +} + +static inline task_t *prev_thread(task_t *p) +{ + if (!p->sig) + BUG(); +#if CONFIG_SMP + if (!spin_is_locked(&p->sig->siglock) && + !rwlock_is_locked(&tasklist_lock)) + BUG(); +#endif + return list_entry((p)->thread_group.prev, task_t, thread_group); +} #define thread_group_leader(p) (p->pid == p->tgid) @@ -903,21 +931,8 @@ static inline void cond_resched(void) This is required every time the blocked sigset_t changes. Athread cathreaders should have t->sigmask_lock. */ -static inline void recalc_sigpending_tsk(struct task_struct *t) -{ - if (has_pending_signals(&t->pending.signal, &t->blocked)) - set_tsk_thread_flag(t, TIF_SIGPENDING); - else - clear_tsk_thread_flag(t, TIF_SIGPENDING); -} - -static inline void recalc_sigpending(void) -{ - if (has_pending_signals(¤t->pending.signal, ¤t->blocked)) - set_thread_flag(TIF_SIGPENDING); - else - clear_thread_flag(TIF_SIGPENDING); -} +extern FASTCALL(void recalc_sigpending_tsk(struct task_struct *t)); +extern void recalc_sigpending(void); /* * Wrappers for p->thread_info->cpu access. No-op on UP. diff --git a/init/do_mounts.c b/init/do_mounts.c index 8f3246e92e22..f15d8bb2736a 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -28,6 +28,7 @@ extern asmlinkage long sys_mount(char *dev_name, char *dir_name, char *type, unsigned long flags, void *data); extern asmlinkage long sys_mkdir(const char *name, int mode); extern asmlinkage long sys_chdir(const char *name); +extern asmlinkage long sys_fchdir(int fd); extern asmlinkage long sys_chroot(const char *name); extern asmlinkage long sys_unlink(const char *name); extern asmlinkage long sys_symlink(const char *old, const char *new); @@ -730,17 +731,13 @@ static void __init mount_root(void) } #ifdef CONFIG_BLK_DEV_INITRD +static int old_fd, root_fd; static int do_linuxrc(void * shell) { static char *argv[] = { "linuxrc", NULL, }; extern char * envp_init[]; - sys_chdir("/root"); - sys_mount(".", "/", NULL, MS_MOVE, NULL); - sys_chroot("."); - - mount_devfs_fs (); - + close(old_fd);close(root_fd); close(0);close(1);close(2); setsid(); (void) open("/dev/console",O_RDWR,0); @@ -758,9 +755,16 @@ static void __init handle_initrd(void) int i, pid; create_dev("/dev/root.old", Root_RAM0, NULL); + /* mount initrd on rootfs' /root */ mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY); sys_mkdir("/old", 0700); - sys_chdir("/old"); + root_fd = open("/", 0, 0); + old_fd = open("/old", 0, 0); + /* move initrd over / and chdir/chroot in initrd root */ + sys_chdir("/root"); + sys_mount(".", "/", NULL, MS_MOVE, NULL); + sys_chroot("."); + mount_devfs_fs (); pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); if (pid > 0) { @@ -768,7 +772,14 @@ static void __init handle_initrd(void) yield(); } - sys_mount("..", ".", NULL, MS_MOVE, NULL); + /* move initrd to rootfs' /old */ + sys_fchdir(old_fd); + sys_mount("/", ".", NULL, MS_MOVE, NULL); + /* switch root and cwd back to / of rootfs */ + sys_fchdir(root_fd); + sys_chroot("."); + close(old_fd); + close(root_fd); sys_umount("/old/dev", 0); if (real_root_dev == Root_RAM0) { diff --git a/kernel/exit.c b/kernel/exit.c index fb08ef1cb838..33078e550697 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -36,7 +36,6 @@ static inline void __unhash_process(struct task_struct *p) nr_threads--; unhash_pid(p); REMOVE_LINKS(p); - list_del(&p->thread_group); p->pid = 0; proc_dentry = p->proc_dentry; if (unlikely(proc_dentry != NULL)) { @@ -66,9 +65,14 @@ static void release_task(struct task_struct * p) atomic_dec(&p->user->processes); security_ops->task_free_security(p); free_uid(p->user); - BUG_ON(p->ptrace || !list_empty(&p->ptrace_list) || - !list_empty(&p->ptrace_children)); + if (unlikely(p->ptrace)) { + write_lock_irq(&tasklist_lock); + __ptrace_unlink(p); + write_unlock_irq(&tasklist_lock); + } + BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children)); unhash_process(p); + exit_sighand(p); release_thread(p); if (p != current) { @@ -240,7 +244,8 @@ void daemonize(void) static void reparent_thread(task_t *p, task_t *reaper, task_t *child_reaper) { /* We dont want people slaying init */ - p->exit_signal = SIGCHLD; + if (p->exit_signal != -1) + p->exit_signal = SIGCHLD; p->self_exec_id++; /* Make sure we're not reparenting to ourselves */ @@ -408,18 +413,15 @@ void exit_mm(struct task_struct *tsk) */ static inline void forget_original_parent(struct task_struct * father) { - struct task_struct *p, *reaper; + struct task_struct *p, *reaper = father; struct list_head *_p; - read_lock(&tasklist_lock); + write_lock_irq(&tasklist_lock); - /* Next in our thread group, if they're not already exiting */ - reaper = father; - do { - reaper = next_thread(reaper); - if (!(reaper->flags & PF_EXITING)) - break; - } while (reaper != father); + if (father->exit_signal != -1) + reaper = prev_thread(reaper); + else + reaper = child_reaper; if (reaper == father) reaper = child_reaper; @@ -428,7 +430,7 @@ static inline void forget_original_parent(struct task_struct * father) * There are only two places where our children can be: * * - in our child list - * - in the global ptrace list + * - in our ptraced child list * * Search them and reparent children. */ @@ -440,17 +442,29 @@ static inline void forget_original_parent(struct task_struct * father) p = list_entry(_p,struct task_struct,ptrace_list); reparent_thread(p, reaper, child_reaper); } - read_unlock(&tasklist_lock); + write_unlock_irq(&tasklist_lock); } -static inline void zap_thread(task_t *p, task_t *father) +static inline void zap_thread(task_t *p, task_t *father, int traced) { - ptrace_unlink(p); - list_del_init(&p->sibling); - p->ptrace = 0; + /* If someone else is tracing this thread, preserve the ptrace links. */ + if (unlikely(traced)) { + task_t *trace_task = p->parent; + int ptrace_flag = p->ptrace; + BUG_ON (ptrace_flag == 0); + + __ptrace_unlink(p); + p->ptrace = ptrace_flag; + __ptrace_link(p, trace_task); + } else { + /* Otherwise, if we were tracing this thread, untrace it. */ + ptrace_unlink (p); + + list_del_init(&p->sibling); + p->parent = p->real_parent; + list_add_tail(&p->sibling, &p->parent->children); + } - p->parent = p->real_parent; - list_add_tail(&p->sibling, &p->parent->children); if (p->state == TASK_ZOMBIE && p->exit_signal != -1) do_notify_parent(p, p->exit_signal); /* @@ -518,7 +532,7 @@ static void exit_notify(void) * */ - if(current->exit_signal != SIGCHLD && + if (current->exit_signal != SIGCHLD && current->exit_signal != -1 && ( current->parent_exec_id != t->self_exec_id || current->self_exec_id != current->parent_exec_id) && !capable(CAP_KILL)) @@ -541,11 +555,11 @@ static void exit_notify(void) zap_again: list_for_each_safe(_p, _n, ¤t->children) - zap_thread(list_entry(_p,struct task_struct,sibling), current); + zap_thread(list_entry(_p,struct task_struct,sibling), current, 0); list_for_each_safe(_p, _n, ¤t->ptrace_children) - zap_thread(list_entry(_p,struct task_struct,ptrace_list), current); + zap_thread(list_entry(_p,struct task_struct,ptrace_list), current, 1); /* - * reparent_thread might drop the tasklist lock, thus we could + * zap_thread might drop the tasklist lock, thus we could * have new children queued back from the ptrace list into the * child list: */ @@ -588,7 +602,6 @@ fake_volatile: __exit_files(tsk); __exit_fs(tsk); exit_namespace(tsk); - exit_sighand(tsk); exit_thread(); if (current->leader) @@ -634,6 +647,41 @@ asmlinkage long sys_exit(int error_code) do_exit((error_code&0xff)<<8); } +static inline int eligible_child(pid_t pid, int options, task_t *p) +{ + if (pid>0) { + if (p->pid != pid) + return 0; + } else if (!pid) { + if (p->pgrp != current->pgrp) + return 0; + } else if (pid != -1) { + if (p->pgrp != -pid) + return 0; + } + + /* + * Do not consider detached threads that are + * not ptraced: + */ + if (p->exit_signal == -1 && !p->ptrace) + return 0; + + /* Wait for all children (clone and not) if __WALL is set; + * otherwise, wait for clone children *only* if __WCLONE is + * set; otherwise, wait for non-clone children *only*. (Note: + * A "clone" child here is one that reports to its parent + * using a signal other than SIGCHLD.) */ + if (((p->exit_signal != SIGCHLD) ^ ((options & __WCLONE) != 0)) + && !(options & __WALL)) + return 0; + + if (security_ops->task_wait(p)) + return 0; + + return 1; +} + asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru) { int flag, retval; @@ -654,34 +702,8 @@ repeat: struct list_head *_p; list_for_each(_p,&tsk->children) { p = list_entry(_p,struct task_struct,sibling); - if (pid>0) { - if (p->pid != pid) - continue; - } else if (!pid) { - if (p->pgrp != current->pgrp) - continue; - } else if (pid != -1) { - if (p->pgrp != -pid) - continue; - } - /* - * Do not consider detached threads that are - * not ptraced: - */ - if (p->exit_signal == -1 && !p->ptrace) - continue; - /* Wait for all children (clone and not) if __WALL is set; - * otherwise, wait for clone children *only* if __WCLONE is - * set; otherwise, wait for non-clone children *only*. (Note: - * A "clone" child here is one that reports to its parent - * using a signal other than SIGCHLD.) */ - if (((p->exit_signal != SIGCHLD) ^ ((options & __WCLONE) != 0)) - && !(options & __WALL)) + if (!eligible_child(pid, options, p)) continue; - - if (security_ops->task_wait(p)) - continue; - flag = 1; switch (p->state) { case TASK_STOPPED: @@ -716,28 +738,33 @@ repeat: retval = p->pid; if (p->real_parent != p->parent) { write_lock_irq(&tasklist_lock); - ptrace_unlink(p); + __ptrace_unlink(p); do_notify_parent(p, SIGCHLD); write_unlock_irq(&tasklist_lock); - } else { - if (p->ptrace) { - write_lock_irq(&tasklist_lock); - ptrace_unlink(p); - write_unlock_irq(&tasklist_lock); - } + } else release_task(p); - } goto end_wait4; default: continue; } } + if (!flag) { + list_for_each (_p,&tsk->ptrace_children) { + p = list_entry(_p,struct task_struct,ptrace_list); + if (!eligible_child(pid, options, p)) + continue; + flag = 1; + break; + } + } if (options & __WNOTHREAD) break; tsk = next_thread(tsk); + if (tsk->sig != current->sig) + BUG(); } while (tsk != current); read_unlock(&tasklist_lock); - if (flag || !list_empty(¤t->ptrace_children)) { + if (flag) { retval = 0; if (options & WNOHANG) goto end_wait4; diff --git a/kernel/fork.c b/kernel/fork.c index 7c9dc7841aa2..4e369b9734b6 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -630,6 +630,9 @@ static inline int copy_sighand(unsigned long clone_flags, struct task_struct * t spin_lock_init(&sig->siglock); atomic_set(&sig->count, 1); memcpy(tsk->sig->action, current->sig->action, sizeof(tsk->sig->action)); + sig->curr_target = NULL; + init_sigpending(&sig->shared_pending); + return 0; } @@ -664,6 +667,12 @@ static struct task_struct *copy_process(unsigned long clone_flags, if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) return ERR_PTR(-EINVAL); + /* + * Thread groups must share signals as well: + */ + if (clone_flags & CLONE_THREAD) + clone_flags |= CLONE_SIGHAND; + retval = security_ops->task_create(clone_flags); if (retval) goto fork_out; @@ -836,21 +845,22 @@ static struct task_struct *copy_process(unsigned long clone_flags, write_lock_irq(&tasklist_lock); /* CLONE_PARENT re-uses the old parent */ - p->real_parent = current->real_parent; - p->parent = current->parent; - if (!(clone_flags & CLONE_PARENT)) { + if (clone_flags & CLONE_PARENT) + p->real_parent = current->real_parent; + else p->real_parent = current; - if (!(p->ptrace & PT_PTRACED)) - p->parent = current; - } + p->parent = p->real_parent; if (clone_flags & CLONE_THREAD) { + spin_lock(¤t->sig->siglock); p->tgid = current->tgid; list_add(&p->thread_group, ¤t->thread_group); + spin_unlock(¤t->sig->siglock); } SET_LINKS(p); - ptrace_link(p, p->parent); + if (p->ptrace & PT_PTRACED) + __ptrace_link(p, current->parent); hash_pid(p); nr_threads++; write_unlock_irq(&tasklist_lock); diff --git a/kernel/ksyms.c b/kernel/ksyms.c index f3e982d4aa52..3b03394fe14d 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -335,17 +335,13 @@ EXPORT_SYMBOL(blk_dev); EXPORT_SYMBOL(bdev_read_only); EXPORT_SYMBOL(set_device_ro); EXPORT_SYMBOL(bmap); -EXPORT_SYMBOL(devfs_register_partitions); -EXPORT_SYMBOL(driverfs_remove_partitions); EXPORT_SYMBOL(blkdev_open); EXPORT_SYMBOL(blkdev_get); EXPORT_SYMBOL(blkdev_put); EXPORT_SYMBOL(ioctl_by_bdev); -EXPORT_SYMBOL(grok_partitions); EXPORT_SYMBOL(register_disk); EXPORT_SYMBOL(read_dev_sector); EXPORT_SYMBOL(init_buffer); -EXPORT_SYMBOL(wipe_partitions); EXPORT_SYMBOL_GPL(generic_file_direct_IO); /* tty routines */ diff --git a/kernel/sched.c b/kernel/sched.c index e1e08ecd37b4..625acc09ec17 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1336,6 +1336,15 @@ int task_nice(task_t *p) } /** + * task_curr - is this task currently executing on a CPU? + * @p: the task in question. + */ +int task_curr(task_t *p) +{ + return cpu_curr(task_cpu(p)) == p; +} + +/** * idle_cpu - is a given cpu idle currently? * @cpu: the processor in question. */ diff --git a/kernel/signal.c b/kernel/signal.c index 8de729b6ee20..5ca0ca83eb2f 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -6,6 +6,8 @@ * 1997-11-02 Modified for POSIX.1b signals by Richard Henderson */ +#define __KERNEL_SYSCALLS__ + #include <linux/config.h> #include <linux/slab.h> #include <linux/module.h> @@ -16,7 +18,7 @@ #include <linux/fs.h> #include <linux/tty.h> #include <linux/binfmts.h> - +#include <asm/param.h> #include <asm/uaccess.h> #include <asm/siginfo.h> @@ -24,40 +26,146 @@ * SLAB caches for signal bits. */ -#define DEBUG_SIG 0 - -#if DEBUG_SIG -#define SIG_SLAB_DEBUG (SLAB_RED_ZONE /* | SLAB_POISON */) -#else -#define SIG_SLAB_DEBUG 0 -#endif - static kmem_cache_t *sigqueue_cachep; atomic_t nr_queued_signals; int max_queued_signals = 1024; +/********************************************************* + + POSIX thread group signal behavior: + +---------------------------------------------------------- +| | userspace | kernel | +---------------------------------------------------------- +| SIGHUP | load-balance | kill-all | +| SIGINT | load-balance | kill-all | +| SIGQUIT | load-balance | kill-all+core | +| SIGILL | specific | kill-all+core | +| SIGTRAP | specific | kill-all+core | +| SIGABRT/SIGIOT | specific | kill-all+core | +| SIGBUS | specific | kill-all+core | +| SIGFPE | specific | kill-all+core | +| SIGKILL | n/a | kill-all | +| SIGUSR1 | load-balance | kill-all | +| SIGSEGV | specific | kill-all+core | +| SIGUSR2 | load-balance | kill-all | +| SIGPIPE | specific | kill-all | +| SIGALRM | load-balance | kill-all | +| SIGTERM | load-balance | kill-all | +| SIGCHLD | load-balance | ignore | +| SIGCONT | specific | continue-all | +| SIGSTOP | n/a | stop-all | +| SIGTSTP | load-balance | stop-all | +| SIGTTIN | load-balance | stop-all | +| SIGTTOU | load-balance | stop-all | +| SIGURG | load-balance | ignore | +| SIGXCPU | specific | kill-all+core | +| SIGXFSZ | specific | kill-all+core | +| SIGVTALRM | load-balance | kill-all | +| SIGPROF | specific | kill-all | +| SIGPOLL/SIGIO | load-balance | kill-all | +| SIGSYS/SIGUNUSED | specific | kill-all+core | +| SIGSTKFLT | specific | kill-all | +| SIGWINCH | load-balance | ignore | +| SIGPWR | load-balance | kill-all | +| SIGRTMIN-SIGRTMAX | load-balance | kill-all | +---------------------------------------------------------- +*/ + +#define M(sig) (1UL << (sig)) + +#define SIG_USER_SPECIFIC_MASK (\ + M(SIGILL) | M(SIGTRAP) | M(SIGABRT) | M(SIGBUS) | \ + M(SIGFPE) | M(SIGSEGV) | M(SIGPIPE) | M(SIGXFSZ) | \ + M(SIGPROF) | M(SIGSYS) | M(SIGSTKFLT) | M(SIGCONT) ) + +#define SIG_USER_LOAD_BALANCE_MASK (\ + M(SIGHUP) | M(SIGINT) | M(SIGQUIT) | M(SIGUSR1) | \ + M(SIGUSR2) | M(SIGALRM) | M(SIGTERM) | M(SIGCHLD) | \ + M(SIGURG) | M(SIGVTALRM) | M(SIGPOLL) | M(SIGWINCH) | \ + M(SIGPWR) | M(SIGTSTP) | M(SIGTTIN) | M(SIGTTOU) ) + +#define SIG_KERNEL_SPECIFIC_MASK (\ + M(SIGCHLD) | M(SIGURG) | M(SIGWINCH) ) + +#define SIG_KERNEL_BROADCAST_MASK (\ + M(SIGHUP) | M(SIGINT) | M(SIGQUIT) | M(SIGILL) | \ + M(SIGTRAP) | M(SIGABRT) | M(SIGBUS) | M(SIGFPE) | \ + M(SIGKILL) | M(SIGUSR1) | M(SIGSEGV) | M(SIGUSR2) | \ + M(SIGPIPE) | M(SIGALRM) | M(SIGTERM) | M(SIGXCPU) | \ + M(SIGXFSZ) | M(SIGVTALRM) | M(SIGPROF) | M(SIGPOLL) | \ + M(SIGSYS) | M(SIGSTKFLT) | M(SIGPWR) | M(SIGCONT) | \ + M(SIGSTOP) | M(SIGTSTP) | M(SIGTTIN) | M(SIGTTOU) ) + +#define SIG_KERNEL_ONLY_MASK (\ + M(SIGKILL) | M(SIGSTOP) ) + +#define SIG_KERNEL_COREDUMP_MASK (\ + M(SIGQUIT) | M(SIGILL) | M(SIGTRAP) | M(SIGABRT) | \ + M(SIGFPE) | M(SIGSEGV) | M(SIGBUS) | M(SIGSYS) | \ + M(SIGXCPU) | M(SIGXFSZ) ) + +#define T(sig, mask) \ + ((1UL << (sig)) & mask) + +#define sig_user_specific(sig) T(sig, SIG_USER_SPECIFIC_MASK) +#define sig_user_load_balance(sig) \ + (T(sig, SIG_USER_LOAD_BALANCE_MASK) || ((sig) >= SIGRTMIN)) +#define sig_kernel_specific(sig) T(sig, SIG_KERNEL_SPECIFIC_MASK) +#define sig_kernel_broadcast(sig) \ + (T(sig, SIG_KERNEL_BROADCAST_MASK) || ((sig) >= SIGRTMIN)) +#define sig_kernel_only(sig) T(sig, SIG_KERNEL_ONLY_MASK) +#define sig_kernel_coredump(sig) T(sig, SIG_KERNEL_COREDUMP_MASK) + +#define sig_user_defined(t, sig) \ + (((t)->sig->action[(sig)-1].sa.sa_handler != SIG_DFL) && \ + ((t)->sig->action[(sig)-1].sa.sa_handler != SIG_IGN)) + +#define sig_ignored(t, sig) \ + (((sig) != SIGCHLD) && \ + ((t)->sig->action[(sig)-1].sa.sa_handler == SIG_IGN)) + void __init signals_init(void) { sigqueue_cachep = kmem_cache_create("sigqueue", sizeof(struct sigqueue), __alignof__(struct sigqueue), - SIG_SLAB_DEBUG, NULL, NULL); + 0, NULL, NULL); if (!sigqueue_cachep) panic("signals_init(): cannot create sigqueue SLAB cache"); } +#define PENDING(p,b) has_pending_signals(&(p)->signal, (b)) + +void recalc_sigpending_tsk(struct task_struct *t) +{ + if (PENDING(&t->pending, &t->blocked) || + PENDING(&t->sig->shared_pending, &t->blocked)) + set_tsk_thread_flag(t, TIF_SIGPENDING); + else + clear_tsk_thread_flag(t, TIF_SIGPENDING); +} + +void recalc_sigpending(void) +{ + if (PENDING(¤t->pending, ¤t->blocked) || + PENDING(¤t->sig->shared_pending, ¤t->blocked)) + set_thread_flag(TIF_SIGPENDING); + else + clear_thread_flag(TIF_SIGPENDING); +} /* Given the mask, find the first available signal that should be serviced. */ static int -next_signal(struct task_struct *tsk, sigset_t *mask) +next_signal(struct sigpending *pending, sigset_t *mask) { unsigned long i, *s, *m, x; int sig = 0; - s = tsk->pending.signal.sig; + s = pending->signal.sig; m = mask->sig; switch (_NSIG_WORDS) { default: @@ -113,15 +221,36 @@ flush_signals(struct task_struct *t) flush_sigqueue(&t->pending); } +void remove_thread_group(struct task_struct *tsk, struct signal_struct *sig) +{ + write_lock_irq(&tasklist_lock); + spin_lock(&tsk->sig->siglock); + + if (tsk == sig->curr_target) + sig->curr_target = next_thread(tsk); + list_del_init(&tsk->thread_group); + + spin_unlock(&tsk->sig->siglock); + write_unlock_irq(&tasklist_lock); +} + void exit_sighand(struct task_struct *tsk) { struct signal_struct * sig = tsk->sig; + if (!sig) + BUG(); + if (!atomic_read(&sig->count)) + BUG(); + remove_thread_group(tsk, sig); + spin_lock_irq(&tsk->sigmask_lock); if (sig) { tsk->sig = NULL; - if (atomic_dec_and_test(&sig->count)) + if (atomic_dec_and_test(&sig->count)) { + flush_sigqueue(&sig->shared_pending); kmem_cache_free(sigact_cachep, sig); + } } clear_tsk_thread_flag(tsk,TIF_SIGPENDING); flush_sigqueue(&tsk->pending); @@ -153,24 +282,10 @@ flush_signal_handlers(struct task_struct *t) void sig_exit(int sig, int exit_code, struct siginfo *info) { - struct task_struct *t; - sigaddset(¤t->pending.signal, sig); recalc_sigpending(); current->flags |= PF_SIGNALED; - /* Propagate the signal to all the tasks in - * our thread group - */ - if (info && (unsigned long)info != 1 - && info->si_code != SI_TKILL) { - read_lock(&tasklist_lock); - for_each_thread(t) { - force_sig_info(sig, info, t); - } - read_unlock(&tasklist_lock); - } - do_exit(exit_code); /* NOTREACHED */ } @@ -209,7 +324,7 @@ unblock_all_signals(void) spin_unlock_irqrestore(¤t->sigmask_lock, flags); } -static int collect_signal(int sig, struct sigpending *list, siginfo_t *info) +static inline int collect_signal(int sig, struct sigpending *list, siginfo_t *info) { if (sigismember(&list->signal, sig)) { /* Collect the siginfo appropriate to this signal. */ @@ -221,9 +336,10 @@ static int collect_signal(int sig, struct sigpending *list, siginfo_t *info) pp = &q->next; } - /* Ok, it wasn't in the queue. We must have - been out of queue space. So zero out the - info. */ + /* Ok, it wasn't in the queue. This must be + a fast-pathed signal or we must have been + out of queue space. So zero out the info. + */ sigdelset(&list->signal, sig); info->si_signo = sig; info->si_errno = 0; @@ -261,20 +377,14 @@ found_another: * Dequeue a signal and return the element to the caller, which is * expected to free it. * - * All callers must be holding current->sigmask_lock. + * All callers have to hold the siglock and the sigmask_lock. */ -int -dequeue_signal(sigset_t *mask, siginfo_t *info) +int dequeue_signal(struct sigpending *pending, sigset_t *mask, siginfo_t *info) { int sig = 0; -#if DEBUG_SIG -printk(KERN_DEBUG "SIG dequeue (%s:%d): %d ", current->comm, current->pid, - signal_pending(current)); -#endif - - sig = next_signal(current, mask); + sig = next_signal(pending, mask); if (sig) { if (current->notifier) { if (sigismember(current->notifier_mask, sig)) { @@ -285,7 +395,7 @@ printk(KERN_DEBUG "SIG dequeue (%s:%d): %d ", current->comm, current->pid, } } - if (!collect_signal(sig, ¤t->pending, info)) + if (!collect_signal(sig, pending, info)) sig = 0; /* XXX: Once POSIX.1b timers are in, if si_code == SI_TIMER, @@ -293,10 +403,6 @@ printk(KERN_DEBUG "SIG dequeue (%s:%d): %d ", current->comm, current->pid, } recalc_sigpending(); -#if DEBUG_SIG -printk(KERN_DEBUG " %d -> %d\n", signal_pending(current), sig); -#endif - return sig; } @@ -338,9 +444,10 @@ static int rm_sig_from_queue(int sig, struct task_struct *t) /* * Bad permissions for sending the signal */ -int bad_signal(int sig, struct siginfo *info, struct task_struct *t) +static inline int bad_signal(int sig, struct siginfo *info, struct task_struct *t) { - return (!info || ((unsigned long)info != 1 && SI_FROMUSER(info))) + return (!info || ((unsigned long)info != 1 && + (unsigned long)info != 2 && SI_FROMUSER(info))) && ((sig != SIGCONT) || (current->session != t->session)) && (current->euid ^ t->suid) && (current->euid ^ t->uid) && (current->uid ^ t->suid) && (current->uid ^ t->uid) @@ -436,6 +543,13 @@ static int send_signal(int sig, struct siginfo *info, struct sigpending *signals { struct sigqueue * q = NULL; + /* + * fast-pathed signals for kernel-internal things like SIGSTOP + * or SIGKILL. + */ + if ((unsigned long)info == 2) + goto out_set; + /* Real-time signals must be queued if sent by sigqueue, or some other real-time mechanism. It is implementation defined whether kill() does so. We attempt to do so, on @@ -444,9 +558,8 @@ static int send_signal(int sig, struct siginfo *info, struct sigpending *signals make sure at least one signal gets delivered and don't pass on the info struct. */ - if (atomic_read(&nr_queued_signals) < max_queued_signals) { + if (atomic_read(&nr_queued_signals) < max_queued_signals) q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC); - } if (q) { atomic_inc(&nr_queued_signals); @@ -473,14 +586,14 @@ static int send_signal(int sig, struct siginfo *info, struct sigpending *signals break; } } else if (sig >= SIGRTMIN && info && (unsigned long)info != 1 - && info->si_code != SI_USER) { + && info->si_code != SI_USER) /* * Queue overflow, abort. We may abort if the signal was rt * and sent by user using something other than kill(). */ return -EAGAIN; - } +out_set: sigaddset(&signals->signal, sig); return 0; } @@ -528,17 +641,17 @@ static int deliver_signal(int sig, struct siginfo *info, struct task_struct *t) return retval; } -int -send_sig_info(int sig, struct siginfo *info, struct task_struct *t) +static int +__send_sig_info(int sig, struct siginfo *info, struct task_struct *t, int shared) { - unsigned long flags; int ret; - -#if DEBUG_SIG -printk(KERN_DEBUG "SIG queue (%s:%d): %d ", t->comm, t->pid, sig); + if (!irqs_disabled()) + BUG(); +#if CONFIG_SMP + if (!spin_is_locked(&t->sig->siglock)) + BUG(); #endif - ret = -EINVAL; if (sig < 0 || sig > _NSIG) goto out_nolock; @@ -556,7 +669,7 @@ printk(KERN_DEBUG "SIG queue (%s:%d): %d ", t->comm, t->pid, sig); if (!sig || !t->sig) goto out_nolock; - spin_lock_irqsave(&t->sigmask_lock, flags); + spin_lock(&t->sigmask_lock); handle_stop_signal(sig, t); /* Optimize away the signal, if it's a signal that can be @@ -566,20 +679,25 @@ printk(KERN_DEBUG "SIG queue (%s:%d): %d ", t->comm, t->pid, sig); if (ignored_signal(sig, t)) goto out; - /* Support queueing exactly one non-rt signal, so that we - can get more detailed information about the cause of - the signal. */ - if (sig < SIGRTMIN && sigismember(&t->pending.signal, sig)) - goto out; +#define LEGACY_QUEUE(sigptr, sig) \ + (((sig) < SIGRTMIN) && sigismember(&(sigptr)->signal, (sig))) + + if (!shared) { + /* Support queueing exactly one non-rt signal, so that we + can get more detailed information about the cause of + the signal. */ + if (LEGACY_QUEUE(&t->pending, sig)) + goto out; - ret = deliver_signal(sig, info, t); + ret = deliver_signal(sig, info, t); + } else { + if (LEGACY_QUEUE(&t->sig->shared_pending, sig)) + goto out; + ret = send_signal(sig, info, &t->sig->shared_pending); + } out: - spin_unlock_irqrestore(&t->sigmask_lock, flags); + spin_unlock(&t->sigmask_lock); out_nolock: -#if DEBUG_SIG -printk(KERN_DEBUG " %d -> %d\n", signal_pending(t), ret); -#endif - return ret; } @@ -605,7 +723,157 @@ force_sig_info(int sig, struct siginfo *info, struct task_struct *t) recalc_sigpending_tsk(t); spin_unlock_irqrestore(&t->sigmask_lock, flags); - return send_sig_info(sig, info, t); + return send_sig_info(sig, (void *)1, t); +} + +static int +__force_sig_info(int sig, struct task_struct *t) +{ + unsigned long int flags; + + spin_lock_irqsave(&t->sigmask_lock, flags); + if (t->sig == NULL) { + spin_unlock_irqrestore(&t->sigmask_lock, flags); + return -ESRCH; + } + + if (t->sig->action[sig-1].sa.sa_handler == SIG_IGN) + t->sig->action[sig-1].sa.sa_handler = SIG_DFL; + sigdelset(&t->blocked, sig); + recalc_sigpending_tsk(t); + spin_unlock_irqrestore(&t->sigmask_lock, flags); + + return __send_sig_info(sig, (void *)2, t, 0); +} + +#define can_take_signal(p, sig) \ + (((unsigned long) p->sig->action[sig-1].sa.sa_handler > 1) && \ + !sigismember(&p->blocked, sig) && (task_curr(p) || !signal_pending(p))) + +static inline +int load_balance_thread_group(struct task_struct *p, int sig, + struct siginfo *info) +{ + struct task_struct *tmp; + int ret; + + /* + * if the specified thread is not blocking this signal + * then deliver it. + */ + if (can_take_signal(p, sig)) + return __send_sig_info(sig, info, p, 0); + + /* + * Otherwise try to find a suitable thread. + * If no such thread is found then deliver to + * the original thread. + */ + + tmp = p->sig->curr_target; + + if (!tmp || tmp->tgid != p->tgid) + /* restart balancing at this thread */ + p->sig->curr_target = p; + + else for (;;) { + if (list_empty(&p->thread_group)) + BUG(); + if (!tmp || tmp->tgid != p->tgid) + BUG(); + + /* + * Do not send signals that are ignored or blocked, + * or to not-running threads that are overworked: + */ + if (!can_take_signal(tmp, sig)) { + tmp = next_thread(tmp); + p->sig->curr_target = tmp; + if (tmp == p) + break; + continue; + } + ret = __send_sig_info(sig, info, tmp, 0); + return ret; + } + /* + * No suitable thread was found - put the signal + * into the shared-pending queue. + */ + return __send_sig_info(sig, info, p, 1); +} + +int __broadcast_thread_group(struct task_struct *p, int sig) +{ + struct task_struct *tmp; + struct list_head *entry; + int err = 0; + + /* send a signal to the head of the list */ + err = __force_sig_info(sig, p); + + /* send a signal to all members of the list */ + list_for_each(entry, &p->thread_group) { + tmp = list_entry(entry, task_t, thread_group); + err = __force_sig_info(sig, tmp); + } + return err; +} + +int +send_sig_info(int sig, struct siginfo *info, struct task_struct *p) +{ + unsigned long flags; + int ret = 0; + + if (!p) + BUG(); + if (!p->sig) + BUG(); + spin_lock_irqsave(&p->sig->siglock, flags); + + /* not a thread group - normal signal behavior */ + if (list_empty(&p->thread_group) || !sig) + goto out_send; + + if (sig_user_defined(p, sig)) { + if (sig_user_specific(sig)) + goto out_send; + if (sig_user_load_balance(sig)) { + ret = load_balance_thread_group(p, sig, info); + goto out_unlock; + } + + /* must not happen */ + BUG(); + } + /* optimize away ignored signals: */ + if (sig_ignored(p, sig)) + goto out_unlock; + + /* blocked (or ptraced) signals get posted */ + spin_lock(&p->sigmask_lock); + if ((p->ptrace & PT_PTRACED) || sigismember(&p->blocked, sig) || + sigismember(&p->real_blocked, sig)) { + spin_unlock(&p->sigmask_lock); + goto out_send; + } + spin_unlock(&p->sigmask_lock); + + if (sig_kernel_broadcast(sig) || sig_kernel_coredump(sig)) { + ret = __broadcast_thread_group(p, sig); + goto out_unlock; + } + if (sig_kernel_specific(sig)) + goto out_send; + + /* must not happen */ + BUG(); +out_send: + ret = __send_sig_info(sig, info, p, 0); +out_unlock: + spin_unlock_irqrestore(&p->sig->siglock, flags); + return ret; } /* @@ -670,15 +938,8 @@ kill_proc_info(int sig, struct siginfo *info, pid_t pid) read_lock(&tasklist_lock); p = find_task_by_pid(pid); error = -ESRCH; - if (p) { - if (!thread_group_leader(p)) { - struct task_struct *tg; - tg = find_task_by_pid(p->tgid); - if (tg) - p = tg; - } + if (p) error = send_sig_info(sig, info, p); - } read_unlock(&tasklist_lock); return error; } @@ -755,25 +1016,36 @@ kill_proc(pid_t pid, int sig, int priv) * Joy. Or not. Pthread wants us to wake up every thread * in our parent group. */ -static void wake_up_parent(struct task_struct *parent) +static inline void wake_up_parent(struct task_struct *p) { - struct task_struct *tsk = parent; + struct task_struct *parent = p->parent, *tsk = parent; + /* + * Fortunately this is not necessary for thread groups: + */ + if (p->tgid == tsk->tgid) { + wake_up_interruptible(&tsk->wait_chldexit); + return; + } + spin_lock_irq(&parent->sig->siglock); do { wake_up_interruptible(&tsk->wait_chldexit); tsk = next_thread(tsk); + if (tsk->sig != parent->sig) + BUG(); } while (tsk != parent); + spin_unlock_irq(&parent->sig->siglock); } /* * Let a parent know about a status change of a child. */ + void do_notify_parent(struct task_struct *tsk, int sig) { struct siginfo info; int why, status; - /* is the thread detached? */ if (sig == -1) BUG(); @@ -812,7 +1084,7 @@ void do_notify_parent(struct task_struct *tsk, int sig) info.si_status = status; send_sig_info(sig, &info, tsk->parent); - wake_up_parent(tsk->parent); + wake_up_parent(tsk); } @@ -837,13 +1109,24 @@ notify_parent(struct task_struct *tsk, int sig) int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs) { + sigset_t *mask = ¤t->blocked; + for (;;) { - unsigned long signr; + unsigned long signr = 0; struct k_sigaction *ka; - spin_lock_irq(¤t->sigmask_lock); - signr = dequeue_signal(¤t->blocked, info); - spin_unlock_irq(¤t->sigmask_lock); + local_irq_disable(); + if (current->sig->shared_pending.head) { + spin_lock(¤t->sig->siglock); + signr = dequeue_signal(¤t->sig->shared_pending, mask, info); + spin_unlock(¤t->sig->siglock); + } + if (!signr) { + spin_lock(¤t->sigmask_lock); + signr = dequeue_signal(¤t->pending, mask, info); + spin_unlock(¤t->sigmask_lock); + } + local_irq_enable(); if (!signr) break; @@ -1137,8 +1420,11 @@ sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo, return -EINVAL; } - spin_lock_irq(¤t->sigmask_lock); - sig = dequeue_signal(&these, &info); + spin_lock_irq(¤t->sig->siglock); + spin_lock(¤t->sigmask_lock); + sig = dequeue_signal(¤t->sig->shared_pending, &these, &info); + if (!sig) + sig = dequeue_signal(¤t->pending, &these, &info); if (!sig) { timeout = MAX_SCHEDULE_TIMEOUT; if (uts) @@ -1149,21 +1435,27 @@ sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo, /* None ready -- temporarily unblock those we're * interested while we are sleeping in so that we'll * be awakened when they arrive. */ - sigset_t oldblocked = current->blocked; + current->real_blocked = current->blocked; sigandsets(¤t->blocked, ¤t->blocked, &these); recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock(¤t->sigmask_lock); + spin_unlock_irq(¤t->sig->siglock); current->state = TASK_INTERRUPTIBLE; timeout = schedule_timeout(timeout); - spin_lock_irq(¤t->sigmask_lock); - sig = dequeue_signal(&these, &info); - current->blocked = oldblocked; + spin_lock_irq(¤t->sig->siglock); + spin_lock(¤t->sigmask_lock); + sig = dequeue_signal(¤t->sig->shared_pending, &these, &info); + if (!sig) + sig = dequeue_signal(¤t->pending, &these, &info); + current->blocked = current->real_blocked; + siginitset(¤t->real_blocked, 0); recalc_sigpending(); } } - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock(¤t->sigmask_lock); + spin_unlock_irq(¤t->sig->siglock); if (sig) { ret = sig; @@ -1195,33 +1487,35 @@ sys_kill(int pid, int sig) } /* - * Kill only one task, even if it's a CLONE_THREAD task. + * Send a signal to only one task, even if it's a CLONE_THREAD task. */ asmlinkage long sys_tkill(int pid, int sig) { - struct siginfo info; - int error; - struct task_struct *p; - - /* This is only valid for single tasks */ - if (pid <= 0) - return -EINVAL; - - info.si_signo = sig; - info.si_errno = 0; - info.si_code = SI_TKILL; - info.si_pid = current->pid; - info.si_uid = current->uid; - - read_lock(&tasklist_lock); - p = find_task_by_pid(pid); - error = -ESRCH; - if (p) { - error = send_sig_info(sig, &info, p); - } - read_unlock(&tasklist_lock); - return error; + struct siginfo info; + int error; + struct task_struct *p; + + /* This is only valid for single tasks */ + if (pid <= 0) + return -EINVAL; + + info.si_signo = sig; + info.si_errno = 0; + info.si_code = SI_TKILL; + info.si_pid = current->pid; + info.si_uid = current->uid; + + read_lock(&tasklist_lock); + p = find_task_by_pid(pid); + error = -ESRCH; + if (p) { + spin_lock_irq(&p->sig->siglock); + error = __send_sig_info(sig, &info, p, 0); + spin_unlock_irq(&p->sig->siglock); + } + read_unlock(&tasklist_lock); + return error; } asmlinkage long @@ -1247,13 +1541,12 @@ do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact) { struct k_sigaction *k; - if (sig < 1 || sig > _NSIG || - (act && (sig == SIGKILL || sig == SIGSTOP))) + if (sig < 1 || sig > _NSIG || (act && sig_kernel_only(sig))) return -EINVAL; k = ¤t->sig->action[sig-1]; - spin_lock(¤t->sig->siglock); + spin_lock_irq(¤t->sig->siglock); if (oact) *oact = *k; @@ -1292,7 +1585,7 @@ do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact) } } - spin_unlock(¤t->sig->siglock); + spin_unlock_irq(¤t->sig->siglock); return 0; } diff --git a/mm/filemap.c b/mm/filemap.c index 771676ff57a9..4360f4a8c690 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1036,7 +1036,52 @@ no_cached_page: UPDATE_ATIME(inode); } -int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size) +/* + * Fault a userspace page into pagetables. Return non-zero on a fault. + * + * FIXME: this assumes that two userspace pages are always sufficient. That's + * not true if PAGE_CACHE_SIZE > PAGE_SIZE. + */ +static inline int fault_in_pages_writeable(char *uaddr, int size) +{ + int ret; + + /* + * Writing zeroes into userspace here is OK, because we know that if + * the zero gets there, we'll be overwriting it. + */ + ret = __put_user(0, uaddr); + if (ret == 0) { + char *end = uaddr + size - 1; + + /* + * If the page was already mapped, this will get a cache miss + * for sure, so try to avoid doing it. + */ + if (((unsigned long)uaddr & PAGE_MASK) != + ((unsigned long)end & PAGE_MASK)) + ret = __put_user(0, end); + } + return ret; +} + +static inline void fault_in_pages_readable(const char *uaddr, int size) +{ + volatile char c; + int ret; + + ret = __get_user(c, (char *)uaddr); + if (ret == 0) { + const char *end = uaddr + size - 1; + + if (((unsigned long)uaddr & PAGE_MASK) != + ((unsigned long)end & PAGE_MASK)) + __get_user(c, (char *)end); + } +} + +int file_read_actor(read_descriptor_t *desc, struct page *page, + unsigned long offset, unsigned long size) { char *kaddr; unsigned long left, count = desc->count; @@ -1044,14 +1089,28 @@ int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long o if (size > count) size = count; + /* + * Faults on the destination of a read are common, so do it before + * taking the kmap. + */ + if (!fault_in_pages_writeable(desc->buf, size)) { + kaddr = kmap_atomic(page, KM_USER0); + left = __copy_to_user(desc->buf, kaddr + offset, size); + kunmap_atomic(kaddr, KM_USER0); + if (left == 0) + goto success; + } + + /* Do it the slow way */ kaddr = kmap(page); left = __copy_to_user(desc->buf, kaddr + offset, size); kunmap(page); - + if (left) { size -= left; desc->error = -EFAULT; } +success: desc->count = count - size; desc->written += size; desc->buf += size; @@ -1838,6 +1897,26 @@ inline void remove_suid(struct dentry *dentry) } } +static inline int +filemap_copy_from_user(struct page *page, unsigned long offset, + const char *buf, unsigned bytes) +{ + char *kaddr; + int left; + + kaddr = kmap_atomic(page, KM_USER0); + left = __copy_from_user(kaddr + offset, buf, bytes); + kunmap_atomic(kaddr, KM_USER0); + + if (left != 0) { + /* Do it the slow way */ + kaddr = kmap(page); + left = __copy_from_user(kaddr + offset, buf, bytes); + kunmap(page); + } + return left; +} + /* * Write to a file through the page cache. * @@ -1990,7 +2069,6 @@ ssize_t generic_file_write_nolock(struct file *file, const char *buf, unsigned long index; unsigned long offset; long page_fault; - char *kaddr; offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */ index = pos >> PAGE_CACHE_SHIFT; @@ -2004,10 +2082,7 @@ ssize_t generic_file_write_nolock(struct file *file, const char *buf, * same page as we're writing to, without it being marked * up-to-date. */ - { volatile unsigned char dummy; - __get_user(dummy, buf); - __get_user(dummy, buf+bytes-1); - } + fault_in_pages_readable(buf, bytes); page = __grab_cache_page(mapping, index, &cached_page, &lru_pvec); if (!page) { @@ -2015,22 +2090,19 @@ ssize_t generic_file_write_nolock(struct file *file, const char *buf, break; } - kaddr = kmap(page); status = a_ops->prepare_write(file, page, offset, offset+bytes); if (unlikely(status)) { /* * prepare_write() may have instantiated a few blocks * outside i_size. Trim these off again. */ - kunmap(page); unlock_page(page); page_cache_release(page); if (pos + bytes > inode->i_size) vmtruncate(inode, inode->i_size); break; } - page_fault = __copy_from_user(kaddr + offset, buf, bytes); - flush_dcache_page(page); + page_fault = filemap_copy_from_user(page, offset, buf, bytes); status = a_ops->commit_write(file, page, offset, offset+bytes); if (unlikely(page_fault)) { status = -EFAULT; @@ -2045,7 +2117,6 @@ ssize_t generic_file_write_nolock(struct file *file, const char *buf, buf += status; } } - kunmap(page); if (!PageReferenced(page)) SetPageReferenced(page); unlock_page(page); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index b3da592923f4..1dc363b27b98 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -782,10 +782,9 @@ void __init free_area_init_core(int nid, pg_data_t *pgdat, struct page **gmap, const unsigned long zone_required_alignment = 1UL << (MAX_ORDER-1); totalpages = 0; - for (i = 0; i < MAX_NR_ZONES; i++) { - unsigned long size = zones_size[i]; - totalpages += size; - } + for (i = 0; i < MAX_NR_ZONES; i++) + totalpages += zones_size[i]; + realtotalpages = totalpages; if (zholes_size) for (i = 0; i < MAX_NR_ZONES; i++) @@ -823,7 +822,7 @@ void __init free_area_init_core(int nid, pg_data_t *pgdat, struct page **gmap, if (zholes_size) realsize -= zholes_size[j]; - printk("zone(%lu): %lu pages.\n", j, size); + printk(" %s zone: %lu pages\n", zone_names[j], realsize); zone->size = size; zone->name = zone_names[j]; spin_lock_init(&zone->lock); diff --git a/mm/vmscan.c b/mm/vmscan.c index a00fe27159d9..5ed1ec3eda52 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -483,7 +483,7 @@ shrink_zone(struct zone *zone, int priority, ratio = (unsigned long)nr_pages * zone->nr_active / ((zone->nr_inactive | 1) * 2); atomic_add(ratio+1, &zone->refill_counter); - if (atomic_read(&zone->refill_counter) > SWAP_CLUSTER_MAX) { + while (atomic_read(&zone->refill_counter) > SWAP_CLUSTER_MAX) { atomic_sub(SWAP_CLUSTER_MAX, &zone->refill_counter); refill_inactive_zone(zone, SWAP_CLUSTER_MAX); } @@ -517,7 +517,7 @@ shrink_caches(struct zone *classzone, int priority, first_classzone = classzone->zone_pgdat->node_zones; zone = classzone; - while (zone >= first_classzone) { + while (zone >= first_classzone && nr_pages > 0) { if (zone->free_pages <= zone->pages_high) { nr_pages = shrink_zone(zone, priority, gfp_mask, nr_pages); |
