Commit 48916012 authored by David S. Miller's avatar David S. Miller

Merge nuts.ninka.net:/disk1/davem/BK/sparcwork-2.5

into nuts.ninka.net:/disk1/davem/BK/sparc-2.5
parents 28cacc5a 6fdc22ba
...@@ -234,9 +234,8 @@ W: http://www.canb.auug.org.au/~sfr/ ...@@ -234,9 +234,8 @@ W: http://www.canb.auug.org.au/~sfr/
S: Supported S: Supported
APPLETALK NETWORK LAYER APPLETALK NETWORK LAYER
P: Jay Schulist P: Arnaldo Carvalho de Melo
M: jschlst@samba.org M: acme@conectiva.com.br
L: linux-atalk@lists.netspace.org
S: Maintained S: Maintained
ARM26 ARCHITECTURE ARM26 ARCHITECTURE
......
...@@ -101,6 +101,13 @@ struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs) ...@@ -101,6 +101,13 @@ struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
struct pt_regs *ret; struct pt_regs *ret;
unsigned long tmp; unsigned long tmp;
/*
* This gets called from entry.S with interrupts disabled, but
* from process context. Enable interrupts here, before trying
* to access user space.
*/
local_irq_enable();
if (!current->thread.vm86_info) { if (!current->thread.vm86_info) {
printk("no vm86_info: BAD\n"); printk("no vm86_info: BAD\n");
do_exit(SIGSEGV); do_exit(SIGSEGV);
......
...@@ -44,6 +44,11 @@ struct irq_router { ...@@ -44,6 +44,11 @@ struct irq_router {
int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq, int new); int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq, int new);
}; };
struct irq_router_handler {
u16 vendor;
int (*probe)(struct irq_router *r, struct pci_dev *router, u16 device);
};
int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL; int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
/* /*
...@@ -258,111 +263,220 @@ static int pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, ...@@ -258,111 +263,220 @@ static int pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq,
} }
/* /*
* PIRQ routing for SiS 85C503 router used in several SiS chipsets * PIRQ routing for SiS 85C503 router used in several SiS chipsets.
* According to the SiS 5595 datasheet (preliminary V1.0, 12/24/1997) * We have to deal with the following issues here:
* the related registers work as follows: * - vendors have different ideas about the meaning of link values
* - some onboard devices (integrated in the chipset) have special
* links and are thus routed differently (i.e. not via PCI INTA-INTD)
* - different revision of the router have a different layout for
* the routing registers, particularly for the onchip devices
* *
* general: one byte per re-routable IRQ, * For all routing registers the common thing is we have one byte
* per routeable link which is defined as:
* bit 7 IRQ mapping enabled (0) or disabled (1) * bit 7 IRQ mapping enabled (0) or disabled (1)
* bits [6:4] reserved * bits [6:4] reserved (sometimes used for onchip devices)
* bits [3:0] IRQ to map to * bits [3:0] IRQ to map to
* allowed: 3-7, 9-12, 14-15 * allowed: 3-7, 9-12, 14-15
* reserved: 0, 1, 2, 8, 13 * reserved: 0, 1, 2, 8, 13
* *
* individual registers in device config space: * The config-space registers located at 0x41/0x42/0x43/0x44 are
* always used to route the normal PCI INT A/B/C/D respectively.
* Apparently there are systems implementing PCI routing table using
* link values 0x01-0x04 and others using 0x41-0x44 for PCI INTA..D.
* We try our best to handle both link mappings.
*
* Currently (2003-05-21) it appears most SiS chipsets follow the
* definition of routing registers from the SiS-5595 southbridge.
* According to the SiS 5595 datasheets the revision id's of the
* router (ISA-bridge) should be 0x01 or 0xb0.
* *
* 0x41/0x42/0x43/0x44: PCI INT A/B/C/D - bits as in general case * Furthermore we've also seen lspci dumps with revision 0x00 and 0xb1.
* Looks like these are used in a number of SiS 5xx/6xx/7xx chipsets.
* They seem to work with the current routing code. However there is
* some concern because of the two USB-OHCI HCs (original SiS 5595
* had only one). YMMV.
* *
* 0x61: IDEIRQ: bits as in general case - but: * Onchip routing for router rev-id 0x01/0xb0 and probably 0x00/0xb1:
*
* 0x61: IDEIRQ:
* bits [6:5] must be written 01 * bits [6:5] must be written 01
* bit 4 channel-select primary (0), secondary (1) * bit 4 channel-select primary (0), secondary (1)
* *
* 0x62: USBIRQ: bits as in general case - but: * 0x62: USBIRQ:
* bit 4 OHCI function disabled (0), enabled (1) * bit 6 OHCI function disabled (0), enabled (1)
*
* 0x6a: ACPI/SCI IRQ: bits 4-6 reserved
*
* 0x7e: Data Acq. Module IRQ - bits 4-6 reserved
* *
* 0x6a: ACPI/SCI IRQ - bits as in general case * We support USBIRQ (in addition to INTA-INTD) and keep the
* IDE, ACPI and DAQ routing untouched as set by the BIOS.
* *
* 0x7e: Data Acq. Module IRQ - bits as in general case * Currently the only reported exception is the new SiS 65x chipset
* which includes the SiS 69x southbridge. Here we have the 85C503
* router revision 0x04 and there are changes in the register layout
* mostly related to the different USB HCs with USB 2.0 support.
* *
* Apparently there are systems implementing PCI routing table using both * Onchip routing for router rev-id 0x04 (try-and-error observation)
* link values 0x01-0x04 and 0x41-0x44 for PCI INTA..D, but register offsets *
* like 0x62 as link values for USBIRQ e.g. So there is no simple * 0x60/0x61/0x62/0x63: 1xEHCI and 3xOHCI (companion) USB-HCs
* "register = offset + pirq" relation. * bit 6-4 are probably unused, not like 5595
* Currently we support PCI INTA..D and USBIRQ and try our best to handle
* both link mappings.
* IDE/ACPI/DAQ mapping is currently unsupported (left untouched as set by BIOS).
*/ */
static int pirq_sis_get(struct pci_dev *router, struct pci_dev *dev, int pirq) #define PIRQ_SIS_IRQ_MASK 0x0f
#define PIRQ_SIS_IRQ_DISABLE 0x80
#define PIRQ_SIS_USB_ENABLE 0x40
/* return value:
* -1 on error
* 0 for PCI INTA-INTD
* 0 or enable bit mask to check or set for onchip functions
*/
static inline int pirq_sis5595_onchip(int pirq, int *reg)
{ {
u8 x; int ret = -1;
int reg = pirq;
*reg = pirq;
switch(pirq) { switch(pirq) {
case 0x01: case 0x01:
case 0x02: case 0x02:
case 0x03: case 0x03:
case 0x04: case 0x04:
reg += 0x40; *reg += 0x40;
case 0x41: case 0x41:
case 0x42: case 0x42:
case 0x43: case 0x43:
case 0x44: case 0x44:
case 0x62: ret = 0;
pci_read_config_byte(router, reg, &x);
if (reg != 0x62)
break; break;
if (!(x & 0x40))
return 0; case 0x62:
ret = PIRQ_SIS_USB_ENABLE; /* documented for 5595 */
break; break;
case 0x61: case 0x61:
case 0x6a: case 0x6a:
case 0x7e: case 0x7e:
printk(KERN_INFO "SiS pirq: advanced IDE/ACPI/DAQ mapping not yet implemented\n"); printk(KERN_INFO "SiS pirq: IDE/ACPI/DAQ mapping not implemented: (%u)\n",
return 0; (unsigned) pirq);
/* fall thru */
default: default:
printk(KERN_INFO "SiS router pirq escape (%d)\n", pirq); printk(KERN_INFO "SiS router unknown request: (%u)\n",
return 0; (unsigned) pirq);
break;
} }
return (x & 0x80) ? 0 : (x & 0x0f); return ret;
} }
static int pirq_sis_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) /* return value:
* -1 on error
* 0 for PCI INTA-INTD
* 0 or enable bit mask to check or set for onchip functions
*/
static inline int pirq_sis96x_onchip(int pirq, int *reg)
{ {
u8 x; int ret = -1;
int reg = pirq;
*reg = pirq;
switch(pirq) { switch(pirq) {
case 0x01: case 0x01:
case 0x02: case 0x02:
case 0x03: case 0x03:
case 0x04: case 0x04:
reg += 0x40; *reg += 0x40;
case 0x41: case 0x41:
case 0x42: case 0x42:
case 0x43: case 0x43:
case 0x44: case 0x44:
case 0x60:
case 0x61:
case 0x62: case 0x62:
x = (irq&0x0f) ? (irq&0x0f) : 0x80; case 0x63:
if (reg != 0x62) ret = 0;
break; break;
/* always mark OHCI enabled, as nothing else knows about this */
x |= 0x40; default:
printk(KERN_INFO "SiS router unknown request: (%u)\n",
(unsigned) pirq);
break; break;
case 0x61: }
case 0x6a: return ret;
case 0x7e: }
printk(KERN_INFO "advanced SiS pirq mapping not yet implemented\n");
static int pirq_sis5595_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
{
u8 x;
int reg, check;
check = pirq_sis5595_onchip(pirq, &reg);
if (check < 0)
return 0; return 0;
default:
printk(KERN_INFO "SiS router pirq escape (%d)\n", pirq); pci_read_config_byte(router, reg, &x);
if (check != 0 && !(x & check))
return 0; return 0;
}
return (x & PIRQ_SIS_IRQ_DISABLE) ? 0 : (x & PIRQ_SIS_IRQ_MASK);
}
static int pirq_sis96x_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
{
u8 x;
int reg, check;
check = pirq_sis96x_onchip(pirq, &reg);
if (check < 0)
return 0;
pci_read_config_byte(router, reg, &x);
if (check != 0 && !(x & check))
return 0;
return (x & PIRQ_SIS_IRQ_DISABLE) ? 0 : (x & PIRQ_SIS_IRQ_MASK);
}
static int pirq_sis5595_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
{
u8 x;
int reg, set;
set = pirq_sis5595_onchip(pirq, &reg);
if (set < 0)
return 0;
x = (irq & PIRQ_SIS_IRQ_MASK);
if (x == 0)
x = PIRQ_SIS_IRQ_DISABLE;
else
x |= set;
pci_write_config_byte(router, reg, x);
return 1;
}
static int pirq_sis96x_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
{
u8 x;
int reg, set;
set = pirq_sis96x_onchip(pirq, &reg);
if (set < 0)
return 0;
x = (irq & PIRQ_SIS_IRQ_MASK);
if (x == 0)
x = PIRQ_SIS_IRQ_DISABLE;
else
x |= set;
pci_write_config_byte(router, reg, x); pci_write_config_byte(router, reg, x);
return 1; return 1;
} }
/* /*
* VLSI: nibble offset 0x74 - educated guess due to routing table and * VLSI: nibble offset 0x74 - educated guess due to routing table and
* config space of VLSI 82C534 PCI-bridge/router (1004:0102) * config space of VLSI 82C534 PCI-bridge/router (1004:0102)
...@@ -455,96 +569,252 @@ static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, ...@@ -455,96 +569,252 @@ static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq,
return pcibios_set_irq_routing(bridge, pin, irq); return pcibios_set_irq_routing(bridge, pin, irq);
} }
static struct irq_router pirq_bios_router = #endif
{ "BIOS", 0, 0, NULL, pirq_bios_set };
static __init int intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
{
#if 0 /* Let's see what chip this is supposed to be ... */
/* We must not touch 440GX even if we have tables. 440GX has
different IRQ routing weirdness */
if (pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82440GX, NULL))
return 0;
#endif #endif
static struct irq_router pirq_routers[] = { switch(device)
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, pirq_piix_get, pirq_piix_set }, {
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, pirq_piix_get, pirq_piix_set }, case PCI_DEVICE_ID_INTEL_82371FB_0:
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, pirq_piix_get, pirq_piix_set }, case PCI_DEVICE_ID_INTEL_82371SB_0:
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX, pirq_piix_get, pirq_piix_set }, case PCI_DEVICE_ID_INTEL_82371AB_0:
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_0, pirq_piix_get, pirq_piix_set }, case PCI_DEVICE_ID_INTEL_82371MX:
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, pirq_piix_get, pirq_piix_set }, case PCI_DEVICE_ID_INTEL_82443MX_0:
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, pirq_piix_get, pirq_piix_set }, case PCI_DEVICE_ID_INTEL_82801AA_0:
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, pirq_piix_get, pirq_piix_set }, case PCI_DEVICE_ID_INTEL_82801AB_0:
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, pirq_piix_get, pirq_piix_set }, case PCI_DEVICE_ID_INTEL_82801BA_0:
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, pirq_piix_get, pirq_piix_set }, case PCI_DEVICE_ID_INTEL_82801BA_10:
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, pirq_piix_get, pirq_piix_set }, case PCI_DEVICE_ID_INTEL_82801CA_0:
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, pirq_piix_get, pirq_piix_set }, case PCI_DEVICE_ID_INTEL_82801CA_12:
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, pirq_piix_get, pirq_piix_set }, case PCI_DEVICE_ID_INTEL_82801DB_0:
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, pirq_piix_get, pirq_piix_set }, case PCI_DEVICE_ID_INTEL_82801E_0:
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_0, pirq_piix_get, pirq_piix_set }, case PCI_DEVICE_ID_INTEL_82801EB_0:
case PCI_DEVICE_ID_INTEL_ESB_0:
{ "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pirq_ali_get, pirq_ali_set }, r->name = "PIIX/ICH";
r->get = pirq_piix_get;
{ "ITE", PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8330G_0, pirq_ite_get, pirq_ite_set }, r->set = pirq_piix_set;
return 1;
{ "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, pirq_via_get, pirq_via_set }, }
{ "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, pirq_via_get, pirq_via_set }, return 0;
{ "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, pirq_via_get, pirq_via_set }, }
{ "OPTI", PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C700, pirq_opti_get, pirq_opti_set },
{ "NatSemi", PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, pirq_cyrix_get, pirq_cyrix_set },
{ "SIS", PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, pirq_sis_get, pirq_sis_set },
{ "VLSI 82C534", PCI_VENDOR_ID_VLSI, PCI_DEVICE_ID_VLSI_82C534, pirq_vlsi_get, pirq_vlsi_set },
{ "ServerWorks", PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4,
pirq_serverworks_get, pirq_serverworks_set },
{ "ServerWorks", PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5,
pirq_serverworks_get, pirq_serverworks_set },
{ "AMD756 VIPER", PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B,
pirq_amd756_get, pirq_amd756_set },
{ "AMD766", PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413,
pirq_amd756_get, pirq_amd756_set },
{ "AMD768", PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7443,
pirq_amd756_get, pirq_amd756_set },
{ "default", 0, 0, NULL, NULL }
};
static struct irq_router *pirq_router; static __init int via_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
{
/* FIXME: We should move some of the quirk fixup stuff here */
switch(device)
{
case PCI_DEVICE_ID_VIA_82C586_0:
case PCI_DEVICE_ID_VIA_82C596:
case PCI_DEVICE_ID_VIA_82C686:
case PCI_DEVICE_ID_VIA_8231:
/* FIXME: add new ones for 8233/5 */
r->name = "VIA";
r->get = pirq_via_get;
r->set = pirq_via_set;
return 1;
}
return 0;
}
static __init int vlsi_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
{
switch(device)
{
case PCI_DEVICE_ID_VLSI_82C534:
r->name = "VLSI 82C534";
r->get = pirq_vlsi_get;
r->set = pirq_vlsi_set;
return 1;
}
return 0;
}
static __init int serverworks_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
{
switch(device)
{
case PCI_DEVICE_ID_SERVERWORKS_OSB4:
case PCI_DEVICE_ID_SERVERWORKS_CSB5:
r->name = "ServerWorks";
r->get = pirq_serverworks_get;
r->set = pirq_serverworks_set;
return 1;
}
return 0;
}
static __init int sis_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
{
if (device != PCI_DEVICE_ID_SI_503)
return 0;
/*
* In case of SiS south bridge, we need to detect the two
* kinds of routing tables we have seen so far (5595 and 96x).
*
* The 96x tends to still come with routing tables that claim
* to be 503's.. Silly thing. Check the actual router chip.
*/
if ((router->device & 0xfff0) == 0x0960) {
r->name = "SIS96x";
r->get = pirq_sis96x_get;
r->set = pirq_sis96x_set;
DBG("PCI: Detecting SiS router at %02x:%02x : SiS096x detected\n",
rt->rtr_bus, rt->rtr_devfn);
} else {
r->name = "SIS5595";
r->get = pirq_sis5595_get;
r->set = pirq_sis5595_set;
DBG("PCI: Detecting SiS router at %02x:%02x : SiS5595 detected\n",
rt->rtr_bus, rt->rtr_devfn);
}
return 1;
}
static __init int cyrix_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
{
switch(device)
{
case PCI_DEVICE_ID_CYRIX_5520:
r->name = "NatSemi";
r->get = pirq_cyrix_get;
r->set = pirq_cyrix_set;
return 1;
}
return 0;
}
static __init int opti_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
{
switch(device)
{
case PCI_DEVICE_ID_OPTI_82C700:
r->name = "OPTI";
r->get = pirq_opti_get;
r->set = pirq_opti_set;
return 1;
}
return 0;
}
static __init int ite_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
{
switch(device)
{
case PCI_DEVICE_ID_ITE_IT8330G_0:
r->name = "ITE";
r->get = pirq_ite_get;
r->set = pirq_ite_set;
return 1;
}
return 0;
}
static __init int ali_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
{
switch(device)
{
case PCI_DEVICE_ID_AL_M1533:
r->name = "ALI";
r->get = pirq_ali_get;
r->set = pirq_ali_set;
return 1;
/* Should add 156x some day */
}
return 0;
}
static __init int amd_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
{
switch(device)
{
case PCI_DEVICE_ID_AMD_VIPER_740B:
r->name = "AMD756";
break;
case PCI_DEVICE_ID_AMD_VIPER_7413:
r->name = "AMD766";
break;
case PCI_DEVICE_ID_AMD_VIPER_7443:
r->name = "AMD768";
break;
default:
return 0;
}
r->get = pirq_amd756_get;
r->set = pirq_amd756_set;
return 1;
}
static __initdata struct irq_router_handler pirq_routers[] = {
{ PCI_VENDOR_ID_INTEL, intel_router_probe },
{ PCI_VENDOR_ID_AL, ali_router_probe },
{ PCI_VENDOR_ID_ITE, ite_router_probe },
{ PCI_VENDOR_ID_VIA, via_router_probe },
{ PCI_VENDOR_ID_OPTI, opti_router_probe },
{ PCI_VENDOR_ID_SI, sis_router_probe },
{ PCI_VENDOR_ID_CYRIX, cyrix_router_probe },
{ PCI_VENDOR_ID_VLSI, vlsi_router_probe },
{ PCI_VENDOR_ID_SERVERWORKS, serverworks_router_probe },
{ PCI_VENDOR_ID_AMD, amd_router_probe },
/* Someone with docs needs to add the ATI Radeon IGP */
{ 0, NULL }
};
static struct irq_router pirq_router;
static struct pci_dev *pirq_router_dev; static struct pci_dev *pirq_router_dev;
static void __init pirq_find_router(void)
/*
* FIXME: should we have an option to say "generic for
* chipset" ?
*/
static void __init pirq_find_router(struct irq_router *r)
{ {
struct irq_routing_table *rt = pirq_table; struct irq_routing_table *rt = pirq_table;
struct irq_router *r; struct irq_router_handler *h;
#ifdef CONFIG_PCI_BIOS #ifdef CONFIG_PCI_BIOS
if (!rt->signature) { if (!rt->signature) {
printk(KERN_INFO "PCI: Using BIOS for IRQ routing\n"); printk(KERN_INFO "PCI: Using BIOS for IRQ routing\n");
pirq_router = &pirq_bios_router; r->set = pirq_bios_set;
r->name = "BIOS";
return; return;
} }
#endif #endif
/* Default unless a driver reloads it */
r->name = "default";
r->get = NULL;
r->set = NULL;
DBG("PCI: Attempting to find IRQ router for %04x:%04x\n", DBG("PCI: Attempting to find IRQ router for %04x:%04x\n",
rt->rtr_vendor, rt->rtr_device); rt->rtr_vendor, rt->rtr_device);
/* fall back to default router if nothing else found */
pirq_router = &pirq_routers[ARRAY_SIZE(pirq_routers) - 1];
pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn); pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn);
if (!pirq_router_dev) { if (!pirq_router_dev) {
DBG("PCI: Interrupt router not found at %02x:%02x\n", rt->rtr_bus, rt->rtr_devfn); DBG("PCI: Interrupt router not found at %02x:%02x\n", rt->rtr_bus, rt->rtr_devfn);
return; return;
} }
for(r=pirq_routers; r->vendor; r++) { for( h = pirq_routers; h->vendor; h++) {
/* Exact match against router table entry? Use it! */ /* First look for a router match */
if (r->vendor == rt->rtr_vendor && r->device == rt->rtr_device) { if (rt->rtr_vendor == h->vendor && h->probe(r, pirq_router_dev, rt->rtr_device))
pirq_router = r; break;
/* Fall back to a device match */
if (pirq_router_dev->vendor == h->vendor && h->probe(r, pirq_router_dev, pirq_router_dev->device))
break; break;
}
/* Match against router device entry? Use it as a fallback */
if (r->vendor == pirq_router_dev->vendor && r->device == pirq_router_dev->device) {
pirq_router = r;
}
} }
printk(KERN_INFO "PCI: Using IRQ router %s [%04x/%04x] at %s\n", printk(KERN_INFO "PCI: Using IRQ router %s [%04x/%04x] at %s\n",
pirq_router->name, pirq_router.name,
pirq_router_dev->vendor, pirq_router_dev->vendor,
pirq_router_dev->device, pirq_router_dev->device,
pci_name(pirq_router_dev)); pci_name(pirq_router_dev));
...@@ -574,7 +844,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) ...@@ -574,7 +844,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
int i, pirq, newirq; int i, pirq, newirq;
int irq = 0; int irq = 0;
u32 mask; u32 mask;
struct irq_router *r = pirq_router; struct irq_router *r = &pirq_router;
struct pci_dev *dev2 = NULL; struct pci_dev *dev2 = NULL;
char *msg = NULL; char *msg = NULL;
...@@ -775,7 +1045,7 @@ static int __init pcibios_irq_init(void) ...@@ -775,7 +1045,7 @@ static int __init pcibios_irq_init(void)
#endif #endif
if (pirq_table) { if (pirq_table) {
pirq_peer_trick(); pirq_peer_trick();
pirq_find_router(); pirq_find_router(&pirq_router);
if (pirq_table->exclusive_irqs) { if (pirq_table->exclusive_irqs) {
int i; int i;
for (i=0; i<16; i++) for (i=0; i<16; i++)
......
...@@ -141,6 +141,10 @@ static struct agp_device_ids sis_agp_device_ids[] __devinitdata = ...@@ -141,6 +141,10 @@ static struct agp_device_ids sis_agp_device_ids[] __devinitdata =
.device_id = PCI_DEVICE_ID_SI_655, .device_id = PCI_DEVICE_ID_SI_655,
.chipset_name = "655", .chipset_name = "655",
}, },
{
.device_id = PCI_DEVICE_ID_SI_661,
.chipset_name = "661",
},
{ {
.device_id = PCI_DEVICE_ID_SI_730, .device_id = PCI_DEVICE_ID_SI_730,
.chipset_name = "730", .chipset_name = "730",
...@@ -153,6 +157,10 @@ static struct agp_device_ids sis_agp_device_ids[] __devinitdata = ...@@ -153,6 +157,10 @@ static struct agp_device_ids sis_agp_device_ids[] __devinitdata =
.device_id = PCI_DEVICE_ID_SI_740, .device_id = PCI_DEVICE_ID_SI_740,
.chipset_name = "740", .chipset_name = "740",
}, },
{
.device_id = PCI_DEVICE_ID_SI_741,
.chipset_name = "741",
},
{ {
.device_id = PCI_DEVICE_ID_SI_745, .device_id = PCI_DEVICE_ID_SI_745,
.chipset_name = "745", .chipset_name = "745",
...@@ -161,6 +169,10 @@ static struct agp_device_ids sis_agp_device_ids[] __devinitdata = ...@@ -161,6 +169,10 @@ static struct agp_device_ids sis_agp_device_ids[] __devinitdata =
.device_id = PCI_DEVICE_ID_SI_746, .device_id = PCI_DEVICE_ID_SI_746,
.chipset_name = "746", .chipset_name = "746",
}, },
{
.device_id = PCI_DEVICE_ID_SI_760,
.chipset_name = "760",
},
{ }, /* dummy final entry, always present */ { }, /* dummy final entry, always present */
}; };
......
/* /*
* Version 2.11 * Version 2.13
* *
* AMD 755/756/766/8111 and nVidia nForce IDE driver for Linux. * AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s IDE driver for Linux.
* *
* Copyright (c) 2000-2002 Vojtech Pavlik * Copyright (c) 2000-2002 Vojtech Pavlik
* *
...@@ -40,9 +40,11 @@ ...@@ -40,9 +40,11 @@
#define AMD_UDMA_33 0x01 #define AMD_UDMA_33 0x01
#define AMD_UDMA_66 0x02 #define AMD_UDMA_66 0x02
#define AMD_UDMA_100 0x03 #define AMD_UDMA_100 0x03
#define AMD_UDMA_133 0x04
#define AMD_CHECK_SWDMA 0x08 #define AMD_CHECK_SWDMA 0x08
#define AMD_BAD_SWDMA 0x10 #define AMD_BAD_SWDMA 0x10
#define AMD_BAD_FIFO 0x20 #define AMD_BAD_FIFO 0x20
#define AMD_CHECK_SERENADE 0x40
/* /*
* AMD SouthBridge chips. * AMD SouthBridge chips.
...@@ -50,27 +52,33 @@ ...@@ -50,27 +52,33 @@
static struct amd_ide_chip { static struct amd_ide_chip {
unsigned short id; unsigned short id;
unsigned char rev;
unsigned long base; unsigned long base;
unsigned char flags; unsigned char flags;
} amd_ide_chips[] = { } amd_ide_chips[] = {
{ PCI_DEVICE_ID_AMD_COBRA_7401, 0x00, 0x40, AMD_UDMA_33 | AMD_BAD_SWDMA }, /* AMD-755 Cobra */ { PCI_DEVICE_ID_AMD_COBRA_7401, 0x40, AMD_UDMA_33 | AMD_BAD_SWDMA },
{ PCI_DEVICE_ID_AMD_VIPER_7409, 0x00, 0x40, AMD_UDMA_66 | AMD_CHECK_SWDMA }, /* AMD-756 Viper */ { PCI_DEVICE_ID_AMD_VIPER_7409, 0x40, AMD_UDMA_66 | AMD_CHECK_SWDMA },
{ PCI_DEVICE_ID_AMD_VIPER_7411, 0x00, 0x40, AMD_UDMA_100 | AMD_BAD_FIFO }, /* AMD-766 Viper */ { PCI_DEVICE_ID_AMD_VIPER_7411, 0x40, AMD_UDMA_100 | AMD_BAD_FIFO },
{ PCI_DEVICE_ID_AMD_OPUS_7441, 0x00, 0x40, AMD_UDMA_100 }, /* AMD-768 Opus */ { PCI_DEVICE_ID_AMD_OPUS_7441, 0x40, AMD_UDMA_100 },
{ PCI_DEVICE_ID_AMD_8111_IDE, 0x00, 0x40, AMD_UDMA_100 }, /* AMD-8111 */ { PCI_DEVICE_ID_AMD_8111_IDE, 0x40, AMD_UDMA_133 | AMD_CHECK_SERENADE },
{ PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, 0x00, 0x50, AMD_UDMA_100 }, /* nVidia nForce */ { PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, 0x50, AMD_UDMA_100 },
{ PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, 0x00, 0x50, AMD_UDMA_100 }, /* nVidia nForce 2 */ { PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, 0x50, AMD_UDMA_133 },
{ 0 } { 0 }
}; };
static struct amd_ide_chip *amd_config; static struct amd_ide_chip *amd_config;
static ide_pci_device_t *amd_chipset;
static unsigned int amd_80w; static unsigned int amd_80w;
static unsigned int amd_clock; static unsigned int amd_clock;
static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3 }; static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7 };
static unsigned char amd_udma2cyc[] = { 4, 6, 8, 10, 3, 2, 1, 1 }; static unsigned char amd_udma2cyc[] = { 4, 6, 8, 10, 3, 2, 1, 15 };
static char *amd_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100" }; static char *amd_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" };
/* /*
* AMD /proc entry. * AMD /proc entry.
...@@ -102,7 +110,7 @@ static int amd74xx_get_info(char *buffer, char **addr, off_t offset, int count) ...@@ -102,7 +110,7 @@ static int amd74xx_get_info(char *buffer, char **addr, off_t offset, int count)
amd_print("----------AMD BusMastering IDE Configuration----------------"); amd_print("----------AMD BusMastering IDE Configuration----------------");
amd_print("Driver Version: 2.11"); amd_print("Driver Version: 2.13");
amd_print("South Bridge: %s", pci_name(bmide_dev)); amd_print("South Bridge: %s", pci_name(bmide_dev));
pci_read_config_byte(dev, PCI_REVISION_ID, &t); pci_read_config_byte(dev, PCI_REVISION_ID, &t);
...@@ -153,6 +161,12 @@ static int amd74xx_get_info(char *buffer, char **addr, off_t offset, int count) ...@@ -153,6 +161,12 @@ static int amd74xx_get_info(char *buffer, char **addr, off_t offset, int count)
continue; continue;
} }
if (den[i] && uen[i] && udma[i] == 15) {
speed[i] = amd_clock * 4;
cycle[i] = 500000 / amd_clock;
continue;
}
speed[i] = 4 * amd_clock / ((den[i] && uen[i]) ? udma[i] : (active[i] + recover[i]) * 2); speed[i] = 4 * amd_clock / ((den[i] && uen[i]) ? udma[i] : (active[i] + recover[i]) * 2);
cycle[i] = 1000000 * ((den[i] && uen[i]) ? udma[i] : (active[i] + recover[i]) * 2) / amd_clock / 2; cycle[i] = 1000000 * ((den[i] && uen[i]) ? udma[i] : (active[i] + recover[i]) * 2) / amd_clock / 2;
} }
...@@ -198,6 +212,7 @@ static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timi ...@@ -198,6 +212,7 @@ static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timi
case AMD_UDMA_33: t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break; case AMD_UDMA_33: t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
case AMD_UDMA_66: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break; case AMD_UDMA_66: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break;
case AMD_UDMA_100: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break; case AMD_UDMA_100: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break;
case AMD_UDMA_133: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 15)]) : 0x03; break;
default: return; default: return;
} }
...@@ -232,6 +247,7 @@ static int amd_set_drive(ide_drive_t *drive, u8 speed) ...@@ -232,6 +247,7 @@ static int amd_set_drive(ide_drive_t *drive, u8 speed)
} }
if (speed == XFER_UDMA_5 && amd_clock <= 33333) t.udma = 1; if (speed == XFER_UDMA_5 && amd_clock <= 33333) t.udma = 1;
if (speed == XFER_UDMA_6 && amd_clock <= 33333) t.udma = 15;
amd_set_speed(HWIF(drive)->pci_dev, drive->dn, &t); amd_set_speed(HWIF(drive)->pci_dev, drive->dn, &t);
...@@ -271,7 +287,8 @@ static int amd74xx_ide_dma_check(ide_drive_t *drive) ...@@ -271,7 +287,8 @@ static int amd74xx_ide_dma_check(ide_drive_t *drive)
XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA | XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA |
((amd_config->flags & AMD_BAD_SWDMA) ? 0 : XFER_SWDMA) | ((amd_config->flags & AMD_BAD_SWDMA) ? 0 : XFER_SWDMA) |
(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_66 ? XFER_UDMA_66 : 0) | (w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_66 ? XFER_UDMA_66 : 0) |
(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_100 ? XFER_UDMA_100 : 0)); (w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_100 ? XFER_UDMA_100 : 0) |
(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_133 ? XFER_UDMA_133 : 0));
amd_set_drive(drive, speed); amd_set_drive(drive, speed);
...@@ -307,13 +324,15 @@ static unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char ...@@ -307,13 +324,15 @@ static unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char
switch (amd_config->flags & AMD_UDMA) { switch (amd_config->flags & AMD_UDMA) {
case AMD_UDMA_133:
case AMD_UDMA_100: case AMD_UDMA_100:
pci_read_config_byte(dev, AMD_CABLE_DETECT, &t); pci_read_config_byte(dev, AMD_CABLE_DETECT, &t);
pci_read_config_dword(dev, AMD_UDMA_TIMING, &u); pci_read_config_dword(dev, AMD_UDMA_TIMING, &u);
amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0); amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0);
for (i = 24; i >= 0; i -= 8) for (i = 24; i >= 0; i -= 8)
if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) { if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) {
printk(KERN_WARNING "AMD_IDE: Bios didn't set cable bits correctly. Enabling workaround.\n"); printk(KERN_WARNING "%s: BIOS didn't set cable bits correctly. Enabling workaround.\n",
amd_chipset->name);
amd_80w |= (1 << (1 - (i >> 4))); amd_80w |= (1 << (1 - (i >> 4)));
} }
break; break;
...@@ -334,6 +353,15 @@ static unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char ...@@ -334,6 +353,15 @@ static unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char
pci_write_config_byte(dev, AMD_IDE_CONFIG, pci_write_config_byte(dev, AMD_IDE_CONFIG,
(amd_config->flags & AMD_BAD_FIFO) ? (t & 0x0f) : (t | 0xf0)); (amd_config->flags & AMD_BAD_FIFO) ? (t & 0x0f) : (t | 0xf0));
/*
* Take care of incorrectly wired Serenade mainboards.
*/
if ((amd_config->flags & AMD_CHECK_SERENADE) &&
dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
amd_config->flags = AMD_UDMA_100;
/* /*
* Determine the system bus clock. * Determine the system bus clock.
*/ */
...@@ -347,8 +375,10 @@ static unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char ...@@ -347,8 +375,10 @@ static unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char
} }
if (amd_clock < 20000 || amd_clock > 50000) { if (amd_clock < 20000 || amd_clock > 50000) {
printk(KERN_WARNING "AMD_IDE: User given PCI clock speed impossible (%d), using 33 MHz instead.\n", amd_clock); printk(KERN_WARNING "%s: User given PCI clock speed impossible (%d), using 33 MHz instead.\n",
printk(KERN_WARNING "AMD_IDE: Use ide0=ata66 if you want to assume 80-wire cable\n"); amd_chipset->name, amd_clock);
printk(KERN_WARNING "%s: Use ide0=ata66 if you want to assume 80-wire cable\n",
amd_chipset->name);
amd_clock = 33333; amd_clock = 33333;
} }
...@@ -357,8 +387,8 @@ static unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char ...@@ -357,8 +387,8 @@ static unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char
*/ */
pci_read_config_byte(dev, PCI_REVISION_ID, &t); pci_read_config_byte(dev, PCI_REVISION_ID, &t);
printk(KERN_INFO "AMD_IDE: %s (rev %02x) %s controller on pci%s\n", printk(KERN_INFO "%s: %s (rev %02x) %s controller\n",
pci_name(dev), t, amd_dma[amd_config->flags & AMD_UDMA], pci_name(dev)); amd_chipset->name, pci_name(dev), t, amd_dma[amd_config->flags & AMD_UDMA]);
/* /*
* Register /proc/ide/amd74xx entry * Register /proc/ide/amd74xx entry
...@@ -373,8 +403,7 @@ static unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char ...@@ -373,8 +403,7 @@ static unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char
} }
#endif /* DISPLAY_AMD_TIMINGS && CONFIG_PROC_FS */ #endif /* DISPLAY_AMD_TIMINGS && CONFIG_PROC_FS */
return dev->irq;
return 0;
} }
static void __init init_hwif_amd74xx(ide_hwif_t *hwif) static void __init init_hwif_amd74xx(ide_hwif_t *hwif)
...@@ -414,23 +443,29 @@ extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); ...@@ -414,23 +443,29 @@ extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id) static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
{ {
ide_pci_device_t *d = amd74xx_chipsets + id->driver_data; amd_chipset = amd74xx_chipsets + id->driver_data;
amd_config = amd_ide_chips + id->driver_data; amd_config = amd_ide_chips + id->driver_data;
if (dev->device != d->device) BUG(); if (dev->device != amd_chipset->device) BUG();
if (dev->device != amd_config->id) BUG(); if (dev->device != amd_config->id) BUG();
ide_setup_pci_device(dev, d); ide_setup_pci_device(dev, amd_chipset);
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
return 0; return 0;
} }
static struct pci_device_id amd74xx_pci_tbl[] = { static struct pci_device_id amd74xx_pci_tbl[] = {
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_COBRA_7401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_COBRA_7401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7409, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7409, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7441, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7441, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6}, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 },
{ 0, }, { 0, },
}; };
......
...@@ -109,6 +109,72 @@ static ide_pci_device_t amd74xx_chipsets[] __devinitdata = { ...@@ -109,6 +109,72 @@ static ide_pci_device_t amd74xx_chipsets[] __devinitdata = {
.bootable = ON_BOARD, .bootable = ON_BOARD,
.extra = 0, .extra = 0,
}, },
{ /* 7 */
.vendor = PCI_VENDOR_ID_NVIDIA,
.device = PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE,
.name = "NFORCE2S",
.init_chipset = init_chipset_amd74xx,
.init_hwif = init_hwif_amd74xx,
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
.bootable = ON_BOARD,
},
{ /* 8 */
.vendor = PCI_VENDOR_ID_NVIDIA,
.device = PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,
.name = "NFORCE2S-SATA",
.init_chipset = init_chipset_amd74xx,
.init_hwif = init_hwif_amd74xx,
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
.bootable = ON_BOARD,
},
{ /* 9 */
.vendor = PCI_VENDOR_ID_NVIDIA,
.device = PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE,
.name = "NFORCE3",
.init_chipset = init_chipset_amd74xx,
.init_hwif = init_hwif_amd74xx,
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
.bootable = ON_BOARD,
},
{ /* 10 */
.vendor = PCI_VENDOR_ID_NVIDIA,
.device = PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE,
.name = "NFORCE3S",
.init_chipset = init_chipset_amd74xx,
.init_hwif = init_hwif_amd74xx,
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
.bootable = ON_BOARD,
},
{ /* 11 */
.vendor = PCI_VENDOR_ID_NVIDIA,
.device = PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,
.name = "NFORCE3S-SATA",
.init_chipset = init_chipset_amd74xx,
.init_hwif = init_hwif_amd74xx,
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
.bootable = ON_BOARD,
},
{ /* 12 */
.vendor = PCI_VENDOR_ID_NVIDIA,
.device = PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,
.name = "NFORCE3S-SATA2",
.init_chipset = init_chipset_amd74xx,
.init_hwif = init_hwif_amd74xx,
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
.bootable = ON_BOARD,
},
{ {
.vendor = 0, .vendor = 0,
.device = 0, .device = 0,
......
...@@ -615,8 +615,8 @@ static int cp_rx_poll (struct net_device *dev, int *budget) ...@@ -615,8 +615,8 @@ static int cp_rx_poll (struct net_device *dev, int *budget)
if (cpr16(IntrStatus) & cp_rx_intr_mask) if (cpr16(IntrStatus) & cp_rx_intr_mask)
goto rx_status_loop; goto rx_status_loop;
cpw16_f(IntrMask, cp_intr_mask);
netif_rx_complete(dev); netif_rx_complete(dev);
cpw16_f(IntrMask, cp_intr_mask);
return 0; /* done */ return 0; /* done */
} }
......
...@@ -45,7 +45,7 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) ...@@ -45,7 +45,7 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
DBGC((KERN_ERR " got res [%lx:%lx] bus [%lx:%lx] flags %lx for " DBGC((KERN_ERR " got res [%lx:%lx] bus [%lx:%lx] flags %lx for "
"BAR %d of %s\n", res->start, res->end, "BAR %d of %s\n", res->start, res->end,
region.start, region.end, res->flags, region.start, region.end, res->flags,
resno, dev->dev.name)); resno, pci_name(dev)));
new = region.start | (res->flags & PCI_REGION_FLAG_MASK); new = region.start | (res->flags & PCI_REGION_FLAG_MASK);
if (res->flags & IORESOURCE_IO) if (res->flags & IORESOURCE_IO)
......
...@@ -1160,7 +1160,7 @@ int __init isapnp_init(void) ...@@ -1160,7 +1160,7 @@ int __init isapnp_init(void)
return 0; return 0;
} }
fs_initcall(isapnp_init); device_initcall(isapnp_init);
/* format is: noisapnp */ /* format is: noisapnp */
......
...@@ -457,7 +457,7 @@ config SCSI_SATA_VIA ...@@ -457,7 +457,7 @@ config SCSI_SATA_VIA
config SCSI_BUSLOGIC config SCSI_BUSLOGIC
tristate "BusLogic SCSI support" tristate "BusLogic SCSI support"
depends on (PCI || ISA) && SCSI depends on (PCI || ISA || MCA) && SCSI
---help--- ---help---
This is support for BusLogic MultiMaster and FlashPoint SCSI Host This is support for BusLogic MultiMaster and FlashPoint SCSI Host
Adapters. Consult the SCSI-HOWTO, available from Adapters. Consult the SCSI-HOWTO, available from
......
...@@ -117,6 +117,9 @@ static struct ata_port_operations piix_pata_ops = { ...@@ -117,6 +117,9 @@ static struct ata_port_operations piix_pata_ops = {
.eng_timeout = ata_eng_timeout, .eng_timeout = ata_eng_timeout,
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.port_start = ata_port_start,
.port_stop = ata_port_stop,
}; };
static struct ata_port_operations piix_sata_ops = { static struct ata_port_operations piix_sata_ops = {
...@@ -137,6 +140,9 @@ static struct ata_port_operations piix_sata_ops = { ...@@ -137,6 +140,9 @@ static struct ata_port_operations piix_sata_ops = {
.eng_timeout = ata_eng_timeout, .eng_timeout = ata_eng_timeout,
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.port_start = ata_port_start,
.port_stop = ata_port_stop,
}; };
static struct ata_port_info piix_port_info[] = { static struct ata_port_info piix_port_info[] = {
......
...@@ -915,15 +915,15 @@ scsi_show_extd_sense(unsigned char asc, unsigned char ascq) { ...@@ -915,15 +915,15 @@ scsi_show_extd_sense(unsigned char asc, unsigned char ascq) {
/* Print sense information */ /* Print sense information */
static void static void
print_sense_internal(const char * devclass, print_sense_internal(const char *devclass,
const unsigned char * sense_buffer, const unsigned char *sense_buffer,
struct request *req) struct request *req)
{ {
int s, sense_class, valid, code, info; int s, sense_class, valid, code, info;
const char * error = NULL; const char *error = NULL;
unsigned char asc, ascq; unsigned char asc, ascq;
const char *sense_txt; const char *sense_txt;
char *name = req->rq_disk ? req->rq_disk->disk_name : "?"; const char *name = req->rq_disk ? req->rq_disk->disk_name : devclass;
sense_class = (sense_buffer[0] >> 4) & 0x07; sense_class = (sense_buffer[0] >> 4) & 0x07;
code = sense_buffer[0] & 0xf; code = sense_buffer[0] & 0xf;
...@@ -966,11 +966,9 @@ print_sense_internal(const char * devclass, ...@@ -966,11 +966,9 @@ print_sense_internal(const char * devclass,
sense_txt = scsi_sense_key_string(sense_buffer[2]); sense_txt = scsi_sense_key_string(sense_buffer[2]);
if (sense_txt) if (sense_txt)
printk("%s%s: sense key %s\n", printk("%s: sense key %s\n", name, sense_txt);
devclass, name, sense_txt);
else else
printk("%s%s: sense = %2x %2x\n", printk("%s: sense = %2x %2x\n", name,
devclass, name,
sense_buffer[0], sense_buffer[2]); sense_buffer[0], sense_buffer[2]);
asc = ascq = 0; asc = ascq = 0;
...@@ -993,11 +991,9 @@ print_sense_internal(const char * devclass, ...@@ -993,11 +991,9 @@ print_sense_internal(const char * devclass,
sense_txt = scsi_sense_key_string(sense_buffer[0]); sense_txt = scsi_sense_key_string(sense_buffer[0]);
if (sense_txt) if (sense_txt)
printk("%s%s: old sense key %s\n", printk("%s: old sense key %s\n", name, sense_txt);
devclass, name, sense_txt);
else else
printk("%s%s: sense = %2x %2x\n", printk("%s: sense = %2x %2x\n", name,
devclass, name,
sense_buffer[0], sense_buffer[2]); sense_buffer[0], sense_buffer[2]);
printk("Non-extended sense class %d code 0x%0x\n", printk("Non-extended sense class %d code 0x%0x\n",
......
...@@ -1058,10 +1058,12 @@ void sata_phy_reset(struct ata_port *ap) ...@@ -1058,10 +1058,12 @@ void sata_phy_reset(struct ata_port *ap)
u32 sstatus; u32 sstatus;
unsigned long timeout = jiffies + (HZ * 5); unsigned long timeout = jiffies + (HZ * 5);
if (ap->flags & ATA_FLAG_SATA_RESET) {
scr_write(ap, SCR_CONTROL, 0x301); /* issue phy wake/reset */ scr_write(ap, SCR_CONTROL, 0x301); /* issue phy wake/reset */
scr_read(ap, SCR_CONTROL); /* dummy read; flush */ scr_read(ap, SCR_STATUS); /* dummy read; flush */
udelay(400); /* FIXME: a guess */ udelay(400); /* FIXME: a guess */
scr_write(ap, SCR_CONTROL, 0x300); /* issue phy wake/reset */ }
scr_write(ap, SCR_CONTROL, 0x300); /* issue phy wake/clear reset */
/* wait for phy to become ready, if necessary */ /* wait for phy to become ready, if necessary */
do { do {
...@@ -1084,6 +1086,11 @@ void sata_phy_reset(struct ata_port *ap) ...@@ -1084,6 +1086,11 @@ void sata_phy_reset(struct ata_port *ap)
if (ap->flags & ATA_FLAG_PORT_DISABLED) if (ap->flags & ATA_FLAG_PORT_DISABLED)
return; return;
if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
ata_port_disable(ap);
return;
}
ata_bus_reset(ap); ata_bus_reset(ap);
} }
...@@ -1337,9 +1344,13 @@ void ata_bus_reset(struct ata_port *ap) ...@@ -1337,9 +1344,13 @@ void ata_bus_reset(struct ata_port *ap)
outb(ap->ctl, ioaddr->ctl_addr); outb(ap->ctl, ioaddr->ctl_addr);
/* determine if device 0/1 are present */ /* determine if device 0/1 are present */
if (ap->flags & ATA_FLAG_SATA_RESET)
dev0 = 1;
else {
dev0 = ata_dev_devchk(ap, 0); dev0 = ata_dev_devchk(ap, 0);
if (slave_possible) if (slave_possible)
dev1 = ata_dev_devchk(ap, 1); dev1 = ata_dev_devchk(ap, 1);
}
if (dev0) if (dev0)
devmask |= (1 << 0); devmask |= (1 << 0);
...@@ -2569,6 +2580,7 @@ static int ata_thread (void *data) ...@@ -2569,6 +2580,7 @@ static int ata_thread (void *data)
printk(KERN_DEBUG "ata%u: thread exiting\n", ap->id); printk(KERN_DEBUG "ata%u: thread exiting\n", ap->id);
ap->thr_pid = -1; ap->thr_pid = -1;
del_timer_sync(&ap->thr_timer);
complete_and_exit (&ap->thr_exited, 0); complete_and_exit (&ap->thr_exited, 0);
} }
...@@ -2664,6 +2676,26 @@ static void atapi_cdb_send(struct ata_port *ap) ...@@ -2664,6 +2676,26 @@ static void atapi_cdb_send(struct ata_port *ap)
goto out; goto out;
} }
int ata_port_start (struct ata_port *ap)
{
struct pci_dev *pdev = ap->host_set->pdev;
ap->prd = pci_alloc_consistent(pdev, ATA_PRD_TBL_SZ, &ap->prd_dma);
if (!ap->prd)
return -ENOMEM;
DPRINTK("prd alloc, virt %p, dma %x\n", ap->prd, ap->prd_dma);
return 0;
}
void ata_port_stop (struct ata_port *ap)
{
struct pci_dev *pdev = ap->host_set->pdev;
pci_free_consistent(pdev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
}
/** /**
* ata_host_remove - * ata_host_remove -
* @ap: * @ap:
...@@ -2683,7 +2715,7 @@ static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister) ...@@ -2683,7 +2715,7 @@ static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister)
ata_thread_kill(ap); /* FIXME: check return val */ ata_thread_kill(ap); /* FIXME: check return val */
pci_free_consistent(ap->host_set->pdev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); ap->ops->port_stop(ap);
} }
/** /**
...@@ -2764,9 +2796,9 @@ static struct ata_port * ata_host_add(struct ata_probe_ent *ent, ...@@ -2764,9 +2796,9 @@ static struct ata_port * ata_host_add(struct ata_probe_ent *ent,
struct ata_host_set *host_set, struct ata_host_set *host_set,
unsigned int port_no) unsigned int port_no)
{ {
struct pci_dev *pdev = ent->pdev;
struct Scsi_Host *host; struct Scsi_Host *host;
struct ata_port *ap; struct ata_port *ap;
int rc;
DPRINTK("ENTER\n"); DPRINTK("ENTER\n");
host = scsi_host_alloc(ent->sht, sizeof(struct ata_port)); host = scsi_host_alloc(ent->sht, sizeof(struct ata_port));
...@@ -2777,10 +2809,9 @@ static struct ata_port * ata_host_add(struct ata_probe_ent *ent, ...@@ -2777,10 +2809,9 @@ static struct ata_port * ata_host_add(struct ata_probe_ent *ent,
ata_host_init(ap, host, host_set, ent, port_no); ata_host_init(ap, host, host_set, ent, port_no);
ap->prd = pci_alloc_consistent(pdev, ATA_PRD_TBL_SZ, &ap->prd_dma); rc = ap->ops->port_start(ap);
if (!ap->prd) if (rc)
goto err_out; goto err_out;
DPRINTK("prd alloc, virt %p, dma %x\n", ap->prd, ap->prd_dma);
ap->thr_pid = kernel_thread(ata_thread, ap, CLONE_FS | CLONE_FILES); ap->thr_pid = kernel_thread(ata_thread, ap, CLONE_FS | CLONE_FILES);
if (ap->thr_pid < 0) { if (ap->thr_pid < 0) {
...@@ -2792,7 +2823,7 @@ static struct ata_port * ata_host_add(struct ata_probe_ent *ent, ...@@ -2792,7 +2823,7 @@ static struct ata_port * ata_host_add(struct ata_probe_ent *ent,
return ap; return ap;
err_out_free: err_out_free:
pci_free_consistent(ap->host_set->pdev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); ap->ops->port_stop(ap);
err_out: err_out:
scsi_host_put(host); scsi_host_put(host);
...@@ -2828,6 +2859,7 @@ int ata_device_add(struct ata_probe_ent *ent) ...@@ -2828,6 +2859,7 @@ int ata_device_add(struct ata_probe_ent *ent)
host_set->n_ports = ent->n_ports; host_set->n_ports = ent->n_ports;
host_set->irq = ent->irq; host_set->irq = ent->irq;
host_set->mmio_base = ent->mmio_base; host_set->mmio_base = ent->mmio_base;
host_set->private_data = ent->private_data;
/* register each port bound to this device */ /* register each port bound to this device */
for (i = 0; i < ent->n_ports; i++) { for (i = 0; i < ent->n_ports; i++) {
...@@ -3170,6 +3202,8 @@ void ata_pci_remove_one (struct pci_dev *pdev) ...@@ -3170,6 +3202,8 @@ void ata_pci_remove_one (struct pci_dev *pdev)
free_irq(host_set->irq, host_set); free_irq(host_set->irq, host_set);
if (host_set->mmio_base) if (host_set->mmio_base)
iounmap(host_set->mmio_base); iounmap(host_set->mmio_base);
if (host_set->ports[0]->ops->host_stop)
host_set->ports[0]->ops->host_stop(host_set);
for (i = 0; i < host_set->n_ports; i++) { for (i = 0; i < host_set->n_ports; i++) {
Scsi_Host_Template *sht; Scsi_Host_Template *sht;
...@@ -3274,6 +3308,8 @@ EXPORT_SYMBOL_GPL(ata_check_status_pio); ...@@ -3274,6 +3308,8 @@ EXPORT_SYMBOL_GPL(ata_check_status_pio);
EXPORT_SYMBOL_GPL(ata_check_status_mmio); EXPORT_SYMBOL_GPL(ata_check_status_mmio);
EXPORT_SYMBOL_GPL(ata_exec_command_pio); EXPORT_SYMBOL_GPL(ata_exec_command_pio);
EXPORT_SYMBOL_GPL(ata_exec_command_mmio); EXPORT_SYMBOL_GPL(ata_exec_command_mmio);
EXPORT_SYMBOL_GPL(ata_port_start);
EXPORT_SYMBOL_GPL(ata_port_stop);
EXPORT_SYMBOL_GPL(ata_interrupt); EXPORT_SYMBOL_GPL(ata_interrupt);
EXPORT_SYMBOL_GPL(ata_fill_sg); EXPORT_SYMBOL_GPL(ata_fill_sg);
EXPORT_SYMBOL_GPL(ata_bmdma_start_pio); EXPORT_SYMBOL_GPL(ata_bmdma_start_pio);
......
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
/* The size of the first scatter/gather segments (determines the maximum block /* The size of the first scatter/gather segments (determines the maximum block
size for SCSI adapters not supporting scatter/gather). The default is set size for SCSI adapters not supporting scatter/gather). The default is set
to try to allocate the buffer as one chunk. */ to try to allocate the buffer as one chunk. */
#define OSST_FIRST_ORDER 5 #define OSST_FIRST_ORDER (15-PAGE_SHIFT)
/* The following lines define defaults for properties that can be set /* The following lines define defaults for properties that can be set
......
...@@ -32,22 +32,46 @@ ...@@ -32,22 +32,46 @@
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
#include <linux/libata.h> #include <linux/libata.h>
#include <asm/io.h>
#undef DIRECT_HDMA
#define DRV_NAME "sata_promise" #define DRV_NAME "sata_promise"
#define DRV_VERSION "0.83" #define DRV_VERSION "0.84"
enum { enum {
PDC_PRD_TBL = 0x44, /* Direct command DMA table addr */ PDC_PRD_TBL = 0x44, /* Direct command DMA table addr */
PDC_PKT_SUBMIT = 0x40, /* Command packet pointer addr */
PDC_HDMA_PKT_SUBMIT = 0x100, /* Host DMA packet pointer addr */
PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */ PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */
PDC_TBG_MODE = 0x41, /* TBG mode */ PDC_TBG_MODE = 0x41, /* TBG mode */
PDC_FLASH_CTL = 0x44, /* Flash control register */ PDC_FLASH_CTL = 0x44, /* Flash control register */
PDC_CTLSTAT = 0x60, /* IDE control and status register */ PDC_CTLSTAT = 0x60, /* IDE control and status register */
PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */ PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */
PDC_SLEW_CTL = 0x470, /* slew rate control reg */ PDC_SLEW_CTL = 0x470, /* slew rate control reg */
PDC_HDMA_CTLSTAT = 0x12C, /* Host DMA control / status */
PDC_20621_SEQCTL = 0x400, PDC_20621_SEQCTL = 0x400,
PDC_20621_SEQMASK = 0x480, PDC_20621_SEQMASK = 0x480,
PDC_20621_PAGE_SIZE = (32 * 1024),
/* chosen, not constant, values; we design our own DIMM mem map */
PDC_20621_DIMM_WINDOW = 0x0C, /* page# for 32K DIMM window */
PDC_20621_DIMM_BASE = 0x00200000,
PDC_20621_DIMM_DATA = (64 * 1024),
PDC_DIMM_DATA_STEP = (256 * 1024),
PDC_DIMM_WINDOW_STEP = (8 * 1024),
PDC_DIMM_HOST_PRD = (6 * 1024),
PDC_DIMM_HOST_PKT = (128 * 0),
PDC_DIMM_HPKT_PRD = (128 * 1),
PDC_DIMM_ATA_PKT = (128 * 2),
PDC_DIMM_APKT_PRD = (128 * 3),
PDC_DIMM_HEADER_SZ = PDC_DIMM_APKT_PRD + 128,
PDC_PAGE_WINDOW = 0x40,
PDC_PAGE_DATA = PDC_PAGE_WINDOW +
(PDC_20621_DIMM_DATA / PDC_20621_PAGE_SIZE),
PDC_PAGE_SET = PDC_DIMM_DATA_STEP / PDC_20621_PAGE_SIZE,
PDC_CHIP0_OFS = 0xC0000, /* offset of chip #0 */ PDC_CHIP0_OFS = 0xC0000, /* offset of chip #0 */
...@@ -56,6 +80,14 @@ enum { ...@@ -56,6 +80,14 @@ enum {
board_20621 = 2, /* FastTrak S150 SX4 */ board_20621 = 2, /* FastTrak S150 SX4 */
PDC_FLAG_20621 = (1 << 30), /* we have a 20621 */ PDC_FLAG_20621 = (1 << 30), /* we have a 20621 */
PDC_HDMA_RESET = (1 << 11), /* HDMA reset */
};
struct pdc_port_priv {
u8 dimm_buf[(ATA_PRD_SZ * ATA_MAX_PRD) + 512];
u8 *pkt;
dma_addr_t pkt_dma;
}; };
...@@ -67,9 +99,20 @@ static void pdc_sata_set_udmamode (struct ata_port *ap, struct ata_device *adev, ...@@ -67,9 +99,20 @@ static void pdc_sata_set_udmamode (struct ata_port *ap, struct ata_device *adev,
unsigned int udma); unsigned int udma);
static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
static void pdc_dma_start(struct ata_queued_cmd *qc); static void pdc_dma_start(struct ata_queued_cmd *qc);
static void pdc20621_dma_start(struct ata_queued_cmd *qc);
static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs); static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
static void pdc_eng_timeout(struct ata_port *ap); static void pdc_eng_timeout(struct ata_port *ap);
static void pdc_20621_phy_reset (struct ata_port *ap); static void pdc_20621_phy_reset (struct ata_port *ap);
static int pdc_port_start(struct ata_port *ap);
static void pdc_port_stop(struct ata_port *ap);
static void pdc_fill_sg(struct ata_queued_cmd *qc);
static void pdc20621_fill_sg(struct ata_queued_cmd *qc);
static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
static void pdc20621_host_stop(struct ata_host_set *host_set);
static inline void pdc_dma_complete (struct ata_port *ap,
struct ata_queued_cmd *qc);
static Scsi_Host_Template pdc_sata_sht = { static Scsi_Host_Template pdc_sata_sht = {
...@@ -93,34 +136,39 @@ static struct ata_port_operations pdc_sata_ops = { ...@@ -93,34 +136,39 @@ static struct ata_port_operations pdc_sata_ops = {
.port_disable = ata_port_disable, .port_disable = ata_port_disable,
.set_piomode = pdc_sata_set_piomode, .set_piomode = pdc_sata_set_piomode,
.set_udmamode = pdc_sata_set_udmamode, .set_udmamode = pdc_sata_set_udmamode,
.tf_load = ata_tf_load_mmio, .tf_load = pdc_tf_load_mmio,
.tf_read = ata_tf_read_mmio, .tf_read = ata_tf_read_mmio,
.check_status = ata_check_status_mmio, .check_status = ata_check_status_mmio,
.exec_command = ata_exec_command_mmio, .exec_command = pdc_exec_command_mmio,
.phy_reset = sata_phy_reset, .phy_reset = sata_phy_reset,
.phy_config = pata_phy_config, /* not a typo */ .phy_config = pata_phy_config, /* not a typo */
.bmdma_start = pdc_dma_start, .bmdma_start = pdc_dma_start,
.fill_sg = ata_fill_sg, .fill_sg = pdc_fill_sg,
.eng_timeout = pdc_eng_timeout, .eng_timeout = pdc_eng_timeout,
.irq_handler = pdc_interrupt, .irq_handler = pdc_interrupt,
.scr_read = pdc_sata_scr_read, .scr_read = pdc_sata_scr_read,
.scr_write = pdc_sata_scr_write, .scr_write = pdc_sata_scr_write,
.port_start = pdc_port_start,
.port_stop = pdc_port_stop,
}; };
static struct ata_port_operations pdc_20621_ops = { static struct ata_port_operations pdc_20621_ops = {
.port_disable = ata_port_disable, .port_disable = ata_port_disable,
.set_piomode = pdc_sata_set_piomode, .set_piomode = pdc_sata_set_piomode,
.set_udmamode = pdc_sata_set_udmamode, .set_udmamode = pdc_sata_set_udmamode,
.tf_load = ata_tf_load_mmio, .tf_load = pdc_tf_load_mmio,
.tf_read = ata_tf_read_mmio, .tf_read = ata_tf_read_mmio,
.check_status = ata_check_status_mmio, .check_status = ata_check_status_mmio,
.exec_command = ata_exec_command_mmio, .exec_command = pdc_exec_command_mmio,
.phy_reset = pdc_20621_phy_reset, .phy_reset = pdc_20621_phy_reset,
.phy_config = pata_phy_config, /* not a typo */ .phy_config = pata_phy_config, /* not a typo */
.bmdma_start = pdc_dma_start, .bmdma_start = pdc20621_dma_start,
.fill_sg = ata_fill_sg, .fill_sg = pdc20621_fill_sg,
.eng_timeout = pdc_eng_timeout, .eng_timeout = pdc_eng_timeout,
.irq_handler = pdc_interrupt, .irq_handler = pdc20621_interrupt,
.port_start = pdc_port_start,
.port_stop = pdc_port_stop,
.host_stop = pdc20621_host_stop,
}; };
static struct ata_port_info pdc_port_info[] = { static struct ata_port_info pdc_port_info[] = {
...@@ -160,16 +208,16 @@ static struct ata_port_info pdc_port_info[] = { ...@@ -160,16 +208,16 @@ static struct ata_port_info pdc_port_info[] = {
static struct pci_device_id pdc_sata_pci_tbl[] = { static struct pci_device_id pdc_sata_pci_tbl[] = {
{ PCI_VENDOR_ID_PROMISE, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_PROMISE, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_2037x }, board_2037x },
{ PCI_VENDOR_ID_PROMISE, 0x3373, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_2037x },
{ PCI_VENDOR_ID_PROMISE, 0x3375, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_PROMISE, 0x3375, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_2037x }, board_2037x },
{ PCI_VENDOR_ID_PROMISE, 0x3318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_PROMISE, 0x3318, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20319 }, board_20319 },
{ PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20319 }, board_20319 },
#if 0 /* broken currently */
{ PCI_VENDOR_ID_PROMISE, 0x6622, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_PROMISE, 0x6622, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20621 }, board_20621 },
#endif
{ } /* terminate list */ { } /* terminate list */
}; };
...@@ -182,6 +230,60 @@ static struct pci_driver pdc_sata_pci_driver = { ...@@ -182,6 +230,60 @@ static struct pci_driver pdc_sata_pci_driver = {
}; };
static void pdc20621_host_stop(struct ata_host_set *host_set)
{
void *mmio = host_set->private_data;
assert(mmio != NULL);
iounmap(mmio);
}
static int pdc_port_start(struct ata_port *ap)
{
struct pci_dev *pdev = ap->host_set->pdev;
struct pdc_port_priv *pp;
int rc;
rc = ata_port_start(ap);
if (rc)
return rc;
pp = kmalloc(sizeof(*pp), GFP_KERNEL);
if (!pp) {
rc = -ENOMEM;
goto err_out;
}
pp->pkt = pci_alloc_consistent(pdev, 128, &pp->pkt_dma);
if (!pp->pkt) {
rc = -ENOMEM;
goto err_out_kfree;
}
ap->private_data = pp;
return 0;
err_out_kfree:
kfree(pp);
err_out:
ata_port_stop(ap);
return rc;
}
static void pdc_port_stop(struct ata_port *ap)
{
struct pci_dev *pdev = ap->host_set->pdev;
struct pdc_port_priv *pp = ap->private_data;
ap->private_data = NULL;
pci_free_consistent(pdev, 128, pp->pkt, pp->pkt_dma);
kfree(pp);
ata_port_stop(ap);
}
static void pdc_20621_phy_reset (struct ata_port *ap) static void pdc_20621_phy_reset (struct ata_port *ap)
{ {
VPRINTK("ENTER\n"); VPRINTK("ENTER\n");
...@@ -231,7 +333,8 @@ enum pdc_packet_bits { ...@@ -231,7 +333,8 @@ enum pdc_packet_bits {
PDC_REG_DEVCTL = (1 << 3) | (1 << 2) | (1 << 1), PDC_REG_DEVCTL = (1 << 3) | (1 << 2) | (1 << 1),
}; };
static inline void pdc_pkt_header(struct ata_taskfile *tf, dma_addr_t sg_table, static inline unsigned int pdc_pkt_header(struct ata_taskfile *tf,
dma_addr_t sg_table,
unsigned int devno, u8 *buf) unsigned int devno, u8 *buf)
{ {
u8 dev_reg; u8 dev_reg;
...@@ -273,9 +376,11 @@ static inline void pdc_pkt_header(struct ata_taskfile *tf, dma_addr_t sg_table, ...@@ -273,9 +376,11 @@ static inline void pdc_pkt_header(struct ata_taskfile *tf, dma_addr_t sg_table,
/* device control register */ /* device control register */
buf[14] = (1 << 5) | PDC_REG_DEVCTL; buf[14] = (1 << 5) | PDC_REG_DEVCTL;
buf[15] = tf->ctl; buf[15] = tf->ctl;
return 16; /* offset of next byte */
} }
static inline void pdc_pkt_footer(struct ata_taskfile *tf, u8 *buf, static inline unsigned int pdc_pkt_footer(struct ata_taskfile *tf, u8 *buf,
unsigned int i) unsigned int i)
{ {
if (tf->flags & ATA_TFLAG_DEVICE) { if (tf->flags & ATA_TFLAG_DEVICE) {
...@@ -286,19 +391,14 @@ static inline void pdc_pkt_footer(struct ata_taskfile *tf, u8 *buf, ...@@ -286,19 +391,14 @@ static inline void pdc_pkt_footer(struct ata_taskfile *tf, u8 *buf,
/* and finally the command itself; also includes end-of-pkt marker */ /* and finally the command itself; also includes end-of-pkt marker */
buf[i++] = (1 << 5) | PDC_LAST_REG | ATA_REG_CMD; buf[i++] = (1 << 5) | PDC_LAST_REG | ATA_REG_CMD;
buf[i++] = tf->command; buf[i++] = tf->command;
return i;
} }
static void pdc_prep_lba28(struct ata_taskfile *tf, dma_addr_t sg_table, static inline unsigned int pdc_prep_lba28(struct ata_taskfile *tf, u8 *buf, unsigned int i)
unsigned int devno, u8 *buf)
{ {
unsigned int i;
pdc_pkt_header(tf, sg_table, devno, buf);
/* the "(1 << 5)" should be read "(count << 5)" */ /* the "(1 << 5)" should be read "(count << 5)" */
i = 16;
/* ATA command block registers */ /* ATA command block registers */
buf[i++] = (1 << 5) | ATA_REG_FEATURE; buf[i++] = (1 << 5) | ATA_REG_FEATURE;
buf[i++] = tf->feature; buf[i++] = tf->feature;
...@@ -315,20 +415,13 @@ static void pdc_prep_lba28(struct ata_taskfile *tf, dma_addr_t sg_table, ...@@ -315,20 +415,13 @@ static void pdc_prep_lba28(struct ata_taskfile *tf, dma_addr_t sg_table,
buf[i++] = (1 << 5) | ATA_REG_LBAH; buf[i++] = (1 << 5) | ATA_REG_LBAH;
buf[i++] = tf->lbah; buf[i++] = tf->lbah;
pdc_pkt_footer(tf, buf, i); return i;
} }
static void pdc_prep_lba48(struct ata_taskfile *tf, dma_addr_t sg_table, static inline unsigned int pdc_prep_lba48(struct ata_taskfile *tf, u8 *buf, unsigned int i)
unsigned int devno, u8 *buf)
{ {
unsigned int i;
pdc_pkt_header(tf, sg_table, devno, buf);
/* the "(2 << 5)" should be read "(count << 5)" */ /* the "(2 << 5)" should be read "(count << 5)" */
i = 16;
/* ATA command block registers */ /* ATA command block registers */
buf[i++] = (2 << 5) | ATA_REG_FEATURE; buf[i++] = (2 << 5) | ATA_REG_FEATURE;
buf[i++] = tf->hob_feature; buf[i++] = tf->hob_feature;
...@@ -350,28 +443,461 @@ static void pdc_prep_lba48(struct ata_taskfile *tf, dma_addr_t sg_table, ...@@ -350,28 +443,461 @@ static void pdc_prep_lba48(struct ata_taskfile *tf, dma_addr_t sg_table,
buf[i++] = tf->hob_lbah; buf[i++] = tf->hob_lbah;
buf[i++] = tf->lbah; buf[i++] = tf->lbah;
pdc_pkt_footer(tf, buf, i); return i;
} }
static inline void __pdc_dma_complete (struct ata_port *ap, static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf,
struct ata_queued_cmd *qc) unsigned int portno,
unsigned int total_len)
{
u32 addr;
unsigned int dw = PDC_DIMM_APKT_PRD >> 2;
u32 *buf32 = (u32 *) buf;
/* output ATA packet S/G table */
addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA +
(PDC_DIMM_DATA_STEP * portno);
VPRINTK("ATA sg addr 0x%x, %d\n", addr, addr);
buf32[dw] = cpu_to_le32(addr);
buf32[dw + 1] = cpu_to_le32(total_len | ATA_PRD_EOT);
VPRINTK("ATA PSG @ %x == (0x%x, 0x%x)\n",
PDC_20621_DIMM_BASE +
(PDC_DIMM_WINDOW_STEP * portno) +
PDC_DIMM_APKT_PRD,
buf32[dw], buf32[dw + 1]);
}
static inline void pdc20621_host_sg(struct ata_taskfile *tf, u8 *buf,
unsigned int portno,
unsigned int total_len)
{
u32 addr;
unsigned int dw = PDC_DIMM_HPKT_PRD >> 2;
u32 *buf32 = (u32 *) buf;
/* output Host DMA packet S/G table */
addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA +
(PDC_DIMM_DATA_STEP * portno);
buf32[dw] = cpu_to_le32(addr);
buf32[dw + 1] = cpu_to_le32(total_len | ATA_PRD_EOT);
VPRINTK("HOST PSG @ %x == (0x%x, 0x%x)\n",
PDC_20621_DIMM_BASE +
(PDC_DIMM_WINDOW_STEP * portno) +
PDC_DIMM_HPKT_PRD,
buf32[dw], buf32[dw + 1]);
}
static inline unsigned int pdc20621_ata_pkt(struct ata_taskfile *tf,
unsigned int devno, u8 *buf,
unsigned int portno)
{
unsigned int i, dw;
u32 *buf32 = (u32 *) buf;
u8 dev_reg;
unsigned int dimm_sg = PDC_20621_DIMM_BASE +
(PDC_DIMM_WINDOW_STEP * portno) +
PDC_DIMM_APKT_PRD;
VPRINTK("ENTER, dimm_sg == 0x%x, %d\n", dimm_sg, dimm_sg);
i = PDC_DIMM_ATA_PKT;
/*
* Set up ATA packet
*/
if (tf->protocol == ATA_PROT_DMA_READ)
buf[i++] = PDC_PKT_READ;
else if (tf->protocol == ATA_PROT_NODATA)
buf[i++] = PDC_PKT_NODATA;
else
buf[i++] = 0;
buf[i++] = 0; /* reserved */
buf[i++] = portno + 1; /* seq. id */
buf[i++] = 0xff; /* delay seq. id */
/* dimm dma S/G, and next-pkt */
dw = i >> 2;
buf32[dw] = cpu_to_le32(dimm_sg);
buf32[dw + 1] = 0;
i += 8;
if (devno == 0)
dev_reg = ATA_DEVICE_OBS;
else
dev_reg = ATA_DEVICE_OBS | ATA_DEV1;
/* select device */
buf[i++] = (1 << 5) | PDC_PKT_CLEAR_BSY | ATA_REG_DEVICE;
buf[i++] = dev_reg;
/* device control register */
buf[i++] = (1 << 5) | PDC_REG_DEVCTL;
buf[i++] = tf->ctl;
return i;
}
static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf,
unsigned int portno)
{
unsigned int dw;
u32 tmp, *buf32 = (u32 *) buf;
unsigned int host_sg = PDC_20621_DIMM_BASE +
(PDC_DIMM_WINDOW_STEP * portno) +
PDC_DIMM_HOST_PRD;
unsigned int dimm_sg = PDC_20621_DIMM_BASE +
(PDC_DIMM_WINDOW_STEP * portno) +
PDC_DIMM_HPKT_PRD;
VPRINTK("ENTER, dimm_sg == 0x%x, %d\n", dimm_sg, dimm_sg);
VPRINTK("host_sg == 0x%x, %d\n", host_sg, host_sg);
dw = PDC_DIMM_HOST_PKT >> 2;
/*
* Set up Host DMA packet
*/
if (tf->protocol == ATA_PROT_DMA_READ)
tmp = PDC_PKT_READ;
else
tmp = 0;
tmp |= ((portno + 1 + 4) << 16); /* seq. id */
tmp |= (0xff << 24); /* delay seq. id */
buf32[dw + 0] = cpu_to_le32(tmp);
buf32[dw + 1] = cpu_to_le32(host_sg);
buf32[dw + 2] = cpu_to_le32(dimm_sg);
buf32[dw + 3] = 0;
VPRINTK("HOST PKT @ %x == (0x%x 0x%x 0x%x 0x%x)\n",
PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * portno) +
PDC_DIMM_HOST_PKT,
buf32[dw + 0],
buf32[dw + 1],
buf32[dw + 2],
buf32[dw + 3]);
}
static void pdc20621_fill_sg(struct ata_queued_cmd *qc)
{ {
void *dmactl = (void *) ap->ioaddr.cmd_addr + PDC_CTLSTAT; struct scatterlist *sg = qc->sg;
u32 val; struct ata_port *ap = qc->ap;
struct pdc_port_priv *pp = ap->private_data;
void *dimm_mmio = ap->host_set->private_data;
unsigned int portno = ap->port_no;
unsigned int i, last, idx, total_len = 0, sgt_len;
u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
VPRINTK("ata%u: ENTER\n", ap->id);
/*
* Build S/G table
*/
last = qc->n_elem;
idx = 0;
for (i = 0; i < last; i++) {
buf[idx++] = cpu_to_le32(sg[i].dma_address);
buf[idx++] = cpu_to_le32(sg[i].length);
total_len += sg[i].length;
}
buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT);
sgt_len = idx * 4;
/*
* Build ATA, host DMA packets
*/
pdc20621_host_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len);
pdc20621_host_pkt(&qc->tf, &pp->dimm_buf[0], portno);
pdc20621_ata_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len);
i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno);
/* clear DMA start/stop bit (bit 7) */ if (qc->tf.flags & ATA_TFLAG_LBA48)
val = readl(dmactl); i = pdc_prep_lba48(&qc->tf, &pp->dimm_buf[0], i);
writel(val & ~(1 << 7), dmactl); else
i = pdc_prep_lba28(&qc->tf, &pp->dimm_buf[0], i);
pdc_pkt_footer(&qc->tf, &pp->dimm_buf[0], i);
/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ /* copy three S/G tables and two packets to DIMM MMIO window */
ata_altstatus(ap); /* dummy read */ memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP),
&pp->dimm_buf, PDC_DIMM_HEADER_SZ);
memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP) +
PDC_DIMM_HOST_PRD,
&pp->dimm_buf[PDC_DIMM_HEADER_SZ], sgt_len);
VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len);
}
#ifdef DIRECT_HDMA
static void pdc20621_push_hdma(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct ata_host_set *host_set = ap->host_set;
unsigned int port_no = ap->port_no;
void *mmio = host_set->mmio_base;
unsigned int rw = (qc->flags & ATA_QCFLAG_WRITE);
u32 tmp;
unsigned int host_sg = PDC_20621_DIMM_BASE +
(PDC_DIMM_WINDOW_STEP * port_no) +
PDC_DIMM_HOST_PRD;
unsigned int dimm_sg = PDC_20621_DIMM_BASE +
(PDC_DIMM_WINDOW_STEP * port_no) +
PDC_DIMM_HPKT_PRD;
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
tmp = readl(mmio + PDC_HDMA_CTLSTAT) & 0xffffff00;
tmp |= port_no + 1 + 4; /* seq. ID */
if (!rw)
tmp |= (1 << 6); /* hdma data direction */
writel(tmp, mmio + PDC_HDMA_CTLSTAT); /* note: stops DMA, if active */
readl(mmio + PDC_HDMA_CTLSTAT); /* flush */
writel(host_sg, mmio + 0x108);
writel(dimm_sg, mmio + 0x10C);
writel(0, mmio + 0x128);
tmp |= (1 << 7);
writel(tmp, mmio + PDC_HDMA_CTLSTAT);
readl(mmio + PDC_HDMA_CTLSTAT); /* flush */
}
#endif
#ifdef ATA_VERBOSE_DEBUG
static void pdc20621_dump_hdma(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
unsigned int port_no = ap->port_no;
void *dimm_mmio = ap->host_set->private_data;
dimm_mmio += (port_no * PDC_DIMM_WINDOW_STEP);
dimm_mmio += PDC_DIMM_HOST_PKT;
printk(KERN_ERR "HDMA[0] == 0x%08X\n", readl(dimm_mmio));
printk(KERN_ERR "HDMA[1] == 0x%08X\n", readl(dimm_mmio + 4));
printk(KERN_ERR "HDMA[2] == 0x%08X\n", readl(dimm_mmio + 8));
printk(KERN_ERR "HDMA[3] == 0x%08X\n", readl(dimm_mmio + 12));
}
#else
static inline void pdc20621_dump_hdma(struct ata_queued_cmd *qc) { }
#endif /* ATA_VERBOSE_DEBUG */
static void pdc20621_dma_start(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct ata_host_set *host_set = ap->host_set;
unsigned int port_no = ap->port_no;
void *mmio = host_set->mmio_base;
unsigned int rw = (qc->flags & ATA_QCFLAG_WRITE);
u8 seq = (u8) (port_no + 1);
unsigned int doing_hdma = 0, port_ofs;
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
VPRINTK("ata%u: ENTER\n", ap->id);
port_ofs = PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no);
/* if writing, we (1) DMA to DIMM, then (2) do ATA command */
if (rw) {
doing_hdma = 1;
seq += 4;
}
wmb(); /* flush PRD, pkt writes */
writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
if (doing_hdma) {
pdc20621_dump_hdma(qc);
#ifdef DIRECT_HDMA
pdc20621_push_hdma(qc);
#else
writel(port_ofs + PDC_DIMM_HOST_PKT,
mmio + PDC_HDMA_PKT_SUBMIT);
#endif
VPRINTK("submitted ofs 0x%x (%u), seq %u\n",
port_ofs + PDC_DIMM_HOST_PKT,
port_ofs + PDC_DIMM_HOST_PKT,
seq);
} else {
writel(port_ofs + PDC_DIMM_ATA_PKT,
(void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
VPRINTK("submitted ofs 0x%x (%u), seq %u\n",
port_ofs + PDC_DIMM_ATA_PKT,
port_ofs + PDC_DIMM_ATA_PKT,
seq);
}
}
static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
struct ata_queued_cmd *qc,
unsigned int doing_hdma,
void *mmio)
{
unsigned int port_no = ap->port_no;
unsigned int port_ofs =
PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no);
u8 status;
unsigned int handled = 0;
VPRINTK("ENTER\n");
switch (qc->tf.protocol) {
case ATA_PROT_DMA_READ:
/* step two - DMA from DIMM to host */
if (doing_hdma) {
VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
pdc_dma_complete(ap, qc);
}
/* step one - exec ATA command */
else {
u8 seq = (u8) (port_no + 1 + 4);
VPRINTK("ata%u: read ata, 0x%x 0x%x\n", ap->id,
readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
/* submit hdma pkt */
pdc20621_dump_hdma(qc);
writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
#ifdef DIRECT_HDMA
pdc20621_push_hdma(qc);
#else
writel(port_ofs + PDC_DIMM_HOST_PKT,
mmio + PDC_HDMA_PKT_SUBMIT);
#endif
}
handled = 1;
break;
case ATA_PROT_DMA_WRITE:
/* step one - DMA from host to DIMM */
if (doing_hdma) {
u8 seq = (u8) (port_no + 1);
VPRINTK("ata%u: write hdma, 0x%x 0x%x\n", ap->id,
readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
/* submit ata pkt */
writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
writel(port_ofs + PDC_DIMM_ATA_PKT,
(void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
}
/* step two - execute ATA command */
else {
VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
pdc_dma_complete(ap, qc);
}
handled = 1;
break;
case ATA_PROT_NODATA: /* command completion, but no data xfer */
status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
ata_qc_complete(qc, status, 0);
handled = 1;
break;
default:
ap->stats.idle_irq++;
break;
}
return handled;
}
static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
{
struct ata_host_set *host_set = dev_instance;
struct ata_port *ap;
u32 mask = 0;
unsigned int i, tmp, port_no;
unsigned int handled = 0;
void *mmio_base;
VPRINTK("ENTER\n");
if (!host_set || !host_set->mmio_base) {
VPRINTK("QUICK EXIT\n");
return IRQ_NONE;
}
mmio_base = host_set->mmio_base;
/* reading should also clear interrupts */
mmio_base += PDC_CHIP0_OFS;
mask = readl(mmio_base + PDC_20621_SEQMASK);
VPRINTK("mask == 0x%x\n", mask);
if (mask == 0xffffffff) {
VPRINTK("QUICK EXIT 2\n");
return IRQ_NONE;
}
mask &= 0xf; /* only 16 tags possible */
if (!mask) {
VPRINTK("QUICK EXIT 3\n");
return IRQ_NONE;
}
spin_lock_irq(&host_set->lock);
for (i = 1; i < 9; i++) {
port_no = i - 1;
if (port_no > 3)
port_no -= 4;
if (port_no >= host_set->n_ports)
ap = NULL;
else
ap = host_set->ports[port_no];
tmp = mask & (1 << i);
VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp);
if (tmp && ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc && ((qc->flags & ATA_QCFLAG_POLL) == 0))
handled += pdc20621_host_intr(ap, qc, (i > 4),
mmio_base);
}
}
spin_unlock_irq(&host_set->lock);
VPRINTK("mask == 0x%x\n", mask);
VPRINTK("EXIT\n");
return IRQ_RETVAL(handled);
}
static void pdc_fill_sg(struct ata_queued_cmd *qc)
{
struct pdc_port_priv *pp = qc->ap->private_data;
unsigned int i;
VPRINTK("ENTER\n");
ata_fill_sg(qc);
i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma, qc->dev->devno, pp->pkt);
if (qc->tf.flags & ATA_TFLAG_LBA48)
i = pdc_prep_lba48(&qc->tf, pp->pkt, i);
else
i = pdc_prep_lba28(&qc->tf, pp->pkt, i);
pdc_pkt_footer(&qc->tf, pp->pkt, i);
} }
static inline void pdc_dma_complete (struct ata_port *ap, static inline void pdc_dma_complete (struct ata_port *ap,
struct ata_queued_cmd *qc) struct ata_queued_cmd *qc)
{ {
__pdc_dma_complete(ap, qc);
/* get drive status; clear intr; complete txn */ /* get drive status; clear intr; complete txn */
ata_qc_complete(ata_qc_from_tag(ap, ap->active_tag), ata_qc_complete(ata_qc_from_tag(ap, ap->active_tag),
ata_wait_idle(ap), 0); ata_wait_idle(ap), 0);
...@@ -395,7 +921,6 @@ static void pdc_eng_timeout(struct ata_port *ap) ...@@ -395,7 +921,6 @@ static void pdc_eng_timeout(struct ata_port *ap)
case ATA_PROT_DMA_READ: case ATA_PROT_DMA_READ:
case ATA_PROT_DMA_WRITE: case ATA_PROT_DMA_WRITE:
printk(KERN_ERR "ata%u: DMA timeout\n", ap->id); printk(KERN_ERR "ata%u: DMA timeout\n", ap->id);
__pdc_dma_complete(ap, qc);
ata_qc_complete(ata_qc_from_tag(ap, ap->active_tag), ata_qc_complete(ata_qc_from_tag(ap, ap->active_tag),
ata_wait_idle(ap) | ATA_ERR, 0); ata_wait_idle(ap) | ATA_ERR, 0);
break; break;
...@@ -457,7 +982,7 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r ...@@ -457,7 +982,7 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
struct ata_port *ap; struct ata_port *ap;
u32 mask = 0; u32 mask = 0;
unsigned int i, tmp; unsigned int i, tmp;
unsigned int handled = 0, have_20621 = 0; unsigned int handled = 0;
void *mmio_base; void *mmio_base;
VPRINTK("ENTER\n"); VPRINTK("ENTER\n");
...@@ -469,21 +994,8 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r ...@@ -469,21 +994,8 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
mmio_base = host_set->mmio_base; mmio_base = host_set->mmio_base;
for (i = 0; i < host_set->n_ports; i++) {
ap = host_set->ports[i];
if (ap && (ap->flags & PDC_FLAG_20621)) {
have_20621 = 1;
break;
}
}
/* reading should also clear interrupts */ /* reading should also clear interrupts */
if (have_20621) {
mmio_base += PDC_CHIP0_OFS;
mask = readl(mmio_base + PDC_20621_SEQMASK);
} else {
mask = readl(mmio_base + PDC_INT_SEQMASK); mask = readl(mmio_base + PDC_INT_SEQMASK);
}
if (mask == 0xffffffff) { if (mask == 0xffffffff) {
VPRINTK("QUICK EXIT 2\n"); VPRINTK("QUICK EXIT 2\n");
...@@ -520,56 +1032,35 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r ...@@ -520,56 +1032,35 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
static void pdc_dma_start(struct ata_queued_cmd *qc) static void pdc_dma_start(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
struct ata_host_set *host_set = ap->host_set; struct pdc_port_priv *pp = ap->private_data;
unsigned int port_no = ap->port_no; unsigned int port_no = ap->port_no;
void *mmio = host_set->mmio_base;
void *dmactl = (void *) ap->ioaddr.cmd_addr + PDC_CTLSTAT;
unsigned int rw = (qc->flags & ATA_QCFLAG_WRITE);
u32 val;
u8 seq = (u8) (port_no + 1); u8 seq = (u8) (port_no + 1);
wmb(); /* flush writes made to PRD table in DMA memory */ VPRINTK("ENTER, ap %p\n", ap);
if (ap->flags & PDC_FLAG_20621)
mmio += PDC_CHIP0_OFS;
VPRINTK("ENTER, ap %p, mmio %p\n", ap, mmio);
/* indicate where our S/G table is to chip */
writel(ap->prd_dma, (void *) ap->ioaddr.cmd_addr + PDC_PRD_TBL);
/* clear dma start bit (paranoia), clear intr seq id (paranoia), writel(0x00000001, ap->host_set->mmio_base + (seq * 4));
* set DMA direction (bit 6 == from chip -> drive)
*/
val = readl(dmactl);
VPRINTK("val == %x\n", val);
val &= ~(1 << 7); /* clear dma start/stop bit */
if (rw) /* set/clear dma direction bit */
val |= (1 << 6);
else
val &= ~(1 << 6);
if (qc->tf.ctl & ATA_NIEN) /* set/clear irq-mask bit */
val |= (1 << 10);
else
val &= ~(1 << 10);
writel(val, dmactl);
val = readl(dmactl);
VPRINTK("val == %x\n", val);
/* FIXME: clear any intr status bits here? */ pp->pkt[2] = seq;
wmb(); /* flush PRD, pkt writes */
writel(pp->pkt_dma, (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
}
ata_exec_command_mmio(ap, &qc->tf); static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
{
if ((tf->protocol != ATA_PROT_DMA_READ) &&
(tf->protocol != ATA_PROT_DMA_WRITE))
ata_tf_load_mmio(ap, tf);
}
VPRINTK("FIVE\n");
if (ap->flags & PDC_FLAG_20621)
writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
else
writel(0x00000001, mmio + (seq * 4));
/* start host DMA transaction */ static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
writel(val | seq | (1 << 7), dmactl); {
if ((tf->protocol != ATA_PROT_DMA_READ) &&
(tf->protocol != ATA_PROT_DMA_WRITE))
ata_exec_command_mmio(ap, tf);
} }
static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base) static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base)
{ {
port->cmd_addr = base; port->cmd_addr = base;
...@@ -586,6 +1077,32 @@ static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base) ...@@ -586,6 +1077,32 @@ static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base)
static void pdc_20621_init(struct ata_probe_ent *pe) static void pdc_20621_init(struct ata_probe_ent *pe)
{ {
u32 tmp;
void *mmio = pe->mmio_base;
mmio += PDC_CHIP0_OFS;
/*
* Select page 0x40 for our 32k DIMM window
*/
tmp = readl(mmio + PDC_20621_DIMM_WINDOW) & 0xffff0000;
tmp |= PDC_PAGE_WINDOW; /* page 40h; arbitrarily selected */
writel(tmp, mmio + PDC_20621_DIMM_WINDOW);
/*
* Reset Host DMA
*/
tmp = readl(mmio + PDC_HDMA_CTLSTAT);
tmp |= PDC_HDMA_RESET;
writel(tmp, mmio + PDC_HDMA_CTLSTAT);
readl(mmio + PDC_HDMA_CTLSTAT); /* flush */
udelay(10);
tmp = readl(mmio + PDC_HDMA_CTLSTAT);
tmp &= ~PDC_HDMA_RESET;
writel(tmp, mmio + PDC_HDMA_CTLSTAT);
readl(mmio + PDC_HDMA_CTLSTAT); /* flush */
} }
static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
...@@ -629,8 +1146,9 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * ...@@ -629,8 +1146,9 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
static int printed_version; static int printed_version;
struct ata_probe_ent *probe_ent = NULL; struct ata_probe_ent *probe_ent = NULL;
unsigned long base; unsigned long base;
void *mmio_base; void *mmio_base, *dimm_mmio = NULL;
unsigned int board_idx = (unsigned int) ent->driver_data; unsigned int board_idx = (unsigned int) ent->driver_data;
unsigned int have_20621 = (board_idx == board_20621);
int rc; int rc;
if (!printed_version++) if (!printed_version++)
...@@ -670,6 +1188,15 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * ...@@ -670,6 +1188,15 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
} }
base = (unsigned long) mmio_base; base = (unsigned long) mmio_base;
if (have_20621) {
dimm_mmio = ioremap(pci_resource_start(pdev, 4),
pci_resource_len(pdev, 4));
if (!dimm_mmio) {
rc = -ENOMEM;
goto err_out_iounmap;
}
}
probe_ent->sht = pdc_port_info[board_idx].sht; probe_ent->sht = pdc_port_info[board_idx].sht;
probe_ent->host_flags = pdc_port_info[board_idx].host_flags; probe_ent->host_flags = pdc_port_info[board_idx].host_flags;
probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask; probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask;
...@@ -680,8 +1207,10 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * ...@@ -680,8 +1207,10 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
probe_ent->irq_flags = SA_SHIRQ; probe_ent->irq_flags = SA_SHIRQ;
probe_ent->mmio_base = mmio_base; probe_ent->mmio_base = mmio_base;
if (board_idx == board_20621) if (have_20621) {
probe_ent->private_data = dimm_mmio;
base += PDC_CHIP0_OFS; base += PDC_CHIP0_OFS;
}
pdc_sata_setup_port(&probe_ent->port[0], base + 0x200); pdc_sata_setup_port(&probe_ent->port[0], base + 0x200);
probe_ent->port[0].scr_addr = base + 0x400; probe_ent->port[0].scr_addr = base + 0x400;
...@@ -712,15 +1241,10 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * ...@@ -712,15 +1241,10 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
pci_set_master(pdev); pci_set_master(pdev);
/* initialize adapter */ /* initialize adapter */
switch (board_idx) { if (have_20621)
case board_20621:
pdc_20621_init(probe_ent); pdc_20621_init(probe_ent);
break; else
default:
pdc_host_init(board_idx, probe_ent); pdc_host_init(board_idx, probe_ent);
break;
}
/* FIXME: check ata_device_add return value */ /* FIXME: check ata_device_add return value */
ata_device_add(probe_ent); ata_device_add(probe_ent);
...@@ -728,6 +1252,8 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * ...@@ -728,6 +1252,8 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
return 0; return 0;
err_out_iounmap:
iounmap(mmio_base);
err_out_free_ent: err_out_free_ent:
kfree(probe_ent); kfree(probe_ent);
err_out_regions: err_out_regions:
...@@ -738,7 +1264,6 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * ...@@ -738,7 +1264,6 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
} }
static int __init pdc_sata_init(void) static int __init pdc_sata_init(void)
{ {
int rc; int rc;
......
...@@ -106,6 +106,8 @@ static struct ata_port_operations sil_ops = { ...@@ -106,6 +106,8 @@ static struct ata_port_operations sil_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.scr_read = sil_scr_read, .scr_read = sil_scr_read,
.scr_write = sil_scr_write, .scr_write = sil_scr_write,
.port_start = ata_port_start,
.port_stop = ata_port_stop,
}; };
static struct ata_port_info sil_port_info[] = { static struct ata_port_info sil_port_info[] = {
......
...@@ -235,6 +235,8 @@ static struct ata_port_operations k2_sata_ops = { ...@@ -235,6 +235,8 @@ static struct ata_port_operations k2_sata_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.scr_read = k2_sata_scr_read, .scr_read = k2_sata_scr_read,
.scr_write = k2_sata_scr_write, .scr_write = k2_sata_scr_write,
.port_start = ata_port_start,
.port_stop = ata_port_stop,
}; };
......
...@@ -98,6 +98,9 @@ static struct ata_port_operations svia_sata_ops = { ...@@ -98,6 +98,9 @@ static struct ata_port_operations svia_sata_ops = {
.eng_timeout = ata_eng_timeout, .eng_timeout = ata_eng_timeout,
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.port_start = ata_port_start,
.port_stop = ata_port_stop,
}; };
static struct ata_port_info svia_port_info[] = { static struct ata_port_info svia_port_info[] = {
......
...@@ -547,6 +547,8 @@ int minix_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *sta ...@@ -547,6 +547,8 @@ int minix_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *sta
*/ */
void minix_truncate(struct inode * inode) void minix_truncate(struct inode * inode)
{ {
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)))
return;
if (INODE_VERSION(inode) == MINIX_V1) if (INODE_VERSION(inode) == MINIX_V1)
V1_minix_truncate(inode); V1_minix_truncate(inode);
else else
......
...@@ -207,6 +207,7 @@ struct ata_probe_ent { ...@@ -207,6 +207,7 @@ struct ata_probe_ent {
unsigned int irq_flags; unsigned int irq_flags;
unsigned long host_flags; unsigned long host_flags;
void *mmio_base; void *mmio_base;
void *private_data;
}; };
struct ata_host_set { struct ata_host_set {
...@@ -215,6 +216,7 @@ struct ata_host_set { ...@@ -215,6 +216,7 @@ struct ata_host_set {
unsigned long irq; unsigned long irq;
void *mmio_base; void *mmio_base;
unsigned int n_ports; unsigned int n_ports;
void *private_data;
struct ata_port * ports[0]; struct ata_port * ports[0];
}; };
...@@ -264,6 +266,8 @@ struct ata_queued_cmd { ...@@ -264,6 +266,8 @@ struct ata_queued_cmd {
ata_qc_cb_t callback; ata_qc_cb_t callback;
struct semaphore sem; struct semaphore sem;
void *private_data;
}; };
struct ata_host_stats { struct ata_host_stats {
...@@ -333,6 +337,8 @@ struct ata_port { ...@@ -333,6 +337,8 @@ struct ata_port {
struct semaphore thr_sem; struct semaphore thr_sem;
struct timer_list thr_timer; struct timer_list thr_timer;
unsigned long thr_timeout; unsigned long thr_timeout;
void *private_data;
}; };
struct ata_port_operations { struct ata_port_operations {
...@@ -363,6 +369,11 @@ struct ata_port_operations { ...@@ -363,6 +369,11 @@ struct ata_port_operations {
u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg); u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
void (*scr_write) (struct ata_port *ap, unsigned int sc_reg, void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
u32 val); u32 val);
int (*port_start) (struct ata_port *ap);
void (*port_stop) (struct ata_port *ap);
void (*host_stop) (struct ata_host_set *host_set);
}; };
struct ata_port_info { struct ata_port_info {
...@@ -406,6 +417,8 @@ extern u8 ata_check_status_pio(struct ata_port *ap); ...@@ -406,6 +417,8 @@ extern u8 ata_check_status_pio(struct ata_port *ap);
extern u8 ata_check_status_mmio(struct ata_port *ap); extern u8 ata_check_status_mmio(struct ata_port *ap);
extern void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf); extern void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf);
extern void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf); extern void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
extern int ata_port_start (struct ata_port *ap);
extern void ata_port_stop (struct ata_port *ap);
extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs); extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
extern void ata_fill_sg(struct ata_queued_cmd *qc); extern void ata_fill_sg(struct ata_queued_cmd *qc);
extern void ata_bmdma_start_mmio (struct ata_queued_cmd *qc); extern void ata_bmdma_start_mmio (struct ata_queued_cmd *qc);
......
...@@ -440,6 +440,7 @@ ...@@ -440,6 +440,7 @@
#define PCI_DEVICE_ID_AMD_LANCE 0x2000 #define PCI_DEVICE_ID_AMD_LANCE 0x2000
#define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001 #define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001
#define PCI_DEVICE_ID_AMD_SCSI 0x2020 #define PCI_DEVICE_ID_AMD_SCSI 0x2020
#define PCI_DEVICE_ID_AMD_SERENADE 0x36c0
#define PCI_DEVICE_ID_AMD_FE_GATE_7006 0x7006 #define PCI_DEVICE_ID_AMD_FE_GATE_7006 0x7006
#define PCI_DEVICE_ID_AMD_FE_GATE_7007 0x7007 #define PCI_DEVICE_ID_AMD_FE_GATE_7007 0x7007
#define PCI_DEVICE_ID_AMD_FE_GATE_700C 0x700C #define PCI_DEVICE_ID_AMD_FE_GATE_700C 0x700C
...@@ -581,12 +582,14 @@ ...@@ -581,12 +582,14 @@
#define PCI_DEVICE_ID_SI_651 0x0651 #define PCI_DEVICE_ID_SI_651 0x0651
#define PCI_DEVICE_ID_SI_652 0x0652 #define PCI_DEVICE_ID_SI_652 0x0652
#define PCI_DEVICE_ID_SI_655 0x0655 #define PCI_DEVICE_ID_SI_655 0x0655
#define PCI_DEVICE_ID_SI_661 0x0661
#define PCI_DEVICE_ID_SI_730 0x0730 #define PCI_DEVICE_ID_SI_730 0x0730
#define PCI_DEVICE_ID_SI_733 0x0733 #define PCI_DEVICE_ID_SI_733 0x0733
#define PCI_DEVICE_ID_SI_630_VGA 0x6300 #define PCI_DEVICE_ID_SI_630_VGA 0x6300
#define PCI_DEVICE_ID_SI_730_VGA 0x7300 #define PCI_DEVICE_ID_SI_730_VGA 0x7300
#define PCI_DEVICE_ID_SI_735 0x0735 #define PCI_DEVICE_ID_SI_735 0x0735
#define PCI_DEVICE_ID_SI_740 0x0740 #define PCI_DEVICE_ID_SI_740 0x0740
#define PCI_DEVICE_ID_SI_741 0x0741
#define PCI_DEVICE_ID_SI_745 0x0745 #define PCI_DEVICE_ID_SI_745 0x0745
#define PCI_DEVICE_ID_SI_746 0x0746 #define PCI_DEVICE_ID_SI_746 0x0746
#define PCI_DEVICE_ID_SI_748 0x0748 #define PCI_DEVICE_ID_SI_748 0x0748
...@@ -594,6 +597,7 @@ ...@@ -594,6 +597,7 @@
#define PCI_DEVICE_ID_SI_751 0x0751 #define PCI_DEVICE_ID_SI_751 0x0751
#define PCI_DEVICE_ID_SI_752 0x0752 #define PCI_DEVICE_ID_SI_752 0x0752
#define PCI_DEVICE_ID_SI_755 0x0755 #define PCI_DEVICE_ID_SI_755 0x0755
#define PCI_DEVICE_ID_SI_760 0x0760
#define PCI_DEVICE_ID_SI_900 0x0900 #define PCI_DEVICE_ID_SI_900 0x0900
#define PCI_DEVICE_ID_SI_961 0x0961 #define PCI_DEVICE_ID_SI_961 0x0961
#define PCI_DEVICE_ID_SI_962 0x0962 #define PCI_DEVICE_ID_SI_962 0x0962
...@@ -1023,7 +1027,13 @@ ...@@ -1023,7 +1027,13 @@
#define PCI_DEVICE_ID_NVIDIA_VTNT2 0x002C #define PCI_DEVICE_ID_NVIDIA_VTNT2 0x002C
#define PCI_DEVICE_ID_NVIDIA_UVTNT2 0x002D #define PCI_DEVICE_ID_NVIDIA_UVTNT2 0x002D
#define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE 0x0065 #define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE 0x0065
#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE 0x0085
#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA 0x008e
#define PCI_DEVICE_ID_NVIDIA_ITNT2 0x00A0 #define PCI_DEVICE_ID_NVIDIA_ITNT2 0x00A0
#define PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE 0x00d5
#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA 0x00e3
#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE 0x00e5
#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2 0x00ee
#define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR 0x0100 #define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR 0x0100
#define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR 0x0101 #define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR 0x0101
#define PCI_DEVICE_ID_NVIDIA_QUADRO 0x0103 #define PCI_DEVICE_ID_NVIDIA_QUADRO 0x0103
......
...@@ -249,6 +249,7 @@ static struct atalk_iface *atif_add_device(struct net_device *dev, ...@@ -249,6 +249,7 @@ static struct atalk_iface *atif_add_device(struct net_device *dev,
if (!iface) if (!iface)
goto out; goto out;
memset(iface, 0, sizeof(*iface));
dev_hold(dev); dev_hold(dev);
iface->dev = dev; iface->dev = dev;
dev->atalk_ptr = iface; dev->atalk_ptr = iface;
...@@ -580,6 +581,7 @@ static int atrtr_create(struct rtentry *r, struct net_device *devhint) ...@@ -580,6 +581,7 @@ static int atrtr_create(struct rtentry *r, struct net_device *devhint)
retval = -ENOBUFS; retval = -ENOBUFS;
if (!rt) if (!rt)
goto out; goto out;
memset(rt, 0, sizeof(*rt));
rt->next = atalk_routes; rt->next = atalk_routes;
atalk_routes = rt; atalk_routes = rt;
...@@ -937,9 +939,13 @@ static unsigned long atalk_sum_partial(const unsigned char *data, ...@@ -937,9 +939,13 @@ static unsigned long atalk_sum_partial(const unsigned char *data,
{ {
/* This ought to be unwrapped neatly. I'll trust gcc for now */ /* This ought to be unwrapped neatly. I'll trust gcc for now */
while (len--) { while (len--) {
sum += *data++; sum += *data;
sum <<= 1; sum <<= 1;
sum = ((sum >> 16) + sum) & 0xFFFF; if (sum & 0x10000) {
sum++;
sum &= 0xffff;
}
data++;
} }
return sum; return sum;
} }
...@@ -1048,6 +1054,7 @@ static int atalk_create(struct socket *sock, int protocol) ...@@ -1048,6 +1054,7 @@ static int atalk_create(struct socket *sock, int protocol)
at = at_sk(sk) = kmalloc(sizeof(*at), GFP_KERNEL); at = at_sk(sk) = kmalloc(sizeof(*at), GFP_KERNEL);
if (!at) if (!at)
goto outsk; goto outsk;
memset(at, 0, sizeof(*at));
rc = 0; rc = 0;
sock->ops = &atalk_dgram_ops; sock->ops = &atalk_dgram_ops;
sock_init_data(sock, sk); sock_init_data(sock, sk);
......
...@@ -3049,7 +3049,7 @@ static int __init net_dev_init(void) ...@@ -3049,7 +3049,7 @@ static int __init net_dev_init(void)
return rc; return rc;
} }
fs_initcall(net_dev_init); subsys_initcall(net_dev_init);
EXPORT_SYMBOL(__dev_get); EXPORT_SYMBOL(__dev_get);
EXPORT_SYMBOL(__dev_get_by_flags); EXPORT_SYMBOL(__dev_get_by_flags);
......
...@@ -187,7 +187,7 @@ static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb) ...@@ -187,7 +187,7 @@ static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb)
sk_for_each_bound(sk2, node, &tb->owners) { sk_for_each_bound(sk2, node, &tb->owners) {
if (sk != sk2 && if (sk != sk2 &&
!ipv6_only_sock(sk2) && !tcp_v6_ipv6only(sk2) &&
(!sk->sk_bound_dev_if || (!sk->sk_bound_dev_if ||
!sk2->sk_bound_dev_if || !sk2->sk_bound_dev_if ||
sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) { sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) {
......
...@@ -326,7 +326,6 @@ void __ipxitf_down(struct ipx_interface *intrfc) ...@@ -326,7 +326,6 @@ void __ipxitf_down(struct ipx_interface *intrfc)
if (intrfc->if_dev) if (intrfc->if_dev)
dev_put(intrfc->if_dev); dev_put(intrfc->if_dev);
kfree(intrfc); kfree(intrfc);
module_put(THIS_MODULE);
} }
void ipxitf_down(struct ipx_interface *intrfc) void ipxitf_down(struct ipx_interface *intrfc)
...@@ -358,6 +357,17 @@ static int ipxitf_device_event(struct notifier_block *notifier, ...@@ -358,6 +357,17 @@ static int ipxitf_device_event(struct notifier_block *notifier,
return NOTIFY_DONE; return NOTIFY_DONE;
} }
static __exit void ipxitf_cleanup(void)
{
struct ipx_interface *i, *tmp;
spin_lock_bh(&ipx_interfaces_lock);
list_for_each_entry_safe(i, tmp, &ipx_interfaces, node)
__ipxitf_put(i);
spin_unlock_bh(&ipx_interfaces_lock);
}
static void ipxitf_def_skb_handler(struct sock *sock, struct sk_buff *skb) static void ipxitf_def_skb_handler(struct sock *sock, struct sk_buff *skb)
{ {
if (sock_queue_rcv_skb(sock, skb) < 0) if (sock_queue_rcv_skb(sock, skb) < 0)
...@@ -888,7 +898,6 @@ static struct ipx_interface *ipxitf_alloc(struct net_device *dev, __u32 netnum, ...@@ -888,7 +898,6 @@ static struct ipx_interface *ipxitf_alloc(struct net_device *dev, __u32 netnum,
INIT_HLIST_HEAD(&intrfc->if_sklist); INIT_HLIST_HEAD(&intrfc->if_sklist);
atomic_set(&intrfc->refcnt, 1); atomic_set(&intrfc->refcnt, 1);
spin_lock_init(&intrfc->if_sklist_lock); spin_lock_init(&intrfc->if_sklist_lock);
__module_get(THIS_MODULE);
} }
return intrfc; return intrfc;
...@@ -1979,21 +1988,13 @@ static int __init ipx_init(void) ...@@ -1979,21 +1988,13 @@ static int __init ipx_init(void)
static void __exit ipx_proto_finito(void) static void __exit ipx_proto_finito(void)
{ {
/*
* No need to worry about having anything on the ipx_interfaces list,
* when a interface is created we increment the module usage count, so
* the module will only be unloaded when there are no more interfaces
*/
if (unlikely(!list_empty(&ipx_interfaces)))
BUG();
if (unlikely(!list_empty(&ipx_routes)))
BUG();
ipx_proc_exit(); ipx_proc_exit();
ipx_unregister_sysctl(); ipx_unregister_sysctl();
unregister_netdevice_notifier(&ipx_dev_notifier); unregister_netdevice_notifier(&ipx_dev_notifier);
ipxitf_cleanup();
unregister_snap_client(pSNAP_datalink); unregister_snap_client(pSNAP_datalink);
pSNAP_datalink = NULL; pSNAP_datalink = NULL;
......
...@@ -250,40 +250,18 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) ...@@ -250,40 +250,18 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
if (!sk->sk_zapped) if (!sk->sk_zapped)
goto out; goto out;
/* bind to a specific sap, optional. */ rc = -ENODEV;
if (!addr->sllc_sap) { llc->dev = dev_getfirstbyhwtype(addr->sllc_arphrd);
if (!llc->dev)
goto out;
rc = -EUSERS; rc = -EUSERS;
addr->sllc_sap = llc_ui_autoport(); llc->laddr.lsap = llc_ui_autoport();
if (!addr->sllc_sap) if (!llc->laddr.lsap)
goto out; goto out;
}
sap = llc_sap_find(addr->sllc_sap);
if (!sap) {
sap = llc_sap_open(addr->sllc_sap, NULL);
rc = -EBUSY; /* some other network layer is using the sap */ rc = -EBUSY; /* some other network layer is using the sap */
sap = llc_sap_open(llc->laddr.lsap, NULL);
if (!sap) if (!sap)
goto out; goto out;
} else {
struct llc_addr laddr, daddr;
struct sock *ask;
memset(&laddr, 0, sizeof(laddr));
memset(&daddr, 0, sizeof(daddr));
/*
* FIXME: check if the the address is multicast,
* only SOCK_DGRAM can do this.
*/
memcpy(laddr.mac, addr->sllc_mac, IFHWADDRLEN);
laddr.lsap = addr->sllc_sap;
rc = -EADDRINUSE; /* mac + sap clash. */
ask = llc_lookup_established(sap, &daddr, &laddr);
if (ask) {
sock_put(ask);
goto out;
}
}
llc->laddr.lsap = addr->sllc_sap;
if (llc->dev)
memcpy(llc->laddr.mac, llc->dev->dev_addr, IFHWADDRLEN); memcpy(llc->laddr.mac, llc->dev->dev_addr, IFHWADDRLEN);
memcpy(&llc->addr, addr, sizeof(llc->addr)); memcpy(&llc->addr, addr, sizeof(llc->addr));
/* assign new connection to its SAP */ /* assign new connection to its SAP */
...@@ -315,6 +293,8 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) ...@@ -315,6 +293,8 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
{ {
struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr; struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr;
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct llc_opt *llc = llc_sk(sk);
struct llc_sap *sap;
int rc = -EINVAL; int rc = -EINVAL;
dprintk("%s: binding %02X\n", __FUNCTION__, addr->sllc_sap); dprintk("%s: binding %02X\n", __FUNCTION__, addr->sllc_sap);
...@@ -323,8 +303,43 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) ...@@ -323,8 +303,43 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
rc = -EAFNOSUPPORT; rc = -EAFNOSUPPORT;
if (addr->sllc_family != AF_LLC) if (addr->sllc_family != AF_LLC)
goto out; goto out;
/* use autobind, to avoid code replication. */ if (!addr->sllc_sap) {
rc = llc_ui_autobind(sock, addr); rc = -EUSERS;
addr->sllc_sap = llc_ui_autoport();
if (!addr->sllc_sap)
goto out;
}
sap = llc_sap_find(addr->sllc_sap);
if (!sap) {
sap = llc_sap_open(addr->sllc_sap, NULL);
rc = -EBUSY; /* some other network layer is using the sap */
if (!sap)
goto out;
} else {
struct llc_addr laddr, daddr;
struct sock *ask;
memset(&laddr, 0, sizeof(laddr));
memset(&daddr, 0, sizeof(daddr));
/*
* FIXME: check if the the address is multicast,
* only SOCK_DGRAM can do this.
*/
memcpy(laddr.mac, addr->sllc_mac, IFHWADDRLEN);
laddr.lsap = addr->sllc_sap;
rc = -EADDRINUSE; /* mac + sap clash. */
ask = llc_lookup_established(sap, &daddr, &laddr);
if (ask) {
sock_put(ask);
goto out;
}
}
llc->laddr.lsap = addr->sllc_sap;
memcpy(llc->laddr.mac, addr->sllc_mac, IFHWADDRLEN);
memcpy(&llc->addr, addr, sizeof(llc->addr));
/* assign new connection to its SAP */
llc_sap_add_socket(sap, sk);
rc = sk->sk_zapped = 0;
out: out:
return rc; return rc;
} }
...@@ -399,14 +414,6 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr, ...@@ -399,14 +414,6 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr,
llc->daddr.lsap = addr->sllc_sap; llc->daddr.lsap = addr->sllc_sap;
memcpy(llc->daddr.mac, addr->sllc_mac, IFHWADDRLEN); memcpy(llc->daddr.mac, addr->sllc_mac, IFHWADDRLEN);
} }
if (!llc->dev) {
rc = -ENODEV;
dev = dev_getfirstbyhwtype(addr->sllc_arphrd);
if (!dev)
goto out;
llc->dev = dev;
memcpy(llc->laddr.mac, llc->dev->dev_addr, IFHWADDRLEN);
} else
dev = llc->dev; dev = llc->dev;
if (sk->sk_type != SOCK_STREAM) if (sk->sk_type != SOCK_STREAM)
goto out; goto out;
...@@ -610,7 +617,7 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -610,7 +617,7 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
int rc = -EOPNOTSUPP; int rc = -EOPNOTSUPP;
dprintk("%s: accepting on %02X\n", __FUNCTION__, dprintk("%s: accepting on %02X\n", __FUNCTION__,
llc_sk(sk)->addr.sllc_sap); llc_sk(sk)->laddr.lsap);
lock_sock(sk); lock_sock(sk);
if (sk->sk_type != SOCK_STREAM) if (sk->sk_type != SOCK_STREAM)
goto out; goto out;
...@@ -622,7 +629,7 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -622,7 +629,7 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
if (rc) if (rc)
goto out; goto out;
dprintk("%s: got a new connection on %02X\n", __FUNCTION__, dprintk("%s: got a new connection on %02X\n", __FUNCTION__,
llc_sk(sk)->addr.sllc_sap); llc_sk(sk)->laddr.lsap);
skb = skb_dequeue(&sk->sk_receive_queue); skb = skb_dequeue(&sk->sk_receive_queue);
rc = -EINVAL; rc = -EINVAL;
if (!skb->sk) if (!skb->sk)
...@@ -747,12 +754,6 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -747,12 +754,6 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock,
if (rc) if (rc)
goto release; goto release;
} }
if (!llc->dev) {
rc = -ENODEV;
dev = dev_getfirstbyhwtype(addr->sllc_arphrd);
if (!dev)
goto release;
} else
dev = llc->dev; dev = llc->dev;
hdrlen = dev->hard_header_len + llc_ui_header_len(sk, addr); hdrlen = dev->hard_header_len + llc_ui_header_len(sk, addr);
size = hdrlen + len; size = hdrlen + len;
......
...@@ -48,8 +48,6 @@ static struct sock *llc_get_sk_idx(loff_t pos) ...@@ -48,8 +48,6 @@ static struct sock *llc_get_sk_idx(loff_t pos)
--pos; --pos;
} }
read_unlock_bh(&sap->sk_list.lock); read_unlock_bh(&sap->sk_list.lock);
if (!pos)
break;
} }
sk = NULL; sk = NULL;
found: found:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment