Commit 3dd5a454 authored by Anton Blanchard's avatar Anton Blanchard

Merge samba.org:/scratch/anton/linux-2.5

into samba.org:/scratch/anton/linux-2.5_ppc64
parents f733206b 4f9af681
......@@ -104,8 +104,8 @@ APISOURCES := $(TOPDIR)/drivers/media/video/videodev.c \
$(TOPDIR)/sound/sound_firmware.c \
$(TOPDIR)/drivers/net/wan/syncppp.c \
$(TOPDIR)/drivers/net/wan/z85230.c \
$(TOPDIR)/drivers/usb/hcd.c \
$(TOPDIR)/drivers/usb/usb.c \
$(TOPDIR)/drivers/usb/core/hcd.c \
$(TOPDIR)/drivers/usb/core/usb.c \
$(TOPDIR)/drivers/video/fbmem.c \
$(TOPDIR)/drivers/video/fbcmap.c \
$(TOPDIR)/drivers/video/fbcon.c \
......
......@@ -282,7 +282,7 @@
</sect1>
<sect1><title>USB Core APIs</title>
!Edrivers/usb/usb.c
!Edrivers/usb/core/usb.c
</sect1>
<sect1><title>Host Controller APIs</title>
......@@ -290,7 +290,7 @@
most of which implement standard register interfaces such as
EHCI, OHCI, or UHCI.
</para>
!Edrivers/usb/hcd.c
!Edrivers/usb/core/hcd.c
</sect1>
</chapter>
......
......@@ -70,6 +70,10 @@ Driver details:
Change history:
Version 0.9.7:
* Support other i8xx chipsets too (by adding 82801BA(M) and
82801CA(M) detection)
Version 0.9.6:
* Internal driver cleanups, prep for 1.0.0 release.
......
......@@ -1386,6 +1386,13 @@ P: Ingo Molnar
M: mingo@redhat.com
S: Maintained
SIS 5513 IDE CONTROLLER DRIVER
P: Lionel Bouton
M: Lionel.Bouton@inet6.fr
W: http://inet6.dyn.dhs.org/sponsoring/sis5513/index.html
W: http://gyver.homeip.net/sis5513/index.html
S: Maintained
SIS 900/7016 FAST ETHERNET DRIVER
P: Ollie Lho
M: ollie@sis.com.tw
......
......@@ -826,13 +826,15 @@ CONFIG_USB=y
# CONFIG_USB_OHCI_HCD is not set
CONFIG_USB_UHCI_ALT=y
# CONFIG_USB_OHCI is not set
CONFIG_USB_HOST=y
#
# USB Device Class drivers
#
# CONFIG_USB_AUDIO is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_BLUETOOTH is not set
# CONFIG_USB_BLUETOOTH_TTY is not set
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
......@@ -842,8 +844,6 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_HP8200e is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
#
# USB Human Interface Devices (HID)
......@@ -871,19 +871,28 @@ CONFIG_USB_STORAGE=y
#
# USB Multimedia devices
#
# CONFIG_USB_DABUSB is not set
#
# Video4Linux support is needed for USB Multimedia device support
#
# CONFIG_USB_VICAM is not set
# CONFIG_USB_DSBR is not set
# CONFIG_USB_IBMCAM is not set
# CONFIG_USB_KONICAWC is not set
# CONFIG_USB_OV511 is not set
# CONFIG_USB_PWC is not set
# CONFIG_USB_SE401 is not set
# CONFIG_USB_STV680 is not set
#
# USB Network adaptors
#
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
# CONFIG_USB_KAWETH is not set
# CONFIG_USB_CATC is not set
# CONFIG_USB_CDCETHER is not set
# CONFIG_USB_KAWETH is not set
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
# CONFIG_USB_USBNET is not set
#
......@@ -927,9 +936,10 @@ CONFIG_USB_STORAGE=y
#
# USB Miscellaneous drivers
#
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_AUERSWALD is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_TIGL is not set
# CONFIG_USB_AUERSWALD is not set
# CONFIG_USB_RIO500 is not set
#
# Kernel hacking
......
......@@ -637,7 +637,7 @@ static int __init detect_init_APIC (void)
printk("Could not enable APIC!\n");
return -1;
}
set_bit(X86_FEATURE_APIC, &boot_cpu_data.x86_capability);
set_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
boot_cpu_physical_apicid = 0;
if (nmi_watchdog != NMI_NONE)
......
......@@ -284,7 +284,7 @@ static void __init intel_mcheck_init(struct cpuinfo_x86 *c)
* Check for MCE support
*/
if( !test_bit(X86_FEATURE_MCE, &c->x86_capability) )
if( !test_bit(X86_FEATURE_MCE, c->x86_capability) )
return;
/*
......@@ -314,7 +314,7 @@ static void __init intel_mcheck_init(struct cpuinfo_x86 *c)
* Check for PPro style MCA
*/
if( !test_bit(X86_FEATURE_MCA, &c->x86_capability) )
if( !test_bit(X86_FEATURE_MCA, c->x86_capability) )
return;
/* Ok machine check is available */
......
......@@ -387,7 +387,7 @@ static void set_mtrr_prepare_save (struct set_mtrr_context *ctxt)
return;
/* Save value of CR4 and clear Page Global Enable (bit 7) */
if ( test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability) ) {
if ( test_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability) ) {
ctxt->cr4val = read_cr4();
write_cr4(ctxt->cr4val & (unsigned char) ~(1<<7));
}
......@@ -448,7 +448,7 @@ static void set_mtrr_done (struct set_mtrr_context *ctxt)
write_cr0( read_cr0() & 0xbfffffff );
/* Restore value of CR4 */
if ( test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability) )
if ( test_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability) )
write_cr4(ctxt->cr4val);
/* Re-enable interrupts locally (if enabled previously) */
......@@ -2122,7 +2122,7 @@ static void __init centaur_mcr_init(void)
static int __init mtrr_setup(void)
{
if ( test_bit(X86_FEATURE_MTRR, &boot_cpu_data.x86_capability) ) {
if ( test_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability) ) {
/* Intel (P6) standard MTRRs */
mtrr_if = MTRR_IF_INTEL;
get_mtrr = intel_get_mtrr;
......@@ -2166,14 +2166,14 @@ static int __init mtrr_setup(void)
break;
}
} else if ( test_bit(X86_FEATURE_K6_MTRR, &boot_cpu_data.x86_capability) ) {
} else if ( test_bit(X86_FEATURE_K6_MTRR, boot_cpu_data.x86_capability) ) {
/* Pre-Athlon (K6) AMD CPU MTRRs */
mtrr_if = MTRR_IF_AMD_K6;
get_mtrr = amd_get_mtrr;
set_mtrr_up = amd_set_mtrr_up;
size_or_mask = 0xfff00000; /* 32 bits */
size_and_mask = 0;
} else if ( test_bit(X86_FEATURE_CYRIX_ARR, &boot_cpu_data.x86_capability) ) {
} else if ( test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) ) {
/* Cyrix ARRs */
mtrr_if = MTRR_IF_CYRIX_ARR;
get_mtrr = cyrix_get_arr;
......@@ -2182,7 +2182,7 @@ static int __init mtrr_setup(void)
cyrix_arr_init();
size_or_mask = 0xfff00000; /* 32 bits */
size_and_mask = 0;
} else if ( test_bit(X86_FEATURE_CENTAUR_MCR, &boot_cpu_data.x86_capability) ) {
} else if ( test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability) ) {
/* Centaur MCRs */
mtrr_if = MTRR_IF_CENTAUR_MCR;
get_mtrr = centaur_get_mcr;
......
......@@ -612,7 +612,7 @@ static void __init parse_mem_cmdline (char ** cmdline_p)
to--;
if (!memcmp(from+4, "nopentium", 9)) {
from += 9+4;
clear_bit(X86_FEATURE_PSE, &boot_cpu_data.x86_capability);
clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
} else if (!memcmp(from+4, "exactmap", 8)) {
from += 8+4;
e820.nr_map = 0;
......@@ -1121,7 +1121,7 @@ static int __init init_amd(struct cpuinfo_x86 *c)
/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
clear_bit(0*32+31, &c->x86_capability);
clear_bit(0*32+31, c->x86_capability);
r = get_model_name(c);
......@@ -1132,8 +1132,8 @@ static int __init init_amd(struct cpuinfo_x86 *c)
{
/* Based on AMD doc 20734R - June 2000 */
if ( c->x86_model == 0 ) {
clear_bit(X86_FEATURE_APIC, &c->x86_capability);
set_bit(X86_FEATURE_PGE, &c->x86_capability);
clear_bit(X86_FEATURE_APIC, c->x86_capability);
set_bit(X86_FEATURE_PGE, c->x86_capability);
}
break;
}
......@@ -1213,7 +1213,7 @@ static int __init init_amd(struct cpuinfo_x86 *c)
/* Set MTRR capability flag if appropriate */
if (c->x86_model == 13 || c->x86_model == 9 ||
(c->x86_model == 8 && c->x86_mask >= 8))
set_bit(X86_FEATURE_K6_MTRR, &c->x86_capability);
set_bit(X86_FEATURE_K6_MTRR, c->x86_capability);
break;
}
break;
......@@ -1226,12 +1226,12 @@ static int __init init_amd(struct cpuinfo_x86 *c)
* here.
*/
if (c->x86_model == 6 || c->x86_model == 7) {
if (!test_bit(X86_FEATURE_XMM, &c->x86_capability)) {
if (!test_bit(X86_FEATURE_XMM, c->x86_capability)) {
printk(KERN_INFO "Enabling disabled K7/SSE Support.\n");
rdmsr(MSR_K7_HWCR, l, h);
l &= ~0x00008000;
wrmsr(MSR_K7_HWCR, l, h);
set_bit(X86_FEATURE_XMM, &c->x86_capability);
set_bit(X86_FEATURE_XMM, c->x86_capability);
}
}
break;
......@@ -1348,12 +1348,12 @@ static void __init init_cyrix(struct cpuinfo_x86 *c)
/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
clear_bit(0*32+31, &c->x86_capability);
clear_bit(0*32+31, c->x86_capability);
/* Cyrix used bit 24 in extended (AMD) CPUID for Cyrix MMX extensions */
if ( test_bit(1*32+24, &c->x86_capability) ) {
clear_bit(1*32+24, &c->x86_capability);
set_bit(X86_FEATURE_CXMMX, &c->x86_capability);
if ( test_bit(1*32+24, c->x86_capability) ) {
clear_bit(1*32+24, c->x86_capability);
set_bit(X86_FEATURE_CXMMX, c->x86_capability);
}
do_cyrix_devid(&dir0, &dir1);
......@@ -1400,7 +1400,7 @@ static void __init init_cyrix(struct cpuinfo_x86 *c)
} else /* 686 */
p = Cx86_cb+1;
/* Emulate MTRRs using Cyrix's ARRs. */
set_bit(X86_FEATURE_CYRIX_ARR, &c->x86_capability);
set_bit(X86_FEATURE_CYRIX_ARR, c->x86_capability);
/* 6x86's contain this bug */
c->coma_bug = 1;
break;
......@@ -1444,7 +1444,7 @@ static void __init init_cyrix(struct cpuinfo_x86 *c)
p = Cx86_cb+2;
c->x86_model = (dir1 & 0x20) ? 1 : 2;
#ifndef CONFIG_CS5520
clear_bit(X86_FEATURE_TSC, &c->x86_capability);
clear_bit(X86_FEATURE_TSC, c->x86_capability);
#endif
}
break;
......@@ -1466,7 +1466,7 @@ static void __init init_cyrix(struct cpuinfo_x86 *c)
if (((dir1 & 0x0f) > 4) || ((dir1 & 0xf0) == 0x20))
(c->x86_model)++;
/* Emulate MTRRs using Cyrix's ARRs. */
set_bit(X86_FEATURE_CYRIX_ARR, &c->x86_capability);
set_bit(X86_FEATURE_CYRIX_ARR, c->x86_capability);
break;
case 0xf: /* Cyrix 486 without DEVID registers */
......@@ -1765,7 +1765,7 @@ static void __init init_centaur(struct cpuinfo_x86 *c)
/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
clear_bit(0*32+31, &c->x86_capability);
clear_bit(0*32+31, c->x86_capability);
switch (c->x86) {
......@@ -1776,7 +1776,7 @@ static void __init init_centaur(struct cpuinfo_x86 *c)
fcr_set=ECX8|DSMC|EDCTLB|EMMX|ERETSTK;
fcr_clr=DPDC;
printk(KERN_NOTICE "Disabling bugged TSC.\n");
clear_bit(X86_FEATURE_TSC, &c->x86_capability);
clear_bit(X86_FEATURE_TSC, c->x86_capability);
#ifdef CONFIG_X86_OOSTORE
winchip_create_optimal_mcr();
/* Enable
......@@ -1855,12 +1855,12 @@ static void __init init_centaur(struct cpuinfo_x86 *c)
printk(KERN_INFO "Centaur FCR is 0x%X\n",lo);
}
/* Emulate MTRRs using Centaur's MCR. */
set_bit(X86_FEATURE_CENTAUR_MCR, &c->x86_capability);
set_bit(X86_FEATURE_CENTAUR_MCR, c->x86_capability);
/* Report CX8 */
set_bit(X86_FEATURE_CX8, &c->x86_capability);
set_bit(X86_FEATURE_CX8, c->x86_capability);
/* Set 3DNow! on Winchip 2 and above. */
if (c->x86_model >=8)
set_bit(X86_FEATURE_3DNOW, &c->x86_capability);
set_bit(X86_FEATURE_3DNOW, c->x86_capability);
/* See if we can find out some more. */
if ( cpuid_eax(0x80000000) >= 0x80000005 ) {
/* Yes, we can. */
......@@ -1878,8 +1878,8 @@ static void __init init_centaur(struct cpuinfo_x86 *c)
lo |= (1<<1 | 1<<7); /* Report CX8 & enable PGE */
wrmsr (MSR_VIA_FCR, lo, hi);
set_bit(X86_FEATURE_CX8, &c->x86_capability);
set_bit(X86_FEATURE_3DNOW, &c->x86_capability);
set_bit(X86_FEATURE_CX8, c->x86_capability);
set_bit(X86_FEATURE_3DNOW, c->x86_capability);
get_model_name(c);
display_cacheinfo(c);
......@@ -1973,7 +1973,7 @@ static void __init init_rise(struct cpuinfo_x86 *c)
"movl $0x2333313a, %%edx\n\t"
"cpuid\n\t" : : : "eax", "ebx", "ecx", "edx"
);
set_bit(X86_FEATURE_CX8, &c->x86_capability);
set_bit(X86_FEATURE_CX8, c->x86_capability);
}
......@@ -2123,7 +2123,7 @@ static void __init init_intel(struct cpuinfo_x86 *c)
/* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it */
if ( c->x86 == 6 && c->x86_model < 3 && c->x86_mask < 3 )
clear_bit(X86_FEATURE_SEP, &c->x86_capability);
clear_bit(X86_FEATURE_SEP, c->x86_capability);
/* Names for the Pentium II/Celeron processors
detectable only by also checking the cache size.
......@@ -2153,7 +2153,7 @@ static void __init init_intel(struct cpuinfo_x86 *c)
strcpy(c->x86_model_id, p);
#ifdef CONFIG_SMP
if (test_bit(X86_FEATURE_HT, &c->x86_capability)) {
if (test_bit(X86_FEATURE_HT, c->x86_capability)) {
extern int phys_proc_id[NR_CPUS];
u32 eax, ebx, ecx, edx;
......@@ -2322,7 +2322,7 @@ static int __init deep_magic_nexgen_probe(void)
static void __init squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
{
if( test_bit(X86_FEATURE_PN, &c->x86_capability) &&
if( test_bit(X86_FEATURE_PN, c->x86_capability) &&
disable_x86_serial_nr ) {
/* Disable processor serial number */
unsigned long lo,hi;
......@@ -2330,7 +2330,7 @@ static void __init squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
lo |= 0x200000;
wrmsr(MSR_IA32_BBL_CR_CTL,lo,hi);
printk(KERN_NOTICE "CPU serial number disabled.\n");
clear_bit(X86_FEATURE_PN, &c->x86_capability);
clear_bit(X86_FEATURE_PN, c->x86_capability);
/* Disabling the serial number may affect the cpuid level */
c->cpuid_level = cpuid_eax(0);
......@@ -2496,8 +2496,9 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
/* Intel-defined flags: level 0x00000001 */
if ( c->cpuid_level >= 0x00000001 ) {
cpuid(0x00000001, &tfms, &junk, &junk,
&c->x86_capability[0]);
u32 capability;
cpuid(0x00000001, &tfms, &junk, &junk, &capability);
c->x86_capability[0] = capability;
c->x86 = (tfms >> 8) & 15;
c->x86_model = (tfms >> 4) & 15;
c->x86_mask = tfms & 15;
......@@ -2523,7 +2524,7 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
}
}
printk(KERN_DEBUG "CPU: Before vendor init, caps: %08x %08x %08x, vendor = %d\n",
printk(KERN_DEBUG "CPU: Before vendor init, caps: %08lx %08lx %08lx, vendor = %d\n",
c->x86_capability[0],
c->x86_capability[1],
c->x86_capability[2],
......@@ -2588,7 +2589,7 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
}
printk(KERN_DEBUG "CPU: After vendor init, caps: %08x %08x %08x %08x\n",
printk(KERN_DEBUG "CPU: After vendor init, caps: %08lx %08lx %08lx %08lx\n",
c->x86_capability[0],
c->x86_capability[1],
c->x86_capability[2],
......@@ -2602,13 +2603,13 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
/* TSC disabled? */
#ifndef CONFIG_X86_TSC
if ( tsc_disable )
clear_bit(X86_FEATURE_TSC, &c->x86_capability);
clear_bit(X86_FEATURE_TSC, c->x86_capability);
#endif
/* FXSR disabled? */
if (disable_x86_fxsr) {
clear_bit(X86_FEATURE_FXSR, &c->x86_capability);
clear_bit(X86_FEATURE_XMM, &c->x86_capability);
clear_bit(X86_FEATURE_FXSR, c->x86_capability);
clear_bit(X86_FEATURE_XMM, c->x86_capability);
}
/* Disable the PN if appropriate */
......@@ -2631,7 +2632,7 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
/* Now the feature flags better reflect actual CPU features! */
printk(KERN_DEBUG "CPU: After generic, caps: %08x %08x %08x %08x\n",
printk(KERN_DEBUG "CPU: After generic, caps: %08lx %08lx %08lx %08lx\n",
c->x86_capability[0],
c->x86_capability[1],
c->x86_capability[2],
......@@ -2649,7 +2650,7 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
}
printk(KERN_DEBUG "CPU: Common caps: %08x %08x %08x %08x\n",
printk(KERN_DEBUG "CPU: Common caps: %08lx %08lx %08lx %08lx\n",
boot_cpu_data.x86_capability[0],
boot_cpu_data.x86_capability[1],
boot_cpu_data.x86_capability[2],
......@@ -2759,7 +2760,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
else
seq_printf(m, "stepping\t: unknown\n");
if ( test_bit(X86_FEATURE_TSC, &c->x86_capability) ) {
if ( test_bit(X86_FEATURE_TSC, c->x86_capability) ) {
seq_printf(m, "cpu MHz\t\t: %lu.%03lu\n",
cpu_khz / 1000, (cpu_khz % 1000));
}
......@@ -2789,7 +2790,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
c->wp_works_ok ? "yes" : "no");
for ( i = 0 ; i < 32*NCAPINTS ; i++ )
if ( test_bit(i, &c->x86_capability) &&
if ( test_bit(i, c->x86_capability) &&
x86_cap_flags[i] != NULL )
seq_printf(m, " %s", x86_cap_flags[i]);
......
......@@ -35,7 +35,7 @@
/*
* core module and version information
*/
#define RNG_VERSION "0.9.6"
#define RNG_VERSION "0.9.7"
#define RNG_MODULE_NAME "i810_rng"
#define RNG_DRIVER_NAME RNG_MODULE_NAME " hardware driver " RNG_VERSION
#define PFX RNG_MODULE_NAME ": "
......@@ -334,7 +334,8 @@ static int __init rng_init_one (struct pci_dev *dev)
static struct pci_device_id rng_pci_tbl[] __initdata = {
{ 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, },
{ 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, },
{ 0x8086, 0x1130, PCI_ANY_ID, PCI_ANY_ID, },
{ 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, },
{ 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, },
{ 0, },
};
MODULE_DEVICE_TABLE (pci, rng_pci_tbl);
......
......@@ -173,10 +173,10 @@ static inline int noncached_address(unsigned long addr)
* caching for the high addresses through the KEN pin, but
* we maintain the tradition of paranoia in this code.
*/
return !( test_bit(X86_FEATURE_MTRR, &boot_cpu_data.x86_capability) ||
test_bit(X86_FEATURE_K6_MTRR, &boot_cpu_data.x86_capability) ||
test_bit(X86_FEATURE_CYRIX_ARR, &boot_cpu_data.x86_capability) ||
test_bit(X86_FEATURE_CENTAUR_MCR, &boot_cpu_data.x86_capability) )
return !( test_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability) ||
test_bit(X86_FEATURE_K6_MTRR, boot_cpu_data.x86_capability) ||
test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) ||
test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability) )
&& addr >= __pa(high_memory);
#else
return addr >= __pa(high_memory);
......
......@@ -736,7 +736,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
int entropy = 0;
#if defined (__i386__)
if ( test_bit(X86_FEATURE_TSC, &boot_cpu_data.x86_capability) ) {
if ( test_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability) ) {
__u32 high;
rdtsc(time, high);
num ^= high;
......
......@@ -212,9 +212,8 @@ void __init init_ali14xx (void)
ide_hwifs[1].chipset = ide_ali14xx;
ide_hwifs[0].tuneproc = &ali14xx_tune_drive;
ide_hwifs[1].tuneproc = &ali14xx_tune_drive;
ide_hwifs[0].mate = &ide_hwifs[1];
ide_hwifs[1].mate = &ide_hwifs[0];
ide_hwifs[1].unit = 1;
ide_hwifs[0].unit = ATA_PRIMARY;
ide_hwifs[1].unit = ATA_SECONDARY;
/* initialize controller registers */
if (!initRegisters()) {
......
......@@ -689,7 +689,7 @@ static void cmd640_tune_drive (ide_drive_t *drive, byte mode_wanted)
/*
* Probe for a cmd640 chipset, and initialize it if found. Called from ide.c
*/
int __init ide_probe_for_cmd640x (void)
int __init ide_probe_for_cmd640x(void)
{
#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
int second_port_toggled = 0;
......@@ -793,9 +793,7 @@ int __init ide_probe_for_cmd640x (void)
cmd_hwif0->serialized = 1;
cmd_hwif1->serialized = 1;
cmd_hwif1->chipset = ide_cmd640;
cmd_hwif0->mate = cmd_hwif1;
cmd_hwif1->mate = cmd_hwif0;
cmd_hwif1->unit = 1;
cmd_hwif1->unit = ATA_SECONDARY;
#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
cmd_hwif1->tuneproc = &cmd640_tune_drive;
#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
......
......@@ -346,8 +346,7 @@ unsigned int __init pci_init_cs5530(struct pci_dev *dev)
*/
void __init ide_init_cs5530(struct ata_channel *hwif)
{
if (hwif->mate)
hwif->serialized = hwif->mate->serialized = 1;
hwif->serialized = 1;
if (!hwif->dma_base) {
hwif->autodma = 0;
} else {
......
......@@ -124,7 +124,6 @@ void __init init_dtc2278 (void)
ide_hwifs[0].drives[1].no_unmask = 1;
ide_hwifs[1].drives[0].no_unmask = 1;
ide_hwifs[1].drives[1].no_unmask = 1;
ide_hwifs[0].mate = &ide_hwifs[1];
ide_hwifs[1].mate = &ide_hwifs[0];
ide_hwifs[1].unit = 1;
ide_hwifs[0].unit = ATA_PRIMARY;
ide_hwifs[1].unit = ATA_SECONDARY;
}
......@@ -1131,7 +1131,7 @@ unsigned int __init pci_init_hpt366(struct pci_dev *dev)
hpt366_proc = 1;
hpt366_display_info = &hpt366_get_info;
}
#endif /* DISPLAY_HPT366_TIMINGS && CONFIG_PROC_FS */
#endif
return dev->irq;
}
......@@ -1146,7 +1146,7 @@ unsigned int __init ata66_hpt366(struct ata_channel *hwif)
printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n",
ata66, (ata66 & regmask) ? "33" : "66",
PCI_FUNC(hwif->pci_dev->devfn));
#endif /* DEBUG */
#endif
return ((ata66 & regmask) ? 0 : 1);
}
......
......@@ -319,9 +319,8 @@ void __init init_ht6560b (void)
ide_hwifs[1].tuneproc = &tune_ht6560b;
ide_hwifs[0].serialized = 1; /* is this needed? */
ide_hwifs[1].serialized = 1; /* is this needed? */
ide_hwifs[0].mate = &ide_hwifs[1];
ide_hwifs[1].mate = &ide_hwifs[0];
ide_hwifs[1].unit = 1;
ide_hwifs[0].unit = ATA_PRIMARY;
ide_hwifs[1].unit = ATA_SECONDARY;
/*
* Setting default configurations for drives
......
......@@ -421,7 +421,7 @@ int check_drive_lists (ide_drive_t *drive, int good_bad)
return 0;
}
static int report_drive_dmaing (ide_drive_t *drive)
int report_drive_dmaing (ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
......
......@@ -182,7 +182,7 @@ typedef struct ide_pci_device_s {
unsigned short device;
unsigned int (*init_chipset)(struct pci_dev *dev);
unsigned int (*ata66_check)(struct ata_channel *hwif);
void (*init_hwif)(struct ata_channel *hwif);
void (*init_channel)(struct ata_channel *hwif);
void (*dma_init)(struct ata_channel *hwif, unsigned long dmabase);
ide_pci_enablebit_t enablebits[2];
unsigned int bootable;
......@@ -436,24 +436,21 @@ static unsigned long __init get_dma_base(struct ata_channel *hwif, int extra, co
unsigned long dma_base = 0;
struct pci_dev *dev = hwif->pci_dev;
/*
* If we are on the second channel, the dma base address will be one
* entry away from the primary interface.
*/
if (hwif->mate && hwif->mate->dma_base)
dma_base = hwif->mate->dma_base - (hwif->unit ? 0 : 8);
else
dma_base = pci_resource_start(dev, 4);
if (!dma_base)
return 0;
if (extra) /* PDC20246, PDC20262, HPT343, & HPT366 */
/* PDC20246, PDC20262, HPT343, & HPT366 */
if (extra) {
request_region(dma_base + 16, extra, name);
dma_base += hwif->unit ? 8 : 0;
hwif->dma_extra = extra;
}
/* If we are on the second channel, the dma base address will be one
* entry away from the primary interface.
*/
if (hwif->unit == ATA_SECONDARY)
dma_base += 8;
if ((dev->vendor == PCI_VENDOR_ID_AL && dev->device == PCI_DEVICE_ID_AL_M5219) ||
(dev->vendor == PCI_VENDOR_ID_AMD && dev->device == PCI_DEVICE_ID_AMD_VIPER_7409) ||
......@@ -463,8 +460,7 @@ static unsigned long __init get_dma_base(struct ata_channel *hwif, int extra, co
printk(KERN_INFO "%s: simplex device: DMA forced\n", name);
} else {
/*
* If the device claims "simplex" DMA, this means only one of
/* If the device claims "simplex" DMA, this means only one of
* the two interfaces can be trusted with DMA at any point in
* time. So we should enable DMA only on one of the two
* interfaces.
......@@ -472,7 +468,7 @@ static unsigned long __init get_dma_base(struct ata_channel *hwif, int extra, co
if ((inb(dma_base + 2) & 0x80)) {
if ((!hwif->drives[0].present && !hwif->drives[1].present) ||
(hwif->mate && hwif->mate->dma_base)) {
hwif->unit == ATA_SECONDARY) {
printk("%s: simplex device: DMA disabled\n", name);
dma_base = 0;
}
......@@ -489,8 +485,9 @@ static void __init setup_channel_dma(struct ata_channel *hwif, struct pci_dev *d
ide_pci_device_t *d,
int port,
u8 class_rev,
int pciirq, struct ata_channel **mate,
int autodma, unsigned short *pcicmd)
int pciirq,
int autodma,
unsigned short *pcicmd)
{
unsigned long dma_base;
......@@ -503,8 +500,13 @@ static void __init setup_channel_dma(struct ata_channel *hwif, struct pci_dev *d
if (!((d->flags & ATA_F_DMA) || ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))))
return;
dma_base = get_dma_base(hwif, (!*mate && d->extra) ? d->extra : 0, dev->name);
if (dma_base && !(*pcicmd & PCI_COMMAND_MASTER)) {
dma_base = get_dma_base(hwif, ((port == ATA_PRIMARY) && d->extra) ? d->extra : 0, dev->name);
if (!dma_base) {
printk("%s: %s Bus-Master DMA was disabled by BIOS\n", hwif->name, dev->name);
return;
}
if (!(*pcicmd & PCI_COMMAND_MASTER)) {
/*
* Set up BM-DMA capability (PnP BIOS should have done this already)
......@@ -517,13 +519,10 @@ static void __init setup_channel_dma(struct ata_channel *hwif, struct pci_dev *d
dma_base = 0;
}
}
if (dma_base) {
if (d->dma_init)
d->dma_init(hwif, dma_base);
else
ide_setup_dma(hwif, dma_base, 8);
} else
printk("%s: %s Bus-Master DMA was disabled by BIOS\n", hwif->name, dev->name);
}
#endif
......@@ -537,17 +536,16 @@ static int __init setup_host_channel(struct pci_dev *dev,
int port,
u8 class_rev,
int pciirq,
struct ata_channel **mate,
int autodma,
unsigned short *pcicmd)
{
unsigned long base = 0;
unsigned long ctl = 0;
ide_pci_enablebit_t *e = &(d->enablebits[port]);
struct ata_channel *hwif;
struct ata_channel *ch;
u8 tmp;
if (port == 1) {
if (port == ATA_SECONDARY) {
/* If this is a Promise FakeRaid controller, the 2nd controller
* will be marked as disabled while it is actually there and
......@@ -569,7 +567,7 @@ static int __init setup_host_channel(struct pci_dev *dev,
/* Nothing to be done for the second port.
*/
if (port == 1) {
if (port == ATA_SECONDARY) {
if ((d->flags & ATA_F_HPTHACK) && (class_rev < 0x03))
return 0;
}
......@@ -599,57 +597,50 @@ static int __init setup_host_channel(struct pci_dev *dev,
if (!base)
base = port ? 0x170 : 0x1f0;
if ((hwif = lookup_hwif(base, d->bootable, dev->name)) == NULL)
if ((ch = lookup_hwif(base, d->bootable, dev->name)) == NULL)
return -ENOMEM; /* no room in ide_hwifs[] */
if (hwif->io_ports[IDE_DATA_OFFSET] != base) {
ide_init_hwif_ports(&hwif->hw, base, (ctl | 2), NULL);
memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
if (ch->io_ports[IDE_DATA_OFFSET] != base) {
ide_init_hwif_ports(&ch->hw, base, (ctl | 2), NULL);
memcpy(ch->io_ports, ch->hw.io_ports, sizeof(ch->io_ports));
ch->noprobe = !ch->io_ports[IDE_DATA_OFFSET];
}
hwif->chipset = ide_pci;
hwif->pci_dev = dev;
hwif->unit = port;
if (!hwif->irq)
hwif->irq = pciirq;
ch->chipset = ide_pci;
ch->pci_dev = dev;
ch->unit = port;
if (!ch->irq)
ch->irq = pciirq;
/* Setup the mate interface if we have two channels.
/* Serialize the interfaces if requested by configuration information.
*/
if (*mate) {
hwif->mate = *mate;
(*mate)->mate = hwif;
if (d->flags & ATA_F_SER) {
hwif->serialized = 1;
(*mate)->serialized = 1;
}
}
if (d->flags & ATA_F_SER)
ch->serialized = 1;
/* Cross wired IRQ lines on UMC chips and no DMA transfers.*/
if (d->flags & ATA_F_FIXIRQ) {
hwif->irq = port ? 15 : 14;
ch->irq = port ? 15 : 14;
goto no_dma;
}
if (d->flags & ATA_F_NODMA)
goto no_dma;
/* Check whatever this interface is UDMA4 mode capable. */
if (hwif->udma_four) {
if (ch->udma_four) {
printk("%s: warning: ATA-66/100 forced bit set!\n", dev->name);
} else {
if (d->ata66_check)
hwif->udma_four = d->ata66_check(hwif);
ch->udma_four = d->ata66_check(ch);
}
#ifdef CONFIG_BLK_DEV_IDEDMA
setup_channel_dma(hwif, dev, d, port, class_rev, pciirq, mate, autodma, pcicmd);
setup_channel_dma(ch, dev, d, port, class_rev, pciirq, autodma, pcicmd);
#endif
no_dma:
if (d->init_hwif) /* Call chipset-specific routine for each enabled hwif */
d->init_hwif(hwif);
*mate = hwif;
/* Call chipset-specific routine for each enabled channel. */
if (d->init_channel)
d->init_channel(ch);
return 0;
}
......@@ -671,7 +662,6 @@ static void __init setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d)
int pciirq = 0;
unsigned short pcicmd = 0;
unsigned short tried_config = 0;
struct ata_channel *mate = NULL;
unsigned int class_rev;
#ifdef CONFIG_IDEDMA_AUTO
......@@ -679,9 +669,9 @@ static void __init setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d)
autodma = 1;
#endif
if (d->init_hwif == IDE_NO_DRIVER) {
if (d->init_channel == IDE_NO_DRIVER) {
printk(KERN_WARNING "%s: detected chipset, but driver not compiled in!\n", dev->name);
d->init_hwif = NULL;
d->init_channel = NULL;
}
if (pci_enable_device(dev)) {
......@@ -779,8 +769,8 @@ static void __init setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d)
/*
* Set up IDE chanells. First the primary, then the secondary.
*/
setup_host_channel(dev, d, 0, class_rev, pciirq, &mate, autodma, &pcicmd);
setup_host_channel(dev, d, 1, class_rev, pciirq, &mate, autodma, &pcicmd);
setup_host_channel(dev, d, ATA_PRIMARY, class_rev, pciirq, autodma, &pcicmd);
setup_host_channel(dev, d, ATA_SECONDARY, class_rev, pciirq, autodma, &pcicmd);
}
static void __init pdc20270_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d)
......@@ -856,12 +846,6 @@ static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_devic
if (hpt363_shared_pin && hpt363_shared_irq) {
d->bootable = ON_BOARD;
printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", dev->name, pin1, pin2);
#if 0
/* I forgot why I did this once, but it fixed something. */
pci_write_config_byte(dev2, PCI_INTERRUPT_PIN, dev->irq);
printk("PCI: %s: Fixing interrupt %d pin %d to ZERO \n", d->name, dev2->irq, pin2);
pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, 0);
#endif
}
break;
}
......@@ -894,7 +878,7 @@ static void __init scan_pcidev(struct pci_dev *dev)
while (d->vendor && !(d->vendor == vendor && d->device == device))
++d;
if (d->init_hwif == ATA_PCI_IGNORE)
if (d->init_channel == ATA_PCI_IGNORE)
printk("%s: has been ignored by PCI bus scan\n", dev->name);
else if ((d->vendor == PCI_VENDOR_ID_OPTI && d->device == PCI_DEVICE_ID_OPTI_82C558) && !(PCI_FUNC(dev->devfn) & 1))
return;
......
......@@ -16,6 +16,16 @@
*
* Copyright (c) 1995-1998 Mark Lord
*
* TODO:
*
* - Find a way to duplicate less code with ide-dma and use the
* dma fileds in the hwif structure instead of our own
* - Fix check_disk_change() call
* - Make module-able (includes setting ppc_md. hooks from within
* this file and not from arch code, and handling module deps with
* mediabay (by having both modules do dynamic lookup of each other
* symbols or by storing hooks at arch level).
*
*/
#include <linux/config.h>
#include <linux/types.h>
......@@ -24,26 +34,30 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/pci.h>
#include <asm/prom.h>
#include <asm/io.h>
#include <asm/dbdma.h>
#include <asm/ide.h>
#include <asm/mediabay.h>
#include <asm/feature.h>
#include <asm/pci-bridge.h>
#include <asm/machdep.h>
#include <asm/pmac_feature.h>
#include <asm/sections.h>
#include <asm/irq.h>
#ifdef CONFIG_PMAC_PBOOK
#include <linux/adb.h>
#include <linux/pmu.h>
#include <asm/irq.h>
#endif
#include "ata-timing.h"
extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc);
extern spinlock_t ide_lock;
#undef IDE_PMAC_DEBUG
#define IDE_SYSCLK_NS 30
#define IDE_SYSCLK_ULTRA_PS 0x1d4c /* (15 * 1000 / 2)*/
#define DMA_WAIT_TIMEOUT 500
struct pmac_ide_hwif {
ide_ioreg_t regbase;
......@@ -53,11 +67,20 @@ struct pmac_ide_hwif {
struct device_node* node;
u32 timings[2];
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
/* Those fields are duplicating what is in hwif. We currently
* can't use the hwif ones because of some assumptions that are
* beeing done by the generic code about the kind of dma controller
* and format of the dma table. This will have to be fixed though.
*/
volatile struct dbdma_regs* dma_regs;
struct dbdma_cmd* dma_table;
#endif
struct dbdma_cmd* dma_table_cpu;
dma_addr_t dma_table_dma;
struct scatterlist* sg_table;
int sg_nents;
int sg_dma_direction;
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
} pmac_ide[MAX_HWIFS];
} pmac_ide[MAX_HWIFS] __pmacdata;
static int pmac_ide_count;
......@@ -65,36 +88,160 @@ enum {
controller_ohare, /* OHare based */
controller_heathrow, /* Heathrow/Paddington */
controller_kl_ata3, /* KeyLargo ATA-3 */
controller_kl_ata4 /* KeyLargo ATA-4 */
controller_kl_ata4, /* KeyLargo ATA-4 */
controller_kl_ata4_80 /* KeyLargo ATA-4 with 80 conductor cable */
};
/*
* Extra registers, both 32-bit little-endian
*/
#define IDE_TIMING_CONFIG 0x200
#define IDE_INTERRUPT 0x300
/*
* Timing configuration register definitions
*/
/* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */
#define SYSCLK_TICKS(t) (((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS)
#define SYSCLK_TICKS_66(t) (((t) + IDE_SYSCLK_66_NS - 1) / IDE_SYSCLK_66_NS)
#define IDE_SYSCLK_NS 30 /* 33Mhz cell */
#define IDE_SYSCLK_66_NS 15 /* 66Mhz cell */
/* 66Mhz cell, found in KeyLargo. Can do ultra mode 0 to 2 on
* 40 connector cable and to 4 on 80 connector one.
* Clock unit is 15ns (66Mhz)
*
* 3 Values can be programmed:
* - Write data setup, which appears to match the cycle time. They
* also call it DIOW setup.
* - Ready to pause time (from spec)
* - Address setup. That one is weird. I don't see where exactly
* it fits in UDMA cycles, I got it's name from an obscure piece
* of commented out code in Darwin. They leave it to 0, we do as
* well, despite a comment that would lead to think it has a
* min value of 45ns.
* Apple also add 60ns to the write data setup (or cycle time ?) on
* reads. I can't explain that, I tried it and it broke everything
* here.
*/
#define TR_66_UDMA_MASK 0xfff00000
#define TR_66_UDMA_EN 0x00100000 /* Enable Ultra mode for DMA */
#define TR_66_UDMA_ADDRSETUP_MASK 0xe0000000 /* Address setup */
#define TR_66_UDMA_ADDRSETUP_SHIFT 29
#define TR_66_UDMA_RDY2PAUS_MASK 0x1e000000 /* Ready 2 pause time */
#define TR_66_UDMA_RDY2PAUS_SHIFT 25
#define TR_66_UDMA_WRDATASETUP_MASK 0x01e00000 /* Write data setup time */
#define TR_66_UDMA_WRDATASETUP_SHIFT 21
#define TR_66_MDMA_MASK 0x000ffc00
#define TR_66_MDMA_RECOVERY_MASK 0x000f8000
#define TR_66_MDMA_RECOVERY_SHIFT 15
#define TR_66_MDMA_ACCESS_MASK 0x00007c00
#define TR_66_MDMA_ACCESS_SHIFT 10
#define TR_66_PIO_MASK 0x000003ff
#define TR_66_PIO_RECOVERY_MASK 0x000003e0
#define TR_66_PIO_RECOVERY_SHIFT 5
#define TR_66_PIO_ACCESS_MASK 0x0000001f
#define TR_66_PIO_ACCESS_SHIFT 0
/* 33Mhz cell, found in OHare, Heathrow (& Paddington) and KeyLargo
* Can do pio & mdma modes, clock unit is 30ns (33Mhz)
*
* The access time and recovery time can be programmed. Some older
* Darwin code base limit OHare to 150ns cycle time. I decided to do
* the same here fore safety against broken old hardware ;)
* The HalfTick bit, when set, adds half a clock (15ns) to the access
* time and removes one from recovery. It's not supported on KeyLargo
* implementation afaik. The E bit appears to be set for PIO mode 0 and
* is used to reach long timings used in this mode.
*/
#define TR_33_MDMA_MASK 0x003ff800
#define TR_33_MDMA_RECOVERY_MASK 0x001f0000
#define TR_33_MDMA_RECOVERY_SHIFT 16
#define TR_33_MDMA_ACCESS_MASK 0x0000f800
#define TR_33_MDMA_ACCESS_SHIFT 11
#define TR_33_MDMA_HALFTICK 0x00200000
#define TR_33_PIO_MASK 0x000007ff
#define TR_33_PIO_E 0x00000400
#define TR_33_PIO_RECOVERY_MASK 0x000003e0
#define TR_33_PIO_RECOVERY_SHIFT 5
#define TR_33_PIO_ACCESS_MASK 0x0000001f
#define TR_33_PIO_ACCESS_SHIFT 0
/*
* Interrupt register definitions
*/
#define IDE_INTR_DMA 0x80000000
#define IDE_INTR_DEVICE 0x40000000
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
# define BAD_DMA_DRIVE 0
# define GOOD_DMA_DRIVE 1
typedef struct {
/* Rounded Multiword DMA timings
*
* I gave up finding a generic formula for all controller
* types and instead, built tables based on timing values
* used by Apple in Darwin's implementation.
*/
struct mdma_timings_t {
int accessTime;
int recoveryTime;
int cycleTime;
} pmac_ide_timing;
};
struct mdma_timings_t mdma_timings_33[] __pmacdata =
{
{ 240, 240, 480 },
{ 180, 180, 360 },
{ 135, 135, 270 },
{ 120, 120, 240 },
{ 105, 105, 210 },
{ 90, 90, 180 },
{ 75, 75, 150 },
{ 75, 45, 120 },
{ 0, 0, 0 }
};
struct mdma_timings_t mdma_timings_33k[] __pmacdata =
{
{ 240, 240, 480 },
{ 180, 180, 360 },
{ 150, 150, 300 },
{ 120, 120, 240 },
{ 90, 120, 210 },
{ 90, 90, 180 },
{ 90, 60, 150 },
{ 90, 30, 120 },
{ 0, 0, 0 }
};
/* Multiword DMA timings */
static pmac_ide_timing mdma_timings[] =
struct mdma_timings_t mdma_timings_66[] __pmacdata =
{
{ 215, 480 }, /* Mode 0 */
{ 80, 150 }, /* 1 */
{ 70, 120 } /* 2 */
{ 240, 240, 480 },
{ 180, 180, 360 },
{ 135, 135, 270 },
{ 120, 120, 240 },
{ 105, 105, 210 },
{ 90, 90, 180 },
{ 90, 75, 165 },
{ 75, 45, 120 },
{ 0, 0, 0 }
};
/* Ultra DMA timings (for use when I know how to calculate them */
static pmac_ide_timing udma_timings[] =
/* Ultra DMA timings (rounded) */
struct {
int addrSetup; /* ??? */
int rdy2pause;
int wrDataSetup;
} udma_timings[] __pmacdata =
{
{ 0, 114 }, /* Mode 0 */
{ 0, 75 }, /* 1 */
{ 0, 55 }, /* 2 */
{ 100, 45 }, /* 3 */
{ 100, 25 } /* 4 */
{ 0, 180, 120 }, /* Mode 0 */
{ 0, 150, 90 }, /* 1 */
{ 0, 120, 60 }, /* 2 */
{ 0, 90, 45 }, /* 3 */
{ 0, 90, 30 } /* 4 */
};
/* allow up to 256 DBDMA commands per xfer */
......@@ -124,7 +271,7 @@ struct pmu_sleep_notifier idepmac_sleep_notifier = {
};
#endif /* CONFIG_PMAC_PBOOK */
static int
static int __pmac
pmac_ide_find(ide_drive_t *drive)
{
struct ata_channel *hwif = drive->channel;
......@@ -143,7 +290,8 @@ pmac_ide_find(ide_drive_t *drive)
* N.B. this can't be an initfunc, because the media-bay task can
* call ide_[un]register at any time.
*/
void pmac_ide_init_hwif_ports(hw_regs_t *hw,
void __pmac
pmac_ide_init_hwif_ports(hw_regs_t *hw,
ide_ioreg_t data_port, ide_ioreg_t ctrl_port,
int *irq)
{
......@@ -174,7 +322,7 @@ void pmac_ide_init_hwif_ports(hw_regs_t *hw,
ide_hwifs[ix].tuneproc = pmac_ide_tuneproc;
ide_hwifs[ix].selectproc = pmac_ide_selectproc;
ide_hwifs[ix].speedproc = &pmac_ide_tune_chipset;
if (pmac_ide[ix].dma_regs && pmac_ide[ix].dma_table) {
if (pmac_ide[ix].dma_regs && pmac_ide[ix].dma_table_cpu) {
ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc;
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO
if (!noautodma)
......@@ -201,24 +349,33 @@ pmac_ide_get_devnode(ide_drive_t *drive)
/* Setup timings for the selected drive (master/slave). I still need to verify if this
* is enough, I beleive selectproc will be called whenever an IDE command is started,
* but... */
static void
static void __pmac
pmac_ide_selectproc(ide_drive_t *drive)
{
int i = pmac_ide_find(drive);
if (i < 0)
return;
if (drive->select.all & 0x10)
out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), pmac_ide[i].timings[1]);
if (drive->select.b.unit & 0x01)
out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE),
pmac_ide[i].timings[1]);
else
out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), pmac_ide[i].timings[0]);
out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE),
pmac_ide[i].timings[0]);
(void)in_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE));
}
/* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */
#define SYSCLK_TICKS(t) (((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS)
#define SYSCLK_TICKS_UDMA(t) (((t) + IDE_SYSCLK_ULTRA_PS - 1) / IDE_SYSCLK_ULTRA_PS)
static __inline__ int
/* Note: We don't use the generic routine here because for some
* yet unexplained reasons, it cause some media-bay CD-ROMs to
* lockup the bus. Strangely, this new version of the code is
* almost identical to the generic one and works, I've not yet
* managed to figure out what bit is causing the lockup in the
* generic code, possibly a timing issue...
*
* --BenH
*/
static int __pmac
wait_for_ready(ide_drive_t *drive)
{
/* Timeout bumped for some powerbooks */
......@@ -244,57 +401,80 @@ wait_for_ready(ide_drive_t *drive)
return 0;
}
/* Note: We don't use the generic routine here because some of Apple's
* controller seem to be very sensitive about how things are done.
* We should probably set the NIEN bit, but that's an example of thing
* that can cause the controller to hang under some circumstances when
* done on the media-bay CD-ROM during boot. We do get occasional
* spurrious interrupts because of that.
* --BenH
*/
static int
static int __pmac
pmac_ide_do_setfeature(ide_drive_t *drive, byte command)
{
unsigned long flags;
int result = 1;
unsigned long flags;
struct ata_channel *hwif = HWIF(drive);
save_flags(flags);
cli();
disable_irq(hwif->irq); /* disable_irq_nosync ?? */
udelay(1);
SELECT_DRIVE(drive->channel, drive);
SELECT_MASK(drive->channel, drive, 0);
udelay(1);
(void)GET_STAT(); /* Get rid of pending error state */
if(wait_for_ready(drive)) {
printk(KERN_ERR "pmac_ide_do_setfeature disk not ready before SET_FEATURE!\n");
goto out;
}
OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
udelay(10);
OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG);
OUT_BYTE(command, IDE_NSECTOR_REG);
OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG);
udelay(1);
__save_flags(flags); /* local CPU only */
ide__sti(); /* local CPU only -- for jiffies */
result = wait_for_ready(drive);
__restore_flags(flags); /* local CPU only */
OUT_BYTE(drive->ctl, IDE_CONTROL_REG);
if (result)
printk(KERN_ERR "pmac_ide_do_setfeature disk not ready after SET_FEATURE !\n");
out:
restore_flags(flags);
SELECT_MASK(HWIF(drive), drive, 0);
if (result == 0) {
drive->id->dma_ultra &= ~0xFF00;
drive->id->dma_mword &= ~0x0F00;
drive->id->dma_1word &= ~0x0F00;
switch(command) {
case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break;
case XFER_UDMA_6: drive->id->dma_ultra |= 0x4040; break;
case XFER_UDMA_5: drive->id->dma_ultra |= 0x2020; break;
case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break;
case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break;
case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break;
case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break;
case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break;
case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break;
case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break;
case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break;
case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break;
case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break;
case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break;
default: break;
}
}
enable_irq(hwif->irq);
return result;
}
/* Calculate PIO timings */
static void
static void __pmac
pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
{
struct ata_timing *t;
int i;
u32 *timings;
int accessTicks, recTicks;
unsigned accessTicks, recTicks;
unsigned accessTime, recTime;
i = pmac_ide_find(drive);
if (i < 0)
return;
if (pio = 255)
if (pio == 255)
pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO);
else
pio = XFER_PIO_0 + min_t(byte, pio, 4);
......@@ -302,27 +482,40 @@ pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
t = ata_timing_data(pio);
accessTicks = SYSCLK_TICKS(t->active);
if (drive->select.all & 0x10)
timings = &pmac_ide[i].timings[1];
else
timings = &pmac_ide[i].timings[0];
if (pmac_ide[i].kind == controller_kl_ata4) {
/* The "ata-4" IDE controller of Core99 machines */
accessTicks = SYSCLK_TICKS_UDMA(t->active * 1000);
recTicks = SYSCLK_TICKS_UDMA(t->cycle * 1000) - accessTicks;
*timings = ((*timings) & 0x1FFFFFC00) | accessTicks | (recTicks << 5);
timings = &pmac_ide[i].timings[drive->select.b.unit & 0x01];
recTime = t->cycle - t->active - t->setup;
recTime = max(recTime, 150U);
accessTime = t->active;
accessTime = max(accessTime, 150U);
if (pmac_ide[i].kind == controller_kl_ata4 ||
pmac_ide[i].kind == controller_kl_ata4_80) {
/* 66Mhz cell */
accessTicks = SYSCLK_TICKS_66(accessTime);
accessTicks = min(accessTicks, 0x1fU);
recTicks = SYSCLK_TICKS_66(recTime);
recTicks = min(recTicks, 0x1fU);
*timings = ((*timings) & ~TR_66_PIO_MASK) |
(accessTicks << TR_66_PIO_ACCESS_SHIFT) |
(recTicks << TR_66_PIO_RECOVERY_SHIFT);
} else {
/* The old "ata-3" IDE controller */
accessTicks = SYSCLK_TICKS(t->active);
if (accessTicks < 4)
accessTicks = 4;
recTicks = SYSCLK_TICKS(t->cycle) - accessTicks - 4;
if (recTicks < 1)
recTicks = 1;
*timings = ((*timings) & 0xFFFFFF800) | accessTicks | (recTicks << 5);
/* 33Mhz cell */
int ebit = 0;
accessTicks = SYSCLK_TICKS(accessTime);
accessTicks = min(accessTicks, 0x1fU);
accessTicks = max(accessTicks, 4U);
recTicks = SYSCLK_TICKS(recTime);
recTicks = min(recTicks, 0x1fU);
recTicks = max(recTicks, 5U) - 4;
if (recTicks > 9) {
recTicks--; /* guess, but it's only for PIO0, so... */
ebit = 1;
}
*timings = ((*timings) & ~TR_33_PIO_MASK) |
(accessTicks << TR_33_PIO_ACCESS_SHIFT) |
(recTicks << TR_33_PIO_RECOVERY_SHIFT);
if (ebit)
*timings |= TR_33_PIO_E;
}
#ifdef IDE_PMAC_DEBUG
......@@ -335,70 +528,134 @@ pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
}
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
static int
set_timings_udma(int intf, u32 *timings, byte speed)
static int __pmac
set_timings_udma(u32 *timings, byte speed)
{
int cycleTime, accessTime;
int rdyToPauseTicks, cycleTicks;
if (pmac_ide[intf].kind != controller_kl_ata4)
return 1;
unsigned rdyToPauseTicks, wrDataSetupTicks, addrTicks;
cycleTime = udma_timings[speed & 0xf].cycleTime;
accessTime = udma_timings[speed & 0xf].accessTime;
rdyToPauseTicks = SYSCLK_TICKS_66(udma_timings[speed & 0xf].rdy2pause);
wrDataSetupTicks = SYSCLK_TICKS_66(udma_timings[speed & 0xf].wrDataSetup);
addrTicks = SYSCLK_TICKS_66(udma_timings[speed & 0xf].addrSetup);
rdyToPauseTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
cycleTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000);
*timings = ((*timings) & 0xe00fffff) |
((cycleTicks << 1) | (rdyToPauseTicks << 5) | 1) << 20;
*timings = ((*timings) & ~(TR_66_UDMA_MASK | TR_66_MDMA_MASK)) |
(wrDataSetupTicks << TR_66_UDMA_WRDATASETUP_SHIFT) |
(rdyToPauseTicks << TR_66_UDMA_RDY2PAUS_SHIFT) |
(addrTicks <<TR_66_UDMA_ADDRSETUP_SHIFT) |
TR_66_UDMA_EN;
#ifdef IDE_PMAC_DEBUG
printk(KERN_ERR "ide_pmac: Set UDMA timing for mode %d, reg: 0x%08x\n",
speed & 0xf, *timings);
#endif
return 0;
}
static int
set_timings_mdma(int intf, u32 *timings, byte speed)
static int __pmac
set_timings_mdma(int intf_type, u32 *timings, byte speed, int drive_cycle_time)
{
int cycleTime, accessTime;
int accessTicks, recTicks;
int cycleTime, accessTime, recTime;
unsigned accessTicks, recTicks;
struct mdma_timings_t* tm;
int i;
/* Calculate accesstime and cycle time */
cycleTime = mdma_timings[speed & 0xf].cycleTime;
accessTime = mdma_timings[speed & 0xf].accessTime;
if ((pmac_ide[intf].kind == controller_ohare) && (cycleTime < 150))
/* Get default cycle time for mode */
switch(speed & 0xf) {
case 0: cycleTime = 480; break;
case 1: cycleTime = 150; break;
case 2: cycleTime = 120; break;
default:
return -1;
}
/* Adjust for drive */
if (drive_cycle_time && drive_cycle_time > cycleTime)
cycleTime = drive_cycle_time;
/* OHare limits according to some old Apple sources */
if ((intf_type == controller_ohare) && (cycleTime < 150))
cycleTime = 150;
/* Get the proper timing array for this controller */
switch(intf_type) {
case controller_kl_ata4:
case controller_kl_ata4_80:
tm = mdma_timings_66;
break;
case controller_kl_ata3:
tm = mdma_timings_33k;
break;
default:
tm = mdma_timings_33;
break;
}
/* Lookup matching access & recovery times */
i = -1;
for (;;) {
if (tm[i+1].cycleTime < cycleTime)
break;
i++;
}
if (i < 0)
return -1;
cycleTime = tm[i].cycleTime;
accessTime = tm[i].accessTime;
recTime = tm[i].recoveryTime;
/* For ata-4 controller */
if (pmac_ide[intf].kind == controller_kl_ata4) {
accessTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
recTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000) - accessTicks;
*timings = ((*timings) & 0xffe003ff) |
(accessTicks | (recTicks << 5)) << 10;
#ifdef IDE_PMAC_DEBUG
printk(KERN_ERR "ide_pmac: MDMA, cycleTime: %d, accessTime: %d, recTime: %d\n",
cycleTime, accessTime, recTime);
#endif
if (intf_type == controller_kl_ata4 || intf_type == controller_kl_ata4_80) {
/* 66Mhz cell */
accessTicks = SYSCLK_TICKS_66(accessTime);
accessTicks = min(accessTicks, 0x1fU);
accessTicks = max(accessTicks, 0x1U);
recTicks = SYSCLK_TICKS_66(recTime);
recTicks = min(recTicks, 0x1fU);
recTicks = max(recTicks, 0x3U);
/* Clear out mdma bits and disable udma */
*timings = ((*timings) & ~(TR_66_MDMA_MASK | TR_66_UDMA_MASK)) |
(accessTicks << TR_66_MDMA_ACCESS_SHIFT) |
(recTicks << TR_66_MDMA_RECOVERY_SHIFT);
} else if (intf_type == controller_kl_ata3) {
/* 33Mhz cell on KeyLargo */
accessTicks = SYSCLK_TICKS(accessTime);
accessTicks = max(accessTicks, 1U);
accessTicks = min(accessTicks, 0x1fU);
accessTime = accessTicks * IDE_SYSCLK_NS;
recTicks = SYSCLK_TICKS(recTime);
recTicks = max(recTicks, 1U);
recTicks = min(recTicks, 0x1fU);
*timings = ((*timings) & ~TR_33_MDMA_MASK) |
(accessTicks << TR_33_MDMA_ACCESS_SHIFT) |
(recTicks << TR_33_MDMA_RECOVERY_SHIFT);
} else {
/* 33Mhz cell on others */
int halfTick = 0;
int origAccessTime = accessTime;
int origCycleTime = cycleTime;
int origRecTime = recTime;
accessTicks = SYSCLK_TICKS(accessTime);
if (accessTicks < 1)
accessTicks = 1;
accessTicks = max(accessTicks, 1U);
accessTicks = min(accessTicks, 0x1fU);
accessTime = accessTicks * IDE_SYSCLK_NS;
recTicks = SYSCLK_TICKS(cycleTime - accessTime) - 1;
if (recTicks < 1)
recTicks = 1;
cycleTime = (recTicks + 1 + accessTicks) * IDE_SYSCLK_NS;
/* KeyLargo ata-3 don't support the half-tick stuff */
if ((pmac_ide[intf].kind != controller_kl_ata3) &&
(accessTicks > 1) &&
recTicks = SYSCLK_TICKS(recTime);
recTicks = max(recTicks, 2U) - 1;
recTicks = min(recTicks, 0x1fU);
recTime = (recTicks + 1) * IDE_SYSCLK_NS;
if ((accessTicks > 1) &&
((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) &&
((cycleTime - IDE_SYSCLK_NS) >= origCycleTime)) {
((recTime - IDE_SYSCLK_NS/2) >= origRecTime)) {
halfTick = 1;
accessTicks--;
}
*timings = ((*timings) & 0x7FF) |
(accessTicks | (recTicks << 5) | (halfTick << 10)) << 11;
*timings = ((*timings) & ~TR_33_MDMA_MASK) |
(accessTicks << TR_33_MDMA_ACCESS_SHIFT) |
(recTicks << TR_33_MDMA_RECOVERY_SHIFT);
if (halfTick)
*timings |= TR_33_MDMA_HALFTICK;
}
#ifdef IDE_PMAC_DEBUG
printk(KERN_ERR "ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n",
speed & 0xf, *timings);
#endif
return 0;
}
#endif /* #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC */
......@@ -406,11 +663,11 @@ set_timings_mdma(int intf, u32 *timings, byte speed)
/* You may notice we don't use this function on normal operation,
* our, normal mdma function is supposed to be more precise
*/
static int
static int __pmac
pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
{
int intf = pmac_ide_find(drive);
int unit = (drive->select.all & 0x10) ? 1:0;
int unit = (drive->select.b.unit & 0x01);
int ret = 0;
u32 *timings;
......@@ -423,19 +680,25 @@ pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
case XFER_UDMA_4:
case XFER_UDMA_3:
if (pmac_ide[intf].kind != controller_kl_ata4_80)
return 1;
case XFER_UDMA_2:
case XFER_UDMA_1:
case XFER_UDMA_0:
ret = set_timings_udma(intf, timings, speed);
if (pmac_ide[intf].kind != controller_kl_ata4 &&
pmac_ide[intf].kind != controller_kl_ata4_80)
return 1;
ret = set_timings_udma(timings, speed);
break;
case XFER_MW_DMA_2:
case XFER_MW_DMA_1:
case XFER_MW_DMA_0:
ret = set_timings_mdma(pmac_ide[intf].kind, timings, speed, 0);
break;
case XFER_SW_DMA_2:
case XFER_SW_DMA_1:
case XFER_SW_DMA_0:
ret = set_timings_mdma(intf, timings, speed);
break;
return 1;
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
case XFER_PIO_4:
case XFER_PIO_3:
......@@ -460,13 +723,46 @@ pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
return 0;
}
ide_ioreg_t
static void __pmac
sanitize_timings(int i)
{
unsigned value;
switch(pmac_ide[i].kind) {
case controller_kl_ata4:
case controller_kl_ata4_80:
value = 0x0008438c;
break;
case controller_kl_ata3:
value = 0x00084526;
break;
case controller_heathrow:
case controller_ohare:
default:
value = 0x00074526;
break;
}
pmac_ide[i].timings[0] = pmac_ide[i].timings[1] = value;
}
ide_ioreg_t __pmac
pmac_ide_get_base(int index)
{
return pmac_ide[index].regbase;
}
int
int __pmac
pmac_ide_check_base(ide_ioreg_t base)
{
int ix;
for (ix = 0; ix < MAX_HWIFS; ++ix)
if (base == pmac_ide[ix].regbase)
return ix;
return -1;
}
int __pmac
pmac_ide_get_irq(ide_ioreg_t base)
{
int ix;
......@@ -477,7 +773,7 @@ pmac_ide_get_irq(ide_ioreg_t base)
return 0;
}
static int ide_majors[] = { 3, 22, 33, 34, 56, 57 };
static int ide_majors[] __pmacdata = { 3, 22, 33, 34, 56, 57 };
kdev_t __init
pmac_find_ide_boot(char *bootdevice, int n)
......@@ -494,11 +790,11 @@ pmac_find_ide_boot(char *bootdevice, int n)
name = pmac_ide[i].node->full_name;
if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) {
/* XXX should cope with the 2nd drive as well... */
return MKDEV(ide_majors[i], 0);
return mk_kdev(ide_majors[i], 0);
}
}
return 0;
return NODEV;
}
void __init
......@@ -541,8 +837,11 @@ pmac_ide_probe(void)
for (i = 0, np = atas; i < MAX_HWIFS && np != NULL; np = np->next) {
struct device_node *tp;
struct pmac_ide_hwif *pmif;
int *bidp;
int in_bay = 0;
u8 pbus, pid;
struct pci_dev *pdev = NULL;
/*
* If this node is not under a mac-io or dbdma node,
......@@ -561,6 +860,15 @@ pmac_ide_probe(void)
continue;
}
/* We need to find the pci_dev of the mac-io holding the
* IDE interface
*/
if (pci_device_from_OF_node(tp, &pbus, &pid) == 0)
pdev = pci_find_slot(pbus, pid);
if (pdev == NULL)
printk(KERN_WARNING "ide: no PCI host for device %s, DMA disabled\n",
np->full_name);
/*
* If this slot is taken (e.g. by ide-pci.c) try the next one.
*/
......@@ -569,8 +877,23 @@ pmac_ide_probe(void)
++i;
if (i >= MAX_HWIFS)
break;
pmif = &pmac_ide[i];
base = (unsigned long) ioremap(np->addrs[0].address, 0x200) - _IO_BASE;
/*
* Some older OFs have bogus sizes, causing request_OF_resource
* to fail. We fix them up here
*/
if (np->addrs[0].size > 0x1000)
np->addrs[0].size = 0x1000;
if (np->n_addrs > 1 && np->addrs[1].size > 0x100)
np->addrs[1].size = 0x100;
if (request_OF_resource(np, 0, " (mac-io IDE IO)") == NULL) {
printk(KERN_ERR "ide-pmac(%s): can't request IO resource !\n", np->name);
continue;
}
base = (unsigned long) ioremap(np->addrs[0].address, 0x400) - _IO_BASE;
/* XXX This is bogus. Should be fixed in the registry by checking
the kind of host interrupt controller, a bit like gatwick
......@@ -583,21 +906,30 @@ pmac_ide_probe(void)
} else {
irq = np->intrs[0].line;
}
pmac_ide[i].regbase = base;
pmac_ide[i].irq = irq;
pmac_ide[i].node = np;
pmif->regbase = base;
pmif->irq = irq;
pmif->node = np;
if (device_is_compatible(np, "keylargo-ata")) {
if (strcmp(np->name, "ata-4") == 0)
pmac_ide[i].kind = controller_kl_ata4;
pmif->kind = controller_kl_ata4;
else
pmac_ide[i].kind = controller_kl_ata3;
pmif->kind = controller_kl_ata3;
} else if (device_is_compatible(np, "heathrow-ata"))
pmac_ide[i].kind = controller_heathrow;
pmif->kind = controller_heathrow;
else
pmac_ide[i].kind = controller_ohare;
pmif->kind = controller_ohare;
bidp = (int *)get_property(np, "AAPL,bus-id", NULL);
pmac_ide[i].aapl_bus_id = bidp ? *bidp : 0;
pmif->aapl_bus_id = bidp ? *bidp : 0;
if (pmif->kind == controller_kl_ata4) {
char* cable = get_property(np, "cable-type", NULL);
if (cable && !strncmp(cable, "80-", 3))
pmif->kind = controller_kl_ata4_80;
}
/* Make sure we have sane timings */
sanitize_timings(i);
if (np->parent && np->parent->name
&& strcasecmp(np->parent->name, "media-bay") == 0) {
......@@ -605,39 +937,22 @@ pmac_ide_probe(void)
media_bay_set_ide_infos(np->parent,base,irq,i);
#endif /* CONFIG_PMAC_PBOOK */
in_bay = 1;
} else if (pmac_ide[i].kind == controller_ohare) {
if (!bidp)
pmif->aapl_bus_id = 1;
} else if (pmif->kind == controller_ohare) {
/* The code below is having trouble on some ohare machines
* (timing related ?). Until I can put my hand on one of these
* units, I keep the old way
*/
feature_set(np, FEATURE_IDE0_enable);
ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1);
} else {
/* This is necessary to enable IDE when net-booting */
printk(KERN_INFO "pmac_ide: enabling IDE bus ID %d\n",
pmac_ide[i].aapl_bus_id);
switch(pmac_ide[i].aapl_bus_id) {
case 0:
feature_set(np, FEATURE_IDE0_reset);
mdelay(10);
feature_set(np, FEATURE_IDE0_enable);
mdelay(10);
feature_clear(np, FEATURE_IDE0_reset);
break;
case 1:
feature_set(np, FEATURE_IDE1_reset);
pmif->aapl_bus_id);
ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 1);
ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmif->aapl_bus_id, 1);
mdelay(10);
feature_set(np, FEATURE_IDE1_enable);
mdelay(10);
feature_clear(np, FEATURE_IDE1_reset);
break;
case 2:
/* This one exists only for KL, I don't know
about any enable bit */
feature_set(np, FEATURE_IDE2_reset);
mdelay(10);
feature_clear(np, FEATURE_IDE2_reset);
break;
}
ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 0);
big_delay = 1;
}
......@@ -646,13 +961,15 @@ pmac_ide_probe(void)
memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
hwif->chipset = ide_pmac;
hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || in_bay;
hwif->udma_four = (pmif->kind == controller_kl_ata4_80);
hwif->pci_dev = pdev;
#ifdef CONFIG_PMAC_PBOOK
if (in_bay && check_media_bay_by_base(base, MB_CD) == 0)
hwif->noprobe = 0;
#endif /* CONFIG_PMAC_PBOOK */
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
if (np->n_addrs >= 2) {
if (pdev && np->n_addrs >= 2) {
/* has a DBDMA controller channel */
pmac_ide_setup_dma(np, i);
}
......@@ -674,7 +991,15 @@ pmac_ide_probe(void)
static void __init
pmac_ide_setup_dma(struct device_node *np, int ix)
{
pmac_ide[ix].dma_regs =
struct pmac_ide_hwif *pmif = &pmac_ide[ix];
if (request_OF_resource(np, 1, " (mac-io IDE DMA)") == NULL) {
printk(KERN_ERR "ide-pmac(%s): can't request DMA resource !\n",
np->name);
return;
}
pmif->dma_regs =
(volatile struct dbdma_regs*)ioremap(np->addrs[1].address, 0x200);
/*
......@@ -682,14 +1007,24 @@ pmac_ide_setup_dma(struct device_node *np, int ix)
* The +2 is +1 for the stop command and +1 to allow for
* aligning the start address to a multiple of 16 bytes.
*/
pmac_ide[ix].dma_table = (struct dbdma_cmd*)
kmalloc((MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), GFP_KERNEL);
if (pmac_ide[ix].dma_table == 0) {
pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent(
ide_hwifs[ix].pci_dev,
(MAX_DCMDS + 2) * sizeof(struct dbdma_cmd),
&pmif->dma_table_dma);
if (pmif->dma_table_cpu == NULL) {
printk(KERN_ERR "%s: unable to allocate DMA command list\n",
ide_hwifs[ix].name);
return;
}
pmif->sg_table = kmalloc(sizeof(struct scatterlist) * MAX_DCMDS,
GFP_KERNEL);
if (pmif->sg_table == NULL) {
pci_free_consistent( ide_hwifs[ix].pci_dev,
(MAX_DCMDS + 2) * sizeof(struct dbdma_cmd),
pmif->dma_table_cpu, pmif->dma_table_dma);
return;
}
ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc;
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO
if (!noautodma)
......@@ -697,6 +1032,62 @@ pmac_ide_setup_dma(struct device_node *np, int ix)
#endif
}
static int
pmac_ide_build_sglist (int ix, struct request *rq)
{
struct ata_channel *hwif = &ide_hwifs[ix];
struct pmac_ide_hwif *pmif = &pmac_ide[ix];
request_queue_t *q = &hwif->drives[DEVICE_NR(rq->rq_dev) & 1].queue;
struct scatterlist *sg = pmif->sg_table;
int nents;
nents = blk_rq_map_sg(q, rq, pmif->sg_table);
if (rq->q && nents > rq->nr_phys_segments)
printk("ide-pmac: received %d phys segments, build %d\n", rq->nr_phys_segments, nents);
if (rq_data_dir(rq) == READ)
pmif->sg_dma_direction = PCI_DMA_FROMDEVICE;
else
pmif->sg_dma_direction = PCI_DMA_TODEVICE;
return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction);
}
static int
pmac_ide_raw_build_sglist (int ix, struct request *rq)
{
struct ata_channel *hwif = &ide_hwifs[ix];
struct pmac_ide_hwif *pmif = &pmac_ide[ix];
struct scatterlist *sg = pmif->sg_table;
int nents = 0;
ide_task_t *args = rq->special;
unsigned char *virt_addr = rq->buffer;
int sector_count = rq->nr_sectors;
if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
pmif->sg_dma_direction = PCI_DMA_TODEVICE;
else
pmif->sg_dma_direction = PCI_DMA_FROMDEVICE;
if (sector_count > 128) {
memset(&sg[nents], 0, sizeof(*sg));
sg[nents].page = virt_to_page(virt_addr);
sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK;
sg[nents].length = 128 * SECTOR_SIZE;
nents++;
virt_addr = virt_addr + (128 * SECTOR_SIZE);
sector_count -= 128;
}
memset(&sg[nents], 0, sizeof(*sg));
sg[nents].page = virt_to_page(virt_addr);
sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK;
sg[nents].length = sector_count * SECTOR_SIZE;
nents++;
return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction);
}
/*
* pmac_ide_build_dmatable builds the DBDMA command list
* for a transfer and sets the DBDMA channel to point to it.
......@@ -704,47 +1095,40 @@ pmac_ide_setup_dma(struct device_node *np, int ix)
static int
pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr)
{
struct dbdma_cmd *table, *tstart;
int count = 0;
struct dbdma_cmd *table;
int i, count = 0;
struct request *rq = HWGROUP(drive)->rq;
struct buffer_head *bh = rq->bh;
unsigned int size, addr;
volatile struct dbdma_regs *dma = pmac_ide[ix].dma_regs;
struct scatterlist *sg;
/* DMA table is already aligned */
table = (struct dbdma_cmd *) pmac_ide[ix].dma_table_cpu;
table = tstart = (struct dbdma_cmd *) DBDMA_ALIGN(pmac_ide[ix].dma_table);
/* Make sure DMA controller is stopped (necessary ?) */
out_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16);
while (in_le32(&dma->status) & RUN)
udelay(1);
do {
/*
* Determine addr and size of next buffer area. We assume that
* individual virtual buffers are always composed linearly in
* physical memory. For example, we assume that any 8kB buffer
* is always composed of two adjacent physical 4kB pages rather
* than two possibly non-adjacent physical 4kB pages.
*/
if (bh == NULL) { /* paging requests have (rq->bh == NULL) */
addr = virt_to_bus(rq->buffer);
size = rq->nr_sectors << 9;
/* Build sglist */
if (rq->flags & REQ_DRIVE_TASKFILE) {
pmac_ide[ix].sg_nents = i = pmac_ide_raw_build_sglist(ix, rq);
} else {
/* group sequential buffers into one large buffer */
addr = virt_to_bus(bh->b_data);
size = bh->b_size;
while ((bh = bh->b_reqnext) != NULL) {
if ((addr + size) != virt_to_bus(bh->b_data))
break;
size += bh->b_size;
}
pmac_ide[ix].sg_nents = i = pmac_ide_build_sglist(ix, rq);
}
if (!i)
return 0;
/*
* Fill in the next DBDMA command block.
* Note that one DBDMA command can transfer
* at most 65535 bytes.
*/
while (size) {
unsigned int tc = (size < 0xfe00)? size: 0xfe00;
/* Build DBDMA commands list */
sg = pmac_ide[ix].sg_table;
while (i) {
u32 cur_addr;
u32 cur_len;
cur_addr = sg_dma_address(sg);
cur_len = sg_dma_len(sg);
while (cur_len) {
unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00;
if (++count >= MAX_DCMDS) {
printk(KERN_WARNING "%s: DMA table too small\n",
......@@ -753,15 +1137,17 @@ pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr)
}
st_le16(&table->command, wr? OUTPUT_MORE: INPUT_MORE);
st_le16(&table->req_count, tc);
st_le32(&table->phy_addr, addr);
st_le32(&table->phy_addr, cur_addr);
table->cmd_dep = 0;
table->xfer_status = 0;
table->res_count = 0;
addr += tc;
size -= tc;
cur_addr += tc;
cur_len -= tc;
++table;
}
} while (bh != NULL);
sg++;
i--;
}
/* convert the last command to an input/output last command */
if (count)
......@@ -773,10 +1159,24 @@ pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr)
memset(table, 0, sizeof(struct dbdma_cmd));
out_le16(&table->command, DBDMA_STOP);
out_le32(&dma->cmdptr, virt_to_bus(tstart));
out_le32(&dma->cmdptr, pmac_ide[ix].dma_table_dma);
return 1;
}
/* Teardown mappings after DMA has completed. */
static void
pmac_ide_destroy_dmatable (ide_drive_t *drive, int ix)
{
struct pci_dev *dev = HWIF(drive)->pci_dev;
struct scatterlist *sg = pmac_ide[ix].sg_table;
int nents = pmac_ide[ix].sg_nents;
if (nents) {
pci_unmap_sg(dev, sg, nents, pmac_ide[ix].sg_dma_direction);
pmac_ide[ix].sg_nents = 0;
}
}
static __inline__ unsigned char
dma_bits_to_command(unsigned char bits)
......@@ -791,12 +1191,14 @@ dma_bits_to_command(unsigned char bits)
}
static __inline__ unsigned char
udma_bits_to_command(unsigned char bits)
udma_bits_to_command(unsigned char bits, int high_speed)
{
if (high_speed) {
if(bits & 0x10)
return XFER_UDMA_4;
if(bits & 0x08)
return XFER_UDMA_3;
}
if(bits & 0x04)
return XFER_UDMA_2;
if(bits & 0x02)
......@@ -807,14 +1209,13 @@ udma_bits_to_command(unsigned char bits)
}
/* Calculate MultiWord DMA timings */
static int
static int __pmac
pmac_ide_mdma_enable(ide_drive_t *drive, int idx)
{
byte bits = drive->id->dma_mword & 0x07;
byte feature = dma_bits_to_command(bits);
u32 *timings;
int cycleTime, accessTime;
int accessTicks, recTicks;
int drive_cycle_time;
struct hd_driveid *id = drive->id;
int ret;
......@@ -830,66 +1231,30 @@ pmac_ide_mdma_enable(ide_drive_t *drive, int idx)
drive->init_speed = feature;
/* which drive is it ? */
if (drive->select.all & 0x10)
if (drive->select.b.unit & 0x01)
timings = &pmac_ide[idx].timings[1];
else
timings = &pmac_ide[idx].timings[0];
/* Calculate accesstime and cycle time */
cycleTime = mdma_timings[feature & 0xf].cycleTime;
accessTime = mdma_timings[feature & 0xf].accessTime;
/* Check if drive provide explicit cycle time */
if ((id->field_valid & 2) && (id->eide_dma_time))
cycleTime = id->eide_dma_time;
if ((pmac_ide[idx].kind == controller_ohare) && (cycleTime < 150))
cycleTime = 150;
drive_cycle_time = id->eide_dma_time;
else
drive_cycle_time = 0;
/* For ata-4 controller */
if (pmac_ide[idx].kind == controller_kl_ata4) {
accessTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
recTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000) - accessTicks;
*timings = ((*timings) & 0xffe003ff) |
(accessTicks | (recTicks << 5)) << 10;
} else {
int halfTick = 0;
int origAccessTime = accessTime;
int origCycleTime = cycleTime;
/* Calculate controller timings */
set_timings_mdma(pmac_ide[idx].kind, timings, feature, drive_cycle_time);
accessTicks = SYSCLK_TICKS(accessTime);
if (accessTicks < 1)
accessTicks = 1;
accessTime = accessTicks * IDE_SYSCLK_NS;
recTicks = SYSCLK_TICKS(cycleTime - accessTime) - 1;
if (recTicks < 1)
recTicks = 1;
cycleTime = (recTicks + 1 + accessTicks) * IDE_SYSCLK_NS;
/* KeyLargo ata-3 don't support the half-tick stuff */
if ((pmac_ide[idx].kind != controller_kl_ata3) &&
(accessTicks > 1) &&
((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) &&
((cycleTime - IDE_SYSCLK_NS) >= origCycleTime)) {
halfTick = 1;
accessTicks--;
}
*timings = ((*timings) & 0x7FF) |
(accessTicks | (recTicks << 5) | (halfTick << 10)) << 11;
}
#ifdef IDE_PMAC_DEBUG
printk(KERN_INFO "ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n",
feature & 0xf, *timings);
#endif
drive->current_speed = feature;
return 1;
}
/* Calculate Ultra DMA timings */
static int
pmac_ide_udma_enable(ide_drive_t *drive, int idx)
static int __pmac
pmac_ide_udma_enable(ide_drive_t *drive, int idx, int high_speed)
{
byte bits = drive->id->dma_ultra & 0x1f;
byte feature = udma_bits_to_command(bits);
int cycleTime, accessTime;
int rdyToPauseTicks, cycleTicks;
byte feature = udma_bits_to_command(bits, high_speed);
u32 *timings;
int ret;
......@@ -905,25 +1270,18 @@ pmac_ide_udma_enable(ide_drive_t *drive, int idx)
drive->init_speed = feature;
/* which drive is it ? */
if (drive->select.all & 0x10)
if (drive->select.b.unit & 0x01)
timings = &pmac_ide[idx].timings[1];
else
timings = &pmac_ide[idx].timings[0];
cycleTime = udma_timings[feature & 0xf].cycleTime;
accessTime = udma_timings[feature & 0xf].accessTime;
rdyToPauseTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
cycleTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000);
*timings = ((*timings) & 0xe00fffff) |
((cycleTicks << 1) | (rdyToPauseTicks << 5) | 1) << 20;
set_timings_udma(timings, feature);
drive->current_speed = feature;
return 1;
}
static int
static int __pmac
pmac_ide_check_dma(ide_drive_t *drive)
{
int ata4, udma, idx;
......@@ -944,21 +1302,20 @@ pmac_ide_check_dma(ide_drive_t *drive)
enable = 0;
udma = 0;
ata4 = (pmac_ide[idx].kind == controller_kl_ata4);
ata4 = (pmac_ide[idx].kind == controller_kl_ata4 ||
pmac_ide[idx].kind == controller_kl_ata4_80);
if(enable) {
if (ata4 && (drive->type == ATA_DISK) &&
(id->field_valid & 0x0004) && (id->dma_ultra & 0x17)) {
(id->field_valid & 0x0004) && (id->dma_ultra & 0x1f)) {
/* UltraDMA modes. */
drive->using_dma = pmac_ide_udma_enable(drive, idx);
drive->using_dma = pmac_ide_udma_enable(drive, idx,
pmac_ide[idx].kind == controller_kl_ata4_80);
}
if (!drive->using_dma && (id->dma_mword & 0x0007)) {
/* Normal MultiWord DMA modes. */
drive->using_dma = pmac_ide_mdma_enable(drive, idx);
}
/* Without this, strange things will happen on Keylargo-based
* machines
*/
OUT_BYTE(0, IDE_CONTROL_REG);
/* Apply settings to controller */
pmac_ide_selectproc(drive);
......@@ -966,10 +1323,25 @@ pmac_ide_check_dma(ide_drive_t *drive)
return 0;
}
static void ide_toggle_bounce(ide_drive_t *drive, int on)
{
dma64_addr_t addr = BLK_BOUNCE_HIGH;
if (on && drive->type == ATA_DISK && HWIF(drive)->highmem) {
if (!PCI_DMA_BUS_IS_PHYS)
addr = BLK_BOUNCE_ANY;
else
addr = HWIF(drive)->pci_dev->dma_mask;
}
blk_queue_bounce_limit(&drive->queue, addr);
}
int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
{
int ix, dstat, i;
int ix, dstat, reading, ata4;
volatile struct dbdma_regs *dma;
byte unit = (drive->select.b.unit & 0x01);
/* Can we stuff a pointer to our intf structure in config_data
* or select_data in hwif ?
......@@ -978,59 +1350,106 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
if (ix < 0)
return 0;
dma = pmac_ide[ix].dma_regs;
ata4 = (pmac_ide[ix].kind == controller_kl_ata4 ||
pmac_ide[ix].kind == controller_kl_ata4_80);
switch (func) {
case ide_dma_off:
printk(KERN_INFO "%s: DMA disabled\n", drive->name);
case ide_dma_off_quietly:
drive->using_dma = 0;
ide_toggle_bounce(drive, 0);
break;
case ide_dma_on:
case ide_dma_check:
/* Change this to better match ide-dma.c */
pmac_ide_check_dma(drive);
ide_toggle_bounce(drive, drive->using_dma);
break;
case ide_dma_read:
case ide_dma_write:
if (!pmac_ide_build_dmatable(drive, ix, func==ide_dma_write))
/* this almost certainly isn't needed since we don't
appear to have a rwproc */
if (HWIF(drive)->rwproc)
HWIF(drive)->rwproc(drive, func);
reading = (func == ide_dma_read);
if (!pmac_ide_build_dmatable(drive, ix, !reading))
return 1;
/* Apple adds 60ns to wrDataSetup on reads */
if (ata4 && (pmac_ide[ix].timings[unit] & TR_66_UDMA_EN)) {
out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE),
pmac_ide[ix].timings[unit] +
((func == ide_dma_read) ? 0x00800000UL : 0));
(void)in_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE));
}
drive->waiting_for_dma = 1;
if (drive->type != ATA_DISK)
return 0;
BUG_ON(HWGROUP(drive)->handler);
ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
OUT_BYTE(func==ide_dma_write? WIN_WRITEDMA: WIN_READDMA,
IDE_COMMAND_REG);
if ((HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) &&
(drive->addressing == 1)) {
ide_task_t *args = HWGROUP(drive)->rq->special;
OUT_BYTE(args->taskfile.command, IDE_COMMAND_REG);
} else if (drive->addressing) {
OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG);
} else {
OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
}
/* fall through */
case ide_dma_begin:
out_le32(&dma->control, (RUN << 16) | RUN);
/* Make sure it gets to the controller right now */
(void)in_le32(&dma->control);
break;
case ide_dma_end:
case ide_dma_end: /* returns 1 on error, 0 otherwise */
drive->waiting_for_dma = 0;
dstat = in_le32(&dma->status);
out_le32(&dma->control, ((RUN|WAKE|DEAD) << 16));
pmac_ide_destroy_dmatable(drive, ix);
/* verify good dma status */
return (dstat & (RUN|DEAD|ACTIVE)) != RUN;
case ide_dma_test_irq:
if ((in_le32(&dma->status) & (RUN|ACTIVE)) == RUN)
return 1;
/* That's a bit ugly and dangerous, but works in our case
* to workaround a problem with the channel status staying
* active if the drive returns an error
case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
/* We have to things to deal with here:
*
* - The dbdma won't stop if the command was started
* but completed with an error without transfering all
* datas. This happens when bad blocks are met during
* a multi-block transfer.
*
* - The dbdma fifo hasn't yet finished flushing to
* to system memory when the disk interrupt occurs.
*
* The trick here is to increment drive->waiting_for_dma,
* and return as if no interrupt occured. If the counter
* reach a certain timeout value, we then return 1. If
* we really got the interrupt, it will happen right away
* again.
* Apple's solution here may be more elegant. They issue
* a DMA channel interrupt (a separate irq line) via a DBDMA
* NOP command just before the STOP, and wait for both the
* disk and DBDMA interrupts to have completed.
*/
if (IDE_CONTROL_REG) {
byte stat;
stat = GET_ALTSTAT();
if (stat & ERR_STAT)
/* If ACTIVE is cleared, the STOP command have passed and
* transfer is complete.
*/
if (!(in_le32(&dma->status) & ACTIVE))
return 1;
if (!drive->waiting_for_dma)
printk(KERN_WARNING "ide%d, ide_dma_test_irq \
called while not waiting\n", ix);
/* If dbdma didn't execute the STOP command yet, the
* active bit is still set */
drive->waiting_for_dma++;
if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) {
printk(KERN_WARNING "ide%d, timeout waiting \
for dbdma command stop\n", ix);
return 1;
}
/* In some edge cases, some datas may still be in the dbdma
* engine fifo, we wait a bit for dbdma to complete
*/
while ((in_le32(&dma->status) & (RUN|ACTIVE)) != RUN) {
if (++i > 100)
return 0;
udelay(1);
}
return 1;
return 0;
/* Let's implement tose just in case someone wants them */
case ide_dma_bad_drive:
......@@ -1051,7 +1470,6 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
}
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
#ifdef CONFIG_PMAC_PBOOK
static void idepmac_sleep_device(ide_drive_t *drive, int i, unsigned base)
{
int j;
......@@ -1062,7 +1480,9 @@ static void idepmac_sleep_device(ide_drive_t *drive, int i, unsigned base)
switch (drive->type) {
case ATA_DISK:
/* Spin down the drive */
outb(0xa0, base+0x60);
outb(drive->select.all, base+0x60);
(void)inb(base+0x60);
udelay(100);
outb(0x0, base+0x30);
outb(0x0, base+0x20);
outb(0x0, base+0x40);
......@@ -1086,19 +1506,21 @@ static void idepmac_sleep_device(ide_drive_t *drive, int i, unsigned base)
}
}
static void idepmac_wake_device(ide_drive_t *drive, int used_dma)
{
#ifdef CONFIG_PMAC_PBOOK
static void __pmac
idepmac_wake_device(ide_drive_t *drive, int used_dma)
{
/* We force the IDE subdriver to check for a media change
* This must be done first or we may lost the condition
*
* Problem: This can schedule. I moved the block device
* wakeup almost late by priority because of that.
*/
if (DRIVER(drive) && DRIVER(drive)->media_change)
DRIVER(drive)->media_change(drive);
if (drive->driver != NULL && ata_ops(drive)->check_media_change)
ata_ops(drive)->check_media_change(drive);
/* We kick the VFS too (see fix in ide.c revalidate) */
check_disk_change(MKDEV(drive->channel->major, (drive->select.b.unit) << PARTN_BITS));
check_disk_change(mk_kdev(drive->channel->major, (drive->select.b.unit) << PARTN_BITS));
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
/* We re-enable DMA on the drive if it was active. */
......@@ -1108,15 +1530,16 @@ static void idepmac_wake_device(ide_drive_t *drive, int used_dma)
*/
if (used_dma && !ide_spin_wait_hwgroup(drive)) {
/* Lock HW group */
HWGROUP(drive)->busy = 1;
set_bit(IDE_BUSY, &HWGROUP(drive)->flags);
pmac_ide_check_dma(drive);
HWGROUP(drive)->busy = 0;
clear_bit(IDE_BUSY, &HWGROUP(drive)->flags);
spin_unlock_irq(&ide_lock);
}
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
}
static void idepmac_sleep_interface(int i, unsigned base, int mediabay)
static void __pmac
idepmac_sleep_interface(int i, unsigned base, int mediabay)
{
struct device_node* np = pmac_ide[i].node;
......@@ -1128,71 +1551,79 @@ static void idepmac_sleep_interface(int i, unsigned base, int mediabay)
if (mediabay)
return;
/* Disable and reset the bus */
feature_set(np, FEATURE_IDE0_reset);
feature_clear(np, FEATURE_IDE0_enable);
switch(pmac_ide[i].aapl_bus_id) {
case 0:
feature_set(np, FEATURE_IDE0_reset);
feature_clear(np, FEATURE_IDE0_enable);
break;
case 1:
feature_set(np, FEATURE_IDE1_reset);
feature_clear(np, FEATURE_IDE1_enable);
break;
case 2:
feature_set(np, FEATURE_IDE2_reset);
break;
}
/* Disable the bus */
ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmac_ide[i].aapl_bus_id, 0);
}
static void idepmac_wake_interface(int i, unsigned long base, int mediabay)
static void __pmac
idepmac_wake_interface(int i, unsigned long base, int mediabay)
{
struct device_node* np = pmac_ide[i].node;
if (!mediabay) {
/* Revive IDE disk and controller */
switch(pmac_ide[i].aapl_bus_id) {
case 0:
feature_set(np, FEATURE_IDE0_reset);
feature_set(np, FEATURE_IOBUS_enable);
mdelay(10);
feature_set(np, FEATURE_IDE0_enable);
mdelay(10);
feature_clear(np, FEATURE_IDE0_reset);
break;
case 1:
feature_set(np, FEATURE_IDE1_reset);
feature_set(np, FEATURE_IOBUS_enable);
mdelay(10);
feature_set(np, FEATURE_IDE1_enable);
mdelay(10);
feature_clear(np, FEATURE_IDE1_reset);
break;
case 2:
/* This one exists only for KL, I don't know
about any enable bit */
feature_set(np, FEATURE_IDE2_reset);
ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmac_ide[i].aapl_bus_id, 1);
ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmac_ide[i].aapl_bus_id, 1);
mdelay(10);
feature_clear(np, FEATURE_IDE2_reset);
break;
ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmac_ide[i].aapl_bus_id, 0);
}
}
static void
idepmac_sleep_drive(ide_drive_t *drive, int idx, unsigned long base)
{
/* Wait for HW group to complete operations */
if (ide_spin_wait_hwgroup(drive))
// What can we do here ? Wake drive we had already
// put to sleep and return an error ?
return;
else {
/* Lock HW group */
set_bit(IDE_BUSY, &HWGROUP(drive)->flags);
/* Stop the device */
idepmac_sleep_device(drive, idx, base);
spin_unlock_irq(&ide_lock);
}
}
static void
idepmac_wake_drive(ide_drive_t *drive, unsigned long base)
{
int j;
/* Reset timings */
pmac_ide_selectproc(&ide_hwifs[i].drives[0]);
pmac_ide_selectproc(drive);
mdelay(10);
/* Wait up to 20 seconds for the drive to be ready */
for (j = 0; j < 200; j++) {
int status;
mdelay(100);
outb(drive->select.all, base + 0x60);
if (inb(base + 0x60) != drive->select.all)
continue;
status = inb(base + 0x70);
if (!(status & BUSY_STAT))
break;
}
/* We resume processing on the HW group */
spin_lock_irq(&ide_lock);
clear_bit(IDE_BUSY, &HWGROUP(drive)->flags);
if (!list_empty(&drive->queue.queue_head))
do_ide_request(&drive->queue);
spin_unlock_irq(&ide_lock);
}
/* Note: We support only master drives for now. This will have to be
* improved if we want to handle sleep on the iMacDV where the CD-ROM
* is a slave
*/
static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
static int __pmac
idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
{
int i, ret;
unsigned long base;
unsigned long flags;
int big_delay;
switch (when) {
......@@ -1203,34 +1634,19 @@ static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
case PBOOK_SLEEP_NOW:
for (i = 0; i < pmac_ide_count; ++i) {
struct ata_channel *hwif;
ide_drive_t *drive;
int unlock = 0;
int dn;
if ((base = pmac_ide[i].regbase) == 0)
continue;
hwif = &ide_hwifs[i];
drive = &hwif->drives[0];
if (drive->present) {
/* Wait for HW group to complete operations */
if (ide_spin_wait_hwgroup(drive)) {
// What can we do here ? Wake drive we had already
// put to sleep and return an error ?
} else {
unlock = 1;
/* Lock HW group */
HWGROUP(drive)->busy = 1;
/* Stop the device */
idepmac_sleep_device(drive, i, base);
}
for (dn=0; dn<MAX_DRIVES; dn++) {
if (!hwif->drives[dn].present)
continue;
idepmac_sleep_drive(&hwif->drives[dn], i, base);
}
/* Disable irq during sleep */
disable_irq(pmac_ide[i].irq);
if (unlock)
spin_unlock_irq(&ide_lock);
/* Check if this is a media bay with an IDE device or not
* a media bay.
......@@ -1247,6 +1663,9 @@ static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
if ((base = pmac_ide[i].regbase) == 0)
continue;
/* Make sure we have sane timings */
sanitize_timings(i);
/* Check if this is a media bay with an IDE device or not
* a media bay
*/
......@@ -1263,44 +1682,30 @@ static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
for (i = 0; i < pmac_ide_count; ++i) {
struct ata_channel *hwif;
ide_drive_t *drive;
int j, used_dma;
int used_dma, dn;
int irq_on = 0;
if ((base = pmac_ide[i].regbase) == 0)
continue;
hwif = &ide_hwifs[i];
drive = &hwif->drives[0];
/* Wait for the drive to come up and set it's DMA */
if (drive->present) {
/* Wait up to 20 seconds */
for (j = 0; j < 200; j++) {
int status;
mdelay(100);
status = inb(base + 0x70);
if (!(status & BUSY_STAT))
break;
}
}
for (dn=0; dn<MAX_DRIVES; dn++) {
ide_drive_t *drive = &hwif->drives[dn];
if (!drive->present)
continue;
/* We don't have re-configured DMA yet */
used_dma = drive->using_dma;
drive->using_dma = 0;
/* We resume processing on the HW group */
spin_lock_irqsave(&ide_lock, flags);
idepmac_wake_drive(drive, base);
if (!irq_on) {
enable_irq(pmac_ide[i].irq);
if (drive->present)
HWGROUP(drive)->busy = 0;
spin_unlock_irqrestore(&ide_lock, flags);
/* Wake the device
* We could handle the slave here
*/
if (drive->present)
irq_on = 1;
}
idepmac_wake_device(drive, used_dma);
}
if (!irq_on)
enable_irq(pmac_ide[i].irq);
}
break;
}
return PBOOK_SLEEP_OK;
......
......@@ -16,6 +16,7 @@
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/types.h>
#include <linux/ide.h>
#include <linux/init.h>
......
......@@ -140,7 +140,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
/* kludge for Apple PowerBook internal zip */
if (!strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP")) {
printk ("FLOPPY");
type = ide_floppy;
type = ATA_FLOPPY;
break;
}
#endif
......@@ -666,13 +666,12 @@ static int init_irq(struct ata_channel *hwif)
hwif->sharing_irq = h->sharing_irq = 1;
if (hwif->chipset != ide_pci || h->chipset != ide_pci)
save_match(hwif, h, &match);
}
if (hwif->serialized) {
if (hwif->mate && hwif->mate->irq == h->irq)
save_match(hwif, h, &match);
}
if (h->serialized) {
if (h->mate && hwif->irq == h->mate->irq)
/* FIXME: This is still confusing. What would
* happen if we match-ed two times?
*/
if (hwif->serialized || h->serialized)
save_match(hwif, h, &match);
}
}
......@@ -823,12 +822,11 @@ static void init_gendisk(struct ata_channel *hwif)
for (unit = 0; unit < MAX_DRIVES; ++unit) {
char name[80];
ide_add_generic_settings(hwif->drives + unit);
hwif->drives[unit].dn = ((hwif->unit ? 2 : 0) + unit);
sprintf (name, "host%d/bus%d/target%d/lun%d",
(hwif->unit && hwif->mate) ?
hwif->mate->index : hwif->index,
hwif->unit, unit, hwif->drives[unit].lun);
hwif->index, hwif->unit, unit, hwif->drives[unit].lun);
if (hwif->drives[unit].present)
hwif->drives[unit].de = devfs_mk_dir(ide_devfs_handle, name, NULL);
}
......
......@@ -164,19 +164,6 @@ static int proc_ide_read_imodel
PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
}
static int proc_ide_read_mate
(char *page, char **start, off_t off, int count, int *eof, void *data)
{
struct ata_channel *hwif = data;
int len;
if (hwif && hwif->mate && hwif->mate->present)
len = sprintf(page, "%s\n", hwif->mate->name);
else
len = sprintf(page, "(none)\n");
PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
}
static int proc_ide_read_channel
(char *page, char **start, off_t off, int count, int *eof, void *data)
{
......@@ -493,7 +480,6 @@ void destroy_proc_ide_drives(struct ata_channel *hwif)
static ide_proc_entry_t hwif_entries[] = {
{ "channel", S_IFREG|S_IRUGO, proc_ide_read_channel, NULL },
{ "mate", S_IFREG|S_IRUGO, proc_ide_read_mate, NULL },
{ "model", S_IFREG|S_IRUGO, proc_ide_read_imodel, NULL },
{ NULL, 0, NULL, NULL }
};
......
......@@ -2177,7 +2177,7 @@ int ide_register_hw(hw_regs_t *hw, struct ata_channel **hwifp)
}
for (h = 0; h < MAX_HWIFS; ++h) {
hwif = &ide_hwifs[h];
if ((!hwif->present && !hwif->mate && !initializing) ||
if ((!hwif->present && (hwif->unit == ATA_PRIMARY) && !initializing) ||
(!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing))
goto found;
}
......@@ -3052,9 +3052,13 @@ int __init ide_setup (char *s)
goto done;
case -2: /* "serialize" */
do_serialize:
hwif->mate = &ide_hwifs[hw^1];
hwif->mate->mate = hwif;
hwif->serialized = hwif->mate->serialized = 1;
{
struct ata_channel *mate;
mate = &ide_hwifs[hw ^ 1];
hwif->serialized = 1;
mate->serialized = 1;
}
goto done;
case -1: /* "noprobe" */
......
......@@ -141,9 +141,19 @@ void __init ide_init_ns87415(struct ata_channel *hwif)
using_inta = progif & (1 << (hwif->unit << 1));
if (!using_inta)
using_inta = ctrl & (1 << (4 + hwif->unit));
if (hwif->mate) {
hwif->select_data = hwif->mate->select_data;
if (hwif->unit == ATA_SECONDARY) {
/* FIXME: If we are initializing the secondary channel, let us
* assume that the primary channel got initialized just a tad
* bit before now. It would be much cleaner if the data in
* ns87415_control just got duplicated.
*/
if (!hwif->select_data)
hwif->select_data = (unsigned long)
&ns87415_control[ns87415_count - 1];
} else {
if (!hwif->select_data)
hwif->select_data = (unsigned long)
&ns87415_control[ns87415_count++];
ctrl |= (1 << 8) | (1 << 9); /* mask both IRQs */
......@@ -181,13 +191,23 @@ void __init ide_init_ns87415(struct ata_channel *hwif)
if (!using_inta)
hwif->irq = hwif->unit ? 15 : 14; /* legacy mode */
else if (!hwif->irq && hwif->mate && hwif->mate->irq)
hwif->irq = hwif->mate->irq; /* share IRQ with mate */
else {
static int primary_irq = 0;
/* Ugly way to let the primary and secondary channel on the
* chip use the same IRQ line.
*/
if (hwif->unit == ATA_PRIMARY)
primary_irq = hwif->irq;
else if (!hwif->irq)
hwif->irq = primary_irq;
}
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base)
hwif->dmaproc = &ns87415_dmaproc;
#endif /* CONFIG_BLK_DEV_IDEDMA */
#endif
hwif->selectproc = &ns87415_selectproc;
}
......@@ -224,9 +224,8 @@ int __init setup_pdc4030(struct ata_channel *hwif)
*/
hwif->chipset = hwif2->chipset = ide_pdc4030;
hwif->mate = hwif2;
hwif2->mate = hwif;
hwif2->unit = 1;
hwif->unit = ATA_PRIMARY;
hwif2->unit = ATA_SECONDARY;
hwif->selectproc = hwif2->selectproc = &promise_selectproc;
hwif->serialized = hwif2->serialized = 1;
......
/*
* $Id: piix.c,v 1.2 2002/03/13 22:50:43 vojtech Exp $
* $Id: piix.c,v 1.3 2002/03/29 16:06:06 vojtech Exp $
*
* Copyright (c) 2000-2002 Vojtech Pavlik
*
......@@ -128,7 +128,7 @@ static int piix_get_info(char *buffer, char **addr, off_t offset, int count)
piix_print("----------PIIX BusMastering IDE Configuration---------------");
piix_print("Driver Version: 1.2");
piix_print("Driver Version: 1.3");
piix_print("South Bridge: %s", bmide_dev->name);
pci_read_config_byte(dev, PCI_REVISION_ID, &t);
......@@ -331,7 +331,7 @@ static int piix_set_drive(ide_drive_t *drive, unsigned char speed)
umul = 2;
T = 1000000000 / piix_clock;
UT = T / umul;
UT = umul ? (T / umul) : 0;
ata_timing_compute(drive, speed, &t, T, UT);
......
......@@ -411,22 +411,23 @@ int __init probe (int base)
return 1;
} else {
int i,j;
int i;
/* secondary enabled */
printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n",
ide_hwifs[0].name,ide_hwifs[1].name);
for (i=0;i<2;i++) {
for (i = 0; i < 2; i++) {
int j;
ide_hwifs[i].chipset = ide_qd65xx;
ide_hwifs[i].mate = &ide_hwifs[i^1];
ide_hwifs[i].unit = i;
ide_hwifs[i].select_data = base;
ide_hwifs[i].config_data = config | (control <<8);
ide_hwifs[i].tuneproc = &qd6580_tune_drive;
for (j=0;j<2;j++) {
for (j = 0; j < 2; j++) {
ide_hwifs[i].drives[j].drive_data =
i?QD6580_DEF_DATA2:QD6580_DEF_DATA;
ide_hwifs[i].drives[j].io_32bit = 1;
......
/*
* linux/drivers/ide/sis5513.c Version 0.13 March 4, 2002
* linux/drivers/ide/sis5513.c Version 0.13 March 6, 2002
*
* Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
* May be copied or modified under the terms of the GNU General Public License
*
*/
/* Thanks :
* For direct support and hardware : SiS Taiwan.
* For ATA100 support advice : Daniela Engert.
* For checking code correctness, providing patches :
* John Fremlin, Manfred Spraul
*
* Thanks :
*
* SiS Taiwan : for direct support and hardware.
* Daniela Engert : for initial ATA100 advices and numerous others.
* John Fremlin, Manfred Spraul :
* for checking code correctness, providing patches.
*/
/*
......@@ -52,59 +52,40 @@
#include "ata-timing.h"
/* When DEBUG is defined it outputs initial PCI config register
values and changes made to them by the driver */
// #define DEBUG
/* if BROKEN_LEVEL is defined it limits the DMA mode
/* When BROKEN_LEVEL is defined it limits the DMA mode
at boot time to its value */
// #define BROKEN_LEVEL XFER_SW_DMA_0
#define DISPLAY_SIS_TIMINGS
/* Miscellaneaous flags */
#define SIS5513_LATENCY 0x01
/* ATA transfer mode capabilities */
/* registers layout and init values are chipset family dependant */
/* 1/ define families */
#define ATA_00 0x00
#define ATA_16 0x01
#define ATA_33 0x02
#define ATA_66 0x03
#define ATA_100a 0x04
#define ATA_100a 0x04 // SiS730 is ATA100 with ATA66 layout
#define ATA_100 0x05
#define ATA_133 0x06
static unsigned char dma_capability = 0x00;
/* 2/ variable holding the controller chipset family value */
static unsigned char chipset_family;
/*
* Debug code: following IDE config registers' changes
*/
#ifdef DEBUG
/* Copy of IDE Config registers 0x00 -> 0x58
/* Copy of IDE Config registers 0x00 -> 0x57
Fewer might be used depending on the actual chipset */
static unsigned char ide_regs_copy[] = {
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0
};
static unsigned char ide_regs_copy[0x58];
static byte sis5513_max_config_register(void) {
switch(dma_capability) {
switch(chipset_family) {
case ATA_00:
case ATA_16: return 0x4f;
case ATA_33: return 0x52;
......@@ -185,7 +166,7 @@ static void sis5513_print_registers(struct pci_dev* dev, char* marker) {
static const struct {
const char *name;
unsigned short host_id;
unsigned char dma_capability;
unsigned char chipset_family;
unsigned char flags;
} SiSHostChipInfo[] = {
{ "SiS750", PCI_DEVICE_ID_SI_750, ATA_100, SIS5513_LATENCY },
......@@ -211,7 +192,7 @@ static const struct {
/* Cycle time bits and values vary accross chip dma capabilities
These three arrays hold the register layout and the values to set.
Indexed by dma_capability and (dma_mode - XFER_UDMA_0) */
Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */
static byte cycle_time_offset[] = {0,0,5,4,4,0,0};
static byte cycle_time_range[] = {0,0,2,3,3,4,4};
static byte cycle_time_value[][XFER_UDMA_5 - XFER_UDMA_0 + 1] = {
......@@ -293,13 +274,13 @@ static char* get_drives_info (char *buffer, byte pos)
pci_read_config_byte(bmide_dev, 0x45+2*pos, &reg11);
/* UDMA */
if (dma_capability >= ATA_33) {
if (chipset_family >= ATA_33) {
p += sprintf(p, " UDMA %s \t \t \t UDMA %s\n",
(reg01 & 0x80) ? "Enabled" : "Disabled",
(reg11 & 0x80) ? "Enabled" : "Disabled");
p += sprintf(p, " UDMA Cycle Time ");
switch(dma_capability) {
switch(chipset_family) {
case ATA_33: p += sprintf(p, cycle_time[(reg01 & 0x60) >> 5]); break;
case ATA_66:
case ATA_100a: p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break;
......@@ -308,7 +289,7 @@ static char* get_drives_info (char *buffer, byte pos)
default: p += sprintf(p, "133+ ?"); break;
}
p += sprintf(p, " \t UDMA Cycle Time ");
switch(dma_capability) {
switch(chipset_family) {
case ATA_33: p += sprintf(p, cycle_time[(reg11 & 0x60) >> 5]); break;
case ATA_66:
case ATA_100a: p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break;
......@@ -321,7 +302,7 @@ static char* get_drives_info (char *buffer, byte pos)
/* Data Active */
p += sprintf(p, " Data Active Time ");
switch(dma_capability) {
switch(chipset_family) {
case ATA_00:
case ATA_16: /* confirmed */
case ATA_33:
......@@ -332,7 +313,7 @@ static char* get_drives_info (char *buffer, byte pos)
default: p += sprintf(p, "133+ ?"); break;
}
p += sprintf(p, " \t Data Active Time ");
switch(dma_capability) {
switch(chipset_family) {
case ATA_00:
case ATA_16:
case ATA_33:
......@@ -370,7 +351,7 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
u16 reg2, reg3;
p += sprintf(p, "\nSiS 5513 ");
switch(dma_capability) {
switch(chipset_family) {
case ATA_00: p += sprintf(p, "Unknown???"); break;
case ATA_16: p += sprintf(p, "DMA 16"); break;
case ATA_33: p += sprintf(p, "Ultra 33"); break;
......@@ -386,7 +367,7 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
/* Status */
pci_read_config_byte(bmide_dev, 0x4a, &reg);
p += sprintf(p, "Channel Status: ");
if (dma_capability < ATA_66) {
if (chipset_family < ATA_66) {
p += sprintf(p, "%s \t \t \t \t %s\n",
(reg & 0x04) ? "On" : "Off",
(reg & 0x02) ? "On" : "Off");
......@@ -403,7 +384,7 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
(reg & 0x04) ? "Native" : "Compatible");
/* 80-pin cable ? */
if (dma_capability > ATA_33) {
if (chipset_family > ATA_33) {
pci_read_config_byte(bmide_dev, 0x48, &reg);
p += sprintf(p, "Cable Type: %s \t \t \t %s\n",
(reg & 0x10) ? cable_type[1] : cable_type[0],
......@@ -507,7 +488,7 @@ static void config_art_rwp_pio (ide_drive_t *drive, byte pio)
}
/* register layout changed with newer ATA100 chips */
if (dma_capability < ATA_100) {
if (chipset_family < ATA_100) {
pci_read_config_byte(dev, drive_pci, &test1);
pci_read_config_byte(dev, drive_pci+1, &test2);
......@@ -587,7 +568,7 @@ static int sis5513_tune_chipset (ide_drive_t *drive, byte speed)
pci_read_config_byte(dev, drive_pci+1, &reg);
/* Disable UDMA bit for non UDMA modes on UDMA chips */
if ((speed < XFER_UDMA_0) && (dma_capability > ATA_16)) {
if ((speed < XFER_UDMA_0) && (chipset_family > ATA_16)) {
reg &= 0x7F;
pci_write_config_byte(dev, drive_pci+1, reg);
}
......@@ -604,11 +585,11 @@ static int sis5513_tune_chipset (ide_drive_t *drive, byte speed)
/* Force the UDMA bit on if we want to use UDMA */
reg |= 0x80;
/* clean reg cycle time bits */
reg &= ~((0xFF >> (8 - cycle_time_range[dma_capability]))
<< cycle_time_offset[dma_capability]);
reg &= ~((0xFF >> (8 - cycle_time_range[chipset_family]))
<< cycle_time_offset[chipset_family]);
/* set reg cycle time bits */
reg |= cycle_time_value[dma_capability-ATA_00][speed-XFER_UDMA_0]
<< cycle_time_offset[dma_capability];
reg |= cycle_time_value[chipset_family-ATA_00][speed-XFER_UDMA_0]
<< cycle_time_offset[chipset_family];
pci_write_config_byte(dev, drive_pci+1, reg);
break;
case XFER_MW_DMA_2:
......@@ -657,17 +638,17 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
drive->dn, ultra);
#endif
if ((id->dma_ultra & 0x0020) && ultra && udma_66 && (dma_capability >= ATA_100a))
if ((id->dma_ultra & 0x0020) && ultra && udma_66 && (chipset_family >= ATA_100a))
speed = XFER_UDMA_5;
else if ((id->dma_ultra & 0x0010) && ultra && udma_66 && (dma_capability >= ATA_66))
else if ((id->dma_ultra & 0x0010) && ultra && udma_66 && (chipset_family >= ATA_66))
speed = XFER_UDMA_4;
else if ((id->dma_ultra & 0x0008) && ultra && udma_66 && (dma_capability >= ATA_66))
else if ((id->dma_ultra & 0x0008) && ultra && udma_66 && (chipset_family >= ATA_66))
speed = XFER_UDMA_3;
else if ((id->dma_ultra & 0x0004) && ultra && (dma_capability >= ATA_33))
else if ((id->dma_ultra & 0x0004) && ultra && (chipset_family >= ATA_33))
speed = XFER_UDMA_2;
else if ((id->dma_ultra & 0x0002) && ultra && (dma_capability >= ATA_33))
else if ((id->dma_ultra & 0x0002) && ultra && (chipset_family >= ATA_33))
speed = XFER_UDMA_1;
else if ((id->dma_ultra & 0x0001) && ultra && (dma_capability >= ATA_33))
else if ((id->dma_ultra & 0x0001) && ultra && (chipset_family >= ATA_33))
speed = XFER_UDMA_0;
else if (id->dma_mword & 0x0004)
speed = XFER_MW_DMA_2;
......@@ -700,6 +681,8 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
struct hd_driveid *id = drive->id;
ide_dma_action_t dma_func = ide_dma_off_quietly;
config_chipset_for_pio(drive, 5);
if (id && (id->capability & 1) && drive->channel->autodma) {
/* Consult the list of known "bad" drives */
if (ide_dmaproc(ide_dma_bad_drive, drive)) {
......@@ -764,10 +747,6 @@ unsigned int __init pci_init_sis5513(struct pci_dev *dev)
struct pci_dev *host;
int i = 0;
#ifdef DEBUG
sis5513_print_registers(dev, "pci_init_sis5513 start");
#endif
/* Find the chip */
for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !host_dev; i++) {
host = pci_find_device (PCI_VENDOR_ID_SI,
......@@ -777,12 +756,16 @@ unsigned int __init pci_init_sis5513(struct pci_dev *dev)
continue;
host_dev = host;
dma_capability = SiSHostChipInfo[i].dma_capability;
chipset_family = SiSHostChipInfo[i].chipset_family;
printk(SiSHostChipInfo[i].name);
printk("\n");
#ifdef DEBUG
sis5513_print_registers(dev, "pci_init_sis5513 start");
#endif
if (SiSHostChipInfo[i].flags & SIS5513_LATENCY) {
byte latency = (dma_capability == ATA_100)? 0x80 : 0x10; /* Lacking specs */
byte latency = (chipset_family == ATA_100)? 0x80 : 0x10; /* Lacking specs */
pci_write_config_byte(dev, PCI_LATENCY_TIMER, latency);
}
}
......@@ -792,7 +775,7 @@ unsigned int __init pci_init_sis5513(struct pci_dev *dev)
2/ tell old chips to allow per drive IDE timings */
if (host_dev) {
byte reg;
switch(dma_capability) {
switch(chipset_family) {
case ATA_133:
case ATA_100:
/* Set compatibility bit */
......@@ -847,7 +830,7 @@ unsigned int __init ata66_sis5513(struct ata_channel *hwif)
byte mask = hwif->unit ? 0x20 : 0x10;
pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h);
if (dma_capability >= ATA_66) {
if (chipset_family >= ATA_66) {
ata66 = (reg48h & mask) ? 0 : 1;
}
return ata66;
......@@ -866,7 +849,7 @@ void __init ide_init_sis5513(struct ata_channel *hwif)
if (host_dev) {
#ifdef CONFIG_BLK_DEV_IDEDMA
if (dma_capability > ATA_16) {
if (chipset_family > ATA_16) {
hwif->autodma = noautodma ? 0 : 1;
hwif->highmem = 1;
hwif->dmaproc = &sis5513_dmaproc;
......
......@@ -248,8 +248,19 @@ void __init ide_init_trm290(struct ata_channel *hwif)
if ((reg & 0x10))
hwif->irq = hwif->unit ? 15 : 14; /* legacy mode */
else if (!hwif->irq && hwif->mate && hwif->mate->irq)
hwif->irq = hwif->mate->irq; /* sharing IRQ with mate */
else {
static int primary_irq = 0;
/* Ugly way to let the primary and secondary channel on the
* chip use the same IRQ line.
*/
if (hwif->unit == ATA_PRIMARY)
primary_irq = hwif->irq;
else if (!hwif->irq)
hwif->irq = primary_irq;
}
ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->unit ? 0x0080 : 0x0000), 3);
#ifdef CONFIG_BLK_DEV_IDEDMA
......
......@@ -158,7 +158,6 @@ void __init init_umc8672 (void) /* called from ide.c */
ide_hwifs[1].chipset = ide_umc8672;
ide_hwifs[0].tuneproc = &tune_umc;
ide_hwifs[1].tuneproc = &tune_umc;
ide_hwifs[0].mate = &ide_hwifs[1];
ide_hwifs[1].mate = &ide_hwifs[0];
ide_hwifs[1].unit = 1;
ide_hwifs[0].unit = ATA_PRIMARY;
ide_hwifs[1].unit = ATA_SECONDARY;
}
......@@ -37,387 +37,6 @@ CONFIG_USB_LONG_TIMEOUT
If you have an MGE Ellipse UPS, or you see timeouts in HID
transactions, say Y; otherwise say N.
CONFIG_USB_HID
Say Y here if you want full HID support to connect keyboards,
mice, joysticks, graphic tablets, or any other HID based devices
to your computer via USB. You also need to select HID Input layer
support (below) if you want to use keyboards, mice, joysticks and
the like.
You can't use this driver and the HIDBP (Boot Protocol) keyboard
and mouse drivers at the same time. More information is available:
<file:Documentation/input/input.txt>.
If unsure, say Y.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called hid.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_HIDINPUT
Say Y here if you want to use a USB keyboard, mouse or joystick,
or any other HID input device. You also need Input layer support,
(CONFIG_INPUT) which you select under "Input core support".
If unsure, say Y.
CONFIG_USB_HIDDEV
Say Y here if you want to support HID devices (from the USB
specification standpoint) that aren't strictly user interface
devices, like monitor controls and Uninterruptable Power Supplies.
This module supports these devices separately using a separate
event interface on /dev/usb/hiddevX (char 180:96 to 180:111).
This driver requires CONFIG_USB_HID.
If unsure, say Y.
CONFIG_USB_KBD
Say Y here only if you are absolutely sure that you don't want
to use the generic HID driver for your USB keyboard and prefer
to use the keyboard in its limited Boot Protocol mode instead.
This is almost certainly not what you want.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called usbkbd.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
If even remotely unsure, say N.
CONFIG_USB_MOUSE
Say Y here only if you are absolutely sure that you don't want
to use the generic HID driver for your USB keyboard and prefer
to use the keyboard in its limited Boot Protocol mode instead.
This is almost certainly not what you want.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called usbmouse.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
If even remotely unsure, say N.
CONFIG_USB_WACOM
Say Y here if you want to use the USB version of the Wacom Intuos
or Graphire tablet. Make sure to say Y to "Mouse support"
(CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
(CONFIG_INPUT_EVDEV) as well.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called wacom.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_SCANNER
Say Y here if you want to connect a USB scanner to your computer's
USB port. Please read <file:Documentation/usb/scanner.txt> and
<file:Documentation/usb/scanner-hp-sane.txt> for more information.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called scanner.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_AUDIO
Say Y here if you want to connect USB audio equipment such as
speakers to your computer's USB port.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called audio.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_EMI26
This driver loads firmware to Emagic EMI 2|6 low latency USB
Audio interface.
After firmware load the device is handled with standard linux
USB Audio driver.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called audio.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_ACM
This driver supports USB modems and ISDN adapters which support the
Communication Device Class Abstract Control Model interface.
Please read <file:Documentation/usb/acm.txt> for details.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called acm.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_PRINTER
Say Y here if you want to connect a USB printer to your computer's
USB port.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called printer.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_IBMCAM
Say Y here if you want to connect a IBM "C-It" camera, also known as
"Xirlink PC Camera" to your computer's USB port. For more
information, read <file:Documentation/usb/ibmcam.txt>.
This driver uses the Video For Linux API. You must enable
(Y or M in config) Video For Linux (under Character Devices)
to use this driver. Information on this API and pointers to
"v4l" programs may be found on the WWW at
<http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called ibmcam.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>. This
camera has several configuration options which can be specified when
you load the module. Read <file:Documentation/usb/ibmcam.txt> to
learn more.
CONFIG_USB_OV511
Say Y here if you want to connect this type of camera to your
computer's USB port. See <file:Documentation/usb/ov511.txt> for more
information and for a list of supported cameras.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Character Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called ov511.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_CDCETHER
This driver supports devices conforming to the Communication Device
Class Ethernet Control Model. This is used in some cable modems.
For more details on the specification, get the Communication Device
Class specification from <http://www.usb.org/>.
This driver should work with the following devices:
* Ericsson PipeRider (all variants)
* Motorola (DM100 and SB4100)
* Broadcom Cable Modem (reference design)
* Toshiba PCX1100U and possibly other cable modems
The device creates a network device (ethX, where X depends on what
other networking devices you have in use), as for a normal PCI
or ISA based ethernet network card.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called CDCEther.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_PWC
Say Y or M here if you want to use one of these Philips USB webcams:
PCA645, PCA646, PCVC675, PCVC680, PCVC690, PCVC730, PCVC740, or
the Askey VC010. The PCA635, PCVC665 and PCVC720 are not supported
by this driver and never will be.
This driver has an optional plugin, which is distributed as a binary
module only. It contains code that allow you to use higher
resolutions and framerates but may not be distributed as source.
But even without this plugin you can these cams for most
applications.
See <file:Documentation/usb/philips.txt> for more information and
installation instructions.
The built-in microphone is enabled by selecting USB Audio support.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Character Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called pwc.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_SE401
Say Y here if you want to connect this type of camera to your
computer's USB port. See <file:Documentation/usb/se401.txt> for more
information and for a list of supported cameras.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Multimedia Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called se401.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_STV680
Say Y here if you want to connect this type of camera to your
computer's USB port. This includes the Pencam line of cameras.
See <file:Documentation/usb/stv680.txt> for more information and for
a list of supported cameras.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Multimedia Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called stv680.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_VICAM
Say Y here if you have 3com homeconnect camera (vicam).
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Multimedia Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called vicam.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_PEGASUS
Say Y here if you know you have Pegasus or Pegasus-II based adapter.
If in doubt then look at linux/drivers/usb/pegasus.h for the complete
list of supported devices.
If your particular adapter is not in the list and you are _sure_ it
is Pegasus or Pegasus II based then send me (petkan@users.sourceforge.net)
vendor and device IDs.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called pegasus.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_RTL8150
Say Y here if you have RTL8150 based usb-ethernet adapter.
Send me (petkan@users.sourceforge.net) any comments you may have.
You can also check for updates at http://pegasus2.sourceforge.net/
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called rtl8150.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_KAWETH
Say Y here if you want to use one of the following 10Mbps only
USB Ethernet adapters based on the KLSI KL5KUSB101B chipset:
3Com 3C19250
ADS USB-10BT
ATEN USB Ethernet
ASANTE USB To Ethernet Adapter
AOX Endpoints USB Ethernet
Correga K.K.
D-Link DSB-650C and DU-E10
Entrega / Portgear E45
I-O DATA USB-ET/T
Jaton USB Ethernet Device Adapter
Kingston Technology USB Ethernet Adapter
Linksys USB10T
Mobility USB-Ethernet Adapter
NetGear EA-101
Peracom Enet and Enet2
Portsmith Express Ethernet Adapter
Shark Pocket Adapter
SMC 2202USB
Sony Vaio port extender
This driver is likely to work with most 10Mbps only USB Ethernet
adapters, including some "no brand" devices. It does NOT work on
SmartBridges smartNIC or on Belkin F5U111 devices - you should use
the CATC NetMate driver for those. If you are not sure which one
you need, select both, and the correct one should be selected for
you.
This driver makes the adapter appear as a normal Ethernet interface,
typically on eth0, if it is the only ethernet device, or perhaps on
eth1, if you have a PCI or ISA ethernet card installed.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called kaweth.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_CATC
Say Y if you want to use one of the following 10Mbps USB Ethernet
device based on the EL1210A chip. Supported devices are:
Belkin F5U011
Belkin F5U111
CATC NetMate
CATC NetMate II
smartBridges smartNIC
This driver makes the adapter appear as a normal Ethernet interface,
typically on eth0, if it is the only ethernet device, or perhaps on
eth1, if you have a PCI or ISA ethernet card installed.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called catc.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_DC2XX
Say Y here if you want to connect this type of still camera to your
computer's USB port. See <file:Documentation/usb/dc2xx.txt> for
more information; some non-Kodak cameras may also work with this
driver, given application support (such as <http://www.gphoto.org/>).
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called dc2xx.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_MDC800
Say Y here if you want to connect this type of still camera to
your computer's USB port. This driver can be used with gphoto 0.4.3
and higher (look at <http://www.gphoto.org/>).
To use it create a device node with "mknod /dev/mustek c 180 32" and
configure it in your software.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called mdc800.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_USS720
This driver is for USB parallel port adapters that use the Lucent
Technologies USS-720 chip. These cables are plugged into your USB
port and provide USB compatibility to peripherals designed with
parallel port interfaces.
The chip has two modes: automatic mode and manual mode. In automatic
mode, it looks to the computer like a standard USB printer. Only
printers may be connected to the USS-720 in this mode. The generic
USB printer driver ("USB Printer support", above) may be used in
that mode, and you can say N here if you want to use the chip only
in this mode.
Manual mode is not limited to printers, any parallel port
device should work. This driver utilizes manual mode.
Note however that some operations are three orders of magnitude
slower than on a PCI/ISA Parallel Port, so timing critical
applications might not work.
Say Y here if you own an USS-720 USB->Parport cable and intend to
connect anything other than a printer to it.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called uss720.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_DEVICEFS
If you say Y here (and to "/proc file system support" in the "File
systems section, above), you will get a file /proc/bus/usb/devices
......@@ -430,8 +49,8 @@ CONFIG_USB_DEVICEFS
meaning they are generated on the fly and not stored on the hard
drive.
You may need to mount the usbdevfs file system to see the files, use
mount -t usbdevfs none /proc/bus/usb
You may need to mount the usbfs file system to see the files, use
mount -t usbfs none /proc/bus/usb
For the format of the various /proc/bus/usb/ files, please read
<file:Documentation/usb/proc_usb_info.txt>.
......@@ -450,129 +69,3 @@ CONFIG_USB_BANDWIDTH
If you say N here, these conditions will cause warning messages
about USB bandwidth usage to be logged and some devices or
drivers may not work correctly.
CONFIG_USB_DABUSB
A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
brought to you by the DAB-Team (<http://dab.in.tum.de/>). This
driver can be taken as an example for URB-based bulk, control, and
isochronous transactions. URB's are explained in
<file:Documentation/usb/URB.txt>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called dabusb.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_KONICAWC
Say Y here if you want support for webcams based on a Konica
chipset. This is known to work with the Intel YC76 webcam.
This driver uses the Video For Linux API. You must enable
(Y or M in config) Video For Linux (under Character Devices)
to use this driver. Information on this API and pointers to
"v4l" programs may be found on the WWW at
<http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called konicawc.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_USBNET
This driver supports network links over USB with USB "Network"
or "data transfer" cables, often used to network laptops to PCs.
Such cables have chips from suppliers such as Belkin/eTEK, GeneSys
(GeneLink), NetChip and Prolific. Intelligent USB devices could also
use this approach to provide Internet access, using standard USB
cabling. You can find these chips also on some motherboards with
USB PC2PC support.
These links will have names like "usb0", "usb1", etc. They act
like two-node Ethernets, so you can use 802.1d Ethernet Bridging
(CONFIG_BRIDGE) to simplify your network routing.
This code is also available as a kernel module (code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called usbnet.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_RIO500
Say Y here if you want to connect a USB Rio500 mp3 player to your
computer's USB port. Please read <file:Documentation/usb/rio.txt>
for more information.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called rio500.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_AUERSWALD
Say Y here if you want to connect an Auerswald USB ISDN Device
to your computer's USB port.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called auerswald.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_DSBR
Say Y here if you want to connect this type of radio to your
computer's USB port. Note that the audio is not digital, and
you must connect the line out connector to a sound card or a
set of speakers.
This driver uses the Video For Linux API. You must enable
(Y or M in config) Video For Linux (under Character Devices)
to use this driver. Information on this API and pointers to
"v4l" programs may be found on the WWW at
<http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called dsbr100.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_MICROTEK
Say Y here if you want support for the Microtek X6USB and
possibly the Phantom 336CX, Phantom C6 and ScanMaker V6U(S)L.
Support for anything but the X6 is experimental.
Please report failures and successes.
The scanner will appear as a scsi generic device to the rest
of the system. Scsi support is required.
This driver can be compiled as a module, called microtek.o.
CONFIG_USB_HPUSBSCSI
Say Y here if you want support for the HP 53xx series of scanners
and the Minolta Scan Dual. This driver is experimental.
The scanner will be accessible as a SCSI device.
This can be compiled as a module, called hpusbscsi.o.
CONFIG_USB_BLUETOOTH
Say Y here if you want to connect a USB Bluetooth device to your
computer's USB port. You will need the Bluetooth stack (available
at <http://developer.axis.com/software/index.shtml>) to fully use
the device.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called bluetooth.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_TIGL
If you own a Texas Instruments graphing calculator and use a
TI-GRAPH LINK USB cable (aka SilverLink), then you might be
interested in this driver.
If you enable this driver, you will be able to communicate with
your calculator through a set of device nodes under /dev.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called tiglusb.o. If you want to compile it as a
module, say M here and read Documentation/modules.txt.
If you don't know what the SilverLink cable is or what a Texas
Instruments graphing calculator is, then you probably don't need this
driver.
If unsure, say N.
CONFIG_USB_ACM
This driver supports USB modems and ISDN adapters which support the
Communication Device Class Abstract Control Model interface.
Please read <file:Documentation/usb/acm.txt> for details.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called acm.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_AUDIO
Say Y here if you want to connect USB audio equipment such as
speakers to your computer's USB port.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called audio.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_BLUETOOTH_TTY
Say Y here if you want to connect a USB Bluetooth device to your
computer's USB port. You will need the Bluetooth stack (available
at <http://developer.axis.com/software/index.shtml>) to fully use
the device.
This driver implements a tty inteface to a Bluetooth device. If
you want to use a socket based Bluetooth stack (like the BlueZ
stack), do not use this driver.
If in doubt, say N here.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called bluetty.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_PRINTER
Say Y here if you want to connect a USB printer to your computer's
USB port.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called printer.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
......@@ -3,14 +3,14 @@
#
comment 'USB Device Class drivers'
dep_tristate ' USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB $CONFIG_SOUND
dep_tristate ' USB Bluetooth support (EXPERIMENTAL)' CONFIG_USB_BLUETOOTH $CONFIG_USB $CONFIG_EXPERIMENTAL
dep_tristate ' USB Bluetooth TTY support' CONFIG_USB_BLUETOOTH_TTY $CONFIG_USB
dep_tristate ' USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB
dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
# Turn on CONFIG_USB_CLASS if any of the drivers are compiled into the kernel
# to make our Makefile logic a bit simpler.
if [ "$CONFIG_USB_AUDIO" = "y" -o "$CONFIG_USB_BLUETOOTH" = "y" ]; then
if [ "$CONFIG_USB_AUDIO" = "y" -o "$CONFIG_USB_BLUETOOTH_TTY" = "y" ]; then
define_bool CONFIG_USB_CLASS y
fi
if [ "$CONFIG_USB_ACM" = "y" -o "$CONFIG_USB_PRINTER" = "y" ]; then
......
......@@ -7,7 +7,7 @@ O_TARGET := usb-class.o
obj-$(CONFIG_USB_ACM) += cdc-acm.o
obj-$(CONFIG_USB_AUDIO) += audio.o
obj-$(CONFIG_USB_BLUETOOTH) += bluetooth.o
obj-$(CONFIG_USB_BLUETOOTH_TTY) += bluetty.o
obj-$(CONFIG_USB_PRINTER) += printer.o
......
/*
* bluetooth.c Version 0.13
* bluetty.c Version 0.13
*
* Copyright (c) 2000, 2001 Greg Kroah-Hartman <greg@kroah.com>
* Copyright (c) 2000 Mark Douglas Corner <mcorner@umich.edu>
*
* USB Bluetooth driver, based on the Bluetooth Spec version 1.0B
* USB Bluetooth TTY driver, based on the Bluetooth Spec version 1.0B
*
* (2001/11/30) Version 0.13 gkh
* - added locking patch from Masoodur Rahman <rmasoodu@in.ibm.com>
......@@ -237,7 +237,7 @@ static struct usb_device_id usb_bluetooth_ids [] = {
MODULE_DEVICE_TABLE (usb, usb_bluetooth_ids);
static struct usb_driver usb_bluetooth_driver = {
name: "bluetooth",
name: "bluetty",
probe: usb_bluetooth_probe,
disconnect: usb_bluetooth_disconnect,
id_table: usb_bluetooth_ids,
......
......@@ -597,33 +597,31 @@ static int proc_bulk(struct dev_state *ps, void *arg)
if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))
return -EINVAL;
len1 = bulk.len;
if (len1 > PAGE_SIZE)
return -EINVAL;
if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
if (!(tbuf = kmalloc(len1, GFP_KERNEL)))
return -ENOMEM;
tmo = (bulk.timeout * HZ + 999) / 1000;
if (bulk.ep & 0x80) {
if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
free_page((unsigned long)tbuf);
kfree(tbuf);
return -EINVAL;
}
i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
if (!i && len2) {
if (copy_to_user(bulk.data, tbuf, len2)) {
free_page((unsigned long)tbuf);
kfree(tbuf);
return -EFAULT;
}
}
} else {
if (len1) {
if (copy_from_user(tbuf, bulk.data, len1)) {
free_page((unsigned long)tbuf);
kfree(tbuf);
return -EFAULT;
}
}
i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
}
free_page((unsigned long)tbuf);
kfree(tbuf);
if (i < 0) {
printk(KERN_WARNING "usbfs: USBDEVFS_BULK failed dev %d ep 0x%x len %u ret %d\n",
dev->devnum, bulk.ep, bulk.len, i);
......@@ -1059,6 +1057,8 @@ static int proc_ioctl (struct dev_state *ps, void *arg)
int size;
void *buf = 0;
int retval = 0;
struct usb_interface *ifp = 0;
struct usb_driver *driver = 0;
/* get input parameters and alloc buffer */
if (copy_from_user(&ctrl, (void *) arg, sizeof (ctrl)))
......@@ -1076,33 +1076,41 @@ static int proc_ioctl (struct dev_state *ps, void *arg)
}
}
/* ioctl to device */
if (ctrl.ifno < 0) {
switch (ctrl.ioctl_code) {
/* access/release token for issuing control messages
* ask a particular driver to bind/unbind, ... etc
*/
}
retval = -ENOSYS;
/* ioctl to the driver which has claimed a given interface */
} else {
struct usb_interface *ifp = 0;
if (!ps->dev)
retval = -ENODEV;
else if (ctrl.ifno >= ps->dev->actconfig->bNumInterfaces)
else if (!(ifp = usb_ifnum_to_if (ps->dev, ctrl.ifno)))
retval = -EINVAL;
else {
if (!(ifp = usb_ifnum_to_if (ps->dev, ctrl.ifno)))
else switch (ctrl.ioctl_code) {
/* disconnect kernel driver from interface, leaving it unbound. */
case USBDEVFS_DISCONNECT:
driver = ifp->driver;
if (driver) {
down (&driver->serialize);
dbg ("disconnect '%s' from dev %d interface %d",
driver->name, ps->dev->devnum, ctrl.ifno);
driver->disconnect (ps->dev, ifp->private_data);
usb_driver_release_interface (driver, ifp);
up (&driver->serialize);
} else
retval = -EINVAL;
else if (ifp->driver == 0 || ifp->driver->ioctl == 0)
break;
/* let kernel drivers try to (re)bind to the interface */
case USBDEVFS_CONNECT:
usb_find_interface_driver_for_ifnum (ps->dev, ctrl.ifno);
break;
/* talk directly to the interface's driver */
default:
driver = ifp->driver;
if (driver == 0 || driver->ioctl == 0)
retval = -ENOSYS;
}
if (retval == 0) {
else {
if (ifp->driver->owner)
__MOD_INC_USE_COUNT(ifp->driver->owner);
/* ifno might usefully be passed ... */
retval = ifp->driver->ioctl (ps->dev, ctrl.ioctl_code, buf);
retval = driver->ioctl (ps->dev, ctrl.ioctl_code, buf);
/* size = min_t(int, size, retval)? */
if (ifp->driver->owner)
__MOD_DEC_USE_COUNT(ifp->driver->owner);
......
......@@ -181,6 +181,24 @@ extern int usb_hcd_pci_resume (struct pci_dev *dev);
#endif /* CONFIG_PCI */
/* -------------------------------------------------------------------------- */
/* Enumeration is only for the hub driver, or HCD virtual root hubs */
extern struct usb_device *usb_alloc_dev(struct usb_device *parent,
struct usb_bus *);
extern void usb_free_dev(struct usb_device *);
extern int usb_new_device(struct usb_device *dev);
extern void usb_connect(struct usb_device *dev);
extern void usb_disconnect(struct usb_device **);
#ifndef _LINUX_HUB_H
/* exported to hub driver ONLY to support usb_reset_device () */
extern int usb_get_configuration(struct usb_device *dev);
extern void usb_set_maxpacket(struct usb_device *dev);
extern void usb_destroy_configuration(struct usb_device *dev);
extern int usb_set_address(struct usb_device *dev);
#endif /* _LINUX_HUB_H */
/*-------------------------------------------------------------------------*/
/*
......
......@@ -29,6 +29,7 @@
#include <asm/uaccess.h>
#include <asm/byteorder.h>
#include "hcd.h"
#include "hub.h"
/* Wakes up khubd */
......
......@@ -196,6 +196,28 @@ void usb_deregister(struct usb_driver *driver)
usbfs_update_special();
}
/**
* usb_ifnum_to_ifpos - convert the interface number to the interface position
* @dev: the device to use
* @ifnum: the interface number (bInterfaceNumber); not interface position
*
* This is used to convert the interface _number_ (as in
* interface.bInterfaceNumber) to the interface _position_ (as in
* dev->actconfig->interface + position). Note that the number is the same as
* the position for all interfaces _except_ devices with interfaces not
* sequentially numbered (e.g., 0, 2, 3, etc).
*/
int usb_ifnum_to_ifpos(struct usb_device *dev, unsigned ifnum)
{
int i;
for (i = 0; i < dev->actconfig->bNumInterfaces; i++)
if (dev->actconfig->interface[i].altsetting[0].bInterfaceNumber == ifnum)
return i;
return -EINVAL;
}
/**
* usb_ifnum_to_if - get the interface object with a given interface number
* @dev: the device whose current configuration is considered
......@@ -570,6 +592,24 @@ static int usb_find_interface_driver(struct usb_device *dev, unsigned ifnum)
return -1;
}
/**
* usb_find_interface_driver_for_ifnum - finds a usb interface driver for the specified ifnum
* @dev: the device to use
* @ifnum: the interface number (bInterfaceNumber); not interface position!
*
* This converts a ifnum to ifpos via a call to usb_ifnum_to_ifpos and then
* calls usb_find_interface_driver() with the found ifpos. Note
* usb_find_interface_driver's ifnum parameter is actually interface position.
*/
int usb_find_interface_driver_for_ifnum(struct usb_device *dev, unsigned ifnum)
{
int ifpos = usb_ifnum_to_ifpos(dev, ifnum);
if (0 > ifpos)
return -EINVAL;
return usb_find_interface_driver(dev, ifpos);
}
#ifdef CONFIG_HOTPLUG
......@@ -789,50 +829,32 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus)
return dev;
}
// usbcore-internal ...
// but usb_dec_dev_use() is #defined to this, and that's public!!
// FIXME the public call should BUG() whenever count goes to zero,
// the usbcore-internal one should do so _unless_ it does so...
/**
* usb_free_dev - free a usb device structure (usbcore-internal)
* @dev: device that's been disconnected
* Context: !in_interrupt ()
*
* Used by hub and virtual root hub drivers. The device is completely
* gone, everything is cleaned up, so it's time to get rid of these last
* records of this device.
*/
void usb_free_dev(struct usb_device *dev)
{
if (atomic_dec_and_test(&dev->refcnt)) {
/* Normally only goes to zero in usb_disconnect(), from
* khubd or from roothub shutdown (rmmod/apmd/... thread).
* Abnormally, roothub init errors can happen, so HCDs
* call this directly.
*
* Otherwise this is a nasty device driver bug, often in
* disconnect processing.
*/
if (in_interrupt ())
BUG ();
dev->bus->op->deallocate(dev);
usb_destroy_configuration(dev);
usb_bus_put(dev->bus);
kfree(dev);
if (!atomic_dec_and_test (&dev->refcnt)) {
/* MUST go to zero here, else someone's hanging on to
* a device that's supposed to have been cleaned up!!
*/
BUG ();
}
}
/**
* usb_inc_dev_use - record another reference to a device
* @dev: the device being referenced
*
* Each live reference to a device should be refcounted.
*
* Device drivers should normally record such references in their
* open() methods.
* Drivers should then release them, using usb_dec_dev_use(), in their
* close() methods.
*/
void usb_inc_dev_use(struct usb_device *dev)
{
atomic_inc(&dev->refcnt);
dev->bus->op->deallocate (dev);
usb_destroy_configuration (dev);
usb_bus_put (dev->bus);
kfree (dev);
}
/**
* usb_alloc_urb - creates a new urb for a USB driver to use
* @iso_packets: number of iso packets for this urb
......@@ -2636,6 +2658,7 @@ module_exit(usb_exit);
* into the kernel, and other device drivers are built as modules,
* then these symbols need to be exported for the modules to use.
*/
EXPORT_SYMBOL(usb_ifnum_to_ifpos);
EXPORT_SYMBOL(usb_ifnum_to_if);
EXPORT_SYMBOL(usb_epnum_to_ep_desc);
......@@ -2647,6 +2670,7 @@ EXPORT_SYMBOL(usb_alloc_dev);
EXPORT_SYMBOL(usb_free_dev);
EXPORT_SYMBOL(usb_inc_dev_use);
EXPORT_SYMBOL(usb_find_interface_driver_for_ifnum);
EXPORT_SYMBOL(usb_driver_claim_interface);
EXPORT_SYMBOL(usb_interface_claimed);
EXPORT_SYMBOL(usb_driver_release_interface);
......
......@@ -749,7 +749,7 @@ static void uhci_inc_fsbr(struct uhci *uhci, struct urb *urb)
if ((!(urb->transfer_flags & USB_NO_FSBR)) && !urbp->fsbr) {
urbp->fsbr = 1;
if (!uhci->fsbr++)
if (!uhci->fsbr++ && !uhci->fsbrtimeout)
uhci->skel_term_qh->link = uhci->skel_hs_control_qh->dma_handle | UHCI_PTR_QH;
}
......@@ -1631,8 +1631,7 @@ static void uhci_transfer_result(struct uhci *uhci, struct urb *urb)
if (urb->status != -EINPROGRESS) {
info("uhci_transfer_result: called for URB %p not in flight?", urb);
spin_unlock_irqrestore(&urb->lock, flags);
return;
goto out;
}
switch (usb_pipetype(urb->pipe)) {
......@@ -1652,10 +1651,8 @@ static void uhci_transfer_result(struct uhci *uhci, struct urb *urb)
urbp->status = ret;
if (ret == -EINPROGRESS) {
spin_unlock_irqrestore(&urb->lock, flags);
return;
}
if (ret == -EINPROGRESS)
goto out;
switch (usb_pipetype(urb->pipe)) {
case PIPE_CONTROL:
......@@ -1669,11 +1666,8 @@ static void uhci_transfer_result(struct uhci *uhci, struct urb *urb)
break;
case PIPE_INTERRUPT:
/* Interrupts are an exception */
if (urb->interval) {
uhci_add_complete(urb);
spin_unlock_irqrestore(&urb->lock, flags);
return; /* <-- note return */
}
if (urb->interval)
goto out_complete;
/* Release bandwidth for Interrupt or Isoc. transfers */
/* Spinlock needed ? */
......@@ -1689,8 +1683,10 @@ static void uhci_transfer_result(struct uhci *uhci, struct urb *urb)
/* Remove it from uhci->urb_list */
list_del_init(&urb->urb_list);
out_complete:
uhci_add_complete(urb);
out:
spin_unlock_irqrestore(&urb->lock, flags);
}
......@@ -1820,6 +1816,9 @@ static int uhci_unlink_urb(struct urb *urb)
} else {
urb->status = -ENOENT;
spin_unlock(&urb->lock);
spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
if (in_interrupt()) { /* wait at least 1 frame */
static int errorcount = 10;
......@@ -1829,9 +1828,6 @@ static int uhci_unlink_urb(struct urb *urb)
} else
schedule_timeout(1+1*HZ/1000);
spin_unlock(&urb->lock);
spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
uhci_call_completion(urb);
}
}
......@@ -1846,10 +1842,6 @@ static int uhci_fsbr_timeout(struct uhci *uhci, struct urb *urb)
uhci_dec_fsbr(uhci, urb);
/* There is a race with updating IOC in here, but it's not worth */
/* trying to fix since this is merely an optimization. The only */
/* time we'd lose is if the status of the packet got updated */
/* and we'd be turning on FSBR next frame anyway, so it's a wash */
urbp->fsbr_timeout = 1;
head = &urbp->td_list;
......@@ -2013,23 +2005,23 @@ static void rh_int_timer_do(unsigned long ptr)
tmp = head->next;
while (tmp != head) {
struct urb *u = list_entry(tmp, struct urb, urb_list);
struct urb_priv *urbp = (struct urb_priv *)u->hcpriv;
struct urb_priv *up = (struct urb_priv *)u->hcpriv;
tmp = tmp->next;
spin_lock(&urb->lock);
spin_lock(&u->lock);
/* Check if the FSBR timed out */
if (urbp->fsbr && !urbp->fsbr_timeout && time_after_eq(jiffies, urbp->fsbrtime + IDLE_TIMEOUT))
if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT))
uhci_fsbr_timeout(uhci, u);
/* Check if the URB timed out */
if (u->timeout && time_after_eq(jiffies, urbp->inserttime + u->timeout)) {
if (u->timeout && time_after_eq(jiffies, up->inserttime + u->timeout)) {
list_del(&u->urb_list);
list_add_tail(&u->urb_list, &list);
}
spin_unlock(&urb->lock);
spin_unlock(&u->lock);
}
spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
......@@ -2202,12 +2194,12 @@ static int rh_submit_urb(struct urb *urb)
OK(0);
case RH_PORT_RESET:
SET_RH_PORTSTAT(USBPORTSC_PR);
wait_ms(50); /* USB v1.1 7.1.7.3 */
mdelay(50); /* USB v1.1 7.1.7.3 */
uhci->rh.c_p_r[wIndex - 1] = 1;
CLR_RH_PORTSTAT(USBPORTSC_PR);
udelay(10);
SET_RH_PORTSTAT(USBPORTSC_PE);
wait_ms(10);
mdelay(10);
SET_RH_PORTSTAT(0xa);
OK(0);
case RH_PORT_POWER:
......@@ -2724,6 +2716,7 @@ static int alloc_uhci(struct pci_dev *dev, unsigned int io_addr, unsigned int io
}
uhci->dev = dev;
uhci->irq = dev->irq;
uhci->io_addr = io_addr;
uhci->io_size = io_size;
pci_set_drvdata(dev, uhci);
......@@ -2750,6 +2743,11 @@ static int alloc_uhci(struct pci_dev *dev, unsigned int io_addr, unsigned int io
/* or broken setup */
reset_hc(uhci);
uhci->fsbr = 0;
uhci->fsbrtimeout = 0;
uhci->is_suspended = 0;
spin_lock_init(&uhci->qh_remove_list_lock);
INIT_LIST_HEAD(&uhci->qh_remove_list);
......@@ -2932,8 +2930,6 @@ static int alloc_uhci(struct pci_dev *dev, unsigned int io_addr, unsigned int io
if (request_irq(dev->irq, uhci_interrupt, SA_SHIRQ, "usb-uhci", uhci))
goto err_request_irq;
uhci->irq = dev->irq;
/* disable legacy emulation */
pci_write_config_word(uhci->dev, USBLEGSUP, USBLEGSUP_DEFAULT);
......
......@@ -287,17 +287,17 @@ struct virt_root_hub {
struct uhci {
struct pci_dev *dev;
#ifdef CONFIG_PROC_FS
/* procfs */
int num;
struct proc_dir_entry *proc_entry;
#endif
/* Grabbed from PCI */
int irq;
unsigned int io_addr;
unsigned int io_size;
struct list_head uhci_list;
struct pci_pool *qh_pool;
struct pci_pool *td_pool;
......
......@@ -11,7 +11,7 @@ static __inline__ void uhci_wait_ms(unsigned int ms)
{
if(!in_interrupt())
{
current->state = TASK_UNINTERRUPTIBLE;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1 + ms * HZ / 1000);
}
else
......
CONFIG_USB_DC2XX
Say Y here if you want to connect this type of still camera to your
computer's USB port. See <file:Documentation/usb/dc2xx.txt> for
more information; some non-Kodak cameras may also work with this
driver, given application support (such as <http://www.gphoto.org/>).
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called dc2xx.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_MDC800
Say Y here if you want to connect this type of still camera to
your computer's USB port. This driver can be used with gphoto 0.4.3
and higher (look at <http://www.gphoto.org/>).
To use it create a device node with "mknod /dev/mustek c 180 32" and
configure it in your software.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called mdc800.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_HPUSBSCSI
Say Y here if you want support for the HP 53xx series of scanners
and the Minolta Scan Dual. This driver is experimental.
The scanner will be accessible as a SCSI device.
This can be compiled as a module, called hpusbscsi.o.
CONFIG_USB_MICROTEK
Say Y here if you want support for the Microtek X6USB and
possibly the Phantom 336CX, Phantom C6 and ScanMaker V6U(S)L.
Support for anything but the X6 is experimental.
Please report failures and successes.
The scanner will appear as a scsi generic device to the rest
of the system. Scsi support is required.
This driver can be compiled as a module, called microtek.o.
CONFIG_USB_SCANNER
Say Y here if you want to connect a USB scanner to your computer's
USB port. Please read <file:Documentation/usb/scanner.txt> and
<file:Documentation/usb/scanner-hp-sane.txt> for more information.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called scanner.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_HID
Say Y here if you want full HID support to connect keyboards,
mice, joysticks, graphic tablets, or any other HID based devices
to your computer via USB. You also need to select HID Input layer
support (below) if you want to use keyboards, mice, joysticks and
the like.
You can't use this driver and the HIDBP (Boot Protocol) keyboard
and mouse drivers at the same time. More information is available:
<file:Documentation/input/input.txt>.
If unsure, say Y.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called hid.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_HIDINPUT
Say Y here if you want to use a USB keyboard, mouse or joystick,
or any other HID input device. You also need Input layer support,
(CONFIG_INPUT) which you select under "Input core support".
If unsure, say Y.
CONFIG_USB_HIDDEV
Say Y here if you want to support HID devices (from the USB
specification standpoint) that aren't strictly user interface
devices, like monitor controls and Uninterruptable Power Supplies.
This module supports these devices separately using a separate
event interface on /dev/usb/hiddevX (char 180:96 to 180:111).
This driver requires CONFIG_USB_HID.
If unsure, say Y.
CONFIG_USB_KBD
Say Y here only if you are absolutely sure that you don't want
to use the generic HID driver for your USB keyboard and prefer
to use the keyboard in its limited Boot Protocol mode instead.
This is almost certainly not what you want.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called usbkbd.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
If even remotely unsure, say N.
CONFIG_USB_MOUSE
Say Y here only if you are absolutely sure that you don't want
to use the generic HID driver for your USB keyboard and prefer
to use the keyboard in its limited Boot Protocol mode instead.
This is almost certainly not what you want.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called usbmouse.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
If even remotely unsure, say N.
CONFIG_USB_WACOM
Say Y here if you want to use the USB version of the Wacom Intuos
or Graphire tablet. Make sure to say Y to "Mouse support"
(CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
(CONFIG_INPUT_EVDEV) as well.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called wacom.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_DABUSB
A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
brought to you by the DAB-Team (<http://dab.in.tum.de/>). This
driver can be taken as an example for URB-based bulk, control, and
isochronous transactions. URB's are explained in
<file:Documentation/usb/URB.txt>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called dabusb.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_DSBR
Say Y here if you want to connect this type of radio to your
computer's USB port. Note that the audio is not digital, and
you must connect the line out connector to a sound card or a
set of speakers.
This driver uses the Video For Linux API. You must enable
(Y or M in config) Video For Linux (under Character Devices)
to use this driver. Information on this API and pointers to
"v4l" programs may be found on the WWW at
<http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called dsbr100.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_IBMCAM
Say Y here if you want to connect a IBM "C-It" camera, also known as
"Xirlink PC Camera" to your computer's USB port. For more
information, read <file:Documentation/usb/ibmcam.txt>.
This driver uses the Video For Linux API. You must enable
(Y or M in config) Video For Linux (under Character Devices)
to use this driver. Information on this API and pointers to
"v4l" programs may be found on the WWW at
<http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called ibmcam.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>. This
camera has several configuration options which can be specified when
you load the module. Read <file:Documentation/usb/ibmcam.txt> to
learn more.
CONFIG_USB_KONICAWC
Say Y here if you want support for webcams based on a Konica
chipset. This is known to work with the Intel YC76 webcam.
This driver uses the Video For Linux API. You must enable
(Y or M in config) Video For Linux (under Character Devices)
to use this driver. Information on this API and pointers to
"v4l" programs may be found on the WWW at
<http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called konicawc.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_OV511
Say Y here if you want to connect this type of camera to your
computer's USB port. See <file:Documentation/usb/ov511.txt> for more
information and for a list of supported cameras.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Character Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called ov511.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_PWC
Say Y or M here if you want to use one of these Philips USB webcams:
PCA645, PCA646, PCVC675, PCVC680, PCVC690, PCVC730, PCVC740, or
the Askey VC010. The PCA635, PCVC665 and PCVC720 are not supported
by this driver and never will be.
This driver has an optional plugin, which is distributed as a binary
module only. It contains code that allow you to use higher
resolutions and framerates but may not be distributed as source.
But even without this plugin you can these cams for most
applications.
See <file:Documentation/usb/philips.txt> for more information and
installation instructions.
The built-in microphone is enabled by selecting USB Audio support.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Character Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called pwc.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_SE401
Say Y here if you want to connect this type of camera to your
computer's USB port. See <file:Documentation/usb/se401.txt> for more
information and for a list of supported cameras.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Multimedia Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called se401.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_STV680
Say Y here if you want to connect this type of camera to your
computer's USB port. This includes the Pencam line of cameras.
See <file:Documentation/usb/stv680.txt> for more information and for
a list of supported cameras.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Multimedia Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called stv680.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_VICAM
Say Y here if you have 3com homeconnect camera (vicam).
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Multimedia Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called vicam.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_AUERSWALD
Say Y here if you want to connect an Auerswald USB ISDN Device
to your computer's USB port.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called auerswald.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_EMI26
This driver loads firmware to Emagic EMI 2|6 low latency USB
Audio interface.
After firmware load the device is handled with standard linux
USB Audio driver.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called audio.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_RIO500
Say Y here if you want to connect a USB Rio500 mp3 player to your
computer's USB port. Please read <file:Documentation/usb/rio.txt>
for more information.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called rio500.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_TIGL
If you own a Texas Instruments graphing calculator and use a
TI-GRAPH LINK USB cable (aka SilverLink), then you might be
interested in this driver.
If you enable this driver, you will be able to communicate with
your calculator through a set of device nodes under /dev.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called tiglusb.o. If you want to compile it as a
module, say M here and read Documentation/modules.txt.
If you don't know what the SilverLink cable is or what a Texas
Instruments graphing calculator is, then you probably don't need this
driver.
If unsure, say N.
CONFIG_USB_USS720
This driver is for USB parallel port adapters that use the Lucent
Technologies USS-720 chip. These cables are plugged into your USB
port and provide USB compatibility to peripherals designed with
parallel port interfaces.
The chip has two modes: automatic mode and manual mode. In automatic
mode, it looks to the computer like a standard USB printer. Only
printers may be connected to the USS-720 in this mode. The generic
USB printer driver ("USB Printer support", above) may be used in
that mode, and you can say N here if you want to use the chip only
in this mode.
Manual mode is not limited to printers, any parallel port
device should work. This driver utilizes manual mode.
Note however that some operations are three orders of magnitude
slower than on a PCI/ISA Parallel Port, so timing critical
applications might not work.
Say Y here if you own an USS-720 USB->Parport cable and intend to
connect anything other than a printer to it.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called uss720.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_CATC
Say Y if you want to use one of the following 10Mbps USB Ethernet
device based on the EL1210A chip. Supported devices are:
Belkin F5U011
Belkin F5U111
CATC NetMate
CATC NetMate II
smartBridges smartNIC
This driver makes the adapter appear as a normal Ethernet interface,
typically on eth0, if it is the only ethernet device, or perhaps on
eth1, if you have a PCI or ISA ethernet card installed.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called catc.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_CDCETHER
This driver supports devices conforming to the Communication Device
Class Ethernet Control Model. This is used in some cable modems.
For more details on the specification, get the Communication Device
Class specification from <http://www.usb.org/>.
This driver should work with the following devices:
* Ericsson PipeRider (all variants)
* Motorola (DM100 and SB4100)
* Broadcom Cable Modem (reference design)
* Toshiba PCX1100U and possibly other cable modems
The device creates a network device (ethX, where X depends on what
other networking devices you have in use), as for a normal PCI
or ISA based ethernet network card.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called cdc-ether.o. If you want to compile it
as a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_KAWETH
Say Y here if you want to use one of the following 10Mbps only
USB Ethernet adapters based on the KLSI KL5KUSB101B chipset:
3Com 3C19250
ADS USB-10BT
ATEN USB Ethernet
ASANTE USB To Ethernet Adapter
AOX Endpoints USB Ethernet
Correga K.K.
D-Link DSB-650C and DU-E10
Entrega / Portgear E45
I-O DATA USB-ET/T
Jaton USB Ethernet Device Adapter
Kingston Technology USB Ethernet Adapter
Linksys USB10T
Mobility USB-Ethernet Adapter
NetGear EA-101
Peracom Enet and Enet2
Portsmith Express Ethernet Adapter
Shark Pocket Adapter
SMC 2202USB
Sony Vaio port extender
This driver is likely to work with most 10Mbps only USB Ethernet
adapters, including some "no brand" devices. It does NOT work on
SmartBridges smartNIC or on Belkin F5U111 devices - you should use
the CATC NetMate driver for those. If you are not sure which one
you need, select both, and the correct one should be selected for
you.
This driver makes the adapter appear as a normal Ethernet interface,
typically on eth0, if it is the only ethernet device, or perhaps on
eth1, if you have a PCI or ISA ethernet card installed.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called kaweth.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_PEGASUS
Say Y here if you know you have Pegasus or Pegasus-II based adapter.
If in doubt then look at linux/drivers/usb/pegasus.h for the complete
list of supported devices.
If your particular adapter is not in the list and you are _sure_ it
is Pegasus or Pegasus II based then send me (petkan@users.sourceforge.net)
vendor and device IDs.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called pegasus.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_RTL8150
Say Y here if you have RTL8150 based usb-ethernet adapter.
Send me (petkan@users.sourceforge.net) any comments you may have.
You can also check for updates at http://pegasus2.sourceforge.net/
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called rtl8150.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_USBNET
This driver supports network links over USB with USB "Network"
or "data transfer" cables, often used to network laptops to PCs.
Such cables have chips from suppliers such as Belkin/eTEK, GeneSys
(GeneLink), NetChip and Prolific. Intelligent USB devices could also
use this approach to provide Internet access, using standard USB
cabling. You can find these chips also on some motherboards with
USB PC2PC support.
These links will have names like "usb0", "usb1", etc. They act
like two-node Ethernets, so you can use 802.1d Ethernet Bridging
(CONFIG_BRIDGE) to simplify your network routing.
This code is also available as a kernel module (code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called usbnet.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
/*
* USB Host-to-Host Links
* Copyright (C) 2000-2001 by David Brownell <dbrownell@users.sourceforge.net>
* Copyright (C) 2000-2002 by David Brownell <dbrownell@users.sourceforge.net>
*/
/*
......@@ -62,6 +62,7 @@
* 18-dec-2000 (db) tx watchdog, "net1080" renaming to "usbnet", device_info
* and prolific support, isolate net1080-specific bits, cleanup.
* fix unlink_urbs oops in D3 PM resume code path.
*
* 02-feb-2001 (db) fix tx skb sharing, packet length, match_flags, ...
* 08-feb-2001 stubbed in "linuxdev", maybe the SA-1100 folk can use it;
* AnchorChips 2720 support (from spec) for testing;
......@@ -83,6 +84,11 @@
* tie mostly to (sub)driver info. Workaround some PL-2302
* chips that seem to reject SET_INTERFACE requests.
*
* 06-apr-2002 Added ethtool support, based on a patch from Brad Hards.
* Level of diagnostics is more configurable; they use device
* location (usb_device->devpath) instead of address (2.5).
* For tx_fixup, memflags can't be NOIO.
*
*-------------------------------------------------------------------------*/
#include <linux/config.h>
......@@ -93,6 +99,8 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/random.h>
#include <linux/ethtool.h>
#include <asm/uaccess.h>
#include <asm/unaligned.h>
// #define DEBUG // error path messages, extra info
......@@ -113,6 +121,8 @@
#define CONFIG_USB_PL2301
#define DRIVER_VERSION "06-Apr-2002"
/*-------------------------------------------------------------------------*/
/*
......@@ -164,6 +174,7 @@ struct usbnet {
// protocol/interface state
struct net_device net;
struct net_device_stats stats;
int msg_level;
#ifdef CONFIG_USB_NET1080
u16 packet_id;
......@@ -224,6 +235,13 @@ struct skb_data { // skb->cb is one of these
size_t length;
};
static const char driver_name [] = "usbnet";
/* use ethtool to change the level for any given device */
static int msg_level = 1;
MODULE_PARM (msg_level, "i");
MODULE_PARM_DESC (msg_level, "Initial message level (default = 1)");
#define mutex_lock(x) down(x)
#define mutex_unlock(x) up(x)
......@@ -241,7 +259,9 @@ struct skb_data { // skb->cb is one of these
#endif
#define devinfo(usbnet, fmt, arg...) \
printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net.name, ## arg)
do { if ((usbnet)->msg_level >= 1) \
printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net.name, ## arg); \
} while (0)
#ifdef CONFIG_USB_AN2720
......@@ -948,7 +968,8 @@ static int net1080_reset (struct usbnet *dev)
MK_TTL (NC_READ_TTL_MS, TTL_OTHER (ttl)) );
dbg ("%s: assigned TTL, %d ms", dev->net.name, NC_READ_TTL_MS);
devdbg (dev, "port %c, peer %sconnected",
if (dev->msg_level >= 2)
devinfo (dev, "port %c, peer %sconnected",
(status & STATUS_PORT_A) ? 'A' : 'B',
(status & STATUS_CONN_OTHER) ? "" : "dis"
);
......@@ -1441,7 +1462,8 @@ static int usbnet_stop (struct net_device *net)
mutex_lock (&dev->mutex);
netif_stop_queue (net);
devdbg (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",
if (dev->msg_level >= 2)
devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",
dev->stats.rx_packets, dev->stats.tx_packets,
dev->stats.rx_errors, dev->stats.tx_errors
);
......@@ -1482,9 +1504,10 @@ static int usbnet_open (struct net_device *net)
// put into "known safe" state
if (info->reset && (retval = info->reset (dev)) < 0) {
devinfo (dev, "open reset fail (%d) usbnet %03d/%03d, %s",
devinfo (dev, "open reset fail (%d) usbnet bus%d%s, %s",
retval,
dev->udev->bus->busnum, dev->udev->devnum,
// FIXME busnum is unstable
dev->udev->bus->busnum, dev->udev->devpath,
info->description);
goto done;
}
......@@ -1496,7 +1519,9 @@ static int usbnet_open (struct net_device *net)
}
netif_start_queue (net);
devdbg (dev, "open: enable queueing (rx %d, tx %d) mtu %d %s framing",
if (dev->msg_level >= 2)
devinfo (dev, "open: enable queueing "
"(rx %d, tx %d) mtu %d %s framing",
RX_QLEN, TX_QLEN, dev->net.mtu,
(info->flags & (FLAG_FRAMING_NC | FLAG_FRAMING_GL))
? ((info->flags & FLAG_FRAMING_NC)
......@@ -1514,6 +1539,80 @@ static int usbnet_open (struct net_device *net)
/*-------------------------------------------------------------------------*/
static int usbnet_ethtool_ioctl (struct net_device *net, void *useraddr)
{
struct usbnet *dev = (struct usbnet *) net->priv;
u32 cmd;
if (get_user (cmd, (u32 *)useraddr))
return -EFAULT;
switch (cmd) {
case ETHTOOL_GDRVINFO: { /* get driver info */
struct ethtool_drvinfo info;
memset (&info, 0, sizeof info);
info.cmd = ETHTOOL_GDRVINFO;
strncpy (info.driver, driver_name, sizeof info.driver);
strncpy (info.version, DRIVER_VERSION, sizeof info.version);
strncpy (info.fw_version, dev->driver_info->description,
sizeof info.fw_version);
snprintf (info.bus_info, sizeof info.bus_info, "USB bus%d%s",
/* FIXME busnums are bogus/unstable IDs */
dev->udev->bus->busnum, dev->udev->devpath);
if (copy_to_user (useraddr, &info, sizeof (info)))
return -EFAULT;
return 0;
}
case ETHTOOL_GLINK: /* get link status */
if (dev->driver_info->check_connect) {
struct ethtool_value edata = { ETHTOOL_GLINK };
edata.data = dev->driver_info->check_connect (dev);
if (copy_to_user (useraddr, &edata, sizeof (edata)))
return -EFAULT;
return 0;
}
break;
case ETHTOOL_GMSGLVL: { /* get message-level */
struct ethtool_value edata = {ETHTOOL_GMSGLVL};
edata.data = dev->msg_level;
if (copy_to_user (useraddr, &edata, sizeof (edata)))
return -EFAULT;
return 0;
}
case ETHTOOL_SMSGLVL: { /* set message-level */
struct ethtool_value edata;
if (copy_from_user (&edata, useraddr, sizeof (edata)))
return -EFAULT;
dev->msg_level = edata.data;
return 0;
}
/* could also map RINGPARAM to RX/TX QLEN */
}
/* Note that the ethtool user space code requires EOPNOTSUPP */
return -EOPNOTSUPP;
}
static int usbnet_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
{
switch (cmd) {
case SIOCETHTOOL:
return usbnet_ethtool_ioctl (net, (void *)rq->ifr_data);
default:
return -EOPNOTSUPP;
}
}
/*-------------------------------------------------------------------------*/
/* usb_clear_halt cannot be called in interrupt context */
static void
......@@ -1576,12 +1675,10 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
struct nc_trailer *trailer = 0;
#endif /* CONFIG_USB_NET1080 */
flags = in_interrupt () ? GFP_ATOMIC : GFP_NOIO; /* might be used for nfs */
// some devices want funky USB-level framing, for
// win32 driver (usually) and/or hardware quirks
if (info->tx_fixup) {
skb = info->tx_fixup (dev, skb, flags);
skb = info->tx_fixup (dev, skb, GFP_ATOMIC);
if (!skb) {
dbg ("can't tx_fixup skb");
goto drop;
......@@ -1750,8 +1847,9 @@ static void usbnet_disconnect (struct usb_device *udev, void *ptr)
{
struct usbnet *dev = (struct usbnet *) ptr;
devinfo (dev, "unregister usbnet %03d/%03d, %s",
udev->bus->busnum, udev->devnum,
devinfo (dev, "unregister usbnet bus%d%s, %s",
// FIXME busnum is unstable
udev->bus->busnum, udev->devpath,
dev->driver_info->description);
unregister_netdev (&dev->net);
......@@ -1811,6 +1909,7 @@ usbnet_probe (struct usb_device *udev, unsigned ifnum,
usb_inc_dev_use (udev);
dev->udev = udev;
dev->driver_info = info;
dev->msg_level = msg_level;
INIT_LIST_HEAD (&dev->dev_list);
skb_queue_head_init (&dev->rxq);
skb_queue_head_init (&dev->txq);
......@@ -1836,10 +1935,12 @@ usbnet_probe (struct usb_device *udev, unsigned ifnum,
net->stop = usbnet_stop;
net->watchdog_timeo = TX_TIMEOUT_JIFFIES;
net->tx_timeout = usbnet_tx_timeout;
net->do_ioctl = usbnet_ioctl;
register_netdev (&dev->net);
devinfo (dev, "register usbnet %03d/%03d, %s",
udev->bus->busnum, udev->devnum,
devinfo (dev, "register usbnet bus%d%s, %s",
// FIXME busnum is unstable
udev->bus->busnum, udev->devpath,
dev->driver_info->description);
// ok, it's ready to go.
......@@ -1936,7 +2037,7 @@ static const struct usb_device_id products [] = {
MODULE_DEVICE_TABLE (usb, products);
static struct usb_driver usbnet_driver = {
name: "usbnet",
name: driver_name,
id_table: products,
probe: usbnet_probe,
disconnect: usbnet_disconnect,
......
#ifndef _ASM_GENERIC_PERCPU_H_
#define _ASM_GENERIC_PERCPU_H_
#define __GENERIC_PER_CPU
#include <linux/compiler.h>
extern unsigned long __per_cpu_offset[NR_CPUS];
/* var is in discarded region: offset to particular copy we want */
#define per_cpu(var, cpu) (*RELOC_HIDE(&var, __per_cpu_offset[cpu]))
#define this_cpu(var) per_cpu(var, smp_processor_id())
#endif /* _ASM_GENERIC_PERCPU_H_ */
......@@ -194,7 +194,7 @@ static void __init check_config(void)
*/
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_GOOD_APIC)
if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL
&& test_bit(X86_FEATURE_APIC, &boot_cpu_data.x86_capability)
&& test_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability)
&& boot_cpu_data.x86 == 5
&& boot_cpu_data.x86_model == 2
&& (boot_cpu_data.x86_mask < 6 || boot_cpu_data.x86_mask == 11))
......
#ifndef __ARCH_I386_PERCPU__
#define __ARCH_I386_PERCPU__
#include <asm-generic/percpu.h>
#endif /* __ARCH_I386_PERCPU__ */
......@@ -40,7 +40,7 @@ struct cpuinfo_x86 {
char hard_math;
char rfu;
int cpuid_level; /* Maximum supported CPUID level, -1=no CPUID */
__u32 x86_capability[NCAPINTS];
unsigned long x86_capability[NCAPINTS];
char x86_vendor_id[16];
char x86_model_id[64];
int x86_cache_size; /* in KB - valid for CPUS which support this
......
#ifndef __ARCH_PPC_PERCPU__
#define __ARCH_PPC_PERCPU__
#include <asm-generic/percpu.h>
#endif /* __ARCH_PPC_PERCPU__ */
......@@ -15,8 +15,8 @@
/* This macro obfuscates arithmetic on a variable address so that gcc
shouldn't recognize the original var, and make assumptions about it */
#define RELOC_HIDE(var, off) \
({ __typeof__(&(var)) __ptr; \
__asm__ ("" : "=g"(__ptr) : "0"((void *)&(var) + (off))); \
*__ptr; })
#define RELOC_HIDE(ptr, off) \
({ __typeof__(ptr) __ptr; \
__asm__ ("" : "=g"(__ptr) : "0"((void *)(ptr) + (off))); \
__ptr; })
#endif /* __LINUX_COMPILER_H */
......@@ -433,10 +433,10 @@ typedef void (ide_intrproc_t) (ide_drive_t *);
typedef void (ide_maskproc_t) (ide_drive_t *, int);
typedef void (ide_rw_proc_t) (ide_drive_t *, ide_dma_action_t);
/*
* ide soft-power support
*/
typedef int (ide_busproc_t) (ide_drive_t *, int);
enum {
ATA_PRIMARY = 0,
ATA_SECONDARY = 1
};
struct ata_channel {
struct device dev; /* device handle */
......@@ -467,7 +467,6 @@ struct ata_channel {
struct scatterlist *sg_table; /* Scatter-gather list used to build the above */
int sg_nents; /* Current number of entries in it */
int sg_dma_direction; /* dma transfer direction */
struct ata_channel *mate; /* other hwif from same PCI chip */
unsigned long dma_base; /* base addr for dma ports */
unsigned dma_extra; /* extra addr for dma ports */
unsigned long config_data; /* for use by chipset-specific code */
......@@ -480,7 +479,7 @@ struct ata_channel {
hwif_chipset_t chipset; /* sub-module for tuning.. */
unsigned noprobe : 1; /* don't probe for this interface */
unsigned present : 1; /* there is a device on this interface */
unsigned serialized : 1; /* serialized operation with mate hwif */
unsigned serialized : 1; /* serialized operation between channels */
unsigned sharing_irq: 1; /* 1 = sharing irq with another hwif */
unsigned reset : 1; /* reset after probe */
unsigned autodma : 1; /* automatically try to enable DMA at boot */
......@@ -490,7 +489,7 @@ struct ata_channel {
unsigned long last_time; /* time when previous rq was done */
#endif
byte straight8; /* Alan's straight 8 check */
ide_busproc_t *busproc; /* driver soft-power interface */
int (*busproc)(ide_drive_t *, int); /* driver soft-power interface */
byte bus_state; /* power state of the IDE bus */
};
......@@ -513,7 +512,6 @@ typedef enum {
*/
typedef ide_startstop_t (ide_pre_handler_t)(ide_drive_t *, struct request *);
typedef ide_startstop_t (ide_handler_t)(ide_drive_t *);
typedef ide_startstop_t (ide_post_handler_t)(ide_drive_t *);
/*
* when ide_timer_expiry fires, invoke a handler of this type
......
#ifndef __LINUX_PERCPU_H
#define __LINUX_PERCPU_H
#include <linux/config.h>
#ifdef CONFIG_SMP
#define __per_cpu_data __attribute__((section(".data.percpu")))
#include <asm/percpu.h>
#else
#define __per_cpu_data
#define per_cpu(var, cpu) var
#define this_cpu(var) var
#endif
#endif /* __LINUX_PERCPU_H */
......@@ -72,16 +72,6 @@ extern volatile int smp_msg_id;
#define MSG_RESCHEDULE 0x0003 /* Reschedule request from master CPU*/
#define MSG_CALL_FUNCTION 0x0004 /* Call function on all other CPUs */
#define __per_cpu_data __attribute__((section(".data.percpu")))
#ifndef __HAVE_ARCH_PER_CPU
extern unsigned long __per_cpu_offset[NR_CPUS];
/* var is in discarded region: offset to particular copy we want */
#define per_cpu(var, cpu) RELOC_HIDE(var, per_cpu_offset(cpu))
#define this_cpu(var) per_cpu(var, smp_processor_id())
#endif /* !__HAVE_ARCH_PER_CPU */
#else /* !SMP */
/*
......
......@@ -305,6 +305,7 @@ struct usb_qualifier_descriptor {
} __attribute__ ((packed));
/* helpers for driver access to descriptors */
extern int usb_ifnum_to_ifpos(struct usb_device *dev, unsigned ifnum);
extern struct usb_interface *
usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum);
extern struct usb_endpoint_descriptor *
......@@ -470,8 +471,10 @@ struct usb_device_id {
/**
* struct usb_driver - identifies USB driver to usbcore
* @owner: pointer to the module owner of this driver
* @name: The driver name should be unique among USB drivers
* @owner: Pointer to the module owner of this driver; initialize
* it using THIS_MODULE.
* @name: The driver name should be unique among USB drivers,
* and should normally be the same as the module name.
* @probe: Called to see if the driver is willing to manage a particular
* interface on a device. The probe routine returns a handle that
* will later be provided to disconnect(), or a null pointer to
......@@ -506,7 +509,7 @@ struct usb_device_id {
* is used by both user and kernel mode hotplugging support.
*
* The probe() and disconnect() methods are called in a context where
* they can sleep, but they should avoid abusing the privilage. Most
* they can sleep, but they should avoid abusing the privilege. Most
* work to connect to a device should be done when the device is opened,
* and undone at the last close. The disconnect code needs to address
* concurrency issues with respect to open() and close() methods, as
......@@ -959,24 +962,6 @@ struct usb_tt {
};
/* -------------------------------------------------------------------------- */
/* Enumeration is only for the hub driver, or HCD virtual root hubs */
extern struct usb_device *usb_alloc_dev(struct usb_device *parent,
struct usb_bus *);
extern void usb_free_dev(struct usb_device *);
extern int usb_new_device(struct usb_device *dev);
extern void usb_connect(struct usb_device *dev);
extern void usb_disconnect(struct usb_device **);
#ifndef _LINUX_HUB_H
/* exported to hub driver ONLY to support usb_reset_device () */
extern int usb_get_configuration(struct usb_device *dev);
extern void usb_set_maxpacket(struct usb_device *dev);
extern void usb_destroy_configuration(struct usb_device *dev);
extern int usb_set_address(struct usb_device *dev);
#endif /* _LINUX_HUB_H */
/* -------------------------------------------------------------------------- */
/* This is arbitrary.
......@@ -1047,11 +1032,52 @@ extern int usb_reset_device(struct usb_device *dev);
/* for drivers using iso endpoints */
extern int usb_get_current_frame_number (struct usb_device *usb_dev);
/* drivers must track when they bind to a device's interfaces */
extern void usb_inc_dev_use(struct usb_device *);
#define usb_dec_dev_use usb_free_dev
/**
* usb_inc_dev_use - record another reference to a device
* @dev: the device being referenced
*
* Each live reference to a device should be refcounted.
*
* Drivers for USB interfaces should normally record such references in
* their probe() methods, when they bind to an interface, and release
* them usb_dec_dev_use(), in their disconnect() methods.
*/
static inline void usb_inc_dev_use (struct usb_device *dev)
{
atomic_inc (&dev->refcnt);
}
/**
* usb_dec_dev_use - drop a reference to a device
* @dev: the device no longer being referenced
*
* Each live reference to a device should be refcounted.
*
* Drivers for USB interfaces should normally release such references in
* their disconnect() methods, and record them in probe().
*
* Note that driver disconnect() methods must guarantee that when they
* return, all of their outstanding references to the device (and its
* interfaces) are cleaned up. That means that all pending URBs from
* this driver must have completed, and that no more copies of the device
* handle are saved in driver records (including other kernel threads).
*/
static inline void usb_dec_dev_use (struct usb_device *dev)
{
if (atomic_dec_and_test (&dev->refcnt)) {
/* May only go to zero when usbcore finishes
* usb_disconnect() processing: khubd or HCDs.
*
* If you hit this BUG() it's likely a problem
* with some driver's disconnect() routine.
*/
BUG ();
}
}
/* used these for multi-interface device registration */
extern int usb_find_interface_driver_for_ifnum(struct usb_device *dev, unsigned int ifnum);
extern void usb_driver_claim_interface(struct usb_driver *driver,
struct usb_interface *iface, void* priv);
extern int usb_interface_claimed(struct usb_interface *iface);
......
......@@ -142,6 +142,8 @@ struct usbdevfs_hub_portinfo {
#define USBDEVFS_HUB_PORTINFO _IOR('U', 19, struct usbdevfs_hub_portinfo)
#define USBDEVFS_RESET _IO('U', 20)
#define USBDEVFS_CLEAR_HALT _IOR('U', 21, unsigned int)
#define USBDEVFS_DISCONNECT _IO('U', 22)
#define USBDEVFS_CONNECT _IO('U', 23)
/* --------------------------------------------------------------------- */
......
......@@ -27,6 +27,7 @@
#include <linux/iobuf.h>
#include <linux/bootmem.h>
#include <linux/tty.h>
#include <linux/percpu.h>
#include <asm/io.h>
#include <asm/bugs.h>
......@@ -270,12 +271,9 @@ static void __init smp_init(void)
#define smp_init() do { } while (0)
#endif
static inline void setup_per_cpu_areas(void)
{
}
#else
#ifndef __HAVE_ARCH_PER_CPU
#ifdef __GENERIC_PER_CPU
unsigned long __per_cpu_offset[NR_CPUS];
static void __init setup_per_cpu_areas(void)
......@@ -297,7 +295,11 @@ static void __init setup_per_cpu_areas(void)
memcpy(ptr, __per_cpu_start, size);
}
}
#endif /* !__HAVE_ARCH_PER_CPU */
#else
static inline void setup_per_cpu_areas(void)
{
}
#endif /* !__GENERIC_PER_CPU */
/* Called by boot processor to activate the rest. */
static void __init smp_init(void)
......
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